Dashboard: Show hidden elements (#99073)

This commit is contained in:
Bogdan Matei 2025-01-17 15:40:18 +02:00 committed by GitHub
parent 356b32008b
commit 1d7d658934
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 63 additions and 24 deletions

View File

@ -39,7 +39,10 @@ export class DashboardEditPane extends SceneObjectBase<DashboardEditPaneState> {
}
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) {

View File

@ -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<DashboardSceneState> {
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<DashboardSceneState> {
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<DashboardSceneState> {
return this._initialState !== undefined;
}
public onToggleHiddenElements = () => this.setState({ showHiddenElements: !this.state.showHiddenElements });
public pauseTrackingChanges() {
this._changeTracker.stopTrackingChanges();
}

View File

@ -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) {
</Button>
),
});
leftActions.push({
group: 'hidden-elements',
condition: isEditingAndShowingDashboard,
render: () => (
<InlineLabel key="toggle-hidden-elements" transparent={true} className={styles.hiddenElementsContainer}>
<Switch
value={showHiddenElements}
onChange={(evt) => {
evt.stopPropagation();
dashboard.onToggleHiddenElements();
}}
data-testid={selectors.components.PageToolbar.itemButton('toggle_hidden_elements')}
/>
<span>
<Trans i18nKey="dashboard.toolbar.show-hidden-elements">Show hidden</Trans>
</span>
</InlineLabel>
),
});
} 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),
}),

View File

@ -95,8 +95,8 @@ export class RowItem extends SceneObjectBase<RowItemState> implements LayoutPare
};
public static Component = ({ model }: SceneComponentProps<RowItem>) => {
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<HTMLDivElement>(null);
@ -113,22 +113,24 @@ export class RowItem extends SceneObjectBase<RowItemState> implements LayoutPare
)}
ref={ref}
>
<div className={styles.rowHeader}>
<button
onClick={model.onCollapseToggle}
className={styles.rowTitleButton}
aria-label={isCollapsed ? 'Expand row' : 'Collapse row'}
data-testid={selectors.components.DashboardRow.title(titleInterpolated)}
>
<Icon name={isCollapsed ? 'angle-right' : 'angle-down'} />
<span className={styles.rowTitle} role="heading">
{titleInterpolated}
</span>
</button>
{isEditing && (
<Button icon="pen" variant="secondary" size="sm" fill="text" onPointerDown={(evt) => onSelect?.(evt)} />
)}
</div>
{(!isHeaderHidden || (isEditing && showHiddenElements)) && (
<div className={styles.rowHeader}>
<button
onClick={model.onCollapseToggle}
className={styles.rowTitleButton}
aria-label={isCollapsed ? 'Expand row' : 'Collapse row'}
data-testid={selectors.components.DashboardRow.title(titleInterpolated)}
>
<Icon name={isCollapsed ? 'angle-right' : 'angle-down'} />
<span className={styles.rowTitle} role="heading">
{titleInterpolated}
</span>
</button>
{isEditing && (
<Button icon="pen" variant="secondary" size="sm" fill="text" onPointerDown={(evt) => onSelect?.(evt)} />
)}
</div>
)}
{!isCollapsed && <layout.Component model={layout} />}
</div>
);
@ -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 (
<Switch

View File

@ -957,6 +957,7 @@
"settings": "Dashboard settings",
"share": "Share dashboard",
"share-button": "Share",
"show-hidden-elements": "Show hidden",
"unmark-favorite": "Unmark as favorite"
},
"validation": {

View File

@ -957,6 +957,7 @@
"settings": "Đäşĥþőäřđ şęŧŧįʼnģş",
"share": "Ŝĥäřę đäşĥþőäřđ",
"share-button": "Ŝĥäřę",
"show-hidden-elements": "Ŝĥőŵ ĥįđđęʼn",
"unmark-favorite": "Ůʼnmäřĸ äş ƒävőřįŧę"
},
"validation": {