Variables: Refreshes all panels even if panel is full screen (#34097)

* Variables: Refreshes all panels even if panel is full screen

* Chore: updates after PR comments
This commit is contained in:
Hugo Häggmark 2021-05-14 10:42:33 +02:00 committed by GitHub
parent 062e1d5ab8
commit 57d898cd5a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 164 additions and 1 deletions

View File

@ -37,6 +37,7 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1`
"getVariablesFromState": [Function],
"gnetId": null,
"graphTooltip": 0,
"hasChangesThatAffectsAllPanels": false,
"id": null,
"links": Array [],
"meta": Object {
@ -175,6 +176,7 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1`
"getVariablesFromState": [Function],
"gnetId": null,
"graphTooltip": 0,
"hasChangesThatAffectsAllPanels": false,
"id": null,
"links": Array [],
"meta": Object {
@ -283,6 +285,7 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1`
"getVariablesFromState": [Function],
"gnetId": null,
"graphTooltip": 0,
"hasChangesThatAffectsAllPanels": false,
"id": null,
"links": Array [],
"meta": Object {
@ -413,6 +416,7 @@ exports[`DashboardPage When dashboard has editview url state should render setti
"getVariablesFromState": [Function],
"gnetId": null,
"graphTooltip": 0,
"hasChangesThatAffectsAllPanels": false,
"id": null,
"links": Array [],
"meta": Object {
@ -551,6 +555,7 @@ exports[`DashboardPage When dashboard has editview url state should render setti
"getVariablesFromState": [Function],
"gnetId": null,
"graphTooltip": 0,
"hasChangesThatAffectsAllPanels": false,
"id": null,
"links": Array [],
"meta": Object {
@ -659,6 +664,7 @@ exports[`DashboardPage When dashboard has editview url state should render setti
"getVariablesFromState": [Function],
"gnetId": null,
"graphTooltip": 0,
"hasChangesThatAffectsAllPanels": false,
"id": null,
"links": Array [],
"meta": Object {
@ -771,6 +777,7 @@ exports[`DashboardPage When dashboard has editview url state should render setti
"getVariablesFromState": [Function],
"gnetId": null,
"graphTooltip": 0,
"hasChangesThatAffectsAllPanels": false,
"id": null,
"links": Array [],
"meta": Object {

View File

@ -84,6 +84,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
"getVariablesFromState": [Function],
"gnetId": null,
"graphTooltip": 0,
"hasChangesThatAffectsAllPanels": false,
"id": null,
"links": Array [],
"meta": Object {
@ -355,6 +356,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
"getVariablesFromState": [Function],
"gnetId": null,
"graphTooltip": 0,
"hasChangesThatAffectsAllPanels": false,
"id": null,
"links": Array [],
"meta": Object {
@ -626,6 +628,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
"getVariablesFromState": [Function],
"gnetId": null,
"graphTooltip": 0,
"hasChangesThatAffectsAllPanels": false,
"id": null,
"links": Array [],
"meta": Object {
@ -897,6 +900,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
"getVariablesFromState": [Function],
"gnetId": null,
"graphTooltip": 0,
"hasChangesThatAffectsAllPanels": false,
"id": null,
"links": Array [],
"meta": Object {

View File

@ -6,6 +6,7 @@ import { variableAdapters } from '../../variables/adapters';
import { createAdHocVariableAdapter } from '../../variables/adhoc/adapter';
import { createQueryVariableAdapter } from '../../variables/query/adapter';
import { createCustomVariableAdapter } from '../../variables/custom/adapter';
import { expect } from '../../../../test/lib/common';
jest.mock('app/core/services/context_srv', () => ({}));
variableAdapters.setInit(() => [
@ -764,3 +765,123 @@ describe('DashboardModel', () => {
);
});
});
describe('exitViewPanel', () => {
function getTestContext() {
const panel: any = { setIsViewing: jest.fn() };
const dashboard = new DashboardModel({});
dashboard.startRefresh = jest.fn();
dashboard.panelInView = panel;
return { dashboard, panel };
}
describe('when called', () => {
it('then panelInView is set to undefined', () => {
const { dashboard, panel } = getTestContext();
dashboard.exitViewPanel(panel);
expect(dashboard.panelInView).toBeUndefined();
});
it('then setIsViewing is called on panel', () => {
const { dashboard, panel } = getTestContext();
dashboard.exitViewPanel(panel);
expect(panel.setIsViewing).toHaveBeenCalledWith(false);
});
it('then startRefresh is not called', () => {
const { dashboard, panel } = getTestContext();
dashboard.exitViewPanel(panel);
expect(dashboard.startRefresh).not.toHaveBeenCalled();
});
describe('and there is a change that affects all panels', () => {
it('then startRefresh is not called', () => {
const { dashboard, panel } = getTestContext();
dashboard.setChangeAffectsAllPanels();
dashboard.exitViewPanel(panel);
expect(dashboard.startRefresh).toHaveBeenCalled();
});
});
});
});
describe('exitPanelEditor', () => {
function getTestContext() {
const panel: any = { destroy: jest.fn() };
const dashboard = new DashboardModel({});
dashboard.startRefresh = jest.fn();
dashboard.panelInEdit = panel;
return { dashboard, panel };
}
describe('when called', () => {
it('then panelInEdit is set to undefined', () => {
const { dashboard } = getTestContext();
dashboard.exitPanelEditor();
expect(dashboard.panelInEdit).toBeUndefined();
});
it('then destroy is called on panel', () => {
const { dashboard, panel } = getTestContext();
dashboard.exitPanelEditor();
expect(panel.destroy).toHaveBeenCalled();
});
it('then startRefresh is not called', () => {
const { dashboard } = getTestContext();
dashboard.exitPanelEditor();
expect(dashboard.startRefresh).not.toHaveBeenCalled();
});
describe('and there is a change that affects all panels', () => {
it('then startRefresh is not called', () => {
const { dashboard } = getTestContext();
dashboard.setChangeAffectsAllPanels();
dashboard.exitPanelEditor();
expect(dashboard.startRefresh).toHaveBeenCalled();
});
});
});
});
describe('setChangeAffectsAllPanels', () => {
it.each`
panelInEdit | panelInView | expected
${null} | ${null} | ${false}
${undefined} | ${undefined} | ${false}
${null} | ${{}} | ${true}
${undefined} | ${{}} | ${true}
${{}} | ${null} | ${true}
${{}} | ${undefined} | ${true}
${{}} | ${{}} | ${true}
`(
'when called and panelInEdit:{$panelInEdit} and panelInView:{$panelInView}',
({ panelInEdit, panelInView, expected }) => {
const dashboard = new DashboardModel({});
dashboard.panelInEdit = panelInEdit;
dashboard.panelInView = panelInView;
dashboard.setChangeAffectsAllPanels();
expect(dashboard['hasChangesThatAffectsAllPanels']).toEqual(expected);
}
);
});

View File

@ -92,6 +92,7 @@ export class DashboardModel {
panels: PanelModel[];
panelInEdit?: PanelModel;
panelInView?: PanelModel;
private hasChangesThatAffectsAllPanels: boolean;
// ------------------
// not persisted
@ -114,6 +115,7 @@ export class DashboardModel {
panelInView: true,
getVariablesFromState: true,
formatDate: true,
hasChangesThatAffectsAllPanels: true,
};
constructor(data: any, meta?: DashboardMeta, private getVariablesFromState: GetVariables = getVariables) {
@ -154,6 +156,7 @@ export class DashboardModel {
this.addBuiltInAnnotationQuery();
this.sortPanelsByGridPos();
this.hasChangesThatAffectsAllPanels = false;
}
addBuiltInAnnotationQuery() {
@ -365,11 +368,28 @@ export class DashboardModel {
exitViewPanel(panel: PanelModel) {
this.panelInView = undefined;
panel.setIsViewing(false);
this.refreshIfChangeAffectsAllPanels();
}
exitPanelEditor() {
this.panelInEdit!.destroy();
this.panelInEdit = undefined;
this.refreshIfChangeAffectsAllPanels();
}
setChangeAffectsAllPanels() {
if (this.panelInEdit || this.panelInView) {
this.hasChangesThatAffectsAllPanels = true;
}
}
private refreshIfChangeAffectsAllPanels() {
if (!this.hasChangesThatAffectsAllPanels) {
return;
}
this.hasChangesThatAffectsAllPanels = false;
this.startRefresh();
}
private ensureListExist(data: any) {

View File

@ -111,7 +111,7 @@ export const initDashboardTemplating = (list: VariableModel[]): ThunkResult<void
};
export const addSystemTemplateVariables = (dashboard: DashboardModel): ThunkResult<void> => {
return (dispatch, getState) => {
return (dispatch) => {
const dashboardModel: DashboardVariableModel = {
...initialVariableModelState,
id: '__dashboard',
@ -493,6 +493,7 @@ export const variableUpdated = (
return Promise.all(promises).then(() => {
if (emitChangeEvents) {
const dashboard = getState().dashboard.getModel();
dashboard?.setChangeAffectsAllPanels();
dashboard?.processRepeats();
locationService.partial(getQueryWithVariables(getState));
dashboard?.startRefresh();
@ -526,6 +527,7 @@ export const onTimeRangeUpdated = (
try {
await Promise.all(promises);
const dashboard = getState().dashboard.getModel();
dashboard?.setChangeAffectsAllPanels();
dashboard?.startRefresh();
} catch (error) {
console.error(error);

View File

@ -54,11 +54,13 @@ const getTestContext = () => {
const templateSrvMock = ({ updateTimeRange: updateTimeRangeMock } as unknown) as TemplateSrv;
const dependencies: OnTimeRangeUpdatedDependencies = { templateSrv: templateSrvMock };
const templateVariableValueUpdatedMock = jest.fn();
const setChangeAffectsAllPanelsMock = jest.fn();
const dashboard = ({
getModel: () =>
(({
templateVariableValueUpdated: templateVariableValueUpdatedMock,
startRefresh: startRefreshMock,
setChangeAffectsAllPanels: setChangeAffectsAllPanelsMock,
} as unknown) as DashboardModel),
} as unknown) as DashboardState;
const startRefreshMock = jest.fn();
@ -82,6 +84,7 @@ const getTestContext = () => {
updateTimeRangeMock,
templateVariableValueUpdatedMock,
startRefreshMock,
setChangeAffectsAllPanelsMock,
};
};
@ -95,6 +98,7 @@ describe('when onTimeRangeUpdated is dispatched', () => {
updateTimeRangeMock,
templateVariableValueUpdatedMock,
startRefreshMock,
setChangeAffectsAllPanelsMock,
} = getTestContext();
const tester = await reduxTester<RootReducerType>({ preloadedState })
@ -117,6 +121,7 @@ describe('when onTimeRangeUpdated is dispatched', () => {
expect(updateTimeRangeMock).toHaveBeenCalledWith(range);
expect(templateVariableValueUpdatedMock).toHaveBeenCalledTimes(1);
expect(startRefreshMock).toHaveBeenCalledTimes(1);
expect(setChangeAffectsAllPanelsMock).toHaveBeenCalledTimes(1);
});
});
@ -130,6 +135,7 @@ describe('when onTimeRangeUpdated is dispatched', () => {
updateTimeRangeMock,
templateVariableValueUpdatedMock,
startRefreshMock,
setChangeAffectsAllPanelsMock,
} = getTestContext();
const base = await reduxTester<RootReducerType>({ preloadedState })
@ -154,6 +160,7 @@ describe('when onTimeRangeUpdated is dispatched', () => {
expect(updateTimeRangeMock).toHaveBeenCalledWith(range);
expect(templateVariableValueUpdatedMock).toHaveBeenCalledTimes(0);
expect(startRefreshMock).toHaveBeenCalledTimes(1);
expect(setChangeAffectsAllPanelsMock).toHaveBeenCalledTimes(1);
});
});
@ -168,6 +175,7 @@ describe('when onTimeRangeUpdated is dispatched', () => {
updateTimeRangeMock,
templateVariableValueUpdatedMock,
startRefreshMock,
setChangeAffectsAllPanelsMock,
} = getTestContext();
adapter.updateOptions = jest.fn().mockRejectedValue(new Error('Something broke'));
@ -196,6 +204,7 @@ describe('when onTimeRangeUpdated is dispatched', () => {
expect(updateTimeRangeMock).toHaveBeenCalledWith(range);
expect(templateVariableValueUpdatedMock).toHaveBeenCalledTimes(0);
expect(startRefreshMock).toHaveBeenCalledTimes(0);
expect(setChangeAffectsAllPanelsMock).toHaveBeenCalledTimes(0);
});
});
});