diff --git a/public/app/features/dashboard-scene/scene/DashboardScene.tsx b/public/app/features/dashboard-scene/scene/DashboardScene.tsx index 1594bf6d135..f47559a022a 100644 --- a/public/app/features/dashboard-scene/scene/DashboardScene.tsx +++ b/public/app/features/dashboard-scene/scene/DashboardScene.tsx @@ -57,6 +57,7 @@ import { getPanelIdForVizPanel, isPanelClone, } from '../utils/utils'; +import { SchemaV2EditorDrawer } from '../v2schema/SchemaV2EditorDrawer'; import { AddLibraryPanelDrawer } from './AddLibraryPanelDrawer'; import { DashboardControls } from './DashboardControls'; @@ -393,6 +394,14 @@ export class DashboardScene extends SceneObjectBase { }); } + public openV2SchemaEditor() { + this.setState({ + overlay: new SchemaV2EditorDrawer({ + dashboardRef: this.getRef(), + }), + }); + } + public getPageNav(location: H.Location, navIndex: NavIndex) { const { meta, viewPanelScene, editPanel } = this.state; diff --git a/public/app/features/dashboard-scene/scene/NavToolbarActions.tsx b/public/app/features/dashboard-scene/scene/NavToolbarActions.tsx index 7f952fbcf93..80cf335232e 100644 --- a/public/app/features/dashboard-scene/scene/NavToolbarActions.tsx +++ b/public/app/features/dashboard-scene/scene/NavToolbarActions.tsx @@ -577,6 +577,24 @@ export function ToolbarActions({ dashboard }: Props) { }, }); + // Will open a schema v2 editor drawer. Only available with dashboardSchemaV2 feature toggle on. + toolbarActions.push({ + group: 'main-buttons', + condition: uid && config.featureToggles.dashboardSchemaV2, + render: () => { + return ( + } + key="schema-v2-button" + onClick={() => { + dashboard.openV2SchemaEditor(); + }} + /> + ); + }, + }); + const actionElements: React.ReactNode[] = []; let lastGroup = ''; diff --git a/public/app/features/dashboard-scene/v2schema/SchemaV2EditorDrawer.tsx b/public/app/features/dashboard-scene/v2schema/SchemaV2EditorDrawer.tsx new file mode 100644 index 00000000000..57402e69db6 --- /dev/null +++ b/public/app/features/dashboard-scene/v2schema/SchemaV2EditorDrawer.tsx @@ -0,0 +1,97 @@ +/* eslint-disable */ +import { css } from '@emotion/css'; + +import { GrafanaTheme2 } from '@grafana/data'; +import { SceneComponentProps, SceneObjectBase, SceneObjectState, SceneObjectRef } from '@grafana/scenes'; +import { Box, Button, CodeEditor, Drawer, useStyles2 } from '@grafana/ui'; + +import { DashboardScene } from '../scene/DashboardScene'; +import { transformSceneToSaveModelSchemaV2 } from '../serialization/transformSceneToSaveModelSchemaV2'; + +interface SchemaV2EditorDrawerState extends SceneObjectState { + dashboardRef: SceneObjectRef; + jsonText: string; +} + +export class SchemaV2EditorDrawer extends SceneObjectBase { + constructor(state: Omit) { + super({ + ...state, + jsonText: '', + }); + + this.addActivationHandler(() => this.setState({ jsonText: this.getJsonText() })); + } + + private getJsonText(): string { + const dashboard = this.state.dashboardRef.resolve(); + return JSON.stringify(transformSceneToSaveModelSchemaV2(dashboard), null, 2); + } + + public onClose = () => { + this.state.dashboardRef.resolve().setState({ overlay: undefined }); + }; + + private onSave = () => { + // TODO: uncomment when transformation is available + // const manager = getDashboardScenePageStateManager(); + // const dashboard = transformSceneToSaveModelSchemaV2({ + // dashboard: JSON.parse(this.state.jsonText), + // meta: this.state.dashboardRef.resolve().state.meta, + // }); + // manager.setState({ + // dashboard, + // }); + }; + + static Component = ({ model }: SceneComponentProps) => { + const { jsonText } = model.useState(); + const styles = useStyles2(getStyles); + + const renderBody = () => { + return ( +
+ model.setState({ jsonText: value })} + /> + + { + + } + +
+ ); + }; + + return ( + + {renderBody()} + + ); + }; +} + +const getStyles = (theme: GrafanaTheme2) => ({ + wrapper: css({ + display: 'flex', + height: '100%', + flexDirection: 'column', + gap: theme.spacing(2), + }), + codeEditor: css({ + flexGrow: 1, + }), +}); +/* eslint-enable */