From 5aeaa18ac2d4c8866b774b8b9bd175d216c0e065 Mon Sep 17 00:00:00 2001 From: Adela Almasan <88068998+adela-almasan@users.noreply.github.com> Date: Thu, 13 Feb 2025 11:46:29 -0600 Subject: [PATCH] Canvas: One click links and actions (#99616) Co-authored-by: Leon Sorokin --- .../VizTooltip/VizTooltipFooter.tsx | 95 +++++++---- public/app/features/actions/utils.ts | 1 + public/app/features/canvas/element.ts | 3 +- public/app/features/canvas/elements/cloud.tsx | 3 +- .../features/canvas/elements/droneFront.tsx | 3 +- .../features/canvas/elements/droneSide.tsx | 3 +- .../app/features/canvas/elements/droneTop.tsx | 3 +- .../app/features/canvas/elements/ellipse.tsx | 3 +- public/app/features/canvas/elements/icon.tsx | 3 +- .../features/canvas/elements/metricValue.tsx | 9 +- .../canvas/elements/parallelogram.tsx | 3 +- .../features/canvas/elements/rectangle.tsx | 3 +- .../canvas/elements/server/server.tsx | 3 +- public/app/features/canvas/elements/text.tsx | 3 +- .../app/features/canvas/elements/triangle.tsx | 3 +- .../features/canvas/elements/windTurbine.tsx | 3 +- .../app/features/canvas/runtime/element.tsx | 148 ++++++++++++------ public/app/features/canvas/runtime/scene.tsx | 2 + .../app/plugins/panel/canvas/CanvasPanel.tsx | 5 + .../panel/canvas/components/CanvasTooltip.tsx | 1 - .../canvas/editor/element/elementEditor.tsx | 35 +---- .../plugins/panel/canvas/migrations.test.ts | 14 +- public/app/plugins/panel/canvas/migrations.ts | 23 ++- public/app/plugins/panel/canvas/module.tsx | 1 - public/locales/en-US/grafana.json | 1 + public/locales/pseudo-LOCALE/grafana.json | 1 + 26 files changed, 218 insertions(+), 157 deletions(-) diff --git a/packages/grafana-ui/src/components/VizTooltip/VizTooltipFooter.tsx b/packages/grafana-ui/src/components/VizTooltip/VizTooltipFooter.tsx index c3c4a34eb64..5b79c42711f 100644 --- a/packages/grafana-ui/src/components/VizTooltip/VizTooltipFooter.tsx +++ b/packages/grafana-ui/src/components/VizTooltip/VizTooltipFooter.tsx @@ -1,11 +1,13 @@ import { css } from '@emotion/css'; +import { useMemo } from 'react'; -import { ActionModel, Field, GrafanaTheme2, LinkModel } from '@grafana/data'; +import { ActionModel, Field, GrafanaTheme2, LinkModel, ThemeSpacingTokens } from '@grafana/data'; import { Button, DataLinkButton, Icon, Stack } from '..'; import { useStyles2 } from '../../themes'; import { Trans } from '../../utils/i18n'; import { ActionButton } from '../Actions/ActionButton'; +import { ResponsiveProp } from '../Layout/utils/responsiveness'; interface VizTooltipFooterProps { dataLinks: Array>; @@ -15,50 +17,75 @@ interface VizTooltipFooterProps { export const ADD_ANNOTATION_ID = 'add-annotation-button'; -const renderDataLinks = (dataLinks: LinkModel[], styles: ReturnType) => { - const oneClickLink = dataLinks.find((link) => link.oneClick === true); +type RenderOneClickTrans = (title: string) => React.ReactNode; +type RenderItem = ( + item: T, + idx: number, + styles: ReturnType +) => React.ReactNode; + +function makeRenderLinksOrActions( + renderOneClickTrans: RenderOneClickTrans, + renderItem: RenderItem, + itemGap?: ResponsiveProp +) { + const renderLinksOrActions = (items: T[], styles: ReturnType) => { + if (items.length === 0) { + return; + } + + const oneClickItem = items.find((item) => item.oneClick === true); + + if (oneClickItem != null) { + return ( +
+ + + + {renderOneClickTrans(oneClickItem.title)} + + +
+ ); + } - if (oneClickLink != null) { return ( - - - - - Click to open {{ linkTitle: oneClickLink.title }} - - - +
+ + {items.map((item, i) => renderItem(item, i, styles))} + +
); - } + }; - return ( - - {dataLinks.map((link, i) => ( - - ))} - - ); -}; + return renderLinksOrActions; +} -const renderActions = (actions: ActionModel[]) => { - return ( - - {actions.map((action, i) => ( - - ))} - - ); -}; +const renderDataLinks = makeRenderLinksOrActions( + (title) => ( + Click to open {{ linkTitle: title }} + ), + (item, i, styles) => ( + + ), + 0.5 +); + +const renderActions = makeRenderLinksOrActions( + (title) => Click to {{ actionTitle: title }}, + (item, i, styles) => +); export const VizTooltipFooter = ({ dataLinks, actions = [], annotate }: VizTooltipFooterProps) => { const styles = useStyles2(getStyles); - const hasOneClickLink = dataLinks.some((link) => link.oneClick === true); + const hasOneClickLink = useMemo(() => dataLinks.some((link) => link.oneClick === true), [dataLinks]); + const hasOneClickAction = useMemo(() => actions.some((action) => action.oneClick === true), [actions]); return (
- {dataLinks.length > 0 &&
{renderDataLinks(dataLinks, styles)}
} - {!hasOneClickLink && actions.length > 0 &&
{renderActions(actions)}
} - {!hasOneClickLink && annotate != null && ( + {!hasOneClickAction && renderDataLinks(dataLinks, styles)} + {!hasOneClickLink && renderActions(actions, styles)} + {!hasOneClickLink && !hasOneClickAction && annotate != null && (