Dashboard: Enable JSON editor for Schema v2 (#102466)

Co-authored-by: Haris Rozajac <haris.rozajac12@gmail.com>
pull/102293/head
Ivan Ortega Alba 1 month ago committed by GitHub
parent 7ae86ee017
commit 3c3e5754b3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 53
      public/app/features/dashboard-scene/settings/JsonModelEditView.tsx
  2. 8
      public/app/features/dashboard/api/v2.test.ts
  3. 4
      public/app/features/dashboard/services/DashboardLoaderSrv.ts
  4. 2
      public/app/features/dashboard/services/DashboardSrv.ts

@ -4,11 +4,13 @@ import { useState } from 'react';
import { GrafanaTheme2, PageLayoutType } from '@grafana/data';
import { SceneComponentProps, SceneObjectBase, sceneUtils } from '@grafana/scenes';
import { Dashboard } from '@grafana/schema';
import { Spec as DashboardV2Spec } from '@grafana/schema/dist/esm/schema/dashboard/v2alpha1/types.spec.gen';
import { Alert, Box, Button, CodeEditor, Stack, useStyles2 } from '@grafana/ui';
import { Page } from 'app/core/components/Page/Page';
import { Trans, t } from 'app/core/internationalization';
import { getDashboardAPI } from 'app/features/dashboard/api/dashboard_api';
import { getPrettyJSON } from 'app/features/inspector/utils/utils';
import { DashboardDTO, SaveDashboardResponseDTO } from 'app/types';
import { DashboardDataDTO, SaveDashboardResponseDTO } from 'app/types';
import {
NameAlreadyExistsError,
@ -17,10 +19,10 @@ import {
isVersionMismatchError,
} from '../saving/shared';
import { useSaveDashboard } from '../saving/useSaveDashboard';
import { DashboardScene } from '../scene/DashboardScene';
import { DashboardScene, isV2Dashboard } from '../scene/DashboardScene';
import { NavToolbarActions } from '../scene/NavToolbarActions';
import { transformSaveModelSchemaV2ToScene } from '../serialization/transformSaveModelSchemaV2ToScene';
import { transformSaveModelToScene } from '../serialization/transformSaveModelToScene';
import { transformSceneToSaveModel } from '../serialization/transformSceneToSaveModel';
import { getDashboardSceneFor } from '../utils/utils';
import { DashboardEditView, DashboardEditViewState, useDashboardEditPageNav } from './utils';
@ -46,9 +48,8 @@ export class JsonModelEditView extends SceneObjectBase<JsonModelEditViewState> i
return getDashboardSceneFor(this);
}
public getSaveModel(): Dashboard {
const dashboard = this.getDashboard();
return transformSceneToSaveModel(dashboard);
public getSaveModel(): Dashboard | DashboardV2Spec {
return this.getDashboard().getSaveModel();
}
public getJsonText(): string {
@ -60,21 +61,34 @@ export class JsonModelEditView extends SceneObjectBase<JsonModelEditViewState> i
this.setState({ jsonText: value });
};
public onSaveSuccess = (result: SaveDashboardResponseDTO) => {
const jsonModel = JSON.parse(this.state.jsonText);
public onSaveSuccess = async (result: SaveDashboardResponseDTO) => {
const jsonModel: DashboardDataDTO | DashboardV2Spec = JSON.parse(this.state.jsonText);
const dashboard = this.getDashboard();
jsonModel.version = result.version;
const rsp: DashboardDTO = {
dashboard: jsonModel,
meta: dashboard.state.meta,
};
const newDashboardScene = transformSaveModelToScene(rsp);
const newState = sceneUtils.cloneSceneObjectState(newDashboardScene.state);
const isV2 = isV2Dashboard(jsonModel);
let newDashboardScene: DashboardScene;
if (isV2) {
// FIXME: We could avoid this call by storing the entire dashboard DTO as initial dashboard scene instead of only the spec and metadata
const dto = await getDashboardAPI('v2').getDashboardDTO(result.uid);
newDashboardScene = transformSaveModelSchemaV2ToScene(dto);
const newState = sceneUtils.cloneSceneObjectState(newDashboardScene.state);
dashboard.pauseTrackingChanges();
dashboard.setInitialSaveModel(dto.spec, dto.metadata);
dashboard.setState(newState);
} else {
jsonModel.version = result.version;
newDashboardScene = transformSaveModelToScene({
dashboard: jsonModel,
meta: dashboard.state.meta,
});
const newState = sceneUtils.cloneSceneObjectState(newDashboardScene.state);
dashboard.pauseTrackingChanges();
dashboard.setInitialSaveModel(rsp.dashboard);
dashboard.setState(newState);
dashboard.pauseTrackingChanges();
dashboard.setInitialSaveModel(jsonModel, dashboard.state.meta);
dashboard.setState(newState);
}
this.setState({ jsonText: this.getJsonText() });
};
@ -94,11 +108,12 @@ export class JsonModelEditView extends SceneObjectBase<JsonModelEditViewState> i
folderUid: dashboard.state.meta.folderUid,
overwrite,
rawDashboardJSON: JSON.parse(model.state.jsonText),
k8s: dashboard.state.meta.k8s,
});
setIsSaving(true);
if (result.status === 'success') {
model.onSaveSuccess(result);
await model.onSaveSuccess(result);
setIsSaving(false);
} else {
setIsSaving(true);

@ -8,6 +8,8 @@ import {
AnnoKeyFolderId,
AnnoKeyFolderTitle,
AnnoKeyFolderUrl,
AnnoKeyMessage,
AnnoKeySavedFromUI,
DeprecatedInternalId,
} from 'app/features/apiserver/types';
@ -58,6 +60,10 @@ jest.mock('@grafana/runtime', () => ({
}),
config: {
...jest.requireActual('@grafana/runtime').config,
buildInfo: {
...jest.requireActual('@grafana/runtime').config.buildInfo,
versionString: '10.0.0',
},
},
}));
@ -138,6 +144,7 @@ describe('v2 dashboard API', () => {
annotations: {
[AnnoKeyFolder]: 'new-folder',
[AnnoKeyMessage]: 'test save',
},
},
};
@ -205,6 +212,7 @@ describe('v2 dashboard API', () => {
name: 'existing-dash',
annotations: {
[AnnoKeyFolder]: 'folderUidXyz',
[AnnoKeySavedFromUI]: '10.0.0',
},
},
spec: {

@ -148,8 +148,8 @@ export class DashboardLoaderSrv extends DashboardLoaderSrvBase<DashboardDTO> {
return result;
})
.catch((e) => {
console.error('Failed to load dashboard', e);
if (isFetchError(e) && !(e instanceof DashboardVersionError)) {
console.error('Failed to load dashboard', e);
e.isHandled = true;
if (e.status === 404) {
appEvents.emit(AppEvents.alertError, ['Dashboard not found']);
@ -216,8 +216,8 @@ export class DashboardLoaderSrvV2 extends DashboardLoaderSrvBase<DashboardWithAc
return result;
})
.catch((e) => {
console.error('Failed to load dashboard', e);
if (isFetchError(e) && !(e instanceof DashboardVersionError)) {
console.error('Failed to load dashboard', e);
e.isHandled = true;
if (e.status === 404) {
appEvents.emit(AppEvents.alertError, ['Dashboard not found']);

@ -56,6 +56,8 @@ export class DashboardSrv {
return getDashboardAPI().saveDashboard({
dashboard: parsedJson,
folderUid: this.dashboard?.meta.folderUid || parsedJson.folderUid,
message: 'Edit Dashboard JSON',
k8s: this.dashboard?.meta.k8s,
});
}

Loading…
Cancel
Save