From 6d7147c38df08c8c2423fdc175ff9643802fb9c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Sat, 22 Feb 2025 14:15:26 +0100 Subject: [PATCH] Dashboard: Edit pane tabs (#101145) * Dashboard: Edit pane tabs * update design * Added translation elements * Update * Update * Update * Fix css issue * Update --- .../edit-pane/DashboardAddPane.tsx | 75 ++++++++++++++++++ .../edit-pane/DashboardEditPane.tsx | 52 ++++++++++++- .../scene/NavToolbarActions.tsx | 77 ------------------- public/locales/en-US/grafana.json | 11 ++- public/locales/pseudo-LOCALE/grafana.json | 11 ++- 5 files changed, 144 insertions(+), 82 deletions(-) create mode 100644 public/app/features/dashboard-scene/edit-pane/DashboardAddPane.tsx diff --git a/public/app/features/dashboard-scene/edit-pane/DashboardAddPane.tsx b/public/app/features/dashboard-scene/edit-pane/DashboardAddPane.tsx new file mode 100644 index 00000000000..f58103b09c9 --- /dev/null +++ b/public/app/features/dashboard-scene/edit-pane/DashboardAddPane.tsx @@ -0,0 +1,75 @@ +import { selectors } from '@grafana/e2e-selectors'; +import { Box, Card, Icon } from '@grafana/ui'; +import { t, Trans } from 'app/core/internationalization'; + +import { DashboardInteractions } from '../utils/interactions'; +import { getDashboardSceneFor } from '../utils/utils'; + +import { DashboardEditPane } from './DashboardEditPane'; + +export interface Props { + editPane: DashboardEditPane; +} + +export function DashboardAddPane({ editPane }: Props) { + const dashboard = getDashboardSceneFor(editPane); + + return ( + + dashboard.onCreateNewPanel()} + data-testid={selectors.components.PageToolbar.itemButton('add_visualization')} + title={t('dashboard.toolbar.add-panel-description', 'A container for visualizations and other content')} + > + + Panel + + + + + + { + dashboard.onShowAddLibraryPanelDrawer(); + DashboardInteractions.toolbarAddButtonClicked({ item: 'add_library_panel' }); + }} + data-testid={selectors.pages.AddDashboard.itemButton('Add new panel from panel library menu item')} + title={t( + 'dashboard.toolbar.libray-panel-description', + 'Libray panels allow you share and reuse panels between dashboards' + )} + > + + Import library panel + + + + + + dashboard.onCreateNewRow()} + data-testid={selectors.components.PageToolbar.itemButton('add_row')} + title={t('dashboard.toolbar.row-description', 'A group of panels with an optional header')} + > + + Row + + + + + + dashboard.onCreateNewTab()} + data-testid={selectors.components.PageToolbar.itemButton('add_tab')} + title={t('dashboard.toolbar.tabs-description', 'Break up your dashboard into different horizontal tabs')} + > + + Tab + + + + + + + ); +} diff --git a/public/app/features/dashboard-scene/edit-pane/DashboardEditPane.tsx b/public/app/features/dashboard-scene/edit-pane/DashboardEditPane.tsx index e2e2b091420..fbaf5aa5260 100644 --- a/public/app/features/dashboard-scene/edit-pane/DashboardEditPane.tsx +++ b/public/app/features/dashboard-scene/edit-pane/DashboardEditPane.tsx @@ -4,12 +4,20 @@ import { useEffect, useRef } from 'react'; import { GrafanaTheme2 } from '@grafana/data'; import { SceneObjectState, SceneObjectBase, SceneObject, sceneGraph, useSceneObjectState } from '@grafana/scenes'; -import { ElementSelectionContextItem, ElementSelectionContextState, ToolbarButton, useStyles2 } from '@grafana/ui'; +import { + ElementSelectionContextItem, + ElementSelectionContextState, + Tab, + TabsBar, + ToolbarButton, + useStyles2, +} from '@grafana/ui'; import { t } from 'app/core/internationalization'; import { isInCloneChain } from '../utils/clone'; import { getDashboardSceneFor } from '../utils/utils'; +import { DashboardAddPane } from './DashboardAddPane'; import { ElementEditPane } from './ElementEditPane'; import { ElementSelection } from './ElementSelection'; import { useEditableElement } from './useEditableElement'; @@ -17,8 +25,11 @@ import { useEditableElement } from './useEditableElement'; export interface DashboardEditPaneState extends SceneObjectState { selection?: ElementSelection; selectionContext: ElementSelectionContextState; + tab?: EditPaneTab; } +export type EditPaneTab = 'add' | 'configure' | 'outline'; + export class DashboardEditPane extends SceneObjectBase { public constructor() { super({ @@ -122,6 +133,10 @@ export class DashboardEditPane extends SceneObjectBase { }, }); } + + public onChangeTab = (tab: EditPaneTab) => { + this.setState({ tab }); + }; } export interface Props { @@ -157,7 +172,7 @@ export function DashboardEditPaneRenderer({ editPane, isCollapsed, onToggleColla } }, [editPane, isCollapsed]); - const { selection } = useSceneObjectState(editPane, { shouldActivateOrKeepAlive: true }); + const { selection, tab = 'configure' } = useSceneObjectState(editPane, { shouldActivateOrKeepAlive: true }); const styles = useStyles2(getStyles); const paneRef = useRef(null); const editableElement = useEditableElement(selection); @@ -191,7 +206,28 @@ export function DashboardEditPaneRenderer({ editPane, isCollapsed, onToggleColla return (
- + + editPane.onChangeTab('add')} + /> + editPane.onChangeTab('configure')} + /> + editPane.onChangeTab('outline')} + /> + +
+ {tab === 'add' && } + {tab === 'configure' && } + {tab === 'outline' &&
} +
); } @@ -202,11 +238,21 @@ function getStyles(theme: GrafanaTheme2) { display: 'flex', flexDirection: 'column', flex: '1 1 0', + }), + tabContent: css({ + display: 'flex', + flex: '1 1 0', + flexDirection: 'column', + minHeight: 0, overflow: 'auto', }), rotate180: css({ rotate: '180deg', }), + tabsbar: css({ + padding: theme.spacing(0, 1), + margin: theme.spacing(0.5, 1), + }), expandOptionsWrapper: css({ display: 'flex', flexDirection: 'column', diff --git a/public/app/features/dashboard-scene/scene/NavToolbarActions.tsx b/public/app/features/dashboard-scene/scene/NavToolbarActions.tsx index edda9d01268..d5564aa2814 100644 --- a/public/app/features/dashboard-scene/scene/NavToolbarActions.tsx +++ b/public/app/features/dashboard-scene/scene/NavToolbarActions.tsx @@ -156,83 +156,6 @@ export function ToolbarActions({ dashboard }: Props) { } if (dashboardNewLayouts) { - leftActions.push({ - group: 'add-panel', - condition: isEditingAndShowingDashboard, - render: () => ( - - ), - }); - leftActions.push({ - group: 'add-panel', - condition: isEditingAndShowingDashboard, - render: () => ( - - ), - }); - leftActions.push({ - group: 'add-panel', - condition: isEditingAndShowingDashboard, - render: () => ( - - ), - }); - leftActions.push({ - group: 'add-panel', - condition: isEditingAndShowingDashboard, - render: () => ( - - ), - }); leftActions.push({ group: 'hidden-elements', condition: isEditingAndShowingDashboard, diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json index 0e93bc677a7..7d657396dde 100644 --- a/public/locales/en-US/grafana.json +++ b/public/locales/en-US/grafana.json @@ -1057,6 +1057,11 @@ } } }, + "editpane": { + "add": "Add", + "configure": "Configure", + "outline": "Outline" + }, "empty": { "add-library-panel-body": "Add visualizations that are shared with other dashboards.", "add-library-panel-button": "Add library panel", @@ -1194,7 +1199,8 @@ "toolbar": { "add": "Add", "add-panel": "Panel", - "add-panel-lib": "Import", + "add-panel-description": "A container for visualizations and other content", + "add-panel-lib": "Import library panel", "add-row": "Row", "add-tab": "Tab", "alert-rules": "Alert rules", @@ -1219,6 +1225,7 @@ "label": "Exit edit", "tooltip": "Exits edit mode and discards unsaved changes" }, + "libray-panel-description": "Libray panels allow you share and reuse panels between dashboards", "mark-favorite": "Mark as favorite", "more-save-options": "More save options", "open-original": "Open original dashboard", @@ -1227,6 +1234,7 @@ "playlist-stop": "Stop playlist", "public-dashboard": "Public", "refresh": "Refresh dashboard", + "row-description": "A group of panels with an optional header", "save": "Save dashboard", "save-dashboard": { "label": "Save dashboard", @@ -1246,6 +1254,7 @@ "share-button": "Share", "show-hidden-elements": "Show hidden", "switch-old-dashboard": "Switch to old dashboard page", + "tabs-description": "Break up your dashboard into different horizontal tabs", "unlink-library-panel": "Unlink library panel", "unmark-favorite": "Unmark as favorite" }, diff --git a/public/locales/pseudo-LOCALE/grafana.json b/public/locales/pseudo-LOCALE/grafana.json index 583a6e6832f..aa5a7951a0e 100644 --- a/public/locales/pseudo-LOCALE/grafana.json +++ b/public/locales/pseudo-LOCALE/grafana.json @@ -1057,6 +1057,11 @@ } } }, + "editpane": { + "add": "Åđđ", + "configure": "Cőʼnƒįģūřę", + "outline": "Øūŧľįʼnę" + }, "empty": { "add-library-panel-body": "Åđđ vįşūäľįžäŧįőʼnş ŧĥäŧ äřę şĥäřęđ ŵįŧĥ őŧĥęř đäşĥþőäřđş.", "add-library-panel-button": "Åđđ ľįþřäřy päʼnęľ", @@ -1194,7 +1199,8 @@ "toolbar": { "add": "Åđđ", "add-panel": "Päʼnęľ", - "add-panel-lib": "Ĩmpőřŧ", + "add-panel-description": "Å čőʼnŧäįʼnęř ƒőř vįşūäľįžäŧįőʼnş äʼnđ őŧĥęř čőʼnŧęʼnŧ", + "add-panel-lib": "Ĩmpőřŧ ľįþřäřy päʼnęľ", "add-row": "Ŗőŵ", "add-tab": "Ŧäþ", "alert-rules": "Åľęřŧ řūľęş", @@ -1219,6 +1225,7 @@ "label": "Ēχįŧ ęđįŧ", "tooltip": "Ēχįŧş ęđįŧ mőđę äʼnđ đįşčäřđş ūʼnşävęđ čĥäʼnģęş" }, + "libray-panel-description": "Ŀįþřäy päʼnęľş äľľőŵ yőū şĥäřę äʼnđ řęūşę päʼnęľş þęŧŵęęʼn đäşĥþőäřđş", "mark-favorite": "Mäřĸ äş ƒävőřįŧę", "more-save-options": "Mőřę şävę őpŧįőʼnş", "open-original": "Øpęʼn őřįģįʼnäľ đäşĥþőäřđ", @@ -1227,6 +1234,7 @@ "playlist-stop": "Ŝŧőp pľäyľįşŧ", "public-dashboard": "Pūþľįč", "refresh": "Ŗęƒřęşĥ đäşĥþőäřđ", + "row-description": "Å ģřőūp őƒ päʼnęľş ŵįŧĥ äʼn őpŧįőʼnäľ ĥęäđęř", "save": "Ŝävę đäşĥþőäřđ", "save-dashboard": { "label": "Ŝävę đäşĥþőäřđ", @@ -1246,6 +1254,7 @@ "share-button": "Ŝĥäřę", "show-hidden-elements": "Ŝĥőŵ ĥįđđęʼn", "switch-old-dashboard": "Ŝŵįŧčĥ ŧő őľđ đäşĥþőäřđ päģę", + "tabs-description": "ßřęäĸ ūp yőūř đäşĥþőäřđ įʼnŧő đįƒƒęřęʼnŧ ĥőřįžőʼnŧäľ ŧäþş", "unlink-library-panel": "Ůʼnľįʼnĸ ľįþřäřy päʼnęľ", "unmark-favorite": "Ůʼnmäřĸ äş ƒävőřįŧę" },