From f2af81b1c74a56e6854039cfe5f32e9b035ce262 Mon Sep 17 00:00:00 2001 From: Sam Faber-Manning Date: Thu, 30 Jun 2022 10:43:20 -0700 Subject: [PATCH] feat: add extension point to the right side of the menu bar (#20514) * add setupExtensions * add 'navbar.right' extension to registry * add test for navbar.right extension point * rename MenuRight -> RightMenu * lint --- .../src/ui-overrides/UiOverrideRegistry.ts | 1 + superset-frontend/src/preamble.ts | 3 +++ .../src/setup/setupExtensions.ts | 21 +++++++++++++++++++ .../src/views/components/Menu.test.tsx | 18 ++++++++++++++++ .../src/views/components/Menu.tsx | 2 +- .../{MenuRight.tsx => RightMenu.tsx} | 5 +++++ 6 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 superset-frontend/src/setup/setupExtensions.ts rename superset-frontend/src/views/components/{MenuRight.tsx => RightMenu.tsx} (98%) diff --git a/superset-frontend/packages/superset-ui-core/src/ui-overrides/UiOverrideRegistry.ts b/superset-frontend/packages/superset-ui-core/src/ui-overrides/UiOverrideRegistry.ts index fb74ae1ece..6006bd5cc0 100644 --- a/superset-frontend/packages/superset-ui-core/src/ui-overrides/UiOverrideRegistry.ts +++ b/superset-frontend/packages/superset-ui-core/src/ui-overrides/UiOverrideRegistry.ts @@ -34,6 +34,7 @@ type UiGeneratorText

= (props: P) => string | React.ReactElement; export type UiOverrides = Partial<{ 'embedded.documentation.description': UiGeneratorText; 'embedded.documentation.url': string; + 'navbar.right': React.ComponentType; }>; /** diff --git a/superset-frontend/src/preamble.ts b/superset-frontend/src/preamble.ts index ab6d696f5b..4ca1849768 100644 --- a/superset-frontend/src/preamble.ts +++ b/superset-frontend/src/preamble.ts @@ -24,6 +24,7 @@ import { configure, makeApi, supersetTheme } from '@superset-ui/core'; import { merge } from 'lodash'; import setupClient from './setup/setupClient'; import setupColors from './setup/setupColors'; +import setupExtensions from './setup/setupExtensions'; import setupFormatters from './setup/setupFormatters'; import setupDashboardComponents from './setup/setupDasboardComponents'; import { BootstrapUser, User } from './types/bootstrapTypes'; @@ -32,6 +33,8 @@ if (process.env.WEBPACK_MODE === 'development') { setHotLoaderConfig({ logLevel: 'debug', trackTailUpdates: false }); } +setupExtensions(); + // eslint-disable-next-line import/no-mutable-exports export let bootstrapData: { user?: BootstrapUser; diff --git a/superset-frontend/src/setup/setupExtensions.ts b/superset-frontend/src/setup/setupExtensions.ts new file mode 100644 index 0000000000..88a9cf1059 --- /dev/null +++ b/superset-frontend/src/setup/setupExtensions.ts @@ -0,0 +1,21 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// For individual deployments to add custom overrides +export default function setupExtensions() {} diff --git a/superset-frontend/src/views/components/Menu.test.tsx b/superset-frontend/src/views/components/Menu.test.tsx index 31aad0be8a..e393ab1b2f 100644 --- a/superset-frontend/src/views/components/Menu.test.tsx +++ b/superset-frontend/src/views/components/Menu.test.tsx @@ -20,7 +20,9 @@ import React from 'react'; import * as reactRedux from 'react-redux'; import fetchMock from 'fetch-mock'; import { render, screen } from 'spec/helpers/testing-library'; +import setupExtensions from 'src/setup/setupExtensions'; import userEvent from '@testing-library/user-event'; +import { getUiOverrideRegistry } from '@superset-ui/core'; import { Menu } from './Menu'; const dropdownItems = [ @@ -482,3 +484,19 @@ test('should render without QueryParamProvider', () => { render(

, { useRedux: true }); expect(screen.queryByTestId('new-dropdown')).not.toBeInTheDocument(); }); + +test('should render an extension component if one is supplied', () => { + const uiOverrideRegistry = getUiOverrideRegistry(); + + uiOverrideRegistry.set('navbar.right', () => ( + <>navbar.right extension component + )); + + setupExtensions(); + + render(); + + expect( + screen.getByText('navbar.right extension component'), + ).toBeInTheDocument(); +}); diff --git a/superset-frontend/src/views/components/Menu.tsx b/superset-frontend/src/views/components/Menu.tsx index 3cc61f5243..61bfc5a329 100644 --- a/superset-frontend/src/views/components/Menu.tsx +++ b/superset-frontend/src/views/components/Menu.tsx @@ -28,7 +28,7 @@ import { Link } from 'react-router-dom'; import Icons from 'src/components/Icons'; import { useUiConfig } from 'src/components/UiConfigContext'; import { URL_PARAMS } from 'src/constants'; -import RightMenu from './MenuRight'; +import RightMenu from './RightMenu'; import { Languages } from './LanguagePicker'; interface BrandProps { diff --git a/superset-frontend/src/views/components/MenuRight.tsx b/superset-frontend/src/views/components/RightMenu.tsx similarity index 98% rename from superset-frontend/src/views/components/MenuRight.tsx rename to superset-frontend/src/views/components/RightMenu.tsx index c78dd754cd..e2a206560c 100644 --- a/superset-frontend/src/views/components/MenuRight.tsx +++ b/superset-frontend/src/views/components/RightMenu.tsx @@ -28,6 +28,7 @@ import { css, SupersetTheme, SupersetClient, + getUiOverrideRegistry, } from '@superset-ui/core'; import { MainNav as Menu } from 'src/components/Menu'; import { Tooltip } from 'src/components/Tooltip'; @@ -46,6 +47,8 @@ import { } from './types'; import { MenuObjectProps } from './Menu'; +const uiOverrideRegistry = getUiOverrideRegistry(); + const versionInfoStyles = (theme: SupersetTheme) => css` padding: ${theme.gridUnit * 1.5}px ${theme.gridUnit * 4}px ${theme.gridUnit * 4}px ${theme.gridUnit * 7}px; @@ -255,6 +258,7 @@ const RightMenu = ({ } return null; }; + const RightMenuExtension = uiOverrideRegistry.get('navbar.right'); const handleDatabaseAdd = () => setQuery({ databaseAdded: true }); @@ -274,6 +278,7 @@ const RightMenu = ({ onClick={handleMenuSelection} onOpenChange={onMenuOpen} > + {RightMenuExtension && } {!navbarRight.user_is_anonymous && showActionDropdown && (