Dashboard schema: strip null values from save model (#41385)

This commit is contained in:
Ryan McKinley 2021-11-09 07:55:42 -08:00 committed by GitHub
parent 24ad769831
commit 0e419e9af1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 53 additions and 20 deletions

View File

@ -0,0 +1,28 @@
import { sortedDeepCloneWithoutNulls } from './object';
describe('objects', () => {
const value = {
hello: null,
world: {
deeper: 10,
foo: null,
arr: [null, 1, 'hello'],
},
bar: undefined,
simple: 'A',
};
it('returns a clean copy', () => {
const copy = sortedDeepCloneWithoutNulls(value);
expect(copy).toMatchObject({
world: {
deeper: 10,
arr: [null, 1, 'hello'],
},
simple: 'A',
});
expect(value.hello).toBeNull();
expect(value.world.foo).toBeNull();
expect(value.bar).toBeUndefined();
});
});

View File

@ -0,0 +1,20 @@
import { isArray, isPlainObject } from 'lodash';
/** @returns a deep clone of the object, but with any null value removed */
export function sortedDeepCloneWithoutNulls<T>(value: T): T {
if (isArray(value)) {
return (value.map(sortedDeepCloneWithoutNulls) as unknown) as T;
}
if (isPlainObject(value)) {
return Object.keys(value)
.sort()
.reduce((acc: any, key) => {
const v = (value as any)[key];
if (v != null) {
acc[key] = sortedDeepCloneWithoutNulls(v);
}
return acc;
}, {});
}
return value;
}

View File

@ -1,17 +0,0 @@
import { isArray, isPlainObject, keys } from 'lodash';
export default function sortByKeys(input: any): any {
if (isArray(input)) {
return input.map(sortByKeys);
}
if (isPlainObject(input)) {
const sortedObject: any = {};
for (const key of keys(input).sort()) {
sortedObject[key] = sortByKeys(input[key]);
}
return sortedObject;
}
return input;
}

View File

@ -56,11 +56,13 @@ describe('DashboardModel', () => {
describe('getSaveModelClone', () => {
it('should sort keys', () => {
const model = new DashboardModel({});
model.autoUpdate = null;
const saveModel = model.getSaveModelClone();
const keys = _keys(saveModel);
expect(keys[0]).toBe('annotations');
expect(keys[1]).toBe('autoUpdate');
expect(keys[1]).toBe('editable');
});
it('should remove add panel panels', () => {

View File

@ -18,7 +18,6 @@ import { DEFAULT_ANNOTATION_COLOR } from '@grafana/ui';
import { GRID_CELL_HEIGHT, GRID_CELL_VMARGIN, GRID_COLUMN_COUNT, REPEAT_DIR_VERTICAL } from 'app/core/constants';
// Utils & Services
import { contextSrv } from 'app/core/services/context_srv';
import sortByKeys from 'app/core/utils/sort_by_keys';
// Types
import { GridPos, PanelModel } from './PanelModel';
import { DashboardMigrator } from './DashboardMigrator';
@ -47,6 +46,7 @@ import { getTimeSrv } from '../services/TimeSrv';
import { mergePanels, PanelMergeInfo } from '../utils/panelMerge';
import { isOnTheSameGridRow } from './utils';
import { RefreshEvent, TimeRangeUpdatedEvent } from '@grafana/runtime';
import { sortedDeepCloneWithoutNulls } from 'app/core/utils/object';
import { Subscription } from 'rxjs';
import { appEvents } from '../../../core/core';
import {
@ -264,7 +264,7 @@ export class DashboardModel {
copy.panels = this.getPanelSaveModels();
// sort by keys
copy = sortByKeys(copy);
copy = sortedDeepCloneWithoutNulls(copy);
copy.getVariables = () => {
return copy.templating.list;
};