mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Dashboards: Only refresh panels on panel edit exit if refresh is set (#67652)
Closes #66838 Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
This commit is contained in:
parent
e51b92991d
commit
7801cf6585
@ -2372,8 +2372,7 @@ exports[`better eslint`] = {
|
|||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "2"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "2"],
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "3"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "3"],
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "4"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "4"]
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "5"]
|
|
||||||
],
|
],
|
||||||
"public/app/features/dashboard/state/DashboardMigrator.test.ts:5381": [
|
"public/app/features/dashboard/state/DashboardMigrator.test.ts:5381": [
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||||
|
@ -287,19 +287,16 @@ describe('timeSrv', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('pauseAutoRefresh', () => {
|
|
||||||
it('should set autoRefreshPaused to true', () => {
|
|
||||||
_dashboard.refresh = '10s';
|
|
||||||
timeSrv.pauseAutoRefresh();
|
|
||||||
expect(timeSrv.autoRefreshPaused).toBe(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('resumeAutoRefresh', () => {
|
describe('resumeAutoRefresh', () => {
|
||||||
it('should set refresh to empty value', () => {
|
it('should set auto-refresh interval', () => {
|
||||||
timeSrv.autoRefreshPaused = true;
|
timeSrv.setAutoRefresh('10s');
|
||||||
|
expect(timeSrv.refreshTimer).not.toBeUndefined();
|
||||||
|
|
||||||
|
timeSrv.stopAutoRefresh();
|
||||||
|
expect(timeSrv.refreshTimer).toBeUndefined();
|
||||||
|
|
||||||
timeSrv.resumeAutoRefresh();
|
timeSrv.resumeAutoRefresh();
|
||||||
expect(timeSrv.autoRefreshPaused).toBe(false);
|
expect(timeSrv.refreshTimer).not.toBeUndefined();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -23,9 +23,8 @@ import { getRefreshFromUrl } from '../utils/getRefreshFromUrl';
|
|||||||
|
|
||||||
export class TimeSrv {
|
export class TimeSrv {
|
||||||
time: any;
|
time: any;
|
||||||
refreshTimer: any;
|
refreshTimer: number | undefined;
|
||||||
refresh: any;
|
refresh: any;
|
||||||
autoRefreshPaused = false;
|
|
||||||
oldRefresh: string | null | undefined;
|
oldRefresh: string | null | undefined;
|
||||||
timeModel?: TimeModel;
|
timeModel?: TimeModel;
|
||||||
timeAtLoad: any;
|
timeAtLoad: any;
|
||||||
@ -235,9 +234,9 @@ export class TimeSrv {
|
|||||||
const validInterval = this.contextSrv.getValidInterval(interval);
|
const validInterval = this.contextSrv.getValidInterval(interval);
|
||||||
const intervalMs = rangeUtil.intervalToMs(validInterval);
|
const intervalMs = rangeUtil.intervalToMs(validInterval);
|
||||||
|
|
||||||
this.refreshTimer = setTimeout(() => {
|
this.refreshTimer = window.setTimeout(() => {
|
||||||
this.startNextRefreshTimer(intervalMs);
|
this.startNextRefreshTimer(intervalMs);
|
||||||
!this.autoRefreshPaused && this.refreshTimeModel();
|
this.refreshTimeModel();
|
||||||
}, intervalMs);
|
}, intervalMs);
|
||||||
|
|
||||||
const refresh = this.contextSrv.getValidInterval(interval);
|
const refresh = this.contextSrv.getValidInterval(interval);
|
||||||
@ -252,10 +251,10 @@ export class TimeSrv {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private startNextRefreshTimer(afterMs: number) {
|
private startNextRefreshTimer(afterMs: number) {
|
||||||
this.refreshTimer = setTimeout(() => {
|
this.refreshTimer = window.setTimeout(() => {
|
||||||
this.startNextRefreshTimer(afterMs);
|
this.startNextRefreshTimer(afterMs);
|
||||||
if (this.contextSrv.isGrafanaVisible()) {
|
if (this.contextSrv.isGrafanaVisible()) {
|
||||||
!this.autoRefreshPaused && this.refreshTimeModel();
|
this.refreshTimeModel();
|
||||||
} else {
|
} else {
|
||||||
this.autoRefreshBlocked = true;
|
this.autoRefreshBlocked = true;
|
||||||
}
|
}
|
||||||
@ -264,18 +263,14 @@ export class TimeSrv {
|
|||||||
|
|
||||||
stopAutoRefresh() {
|
stopAutoRefresh() {
|
||||||
clearTimeout(this.refreshTimer);
|
clearTimeout(this.refreshTimer);
|
||||||
}
|
this.refreshTimer = undefined;
|
||||||
|
|
||||||
// store timeModel refresh value and pause auto-refresh in some places
|
|
||||||
// i.e panel edit
|
|
||||||
pauseAutoRefresh() {
|
|
||||||
this.autoRefreshPaused = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// resume auto-refresh based on old dashboard refresh property
|
// resume auto-refresh based on old dashboard refresh property
|
||||||
resumeAutoRefresh() {
|
resumeAutoRefresh() {
|
||||||
this.autoRefreshPaused = false;
|
if (this.timeModel?.refresh) {
|
||||||
this.refreshTimeModel();
|
this.setAutoRefresh(this.timeModel.refresh);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setTime(time: RawTimeRange, updateUrl = true) {
|
setTime(time: RawTimeRange, updateUrl = true) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { keys as _keys } from 'lodash';
|
import { keys as _keys } from 'lodash';
|
||||||
|
|
||||||
import { VariableHide } from '@grafana/data';
|
import { dateTime, TimeRange, VariableHide } from '@grafana/data';
|
||||||
import { defaultVariableModel } from '@grafana/schema';
|
import { defaultVariableModel } from '@grafana/schema';
|
||||||
import { contextSrv } from 'app/core/services/context_srv';
|
import { contextSrv } from 'app/core/services/context_srv';
|
||||||
|
|
||||||
@ -1158,8 +1158,35 @@ describe('exitViewPanel', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('exitPanelEditor', () => {
|
describe('when initEditPanel is called', () => {
|
||||||
function getTestContext(pauseAutoRefresh = false) {
|
function getTestContext() {
|
||||||
|
const dashboard = createDashboardModelFixture();
|
||||||
|
const timeSrvMock = {
|
||||||
|
pauseAutoRefresh: jest.fn(),
|
||||||
|
resumeAutoRefresh: jest.fn(),
|
||||||
|
stopAutoRefresh: jest.fn(),
|
||||||
|
} as unknown as TimeSrv;
|
||||||
|
setTimeSrv(timeSrvMock);
|
||||||
|
return { dashboard, timeSrvMock };
|
||||||
|
}
|
||||||
|
|
||||||
|
it('should set panelInEdit', () => {
|
||||||
|
const { dashboard } = getTestContext();
|
||||||
|
dashboard.addPanel({ type: 'timeseries' });
|
||||||
|
dashboard.initEditPanel(dashboard.panels[0]);
|
||||||
|
expect(dashboard.panelInEdit).not.toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should stop auto-refresh', () => {
|
||||||
|
const { dashboard, timeSrvMock } = getTestContext();
|
||||||
|
dashboard.addPanel({ type: 'timeseries' });
|
||||||
|
dashboard.initEditPanel(dashboard.panels[0]);
|
||||||
|
expect(timeSrvMock.stopAutoRefresh).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when exitPanelEditor is called', () => {
|
||||||
|
function getTestContext() {
|
||||||
const panel = new PanelModel({ destroy: jest.fn() });
|
const panel = new PanelModel({ destroy: jest.fn() });
|
||||||
const dashboard = createDashboardModelFixture();
|
const dashboard = createDashboardModelFixture();
|
||||||
const timeSrvMock = {
|
const timeSrvMock = {
|
||||||
@ -1169,15 +1196,11 @@ describe('exitPanelEditor', () => {
|
|||||||
} as unknown as TimeSrv;
|
} as unknown as TimeSrv;
|
||||||
dashboard.startRefresh = jest.fn();
|
dashboard.startRefresh = jest.fn();
|
||||||
dashboard.panelInEdit = panel;
|
dashboard.panelInEdit = panel;
|
||||||
if (pauseAutoRefresh) {
|
|
||||||
timeSrvMock.autoRefreshPaused = true;
|
|
||||||
}
|
|
||||||
setTimeSrv(timeSrvMock);
|
setTimeSrv(timeSrvMock);
|
||||||
return { dashboard, panel, timeSrvMock };
|
return { dashboard, panel, timeSrvMock };
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('when called', () => {
|
it('should set panelInEdit to undefined', () => {
|
||||||
it('then panelInEdit is set to undefined', () => {
|
|
||||||
const { dashboard } = getTestContext();
|
const { dashboard } = getTestContext();
|
||||||
|
|
||||||
dashboard.exitPanelEditor();
|
dashboard.exitPanelEditor();
|
||||||
@ -1185,7 +1208,7 @@ describe('exitPanelEditor', () => {
|
|||||||
expect(dashboard.panelInEdit).toBeUndefined();
|
expect(dashboard.panelInEdit).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('then destroy is called on panel', () => {
|
it('should destroy panel', () => {
|
||||||
const { dashboard, panel } = getTestContext();
|
const { dashboard, panel } = getTestContext();
|
||||||
|
|
||||||
dashboard.exitPanelEditor();
|
dashboard.exitPanelEditor();
|
||||||
@ -1193,7 +1216,7 @@ describe('exitPanelEditor', () => {
|
|||||||
expect(panel.destroy).toHaveBeenCalled();
|
expect(panel.destroy).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('then startRefresh is not called', () => {
|
it('should not call startRefresh', () => {
|
||||||
const { dashboard } = getTestContext();
|
const { dashboard } = getTestContext();
|
||||||
|
|
||||||
dashboard.exitPanelEditor();
|
dashboard.exitPanelEditor();
|
||||||
@ -1201,38 +1224,26 @@ describe('exitPanelEditor', () => {
|
|||||||
expect(dashboard.startRefresh).not.toHaveBeenCalled();
|
expect(dashboard.startRefresh).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should call startRefresh if time range changed during edit', () => {
|
||||||
|
const { dashboard } = getTestContext();
|
||||||
|
|
||||||
|
const range: TimeRange = {
|
||||||
|
from: dateTime(new Date().getTime()).subtract(1, 'minutes'),
|
||||||
|
to: dateTime(new Date().getTime()),
|
||||||
|
raw: {
|
||||||
|
from: 'now-1m',
|
||||||
|
to: 'now',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
dashboard.timeRangeUpdated(range);
|
||||||
|
dashboard.exitPanelEditor();
|
||||||
|
|
||||||
|
expect(dashboard.startRefresh).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
it('then auto refresh property is resumed', () => {
|
it('then auto refresh property is resumed', () => {
|
||||||
const { dashboard, timeSrvMock } = getTestContext(true);
|
const { dashboard, timeSrvMock } = getTestContext();
|
||||||
dashboard.exitPanelEditor();
|
dashboard.exitPanelEditor();
|
||||||
expect(timeSrvMock.resumeAutoRefresh).toHaveBeenCalled();
|
expect(timeSrvMock.resumeAutoRefresh).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('initEditPanel', () => {
|
|
||||||
function getTestContext() {
|
|
||||||
const dashboard = createDashboardModelFixture();
|
|
||||||
const timeSrvMock = {
|
|
||||||
pauseAutoRefresh: jest.fn(),
|
|
||||||
resumeAutoRefresh: jest.fn(),
|
|
||||||
} as unknown as TimeSrv;
|
|
||||||
setTimeSrv(timeSrvMock);
|
|
||||||
return { dashboard, timeSrvMock };
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('when called', () => {
|
|
||||||
it('then panelInEdit is not undefined', () => {
|
|
||||||
const { dashboard } = getTestContext();
|
|
||||||
dashboard.addPanel({ type: 'timeseries' });
|
|
||||||
dashboard.initEditPanel(dashboard.panels[0]);
|
|
||||||
expect(dashboard.panelInEdit).not.toBeUndefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('then auto-refresh is paused', () => {
|
|
||||||
const { dashboard, timeSrvMock } = getTestContext();
|
|
||||||
dashboard.addPanel({ type: 'timeseries' });
|
|
||||||
dashboard.initEditPanel(dashboard.panels[0]);
|
|
||||||
expect(timeSrvMock.pauseAutoRefresh).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
@ -101,6 +101,7 @@ export class DashboardModel implements TimeModel {
|
|||||||
private panelsAffectedByVariableChange: number[] | null;
|
private panelsAffectedByVariableChange: number[] | null;
|
||||||
private appEventsSubscription: Subscription;
|
private appEventsSubscription: Subscription;
|
||||||
private lastRefresh: number;
|
private lastRefresh: number;
|
||||||
|
private timeRangeUpdatedDuringEdit = false;
|
||||||
|
|
||||||
// ------------------
|
// ------------------
|
||||||
// not persisted
|
// not persisted
|
||||||
@ -126,6 +127,7 @@ export class DashboardModel implements TimeModel {
|
|||||||
appEventsSubscription: true,
|
appEventsSubscription: true,
|
||||||
panelsAffectedByVariableChange: true,
|
panelsAffectedByVariableChange: true,
|
||||||
lastRefresh: true,
|
lastRefresh: true,
|
||||||
|
timeRangeUpdatedDuringEdit: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@ -379,6 +381,10 @@ export class DashboardModel implements TimeModel {
|
|||||||
timeRangeUpdated(timeRange: TimeRange) {
|
timeRangeUpdated(timeRange: TimeRange) {
|
||||||
this.events.publish(new TimeRangeUpdatedEvent(timeRange));
|
this.events.publish(new TimeRangeUpdatedEvent(timeRange));
|
||||||
dispatch(onTimeRangeUpdated(this.uid, timeRange));
|
dispatch(onTimeRangeUpdated(this.uid, timeRange));
|
||||||
|
|
||||||
|
if (this.panelInEdit) {
|
||||||
|
this.timeRangeUpdatedDuringEdit = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
startRefresh(event: VariablesChangedEvent = { refreshAll: true, panelIds: [] }) {
|
startRefresh(event: VariablesChangedEvent = { refreshAll: true, panelIds: [] }) {
|
||||||
@ -417,11 +423,28 @@ export class DashboardModel implements TimeModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
initEditPanel(sourcePanel: PanelModel): PanelModel {
|
initEditPanel(sourcePanel: PanelModel): PanelModel {
|
||||||
getTimeSrv().pauseAutoRefresh();
|
getTimeSrv().stopAutoRefresh();
|
||||||
this.panelInEdit = sourcePanel.getEditClone();
|
this.panelInEdit = sourcePanel.getEditClone();
|
||||||
|
this.timeRangeUpdatedDuringEdit = false;
|
||||||
return this.panelInEdit;
|
return this.panelInEdit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exitPanelEditor() {
|
||||||
|
this.panelInEdit!.destroy();
|
||||||
|
this.panelInEdit = undefined;
|
||||||
|
|
||||||
|
getTimeSrv().resumeAutoRefresh();
|
||||||
|
|
||||||
|
if (this.panelsAffectedByVariableChange || this.timeRangeUpdatedDuringEdit) {
|
||||||
|
this.startRefresh({
|
||||||
|
panelIds: this.panelsAffectedByVariableChange ?? [],
|
||||||
|
refreshAll: this.timeRangeUpdatedDuringEdit,
|
||||||
|
});
|
||||||
|
this.panelsAffectedByVariableChange = null;
|
||||||
|
this.timeRangeUpdatedDuringEdit = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
initViewPanel(panel: PanelModel) {
|
initViewPanel(panel: PanelModel) {
|
||||||
this.panelInView = panel;
|
this.panelInView = panel;
|
||||||
panel.setIsViewing(true);
|
panel.setIsViewing(true);
|
||||||
@ -433,13 +456,6 @@ export class DashboardModel implements TimeModel {
|
|||||||
this.refreshIfPanelsAffectedByVariableChange();
|
this.refreshIfPanelsAffectedByVariableChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
exitPanelEditor() {
|
|
||||||
this.panelInEdit!.destroy();
|
|
||||||
this.panelInEdit = undefined;
|
|
||||||
getTimeSrv().resumeAutoRefresh();
|
|
||||||
this.refreshIfPanelsAffectedByVariableChange();
|
|
||||||
}
|
|
||||||
|
|
||||||
private refreshIfPanelsAffectedByVariableChange() {
|
private refreshIfPanelsAffectedByVariableChange() {
|
||||||
if (!this.panelsAffectedByVariableChange) {
|
if (!this.panelsAffectedByVariableChange) {
|
||||||
return;
|
return;
|
||||||
|
Loading…
Reference in New Issue
Block a user