mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
DashboardSettings: Provide skeleton for list editing (#78789)
* DashboardSettings: Provide basics for list editing * Update public/app/features/dashboard-scene/scene/DashboardSceneUrlSync.ts Co-authored-by: Torkel Ödegaard <torkel@grafana.com> * Lint * Review * Fix page nav for items * Move links to dashbaord scene state --------- Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
This commit is contained in:
parent
e152323a33
commit
2b953660a4
@ -12,17 +12,21 @@ import {
|
||||
} from 'app/features/dashboard/components/SubMenu/DashboardLinksDashboard';
|
||||
import { getLinkSrv } from 'app/features/panel/panellinks/link_srv';
|
||||
|
||||
interface DashboardLinksControlsState extends SceneObjectState {
|
||||
links: DashboardLink[];
|
||||
dashboardUID: string;
|
||||
}
|
||||
import { getDashboardSceneFor } from '../utils/utils';
|
||||
|
||||
interface DashboardLinksControlsState extends SceneObjectState {}
|
||||
|
||||
export class DashboardLinksControls extends SceneObjectBase<DashboardLinksControlsState> {
|
||||
static Component = DashboardLinksControlsRenderer;
|
||||
}
|
||||
|
||||
function DashboardLinksControlsRenderer({ model }: SceneComponentProps<DashboardLinksControls>) {
|
||||
const { links, dashboardUID } = model.useState();
|
||||
const { links, uid } = getDashboardSceneFor(model).useState();
|
||||
|
||||
if (!links || !uid) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{links.map((link: DashboardLink, index: number) => {
|
||||
@ -30,7 +34,7 @@ function DashboardLinksControlsRenderer({ model }: SceneComponentProps<Dashboard
|
||||
const key = `${link.title}-$${index}`;
|
||||
|
||||
if (link.type === 'dashboards') {
|
||||
return <DashboardLinksDashboard key={key} link={link} linkInfo={linkInfo} dashboardUID={dashboardUID} />;
|
||||
return <DashboardLinksDashboard key={key} link={link} linkInfo={linkInfo} dashboardUID={uid} />;
|
||||
}
|
||||
|
||||
const icon = linkIconMap[link.icon];
|
||||
|
@ -16,6 +16,7 @@ import {
|
||||
SceneVariable,
|
||||
SceneVariableDependencyConfigLike,
|
||||
} from '@grafana/scenes';
|
||||
import { DashboardLink } from '@grafana/schema';
|
||||
import appEvents from 'app/core/app_events';
|
||||
import { getNavModel } from 'app/core/selectors/navModel';
|
||||
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
|
||||
@ -37,6 +38,8 @@ export interface DashboardSceneState extends SceneObjectState {
|
||||
title: string;
|
||||
/** Tags */
|
||||
tags?: string[];
|
||||
/** Links */
|
||||
links?: DashboardLink[];
|
||||
/** A uid when saved */
|
||||
uid?: string;
|
||||
/** @deprecated */
|
||||
|
@ -35,7 +35,7 @@ export class DashboardSceneUrlSync implements SceneObjectUrlSyncHandler {
|
||||
const update: Partial<DashboardSceneState> = {};
|
||||
|
||||
if (typeof values.editview === 'string' && meta.canEdit) {
|
||||
update.editview = createDashboardEditViewFor(values.editview);
|
||||
update.editview = createDashboardEditViewFor(values.editview, this._scene.getRef());
|
||||
|
||||
// If we are not in editing (for example after full page reload)
|
||||
if (!isEditing) {
|
||||
|
@ -226,6 +226,7 @@ export function createDashboardSceneFromDashboardModel(oldModel: DashboardModel)
|
||||
return new DashboardScene({
|
||||
title: oldModel.title,
|
||||
tags: oldModel.tags || [],
|
||||
links: oldModel.links || [],
|
||||
uid: oldModel.uid,
|
||||
id: oldModel.id,
|
||||
meta: oldModel.meta,
|
||||
@ -265,10 +266,7 @@ export function createDashboardSceneFromDashboardModel(oldModel: DashboardModel)
|
||||
intervals: oldModel.timepicker.refresh_intervals,
|
||||
}),
|
||||
],
|
||||
linkControls: new DashboardLinksControls({
|
||||
links: oldModel.links,
|
||||
dashboardUID: oldModel.uid,
|
||||
}),
|
||||
linkControls: new DashboardLinksControls({}),
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
@ -1,16 +1,16 @@
|
||||
import React from 'react';
|
||||
|
||||
import { PageLayoutType } from '@grafana/data';
|
||||
import { SceneComponentProps, SceneObjectBase, SceneObjectState } from '@grafana/scenes';
|
||||
import { SceneComponentProps, SceneObjectBase } from '@grafana/scenes';
|
||||
import { Page } from 'app/core/components/Page/Page';
|
||||
|
||||
import { NavToolbarActions } from '../scene/NavToolbarActions';
|
||||
import { getDashboardSceneFor } from '../utils/utils';
|
||||
|
||||
import { GeneralSettingsEditView } from './GeneralSettings';
|
||||
import { DashboardEditView, useDashboardEditPageNav } from './utils';
|
||||
import { DashboardEditView, DashboardEditViewState, useDashboardEditPageNav } from './utils';
|
||||
|
||||
export interface AnnotationsEditViewState extends SceneObjectState {}
|
||||
export interface AnnotationsEditViewState extends DashboardEditViewState {}
|
||||
|
||||
export class AnnotationsEditView extends SceneObjectBase<AnnotationsEditViewState> implements DashboardEditView {
|
||||
public getUrlKey(): string {
|
||||
|
@ -0,0 +1,81 @@
|
||||
import React from 'react';
|
||||
|
||||
import { NavModel, NavModelItem, PageLayoutType } from '@grafana/data';
|
||||
import { locationService } from '@grafana/runtime';
|
||||
import { SceneComponentProps, SceneObjectBase } from '@grafana/scenes';
|
||||
import { DashboardLink } from '@grafana/schema';
|
||||
import { Link } from '@grafana/ui';
|
||||
import { Page } from 'app/core/components/Page/Page';
|
||||
|
||||
import { DashboardScene } from '../scene/DashboardScene';
|
||||
import { NavToolbarActions } from '../scene/NavToolbarActions';
|
||||
|
||||
import { EditListViewSceneUrlSync } from './EditListViewSceneUrlSync';
|
||||
import { DashboardEditView, DashboardEditListViewState, useDashboardEditPageNav } from './utils';
|
||||
|
||||
export interface DashboardLinksEditViewState extends DashboardEditListViewState {}
|
||||
|
||||
export class DashboardLinksEditView extends SceneObjectBase<DashboardLinksEditViewState> implements DashboardEditView {
|
||||
static Component = DashboardLinksEditViewRenderer;
|
||||
|
||||
protected _urlSync = new EditListViewSceneUrlSync(this);
|
||||
|
||||
public getUrlKey(): string {
|
||||
return 'links';
|
||||
}
|
||||
}
|
||||
|
||||
function DashboardLinksEditViewRenderer({ model }: SceneComponentProps<DashboardLinksEditView>) {
|
||||
const { dashboardRef, editIndex } = model.useState();
|
||||
const dashboard = dashboardRef.resolve();
|
||||
const links = dashboard.state.links || [];
|
||||
const { navModel, pageNav } = useDashboardEditPageNav(dashboard, model.getUrlKey());
|
||||
|
||||
if (editIndex !== undefined) {
|
||||
const link = links[editIndex];
|
||||
if (link) {
|
||||
return <EditLinkView pageNav={pageNav} navModel={navModel} link={link} dashboard={dashboard} />;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Page navModel={navModel} pageNav={pageNav} layout={PageLayoutType.Standard}>
|
||||
<NavToolbarActions dashboard={dashboard} />
|
||||
{links.map((link, i) => (
|
||||
<Link
|
||||
key={`${link.title}-${i}`}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
locationService.partial({ editIndex: i });
|
||||
}}
|
||||
>
|
||||
{link.title}
|
||||
</Link>
|
||||
))}
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
|
||||
interface EditLinkViewProps {
|
||||
link: DashboardLink;
|
||||
pageNav: NavModelItem;
|
||||
navModel: NavModel;
|
||||
dashboard: DashboardScene;
|
||||
}
|
||||
|
||||
function EditLinkView({ pageNav, link, navModel, dashboard }: EditLinkViewProps) {
|
||||
const parentTab = pageNav.children!.find((p) => p.active)!;
|
||||
parentTab.parentItem = pageNav;
|
||||
|
||||
const editLinkPageNav = {
|
||||
text: 'Edit link',
|
||||
parentItem: parentTab,
|
||||
};
|
||||
|
||||
return (
|
||||
<Page navModel={navModel} pageNav={editLinkPageNav} layout={PageLayoutType.Standard}>
|
||||
<NavToolbarActions dashboard={dashboard} />
|
||||
{JSON.stringify(link)}
|
||||
</Page>
|
||||
);
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
import { SceneObjectUrlSyncHandler, SceneObjectUrlValues } from '@grafana/scenes';
|
||||
|
||||
import { DashboardLinksEditView, DashboardLinksEditViewState } from './DashboardLinksEditView';
|
||||
|
||||
export class EditListViewSceneUrlSync implements SceneObjectUrlSyncHandler {
|
||||
constructor(private _scene: DashboardLinksEditView) {}
|
||||
|
||||
getKeys(): string[] {
|
||||
return ['editIndex'];
|
||||
}
|
||||
|
||||
getUrlState(): SceneObjectUrlValues {
|
||||
const state = this._scene.state;
|
||||
return {
|
||||
editIndex: state.editIndex !== undefined ? String(state.editIndex) : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
updateFromUrl(values: SceneObjectUrlValues): void {
|
||||
let update: Partial<DashboardLinksEditViewState> = {};
|
||||
if (typeof values.editIndex === 'string') {
|
||||
update = { editIndex: Number(values.editIndex) };
|
||||
} else {
|
||||
update = { editIndex: undefined };
|
||||
}
|
||||
|
||||
if (Object.keys(update).length > 0) {
|
||||
this._scene.setState(update);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,15 +1,15 @@
|
||||
import React from 'react';
|
||||
|
||||
import { PageLayoutType } from '@grafana/data';
|
||||
import { SceneComponentProps, SceneObjectBase, SceneObjectState } from '@grafana/scenes';
|
||||
import { SceneComponentProps, SceneObjectBase } from '@grafana/scenes';
|
||||
import { Page } from 'app/core/components/Page/Page';
|
||||
|
||||
import { NavToolbarActions } from '../scene/NavToolbarActions';
|
||||
import { getDashboardSceneFor } from '../utils/utils';
|
||||
|
||||
import { DashboardEditView, useDashboardEditPageNav } from './utils';
|
||||
import { DashboardEditView, DashboardEditViewState, useDashboardEditPageNav } from './utils';
|
||||
|
||||
export interface GeneralSettingsEditViewState extends SceneObjectState {}
|
||||
export interface GeneralSettingsEditViewState extends DashboardEditViewState {}
|
||||
|
||||
export class GeneralSettingsEditView
|
||||
extends SceneObjectBase<GeneralSettingsEditViewState>
|
||||
|
@ -1,16 +1,16 @@
|
||||
import React from 'react';
|
||||
|
||||
import { PageLayoutType } from '@grafana/data';
|
||||
import { SceneComponentProps, SceneObjectBase, SceneObjectState } from '@grafana/scenes';
|
||||
import { SceneComponentProps, SceneObjectBase } from '@grafana/scenes';
|
||||
import { Page } from 'app/core/components/Page/Page';
|
||||
|
||||
import { NavToolbarActions } from '../scene/NavToolbarActions';
|
||||
import { getDashboardSceneFor } from '../utils/utils';
|
||||
|
||||
import { GeneralSettingsEditView } from './GeneralSettings';
|
||||
import { DashboardEditView, useDashboardEditPageNav } from './utils';
|
||||
import { DashboardEditView, DashboardEditViewState, useDashboardEditPageNav } from './utils';
|
||||
|
||||
export interface VariablesEditViewState extends SceneObjectState {}
|
||||
export interface VariablesEditViewState extends DashboardEditViewState {}
|
||||
|
||||
export class VariablesEditView extends SceneObjectBase<VariablesEditViewState> implements DashboardEditView {
|
||||
public getUrlKey(): string {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { useLocation } from 'react-router-dom';
|
||||
|
||||
import { locationUtil, NavModelItem } from '@grafana/data';
|
||||
import { SceneObject } from '@grafana/scenes';
|
||||
import { SceneObject, SceneObjectRef, SceneObjectState } from '@grafana/scenes';
|
||||
import { t } from 'app/core/internationalization';
|
||||
import { getNavModel } from 'app/core/selectors/navModel';
|
||||
import { useSelector } from 'app/types';
|
||||
@ -9,9 +9,19 @@ import { useSelector } from 'app/types';
|
||||
import { DashboardScene } from '../scene/DashboardScene';
|
||||
|
||||
import { AnnotationsEditView } from './AnnotationsEditView';
|
||||
import { DashboardLinksEditView } from './DashboardLinksEditView';
|
||||
import { GeneralSettingsEditView } from './GeneralSettings';
|
||||
import { VariablesEditView } from './VariablesEditView';
|
||||
|
||||
export interface DashboardEditViewState extends SceneObjectState {
|
||||
dashboardRef: SceneObjectRef<DashboardScene>;
|
||||
}
|
||||
|
||||
export interface DashboardEditListViewState extends DashboardEditViewState {
|
||||
/** Index of the list item to edit */
|
||||
editIndex?: number;
|
||||
}
|
||||
|
||||
export interface DashboardEditView extends SceneObject {
|
||||
getUrlKey(): string;
|
||||
}
|
||||
@ -24,6 +34,7 @@ export function useDashboardEditPageNav(dashboard: DashboardScene, currentEditVi
|
||||
|
||||
const pageNav: NavModelItem = {
|
||||
text: 'Settings',
|
||||
url: locationUtil.getUrlForPartial(location, { editview: 'settings', editIndex: null }),
|
||||
children: [
|
||||
{
|
||||
text: t('dashboard-settings.general.title', 'General'),
|
||||
@ -40,6 +51,11 @@ export function useDashboardEditPageNav(dashboard: DashboardScene, currentEditVi
|
||||
url: locationUtil.getUrlForPartial(location, { editview: 'variables', editIndex: null }),
|
||||
active: currentEditView === 'variables',
|
||||
},
|
||||
{
|
||||
text: t('dashboard-settings.links.title', 'Links'),
|
||||
url: locationUtil.getUrlForPartial(location, { editview: 'links', editIndex: null }),
|
||||
active: currentEditView === 'links',
|
||||
},
|
||||
],
|
||||
parentItem: dashboardPageNav,
|
||||
};
|
||||
@ -47,14 +63,19 @@ export function useDashboardEditPageNav(dashboard: DashboardScene, currentEditVi
|
||||
return { navModel, pageNav };
|
||||
}
|
||||
|
||||
export function createDashboardEditViewFor(editview: string): DashboardEditView {
|
||||
export function createDashboardEditViewFor(
|
||||
editview: string,
|
||||
dashboardRef: SceneObjectRef<DashboardScene>
|
||||
): DashboardEditView {
|
||||
switch (editview) {
|
||||
case 'annotations':
|
||||
return new AnnotationsEditView({});
|
||||
return new AnnotationsEditView({ dashboardRef });
|
||||
case 'variables':
|
||||
return new VariablesEditView({});
|
||||
return new VariablesEditView({ dashboardRef });
|
||||
case 'links':
|
||||
return new DashboardLinksEditView({ dashboardRef });
|
||||
case 'settings':
|
||||
default:
|
||||
return new GeneralSettingsEditView({});
|
||||
return new GeneralSettingsEditView({ dashboardRef });
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user