diff --git a/superset-frontend/packages/superset-ui-core/src/ui-overrides/ExtensionsRegistry.ts b/superset-frontend/packages/superset-ui-core/src/ui-overrides/ExtensionsRegistry.ts index 964ff67a9b880..dc71c809ea760 100644 --- a/superset-frontend/packages/superset-ui-core/src/ui-overrides/ExtensionsRegistry.ts +++ b/superset-frontend/packages/superset-ui-core/src/ui-overrides/ExtensionsRegistry.ts @@ -38,6 +38,7 @@ type ReturningDisplayable

= (props: P) => string | React.ReactElement; export type Extensions = Partial<{ 'embedded.documentation.description': ReturningDisplayable; 'embedded.documentation.url': string; + 'dashboard.nav.right': React.ComponentType; 'navbar.right': React.ComponentType; 'welcome.banner': React.ComponentType; }>; diff --git a/superset-frontend/src/dashboard/components/Header/Header.test.tsx b/superset-frontend/src/dashboard/components/Header/Header.test.tsx index 730596a9f4b2b..010e88e576da4 100644 --- a/superset-frontend/src/dashboard/components/Header/Header.test.tsx +++ b/superset-frontend/src/dashboard/components/Header/Header.test.tsx @@ -20,6 +20,8 @@ import React from 'react'; import { render, screen, fireEvent } from 'spec/helpers/testing-library'; import userEvent from '@testing-library/user-event'; import fetchMock from 'fetch-mock'; +import { getExtensionsRegistry } from '@superset-ui/core'; +import setupExtensions from 'src/setup/setupExtensions'; import { HeaderProps } from './types'; import Header from '.'; @@ -327,3 +329,17 @@ test('should refresh the charts', async () => { userEvent.click(screen.getByText('Refresh dashboard')); expect(mockedProps.onRefresh).toHaveBeenCalledTimes(1); }); + +test('should render an extension component if one is supplied', () => { + const extensionsRegistry = getExtensionsRegistry(); + extensionsRegistry.set('dashboard.nav.right', () => ( + <>dashboard.nav.right extension component + )); + setupExtensions(); + + const mockedProps = createProps(); + setup(mockedProps); + expect( + screen.getByText('dashboard.nav.right extension component'), + ).toBeInTheDocument(); +}); diff --git a/superset-frontend/src/dashboard/components/Header/index.jsx b/superset-frontend/src/dashboard/components/Header/index.jsx index 0699304b2c218..46ca4fc703c9f 100644 --- a/superset-frontend/src/dashboard/components/Header/index.jsx +++ b/superset-frontend/src/dashboard/components/Header/index.jsx @@ -20,7 +20,13 @@ import moment from 'moment'; import React from 'react'; import PropTypes from 'prop-types'; -import { styled, css, t, getSharedLabelColor } from '@superset-ui/core'; +import { + styled, + css, + t, + getSharedLabelColor, + getUiOverrideRegistry, +} from '@superset-ui/core'; import { Global } from '@emotion/react'; import { isFeatureEnabled, FeatureFlag } from 'src/featureFlags'; import { @@ -53,6 +59,8 @@ import { FILTER_BOX_MIGRATION_STATES } from 'src/explore/constants'; import { PageHeaderWithActions } from 'src/components/PageHeaderWithActions'; import { DashboardEmbedModal } from '../DashboardEmbedControls'; +const uiOverrideRegistry = getUiOverrideRegistry(); + const propTypes = { addSuccessToast: PropTypes.func.isRequired, addDangerToast: PropTypes.func.isRequired, @@ -483,6 +491,8 @@ class Header extends React.PureComponent { dashboardTitleChanged(updates.title); }; + const NavExtension = uiOverrideRegistry.get('dashboard.nav.right'); + return (

) : (
+ {NavExtension && } {userCanEdit && (