SingleTopNav: Handle for non-scenes dashboards (#94198)
handle singleTopNav for non-scenes dashboards
This commit is contained in:
@@ -16,7 +16,6 @@ import {
|
||||
Badge,
|
||||
} from '@grafana/ui';
|
||||
import { updateNavIndex } from 'app/core/actions';
|
||||
import { AppChromeUpdate } from 'app/core/components/AppChrome/AppChromeUpdate';
|
||||
import { NavToolbarSeparator } from 'app/core/components/AppChrome/NavToolbar/NavToolbarSeparator';
|
||||
import config from 'app/core/config';
|
||||
import { useAppNotification } from 'app/core/copy/appNotification';
|
||||
@@ -83,6 +82,7 @@ export const DashNav = memo<Props>((props) => {
|
||||
// this ensures the component rerenders when the location changes
|
||||
useLocation();
|
||||
const forceUpdate = useForceUpdate();
|
||||
const isSingleTopNav = config.featureToggles.singleTopNav;
|
||||
|
||||
// We don't really care about the event payload here only that it triggeres a re-render of this component
|
||||
useBusEvent(props.dashboard.events, DashboardMetaChangedEvent);
|
||||
@@ -357,15 +357,11 @@ export const DashNav = memo<Props>((props) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<AppChromeUpdate
|
||||
actions={
|
||||
<>
|
||||
{renderLeftActions()}
|
||||
<NavToolbarSeparator leftActionsSeparator />
|
||||
<ToolbarButtonRow alignment="right">{renderRightActions()}</ToolbarButtonRow>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
<>
|
||||
{renderLeftActions()}
|
||||
{!isSingleTopNav && <NavToolbarSeparator leftActionsSeparator />}
|
||||
<ToolbarButtonRow alignment="right">{renderRightActions()}</ToolbarButtonRow>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
+2
-2
@@ -5,12 +5,12 @@ import { AccessControlAction } from 'app/types';
|
||||
|
||||
import { SettingsPageProps } from '../DashboardSettings/types';
|
||||
|
||||
export const AccessControlDashboardPermissions = ({ dashboard, sectionNav }: SettingsPageProps) => {
|
||||
export const AccessControlDashboardPermissions = ({ dashboard, sectionNav, toolbar }: SettingsPageProps) => {
|
||||
const canSetPermissions = contextSrv.hasPermission(AccessControlAction.DashboardsPermissionsWrite);
|
||||
const pageNav = sectionNav.node.parentItem;
|
||||
|
||||
return (
|
||||
<Page navModel={sectionNav} pageNav={pageNav}>
|
||||
<Page navModel={sectionNav} pageNav={pageNav} toolbar={toolbar}>
|
||||
<Permissions resource={'dashboards'} resourceId={dashboard.uid} canSetPermissions={canSetPermissions} />
|
||||
</Page>
|
||||
);
|
||||
|
||||
@@ -7,7 +7,7 @@ import { AnnotationSettingsEdit, AnnotationSettingsList, newAnnotationName } fro
|
||||
|
||||
import { SettingsPageProps } from './types';
|
||||
|
||||
export function AnnotationsSettings({ dashboard, editIndex, sectionNav }: SettingsPageProps) {
|
||||
export function AnnotationsSettings({ dashboard, editIndex, sectionNav, toolbar }: SettingsPageProps) {
|
||||
const onNew = () => {
|
||||
const newAnnotation: AnnotationQuery = {
|
||||
name: newAnnotationName,
|
||||
@@ -27,7 +27,7 @@ export function AnnotationsSettings({ dashboard, editIndex, sectionNav }: Settin
|
||||
const isEditing = editIndex != null && editIndex < dashboard.annotations.list.length;
|
||||
|
||||
return (
|
||||
<Page navModel={sectionNav} pageNav={getSubPageNav(dashboard, editIndex, sectionNav.node)}>
|
||||
<Page toolbar={toolbar} navModel={sectionNav} pageNav={getSubPageNav(dashboard, editIndex, sectionNav.node)}>
|
||||
{!isEditing && <AnnotationSettingsList dashboard={dashboard} onNew={onNew} onEdit={onEdit} />}
|
||||
{isEditing && <AnnotationSettingsEdit dashboard={dashboard} editIdx={editIndex!} />}
|
||||
</Page>
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useLocation } from 'react-router-dom-v5-compat';
|
||||
|
||||
import { locationUtil, NavModel, NavModelItem } from '@grafana/data';
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
import { locationService } from '@grafana/runtime';
|
||||
import { config, locationService } from '@grafana/runtime';
|
||||
import { Button, Stack, Text, ToolbarButtonRow } from '@grafana/ui';
|
||||
import { AppChromeUpdate } from 'app/core/components/AppChrome/AppChromeUpdate';
|
||||
import { Page } from 'app/core/components/Page/Page';
|
||||
@@ -36,6 +36,7 @@ const onClose = () => locationService.partial({ editview: null, editIndex: null
|
||||
|
||||
export function DashboardSettings({ dashboard, editview, pageNav, sectionNav }: Props) {
|
||||
const [updateId, setUpdateId] = useState(0);
|
||||
const isSingleTopNav = config.featureToggles.singleTopNav;
|
||||
useEffect(() => {
|
||||
dashboard.events.subscribe(DashboardMetaChangedEvent, () => setUpdateId((v) => v + 1));
|
||||
}, [dashboard]);
|
||||
@@ -81,8 +82,15 @@ export function DashboardSettings({ dashboard, editview, pageNav, sectionNav }:
|
||||
|
||||
return (
|
||||
<>
|
||||
<AppChromeUpdate actions={<ToolbarButtonRow alignment="right">{actions}</ToolbarButtonRow>} />
|
||||
<currentPage.component sectionNav={subSectionNav} dashboard={dashboard} editIndex={editIndex} />
|
||||
{!isSingleTopNav && (
|
||||
<AppChromeUpdate actions={<ToolbarButtonRow alignment="right">{actions}</ToolbarButtonRow>} />
|
||||
)}
|
||||
<currentPage.component
|
||||
toolbar={isSingleTopNav ? <ToolbarButtonRow alignment="right">{actions}</ToolbarButtonRow> : undefined}
|
||||
sectionNav={subSectionNav}
|
||||
dashboard={dashboard}
|
||||
editIndex={editIndex}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -209,9 +217,9 @@ function getSectionNav(
|
||||
};
|
||||
}
|
||||
|
||||
function MakeEditable({ dashboard, sectionNav }: SettingsPageProps) {
|
||||
function MakeEditable({ dashboard, sectionNav, toolbar }: SettingsPageProps) {
|
||||
return (
|
||||
<Page navModel={sectionNav}>
|
||||
<Page navModel={sectionNav} toolbar={toolbar}>
|
||||
<Stack direction="column" gap={2} alignItems="flex-start">
|
||||
<Text variant="h3">Dashboard not editable</Text>
|
||||
<Button type="submit" onClick={() => dashboard.makeEditable()}>
|
||||
|
||||
@@ -39,6 +39,7 @@ export function GeneralSettingsUnconnected({
|
||||
updateTimeZone,
|
||||
updateWeekStart,
|
||||
sectionNav,
|
||||
toolbar,
|
||||
}: Props): JSX.Element {
|
||||
const [renderCounter, setRenderCounter] = useState(0);
|
||||
const [dashboardTitle, setDashboardTitle] = useState(dashboard.title);
|
||||
@@ -119,7 +120,7 @@ export function GeneralSettingsUnconnected({
|
||||
];
|
||||
|
||||
return (
|
||||
<Page navModel={sectionNav} pageNav={pageNav}>
|
||||
<Page navModel={sectionNav} pageNav={pageNav} toolbar={toolbar}>
|
||||
<div style={{ maxWidth: '600px' }}>
|
||||
<Box marginBottom={5}>
|
||||
<Field
|
||||
|
||||
@@ -11,7 +11,7 @@ import { getDashboardSrv } from '../../services/DashboardSrv';
|
||||
|
||||
import { SettingsPageProps } from './types';
|
||||
|
||||
export function JsonEditorSettings({ dashboard, sectionNav }: SettingsPageProps) {
|
||||
export function JsonEditorSettings({ dashboard, sectionNav, toolbar }: SettingsPageProps) {
|
||||
const dashboardSaveModel = dashboard.getSaveModelClone();
|
||||
const [dashboardJson, setDashboardJson] = useState<string>(JSON.stringify(dashboardSaveModel, null, 2));
|
||||
const pageNav = sectionNav.node.parentItem;
|
||||
@@ -24,7 +24,7 @@ export function JsonEditorSettings({ dashboard, sectionNav }: SettingsPageProps)
|
||||
const styles = useStyles2(getStyles);
|
||||
|
||||
return (
|
||||
<Page navModel={sectionNav} pageNav={pageNav}>
|
||||
<Page navModel={sectionNav} pageNav={pageNav} toolbar={toolbar}>
|
||||
<div className={styles.wrapper}>
|
||||
<Trans i18nKey="dashboard-settings.json-editor.subtitle">
|
||||
The JSON model below is the data structure that defines the dashboard. This includes dashboard settings, panel
|
||||
|
||||
@@ -10,7 +10,7 @@ import { SettingsPageProps } from './types';
|
||||
|
||||
export type LinkSettingsMode = 'list' | 'new' | 'edit';
|
||||
|
||||
export function LinksSettings({ dashboard, sectionNav, editIndex }: SettingsPageProps) {
|
||||
export function LinksSettings({ dashboard, sectionNav, editIndex, toolbar }: SettingsPageProps) {
|
||||
const [isNew, setIsNew] = useState<boolean>(false);
|
||||
|
||||
const onGoBack = () => {
|
||||
@@ -44,7 +44,7 @@ export function LinksSettings({ dashboard, sectionNav, editIndex }: SettingsPage
|
||||
}
|
||||
|
||||
return (
|
||||
<Page navModel={sectionNav} pageNav={pageNav}>
|
||||
<Page navModel={sectionNav} pageNav={pageNav} toolbar={toolbar}>
|
||||
{!isEditing && <LinkSettingsList dashboard={dashboard} onNew={onNew} onEdit={onEdit} />}
|
||||
{isEditing && <LinkSettingsEdit dashboard={dashboard} editLinkIdx={editIndex} onGoBack={onGoBack} />}
|
||||
</Page>
|
||||
|
||||
@@ -143,7 +143,7 @@ export class VersionsSettings extends PureComponent<Props, State> {
|
||||
|
||||
if (viewMode === 'compare') {
|
||||
return (
|
||||
<Page navModel={this.props.sectionNav} pageNav={pageNav}>
|
||||
<Page navModel={this.props.sectionNav} pageNav={pageNav} toolbar={this.props.toolbar}>
|
||||
<VersionHistoryHeader
|
||||
onClick={this.reset}
|
||||
baseVersion={baseInfo?.version}
|
||||
@@ -165,7 +165,7 @@ export class VersionsSettings extends PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
return (
|
||||
<Page navModel={this.props.sectionNav} pageNav={pageNav}>
|
||||
<Page navModel={this.props.sectionNav} pageNav={pageNav} toolbar={this.props.toolbar}>
|
||||
{isLoading ? (
|
||||
<VersionsHistorySpinner msg="Fetching history list…" />
|
||||
) : (
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ComponentType } from 'react';
|
||||
import { ComponentType, ReactNode } from 'react';
|
||||
|
||||
import { NavModel } from '@grafana/data';
|
||||
import { IconName } from '@grafana/ui';
|
||||
@@ -17,4 +17,5 @@ export interface SettingsPageProps {
|
||||
dashboard: DashboardModel;
|
||||
sectionNav: NavModel;
|
||||
editIndex?: number;
|
||||
toolbar?: ReactNode;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Subscription } from 'rxjs';
|
||||
|
||||
import { FieldConfigSource, GrafanaTheme2, NavModel, NavModelItem, PageLayoutType } from '@grafana/data';
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
import { locationService } from '@grafana/runtime';
|
||||
import { config, locationService } from '@grafana/runtime';
|
||||
import {
|
||||
Button,
|
||||
HorizontalGroup,
|
||||
@@ -432,6 +432,7 @@ export class PanelEditorUnconnected extends PureComponent<Props> {
|
||||
|
||||
render() {
|
||||
const { initDone, uiState, theme, sectionNav, pageNav, className, updatePanelEditorUIState } = this.props;
|
||||
const isSingleTopNav = config.featureToggles.singleTopNav;
|
||||
const styles = getStyles(theme, this.props);
|
||||
|
||||
if (!initDone) {
|
||||
@@ -445,10 +446,17 @@ export class PanelEditorUnconnected extends PureComponent<Props> {
|
||||
data-testid={selectors.components.PanelEditor.General.content}
|
||||
layout={PageLayoutType.Custom}
|
||||
className={className}
|
||||
toolbar={
|
||||
isSingleTopNav ? (
|
||||
<ToolbarButtonRow alignment="right">{this.renderEditorActions()}</ToolbarButtonRow>
|
||||
) : undefined
|
||||
}
|
||||
>
|
||||
<AppChromeUpdate
|
||||
actions={<ToolbarButtonRow alignment="right">{this.renderEditorActions()}</ToolbarButtonRow>}
|
||||
/>
|
||||
{!isSingleTopNav && (
|
||||
<AppChromeUpdate
|
||||
actions={<ToolbarButtonRow alignment="right">{this.renderEditorActions()}</ToolbarButtonRow>}
|
||||
/>
|
||||
)}
|
||||
<div className={styles.wrapper}>
|
||||
<div className={styles.verticalSplitPanesWrapper}>
|
||||
{!uiState.isPanelOptionsVisible ? (
|
||||
|
||||
@@ -7,6 +7,7 @@ import { selectors } from '@grafana/e2e-selectors';
|
||||
import { config, locationService } from '@grafana/runtime';
|
||||
import { Themeable2, withTheme2 } from '@grafana/ui';
|
||||
import { notifyApp } from 'app/core/actions';
|
||||
import { AppChromeUpdate } from 'app/core/components/AppChrome/AppChromeUpdate';
|
||||
import { ScrollRefElement } from 'app/core/components/NativeScrollbar';
|
||||
import { Page } from 'app/core/components/Page/Page';
|
||||
import { EntityNotFound } from 'app/core/components/PageNotFound/EntityNotFound';
|
||||
@@ -359,6 +360,7 @@ export class UnthemedDashboardPage extends PureComponent<Props, State> {
|
||||
const { editPanel, viewPanel, pageNav, sectionNav } = this.state;
|
||||
const kioskMode = getKioskMode(this.props.queryParams);
|
||||
const styles = getStyles(theme);
|
||||
const isSingleTopNav = config.featureToggles.singleTopNav;
|
||||
|
||||
if (!dashboard || !pageNav || !sectionNav) {
|
||||
return <DashboardLoading initPhase={this.props.initPhase} />;
|
||||
@@ -434,9 +436,8 @@ export class UnthemedDashboardPage extends PureComponent<Props, State> {
|
||||
layout={PageLayoutType.Canvas}
|
||||
className={pageClassName}
|
||||
onSetScrollRef={this.setScrollRef}
|
||||
>
|
||||
{showToolbar && (
|
||||
<header data-testid={selectors.pages.Dashboard.DashNav.navV2}>
|
||||
toolbar={
|
||||
isSingleTopNav ? (
|
||||
<DashNav
|
||||
dashboard={dashboard}
|
||||
title={dashboard.title}
|
||||
@@ -445,6 +446,23 @@ export class UnthemedDashboardPage extends PureComponent<Props, State> {
|
||||
kioskMode={kioskMode}
|
||||
hideTimePicker={dashboard.timepicker.hidden}
|
||||
/>
|
||||
) : undefined
|
||||
}
|
||||
>
|
||||
{showToolbar && (
|
||||
<header data-testid={selectors.pages.Dashboard.DashNav.navV2}>
|
||||
<AppChromeUpdate
|
||||
actions={
|
||||
<DashNav
|
||||
dashboard={dashboard}
|
||||
title={dashboard.title}
|
||||
folderTitle={dashboard.meta.folderTitle}
|
||||
isFullscreen={!!viewPanel}
|
||||
kioskMode={kioskMode}
|
||||
hideTimePicker={dashboard.timepicker.hidden}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</header>
|
||||
)}
|
||||
<DashboardPrompt dashboard={dashboard} />
|
||||
|
||||
@@ -105,14 +105,14 @@ class VariableEditorContainerUnconnected extends PureComponent<Props, State> {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { editIndex, variables, sectionNav } = this.props;
|
||||
const { editIndex, variables, sectionNav, toolbar } = this.props;
|
||||
const variableToEdit = editIndex != null ? variables[editIndex] : undefined;
|
||||
const node = sectionNav.node;
|
||||
const parentItem = node.parentItem;
|
||||
const subPageNav = variableToEdit ? { text: variableToEdit.name, parentItem } : parentItem;
|
||||
|
||||
return (
|
||||
<Page navModel={this.props.sectionNav} pageNav={subPageNav}>
|
||||
<Page toolbar={toolbar} navModel={this.props.sectionNav} pageNav={subPageNav}>
|
||||
{!variableToEdit && (
|
||||
<VariableEditorList
|
||||
variables={this.props.variables}
|
||||
|
||||
Reference in New Issue
Block a user