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 82e68efcf0e96..2da3231ee57bb 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 @@ -35,16 +35,36 @@ type ReturningDisplayable

= (props: P) => string | React.ReactElement; * When defining a new option here, take care to keep any parameters to functions (or components) minimal. * Any removal or alteration to a parameter will be considered a breaking change. */ + +// from src/views/components/Menu, not imported since this is a separate package +interface MenuObjectChildProps { + label: string; + name?: string; + icon?: string; + index?: number; + url?: string; + isFrontendRoute?: boolean; + perm?: string | boolean; + view?: string; + disable?: boolean; +} + type ConfigDetailsProps = { embeddedId: string; }; +type RightMenuItemIconProps = { + menuChild: MenuObjectChildProps; +}; export type Extensions = Partial<{ + 'alertsreports.header.icon': React.ComponentType; 'embedded.documentation.configuration_details': React.ComponentType; 'embedded.documentation.description': ReturningDisplayable; 'embedded.documentation.url': string; 'dashboard.nav.right': React.ComponentType; + 'navbar.right-menu.item.icon': React.ComponentType; 'navbar.right': React.ComponentType; + 'report-modal.dropdown.item.icon': React.ComponentType; 'welcome.message': React.ComponentType; 'welcome.banner': React.ComponentType; 'welcome.main.replacement': React.ComponentType; diff --git a/superset-frontend/src/components/ReportModal/HeaderReportDropdown/index.tsx b/superset-frontend/src/components/ReportModal/HeaderReportDropdown/index.tsx index 92388f9f8a0a7..f7bb9ba55cf2f 100644 --- a/superset-frontend/src/components/ReportModal/HeaderReportDropdown/index.tsx +++ b/superset-frontend/src/components/ReportModal/HeaderReportDropdown/index.tsx @@ -23,9 +23,11 @@ import { t, SupersetTheme, css, + styled, useTheme, FeatureFlag, isFeatureEnabled, + getExtensionsRegistry, } from '@superset-ui/core'; import Icons from 'src/components/Icons'; import { Switch } from 'src/components/Switch'; @@ -46,6 +48,8 @@ import { import { reportSelector } from 'src/views/CRUD/hooks'; import { MenuItemWithCheckboxContainer } from 'src/explore/components/useExploreAdditionalActionsMenu/index'; +const extensionsRegistry = getExtensionsRegistry(); + const deleteColor = (theme: SupersetTheme) => css` color: ${theme.colors.error.base}; `; @@ -70,6 +74,21 @@ const onMenuItemHover = (theme: SupersetTheme) => css` background-color: ${theme.colors.secondary.light5}; } `; + +const StyledDropdownItemWithIcon = styled.div` + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + > *:first-child { + margin-right: ${({ theme }) => theme.gridUnit}px; + } +`; + +const DropdownItemExtension = extensionsRegistry.get( + 'report-modal.dropdown.item.icon', +); + export enum CreationMethod { CHARTS = 'charts', DASHBOARDS = 'dashboards', @@ -204,7 +223,14 @@ export default function HeaderReportDropDown({ ) : (

- {t('Set up an email report')} + {DropdownItemExtension ? ( + +
{t('Set up an email report')}
+ +
+ ) : ( + t('Set up an email report') + )}
diff --git a/superset-frontend/src/views/CRUD/alert/AlertList.tsx b/superset-frontend/src/views/CRUD/alert/AlertList.tsx index 5abe754a63469..826b5519f4a1a 100644 --- a/superset-frontend/src/views/CRUD/alert/AlertList.tsx +++ b/superset-frontend/src/views/CRUD/alert/AlertList.tsx @@ -19,7 +19,13 @@ import React, { useState, useMemo, useEffect, useCallback } from 'react'; import { useHistory } from 'react-router-dom'; -import { t, SupersetClient, makeApi, styled } from '@superset-ui/core'; +import { + t, + SupersetClient, + makeApi, + styled, + getExtensionsRegistry, +} from '@superset-ui/core'; import moment from 'moment'; import ActionsBar, { ActionProps } from 'src/components/ListView/ActionsBar'; import FacePile from 'src/components/FacePile'; @@ -49,6 +55,8 @@ import Owner from 'src/types/Owner'; import AlertReportModal from './AlertReportModal'; import { AlertObject, AlertState } from './types'; +const extensionsRegistry = getExtensionsRegistry(); + const PAGE_SIZE = 25; const AlertStateLabel: Record = { @@ -82,6 +90,18 @@ const RefreshContainer = styled.div` background-color: ${({ theme }) => theme.colors.grayscale.light5}; `; +const StyledHeaderWithIcon = styled.div` + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + > *:first-child { + margin-right: ${({ theme }) => theme.gridUnit}px; + } +`; + +const HeaderExtension = extensionsRegistry.get('alertsreports.header.icon'); + function AlertList({ addDangerToast, isReportEnabled = false, @@ -495,11 +515,20 @@ function AlertList({ [], ); + const header = HeaderExtension ? ( + +
{t('Alerts & reports')}
+ +
+ ) : ( + t('Alerts & reports') + ); + return ( <> ` } `; +const StyledMenuItemWithIcon = styled.div` + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; +`; + const StyledAnchor = styled.a` padding-right: ${({ theme }) => theme.gridUnit}px; padding-left: ${({ theme }) => theme.gridUnit}px; @@ -330,6 +337,9 @@ const RightMenu = ({ return null; }; const RightMenuExtension = extensionsRegistry.get('navbar.right'); + const RightMenuItemIconExtension = extensionsRegistry.get( + 'navbar.right-menu.item.icon', + ); const handleDatabaseAdd = () => setQuery({ databaseAdded: true }); const handleDatasetAdd = () => setQuery({ datasetAdded: true }); @@ -447,12 +457,20 @@ const RightMenu = ({ {section?.childs?.map?.(child => { if (typeof child !== 'string') { + const menuItemDisplay = RightMenuItemIconExtension ? ( + + {child.label} + + + ) : ( + child.label + ); return ( {isFrontendRoute(child.url) ? ( - {child.label} + {menuItemDisplay} ) : ( - {child.label} + {menuItemDisplay} )} );