mirror of
https://github.com/grafana/grafana.git
synced 2025-02-15 10:03:33 -06:00
* fix(pagetoolbar): pad elements top and bottom to keep vertical align and wrapper padding * fix(sidemenu): prevent mobile sidemenu squashing dashboard, vertically align mobile sidemenu icon * fix(dashboardsettings): prevent subheader overlap * fix(pagetoolbar): center align all toolbar elements vertically * refactor(pagetoolbar): combine vertical paddings to bring back original padding values * refactor: update padding values for components that use PageToolbar * fix(playlists): update Empty cta link route to prevent 404 * test(dashboard): update snapshot
201 lines
6.1 KiB
TypeScript
201 lines
6.1 KiB
TypeScript
import React, { PureComponent } from 'react';
|
|
import { css, cx } from '@emotion/css';
|
|
import { selectors } from '@grafana/e2e-selectors';
|
|
import { Button, CustomScrollbar, Icon, IconName, PageToolbar, stylesFactory } from '@grafana/ui';
|
|
import config from 'app/core/config';
|
|
import { contextSrv } from 'app/core/services/context_srv';
|
|
import { dashboardWatcher } from 'app/features/live/dashboard/dashboardWatcher';
|
|
import { DashboardModel } from '../../state/DashboardModel';
|
|
import { SaveDashboardButton, SaveDashboardAsButton } from '../SaveDashboard/SaveDashboardButton';
|
|
import { VariableEditorContainer } from '../../../variables/editor/VariableEditorContainer';
|
|
import { DashboardPermissions } from '../DashboardPermissions/DashboardPermissions';
|
|
import { GeneralSettings } from './GeneralSettings';
|
|
import { AnnotationsSettings } from './AnnotationsSettings';
|
|
import { LinksSettings } from './LinksSettings';
|
|
import { VersionsSettings } from './VersionsSettings';
|
|
import { JsonEditorSettings } from './JsonEditorSettings';
|
|
import { GrafanaTheme2 } from '@grafana/data';
|
|
import { locationService } from '@grafana/runtime';
|
|
|
|
export interface Props {
|
|
dashboard: DashboardModel;
|
|
editview: string;
|
|
}
|
|
|
|
export interface SettingsPage {
|
|
id: string;
|
|
title: string;
|
|
icon: IconName;
|
|
render: () => React.ReactNode;
|
|
}
|
|
|
|
export class DashboardSettings extends PureComponent<Props> {
|
|
onClose = () => {
|
|
locationService.partial({ editview: null });
|
|
};
|
|
|
|
onChangePage = (editview: string) => {
|
|
locationService.partial({ editview });
|
|
};
|
|
|
|
getPages(): SettingsPage[] {
|
|
const { dashboard } = this.props;
|
|
const pages: SettingsPage[] = [];
|
|
|
|
if (dashboard.meta.canEdit) {
|
|
pages.push(this.getGeneralPage());
|
|
|
|
pages.push({
|
|
title: 'Annotations',
|
|
id: 'annotations',
|
|
icon: 'comment-alt',
|
|
render: () => <AnnotationsSettings dashboard={dashboard} />,
|
|
});
|
|
|
|
pages.push({
|
|
title: 'Variables',
|
|
id: 'templating',
|
|
icon: 'calculator-alt',
|
|
render: () => <VariableEditorContainer />,
|
|
});
|
|
|
|
pages.push({
|
|
title: 'Links',
|
|
id: 'links',
|
|
icon: 'link',
|
|
render: () => <LinksSettings dashboard={dashboard} />,
|
|
});
|
|
}
|
|
|
|
if (dashboard.meta.canMakeEditable) {
|
|
pages.push({
|
|
title: 'General',
|
|
icon: 'sliders-v-alt',
|
|
id: 'settings',
|
|
render: () => this.renderMakeEditable(),
|
|
});
|
|
}
|
|
|
|
if (dashboard.id && dashboard.meta.canSave) {
|
|
pages.push({
|
|
title: 'Versions',
|
|
id: 'versions',
|
|
icon: 'history',
|
|
render: () => <VersionsSettings dashboard={dashboard} />,
|
|
});
|
|
}
|
|
|
|
if (dashboard.id && dashboard.meta.canAdmin) {
|
|
pages.push({
|
|
title: 'Permissions',
|
|
id: 'permissions',
|
|
icon: 'lock',
|
|
render: () => <DashboardPermissions dashboard={dashboard} />,
|
|
});
|
|
}
|
|
|
|
pages.push({
|
|
title: 'JSON Model',
|
|
id: 'dashboard_json',
|
|
icon: 'arrow',
|
|
render: () => <JsonEditorSettings dashboard={dashboard} />,
|
|
});
|
|
|
|
return pages;
|
|
}
|
|
|
|
onMakeEditable = () => {
|
|
const { dashboard } = this.props;
|
|
dashboard.editable = true;
|
|
dashboard.meta.canMakeEditable = false;
|
|
dashboard.meta.canEdit = true;
|
|
dashboard.meta.canSave = true;
|
|
this.forceUpdate();
|
|
};
|
|
|
|
onPostSave = () => {
|
|
this.props.dashboard.meta.hasUnsavedFolderChange = false;
|
|
dashboardWatcher.reloadPage();
|
|
};
|
|
|
|
renderMakeEditable(): React.ReactNode {
|
|
return (
|
|
<div>
|
|
<div className="dashboard-settings__header">Dashboard not editable</div>
|
|
<Button onClick={this.onMakeEditable}>Make editable</Button>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
getGeneralPage(): SettingsPage {
|
|
return {
|
|
title: 'General',
|
|
id: 'settings',
|
|
icon: 'sliders-v-alt',
|
|
render: () => <GeneralSettings dashboard={this.props.dashboard} />,
|
|
};
|
|
}
|
|
|
|
render() {
|
|
const { dashboard, editview } = this.props;
|
|
const folderTitle = dashboard.meta.folderTitle;
|
|
const pages = this.getPages();
|
|
const currentPage = pages.find((page) => page.id === editview) ?? pages[0];
|
|
const canSaveAs = contextSrv.hasEditPermissionInFolders;
|
|
const canSave = dashboard.meta.canSave;
|
|
const styles = getStyles(config.theme2);
|
|
|
|
return (
|
|
<div className="dashboard-settings">
|
|
<PageToolbar title={`${dashboard.title} / Settings`} parent={folderTitle} onGoBack={this.onClose} />
|
|
<CustomScrollbar>
|
|
<div className={styles.scrollInner}>
|
|
<div className={styles.settingsWrapper}>
|
|
<aside className="dashboard-settings__aside">
|
|
{pages.map((page) => (
|
|
<a
|
|
className={cx('dashboard-settings__nav-item', { active: page.id === editview })}
|
|
aria-label={selectors.pages.Dashboard.Settings.General.sectionItems(page.title)}
|
|
onClick={() => this.onChangePage(page.id)}
|
|
key={page.id}
|
|
>
|
|
<Icon name={page.icon} style={{ marginRight: '4px' }} />
|
|
{page.title}
|
|
</a>
|
|
))}
|
|
<div className="dashboard-settings__aside-actions">
|
|
{canSave && <SaveDashboardButton dashboard={dashboard} onSaveSuccess={this.onPostSave} />}
|
|
{canSaveAs && (
|
|
<SaveDashboardAsButton dashboard={dashboard} onSaveSuccess={this.onPostSave} variant="secondary" />
|
|
)}
|
|
</div>
|
|
</aside>
|
|
<div className={styles.settingsContent}>{currentPage.render()}</div>
|
|
</div>
|
|
</div>
|
|
</CustomScrollbar>
|
|
</div>
|
|
);
|
|
}
|
|
}
|
|
|
|
const getStyles = stylesFactory((theme: GrafanaTheme2) => ({
|
|
scrollInner: css`
|
|
min-width: 100%;
|
|
display: flex;
|
|
`,
|
|
settingsWrapper: css`
|
|
margin: ${theme.spacing(0, 2, 2)};
|
|
display: flex;
|
|
flex-grow: 1;
|
|
`,
|
|
settingsContent: css`
|
|
flex-grow: 1;
|
|
height: 100%;
|
|
padding: 32px;
|
|
border: 1px solid ${theme.colors.border.weak};
|
|
background: ${theme.colors.background.primary};
|
|
border-radius: ${theme.shape.borderRadius()};
|
|
`,
|
|
}));
|