2024-12-13 17:20:22 +08:00
|
|
|
import { config } from '@grafana/runtime';
|
|
|
|
import { Dashboard } from '@grafana/schema';
|
2025-01-16 20:18:47 +08:00
|
|
|
import { DashboardV2Spec } from '@grafana/schema/dist/esm/schema/dashboard/v2alpha0';
|
2025-01-09 23:14:41 +08:00
|
|
|
import { AnnoKeyDashboardSnapshotOriginalUrl } from 'app/features/apiserver/types';
|
|
|
|
import { DashboardWithAccessInfo } from 'app/features/dashboard/api/types';
|
2024-12-13 17:20:22 +08:00
|
|
|
import { SaveDashboardAsOptions } from 'app/features/dashboard/components/SaveDashboard/types';
|
2025-01-03 00:33:16 +08:00
|
|
|
import {
|
|
|
|
getPanelPluginCounts,
|
|
|
|
getV1SchemaVariables,
|
|
|
|
getV2SchemaVariables,
|
|
|
|
} from 'app/features/dashboard/utils/tracking';
|
2025-01-09 23:14:41 +08:00
|
|
|
import { DashboardMeta, SaveDashboardResponseDTO } from 'app/types';
|
2024-12-13 17:20:22 +08:00
|
|
|
|
2024-12-19 19:00:59 +08:00
|
|
|
import { getRawDashboardChanges, getRawDashboardV2Changes } from '../saving/getDashboardChanges';
|
2024-12-13 17:20:22 +08:00
|
|
|
import { DashboardChangeInfo } from '../saving/shared';
|
|
|
|
import { DashboardScene } from '../scene/DashboardScene';
|
|
|
|
|
|
|
|
import { transformSceneToSaveModel } from './transformSceneToSaveModel';
|
|
|
|
import { transformSceneToSaveModelSchemaV2 } from './transformSceneToSaveModelSchemaV2';
|
|
|
|
|
2025-01-09 23:14:41 +08:00
|
|
|
export interface DashboardSceneSerializerLike<T, M> {
|
2024-12-13 17:20:22 +08:00
|
|
|
/**
|
|
|
|
* The save model which the dashboard scene was originally created from
|
|
|
|
*/
|
|
|
|
initialSaveModel?: T;
|
2025-01-09 23:14:41 +08:00
|
|
|
metadata?: M;
|
2024-12-13 17:20:22 +08:00
|
|
|
getSaveModel: (s: DashboardScene) => T;
|
|
|
|
getSaveAsModel: (s: DashboardScene, options: SaveDashboardAsOptions) => T;
|
|
|
|
getDashboardChangesFromScene: (
|
|
|
|
scene: DashboardScene,
|
|
|
|
options: {
|
|
|
|
saveTimeRange?: boolean;
|
|
|
|
saveVariables?: boolean;
|
|
|
|
saveRefresh?: boolean;
|
|
|
|
}
|
|
|
|
) => DashboardChangeInfo;
|
|
|
|
onSaveComplete(saveModel: T, result: SaveDashboardResponseDTO): void;
|
2025-01-03 00:33:16 +08:00
|
|
|
getTrackingInformation: (s: DashboardScene) => DashboardTrackingInfo | undefined;
|
2024-12-19 23:09:19 +08:00
|
|
|
getSnapshotUrl: () => string | undefined;
|
2024-12-13 17:20:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
interface DashboardTrackingInfo {
|
|
|
|
uid?: string;
|
|
|
|
title?: string;
|
|
|
|
schemaVersion: number;
|
|
|
|
panels_count: number;
|
|
|
|
settings_nowdelay?: number;
|
|
|
|
settings_livenow?: boolean;
|
|
|
|
}
|
|
|
|
|
2025-01-09 23:14:41 +08:00
|
|
|
export class V1DashboardSerializer implements DashboardSceneSerializerLike<Dashboard, DashboardMeta> {
|
2024-12-13 17:20:22 +08:00
|
|
|
initialSaveModel?: Dashboard;
|
2025-01-09 23:14:41 +08:00
|
|
|
metadata?: DashboardMeta;
|
2024-12-13 17:20:22 +08:00
|
|
|
|
|
|
|
getSaveModel(s: DashboardScene) {
|
|
|
|
return transformSceneToSaveModel(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
getSaveAsModel(s: DashboardScene, options: SaveDashboardAsOptions) {
|
|
|
|
const saveModel = this.getSaveModel(s);
|
|
|
|
|
|
|
|
return {
|
|
|
|
...saveModel,
|
|
|
|
id: null,
|
|
|
|
uid: '',
|
|
|
|
title: options.title || '',
|
|
|
|
description: options.description || '',
|
|
|
|
tags: options.isNew || options.copyTags ? saveModel.tags : [],
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
getDashboardChangesFromScene(
|
|
|
|
scene: DashboardScene,
|
|
|
|
options: { saveTimeRange?: boolean; saveVariables?: boolean; saveRefresh?: boolean }
|
|
|
|
) {
|
|
|
|
const changedSaveModel = this.getSaveModel(scene);
|
|
|
|
const changeInfo = getRawDashboardChanges(
|
|
|
|
this.initialSaveModel!,
|
|
|
|
changedSaveModel,
|
|
|
|
options.saveTimeRange,
|
|
|
|
options.saveVariables,
|
|
|
|
options.saveRefresh
|
|
|
|
);
|
|
|
|
|
|
|
|
const hasFolderChanges = scene.getInitialState()?.meta.folderUid !== scene.state.meta.folderUid;
|
|
|
|
|
|
|
|
return {
|
|
|
|
...changeInfo,
|
|
|
|
hasFolderChanges,
|
|
|
|
hasChanges: changeInfo.hasChanges || hasFolderChanges,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
onSaveComplete(saveModel: Dashboard, result: SaveDashboardResponseDTO): void {
|
|
|
|
this.initialSaveModel = {
|
|
|
|
...saveModel,
|
|
|
|
id: result.id,
|
|
|
|
uid: result.uid,
|
|
|
|
version: result.version,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
getTrackingInformation(): DashboardTrackingInfo | undefined {
|
2025-01-03 00:33:16 +08:00
|
|
|
const panelTypes = this.initialSaveModel?.panels?.map((p) => p.type) || [];
|
|
|
|
const panels = getPanelPluginCounts(panelTypes);
|
2024-12-13 17:20:22 +08:00
|
|
|
const variables = getV1SchemaVariables(this.initialSaveModel?.templating?.list || []);
|
|
|
|
|
|
|
|
if (this.initialSaveModel) {
|
|
|
|
return {
|
|
|
|
uid: this.initialSaveModel.uid,
|
|
|
|
title: this.initialSaveModel.title,
|
|
|
|
schemaVersion: this.initialSaveModel.schemaVersion,
|
|
|
|
panels_count: this.initialSaveModel.panels?.length || 0,
|
|
|
|
settings_nowdelay: undefined,
|
|
|
|
settings_livenow: !!this.initialSaveModel.liveNow,
|
|
|
|
...panels,
|
|
|
|
...variables,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
return undefined;
|
|
|
|
}
|
2024-12-19 23:09:19 +08:00
|
|
|
|
|
|
|
getSnapshotUrl() {
|
|
|
|
return this.initialSaveModel?.snapshot?.originalUrl;
|
|
|
|
}
|
2024-12-13 17:20:22 +08:00
|
|
|
}
|
|
|
|
|
2025-01-09 23:14:41 +08:00
|
|
|
export class V2DashboardSerializer
|
|
|
|
implements DashboardSceneSerializerLike<DashboardV2Spec, DashboardWithAccessInfo<DashboardV2Spec>['metadata']>
|
|
|
|
{
|
2024-12-13 17:20:22 +08:00
|
|
|
initialSaveModel?: DashboardV2Spec;
|
2025-01-09 23:14:41 +08:00
|
|
|
metadata?: DashboardWithAccessInfo<DashboardV2Spec>['metadata'];
|
2024-12-13 17:20:22 +08:00
|
|
|
|
|
|
|
getSaveModel(s: DashboardScene) {
|
|
|
|
return transformSceneToSaveModelSchemaV2(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
getSaveAsModel(s: DashboardScene, options: SaveDashboardAsOptions) {
|
|
|
|
throw new Error('Method not implemented.');
|
|
|
|
// eslint-disable-next-line
|
|
|
|
return {} as DashboardV2Spec;
|
|
|
|
}
|
|
|
|
|
2024-12-19 19:00:59 +08:00
|
|
|
getDashboardChangesFromScene(
|
|
|
|
scene: DashboardScene,
|
|
|
|
options: { saveTimeRange?: boolean; saveVariables?: boolean; saveRefresh?: boolean }
|
|
|
|
) {
|
|
|
|
const changedSaveModel = this.getSaveModel(scene);
|
|
|
|
const changeInfo = getRawDashboardV2Changes(
|
|
|
|
this.initialSaveModel!,
|
|
|
|
changedSaveModel,
|
|
|
|
options.saveTimeRange,
|
|
|
|
options.saveVariables,
|
|
|
|
options.saveRefresh
|
|
|
|
);
|
|
|
|
|
|
|
|
const hasFolderChanges = scene.getInitialState()?.meta.folderUid !== scene.state.meta.folderUid;
|
2025-01-13 20:07:45 +08:00
|
|
|
const isNew = scene.getInitialState()?.meta.isNew;
|
2024-12-19 19:00:59 +08:00
|
|
|
|
|
|
|
return {
|
|
|
|
...changeInfo,
|
|
|
|
hasFolderChanges,
|
|
|
|
hasChanges: changeInfo.hasChanges || hasFolderChanges,
|
|
|
|
isNew,
|
|
|
|
};
|
2024-12-13 17:20:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
onSaveComplete(saveModel: DashboardV2Spec, result: SaveDashboardResponseDTO): void {
|
|
|
|
throw new Error('v2 schema: Method not implemented.');
|
|
|
|
}
|
|
|
|
|
2025-01-03 00:33:16 +08:00
|
|
|
getTrackingInformation(s: DashboardScene): DashboardTrackingInfo | undefined {
|
|
|
|
const panelPluginIds =
|
|
|
|
Object.values(this.initialSaveModel?.elements ?? [])
|
|
|
|
.filter((e) => e.kind === 'Panel')
|
|
|
|
.map((p) => p.spec.vizConfig.kind) || [];
|
|
|
|
const panels = getPanelPluginCounts(panelPluginIds);
|
|
|
|
const variables = getV2SchemaVariables(this.initialSaveModel?.variables || []);
|
|
|
|
|
|
|
|
if (this.initialSaveModel) {
|
|
|
|
return {
|
|
|
|
schemaVersion: this.initialSaveModel.schemaVersion,
|
|
|
|
uid: s.state.uid,
|
|
|
|
title: this.initialSaveModel.title,
|
|
|
|
panels_count: panelPluginIds.length || 0,
|
|
|
|
settings_nowdelay: undefined,
|
|
|
|
settings_livenow: !!this.initialSaveModel.liveNow,
|
|
|
|
...panels,
|
|
|
|
...variables,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2024-12-13 17:20:22 +08:00
|
|
|
return undefined;
|
|
|
|
}
|
2024-12-19 23:09:19 +08:00
|
|
|
|
|
|
|
getSnapshotUrl() {
|
2025-01-09 23:14:41 +08:00
|
|
|
return this.metadata?.annotations?.[AnnoKeyDashboardSnapshotOriginalUrl];
|
2024-12-19 23:09:19 +08:00
|
|
|
}
|
2024-12-13 17:20:22 +08:00
|
|
|
}
|
|
|
|
|
2025-01-09 23:14:41 +08:00
|
|
|
export function getDashboardSceneSerializer(): DashboardSceneSerializerLike<
|
|
|
|
Dashboard | DashboardV2Spec,
|
|
|
|
DashboardMeta | DashboardWithAccessInfo<DashboardV2Spec>['metadata']
|
|
|
|
> {
|
2024-12-19 19:00:59 +08:00
|
|
|
if (config.featureToggles.useV2DashboardsAPI) {
|
2024-12-13 17:20:22 +08:00
|
|
|
return new V2DashboardSerializer();
|
|
|
|
}
|
|
|
|
|
|
|
|
return new V1DashboardSerializer();
|
|
|
|
}
|