From f93b05f5068454b67dcb1c97d3e296b853bf6231 Mon Sep 17 00:00:00 2001 From: Ryan McKinley Date: Mon, 19 Apr 2021 10:24:39 -0700 Subject: [PATCH] PanelEdit: only update when config changes (#33133) --- packages/grafana-data/src/types/data.ts | 1 + .../PanelEditor/OptionsPaneOptions.tsx | 4 +- .../components/PanelEditor/state/actions.ts | 2 +- .../__snapshots__/DashboardPage.test.tsx.snap | 14 +++---- .../__snapshots__/DashboardGrid.test.tsx.snap | 40 +++++++++---------- .../features/dashboard/state/PanelModel.ts | 24 ++++++----- .../PanelLibraryOptionsGroup.tsx | 2 +- 7 files changed, 47 insertions(+), 40 deletions(-) diff --git a/packages/grafana-data/src/types/data.ts b/packages/grafana-data/src/types/data.ts index 92d3ff43172..f51f3ed176d 100644 --- a/packages/grafana-data/src/types/data.ts +++ b/packages/grafana-data/src/types/data.ts @@ -167,6 +167,7 @@ export enum NullValueMode { * Describes and API for exposing panel specific data configurations. */ export interface DataConfigSource { + configRev?: number; getTransformations: () => DataTransformerConfig[] | undefined; getFieldOverrideOptions: () => ApplyFieldOverrideOptions | undefined; } diff --git a/public/app/features/dashboard/components/PanelEditor/OptionsPaneOptions.tsx b/public/app/features/dashboard/components/PanelEditor/OptionsPaneOptions.tsx index ac06a22e13b..a6f25baaaa7 100644 --- a/public/app/features/dashboard/components/PanelEditor/OptionsPaneOptions.tsx +++ b/public/app/features/dashboard/components/PanelEditor/OptionsPaneOptions.tsx @@ -30,7 +30,9 @@ export const OptionsPaneOptions: React.FC = (props) => { const [panelFrameOptions, vizOptions, justOverrides] = useMemo( () => [getPanelFrameCategory(props), getVizualizationOptions(props), getFieldOverrideCategories(props)], - [props] + + // eslint-disable-next-line react-hooks/exhaustive-deps + [panel.configRev] ); const mainBoxElements: React.ReactNode[] = []; diff --git a/public/app/features/dashboard/components/PanelEditor/state/actions.ts b/public/app/features/dashboard/components/PanelEditor/state/actions.ts index 484ae3a91a5..055b26bc11d 100644 --- a/public/app/features/dashboard/components/PanelEditor/state/actions.ts +++ b/public/app/features/dashboard/components/PanelEditor/state/actions.ts @@ -45,7 +45,7 @@ export function updateSourcePanel(sourcePanel: PanelModel): ThunkResult { export function discardPanelChanges(): ThunkResult { return async (dispatch, getStore) => { const { getPanel } = getStore().panelEditor; - getPanel().hasChanged = false; + getPanel().configRev = 0; dispatch(setDiscardChanges(true)); }; } diff --git a/public/app/features/dashboard/containers/__snapshots__/DashboardPage.test.tsx.snap b/public/app/features/dashboard/containers/__snapshots__/DashboardPage.test.tsx.snap index fa86bdab46f..391c8b99e4b 100644 --- a/public/app/features/dashboard/containers/__snapshots__/DashboardPage.test.tsx.snap +++ b/public/app/features/dashboard/containers/__snapshots__/DashboardPage.test.tsx.snap @@ -56,6 +56,7 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1` "panels": Array [ PanelModel { "cachedPluginOptions": Object {}, + "configRev": 0, "datasource": null, "events": EventBusSrv { "emitter": EventEmitter { @@ -69,7 +70,6 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1` "x": 0, "y": 0, }, - "hasChanged": false, "id": 1, "isEditing": false, "isInView": false, @@ -188,6 +188,7 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1` "panels": Array [ PanelModel { "cachedPluginOptions": Object {}, + "configRev": 0, "datasource": null, "events": EventBusSrv { "emitter": EventEmitter { @@ -201,7 +202,6 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1` "x": 0, "y": 0, }, - "hasChanged": false, "id": 1, "isEditing": false, "isInView": false, @@ -290,6 +290,7 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1` "panels": Array [ PanelModel { "cachedPluginOptions": Object {}, + "configRev": 0, "datasource": null, "events": EventBusSrv { "emitter": EventEmitter { @@ -303,7 +304,6 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1` "x": 0, "y": 0, }, - "hasChanged": false, "id": 1, "isEditing": false, "isInView": false, @@ -414,6 +414,7 @@ exports[`DashboardPage When dashboard has editview url state should render setti "panels": Array [ PanelModel { "cachedPluginOptions": Object {}, + "configRev": 0, "datasource": null, "events": EventBusSrv { "emitter": EventEmitter { @@ -427,7 +428,6 @@ exports[`DashboardPage When dashboard has editview url state should render setti "x": 0, "y": 0, }, - "hasChanged": false, "id": 1, "isEditing": false, "isInView": false, @@ -546,6 +546,7 @@ exports[`DashboardPage When dashboard has editview url state should render setti "panels": Array [ PanelModel { "cachedPluginOptions": Object {}, + "configRev": 0, "datasource": null, "events": EventBusSrv { "emitter": EventEmitter { @@ -559,7 +560,6 @@ exports[`DashboardPage When dashboard has editview url state should render setti "x": 0, "y": 0, }, - "hasChanged": false, "id": 1, "isEditing": false, "isInView": false, @@ -648,6 +648,7 @@ exports[`DashboardPage When dashboard has editview url state should render setti "panels": Array [ PanelModel { "cachedPluginOptions": Object {}, + "configRev": 0, "datasource": null, "events": EventBusSrv { "emitter": EventEmitter { @@ -661,7 +662,6 @@ exports[`DashboardPage When dashboard has editview url state should render setti "x": 0, "y": 0, }, - "hasChanged": false, "id": 1, "isEditing": false, "isInView": false, @@ -754,6 +754,7 @@ exports[`DashboardPage When dashboard has editview url state should render setti "panels": Array [ PanelModel { "cachedPluginOptions": Object {}, + "configRev": 0, "datasource": null, "events": EventBusSrv { "emitter": EventEmitter { @@ -767,7 +768,6 @@ exports[`DashboardPage When dashboard has editview url state should render setti "x": 0, "y": 0, }, - "hasChanged": false, "id": 1, "isEditing": false, "isInView": false, diff --git a/public/app/features/dashboard/dashgrid/__snapshots__/DashboardGrid.test.tsx.snap b/public/app/features/dashboard/dashgrid/__snapshots__/DashboardGrid.test.tsx.snap index e7976d5171c..9a07bf1e0ec 100644 --- a/public/app/features/dashboard/dashgrid/__snapshots__/DashboardGrid.test.tsx.snap +++ b/public/app/features/dashboard/dashgrid/__snapshots__/DashboardGrid.test.tsx.snap @@ -103,6 +103,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "panels": Array [ PanelModel { "cachedPluginOptions": Object {}, + "configRev": 0, "datasource": null, "events": EventBusSrv { "emitter": EventEmitter { @@ -116,7 +117,6 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 0, }, - "hasChanged": false, "id": 1, "isEditing": false, "isInView": false, @@ -134,6 +134,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` }, PanelModel { "cachedPluginOptions": Object {}, + "configRev": 0, "datasource": null, "events": EventBusSrv { "emitter": EventEmitter { @@ -147,7 +148,6 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 10, }, - "hasChanged": false, "id": 2, "isEditing": false, "isInView": false, @@ -165,6 +165,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` }, PanelModel { "cachedPluginOptions": Object {}, + "configRev": 0, "datasource": null, "events": EventBusSrv { "emitter": EventEmitter { @@ -178,7 +179,6 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 20, }, - "hasChanged": false, "id": 3, "isEditing": false, "isInView": false, @@ -196,6 +196,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` }, PanelModel { "cachedPluginOptions": Object {}, + "configRev": 0, "datasource": null, "events": EventBusSrv { "emitter": EventEmitter { @@ -209,7 +210,6 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 120, }, - "hasChanged": false, "id": 4, "isEditing": false, "isInView": false, @@ -252,6 +252,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` panel={ PanelModel { "cachedPluginOptions": Object {}, + "configRev": 0, "datasource": null, "events": EventBusSrv { "emitter": EventEmitter { @@ -265,7 +266,6 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 0, }, - "hasChanged": false, "id": 1, "isEditing": false, "isInView": false, @@ -344,6 +344,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "panels": Array [ PanelModel { "cachedPluginOptions": Object {}, + "configRev": 0, "datasource": null, "events": EventBusSrv { "emitter": EventEmitter { @@ -357,7 +358,6 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 0, }, - "hasChanged": false, "id": 1, "isEditing": false, "isInView": false, @@ -375,6 +375,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` }, PanelModel { "cachedPluginOptions": Object {}, + "configRev": 0, "datasource": null, "events": EventBusSrv { "emitter": EventEmitter { @@ -388,7 +389,6 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 10, }, - "hasChanged": false, "id": 2, "isEditing": false, "isInView": false, @@ -406,6 +406,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` }, PanelModel { "cachedPluginOptions": Object {}, + "configRev": 0, "datasource": null, "events": EventBusSrv { "emitter": EventEmitter { @@ -419,7 +420,6 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 20, }, - "hasChanged": false, "id": 3, "isEditing": false, "isInView": false, @@ -437,6 +437,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` }, PanelModel { "cachedPluginOptions": Object {}, + "configRev": 0, "datasource": null, "events": EventBusSrv { "emitter": EventEmitter { @@ -450,7 +451,6 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 120, }, - "hasChanged": false, "id": 4, "isEditing": false, "isInView": false, @@ -493,6 +493,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` panel={ PanelModel { "cachedPluginOptions": Object {}, + "configRev": 0, "datasource": null, "events": EventBusSrv { "emitter": EventEmitter { @@ -506,7 +507,6 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 10, }, - "hasChanged": false, "id": 2, "isEditing": false, "isInView": false, @@ -585,6 +585,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "panels": Array [ PanelModel { "cachedPluginOptions": Object {}, + "configRev": 0, "datasource": null, "events": EventBusSrv { "emitter": EventEmitter { @@ -598,7 +599,6 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 0, }, - "hasChanged": false, "id": 1, "isEditing": false, "isInView": false, @@ -616,6 +616,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` }, PanelModel { "cachedPluginOptions": Object {}, + "configRev": 0, "datasource": null, "events": EventBusSrv { "emitter": EventEmitter { @@ -629,7 +630,6 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 10, }, - "hasChanged": false, "id": 2, "isEditing": false, "isInView": false, @@ -647,6 +647,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` }, PanelModel { "cachedPluginOptions": Object {}, + "configRev": 0, "datasource": null, "events": EventBusSrv { "emitter": EventEmitter { @@ -660,7 +661,6 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 20, }, - "hasChanged": false, "id": 3, "isEditing": false, "isInView": false, @@ -678,6 +678,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` }, PanelModel { "cachedPluginOptions": Object {}, + "configRev": 0, "datasource": null, "events": EventBusSrv { "emitter": EventEmitter { @@ -691,7 +692,6 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 120, }, - "hasChanged": false, "id": 4, "isEditing": false, "isInView": false, @@ -734,6 +734,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` panel={ PanelModel { "cachedPluginOptions": Object {}, + "configRev": 0, "datasource": null, "events": EventBusSrv { "emitter": EventEmitter { @@ -747,7 +748,6 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 20, }, - "hasChanged": false, "id": 3, "isEditing": false, "isInView": false, @@ -826,6 +826,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "panels": Array [ PanelModel { "cachedPluginOptions": Object {}, + "configRev": 0, "datasource": null, "events": EventBusSrv { "emitter": EventEmitter { @@ -839,7 +840,6 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 0, }, - "hasChanged": false, "id": 1, "isEditing": false, "isInView": false, @@ -857,6 +857,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` }, PanelModel { "cachedPluginOptions": Object {}, + "configRev": 0, "datasource": null, "events": EventBusSrv { "emitter": EventEmitter { @@ -870,7 +871,6 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 10, }, - "hasChanged": false, "id": 2, "isEditing": false, "isInView": false, @@ -888,6 +888,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` }, PanelModel { "cachedPluginOptions": Object {}, + "configRev": 0, "datasource": null, "events": EventBusSrv { "emitter": EventEmitter { @@ -901,7 +902,6 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 20, }, - "hasChanged": false, "id": 3, "isEditing": false, "isInView": false, @@ -919,6 +919,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` }, PanelModel { "cachedPluginOptions": Object {}, + "configRev": 0, "datasource": null, "events": EventBusSrv { "emitter": EventEmitter { @@ -932,7 +933,6 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 120, }, - "hasChanged": false, "id": 4, "isEditing": false, "isInView": false, @@ -975,6 +975,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` panel={ PanelModel { "cachedPluginOptions": Object {}, + "configRev": 0, "datasource": null, "events": EventBusSrv { "emitter": EventEmitter { @@ -988,7 +989,6 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 120, }, - "hasChanged": false, "id": 4, "isEditing": false, "isInView": false, diff --git a/public/app/features/dashboard/state/PanelModel.ts b/public/app/features/dashboard/state/PanelModel.ts index c266027e527..52008c4bde6 100644 --- a/public/app/features/dashboard/state/PanelModel.ts +++ b/public/app/features/dashboard/state/PanelModel.ts @@ -59,7 +59,7 @@ const notPersistedProperties: { [str: string]: boolean } = { queryRunner: true, replaceVariables: true, editSourceId: true, - hasChanged: true, + configRev: true, getDisplayTitle: true, }; @@ -162,7 +162,7 @@ export class PanelModel implements DataConfigSource { isViewing = false; isEditing = false; isInView = false; - hasChanged = false; + configRev = 0; // increments when configs change hasRefreshed?: boolean; events: EventBus; @@ -232,16 +232,20 @@ export class PanelModel implements DataConfigSource { return this.fieldConfig; } + get hasChanged(): boolean { + return this.configRev > 0; + } + updateOptions(options: object) { this.options = options; - this.hasChanged = true; + this.configRev++; this.events.publish(new PanelOptionsChangedEvent()); this.render(); } updateFieldConfig(config: FieldConfigSource) { this.fieldConfig = config; - this.hasChanged = true; + this.configRev++; this.events.publish(new PanelOptionsChangedEvent()); this.resendLastResult(); @@ -398,7 +402,7 @@ export class PanelModel implements DataConfigSource { // switch this.type = pluginId; this.plugin = newPlugin; - this.hasChanged = true; + this.configRev++; // For some reason I need to rebind replace variables here, otherwise the viz repeater does not work this.replaceVariables = this.replaceVariables.bind(this); @@ -417,7 +421,7 @@ export class PanelModel implements DataConfigSource { this.interval = options.minInterval; this.maxDataPoints = options.maxDataPoints; this.targets = options.queries; - this.hasChanged = true; + this.configRev++; this.events.publish(new PanelQueriesChangedEvent()); } @@ -426,13 +430,13 @@ export class PanelModel implements DataConfigSource { query = query || { refId: 'A' }; query.refId = getNextRefIdChar(this.targets); this.targets.push(query as DataQuery); - this.hasChanged = true; + this.configRev++; } changeQuery(query: DataQuery, index: number) { // ensure refId is maintained query.refId = this.targets[index].refId; - this.hasChanged = true; + this.configRev++; // update query in array this.targets = this.targets.map((item, itemIndex) => { @@ -503,13 +507,13 @@ export class PanelModel implements DataConfigSource { setTransformations(transformations: DataTransformerConfig[]) { this.transformations = transformations; this.resendLastResult(); - this.hasChanged = true; + this.configRev++; this.events.publish(new PanelTransformationsChangedEvent()); } setProperty(key: keyof this, value: any) { this[key] = value; - this.hasChanged = true; + this.configRev++; // Custom handling of repeat dependent options, handled here as PanelEditor can // update one key at a time right now diff --git a/public/app/features/library-panels/components/PanelLibraryOptionsGroup/PanelLibraryOptionsGroup.tsx b/public/app/features/library-panels/components/PanelLibraryOptionsGroup/PanelLibraryOptionsGroup.tsx index b2d918bd97d..205f67b97f4 100644 --- a/public/app/features/library-panels/components/PanelLibraryOptionsGroup/PanelLibraryOptionsGroup.tsx +++ b/public/app/features/library-panels/components/PanelLibraryOptionsGroup/PanelLibraryOptionsGroup.tsx @@ -45,7 +45,7 @@ export const PanelLibraryOptionsGroup: FC = ({ panel, searchQuery }) => { libraryPanel: toPanelModelLibraryPanel(changeToPanel), }); - panel.hasChanged = false; + panel.configRev = 0; panel.refresh(); panel.events.publish(new PanelQueriesChangedEvent()); panel.events.publish(new PanelOptionsChangedEvent());