diff --git a/public/app/features/dashboard-scene/settings/JsonModelEditView.tsx b/public/app/features/dashboard-scene/settings/JsonModelEditView.tsx new file mode 100644 index 00000000000..c85348d7870 --- /dev/null +++ b/public/app/features/dashboard-scene/settings/JsonModelEditView.tsx @@ -0,0 +1,81 @@ +import { css } from '@emotion/css'; +import React from 'react'; + +import { GrafanaTheme2, PageLayoutType } from '@grafana/data'; +import { SceneComponentProps, SceneObjectBase } from '@grafana/scenes'; +import { Button, CodeEditor, useStyles2 } from '@grafana/ui'; +import { Page } from 'app/core/components/Page/Page'; +import { Trans } from 'app/core/internationalization'; +import { getPrettyJSON } from 'app/features/inspector/utils/utils'; + +import { DashboardScene } from '../scene/DashboardScene'; +import { transformSceneToSaveModel } from '../serialization/transformSceneToSaveModel'; +import { getDashboardSceneFor } from '../utils/utils'; + +import { DashboardEditView, DashboardEditViewState, useDashboardEditPageNav } from './utils'; + +export interface JsonModelEditViewState extends DashboardEditViewState {} + +export class JsonModelEditView extends SceneObjectBase implements DashboardEditView { + public getUrlKey(): string { + return 'json-model'; + } + + public getDashboard(): DashboardScene { + return getDashboardSceneFor(this); + } + + public getJsonText(): string { + const dashboard = this.getDashboard(); + const jsonData = transformSceneToSaveModel(dashboard); + return getPrettyJSON(jsonData); + } + + static Component = ({ model }: SceneComponentProps) => { + const jsonText = model.getJsonText(); + const dashboard = model.getDashboard(); + const { navModel, pageNav } = useDashboardEditPageNav(dashboard, model.getUrlKey()); + const canSave = dashboard.useState().meta.canSave; + + const styles = useStyles2(getStyles); + + return ( + +
+ + The JSON model below is the data structure that defines the dashboard. This includes dashboard settings, + panel settings, layout, queries, and so on. + + + {canSave && ( +
+ {/**TODO: add saving functionality */} + +
+ )} +
+
+ ); + }; +} + +const getStyles = (theme: GrafanaTheme2) => ({ + wrapper: css({ + display: 'flex', + height: '100%', + flexDirection: 'column', + gap: theme.spacing(2), + }), + codeEditor: css({ + flexGrow: 1, + }), +}); diff --git a/public/app/features/dashboard-scene/settings/utils.ts b/public/app/features/dashboard-scene/settings/utils.ts index 7a2db429433..1a77bbfd46e 100644 --- a/public/app/features/dashboard-scene/settings/utils.ts +++ b/public/app/features/dashboard-scene/settings/utils.ts @@ -11,6 +11,7 @@ import { DashboardScene } from '../scene/DashboardScene'; import { AnnotationsEditView } from './AnnotationsEditView'; import { DashboardLinksEditView } from './DashboardLinksEditView'; import { GeneralSettingsEditView } from './GeneralSettingsEditView'; +import { JsonModelEditView } from './JsonModelEditView'; import { VariablesEditView } from './VariablesEditView'; import { VersionsEditView } from './VersionsEditView'; @@ -60,6 +61,11 @@ export function useDashboardEditPageNav(dashboard: DashboardScene, currentEditVi url: locationUtil.getUrlForPartial(location, { editview: 'versions', editIndex: null }), active: currentEditView === 'versions', }, + { + text: t('dashboard-settings.json-editor.title', 'JSON Model'), + url: locationUtil.getUrlForPartial(location, { editview: 'json-model', editIndex: null }), + active: currentEditView === 'json-model', + }, ], parentItem: dashboardPageNav, }; @@ -77,6 +83,8 @@ export function createDashboardEditViewFor(editview: string): DashboardEditView return new DashboardLinksEditView({}); case 'versions': return new VersionsEditView({}); + case 'json-model': + return new JsonModelEditView({}); case 'settings': default: return new GeneralSettingsEditView({});