From 1d7d658934fec56edb2db4bc5cb42fdf46368d0d Mon Sep 17 00:00:00 2001 From: Bogdan Matei Date: Fri, 17 Jan 2025 15:40:18 +0200 Subject: [PATCH] Dashboard: Show hidden elements (#99073) --- .../edit-pane/DashboardEditPane.tsx | 5 ++- .../dashboard-scene/scene/DashboardScene.tsx | 10 +++-- .../scene/NavToolbarActions.tsx | 30 +++++++++++++- .../scene/layout-rows/RowItem.tsx | 40 ++++++++++--------- public/locales/en-US/grafana.json | 1 + public/locales/pseudo-LOCALE/grafana.json | 1 + 6 files changed, 63 insertions(+), 24 deletions(-) diff --git a/public/app/features/dashboard-scene/edit-pane/DashboardEditPane.tsx b/public/app/features/dashboard-scene/edit-pane/DashboardEditPane.tsx index 55ab34be79d..b8fdd41352d 100644 --- a/public/app/features/dashboard-scene/edit-pane/DashboardEditPane.tsx +++ b/public/app/features/dashboard-scene/edit-pane/DashboardEditPane.tsx @@ -39,7 +39,10 @@ export class DashboardEditPane extends SceneObjectBase { } public disableSelection() { - this.setState({ selectionContext: { ...this.state.selectionContext, enabled: false } }); + this.setState({ + selectionContext: { ...this.state.selectionContext, selected: [], enabled: false }, + selectedObject: undefined, + }); } private selectElement(element: ElementSelectionContextItem, multi?: boolean) { diff --git a/public/app/features/dashboard-scene/scene/DashboardScene.tsx b/public/app/features/dashboard-scene/scene/DashboardScene.tsx index 6622991b47e..a532a77cd15 100644 --- a/public/app/features/dashboard-scene/scene/DashboardScene.tsx +++ b/public/app/features/dashboard-scene/scene/DashboardScene.tsx @@ -109,6 +109,8 @@ export interface DashboardSceneState extends SceneObjectState { controls?: DashboardControls; /** True when editing */ isEditing?: boolean; + /** Controls the visibility of hidden elements like row headers */ + showHiddenElements?: boolean; /** True when user made a change */ isDirty?: boolean; /** meta flags */ @@ -257,7 +259,7 @@ export class DashboardScene extends SceneObjectBase { this._initialUrlState = locationService.getLocation(); // Switch to edit mode - this.setState({ isEditing: true }); + this.setState({ isEditing: true, showHiddenElements: true }); // Propagate change edit mode change to children this.state.body.editModeChanged(true); @@ -338,10 +340,10 @@ export class DashboardScene extends SceneObjectBase { if (restoreInitialState) { // Restore initial state and disable editing - this.setState({ ...this._initialState, isEditing: false }); + this.setState({ ...this._initialState, isEditing: false, showHiddenElements: false }); } else { // Do not restore - this.setState({ isEditing: false }); + this.setState({ isEditing: false, showHiddenElements: false }); } // if we are in edit panel, we need to onDiscard() @@ -359,6 +361,8 @@ export class DashboardScene extends SceneObjectBase { return this._initialState !== undefined; } + public onToggleHiddenElements = () => this.setState({ showHiddenElements: !this.state.showHiddenElements }); + public pauseTrackingChanges() { this._changeTracker.stopTrackingChanges(); } diff --git a/public/app/features/dashboard-scene/scene/NavToolbarActions.tsx b/public/app/features/dashboard-scene/scene/NavToolbarActions.tsx index fd6b419538f..8d65d35238b 100644 --- a/public/app/features/dashboard-scene/scene/NavToolbarActions.tsx +++ b/public/app/features/dashboard-scene/scene/NavToolbarActions.tsx @@ -11,8 +11,10 @@ import { ButtonGroup, Dropdown, Icon, + InlineLabel, Menu, Stack, + Switch, ToolbarButton, ToolbarButtonRow, useStyles2, @@ -54,7 +56,8 @@ NavToolbarActions.displayName = 'NavToolbarActions'; * This part is split into a separate component to help test this */ export function ToolbarActions({ dashboard }: Props) { - const { isEditing, viewPanelScene, isDirty, uid, meta, editview, editPanel, editable } = dashboard.useState(); + const { isEditing, showHiddenElements, viewPanelScene, isDirty, uid, meta, editview, editPanel, editable } = + dashboard.useState(); const { isPlaying } = playlistSrv.useState(); const [isAddPanelMenuOpen, setIsAddPanelMenuOpen] = useState(false); @@ -215,6 +218,25 @@ export function ToolbarActions({ dashboard }: Props) { ), }); + leftActions.push({ + group: 'hidden-elements', + condition: isEditingAndShowingDashboard, + render: () => ( + + { + evt.stopPropagation(); + dashboard.onToggleHiddenElements(); + }} + data-testid={selectors.components.PageToolbar.itemButton('toggle_hidden_elements')} + /> + + Show hidden + + + ), + }); } else { toolbarActions.push({ group: 'add-panel', @@ -741,6 +763,12 @@ interface ToolbarAction { function getStyles(theme: GrafanaTheme2) { return { + hiddenElementsContainer: css({ + display: 'flex', + padding: 0, + gap: theme.spacing(1), + whiteSpace: 'nowrap', + }), buttonWithExtraMargin: css({ margin: theme.spacing(0, 0.5), }), diff --git a/public/app/features/dashboard-scene/scene/layout-rows/RowItem.tsx b/public/app/features/dashboard-scene/scene/layout-rows/RowItem.tsx index e7fab760328..eb168e80bea 100644 --- a/public/app/features/dashboard-scene/scene/layout-rows/RowItem.tsx +++ b/public/app/features/dashboard-scene/scene/layout-rows/RowItem.tsx @@ -95,8 +95,8 @@ export class RowItem extends SceneObjectBase implements LayoutPare }; public static Component = ({ model }: SceneComponentProps) => { - const { layout, title, isCollapsed, height = 'expand' } = model.useState(); - const { isEditing } = getDashboardSceneFor(model).useState(); + const { layout, title, isCollapsed, height = 'expand', isHeaderHidden } = model.useState(); + const { isEditing, showHiddenElements } = getDashboardSceneFor(model).useState(); const styles = useStyles2(getStyles); const titleInterpolated = sceneGraph.interpolate(model, title, undefined, 'text'); const ref = useRef(null); @@ -113,22 +113,24 @@ export class RowItem extends SceneObjectBase implements LayoutPare )} ref={ref} > -
- - {isEditing && ( -
+ {(!isHeaderHidden || (isEditing && showHiddenElements)) && ( +
+ + {isEditing && ( +
+ )} {!isCollapsed && } ); @@ -201,7 +203,7 @@ export function RowTitleInput({ row }: { row: RowItem }) { } export function RowHeaderSwitch({ row }: { row: RowItem }) { - const { isHeaderHidden } = row.useState(); + const { isHeaderHidden = false } = row.useState(); return (