mirror of https://github.com/grafana/grafana
parent
b3f3b70b90
commit
1f9922a5aa
@ -1,22 +1,22 @@ |
|||||||
#! /usr/bin/env bash |
#! /usr/bin/env bash |
||||||
|
|
||||||
deb_ver=3.0.0-beta41460581169 |
deb_ver=3.0.0-beta51460658374 |
||||||
rpm_ver=3.0.0-beta41460581169 |
rpm_ver=3.0.0-beta51460658374 |
||||||
|
|
||||||
#rpm_ver=3.0.0-1 |
#rpm_ver=3.0.0-1 |
||||||
|
|
||||||
wget https://grafanarel.s3.amazonaws.com/builds/grafana_${deb_ver}_amd64.deb |
#wget https://grafanarel.s3.amazonaws.com/builds/grafana_${deb_ver}_amd64.deb |
||||||
|
|
||||||
#package_cloud push grafana/stable/debian/jessie grafana_${deb_ver}_amd64.deb |
#package_cloud push grafana/stable/debian/jessie grafana_${deb_ver}_amd64.deb |
||||||
#package_cloud push grafana/stable/debian/wheezy grafana_${deb_ver}_amd64.deb |
#package_cloud push grafana/stable/debian/wheezy grafana_${deb_ver}_amd64.deb |
||||||
|
|
||||||
package_cloud push grafana/testing/debian/jessie grafana_${deb_ver}_amd64.deb |
#package_cloud push grafana/testing/debian/jessie grafana_${deb_ver}_amd64.deb |
||||||
package_cloud push grafana/testing/debian/wheezy grafana_${deb_ver}_amd64.deb |
#package_cloud push grafana/testing/debian/wheezy grafana_${deb_ver}_amd64.deb |
||||||
|
|
||||||
wget https://grafanarel.s3.amazonaws.com/builds/grafana-${rpm_ver}.x86_64.rpm |
#wget https://grafanarel.s3.amazonaws.com/builds/grafana-${rpm_ver}.x86_64.rpm |
||||||
|
|
||||||
package_cloud push grafana/testing/el/6 grafana-${rpm_ver}.x86_64.rpm |
#package_cloud push grafana/testing/el/6 grafana-${rpm_ver}.x86_64.rpm |
||||||
ackage_cloud push grafana/testing/el/7 grafana-${rpm_ver}.x86_64.rpm |
package_cloud push grafana/testing/el/7 grafana-${rpm_ver}.x86_64.rpm |
||||||
|
|
||||||
# package_cloud push grafana/stable/el/7 grafana-${version}-1.x86_64.rpm |
# package_cloud push grafana/stable/el/7 grafana-${version}-1.x86_64.rpm |
||||||
# package_cloud push grafana/stable/el/6 grafana-${version}-1.x86_64.rpm |
# package_cloud push grafana/stable/el/6 grafana-${version}-1.x86_64.rpm |
||||||
|
|||||||
@ -1,147 +0,0 @@ |
|||||||
define([ |
|
||||||
'angular', |
|
||||||
'jquery', |
|
||||||
'app/core/config', |
|
||||||
'moment', |
|
||||||
], |
|
||||||
function (angular, $, config, moment) { |
|
||||||
"use strict"; |
|
||||||
|
|
||||||
var module = angular.module('grafana.controllers'); |
|
||||||
|
|
||||||
module.controller('DashboardCtrl', function( |
|
||||||
$scope, |
|
||||||
$rootScope, |
|
||||||
dashboardKeybindings, |
|
||||||
timeSrv, |
|
||||||
templateValuesSrv, |
|
||||||
dynamicDashboardSrv, |
|
||||||
dashboardSrv, |
|
||||||
unsavedChangesSrv, |
|
||||||
dashboardViewStateSrv, |
|
||||||
contextSrv, |
|
||||||
$timeout) { |
|
||||||
|
|
||||||
$scope.editor = { index: 0 }; |
|
||||||
$scope.panels = config.panels; |
|
||||||
|
|
||||||
var resizeEventTimeout; |
|
||||||
|
|
||||||
this.init = function(dashboard) { |
|
||||||
$scope.resetRow(); |
|
||||||
$scope.registerWindowResizeEvent(); |
|
||||||
$scope.onAppEvent('show-json-editor', $scope.showJsonEditor); |
|
||||||
$scope.setupDashboard(dashboard); |
|
||||||
}; |
|
||||||
|
|
||||||
$scope.setupDashboard = function(data) { |
|
||||||
$rootScope.performance.dashboardLoadStart = new Date().getTime(); |
|
||||||
$rootScope.performance.panelsInitialized = 0; |
|
||||||
$rootScope.performance.panelsRendered = 0; |
|
||||||
|
|
||||||
var dashboard = dashboardSrv.create(data.dashboard, data.meta); |
|
||||||
dashboardSrv.setCurrent(dashboard); |
|
||||||
|
|
||||||
// init services
|
|
||||||
timeSrv.init(dashboard); |
|
||||||
|
|
||||||
// template values service needs to initialize completely before
|
|
||||||
// the rest of the dashboard can load
|
|
||||||
templateValuesSrv.init(dashboard).finally(function() { |
|
||||||
dynamicDashboardSrv.init(dashboard); |
|
||||||
unsavedChangesSrv.init(dashboard, $scope); |
|
||||||
|
|
||||||
$scope.dashboard = dashboard; |
|
||||||
$scope.dashboardMeta = dashboard.meta; |
|
||||||
$scope.dashboardViewState = dashboardViewStateSrv.create($scope); |
|
||||||
|
|
||||||
dashboardKeybindings.shortcuts($scope); |
|
||||||
|
|
||||||
$scope.updateSubmenuVisibility(); |
|
||||||
$scope.setWindowTitleAndTheme(); |
|
||||||
|
|
||||||
$scope.appEvent("dashboard-loaded", $scope.dashboard); |
|
||||||
}).catch(function(err) { |
|
||||||
if (err.data && err.data.message) { err.message = err.data.message; } |
|
||||||
$scope.appEvent("alert-error", ['Dashboard init failed', 'Template variables could not be initialized: ' + err.message]); |
|
||||||
}); |
|
||||||
}; |
|
||||||
|
|
||||||
$scope.updateSubmenuVisibility = function() { |
|
||||||
$scope.submenuEnabled = $scope.dashboard.isSubmenuFeaturesEnabled(); |
|
||||||
}; |
|
||||||
|
|
||||||
$scope.setWindowTitleAndTheme = function() { |
|
||||||
window.document.title = config.window_title_prefix + $scope.dashboard.title; |
|
||||||
}; |
|
||||||
|
|
||||||
$scope.broadcastRefresh = function() { |
|
||||||
$rootScope.performance.panelsRendered = 0; |
|
||||||
$rootScope.$broadcast('refresh'); |
|
||||||
}; |
|
||||||
|
|
||||||
$scope.addRow = function(dash, row) { |
|
||||||
dash.rows.push(row); |
|
||||||
}; |
|
||||||
|
|
||||||
$scope.addRowDefault = function() { |
|
||||||
$scope.resetRow(); |
|
||||||
$scope.row.title = 'New row'; |
|
||||||
$scope.addRow($scope.dashboard, $scope.row); |
|
||||||
}; |
|
||||||
|
|
||||||
$scope.resetRow = function() { |
|
||||||
$scope.row = { |
|
||||||
title: '', |
|
||||||
height: '250px', |
|
||||||
editable: true, |
|
||||||
}; |
|
||||||
}; |
|
||||||
|
|
||||||
$scope.showJsonEditor = function(evt, options) { |
|
||||||
var editScope = $rootScope.$new(); |
|
||||||
editScope.object = options.object; |
|
||||||
editScope.updateHandler = options.updateHandler; |
|
||||||
$scope.appEvent('show-dash-editor', { src: 'public/app/partials/edit_json.html', scope: editScope }); |
|
||||||
}; |
|
||||||
|
|
||||||
$scope.onDrop = function(panelId, row, dropTarget) { |
|
||||||
var info = $scope.dashboard.getPanelInfoById(panelId); |
|
||||||
if (dropTarget) { |
|
||||||
var dropInfo = $scope.dashboard.getPanelInfoById(dropTarget.id); |
|
||||||
dropInfo.row.panels[dropInfo.index] = info.panel; |
|
||||||
info.row.panels[info.index] = dropTarget; |
|
||||||
var dragSpan = info.panel.span; |
|
||||||
info.panel.span = dropTarget.span; |
|
||||||
dropTarget.span = dragSpan; |
|
||||||
} |
|
||||||
else { |
|
||||||
info.row.panels.splice(info.index, 1); |
|
||||||
info.panel.span = 12 - $scope.dashboard.rowSpan(row); |
|
||||||
row.panels.push(info.panel); |
|
||||||
} |
|
||||||
|
|
||||||
$rootScope.$broadcast('render'); |
|
||||||
}; |
|
||||||
|
|
||||||
$scope.registerWindowResizeEvent = function() { |
|
||||||
angular.element(window).bind('resize', function() { |
|
||||||
$timeout.cancel(resizeEventTimeout); |
|
||||||
resizeEventTimeout = $timeout(function() { $scope.$broadcast('render'); }, 200); |
|
||||||
}); |
|
||||||
$scope.$on('$destroy', function() { |
|
||||||
angular.element(window).unbind('resize'); |
|
||||||
}); |
|
||||||
}; |
|
||||||
|
|
||||||
$scope.timezoneChanged = function() { |
|
||||||
$rootScope.$broadcast("refresh"); |
|
||||||
}; |
|
||||||
|
|
||||||
$scope.formatDate = function(date) { |
|
||||||
return moment(date).format('MMM Do YYYY, h:mm:ss a'); |
|
||||||
}; |
|
||||||
|
|
||||||
}); |
|
||||||
|
|
||||||
}); |
|
||||||
@ -0,0 +1,154 @@ |
|||||||
|
///<reference path="../../headers/common.d.ts" />
|
||||||
|
|
||||||
|
import config from 'app/core/config'; |
||||||
|
import angular from 'angular'; |
||||||
|
import moment from 'moment'; |
||||||
|
import _ from 'lodash'; |
||||||
|
|
||||||
|
import coreModule from 'app/core/core_module'; |
||||||
|
import {DynamicDashboardSrv} from './dynamic_dashboard_srv'; |
||||||
|
|
||||||
|
export class DashboardCtrl { |
||||||
|
|
||||||
|
/** @ngInject */ |
||||||
|
constructor( |
||||||
|
private $scope, |
||||||
|
private $rootScope, |
||||||
|
dashboardKeybindings, |
||||||
|
timeSrv, |
||||||
|
templateValuesSrv, |
||||||
|
dashboardSrv, |
||||||
|
unsavedChangesSrv, |
||||||
|
dashboardViewStateSrv, |
||||||
|
contextSrv, |
||||||
|
$timeout) { |
||||||
|
|
||||||
|
$scope.editor = { index: 0 }; |
||||||
|
$scope.panels = config.panels; |
||||||
|
$scope.dynamicDashboardSrv = new DynamicDashboardSrv(); |
||||||
|
|
||||||
|
var resizeEventTimeout; |
||||||
|
|
||||||
|
$scope.setupDashboard = function(data) { |
||||||
|
$rootScope.performance.dashboardLoadStart = new Date().getTime(); |
||||||
|
$rootScope.performance.panelsInitialized = 0; |
||||||
|
$rootScope.performance.panelsRendered = 0; |
||||||
|
|
||||||
|
var dashboard = dashboardSrv.create(data.dashboard, data.meta); |
||||||
|
dashboardSrv.setCurrent(dashboard); |
||||||
|
|
||||||
|
// init services
|
||||||
|
timeSrv.init(dashboard); |
||||||
|
|
||||||
|
// template values service needs to initialize completely before
|
||||||
|
// the rest of the dashboard can load
|
||||||
|
templateValuesSrv.init(dashboard).finally(function() { |
||||||
|
$scope.dynamicDashboardSrv.init(dashboard); |
||||||
|
|
||||||
|
unsavedChangesSrv.init(dashboard, $scope); |
||||||
|
|
||||||
|
$scope.dashboard = dashboard; |
||||||
|
$scope.dashboardMeta = dashboard.meta; |
||||||
|
$scope.dashboardViewState = dashboardViewStateSrv.create($scope); |
||||||
|
|
||||||
|
dashboardKeybindings.shortcuts($scope); |
||||||
|
|
||||||
|
$scope.updateSubmenuVisibility(); |
||||||
|
$scope.setWindowTitleAndTheme(); |
||||||
|
|
||||||
|
$scope.appEvent("dashboard-loaded", $scope.dashboard); |
||||||
|
}).catch(function(err) { |
||||||
|
if (err.data && err.data.message) { err.message = err.data.message; } |
||||||
|
$scope.appEvent("alert-error", ['Dashboard init failed', 'Template variables could not be initialized: ' + err.message]); |
||||||
|
}); |
||||||
|
}; |
||||||
|
|
||||||
|
$scope.templateVariableUpdated = function() { |
||||||
|
$scope.dynamicDashboardSrv.update($scope.dashboard); |
||||||
|
}; |
||||||
|
|
||||||
|
$scope.updateSubmenuVisibility = function() { |
||||||
|
$scope.submenuEnabled = $scope.dashboard.isSubmenuFeaturesEnabled(); |
||||||
|
}; |
||||||
|
|
||||||
|
$scope.setWindowTitleAndTheme = function() { |
||||||
|
window.document.title = config.window_title_prefix + $scope.dashboard.title; |
||||||
|
}; |
||||||
|
|
||||||
|
$scope.broadcastRefresh = function() { |
||||||
|
$rootScope.performance.panelsRendered = 0; |
||||||
|
$rootScope.$broadcast('refresh'); |
||||||
|
}; |
||||||
|
|
||||||
|
$scope.addRow = function(dash, row) { |
||||||
|
dash.rows.push(row); |
||||||
|
}; |
||||||
|
|
||||||
|
$scope.addRowDefault = function() { |
||||||
|
$scope.resetRow(); |
||||||
|
$scope.row.title = 'New row'; |
||||||
|
$scope.addRow($scope.dashboard, $scope.row); |
||||||
|
}; |
||||||
|
|
||||||
|
$scope.resetRow = function() { |
||||||
|
$scope.row = { |
||||||
|
title: '', |
||||||
|
height: '250px', |
||||||
|
editable: true, |
||||||
|
}; |
||||||
|
}; |
||||||
|
|
||||||
|
$scope.showJsonEditor = function(evt, options) { |
||||||
|
var editScope = $rootScope.$new(); |
||||||
|
editScope.object = options.object; |
||||||
|
editScope.updateHandler = options.updateHandler; |
||||||
|
$scope.appEvent('show-dash-editor', { src: 'public/app/partials/edit_json.html', scope: editScope }); |
||||||
|
}; |
||||||
|
|
||||||
|
$scope.onDrop = function(panelId, row, dropTarget) { |
||||||
|
var info = $scope.dashboard.getPanelInfoById(panelId); |
||||||
|
if (dropTarget) { |
||||||
|
var dropInfo = $scope.dashboard.getPanelInfoById(dropTarget.id); |
||||||
|
dropInfo.row.panels[dropInfo.index] = info.panel; |
||||||
|
info.row.panels[info.index] = dropTarget; |
||||||
|
var dragSpan = info.panel.span; |
||||||
|
info.panel.span = dropTarget.span; |
||||||
|
dropTarget.span = dragSpan; |
||||||
|
} else { |
||||||
|
info.row.panels.splice(info.index, 1); |
||||||
|
info.panel.span = 12 - $scope.dashboard.rowSpan(row); |
||||||
|
row.panels.push(info.panel); |
||||||
|
} |
||||||
|
|
||||||
|
$rootScope.$broadcast('render'); |
||||||
|
}; |
||||||
|
|
||||||
|
$scope.registerWindowResizeEvent = function() { |
||||||
|
angular.element(window).bind('resize', function() { |
||||||
|
$timeout.cancel(resizeEventTimeout); |
||||||
|
resizeEventTimeout = $timeout(function() { $scope.$broadcast('render'); }, 200); |
||||||
|
}); |
||||||
|
$scope.$on('$destroy', function() { |
||||||
|
angular.element(window).unbind('resize'); |
||||||
|
}); |
||||||
|
}; |
||||||
|
|
||||||
|
$scope.timezoneChanged = function() { |
||||||
|
$rootScope.$broadcast("refresh"); |
||||||
|
}; |
||||||
|
|
||||||
|
$scope.formatDate = function(date) { |
||||||
|
return moment(date).format('MMM Do YYYY, h:mm:ss a'); |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
init(dashboard) { |
||||||
|
this.$scope.resetRow(); |
||||||
|
this.$scope.registerWindowResizeEvent(); |
||||||
|
this.$scope.onAppEvent('show-json-editor', this.$scope.showJsonEditor); |
||||||
|
this.$scope.onAppEvent('template-variable-value-updated', this.$scope.templateVariableUpdated); |
||||||
|
this.$scope.setupDashboard(dashboard); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
coreModule.controller('DashboardCtrl', DashboardCtrl); |
||||||
@ -1,181 +0,0 @@ |
|||||||
define([ |
|
||||||
'angular', |
|
||||||
'lodash', |
|
||||||
], |
|
||||||
function (angular, _) { |
|
||||||
'use strict'; |
|
||||||
|
|
||||||
var module = angular.module('grafana.services'); |
|
||||||
|
|
||||||
module.service('dynamicDashboardSrv', function() { |
|
||||||
var self = this; |
|
||||||
|
|
||||||
this.init = function(dashboard) { |
|
||||||
if (dashboard.snapshot) { return; } |
|
||||||
|
|
||||||
this.iteration = new Date().getTime(); |
|
||||||
this.process(dashboard); |
|
||||||
}; |
|
||||||
|
|
||||||
this.update = function(dashboard) { |
|
||||||
if (dashboard.snapshot) { return; } |
|
||||||
|
|
||||||
this.iteration = this.iteration + 1; |
|
||||||
this.process(dashboard); |
|
||||||
}; |
|
||||||
|
|
||||||
this.process = function(dashboard) { |
|
||||||
if (dashboard.templating.list.length === 0) { return; } |
|
||||||
this.dashboard = dashboard; |
|
||||||
|
|
||||||
var i, j, row, panel; |
|
||||||
for (i = 0; i < this.dashboard.rows.length; i++) { |
|
||||||
row = this.dashboard.rows[i]; |
|
||||||
// handle row repeats
|
|
||||||
if (row.repeat) { |
|
||||||
this.repeatRow(row, i); |
|
||||||
} |
|
||||||
// clean up old left overs
|
|
||||||
else if (row.repeatRowId && row.repeatIteration !== this.iteration) { |
|
||||||
this.dashboard.rows.splice(i, 1); |
|
||||||
i = i - 1; |
|
||||||
continue; |
|
||||||
} |
|
||||||
|
|
||||||
// repeat panels
|
|
||||||
for (j = 0; j < row.panels.length; j++) { |
|
||||||
panel = row.panels[j]; |
|
||||||
if (panel.repeat) { |
|
||||||
this.repeatPanel(panel, row); |
|
||||||
} |
|
||||||
// clean up old left overs
|
|
||||||
else if (panel.repeatPanelId && panel.repeatIteration !== this.iteration) { |
|
||||||
row.panels = _.without(row.panels, panel); |
|
||||||
j = j - 1; |
|
||||||
} else if (!_.isEmpty(panel.scopedVars) && panel.repeatIteration !== this.iteration) { |
|
||||||
panel.scopedVars = {}; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
// returns a new row clone or reuses a clone from previous iteration
|
|
||||||
this.getRowClone = function(sourceRow, repeatIndex, sourceRowIndex) { |
|
||||||
if (repeatIndex === 0) { |
|
||||||
return sourceRow; |
|
||||||
} |
|
||||||
|
|
||||||
var i, panel, row, copy; |
|
||||||
var sourceRowId = sourceRowIndex + 1; |
|
||||||
|
|
||||||
// look for row to reuse
|
|
||||||
for (i = 0; i < this.dashboard.rows.length; i++) { |
|
||||||
row = this.dashboard.rows[i]; |
|
||||||
if (row.repeatRowId === sourceRowId && row.repeatIteration !== this.iteration) { |
|
||||||
copy = row; |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
if (!copy) { |
|
||||||
copy = angular.copy(sourceRow); |
|
||||||
this.dashboard.rows.splice(sourceRowIndex + repeatIndex, 0, copy); |
|
||||||
|
|
||||||
// set new panel ids
|
|
||||||
for (i = 0; i < copy.panels.length; i++) { |
|
||||||
panel = copy.panels[i]; |
|
||||||
panel.id = this.dashboard.getNextPanelId(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
copy.repeat = null; |
|
||||||
copy.repeatRowId = sourceRowId; |
|
||||||
copy.repeatIteration = this.iteration; |
|
||||||
return copy; |
|
||||||
}; |
|
||||||
|
|
||||||
// returns a new row clone or reuses a clone from previous iteration
|
|
||||||
this.repeatRow = function(row, rowIndex) { |
|
||||||
var variables = this.dashboard.templating.list; |
|
||||||
var variable = _.findWhere(variables, {name: row.repeat}); |
|
||||||
if (!variable) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
var selected, copy, i, panel; |
|
||||||
if (variable.current.text === 'All') { |
|
||||||
selected = variable.options.slice(1, variable.options.length); |
|
||||||
} else { |
|
||||||
selected = _.filter(variable.options, {selected: true}); |
|
||||||
} |
|
||||||
|
|
||||||
_.each(selected, function(option, index) { |
|
||||||
copy = self.getRowClone(row, index, rowIndex); |
|
||||||
copy.scopedVars = {}; |
|
||||||
copy.scopedVars[variable.name] = option; |
|
||||||
|
|
||||||
for (i = 0; i < copy.panels.length; i++) { |
|
||||||
panel = copy.panels[i]; |
|
||||||
panel.scopedVars = {}; |
|
||||||
panel.scopedVars[variable.name] = option; |
|
||||||
panel.repeatIteration = this.iteration; |
|
||||||
} |
|
||||||
}, this); |
|
||||||
}; |
|
||||||
|
|
||||||
this.getPanelClone = function(sourcePanel, row, index) { |
|
||||||
// if first clone return source
|
|
||||||
if (index === 0) { |
|
||||||
return sourcePanel; |
|
||||||
} |
|
||||||
|
|
||||||
var i, tmpId, panel, clone; |
|
||||||
|
|
||||||
// first try finding an existing clone to use
|
|
||||||
for (i = 0; i < row.panels.length; i++) { |
|
||||||
panel = row.panels[i]; |
|
||||||
if (panel.repeatIteration !== this.iteration && panel.repeatPanelId === sourcePanel.id) { |
|
||||||
clone = panel; |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
if (!clone) { |
|
||||||
clone = { id: this.dashboard.getNextPanelId() }; |
|
||||||
row.panels.push(clone); |
|
||||||
} |
|
||||||
|
|
||||||
// save id
|
|
||||||
tmpId = clone.id; |
|
||||||
// copy properties from source
|
|
||||||
angular.copy(sourcePanel, clone); |
|
||||||
// restore id
|
|
||||||
clone.id = tmpId; |
|
||||||
clone.repeatIteration = this.iteration; |
|
||||||
clone.repeatPanelId = sourcePanel.id; |
|
||||||
clone.repeat = null; |
|
||||||
return clone; |
|
||||||
}; |
|
||||||
|
|
||||||
this.repeatPanel = function(panel, row) { |
|
||||||
var variables = this.dashboard.templating.list; |
|
||||||
var variable = _.findWhere(variables, {name: panel.repeat}); |
|
||||||
if (!variable) { return; } |
|
||||||
|
|
||||||
var selected; |
|
||||||
if (variable.current.text === 'All') { |
|
||||||
selected = variable.options.slice(1, variable.options.length); |
|
||||||
} else { |
|
||||||
selected = _.filter(variable.options, {selected: true}); |
|
||||||
} |
|
||||||
|
|
||||||
_.each(selected, function(option, index) { |
|
||||||
var copy = self.getPanelClone(panel, row, index); |
|
||||||
copy.span = Math.max(12 / selected.length, panel.minSpan); |
|
||||||
copy.scopedVars = copy.scopedVars || {}; |
|
||||||
copy.scopedVars[variable.name] = option; |
|
||||||
}); |
|
||||||
}; |
|
||||||
|
|
||||||
}); |
|
||||||
}); |
|
||||||
@ -0,0 +1,175 @@ |
|||||||
|
///<reference path="../../headers/common.d.ts" />
|
||||||
|
|
||||||
|
import config from 'app/core/config'; |
||||||
|
import angular from 'angular'; |
||||||
|
import _ from 'lodash'; |
||||||
|
|
||||||
|
export class DynamicDashboardSrv { |
||||||
|
iteration: number; |
||||||
|
dashboard: any; |
||||||
|
|
||||||
|
init(dashboard) { |
||||||
|
if (dashboard.snapshot) { return; } |
||||||
|
|
||||||
|
this.iteration = new Date().getTime(); |
||||||
|
this.process(dashboard); |
||||||
|
} |
||||||
|
|
||||||
|
update(dashboard) { |
||||||
|
if (dashboard.snapshot) { return; } |
||||||
|
|
||||||
|
this.iteration = this.iteration + 1; |
||||||
|
this.process(dashboard); |
||||||
|
} |
||||||
|
|
||||||
|
process(dashboard) { |
||||||
|
if (dashboard.templating.list.length === 0) { return; } |
||||||
|
this.dashboard = dashboard; |
||||||
|
|
||||||
|
var i, j, row, panel; |
||||||
|
for (i = 0; i < this.dashboard.rows.length; i++) { |
||||||
|
row = this.dashboard.rows[i]; |
||||||
|
// handle row repeats
|
||||||
|
if (row.repeat) { |
||||||
|
this.repeatRow(row, i); |
||||||
|
} else if (row.repeatRowId && row.repeatIteration !== this.iteration) { |
||||||
|
// clean up old left overs
|
||||||
|
this.dashboard.rows.splice(i, 1); |
||||||
|
i = i - 1; |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
// repeat panels
|
||||||
|
for (j = 0; j < row.panels.length; j++) { |
||||||
|
panel = row.panels[j]; |
||||||
|
if (panel.repeat) { |
||||||
|
this.repeatPanel(panel, row); |
||||||
|
} else if (panel.repeatPanelId && panel.repeatIteration !== this.iteration) { |
||||||
|
// clean up old left overs
|
||||||
|
row.panels = _.without(row.panels, panel); |
||||||
|
j = j - 1; |
||||||
|
} else if (!_.isEmpty(panel.scopedVars) && panel.repeatIteration !== this.iteration) { |
||||||
|
panel.scopedVars = {}; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// returns a new row clone or reuses a clone from previous iteration
|
||||||
|
getRowClone(sourceRow, repeatIndex, sourceRowIndex) { |
||||||
|
if (repeatIndex === 0) { |
||||||
|
return sourceRow; |
||||||
|
} |
||||||
|
|
||||||
|
var i, panel, row, copy; |
||||||
|
var sourceRowId = sourceRowIndex + 1; |
||||||
|
|
||||||
|
// look for row to reuse
|
||||||
|
for (i = 0; i < this.dashboard.rows.length; i++) { |
||||||
|
row = this.dashboard.rows[i]; |
||||||
|
if (row.repeatRowId === sourceRowId && row.repeatIteration !== this.iteration) { |
||||||
|
copy = row; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (!copy) { |
||||||
|
copy = angular.copy(sourceRow); |
||||||
|
this.dashboard.rows.splice(sourceRowIndex + repeatIndex, 0, copy); |
||||||
|
|
||||||
|
// set new panel ids
|
||||||
|
for (i = 0; i < copy.panels.length; i++) { |
||||||
|
panel = copy.panels[i]; |
||||||
|
panel.id = this.dashboard.getNextPanelId(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
copy.repeat = null; |
||||||
|
copy.repeatRowId = sourceRowId; |
||||||
|
copy.repeatIteration = this.iteration; |
||||||
|
return copy; |
||||||
|
} |
||||||
|
|
||||||
|
// returns a new row clone or reuses a clone from previous iteration
|
||||||
|
repeatRow(row, rowIndex) { |
||||||
|
var variables = this.dashboard.templating.list; |
||||||
|
var variable = _.findWhere(variables, {name: row.repeat}); |
||||||
|
if (!variable) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
var selected, copy, i, panel; |
||||||
|
if (variable.current.text === 'All') { |
||||||
|
selected = variable.options.slice(1, variable.options.length); |
||||||
|
} else { |
||||||
|
selected = _.filter(variable.options, {selected: true}); |
||||||
|
} |
||||||
|
|
||||||
|
_.each(selected, (option, index) => { |
||||||
|
copy = this.getRowClone(row, index, rowIndex); |
||||||
|
copy.scopedVars = {}; |
||||||
|
copy.scopedVars[variable.name] = option; |
||||||
|
|
||||||
|
for (i = 0; i < copy.panels.length; i++) { |
||||||
|
panel = copy.panels[i]; |
||||||
|
panel.scopedVars = {}; |
||||||
|
panel.scopedVars[variable.name] = option; |
||||||
|
panel.repeatIteration = this.iteration; |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
getPanelClone(sourcePanel, row, index) { |
||||||
|
// if first clone return source
|
||||||
|
if (index === 0) { |
||||||
|
return sourcePanel; |
||||||
|
} |
||||||
|
|
||||||
|
var i, tmpId, panel, clone; |
||||||
|
|
||||||
|
// first try finding an existing clone to use
|
||||||
|
for (i = 0; i < row.panels.length; i++) { |
||||||
|
panel = row.panels[i]; |
||||||
|
if (panel.repeatIteration !== this.iteration && panel.repeatPanelId === sourcePanel.id) { |
||||||
|
clone = panel; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (!clone) { |
||||||
|
clone = { id: this.dashboard.getNextPanelId() }; |
||||||
|
row.panels.push(clone); |
||||||
|
} |
||||||
|
|
||||||
|
// save id
|
||||||
|
tmpId = clone.id; |
||||||
|
// copy properties from source
|
||||||
|
angular.copy(sourcePanel, clone); |
||||||
|
// restore id
|
||||||
|
clone.id = tmpId; |
||||||
|
clone.repeatIteration = this.iteration; |
||||||
|
clone.repeatPanelId = sourcePanel.id; |
||||||
|
clone.repeat = null; |
||||||
|
return clone; |
||||||
|
} |
||||||
|
|
||||||
|
repeatPanel(panel, row) { |
||||||
|
var variables = this.dashboard.templating.list; |
||||||
|
var variable = _.findWhere(variables, {name: panel.repeat}); |
||||||
|
if (!variable) { return; } |
||||||
|
|
||||||
|
var selected; |
||||||
|
if (variable.current.text === 'All') { |
||||||
|
selected = variable.options.slice(1, variable.options.length); |
||||||
|
} else { |
||||||
|
selected = _.filter(variable.options, {selected: true}); |
||||||
|
} |
||||||
|
|
||||||
|
_.each(selected, (option, index) => { |
||||||
|
var copy = this.getPanelClone(panel, row, index); |
||||||
|
copy.span = Math.max(12 / selected.length, panel.minSpan); |
||||||
|
copy.scopedVars = copy.scopedVars || {}; |
||||||
|
copy.scopedVars[variable.name] = option; |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
@ -1,267 +0,0 @@ |
|||||||
define([ |
|
||||||
'app/features/dashboard/dynamicDashboardSrv', |
|
||||||
'app/features/dashboard/dashboardSrv' |
|
||||||
], function() { |
|
||||||
'use strict'; |
|
||||||
|
|
||||||
function dynamicDashScenario(desc, func) { |
|
||||||
|
|
||||||
describe(desc, function() { |
|
||||||
var ctx = {}; |
|
||||||
|
|
||||||
ctx.setup = function (setupFunc) { |
|
||||||
|
|
||||||
beforeEach(module('grafana.services')); |
|
||||||
beforeEach(module(function($provide) { |
|
||||||
$provide.value('contextSrv', { |
|
||||||
user: { timezone: 'utc'} |
|
||||||
}); |
|
||||||
})); |
|
||||||
|
|
||||||
beforeEach(inject(function(dynamicDashboardSrv, dashboardSrv) { |
|
||||||
ctx.dynamicDashboardSrv = dynamicDashboardSrv; |
|
||||||
ctx.dashboardSrv = dashboardSrv; |
|
||||||
|
|
||||||
var model = { |
|
||||||
rows: [], |
|
||||||
templating: { list: [] } |
|
||||||
}; |
|
||||||
|
|
||||||
setupFunc(model); |
|
||||||
ctx.dash = ctx.dashboardSrv.create(model); |
|
||||||
ctx.dynamicDashboardSrv.init(ctx.dash); |
|
||||||
ctx.rows = ctx.dash.rows; |
|
||||||
})); |
|
||||||
}; |
|
||||||
|
|
||||||
func(ctx); |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
dynamicDashScenario('given dashboard with panel repeat', function(ctx) { |
|
||||||
ctx.setup(function(dash) { |
|
||||||
dash.rows.push({ |
|
||||||
panels: [{id: 2, repeat: 'apps'}] |
|
||||||
}); |
|
||||||
dash.templating.list.push({ |
|
||||||
name: 'apps', |
|
||||||
current: { |
|
||||||
text: 'se1, se2, se3', |
|
||||||
value: ['se1', 'se2', 'se3'] |
|
||||||
}, |
|
||||||
options: [ |
|
||||||
{text: 'se1', value: 'se1', selected: true}, |
|
||||||
{text: 'se2', value: 'se2', selected: true}, |
|
||||||
{text: 'se3', value: 'se3', selected: true}, |
|
||||||
{text: 'se4', value: 'se4', selected: false} |
|
||||||
] |
|
||||||
}); |
|
||||||
}); |
|
||||||
|
|
||||||
it('should repeat panel one time', function() { |
|
||||||
expect(ctx.rows[0].panels.length).to.be(3); |
|
||||||
}); |
|
||||||
|
|
||||||
it('should mark panel repeated', function() { |
|
||||||
expect(ctx.rows[0].panels[0].repeat).to.be('apps'); |
|
||||||
expect(ctx.rows[0].panels[1].repeatPanelId).to.be(2); |
|
||||||
}); |
|
||||||
|
|
||||||
it('should set scopedVars on panels', function() { |
|
||||||
expect(ctx.rows[0].panels[0].scopedVars.apps.value).to.be('se1'); |
|
||||||
expect(ctx.rows[0].panels[1].scopedVars.apps.value).to.be('se2'); |
|
||||||
expect(ctx.rows[0].panels[2].scopedVars.apps.value).to.be('se3'); |
|
||||||
}); |
|
||||||
|
|
||||||
describe('After a second iteration', function() { |
|
||||||
var repeatedPanelAfterIteration1; |
|
||||||
|
|
||||||
beforeEach(function() { |
|
||||||
repeatedPanelAfterIteration1 = ctx.rows[0].panels[1]; |
|
||||||
ctx.rows[0].panels[0].fill = 10; |
|
||||||
ctx.dynamicDashboardSrv.update(ctx.dash); |
|
||||||
}); |
|
||||||
|
|
||||||
it('should have reused same panel instances', function() { |
|
||||||
expect(ctx.rows[0].panels[1]).to.be(repeatedPanelAfterIteration1); |
|
||||||
}); |
|
||||||
|
|
||||||
it('reused panel should copy properties from source', function() { |
|
||||||
expect(ctx.rows[0].panels[1].fill).to.be(10); |
|
||||||
}); |
|
||||||
|
|
||||||
it('should have same panel count', function() { |
|
||||||
expect(ctx.rows[0].panels.length).to.be(3); |
|
||||||
}); |
|
||||||
}); |
|
||||||
|
|
||||||
describe('After a second iteration and selected values reduced', function() { |
|
||||||
beforeEach(function() { |
|
||||||
ctx.dash.templating.list[0].options[1].selected = false; |
|
||||||
|
|
||||||
ctx.dynamicDashboardSrv.update(ctx.dash); |
|
||||||
}); |
|
||||||
|
|
||||||
it('should clean up repeated panel', function() { |
|
||||||
expect(ctx.rows[0].panels.length).to.be(2); |
|
||||||
}); |
|
||||||
}); |
|
||||||
|
|
||||||
describe('After a second iteration and panel repeat is turned off', function() { |
|
||||||
beforeEach(function() { |
|
||||||
ctx.rows[0].panels[0].repeat = null; |
|
||||||
ctx.dynamicDashboardSrv.update(ctx.dash); |
|
||||||
}); |
|
||||||
|
|
||||||
it('should clean up repeated panel', function() { |
|
||||||
expect(ctx.rows[0].panels.length).to.be(1); |
|
||||||
}); |
|
||||||
|
|
||||||
it('should remove scoped vars from reused panel', function() { |
|
||||||
expect(ctx.rows[0].panels[0].scopedVars).to.be.empty(); |
|
||||||
}); |
|
||||||
}); |
|
||||||
|
|
||||||
}); |
|
||||||
|
|
||||||
dynamicDashScenario('given dashboard with row repeat', function(ctx) { |
|
||||||
ctx.setup(function(dash) { |
|
||||||
dash.rows.push({ |
|
||||||
repeat: 'servers', |
|
||||||
panels: [{id: 2}] |
|
||||||
}); |
|
||||||
dash.rows.push({panels: []}); |
|
||||||
dash.templating.list.push({ |
|
||||||
name: 'servers', |
|
||||||
current: { |
|
||||||
text: 'se1, se2', |
|
||||||
value: ['se1', 'se2'] |
|
||||||
}, |
|
||||||
options: [ |
|
||||||
{text: 'se1', value: 'se1', selected: true}, |
|
||||||
{text: 'se2', value: 'se2', selected: true}, |
|
||||||
] |
|
||||||
}); |
|
||||||
}); |
|
||||||
|
|
||||||
it('should repeat row one time', function() { |
|
||||||
expect(ctx.rows.length).to.be(3); |
|
||||||
}); |
|
||||||
|
|
||||||
it('should keep panel ids on first row', function() { |
|
||||||
expect(ctx.rows[0].panels[0].id).to.be(2); |
|
||||||
}); |
|
||||||
|
|
||||||
it('should keep first row as repeat', function() { |
|
||||||
expect(ctx.rows[0].repeat).to.be('servers'); |
|
||||||
}); |
|
||||||
|
|
||||||
it('should clear repeat field on repeated row', function() { |
|
||||||
expect(ctx.rows[1].repeat).to.be(null); |
|
||||||
}); |
|
||||||
|
|
||||||
it('should add scopedVars to rows', function() { |
|
||||||
expect(ctx.rows[0].scopedVars.servers.value).to.be('se1'); |
|
||||||
expect(ctx.rows[1].scopedVars.servers.value).to.be('se2'); |
|
||||||
}); |
|
||||||
|
|
||||||
it('should generate a repeartRowId based on repeat row index', function() { |
|
||||||
expect(ctx.rows[1].repeatRowId).to.be(1); |
|
||||||
}); |
|
||||||
|
|
||||||
it('should set scopedVars on row panels', function() { |
|
||||||
expect(ctx.rows[0].panels[0].scopedVars.servers.value).to.be('se1'); |
|
||||||
expect(ctx.rows[1].panels[0].scopedVars.servers.value).to.be('se2'); |
|
||||||
}); |
|
||||||
|
|
||||||
describe('After a second iteration', function() { |
|
||||||
var repeatedRowAfterFirstIteration; |
|
||||||
|
|
||||||
beforeEach(function() { |
|
||||||
repeatedRowAfterFirstIteration = ctx.rows[1]; |
|
||||||
ctx.rows[0].height = 500; |
|
||||||
ctx.dynamicDashboardSrv.update(ctx.dash); |
|
||||||
}); |
|
||||||
|
|
||||||
it('should still only have 2 rows', function() { |
|
||||||
expect(ctx.rows.length).to.be(3); |
|
||||||
}); |
|
||||||
|
|
||||||
it.skip('should have updated props from source', function() { |
|
||||||
expect(ctx.rows[1].height).to.be(500); |
|
||||||
}); |
|
||||||
|
|
||||||
it('should reuse row instance', function() { |
|
||||||
expect(ctx.rows[1]).to.be(repeatedRowAfterFirstIteration); |
|
||||||
}); |
|
||||||
}); |
|
||||||
|
|
||||||
describe('After a second iteration and selected values reduced', function() { |
|
||||||
beforeEach(function() { |
|
||||||
ctx.dash.templating.list[0].options[1].selected = false; |
|
||||||
ctx.dynamicDashboardSrv.update(ctx.dash); |
|
||||||
}); |
|
||||||
|
|
||||||
it('should remove repeated second row', function() { |
|
||||||
expect(ctx.rows.length).to.be(2); |
|
||||||
}); |
|
||||||
}); |
|
||||||
}); |
|
||||||
|
|
||||||
dynamicDashScenario('given dashboard with row repeat and panel repeat', function(ctx) { |
|
||||||
ctx.setup(function(dash) { |
|
||||||
dash.rows.push({ |
|
||||||
repeat: 'servers', |
|
||||||
panels: [{id: 2, repeat: 'metric'}] |
|
||||||
}); |
|
||||||
dash.templating.list.push({ |
|
||||||
name: 'servers', |
|
||||||
current: { text: 'se1, se2', value: ['se1', 'se2'] }, |
|
||||||
options: [ |
|
||||||
{text: 'se1', value: 'se1', selected: true}, |
|
||||||
{text: 'se2', value: 'se2', selected: true}, |
|
||||||
] |
|
||||||
}); |
|
||||||
dash.templating.list.push({ |
|
||||||
name: 'metric', |
|
||||||
current: { text: 'm1, m2', value: ['m1', 'm2'] }, |
|
||||||
options: [ |
|
||||||
{text: 'm1', value: 'm1', selected: true}, |
|
||||||
{text: 'm2', value: 'm2', selected: true}, |
|
||||||
] |
|
||||||
}); |
|
||||||
}); |
|
||||||
|
|
||||||
it('should repeat row one time', function() { |
|
||||||
expect(ctx.rows.length).to.be(2); |
|
||||||
}); |
|
||||||
|
|
||||||
it('should repeat panel on both rows', function() { |
|
||||||
expect(ctx.rows[0].panels.length).to.be(2); |
|
||||||
expect(ctx.rows[1].panels.length).to.be(2); |
|
||||||
}); |
|
||||||
|
|
||||||
it('should keep panel ids on first row', function() { |
|
||||||
expect(ctx.rows[0].panels[0].id).to.be(2); |
|
||||||
}); |
|
||||||
|
|
||||||
it('should mark second row as repeated', function() { |
|
||||||
expect(ctx.rows[0].repeat).to.be('servers'); |
|
||||||
}); |
|
||||||
|
|
||||||
it('should clear repeat field on repeated row', function() { |
|
||||||
expect(ctx.rows[1].repeat).to.be(null); |
|
||||||
}); |
|
||||||
|
|
||||||
it('should generate a repeartRowId based on repeat row index', function() { |
|
||||||
expect(ctx.rows[1].repeatRowId).to.be(1); |
|
||||||
}); |
|
||||||
|
|
||||||
it('should set scopedVars on row panels', function() { |
|
||||||
expect(ctx.rows[0].panels[0].scopedVars.servers.value).to.be('se1'); |
|
||||||
expect(ctx.rows[1].panels[0].scopedVars.servers.value).to.be('se2'); |
|
||||||
}); |
|
||||||
|
|
||||||
}); |
|
||||||
|
|
||||||
}); |
|
||||||
@ -0,0 +1,264 @@ |
|||||||
|
import {describe, beforeEach, it, sinon, expect, angularMocks} from 'test/lib/common'; |
||||||
|
|
||||||
|
import 'app/features/dashboard/dashboardSrv'; |
||||||
|
import {DynamicDashboardSrv} from '../../app/features/dashboard/dynamic_dashboard_srv'; |
||||||
|
|
||||||
|
function dynamicDashScenario(desc, func) { |
||||||
|
|
||||||
|
describe(desc, function() { |
||||||
|
var ctx: any = {}; |
||||||
|
|
||||||
|
ctx.setup = function (setupFunc) { |
||||||
|
|
||||||
|
beforeEach(angularMocks.module('grafana.services')); |
||||||
|
beforeEach(angularMocks.module(function($provide) { |
||||||
|
$provide.value('contextSrv', { |
||||||
|
user: { timezone: 'utc'} |
||||||
|
}); |
||||||
|
})); |
||||||
|
|
||||||
|
beforeEach(angularMocks.inject(function(dashboardSrv) { |
||||||
|
ctx.dashboardSrv = dashboardSrv; |
||||||
|
var model = { |
||||||
|
rows: [], |
||||||
|
templating: { list: [] } |
||||||
|
}; |
||||||
|
|
||||||
|
setupFunc(model); |
||||||
|
ctx.dash = ctx.dashboardSrv.create(model); |
||||||
|
ctx.dynamicDashboardSrv = new DynamicDashboardSrv(); |
||||||
|
ctx.dynamicDashboardSrv.init(ctx.dash); |
||||||
|
ctx.rows = ctx.dash.rows; |
||||||
|
})); |
||||||
|
}; |
||||||
|
|
||||||
|
func(ctx); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
dynamicDashScenario('given dashboard with panel repeat', function(ctx) { |
||||||
|
ctx.setup(function(dash) { |
||||||
|
dash.rows.push({ |
||||||
|
panels: [{id: 2, repeat: 'apps'}] |
||||||
|
}); |
||||||
|
dash.templating.list.push({ |
||||||
|
name: 'apps', |
||||||
|
current: { |
||||||
|
text: 'se1, se2, se3', |
||||||
|
value: ['se1', 'se2', 'se3'] |
||||||
|
}, |
||||||
|
options: [ |
||||||
|
{text: 'se1', value: 'se1', selected: true}, |
||||||
|
{text: 'se2', value: 'se2', selected: true}, |
||||||
|
{text: 'se3', value: 'se3', selected: true}, |
||||||
|
{text: 'se4', value: 'se4', selected: false} |
||||||
|
] |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should repeat panel one time', function() { |
||||||
|
expect(ctx.rows[0].panels.length).to.be(3); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should mark panel repeated', function() { |
||||||
|
expect(ctx.rows[0].panels[0].repeat).to.be('apps'); |
||||||
|
expect(ctx.rows[0].panels[1].repeatPanelId).to.be(2); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should set scopedVars on panels', function() { |
||||||
|
expect(ctx.rows[0].panels[0].scopedVars.apps.value).to.be('se1'); |
||||||
|
expect(ctx.rows[0].panels[1].scopedVars.apps.value).to.be('se2'); |
||||||
|
expect(ctx.rows[0].panels[2].scopedVars.apps.value).to.be('se3'); |
||||||
|
}); |
||||||
|
|
||||||
|
describe('After a second iteration', function() { |
||||||
|
var repeatedPanelAfterIteration1; |
||||||
|
|
||||||
|
beforeEach(function() { |
||||||
|
repeatedPanelAfterIteration1 = ctx.rows[0].panels[1]; |
||||||
|
ctx.rows[0].panels[0].fill = 10; |
||||||
|
ctx.dynamicDashboardSrv.update(ctx.dash); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should have reused same panel instances', function() { |
||||||
|
expect(ctx.rows[0].panels[1]).to.be(repeatedPanelAfterIteration1); |
||||||
|
}); |
||||||
|
|
||||||
|
it('reused panel should copy properties from source', function() { |
||||||
|
expect(ctx.rows[0].panels[1].fill).to.be(10); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should have same panel count', function() { |
||||||
|
expect(ctx.rows[0].panels.length).to.be(3); |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
describe('After a second iteration and selected values reduced', function() { |
||||||
|
beforeEach(function() { |
||||||
|
ctx.dash.templating.list[0].options[1].selected = false; |
||||||
|
|
||||||
|
ctx.dynamicDashboardSrv.update(ctx.dash); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should clean up repeated panel', function() { |
||||||
|
expect(ctx.rows[0].panels.length).to.be(2); |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
describe('After a second iteration and panel repeat is turned off', function() { |
||||||
|
beforeEach(function() { |
||||||
|
ctx.rows[0].panels[0].repeat = null; |
||||||
|
ctx.dynamicDashboardSrv.update(ctx.dash); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should clean up repeated panel', function() { |
||||||
|
expect(ctx.rows[0].panels.length).to.be(1); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should remove scoped vars from reused panel', function() { |
||||||
|
expect(ctx.rows[0].panels[0].scopedVars).to.be.empty(); |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
}); |
||||||
|
|
||||||
|
dynamicDashScenario('given dashboard with row repeat', function(ctx) { |
||||||
|
ctx.setup(function(dash) { |
||||||
|
dash.rows.push({ |
||||||
|
repeat: 'servers', |
||||||
|
panels: [{id: 2}] |
||||||
|
}); |
||||||
|
dash.rows.push({panels: []}); |
||||||
|
dash.templating.list.push({ |
||||||
|
name: 'servers', |
||||||
|
current: { |
||||||
|
text: 'se1, se2', |
||||||
|
value: ['se1', 'se2'] |
||||||
|
}, |
||||||
|
options: [ |
||||||
|
{text: 'se1', value: 'se1', selected: true}, |
||||||
|
{text: 'se2', value: 'se2', selected: true}, |
||||||
|
] |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should repeat row one time', function() { |
||||||
|
expect(ctx.rows.length).to.be(3); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should keep panel ids on first row', function() { |
||||||
|
expect(ctx.rows[0].panels[0].id).to.be(2); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should keep first row as repeat', function() { |
||||||
|
expect(ctx.rows[0].repeat).to.be('servers'); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should clear repeat field on repeated row', function() { |
||||||
|
expect(ctx.rows[1].repeat).to.be(null); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should add scopedVars to rows', function() { |
||||||
|
expect(ctx.rows[0].scopedVars.servers.value).to.be('se1'); |
||||||
|
expect(ctx.rows[1].scopedVars.servers.value).to.be('se2'); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should generate a repeartRowId based on repeat row index', function() { |
||||||
|
expect(ctx.rows[1].repeatRowId).to.be(1); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should set scopedVars on row panels', function() { |
||||||
|
expect(ctx.rows[0].panels[0].scopedVars.servers.value).to.be('se1'); |
||||||
|
expect(ctx.rows[1].panels[0].scopedVars.servers.value).to.be('se2'); |
||||||
|
}); |
||||||
|
|
||||||
|
describe('After a second iteration', function() { |
||||||
|
var repeatedRowAfterFirstIteration; |
||||||
|
|
||||||
|
beforeEach(function() { |
||||||
|
repeatedRowAfterFirstIteration = ctx.rows[1]; |
||||||
|
ctx.rows[0].height = 500; |
||||||
|
ctx.dynamicDashboardSrv.update(ctx.dash); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should still only have 2 rows', function() { |
||||||
|
expect(ctx.rows.length).to.be(3); |
||||||
|
}); |
||||||
|
|
||||||
|
it.skip('should have updated props from source', function() { |
||||||
|
expect(ctx.rows[1].height).to.be(500); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should reuse row instance', function() { |
||||||
|
expect(ctx.rows[1]).to.be(repeatedRowAfterFirstIteration); |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
describe('After a second iteration and selected values reduced', function() { |
||||||
|
beforeEach(function() { |
||||||
|
ctx.dash.templating.list[0].options[1].selected = false; |
||||||
|
ctx.dynamicDashboardSrv.update(ctx.dash); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should remove repeated second row', function() { |
||||||
|
expect(ctx.rows.length).to.be(2); |
||||||
|
}); |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
dynamicDashScenario('given dashboard with row repeat and panel repeat', function(ctx) { |
||||||
|
ctx.setup(function(dash) { |
||||||
|
dash.rows.push({ |
||||||
|
repeat: 'servers', |
||||||
|
panels: [{id: 2, repeat: 'metric'}] |
||||||
|
}); |
||||||
|
dash.templating.list.push({ |
||||||
|
name: 'servers', |
||||||
|
current: { text: 'se1, se2', value: ['se1', 'se2'] }, |
||||||
|
options: [ |
||||||
|
{text: 'se1', value: 'se1', selected: true}, |
||||||
|
{text: 'se2', value: 'se2', selected: true}, |
||||||
|
] |
||||||
|
}); |
||||||
|
dash.templating.list.push({ |
||||||
|
name: 'metric', |
||||||
|
current: { text: 'm1, m2', value: ['m1', 'm2'] }, |
||||||
|
options: [ |
||||||
|
{text: 'm1', value: 'm1', selected: true}, |
||||||
|
{text: 'm2', value: 'm2', selected: true}, |
||||||
|
] |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should repeat row one time', function() { |
||||||
|
expect(ctx.rows.length).to.be(2); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should repeat panel on both rows', function() { |
||||||
|
expect(ctx.rows[0].panels.length).to.be(2); |
||||||
|
expect(ctx.rows[1].panels.length).to.be(2); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should keep panel ids on first row', function() { |
||||||
|
expect(ctx.rows[0].panels[0].id).to.be(2); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should mark second row as repeated', function() { |
||||||
|
expect(ctx.rows[0].repeat).to.be('servers'); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should clear repeat field on repeated row', function() { |
||||||
|
expect(ctx.rows[1].repeat).to.be(null); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should generate a repeartRowId based on repeat row index', function() { |
||||||
|
expect(ctx.rows[1].repeatRowId).to.be(1); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should set scopedVars on row panels', function() { |
||||||
|
expect(ctx.rows[0].panels[0].scopedVars.servers.value).to.be('se1'); |
||||||
|
expect(ctx.rows[1].panels[0].scopedVars.servers.value).to.be('se2'); |
||||||
|
}); |
||||||
|
|
||||||
|
}); |
||||||
|
|
||||||
Loading…
Reference in new issue