DashboardModel: Tidy up some of the older code (#48355)

This commit is contained in:
kay delaney 2022-05-04 09:39:41 +01:00 committed by GitHub
parent c41397a6e7
commit 713e624790
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 184 additions and 307 deletions

View File

@ -1449,7 +1449,7 @@ describe('DashboardModel', () => {
});
it('should ignore fieldConfig.defaults', () => {
expect(model.panels[0].panels[0].fieldConfig.defaults).toEqual(undefined);
expect(model.panels[0].panels?.[0].fieldConfig.defaults).toEqual(undefined);
});
});
@ -1749,8 +1749,8 @@ describe('DashboardModel', () => {
},
],
});
panel1Targets = nestedModel.panels[0].panels[0].targets;
panel2Targets = nestedModel.panels[0].panels[1].targets;
panel1Targets = nestedModel.panels[0].panels?.[0].targets;
panel2Targets = nestedModel.panels[0].panels?.[1].targets;
});
it('multiple stats query should have been split into one query per stat', () => {
@ -1851,7 +1851,7 @@ describe('DashboardModel', () => {
});
it('should update datasources in panels collapsed rows', () => {
expect(model.panels[3].panels[0].datasource).toEqual({ type: 'prometheus', uid: 'prom-uid' });
expect(model.panels[3].panels?.[0].datasource).toEqual({ type: 'prometheus', uid: 'prom-uid' });
});
});

View File

@ -784,9 +784,10 @@ export class DashboardMigrator {
for (j = 0; j < this.dashboard.panels.length; j++) {
for (k = 0; k < panelUpgrades.length; k++) {
this.dashboard.panels[j] = panelUpgrades[k].call(this, this.dashboard.panels[j]);
if (this.dashboard.panels[j].panels) {
for (n = 0; n < this.dashboard.panels[j].panels.length; n++) {
this.dashboard.panels[j].panels[n] = panelUpgrades[k].call(this, this.dashboard.panels[j].panels[n]);
const rowPanels = this.dashboard.panels[j].panels;
if (rowPanels) {
for (n = 0; n < rowPanels.length; n++) {
rowPanels[n] = panelUpgrades[k].call(this, rowPanels[n]);
}
}
}
@ -895,7 +896,7 @@ export class DashboardMigrator {
delete panel.span;
if (rowPanelModel && rowPanel.collapsed) {
rowPanelModel.panels.push(panel);
rowPanelModel.panels?.push(panel);
} else {
this.dashboard.panels.push(new PanelModel(panel));
}

View File

@ -370,7 +370,7 @@ describe('DashboardModel', () => {
it('should remove panels and put them inside collapsed row', () => {
expect(dashboard.panels.length).toBe(3);
expect(dashboard.panels[1].panels.length).toBe(2);
expect(dashboard.panels[1].panels?.length).toBe(2);
});
describe('and when removing row and its panels', () => {

View File

@ -1,17 +1,4 @@
import {
cloneDeep,
defaults as _defaults,
each,
filter,
find,
findIndex,
indexOf,
isEqual,
map,
maxBy,
pull,
some,
} from 'lodash';
import { cloneDeep, defaults as _defaults, filter, indexOf, isEqual, map, maxBy, pull } from 'lodash';
import { Subscription } from 'rxjs';
import {
@ -194,14 +181,7 @@ export class DashboardModel implements TimeModel {
}
addBuiltInAnnotationQuery() {
let found = false;
for (const item of this.annotations.list) {
if (item.builtIn === 1) {
found = true;
break;
}
}
const found = this.annotations.list.some((item) => item.builtIn === 1);
if (found) {
return;
}
@ -267,9 +247,7 @@ export class DashboardModel implements TimeModel {
// sort by keys
copy = sortedDeepCloneWithoutNulls(copy);
copy.getVariables = () => {
return copy.templating.list;
};
copy.getVariables = () => copy.templating.list;
return copy;
}
@ -296,24 +274,11 @@ export class DashboardModel implements TimeModel {
private getPanelSaveModels() {
return this.panels
.filter((panel: PanelModel) => {
if (this.isSnapshotTruthy()) {
return true;
}
if (panel.type === 'add-panel') {
return false;
}
// skip repeated panels in the saved model
if (panel.repeatPanelId) {
return false;
}
// skip repeated rows in the saved model
if (panel.repeatedByRow) {
return false;
}
return true;
})
.map((panel: PanelModel) => {
.filter(
(panel) =>
this.isSnapshotTruthy() || !(panel.type === 'add-panel' || panel.repeatPanelId || panel.repeatedByRow)
)
.map((panel) => {
// If we save while editing we should include the panel in edit mode instead of the
// unmodified source panel
if (this.panelInEdit && this.panelInEdit.id === panel.id) {
@ -358,18 +323,19 @@ export class DashboardModel implements TimeModel {
};
if (!defaults.saveVariables) {
for (let i = 0; i < copy.templating.list.length; i++) {
const current = copy.templating.list[i];
const original: any = find(originalVariables, { name: current.name, type: current.type });
for (const current of copy.templating.list) {
const original = originalVariables.find(
({ name, type }: any) => name === current.name && type === current.type
);
if (!original) {
continue;
}
if (current.type === 'adhoc') {
copy.templating.list[i].filters = original.filters;
current.filters = original.filters;
} else {
copy.templating.list[i].current = original.current;
current.current = original.current;
}
}
}
@ -384,18 +350,14 @@ export class DashboardModel implements TimeModel {
this.events.publish(new RefreshEvent());
this.lastRefresh = Date.now();
if (this.panelInEdit) {
if (event.refreshAll || event.panelIds.includes(this.panelInEdit.id)) {
this.panelInEdit.refresh();
return;
}
if (this.panelInEdit && (event.refreshAll || event.panelIds.includes(this.panelInEdit.id))) {
this.panelInEdit.refresh();
return;
}
for (const panel of this.panels) {
if (!this.otherPanelInFullscreen(panel)) {
if (event.refreshAll || event.panelIds.includes(panel.id)) {
panel.refresh();
}
if (!this.otherPanelInFullscreen(panel) && (event.refreshAll || event.panelIds.includes(panel.id))) {
panel.refresh();
}
}
}
@ -453,51 +415,40 @@ export class DashboardModel implements TimeModel {
}
private ensurePanelsHaveIds() {
for (const panel of this.panels) {
if (!panel.id) {
panel.id = this.getNextPanelId();
}
if (panel.panels) {
for (const rowPanel of panel.panels) {
if (!rowPanel.id) {
rowPanel.id = this.getNextPanelId();
}
}
}
let nextPanelId = this.getNextPanelId();
for (const panel of this.panelIterator()) {
panel.id ??= nextPanelId++;
}
}
private ensureListExist(data: any) {
if (!data) {
data = {};
}
if (!data.list) {
data.list = [];
}
private ensureListExist(data: any = {}) {
data.list ??= [];
return data;
}
getNextPanelId() {
let max = 0;
for (const panel of this.panels) {
for (const panel of this.panelIterator()) {
if (panel.id > max) {
max = panel.id;
}
if (panel.collapsed) {
for (const rowPanel of panel.panels) {
if (rowPanel.id > max) {
max = rowPanel.id;
}
}
}
}
return max + 1;
}
*panelIterator() {
for (const panel of this.panels) {
yield panel;
const rowPanels = panel.panels ?? [];
for (const rowPanel of rowPanels) {
yield rowPanel as PanelModel;
}
}
}
forEachPanel(callback: (panel: PanelModel, index: number) => void) {
for (let i = 0; i < this.panels.length; i++) {
callback(this.panels[i], i);
@ -509,13 +460,7 @@ export class DashboardModel implements TimeModel {
return this.panelInEdit;
}
for (const panel of this.panels) {
if (panel.id === id) {
return panel;
}
}
return null;
return this.panels.find((p) => p.id === id) ?? null;
}
canEditPanel(panel?: PanelModel | null): boolean | undefined | null {
@ -553,13 +498,12 @@ export class DashboardModel implements TimeModel {
}
hasUnsavedChanges() {
for (const panel of this.panels) {
if (panel.hasChanged) {
console.log('Panel has changed', panel);
return true;
}
const changedPanel = this.panels.find((p) => p.hasChanged);
if (changedPanel) {
console.log('Panel has changed', changedPanel);
}
return false;
return Boolean(changedPanel);
}
cleanUpRepeats() {
@ -568,17 +512,12 @@ export class DashboardModel implements TimeModel {
}
this.iteration = (this.iteration || new Date().getTime()) + 1;
const panelsToRemove = [];
// cleanup scopedVars
deleteScopeVars(this.panels);
for (let i = 0; i < this.panels.length; i++) {
const panel = this.panels[i];
if ((!panel.repeat || panel.repeatedByRow) && panel.repeatPanelId && panel.repeatIteration !== this.iteration) {
panelsToRemove.push(panel);
}
}
const panelsToRemove = this.panels.filter(
(p) => (!p.repeat || p.repeatedByRow) && p.repeatPanelId && p.repeatIteration !== this.iteration
);
// remove panels
pull(this.panels, ...panelsToRemove);
@ -607,13 +546,8 @@ export class DashboardModel implements TimeModel {
}
cleanUpRowRepeats(rowPanels: PanelModel[]) {
const panelsToRemove = [];
for (let i = 0; i < rowPanels.length; i++) {
const panel = rowPanels[i];
if (!panel.repeat && panel.repeatPanelId) {
panelsToRemove.push(panel);
}
}
const panelsToRemove = rowPanels.filter((p) => !p.repeat && p.repeatPanelId);
pull(rowPanels, ...panelsToRemove);
pull(this.panels, ...panelsToRemove);
}
@ -623,18 +557,17 @@ export class DashboardModel implements TimeModel {
return;
}
let rowPanels = row.panels;
let rowPanels = row.panels ?? [];
if (!row.collapsed) {
const rowPanelIndex = findIndex(this.panels, (p: PanelModel) => p.id === row.id);
const rowPanelIndex = this.panels.findIndex((p) => p.id === row.id);
rowPanels = this.getRowPanels(rowPanelIndex);
}
this.cleanUpRowRepeats(rowPanels);
for (let i = 0; i < rowPanels.length; i++) {
const panel = rowPanels[i];
for (const panel of rowPanels) {
if (panel.repeat) {
const panelIndex = findIndex(this.panels, (p: PanelModel) => p.id === panel.id);
const panelIndex = this.panels.findIndex((p) => p.id === panel.id);
this.repeatPanel(panel, panelIndex);
}
}
@ -679,13 +612,13 @@ export class DashboardModel implements TimeModel {
// for row clones we need to figure out panels under row to clone and where to insert clone
let rowPanels: PanelModel[], insertPos: number;
if (sourceRowPanel.collapsed) {
rowPanels = cloneDeep(sourceRowPanel.panels);
rowPanels = cloneDeep(sourceRowPanel.panels) ?? [];
clone.panels = rowPanels;
// insert copied row after preceding row
insertPos = sourcePanelIndex + valueIndex;
} else {
rowPanels = this.getRowPanels(sourcePanelIndex);
clone.panels = map(rowPanels, (panel: PanelModel) => panel.getSaveModel());
clone.panels = rowPanels.map((panel) => panel.getSaveModel());
// insert copied row after preceding row's panels
insertPos = sourcePanelIndex + (rowPanels.length + 1) * valueIndex;
}
@ -696,7 +629,7 @@ export class DashboardModel implements TimeModel {
}
repeatPanel(panel: PanelModel, panelIndex: number) {
const variable: any = this.getPanelRepeatVariable(panel);
const variable = this.getPanelRepeatVariable(panel);
if (!variable) {
return;
}
@ -717,7 +650,7 @@ export class DashboardModel implements TimeModel {
let copy;
copy = this.getPanelRepeatClone(panel, index, panelIndex);
copy.scopedVars = copy.scopedVars || {};
copy.scopedVars ??= {};
copy.scopedVars[variable.name] = option;
if (panel.repeatDirection === REPEAT_DIR_VERTICAL) {
@ -746,12 +679,12 @@ export class DashboardModel implements TimeModel {
const yOffset = yPos - panel.gridPos.y;
if (yOffset > 0) {
const panelBelowIndex = panelIndex + selectedOptions.length;
for (let i = panelBelowIndex; i < this.panels.length; i++) {
if (isOnTheSameGridRow(panel, this.panels[i])) {
for (const curPanel of this.panels.slice(panelBelowIndex)) {
if (isOnTheSameGridRow(panel, curPanel)) {
continue;
}
this.panels[i].gridPos.y += yOffset;
curPanel.gridPos.y += yOffset;
}
}
}
@ -761,7 +694,7 @@ export class DashboardModel implements TimeModel {
let yPos = panel.gridPos.y;
function setScopedVars(panel: PanelModel, variableOption: any) {
panel.scopedVars = panel.scopedVars || {};
panel.scopedVars ??= {};
panel.scopedVars[variable.name] = variableOption;
}
@ -776,19 +709,19 @@ export class DashboardModel implements TimeModel {
if (panel.collapsed) {
// For collapsed row just copy its panels and set scoped vars and proper IDs
each(rowPanels, (rowPanel: PanelModel, i: number) => {
for (const rowPanel of rowPanels) {
setScopedVars(rowPanel, option);
if (optionIndex > 0) {
this.updateRepeatedPanelIds(rowPanel, true);
}
});
}
rowCopy.gridPos.y += optionIndex;
yPos += optionIndex;
panelBelowIndex = panelIndex + optionIndex + 1;
} else {
// insert after 'row' panel
const insertPos = panelIndex + (rowPanels.length + 1) * optionIndex + 1;
each(rowPanels, (rowPanel: PanelModel, i: number) => {
rowPanels.forEach((rowPanel: PanelModel, i: number) => {
setScopedVars(rowPanel, option);
if (optionIndex > 0) {
const cloneRowPanel = new PanelModel(rowPanel);
@ -806,8 +739,8 @@ export class DashboardModel implements TimeModel {
// Update gridPos for panels below if we inserted more than 1 repeated row panel
if (selectedOptions.length > 1) {
for (let i = panelBelowIndex; i < this.panels.length; i++) {
this.panels[i].gridPos.y += yPos;
for (const panel of this.panels.slice(panelBelowIndex)) {
panel.gridPos.y += yPos;
}
}
}
@ -839,11 +772,10 @@ export class DashboardModel implements TimeModel {
if (!rowPanel.panels || rowPanel.panels.length === 0) {
return 0;
}
const rowYPos = rowPanel.gridPos.y;
const positions = map(rowPanel.panels, 'gridPos');
const maxPos = maxBy(positions, (pos: GridPos) => {
return pos.y + pos.h;
});
const maxPos = maxBy(positions, (pos: GridPos) => pos.y + pos.h);
return maxPos!.y + maxPos!.h - rowYPos;
}
@ -853,9 +785,9 @@ export class DashboardModel implements TimeModel {
}
removeRow(row: PanelModel, removePanels: boolean) {
const needToogle = (!removePanels && row.collapsed) || (removePanels && !row.collapsed);
const needToggle = (!removePanels && row.collapsed) || (removePanels && !row.collapsed);
if (needToogle) {
if (needToggle) {
this.toggleRow(row);
}
@ -863,60 +795,30 @@ export class DashboardModel implements TimeModel {
}
expandRows() {
for (let i = 0; i < this.panels.length; i++) {
const panel = this.panels[i];
if (panel.type !== 'row') {
continue;
}
if (panel.collapsed) {
this.toggleRow(panel);
}
const collapsedRows = this.panels.filter((p) => p.type === 'row' && p.collapsed);
for (const row of collapsedRows) {
this.toggleRow(row);
}
}
collapseRows() {
for (let i = 0; i < this.panels.length; i++) {
const panel = this.panels[i];
if (panel.type !== 'row') {
continue;
}
if (!panel.collapsed) {
this.toggleRow(panel);
}
const collapsedRows = this.panels.filter((p) => p.type === 'row' && !p.collapsed);
for (const row of collapsedRows) {
this.toggleRow(row);
}
}
isSubMenuVisible() {
if (this.links.length > 0) {
return true;
}
if (this.getVariables().find((variable) => variable.hide !== 2)) {
return true;
}
if (this.annotations.list.find((annotation) => annotation.hide !== true)) {
return true;
}
return false;
return (
this.links.length > 0 ||
this.getVariables().some((variable) => variable.hide !== 2) ||
this.annotations.list.some((annotation) => !annotation.hide)
);
}
getPanelInfoById(panelId: number) {
for (let i = 0; i < this.panels.length; i++) {
if (this.panels[i].id === panelId) {
return {
panel: this.panels[i],
index: i,
};
}
}
return null;
const panelIndex = this.panels.findIndex((p) => p.id === panelId);
return panelIndex >= 0 ? { panel: this.panels[panelIndex], index: panelIndex } : null;
}
duplicatePanel(panel: PanelModel) {
@ -962,64 +864,64 @@ export class DashboardModel implements TimeModel {
toggleRow(row: PanelModel) {
const rowIndex = indexOf(this.panels, row);
if (row.collapsed) {
row.collapsed = false;
const hasRepeat = some(row.panels as PanelModel[], (p: PanelModel) => p.repeat);
if (!row.collapsed) {
const rowPanels = this.getRowPanels(rowIndex);
if (row.panels.length > 0) {
// Use first panel to figure out if it was moved or pushed
// If the panel doesn't have gridPos.y, use the row gridPos.y instead.
// This can happen for some generated dashboards.
const firstPanelYPos = row.panels[0].gridPos.y ?? row.gridPos.y;
const yDiff = firstPanelYPos - (row.gridPos.y + row.gridPos.h);
// start inserting after row
let insertPos = rowIndex + 1;
// y max will represent the bottom y pos after all panels have been added
// needed to know home much panels below should be pushed down
let yMax = row.gridPos.y;
for (const panel of row.panels) {
// set the y gridPos if it wasn't already set
panel.gridPos.y ?? (panel.gridPos.y = row.gridPos.y); // (Safari 13.1 lacks ??= support)
// make sure y is adjusted (in case row moved while collapsed)
panel.gridPos.y -= yDiff;
// insert after row
this.panels.splice(insertPos, 0, new PanelModel(panel));
// update insert post and y max
insertPos += 1;
yMax = Math.max(yMax, panel.gridPos.y + panel.gridPos.h);
}
const pushDownAmount = yMax - row.gridPos.y - 1;
// push panels below down
for (let panelIndex = insertPos; panelIndex < this.panels.length; panelIndex++) {
this.panels[panelIndex].gridPos.y += pushDownAmount;
}
row.panels = [];
if (hasRepeat) {
this.processRowRepeats(row);
}
}
// sort panels
this.sortPanelsByGridPos();
// remove panels
pull(this.panels, ...rowPanels);
// save panel models inside row panel
row.panels = rowPanels.map((panel: PanelModel) => panel.getSaveModel());
row.collapsed = true;
// emit change event
this.events.publish(new DashboardPanelsChangedEvent());
return;
}
const rowPanels = this.getRowPanels(rowIndex);
row.collapsed = false;
const rowPanels = row.panels ?? [];
const hasRepeat = rowPanels.some((p: PanelModel) => p.repeat);
if (rowPanels.length > 0) {
// Use first panel to figure out if it was moved or pushed
// If the panel doesn't have gridPos.y, use the row gridPos.y instead.
// This can happen for some generated dashboards.
const firstPanelYPos = rowPanels[0].gridPos.y ?? row.gridPos.y;
const yDiff = firstPanelYPos - (row.gridPos.y + row.gridPos.h);
// remove panels
pull(this.panels, ...rowPanels);
// save panel models inside row panel
row.panels = map(rowPanels, (panel: PanelModel) => panel.getSaveModel());
row.collapsed = true;
// start inserting after row
let insertPos = rowIndex + 1;
// y max will represent the bottom y pos after all panels have been added
// needed to know home much panels below should be pushed down
let yMax = row.gridPos.y;
for (const panel of rowPanels) {
// set the y gridPos if it wasn't already set
panel.gridPos.y ?? (panel.gridPos.y = row.gridPos.y); // (Safari 13.1 lacks ??= support)
// make sure y is adjusted (in case row moved while collapsed)
panel.gridPos.y -= yDiff;
// insert after row
this.panels.splice(insertPos, 0, new PanelModel(panel));
// update insert post and y max
insertPos += 1;
yMax = Math.max(yMax, panel.gridPos.y + panel.gridPos.h);
}
const pushDownAmount = yMax - row.gridPos.y - 1;
// push panels below down
for (const panel of this.panels.slice(insertPos)) {
panel.gridPos.y += pushDownAmount;
}
row.panels = [];
if (hasRepeat) {
this.processRowRepeats(row);
}
}
// sort panels
this.sortPanelsByGridPos();
// emit change event
this.events.publish(new DashboardPanelsChangedEvent());
@ -1029,19 +931,11 @@ export class DashboardModel implements TimeModel {
* Will return all panels after rowIndex until it encounters another row
*/
getRowPanels(rowIndex: number): PanelModel[] {
const rowPanels = [];
const panelsBelowRow = this.panels.slice(rowIndex + 1);
const nextRowIndex = panelsBelowRow.findIndex((p) => p.type === 'row');
for (let index = rowIndex + 1; index < this.panels.length; index++) {
const panel = this.panels[index];
// break when encountering another row
if (panel.type === 'row') {
break;
}
// this panel must belong to row
rowPanels.push(panel);
}
// Take all panels up to next row, or all panels if there are no other rows
const rowPanels = panelsBelowRow.slice(0, nextRowIndex >= 0 ? nextRowIndex : this.panels.length);
return rowPanels;
}
@ -1095,14 +989,12 @@ export class DashboardModel implements TimeModel {
hasTimeChanged() {
const { time, originalTime } = this;
if (isEqual(time, originalTime)) {
return false;
}
// Compare momemt values vs strings values
// Compare moment values vs strings values
return !(
isEqual(dateTime(time?.from), dateTime(originalTime?.from)) &&
isEqual(dateTime(time?.to), dateTime(originalTime?.to))
isEqual(time, originalTime) ||
(isEqual(dateTime(time?.from), dateTime(originalTime?.from)) &&
isEqual(dateTime(time?.to), dateTime(originalTime?.to)))
);
}
@ -1120,11 +1012,7 @@ export class DashboardModel implements TimeModel {
}
autoFitPanels(viewHeight: number, kioskMode?: UrlQueryValue) {
const currentGridHeight = Math.max(
...this.panels.map((panel) => {
return panel.gridPos.h + panel.gridPos.y;
})
);
const currentGridHeight = Math.max(...this.panels.map((panel) => panel.gridPos.h + panel.gridPos.y));
const navbarHeight = 55;
const margin = 20;
@ -1145,10 +1033,10 @@ export class DashboardModel implements TimeModel {
const visibleGridHeight = Math.floor(visibleHeight / (GRID_CELL_HEIGHT + GRID_CELL_VMARGIN));
const scaleFactor = currentGridHeight / visibleGridHeight;
this.panels.forEach((panel, i) => {
for (const panel of this.panels) {
panel.gridPos.y = Math.round(panel.gridPos.y / scaleFactor) || 1;
panel.gridPos.h = Math.round(panel.gridPos.h / scaleFactor) || 1;
});
}
}
templateVariableValueUpdated() {
@ -1160,39 +1048,32 @@ export class DashboardModel implements TimeModel {
const panelId = parseInt(panelUrlId ?? '0', 10);
// First try to find it in a collapsed row and exand it
for (const panel of this.panels) {
if (panel.collapsed) {
for (const rowPanel of panel.panels) {
if (rowPanel.id === panelId) {
this.toggleRow(panel);
break;
}
}
}
const collapsedPanels = this.panels.filter((p) => p.collapsed);
for (const panel of collapsedPanels) {
const hasPanel = panel.panels?.some((rp: any) => rp.id === panelId);
hasPanel && this.toggleRow(panel);
}
return this.getPanelById(panelId);
}
toggleLegendsForAll() {
const panelsWithLegends = this.panels.filter((panel) => {
return panel.legend !== undefined && panel.legend !== null;
});
const panelsWithLegends = this.panels.filter(isPanelWithLegend);
// determine if more panels are displaying legends or not
const onCount = panelsWithLegends.filter((panel) => panel.legend!.show).length;
const onCount = panelsWithLegends.filter((panel) => panel.legend.show).length;
const offCount = panelsWithLegends.length - onCount;
const panelLegendsOn = onCount >= offCount;
for (const panel of panelsWithLegends) {
panel.legend!.show = !panelLegendsOn;
panel.legend.show = !panelLegendsOn;
panel.render();
}
}
getVariables = () => {
getVariables() {
return this.getVariablesFromState(this.uid);
};
}
canEditAnnotations(dashboardId: number) {
let canEdit = true;
@ -1209,13 +1090,8 @@ export class DashboardModel implements TimeModel {
}
canAddAnnotations() {
let canAdd = true;
// if RBAC is enabled there are additional conditions to check
if (contextSrv.accessControlEnabled()) {
canAdd = !!this.meta.annotationsPermissions?.dashboard.canAdd;
}
// If RBAC is enabled there are additional conditions to check
const canAdd = !contextSrv.accessControlEnabled() || this.meta.annotationsPermissions?.dashboard.canAdd;
return this.canEditDashboard() && canAdd;
}
@ -1247,27 +1123,23 @@ export class DashboardModel implements TimeModel {
return false;
}
const updated = map(currentVariables, (variable: any) => {
return {
name: variable.name,
type: variable.type,
current: cloneDeep(variable.current),
filters: cloneDeep(variable.filters),
};
});
const updated = currentVariables.map((variable: any) => ({
name: variable.name,
type: variable.type,
current: cloneDeep(variable.current),
filters: cloneDeep(variable.filters),
}));
return !isEqual(updated, originalVariables);
}
private cloneVariablesFrom(variables: any[]): any[] {
return variables.map((variable) => {
return {
name: variable.name,
type: variable.type,
current: cloneDeep(variable.current),
filters: cloneDeep(variable.filters),
};
});
return variables.map((variable) => ({
name: variable.name,
type: variable.type,
current: cloneDeep(variable.current),
filters: cloneDeep(variable.filters),
}));
}
private variablesTimeRangeProcessDoneHandler(event: VariablesTimeRangeProcessDone) {
@ -1299,3 +1171,7 @@ export class DashboardModel implements TimeModel {
this.startRefresh(event.payload);
}
}
function isPanelWithLegend(panel: PanelModel): panel is PanelModel & Pick<Required<PanelModel>, 'legend'> {
return Boolean(panel.legend);
}

View File

@ -139,7 +139,7 @@ export class PanelModel implements DataConfigSource, IPanelModel {
maxPerRow?: number;
collapsed?: boolean;
panels?: any;
panels?: PanelModel[];
declare targets: DataQuery[];
transformations?: DataTransformerConfig[];
datasource: DataSourceRef | null = null;

View File

@ -50,14 +50,14 @@ describe('deleteScopeVars', () => {
});
expect(panel1.scopedVars).toBeDefined();
expect(panel1.panels[0].scopedVars).toBeDefined();
expect(panel1.panels[1].scopedVars).toBeDefined();
expect(panel1.panels?.[0].scopedVars).toBeDefined();
expect(panel1.panels?.[1].scopedVars).toBeDefined();
deleteScopeVars([panel1]);
expect(panel1.scopedVars).toBeUndefined();
expect(panel1.panels[0].scopedVars).toBeUndefined();
expect(panel1.panels[1].scopedVars).toBeUndefined();
expect(panel1.panels?.[0].scopedVars).toBeUndefined();
expect(panel1.panels?.[1].scopedVars).toBeUndefined();
});
});
});