diff --git a/superset-frontend/cypress-base/cypress/integration/explore/chart.test.js b/superset-frontend/cypress-base/cypress/integration/explore/chart.test.js index c89b1b22e..7c8cb855c 100644 --- a/superset-frontend/cypress-base/cypress/integration/explore/chart.test.js +++ b/superset-frontend/cypress-base/cypress/integration/explore/chart.test.js @@ -81,7 +81,9 @@ function verifyMetabar(text) { function saveAndVerifyDashboard(number) { saveChartToDashboard(`${number} - Sample dashboard`); - verifyMetabar(`Added to ${number} dashboard(s)`); + verifyMetabar( + number > 1 ? `Added to ${number} dashboards` : 'Added to 1 dashboard', + ); openDashboardsAddedTo(); verifyDashboardsSubmenuItem(`${number} - Sample dashboard`); } diff --git a/superset-frontend/src/components/Chart/DrillDetail/DrillDetailPane.tsx b/superset-frontend/src/components/Chart/DrillDetail/DrillDetailPane.tsx index 9451cae52..30ea2293a 100644 --- a/superset-frontend/src/components/Chart/DrillDetail/DrillDetailPane.tsx +++ b/superset-frontend/src/components/Chart/DrillDetail/DrillDetailPane.tsx @@ -301,7 +301,9 @@ export default function DrillDetailPane({ margin-bottom: ${theme.gridUnit * 4}px; `} > - {status === 'complete' && } + {status === 'complete' && ( + + )} {status === 'error' && ( { const { icon, title, tooltip = title } = config(contentType); const [isTruncated, setIsTruncated] = useState(false); @@ -149,7 +151,10 @@ const Item = ({ ); return isTruncated || collapsed || (tooltip && tooltip !== title) ? ( - {tooltip}}> + {tooltip}} + > {content} ) : ( @@ -163,6 +168,11 @@ export interface MetadataBarProps { * for each content type, check {@link ContentType} */ items: ContentType[]; + /** + * Antd tooltip placement. To see available values, check {@link TooltipPlacement}. + * Defaults to "top". + */ + tooltipPlacement?: TooltipPlacement; } /** @@ -173,7 +183,7 @@ export interface MetadataBarProps { * To extend the list of content types, a developer needs to request the inclusion of the new type in the design system. * This process is important to make sure the new type is reviewed by the design team, improving Superset consistency. */ -const MetadataBar = ({ items }: MetadataBarProps) => { +const MetadataBar = ({ items, tooltipPlacement = 'top' }: MetadataBarProps) => { const [width, setWidth] = useState(); const [collapsed, setCollapsed] = useState(false); const uniqueItems = uniqWith(items, (a, b) => a.type === b.type); @@ -211,6 +221,7 @@ const MetadataBar = ({ items }: MetadataBarProps) => { contentType={item} collapsed={collapsed} last={index === count - 1} + tooltipPlacement={tooltipPlacement} /> ))} diff --git a/superset-frontend/src/explore/components/ExploreChartHeader/ExploreChartHeader.test.tsx b/superset-frontend/src/explore/components/ExploreChartHeader/ExploreChartHeader.test.tsx index 74d1764f4..3d9f6b995 100644 --- a/superset-frontend/src/explore/components/ExploreChartHeader/ExploreChartHeader.test.tsx +++ b/superset-frontend/src/explore/components/ExploreChartHeader/ExploreChartHeader.test.tsx @@ -159,21 +159,35 @@ test('Cancelling changes to the properties should reset previous properties', as test('renders the metadata bar when saved', async () => { const props = createProps({ showTitlePanelItems: true }); render(, { useRedux: true }); - expect( - await screen.findByText('Added to 1 dashboard(s)'), - ).toBeInTheDocument(); + expect(await screen.findByText('Added to 1 dashboard')).toBeInTheDocument(); expect(await screen.findByText('Simple description')).toBeInTheDocument(); expect(await screen.findByText('John Doe')).toBeInTheDocument(); expect(await screen.findByText('2 days ago')).toBeInTheDocument(); }); +test('Changes "Added to X dashboards" to plural when more than 1 dashboard', async () => { + const props = createProps({ showTitlePanelItems: true }); + render( + , + { useRedux: true }, + ); + expect(await screen.findByText('Added to 2 dashboards')).toBeInTheDocument(); +}); + test('does not render the metadata bar when not saved', async () => { const props = createProps({ showTitlePanelItems: true, slice: null }); render(, { useRedux: true }); await waitFor(() => - expect( - screen.queryByText('Added to 1 dashboard(s)'), - ).not.toBeInTheDocument(), + expect(screen.queryByText('Added to 1 dashboard')).not.toBeInTheDocument(), ); }); diff --git a/superset-frontend/src/explore/components/ExploreChartHeader/index.jsx b/superset-frontend/src/explore/components/ExploreChartHeader/index.jsx index 2b68120fb..958aa16a3 100644 --- a/superset-frontend/src/explore/components/ExploreChartHeader/index.jsx +++ b/superset-frontend/src/explore/components/ExploreChartHeader/index.jsx @@ -26,6 +26,7 @@ import { logging, SupersetClient, t, + tn, } from '@superset-ui/core'; import { chartPropShape } from 'src/dashboard/util/propShapes'; import AlteredSliceTag from 'src/components/AlteredSliceTag'; @@ -170,12 +171,17 @@ export const ExploreChartHeader = ({ type: MetadataType.DASHBOARDS, title: metadata.dashboards.length > 0 - ? t('Added to %s dashboard(s)', metadata.dashboards.length) + ? tn( + 'Added to 1 dashboard', + 'Added to %s dashboards', + metadata.dashboards.length, + metadata.dashboards.length, + ) : t('Not added to any dashboard'), description: metadata.dashboards.length > 0 ? t( - 'You can preview the list of dashboards on the chart settings dropdown.', + 'You can preview the list of dashboards in the chart settings dropdown.', ) : undefined, }); @@ -196,7 +202,7 @@ export const ExploreChartHeader = ({ value: slice?.description, }); } - return ; + return ; }, [metadata, slice?.description]); const oldSliceName = slice?.slice_name;