mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Merge branch 'master' into react-panels
This commit is contained in:
@@ -30,7 +30,7 @@ export class AdHocFiltersCtrl {
|
||||
if (this.variable.value && !_.isArray(this.variable.value)) {
|
||||
}
|
||||
|
||||
for (let tag of this.variable.filters) {
|
||||
for (const tag of this.variable.filters) {
|
||||
if (this.segments.length > 0) {
|
||||
this.segments.push(this.uiSegmentSrv.newCondition('AND'));
|
||||
}
|
||||
@@ -55,8 +55,8 @@ export class AdHocFiltersCtrl {
|
||||
}
|
||||
|
||||
return this.datasourceSrv.get(this.variable.datasource).then(ds => {
|
||||
var options: any = {};
|
||||
var promise = null;
|
||||
const options: any = {};
|
||||
let promise = null;
|
||||
|
||||
if (segment.type !== 'value') {
|
||||
promise = ds.getTagKeys();
|
||||
@@ -113,9 +113,9 @@ export class AdHocFiltersCtrl {
|
||||
}
|
||||
|
||||
updateVariableModel() {
|
||||
var filters = [];
|
||||
var filterIndex = -1;
|
||||
var hasFakes = false;
|
||||
const filters = [];
|
||||
let filterIndex = -1;
|
||||
let hasFakes = false;
|
||||
|
||||
this.segments.forEach(segment => {
|
||||
if (segment.type === 'value' && segment.fake) {
|
||||
@@ -153,7 +153,7 @@ export class AdHocFiltersCtrl {
|
||||
}
|
||||
}
|
||||
|
||||
var template = `
|
||||
const template = `
|
||||
<div class="gf-form-inline">
|
||||
<div class="gf-form" ng-repeat="segment in ctrl.segments">
|
||||
<metric-segment segment="segment" get-options="ctrl.getOptions(segment, $index)"
|
||||
|
||||
@@ -26,15 +26,15 @@ import './dashgrid/RowOptions';
|
||||
import './folder_picker/folder_picker';
|
||||
import './move_to_folder_modal/move_to_folder';
|
||||
import './settings/settings';
|
||||
import './panellinks/module';
|
||||
import './dashlinks/module';
|
||||
|
||||
import coreModule from 'app/core/core_module';
|
||||
import { DashboardListCtrl } from './dashboard_list_ctrl';
|
||||
import { FolderDashboardsCtrl } from './folder_dashboards_ctrl';
|
||||
import { FolderSettingsCtrl } from './folder_settings_ctrl';
|
||||
import { DashboardImportCtrl } from './dashboard_import_ctrl';
|
||||
import { CreateFolderCtrl } from './create_folder_ctrl';
|
||||
|
||||
coreModule.controller('DashboardListCtrl', DashboardListCtrl);
|
||||
coreModule.controller('FolderDashboardsCtrl', FolderDashboardsCtrl);
|
||||
coreModule.controller('FolderSettingsCtrl', FolderSettingsCtrl);
|
||||
coreModule.controller('DashboardImportCtrl', DashboardImportCtrl);
|
||||
|
||||
@@ -87,20 +87,20 @@ export class ChangeTracker {
|
||||
return true;
|
||||
}
|
||||
|
||||
var meta = this.current.meta;
|
||||
const meta = this.current.meta;
|
||||
return !meta.canSave || meta.fromScript || meta.fromFile;
|
||||
}
|
||||
|
||||
// remove stuff that should not count in diff
|
||||
cleanDashboardFromIgnoredChanges(dashData) {
|
||||
// need to new up the domain model class to get access to expand / collapse row logic
|
||||
let model = new DashboardModel(dashData);
|
||||
const model = new DashboardModel(dashData);
|
||||
|
||||
// Expand all rows before making comparison. This is required because row expand / collapse
|
||||
// change order of panel array and panel positions.
|
||||
model.expandRows();
|
||||
|
||||
let dash = model.getSaveModelClone();
|
||||
const dash = model.getSaveModelClone();
|
||||
|
||||
// ignore time and refresh
|
||||
dash.time = 0;
|
||||
@@ -128,7 +128,7 @@ export class ChangeTracker {
|
||||
});
|
||||
|
||||
// ignore template variable values
|
||||
_.each(dash.templating.list, function(value) {
|
||||
_.each(dash.templating.list, value => {
|
||||
value.current = null;
|
||||
value.options = null;
|
||||
value.filters = null;
|
||||
@@ -138,18 +138,18 @@ export class ChangeTracker {
|
||||
}
|
||||
|
||||
hasChanges() {
|
||||
let current = this.cleanDashboardFromIgnoredChanges(this.current.getSaveModelClone());
|
||||
let original = this.cleanDashboardFromIgnoredChanges(this.original);
|
||||
const current = this.cleanDashboardFromIgnoredChanges(this.current.getSaveModelClone());
|
||||
const original = this.cleanDashboardFromIgnoredChanges(this.original);
|
||||
|
||||
var currentTimepicker = _.find(current.nav, { type: 'timepicker' });
|
||||
var originalTimepicker = _.find(original.nav, { type: 'timepicker' });
|
||||
const currentTimepicker = _.find(current.nav, { type: 'timepicker' });
|
||||
const originalTimepicker = _.find(original.nav, { type: 'timepicker' });
|
||||
|
||||
if (currentTimepicker && originalTimepicker) {
|
||||
currentTimepicker.now = originalTimepicker.now;
|
||||
}
|
||||
|
||||
var currentJson = angular.toJson(current, true);
|
||||
var originalJson = angular.toJson(original, true);
|
||||
const currentJson = angular.toJson(current, true);
|
||||
const originalJson = angular.toJson(original, true);
|
||||
|
||||
return currentJson !== originalJson;
|
||||
}
|
||||
@@ -167,8 +167,8 @@ export class ChangeTracker {
|
||||
}
|
||||
|
||||
saveChanges() {
|
||||
var self = this;
|
||||
var cancel = this.$rootScope.$on('dashboard-saved', () => {
|
||||
const self = this;
|
||||
const cancel = this.$rootScope.$on('dashboard-saved', () => {
|
||||
cancel();
|
||||
this.$timeout(() => {
|
||||
self.gotoNext();
|
||||
@@ -179,8 +179,8 @@ export class ChangeTracker {
|
||||
}
|
||||
|
||||
gotoNext() {
|
||||
var baseLen = this.$location.absUrl().length - this.$location.url().length;
|
||||
var nextUrl = this.next.substring(baseLen);
|
||||
const baseLen = this.$location.absUrl().length - this.$location.url().length;
|
||||
const nextUrl = this.next.substring(baseLen);
|
||||
this.$location.url(nextUrl);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ export class CreateFolderCtrl {
|
||||
hasValidationError: boolean;
|
||||
validationError: any;
|
||||
|
||||
/** @ngInject **/
|
||||
/** @ngInject */
|
||||
constructor(private backendSrv, private $location, private validationSrv, navModelSrv) {
|
||||
this.navModel = navModelSrv.getNav('dashboards', 'manage-dashboards', 0);
|
||||
}
|
||||
|
||||
@@ -100,11 +100,11 @@ export class DashboardCtrl {
|
||||
}
|
||||
|
||||
setWindowTitleAndTheme() {
|
||||
window.document.title = config.window_title_prefix + this.dashboard.title;
|
||||
window.document.title = config.windowTitlePrefix + this.dashboard.title;
|
||||
}
|
||||
|
||||
showJsonEditor(evt, options) {
|
||||
var editScope = this.$rootScope.$new();
|
||||
const editScope = this.$rootScope.$new();
|
||||
editScope.object = options.object;
|
||||
editScope.updateHandler = options.updateHandler;
|
||||
this.$scope.appEvent('show-dash-editor', {
|
||||
@@ -131,14 +131,14 @@ export class DashboardCtrl {
|
||||
return;
|
||||
}
|
||||
|
||||
var panelInfo = this.dashboard.getPanelInfoById(options.panelId);
|
||||
const panelInfo = this.dashboard.getPanelInfoById(options.panelId);
|
||||
this.removePanel(panelInfo.panel, true);
|
||||
}
|
||||
|
||||
removePanel(panel: PanelModel, ask: boolean) {
|
||||
// confirm deletion
|
||||
if (ask !== false) {
|
||||
var text2, confirmText;
|
||||
let text2, confirmText;
|
||||
|
||||
if (panel.alert) {
|
||||
text2 = 'Panel includes an alert rule, removing panel will also remove alert rule';
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import _ from 'lodash';
|
||||
import config from 'app/core/config';
|
||||
import locationUtil from 'app/core/utils/location_util';
|
||||
|
||||
export class DashboardImportCtrl {
|
||||
navModel: any;
|
||||
@@ -51,8 +52,8 @@ export class DashboardImportCtrl {
|
||||
this.inputs = [];
|
||||
|
||||
if (this.dash.__inputs) {
|
||||
for (let input of this.dash.__inputs) {
|
||||
var inputModel = {
|
||||
for (const input of this.dash.__inputs) {
|
||||
const inputModel = {
|
||||
name: input.name,
|
||||
label: input.label,
|
||||
info: input.description,
|
||||
@@ -78,7 +79,7 @@ export class DashboardImportCtrl {
|
||||
}
|
||||
|
||||
setDatasourceOptions(input, inputModel) {
|
||||
var sources = _.filter(config.datasources, val => {
|
||||
const sources = _.filter(config.datasources, val => {
|
||||
return val.type === input.pluginId;
|
||||
});
|
||||
|
||||
@@ -95,7 +96,7 @@ export class DashboardImportCtrl {
|
||||
|
||||
inputValueChanged() {
|
||||
this.inputsValid = true;
|
||||
for (let input of this.inputs) {
|
||||
for (const input of this.inputs) {
|
||||
if (!input.value) {
|
||||
this.inputsValid = false;
|
||||
}
|
||||
@@ -162,7 +163,7 @@ export class DashboardImportCtrl {
|
||||
}
|
||||
|
||||
saveDashboard() {
|
||||
var inputs = this.inputs.map(input => {
|
||||
const inputs = this.inputs.map(input => {
|
||||
return {
|
||||
name: input.name,
|
||||
type: input.type,
|
||||
@@ -179,14 +180,15 @@ export class DashboardImportCtrl {
|
||||
folderId: this.folderId,
|
||||
})
|
||||
.then(res => {
|
||||
this.$location.url(res.importedUrl);
|
||||
const dashUrl = locationUtil.stripBaseFromUrl(res.importedUrl);
|
||||
this.$location.url(dashUrl);
|
||||
});
|
||||
}
|
||||
|
||||
loadJsonText() {
|
||||
try {
|
||||
this.parseError = '';
|
||||
var dash = JSON.parse(this.jsonText);
|
||||
const dash = JSON.parse(this.jsonText);
|
||||
this.onUpload(dash);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
@@ -198,8 +200,8 @@ export class DashboardImportCtrl {
|
||||
checkGnetDashboard() {
|
||||
this.gnetError = '';
|
||||
|
||||
var match = /(^\d+$)|dashboards\/(\d+)/.exec(this.gnetUrl);
|
||||
var dashboardId;
|
||||
const match = /(^\d+$)|dashboards\/(\d+)/.exec(this.gnetUrl);
|
||||
let dashboardId;
|
||||
|
||||
if (match && match[1]) {
|
||||
dashboardId = match[1];
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
export class DashboardListCtrl {
|
||||
navModel: any;
|
||||
|
||||
/** @ngInject */
|
||||
constructor(navModelSrv) {
|
||||
this.navModel = navModelSrv.getNav('dashboards', 'manage-dashboards', 0);
|
||||
}
|
||||
}
|
||||
@@ -36,7 +36,7 @@ export class DashboardLoaderSrv {
|
||||
}
|
||||
|
||||
loadDashboard(type, slug, uid) {
|
||||
var promise;
|
||||
let promise;
|
||||
|
||||
if (type === 'script') {
|
||||
promise = this._loadScriptedDashboard(slug);
|
||||
@@ -59,7 +59,7 @@ export class DashboardLoaderSrv {
|
||||
});
|
||||
}
|
||||
|
||||
promise.then(function(result) {
|
||||
promise.then(result => {
|
||||
if (result.meta.dashboardNotFound !== true) {
|
||||
impressionSrv.addDashboardImpression(result.dashboard.id);
|
||||
}
|
||||
@@ -71,7 +71,7 @@ export class DashboardLoaderSrv {
|
||||
}
|
||||
|
||||
_loadScriptedDashboard(file) {
|
||||
var url = 'public/dashboards/' + file.replace(/\.(?!js)/, '/') + '?' + new Date().getTime();
|
||||
const url = 'public/dashboards/' + file.replace(/\.(?!js)/, '/') + '?' + new Date().getTime();
|
||||
|
||||
return this.$http({ url: url, method: 'GET' })
|
||||
.then(this._executeScript.bind(this))
|
||||
@@ -99,14 +99,14 @@ export class DashboardLoaderSrv {
|
||||
}
|
||||
|
||||
_executeScript(result) {
|
||||
var services = {
|
||||
const services = {
|
||||
dashboardSrv: this.dashboardSrv,
|
||||
datasourceSrv: this.datasourceSrv,
|
||||
$q: this.$q,
|
||||
};
|
||||
|
||||
/*jshint -W054 */
|
||||
var script_func = new Function(
|
||||
const scriptFunc = new Function(
|
||||
'ARGS',
|
||||
'kbn',
|
||||
'dateMath',
|
||||
@@ -119,12 +119,12 @@ export class DashboardLoaderSrv {
|
||||
'services',
|
||||
result.data
|
||||
);
|
||||
var script_result = script_func(this.$routeParams, kbn, dateMath, _, moment, window, document, $, $, services);
|
||||
const scriptResult = scriptFunc(this.$routeParams, kbn, dateMath, _, moment, window, document, $, $, services);
|
||||
|
||||
// Handle async dashboard scripts
|
||||
if (_.isFunction(script_result)) {
|
||||
var deferred = this.$q.defer();
|
||||
script_result(dashboard => {
|
||||
if (_.isFunction(scriptResult)) {
|
||||
const deferred = this.$q.defer();
|
||||
scriptResult(dashboard => {
|
||||
this.$timeout(() => {
|
||||
deferred.resolve({ data: dashboard });
|
||||
});
|
||||
@@ -132,7 +132,7 @@ export class DashboardLoaderSrv {
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
return { data: script_result };
|
||||
return { data: scriptResult };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,9 +18,9 @@ export class DashboardMigrator {
|
||||
}
|
||||
|
||||
updateSchema(old) {
|
||||
var i, j, k, n;
|
||||
var oldVersion = this.dashboard.schemaVersion;
|
||||
var panelUpgrades = [];
|
||||
let i, j, k, n;
|
||||
const oldVersion = this.dashboard.schemaVersion;
|
||||
const panelUpgrades = [];
|
||||
this.dashboard.schemaVersion = 16;
|
||||
|
||||
if (oldVersion === this.dashboard.schemaVersion) {
|
||||
@@ -36,7 +36,7 @@ export class DashboardMigrator {
|
||||
}
|
||||
}
|
||||
|
||||
panelUpgrades.push(function(panel) {
|
||||
panelUpgrades.push(panel => {
|
||||
// rename panel type
|
||||
if (panel.type === 'graphite') {
|
||||
panel.type = 'graph';
|
||||
@@ -83,8 +83,8 @@ export class DashboardMigrator {
|
||||
// schema version 3 changes
|
||||
if (oldVersion < 3) {
|
||||
// ensure panel ids
|
||||
var maxId = this.dashboard.getNextPanelId();
|
||||
panelUpgrades.push(function(panel) {
|
||||
let maxId = this.dashboard.getNextPanelId();
|
||||
panelUpgrades.push(panel => {
|
||||
if (!panel.id) {
|
||||
panel.id = maxId;
|
||||
maxId += 1;
|
||||
@@ -95,11 +95,11 @@ export class DashboardMigrator {
|
||||
// schema version 4 changes
|
||||
if (oldVersion < 4) {
|
||||
// move aliasYAxis changes
|
||||
panelUpgrades.push(function(panel) {
|
||||
panelUpgrades.push(panel => {
|
||||
if (panel.type !== 'graph') {
|
||||
return;
|
||||
}
|
||||
_.each(panel.aliasYAxis, function(value, key) {
|
||||
_.each(panel.aliasYAxis, (value, key) => {
|
||||
panel.seriesOverrides = [{ alias: key, yaxis: value }];
|
||||
});
|
||||
delete panel.aliasYAxis;
|
||||
@@ -108,7 +108,7 @@ export class DashboardMigrator {
|
||||
|
||||
if (oldVersion < 6) {
|
||||
// move pulldowns to new schema
|
||||
var annotations = _.find(old.pulldowns, { type: 'annotations' });
|
||||
const annotations = _.find(old.pulldowns, { type: 'annotations' });
|
||||
|
||||
if (annotations) {
|
||||
this.dashboard.annotations = {
|
||||
@@ -118,7 +118,7 @@ export class DashboardMigrator {
|
||||
|
||||
// update template variables
|
||||
for (i = 0; i < this.dashboard.templating.list.length; i++) {
|
||||
var variable = this.dashboard.templating.list[i];
|
||||
const variable = this.dashboard.templating.list[i];
|
||||
if (variable.datasource === void 0) {
|
||||
variable.datasource = null;
|
||||
}
|
||||
@@ -140,29 +140,26 @@ export class DashboardMigrator {
|
||||
}
|
||||
|
||||
// ensure query refIds
|
||||
panelUpgrades.push(function(panel) {
|
||||
_.each(
|
||||
panel.targets,
|
||||
function(target) {
|
||||
if (!target.refId) {
|
||||
target.refId = this.dashboard.getNextQueryLetter(panel);
|
||||
}
|
||||
}.bind(this)
|
||||
);
|
||||
panelUpgrades.push(panel => {
|
||||
_.each(panel.targets, target => {
|
||||
if (!target.refId) {
|
||||
target.refId = this.dashboard.getNextQueryLetter(panel);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (oldVersion < 8) {
|
||||
panelUpgrades.push(function(panel) {
|
||||
_.each(panel.targets, function(target) {
|
||||
panelUpgrades.push(panel => {
|
||||
_.each(panel.targets, target => {
|
||||
// update old influxdb query schema
|
||||
if (target.fields && target.tags && target.groupBy) {
|
||||
if (target.rawQuery) {
|
||||
delete target.fields;
|
||||
delete target.fill;
|
||||
} else {
|
||||
target.select = _.map(target.fields, function(field) {
|
||||
var parts = [];
|
||||
target.select = _.map(target.fields, field => {
|
||||
const parts = [];
|
||||
parts.push({ type: 'field', params: [field.name] });
|
||||
parts.push({ type: field.func, params: [] });
|
||||
if (field.mathExpr) {
|
||||
@@ -174,7 +171,7 @@ export class DashboardMigrator {
|
||||
return parts;
|
||||
});
|
||||
delete target.fields;
|
||||
_.each(target.groupBy, function(part) {
|
||||
_.each(target.groupBy, part => {
|
||||
if (part.type === 'time' && part.interval) {
|
||||
part.params = [part.interval];
|
||||
delete part.interval;
|
||||
@@ -198,13 +195,13 @@ export class DashboardMigrator {
|
||||
// schema version 9 changes
|
||||
if (oldVersion < 9) {
|
||||
// move aliasYAxis changes
|
||||
panelUpgrades.push(function(panel) {
|
||||
panelUpgrades.push(panel => {
|
||||
if (panel.type !== 'singlestat' && panel.thresholds !== '') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (panel.thresholds) {
|
||||
var k = panel.thresholds.split(',');
|
||||
const k = panel.thresholds.split(',');
|
||||
|
||||
if (k.length >= 3) {
|
||||
k.shift();
|
||||
@@ -217,14 +214,14 @@ export class DashboardMigrator {
|
||||
// schema version 10 changes
|
||||
if (oldVersion < 10) {
|
||||
// move aliasYAxis changes
|
||||
panelUpgrades.push(function(panel) {
|
||||
panelUpgrades.push(panel => {
|
||||
if (panel.type !== 'table') {
|
||||
return;
|
||||
}
|
||||
|
||||
_.each(panel.styles, function(style) {
|
||||
_.each(panel.styles, style => {
|
||||
if (style.thresholds && style.thresholds.length >= 3) {
|
||||
var k = style.thresholds;
|
||||
const k = style.thresholds;
|
||||
k.shift();
|
||||
style.thresholds = k;
|
||||
}
|
||||
@@ -234,7 +231,7 @@ export class DashboardMigrator {
|
||||
|
||||
if (oldVersion < 12) {
|
||||
// update template variables
|
||||
_.each(this.dashboard.templating.list, function(templateVariable) {
|
||||
_.each(this.dashboard.templating.list, templateVariable => {
|
||||
if (templateVariable.refresh) {
|
||||
templateVariable.refresh = 1;
|
||||
}
|
||||
@@ -251,7 +248,7 @@ export class DashboardMigrator {
|
||||
|
||||
if (oldVersion < 12) {
|
||||
// update graph yaxes changes
|
||||
panelUpgrades.push(function(panel) {
|
||||
panelUpgrades.push(panel => {
|
||||
if (panel.type !== 'graph') {
|
||||
return;
|
||||
}
|
||||
@@ -300,7 +297,7 @@ export class DashboardMigrator {
|
||||
|
||||
if (oldVersion < 13) {
|
||||
// update graph yaxes changes
|
||||
panelUpgrades.push(function(panel) {
|
||||
panelUpgrades.push(panel => {
|
||||
if (panel.type !== 'graph') {
|
||||
return;
|
||||
}
|
||||
@@ -309,7 +306,7 @@ export class DashboardMigrator {
|
||||
}
|
||||
|
||||
panel.thresholds = [];
|
||||
var t1: any = {},
|
||||
const t1: any = {},
|
||||
t2: any = {};
|
||||
|
||||
if (panel.grid.threshold1 !== null) {
|
||||
@@ -389,7 +386,7 @@ export class DashboardMigrator {
|
||||
|
||||
upgradeToGridLayout(old) {
|
||||
let yPos = 0;
|
||||
let widthFactor = GRID_COLUMN_COUNT / 12;
|
||||
const widthFactor = GRID_COLUMN_COUNT / 12;
|
||||
|
||||
const maxPanelId = _.max(
|
||||
_.flattenDeep(
|
||||
@@ -407,15 +404,15 @@ export class DashboardMigrator {
|
||||
// Add special "row" panels if even one row is collapsed, repeated or has visible title
|
||||
const showRows = _.some(old.rows, row => row.collapse || row.showTitle || row.repeat);
|
||||
|
||||
for (let row of old.rows) {
|
||||
for (const row of old.rows) {
|
||||
if (row.repeatIteration) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let height: any = row.height || DEFAULT_ROW_HEIGHT;
|
||||
const height: any = row.height || DEFAULT_ROW_HEIGHT;
|
||||
const rowGridHeight = getGridHeight(height);
|
||||
|
||||
let rowPanel: any = {};
|
||||
const rowPanel: any = {};
|
||||
let rowPanelModel: PanelModel;
|
||||
if (showRows) {
|
||||
// add special row panel
|
||||
@@ -436,9 +433,9 @@ export class DashboardMigrator {
|
||||
yPos++;
|
||||
}
|
||||
|
||||
let rowArea = new RowArea(rowGridHeight, GRID_COLUMN_COUNT, yPos);
|
||||
const rowArea = new RowArea(rowGridHeight, GRID_COLUMN_COUNT, yPos);
|
||||
|
||||
for (let panel of row.panels) {
|
||||
for (const panel of row.panels) {
|
||||
panel.span = panel.span || DEFAULT_PANEL_SPAN;
|
||||
if (panel.minSpan) {
|
||||
panel.minSpan = Math.min(GRID_COLUMN_COUNT, GRID_COLUMN_COUNT / 12 * panel.minSpan);
|
||||
@@ -446,7 +443,7 @@ export class DashboardMigrator {
|
||||
const panelWidth = Math.floor(panel.span) * widthFactor;
|
||||
const panelHeight = panel.height ? getGridHeight(panel.height) : rowGridHeight;
|
||||
|
||||
let panelPos = rowArea.getPanelPosition(panelHeight, panelWidth);
|
||||
const panelPos = rowArea.getPanelPosition(panelHeight, panelWidth);
|
||||
yPos = rowArea.yPos;
|
||||
panel.gridPos = {
|
||||
x: panelPos.x,
|
||||
|
||||
@@ -95,7 +95,7 @@ export class DashboardModel {
|
||||
|
||||
addBuiltInAnnotationQuery() {
|
||||
let found = false;
|
||||
for (let item of this.annotations.list) {
|
||||
for (const item of this.annotations.list) {
|
||||
if (item.builtIn === 1) {
|
||||
found = true;
|
||||
break;
|
||||
@@ -138,14 +138,14 @@ export class DashboardModel {
|
||||
|
||||
// cleans meta data and other non persistent state
|
||||
getSaveModelClone(options?) {
|
||||
let defaults = _.defaults(options || {}, {
|
||||
const defaults = _.defaults(options || {}, {
|
||||
saveVariables: true,
|
||||
saveTimerange: true,
|
||||
});
|
||||
|
||||
// make clone
|
||||
var copy: any = {};
|
||||
for (var property in this) {
|
||||
let copy: any = {};
|
||||
for (const property in this) {
|
||||
if (DashboardModel.nonPersistedProperties[property] || !this.hasOwnProperty(property)) {
|
||||
continue;
|
||||
}
|
||||
@@ -160,8 +160,8 @@ export class DashboardModel {
|
||||
|
||||
if (!defaults.saveVariables) {
|
||||
for (let i = 0; i < copy.templating.list.length; i++) {
|
||||
let current = copy.templating.list[i];
|
||||
let original = _.find(this.originalTemplating, { name: current.name, type: current.type });
|
||||
const current = copy.templating.list[i];
|
||||
const original = _.find(this.originalTemplating, { name: current.name, type: current.type });
|
||||
|
||||
if (!original) {
|
||||
continue;
|
||||
@@ -246,13 +246,13 @@ export class DashboardModel {
|
||||
getNextPanelId() {
|
||||
let max = 0;
|
||||
|
||||
for (let panel of this.panels) {
|
||||
for (const panel of this.panels) {
|
||||
if (panel.id > max) {
|
||||
max = panel.id;
|
||||
}
|
||||
|
||||
if (panel.collapsed) {
|
||||
for (let rowPanel of panel.panels) {
|
||||
for (const rowPanel of panel.panels) {
|
||||
if (rowPanel.id > max) {
|
||||
max = rowPanel.id;
|
||||
}
|
||||
@@ -270,7 +270,7 @@ export class DashboardModel {
|
||||
}
|
||||
|
||||
getPanelById(id) {
|
||||
for (let panel of this.panels) {
|
||||
for (const panel of this.panels) {
|
||||
if (panel.id === id) {
|
||||
return panel;
|
||||
}
|
||||
@@ -281,7 +281,7 @@ export class DashboardModel {
|
||||
addPanel(panelData) {
|
||||
panelData.id = this.getNextPanelId();
|
||||
|
||||
let panel = new PanelModel(panelData);
|
||||
const panel = new PanelModel(panelData);
|
||||
|
||||
this.panels.unshift(panel);
|
||||
|
||||
@@ -291,7 +291,7 @@ export class DashboardModel {
|
||||
}
|
||||
|
||||
sortPanelsByGridPos() {
|
||||
this.panels.sort(function(panelA, panelB) {
|
||||
this.panels.sort((panelA, panelB) => {
|
||||
if (panelA.gridPos.y === panelB.gridPos.y) {
|
||||
return panelA.gridPos.x - panelB.gridPos.x;
|
||||
} else {
|
||||
@@ -306,15 +306,15 @@ export class DashboardModel {
|
||||
}
|
||||
|
||||
this.iteration = (this.iteration || new Date().getTime()) + 1;
|
||||
let panelsToRemove = [];
|
||||
const panelsToRemove = [];
|
||||
|
||||
// cleanup scopedVars
|
||||
for (let panel of this.panels) {
|
||||
for (const panel of this.panels) {
|
||||
delete panel.scopedVars;
|
||||
}
|
||||
|
||||
for (let i = 0; i < this.panels.length; i++) {
|
||||
let panel = this.panels[i];
|
||||
const panel = this.panels[i];
|
||||
if ((!panel.repeat || panel.repeatedByRow) && panel.repeatPanelId && panel.repeatIteration !== this.iteration) {
|
||||
panelsToRemove.push(panel);
|
||||
}
|
||||
@@ -337,7 +337,7 @@ export class DashboardModel {
|
||||
this.iteration = (this.iteration || new Date().getTime()) + 1;
|
||||
|
||||
for (let i = 0; i < this.panels.length; i++) {
|
||||
let panel = this.panels[i];
|
||||
const panel = this.panels[i];
|
||||
if (panel.repeat) {
|
||||
this.repeatPanel(panel, i);
|
||||
}
|
||||
@@ -348,9 +348,9 @@ export class DashboardModel {
|
||||
}
|
||||
|
||||
cleanUpRowRepeats(rowPanels) {
|
||||
let panelsToRemove = [];
|
||||
const panelsToRemove = [];
|
||||
for (let i = 0; i < rowPanels.length; i++) {
|
||||
let panel = rowPanels[i];
|
||||
const panel = rowPanels[i];
|
||||
if (!panel.repeat && panel.repeatPanelId) {
|
||||
panelsToRemove.push(panel);
|
||||
}
|
||||
@@ -366,16 +366,16 @@ export class DashboardModel {
|
||||
|
||||
let rowPanels = row.panels;
|
||||
if (!row.collapsed) {
|
||||
let rowPanelIndex = _.findIndex(this.panels, p => p.id === row.id);
|
||||
const rowPanelIndex = _.findIndex(this.panels, p => p.id === row.id);
|
||||
rowPanels = this.getRowPanels(rowPanelIndex);
|
||||
}
|
||||
|
||||
this.cleanUpRowRepeats(rowPanels);
|
||||
|
||||
for (let i = 0; i < rowPanels.length; i++) {
|
||||
let panel = rowPanels[i];
|
||||
const panel = rowPanels[i];
|
||||
if (panel.repeat) {
|
||||
let panelIndex = _.findIndex(this.panels, p => p.id === panel.id);
|
||||
const panelIndex = _.findIndex(this.panels, p => p.id === panel.id);
|
||||
this.repeatPanel(panel, panelIndex);
|
||||
}
|
||||
}
|
||||
@@ -387,7 +387,7 @@ export class DashboardModel {
|
||||
return sourcePanel;
|
||||
}
|
||||
|
||||
let clone = new PanelModel(sourcePanel.getSaveModel());
|
||||
const clone = new PanelModel(sourcePanel.getSaveModel());
|
||||
clone.id = this.getNextPanelId();
|
||||
|
||||
// insert after source panel + value index
|
||||
@@ -403,13 +403,13 @@ export class DashboardModel {
|
||||
// if first clone return source
|
||||
if (valueIndex === 0) {
|
||||
if (!sourceRowPanel.collapsed) {
|
||||
let rowPanels = this.getRowPanels(sourcePanelIndex);
|
||||
const rowPanels = this.getRowPanels(sourcePanelIndex);
|
||||
sourceRowPanel.panels = rowPanels;
|
||||
}
|
||||
return sourceRowPanel;
|
||||
}
|
||||
|
||||
let clone = new PanelModel(sourceRowPanel.getSaveModel());
|
||||
const clone = new PanelModel(sourceRowPanel.getSaveModel());
|
||||
// for row clones we need to figure out panels under row to clone and where to insert clone
|
||||
let rowPanels, insertPos;
|
||||
if (sourceRowPanel.collapsed) {
|
||||
@@ -430,7 +430,7 @@ export class DashboardModel {
|
||||
}
|
||||
|
||||
repeatPanel(panel: PanelModel, panelIndex: number) {
|
||||
let variable = _.find(this.templating.list, { name: panel.repeat });
|
||||
const variable = _.find(this.templating.list, { name: panel.repeat });
|
||||
if (!variable) {
|
||||
return;
|
||||
}
|
||||
@@ -440,13 +440,13 @@ export class DashboardModel {
|
||||
return;
|
||||
}
|
||||
|
||||
let selectedOptions = this.getSelectedVariableOptions(variable);
|
||||
let minWidth = panel.minSpan || 6;
|
||||
const selectedOptions = this.getSelectedVariableOptions(variable);
|
||||
const minWidth = panel.minSpan || 6;
|
||||
let xPos = 0;
|
||||
let yPos = panel.gridPos.y;
|
||||
|
||||
for (let index = 0; index < selectedOptions.length; index++) {
|
||||
let option = selectedOptions[index];
|
||||
const option = selectedOptions[index];
|
||||
let copy;
|
||||
|
||||
copy = this.getPanelRepeatClone(panel, index, panelIndex);
|
||||
@@ -476,9 +476,9 @@ export class DashboardModel {
|
||||
}
|
||||
|
||||
// Update gridPos for panels below
|
||||
let yOffset = yPos - panel.gridPos.y;
|
||||
const yOffset = yPos - panel.gridPos.y;
|
||||
if (yOffset > 0) {
|
||||
let panelBelowIndex = panelIndex + selectedOptions.length;
|
||||
const panelBelowIndex = panelIndex + selectedOptions.length;
|
||||
for (let i = panelBelowIndex; i < this.panels.length; i++) {
|
||||
this.panels[i].gridPos.y += yOffset;
|
||||
}
|
||||
@@ -486,7 +486,7 @@ export class DashboardModel {
|
||||
}
|
||||
|
||||
repeatRow(panel: PanelModel, panelIndex: number, variable) {
|
||||
let selectedOptions = this.getSelectedVariableOptions(variable);
|
||||
const selectedOptions = this.getSelectedVariableOptions(variable);
|
||||
let yPos = panel.gridPos.y;
|
||||
|
||||
function setScopedVars(panel, variableOption) {
|
||||
@@ -495,12 +495,12 @@ export class DashboardModel {
|
||||
}
|
||||
|
||||
for (let optionIndex = 0; optionIndex < selectedOptions.length; optionIndex++) {
|
||||
let option = selectedOptions[optionIndex];
|
||||
let rowCopy = this.getRowRepeatClone(panel, optionIndex, panelIndex);
|
||||
const option = selectedOptions[optionIndex];
|
||||
const rowCopy = this.getRowRepeatClone(panel, optionIndex, panelIndex);
|
||||
setScopedVars(rowCopy, option);
|
||||
|
||||
let rowHeight = this.getRowHeight(rowCopy);
|
||||
let rowPanels = rowCopy.panels || [];
|
||||
const rowHeight = this.getRowHeight(rowCopy);
|
||||
const rowPanels = rowCopy.panels || [];
|
||||
let panelBelowIndex;
|
||||
|
||||
if (panel.collapsed) {
|
||||
@@ -516,11 +516,11 @@ export class DashboardModel {
|
||||
panelBelowIndex = panelIndex + optionIndex + 1;
|
||||
} else {
|
||||
// insert after 'row' panel
|
||||
let insertPos = panelIndex + (rowPanels.length + 1) * optionIndex + 1;
|
||||
const insertPos = panelIndex + (rowPanels.length + 1) * optionIndex + 1;
|
||||
_.each(rowPanels, (rowPanel, i) => {
|
||||
setScopedVars(rowPanel, option);
|
||||
if (optionIndex > 0) {
|
||||
let cloneRowPanel = new PanelModel(rowPanel);
|
||||
const cloneRowPanel = new PanelModel(rowPanel);
|
||||
this.updateRepeatedPanelIds(cloneRowPanel, true);
|
||||
// For exposed row additionally set proper Y grid position and add it to dashboard panels
|
||||
cloneRowPanel.gridPos.y += rowHeight * optionIndex;
|
||||
@@ -575,7 +575,7 @@ export class DashboardModel {
|
||||
}
|
||||
|
||||
removePanel(panel: PanelModel) {
|
||||
var index = _.indexOf(this.panels, panel);
|
||||
const index = _.indexOf(this.panels, panel);
|
||||
this.panels.splice(index, 1);
|
||||
this.events.emit('panel-removed', panel);
|
||||
}
|
||||
@@ -592,7 +592,7 @@ export class DashboardModel {
|
||||
|
||||
expandRows() {
|
||||
for (let i = 0; i < this.panels.length; i++) {
|
||||
var panel = this.panels[i];
|
||||
const panel = this.panels[i];
|
||||
|
||||
if (panel.type !== 'row') {
|
||||
continue;
|
||||
@@ -606,7 +606,7 @@ export class DashboardModel {
|
||||
|
||||
collapseRows() {
|
||||
for (let i = 0; i < this.panels.length; i++) {
|
||||
var panel = this.panels[i];
|
||||
const panel = this.panels[i];
|
||||
|
||||
if (panel.type !== 'row') {
|
||||
continue;
|
||||
@@ -628,12 +628,12 @@ export class DashboardModel {
|
||||
return true;
|
||||
}
|
||||
|
||||
var visibleVars = _.filter(this.templating.list, variable => variable.hide !== 2);
|
||||
const visibleVars = _.filter(this.templating.list, variable => variable.hide !== 2);
|
||||
if (visibleVars.length > 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var visibleAnnotations = _.filter(this.annotations.list, annotation => annotation.hide !== true);
|
||||
const visibleAnnotations = _.filter(this.annotations.list, annotation => annotation.hide !== true);
|
||||
if (visibleAnnotations.length > 0) {
|
||||
return true;
|
||||
}
|
||||
@@ -683,29 +683,29 @@ export class DashboardModel {
|
||||
formatDate(date, format?) {
|
||||
date = moment.isMoment(date) ? date : moment(date);
|
||||
format = format || 'YYYY-MM-DD HH:mm:ss';
|
||||
let timezone = this.getTimezone();
|
||||
const timezone = this.getTimezone();
|
||||
|
||||
return timezone === 'browser' ? moment(date).format(format) : moment.utc(date).format(format);
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.events.removeAllListeners();
|
||||
for (let panel of this.panels) {
|
||||
for (const panel of this.panels) {
|
||||
panel.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
toggleRow(row: PanelModel) {
|
||||
let rowIndex = _.indexOf(this.panels, row);
|
||||
const rowIndex = _.indexOf(this.panels, row);
|
||||
|
||||
if (row.collapsed) {
|
||||
row.collapsed = false;
|
||||
let hasRepeat = _.some(row.panels, p => p.repeat);
|
||||
const hasRepeat = _.some(row.panels, p => p.repeat);
|
||||
|
||||
if (row.panels.length > 0) {
|
||||
// Use first panel to figure out if it was moved or pushed
|
||||
let firstPanel = row.panels[0];
|
||||
let yDiff = firstPanel.gridPos.y - (row.gridPos.y + row.gridPos.h);
|
||||
const firstPanel = row.panels[0];
|
||||
const yDiff = firstPanel.gridPos.y - (row.gridPos.y + row.gridPos.h);
|
||||
|
||||
// start inserting after row
|
||||
let insertPos = rowIndex + 1;
|
||||
@@ -713,7 +713,7 @@ export class DashboardModel {
|
||||
// needed to know home much panels below should be pushed down
|
||||
let yMax = row.gridPos.y;
|
||||
|
||||
for (let panel of row.panels) {
|
||||
for (const panel of row.panels) {
|
||||
// make sure y is adjusted (in case row moved while collapsed)
|
||||
// console.log('yDiff', yDiff);
|
||||
panel.gridPos.y -= yDiff;
|
||||
@@ -746,7 +746,7 @@ export class DashboardModel {
|
||||
return;
|
||||
}
|
||||
|
||||
let rowPanels = this.getRowPanels(rowIndex);
|
||||
const rowPanels = this.getRowPanels(rowIndex);
|
||||
|
||||
// remove panels
|
||||
_.pull(this.panels, ...rowPanels);
|
||||
@@ -762,10 +762,10 @@ export class DashboardModel {
|
||||
* Will return all panels after rowIndex until it encounters another row
|
||||
*/
|
||||
getRowPanels(rowIndex: number): PanelModel[] {
|
||||
let rowPanels = [];
|
||||
const rowPanels = [];
|
||||
|
||||
for (let index = rowIndex + 1; index < this.panels.length; index++) {
|
||||
let panel = this.panels[index];
|
||||
const panel = this.panels[index];
|
||||
|
||||
// break when encountering another row
|
||||
if (panel.type === 'row') {
|
||||
@@ -806,10 +806,10 @@ export class DashboardModel {
|
||||
}
|
||||
|
||||
getNextQueryLetter(panel) {
|
||||
var letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
|
||||
return _.find(letters, function(refId) {
|
||||
return _.every(panel.targets, function(other) {
|
||||
return _.find(letters, refId => {
|
||||
return _.every(panel.targets, other => {
|
||||
return other.refId !== refId;
|
||||
});
|
||||
});
|
||||
@@ -824,7 +824,7 @@ export class DashboardModel {
|
||||
}
|
||||
|
||||
private updateSchema(old) {
|
||||
let migrator = new DashboardMigrator(this);
|
||||
const migrator = new DashboardMigrator(this);
|
||||
migrator.updateSchema(old);
|
||||
}
|
||||
|
||||
@@ -875,12 +875,20 @@ export class DashboardModel {
|
||||
})
|
||||
);
|
||||
|
||||
// Consider navbar and submenu controls, padding and margin
|
||||
let visibleHeight = window.innerHeight - 55 - 20;
|
||||
const navbarHeight = 55;
|
||||
const margin = 20;
|
||||
const submenuHeight = 50;
|
||||
|
||||
// Remove submenu if visible
|
||||
if (this.meta.submenuEnabled) {
|
||||
visibleHeight -= 50;
|
||||
let visibleHeight = viewHeight - navbarHeight - margin;
|
||||
|
||||
// Remove submenu height if visible
|
||||
if (this.meta.submenuEnabled && !this.meta.kiosk) {
|
||||
visibleHeight -= submenuHeight;
|
||||
}
|
||||
|
||||
// add back navbar height
|
||||
if (this.meta.kiosk === 'b') {
|
||||
visibleHeight += 55;
|
||||
}
|
||||
|
||||
const visibleGridHeight = Math.floor(visibleHeight / (GRID_CELL_HEIGHT + GRID_CELL_VMARGIN));
|
||||
|
||||
@@ -68,18 +68,18 @@ export class AddPanelPanel extends React.Component<AddPanelPanelProps, AddPanelP
|
||||
}
|
||||
|
||||
getCopiedPanelPlugins(filter) {
|
||||
let panels = _.chain(config.panels)
|
||||
const panels = _.chain(config.panels)
|
||||
.filter({ hideFromList: false })
|
||||
.map(item => item)
|
||||
.value();
|
||||
let copiedPanels = [];
|
||||
|
||||
let copiedPanelJson = store.get(LS_PANEL_COPY_KEY);
|
||||
const copiedPanelJson = store.get(LS_PANEL_COPY_KEY);
|
||||
if (copiedPanelJson) {
|
||||
let copiedPanel = JSON.parse(copiedPanelJson);
|
||||
let pluginInfo = _.find(panels, { id: copiedPanel.type });
|
||||
const copiedPanel = JSON.parse(copiedPanelJson);
|
||||
const pluginInfo = _.find(panels, { id: copiedPanel.type });
|
||||
if (pluginInfo) {
|
||||
let pluginCopy = _.cloneDeep(pluginInfo);
|
||||
const pluginCopy = _.cloneDeep(pluginInfo);
|
||||
pluginCopy.name = copiedPanel.title;
|
||||
pluginCopy.sort = -1;
|
||||
pluginCopy.defaults = copiedPanel;
|
||||
@@ -96,7 +96,7 @@ export class AddPanelPanel extends React.Component<AddPanelPanelProps, AddPanelP
|
||||
const dashboard = this.props.dashboard;
|
||||
const { gridPos } = this.props.panel;
|
||||
|
||||
var newPanel: any = {
|
||||
const newPanel: any = {
|
||||
type: panelPluginInfo.id,
|
||||
title: 'Panel Title',
|
||||
gridPos: { x: gridPos.x, y: gridPos.y, w: gridPos.w, h: gridPos.h },
|
||||
@@ -126,7 +126,7 @@ export class AddPanelPanel extends React.Component<AddPanelPanelProps, AddPanelP
|
||||
}
|
||||
|
||||
renderText(text: string) {
|
||||
let searchWords = this.state.filter.split('');
|
||||
const searchWords = this.state.filter.split('');
|
||||
return <Highlighter highlightClassName="highlight-search-match" textToHighlight={text} searchWords={searchWords} />;
|
||||
}
|
||||
|
||||
@@ -153,7 +153,7 @@ export class AddPanelPanel extends React.Component<AddPanelPanelProps, AddPanelP
|
||||
|
||||
filterKeyPress(evt) {
|
||||
if (evt.key === 'Enter') {
|
||||
let panel = _.head(this.state.panelPlugins);
|
||||
const panel = _.head(this.state.panelPlugins);
|
||||
if (panel) {
|
||||
this.onAddPanel(panel);
|
||||
}
|
||||
@@ -161,7 +161,7 @@ export class AddPanelPanel extends React.Component<AddPanelPanelProps, AddPanelP
|
||||
}
|
||||
|
||||
filterPanels(panels, filter) {
|
||||
let regex = new RegExp(filter, 'i');
|
||||
const regex = new RegExp(filter, 'i');
|
||||
return panels.filter(panel => {
|
||||
return regex.test(panel.name);
|
||||
});
|
||||
@@ -186,12 +186,12 @@ export class AddPanelPanel extends React.Component<AddPanelPanelProps, AddPanelP
|
||||
}
|
||||
|
||||
render() {
|
||||
let addClass = classNames({
|
||||
const addClass = classNames({
|
||||
'active active--panel': this.state.tab === 'Add',
|
||||
'': this.state.tab === 'Copy',
|
||||
});
|
||||
|
||||
let copyClass = classNames({
|
||||
const copyClass = classNames({
|
||||
'': this.state.tab === 'Add',
|
||||
'active active--panel': this.state.tab === 'Copy',
|
||||
});
|
||||
|
||||
@@ -77,7 +77,7 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> {
|
||||
this.state = { animated: false };
|
||||
|
||||
// subscribe to dashboard events
|
||||
let dashboard = this.props.dashboard;
|
||||
const dashboard = this.props.dashboard;
|
||||
dashboard.on('panel-added', this.triggerForceUpdate.bind(this));
|
||||
dashboard.on('panel-removed', this.triggerForceUpdate.bind(this));
|
||||
dashboard.on('repeats-processed', this.triggerForceUpdate.bind(this));
|
||||
@@ -91,8 +91,8 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> {
|
||||
const layout = [];
|
||||
this.panelMap = {};
|
||||
|
||||
for (let panel of this.props.dashboard.panels) {
|
||||
let stringId = panel.id.toString();
|
||||
for (const panel of this.props.dashboard.panels) {
|
||||
const stringId = panel.id.toString();
|
||||
this.panelMap[stringId] = panel;
|
||||
|
||||
if (!panel.gridPos) {
|
||||
@@ -100,7 +100,7 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> {
|
||||
continue;
|
||||
}
|
||||
|
||||
let panelPos: any = {
|
||||
const panelPos: any = {
|
||||
i: stringId,
|
||||
x: panel.gridPos.x,
|
||||
y: panel.gridPos.y,
|
||||
@@ -174,10 +174,10 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> {
|
||||
const panelElements = [];
|
||||
console.log('render panels');
|
||||
|
||||
for (let panel of this.props.dashboard.panels) {
|
||||
for (const panel of this.props.dashboard.panels) {
|
||||
const panelClasses = classNames({ panel: true, 'panel--fullscreen': panel.fullscreen });
|
||||
panelElements.push(
|
||||
<div key={panel.id.toString()} className={panelClasses}>
|
||||
<div key={panel.id.toString()} className={panelClasses} id={`panel-${panel.id}`}>
|
||||
<DashboardPanel panel={panel} dashboard={this.props.dashboard} panelType={panel.type} />
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -94,9 +94,9 @@ export class DashboardPanel extends React.Component<Props, State> {
|
||||
return;
|
||||
}
|
||||
|
||||
let loader = getAngularLoader();
|
||||
var template = '<plugin-component type="panel" class="panel-height-helper"></plugin-component>';
|
||||
let scopeProps = { panel: this.props.panel, dashboard: this.props.dashboard };
|
||||
const loader = getAngularLoader();
|
||||
const template = '<plugin-component type="panel" class="panel-height-helper"></plugin-component>';
|
||||
const scopeProps = { panel: this.props.panel, dashboard: this.props.dashboard };
|
||||
this.angularPanel = loader.load(this.element, scopeProps, template);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,8 +10,7 @@ export interface PanelProps extends OuterProps {
|
||||
data: any[];
|
||||
}
|
||||
|
||||
export interface DataPanel extends ComponentClass<OuterProps> {
|
||||
}
|
||||
export interface DataPanel extends ComponentClass<OuterProps> {}
|
||||
|
||||
interface State {
|
||||
isLoading: boolean;
|
||||
@@ -20,7 +19,7 @@ interface State {
|
||||
|
||||
export const DataPanelWrapper = (ComposedComponent: ComponentClass<PanelProps>) => {
|
||||
class Wrapper extends Component<OuterProps, State> {
|
||||
public static defaultProps = {
|
||||
static defaultProps = {
|
||||
isVisible: true,
|
||||
};
|
||||
|
||||
@@ -33,12 +32,12 @@ export const DataPanelWrapper = (ComposedComponent: ComponentClass<PanelProps>)
|
||||
};
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
componentDidMount() {
|
||||
console.log('data panel mount');
|
||||
this.issueQueries();
|
||||
}
|
||||
|
||||
public issueQueries = async () => {
|
||||
issueQueries = async () => {
|
||||
const { isVisible } = this.props;
|
||||
|
||||
if (!isVisible) {
|
||||
@@ -49,14 +48,12 @@ export const DataPanelWrapper = (ComposedComponent: ComponentClass<PanelProps>)
|
||||
|
||||
await new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
|
||||
this.setState({ isLoading: false, data: [{value: 10}] });
|
||||
|
||||
this.setState({ isLoading: false, data: [{ value: 10 }] });
|
||||
}, 500);
|
||||
});
|
||||
};
|
||||
|
||||
public render() {
|
||||
render() {
|
||||
const { data, isLoading } = this.state;
|
||||
console.log('data panel render');
|
||||
|
||||
@@ -82,4 +79,3 @@ export const DataPanelWrapper = (ComposedComponent: ComponentClass<PanelProps>)
|
||||
|
||||
return Wrapper;
|
||||
};
|
||||
|
||||
|
||||
@@ -33,9 +33,9 @@ export class PanelHeader extends React.Component<PanelHeaderProps, any> {
|
||||
};
|
||||
|
||||
render() {
|
||||
let isFullscreen = false;
|
||||
let isLoading = false;
|
||||
let panelHeaderClass = classNames({ 'panel-header': true, 'grid-drag-handle': !isFullscreen });
|
||||
const isFullscreen = false;
|
||||
const isLoading = false;
|
||||
const panelHeaderClass = classNames({ 'panel-header': true, 'grid-drag-handle': !isFullscreen });
|
||||
|
||||
return (
|
||||
<div className={panelHeaderClass}>
|
||||
|
||||
31
public/app/features/dashboard/dashgrid/PanelLoader.ts
Normal file
31
public/app/features/dashboard/dashgrid/PanelLoader.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import angular from 'angular';
|
||||
import coreModule from 'app/core/core_module';
|
||||
|
||||
export interface AttachedPanel {
|
||||
destroy();
|
||||
}
|
||||
|
||||
export class PanelLoader {
|
||||
/** @ngInject */
|
||||
constructor(private $compile, private $rootScope) {}
|
||||
|
||||
load(elem, panel, dashboard): AttachedPanel {
|
||||
const template = '<plugin-component type="panel" class="panel-height-helper"></plugin-component>';
|
||||
const panelScope = this.$rootScope.$new();
|
||||
panelScope.panel = panel;
|
||||
panelScope.dashboard = dashboard;
|
||||
|
||||
const compiledElem = this.$compile(template)(panelScope);
|
||||
const rootNode = angular.element(elem);
|
||||
rootNode.append(compiledElem);
|
||||
|
||||
return {
|
||||
destroy: () => {
|
||||
panelScope.$destroy();
|
||||
compiledElem.remove();
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
coreModule.service('panelLoader', PanelLoader);
|
||||
@@ -21,9 +21,9 @@ export class QueriesTab extends React.Component<Props, any> {
|
||||
return;
|
||||
}
|
||||
|
||||
let loader = getAngularLoader();
|
||||
var template = '<metrics-tab />';
|
||||
let scopeProps = {
|
||||
const loader = getAngularLoader();
|
||||
const template = '<metrics-tab />';
|
||||
const scopeProps = {
|
||||
ctrl: {
|
||||
panel: this.props.panel,
|
||||
dashboard: this.props.dashboard,
|
||||
|
||||
@@ -23,7 +23,7 @@ export class VizTypePicker extends PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
getPanelPlugins(filter) {
|
||||
let panels = _.chain(config.panels)
|
||||
const panels = _.chain(config.panels)
|
||||
.filter({ hideFromList: false })
|
||||
.map(item => item)
|
||||
.value();
|
||||
|
||||
135
public/app/features/dashboard/dashlinks/editor.html
Normal file
135
public/app/features/dashboard/dashlinks/editor.html
Normal file
@@ -0,0 +1,135 @@
|
||||
<h3 class="dashboard-settings__header">
|
||||
<a ng-click="ctrl.backToList()">Dashboard Links</a>
|
||||
<span ng-show="ctrl.mode === 'new'">> New</span>
|
||||
<span ng-show="ctrl.mode === 'edit'">> Edit</span>
|
||||
</h3>
|
||||
|
||||
<div ng-if="ctrl.mode == 'list'">
|
||||
<div ng-if="ctrl.dashboard.links.length === 0">
|
||||
<div class="empty-list-cta">
|
||||
<div class="empty-list-cta__title">
|
||||
There are no dashboard links added yet
|
||||
</div>
|
||||
<a ng-click="ctrl.setupNew()" class="empty-list-cta__button btn btn-xlarge btn-success">
|
||||
<i class="gicon gicon-add-link"></i>
|
||||
Add Dashboard Link
|
||||
</a>
|
||||
<div class="grafana-info-box">
|
||||
<h5>What are Dashboard Links?</h5>
|
||||
<p>
|
||||
Dashboard Links allow you to place links to other dashboards and web sites directly in below the dashboard header.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-if="ctrl.dashboard.links.length > 0">
|
||||
<div class="page-action-bar">
|
||||
<div class="page-action-bar__spacer"></div>
|
||||
<a type="button" class="btn btn-success" ng-click="ctrl.setupNew()">
|
||||
<i class="fa fa-plus"></i> New</a>
|
||||
</div>
|
||||
<table class="filter-table filter-table--hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Type</th>
|
||||
<th>Info</th>
|
||||
<th colspan="3"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="link in ctrl.dashboard.links">
|
||||
<td class="pointer" ng-click="ctrl.editLink(link)">
|
||||
<i class="fa fa-fw fa-external-link"></i>
|
||||
{{link.type}}
|
||||
</td>
|
||||
<td>
|
||||
<div ng-if="link.title">
|
||||
{{link.title}}
|
||||
</div>
|
||||
<div ng-if="!link.title && link.url">
|
||||
{{link.url}}
|
||||
</div>
|
||||
<span ng-if="!link.title && link.tags" ng-repeat="tag in link.tags" tag-color-from-name="tag" class="label label-tag" style="margin-right: 6px">
|
||||
{{tag}}
|
||||
</span>
|
||||
</td>
|
||||
<td style="width: 1%">
|
||||
<i ng-click="ctrl.moveLink($index, -1)" ng-hide="$first" class="pointer fa fa-arrow-up"></i>
|
||||
</td>
|
||||
<td style="width: 1%">
|
||||
<i ng-click="ctrl.moveLink($index, 1)" ng-hide="$last" class="pointer fa fa-arrow-down"></i>
|
||||
</td>
|
||||
<td style="width: 1%">
|
||||
<a ng-click="ctrl.deleteLink($index)" class="btn btn-danger btn-mini" ng-hide="annotation.builtIn">
|
||||
<i class="fa fa-remove"></i>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-if="ctrl.mode == 'edit' || ctrl.mode == 'new'">
|
||||
<div class="gf-form-group">
|
||||
<div class="gf-form-group">
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label width-8">Type</span>
|
||||
<div class="gf-form-select-wrapper width-10">
|
||||
<select class="gf-form-input" ng-model="ctrl.link.type" ng-options="f for f in ['dashboards','link']"></select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="gf-form" ng-show="ctrl.link.type === 'dashboards'">
|
||||
<span class="gf-form-label width-8">With tags</span>
|
||||
<bootstrap-tagsinput ng-model="ctrl.link.tags" tagclass="label label-tag" placeholder="add tags" style="margin-right: .25rem"></bootstrap-tagsinput>
|
||||
</div>
|
||||
|
||||
<gf-form-switch ng-show="ctrl.link.type === 'dashboards'" class="gf-form" label="As dropdown" checked="ctrl.link.asDropdown"
|
||||
switch-class="max-width-4" label-class="width-8"></gf-form-switch>
|
||||
<div class="gf-form" ng-show="ctrl.link.type === 'dashboards' && ctrl.link.asDropdown">
|
||||
<span class="gf-form-label width-8">Title</span>
|
||||
<input type="text" ng-model="ctrl.link.title" class="gf-form-input max-width-10" ng-model-onblur>
|
||||
</div>
|
||||
<div ng-show="ctrl.link.type === 'link'">
|
||||
<div class="gf-form">
|
||||
<li class="gf-form-label width-8">Url</li>
|
||||
<input type="text" ng-model="ctrl.link.url" class="gf-form-input width-20" ng-model-onblur>
|
||||
</div>
|
||||
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label width-8">Title</span>
|
||||
<input type="text" ng-model="ctrl.link.title" class="gf-form-input width-20" ng-model-onblur>
|
||||
</div>
|
||||
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label width-8">Tooltip</span>
|
||||
<input type="text" ng-model="ctrl.link.tooltip" class="gf-form-input width-20" placeholder="Open dashboard" ng-model-onblur>
|
||||
</div>
|
||||
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label width-8">Icon</span>
|
||||
<div class="gf-form-select-wrapper width-20">
|
||||
<select class="gf-form-input" ng-model="ctrl.link.icon" ng-options="k as k for (k, v) in ctrl.iconMap"></select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="gf-form-group">
|
||||
<h5 class="section-heading">Include</h5>
|
||||
<div>
|
||||
<gf-form-switch class="gf-form" label="Time range" checked="ctrl.link.keepTime" switch-class="max-width-6" label-class="width-9"></gf-form-switch>
|
||||
<gf-form-switch class="gf-form" label="Variable values" checked="ctrl.link.includeVars" switch-class="max-width-6" label-class="width-9"></gf-form-switch>
|
||||
<gf-form-switch class="gf-form" label="Open in new tab" checked="ctrl.link.targetBlank" switch-class="max-width-6" label-class="width-9"></gf-form-switch>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-success" ng-if="ctrl.mode == 'new'" ng-click="ctrl.addLink()">
|
||||
Add
|
||||
</button>
|
||||
<button class="btn btn-success" ng-if="ctrl.mode == 'edit'" ng-click="ctrl.saveLink()">
|
||||
Update
|
||||
</button>
|
||||
</div>
|
||||
78
public/app/features/dashboard/dashlinks/editor.ts
Normal file
78
public/app/features/dashboard/dashlinks/editor.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import angular from 'angular';
|
||||
import _ from 'lodash';
|
||||
|
||||
export let iconMap = {
|
||||
'external link': 'fa-external-link',
|
||||
dashboard: 'fa-th-large',
|
||||
question: 'fa-question',
|
||||
info: 'fa-info',
|
||||
bolt: 'fa-bolt',
|
||||
doc: 'fa-file-text-o',
|
||||
cloud: 'fa-cloud',
|
||||
};
|
||||
|
||||
export class DashLinkEditorCtrl {
|
||||
dashboard: any;
|
||||
iconMap: any;
|
||||
mode: any;
|
||||
link: any;
|
||||
|
||||
/** @ngInject */
|
||||
constructor($scope, $rootScope) {
|
||||
this.iconMap = iconMap;
|
||||
this.dashboard.links = this.dashboard.links || [];
|
||||
this.mode = 'list';
|
||||
|
||||
$scope.$on('$destroy', () => {
|
||||
$rootScope.appEvent('dash-links-updated');
|
||||
});
|
||||
}
|
||||
|
||||
backToList() {
|
||||
this.mode = 'list';
|
||||
}
|
||||
|
||||
setupNew() {
|
||||
this.mode = 'new';
|
||||
this.link = { type: 'dashboards', icon: 'external link' };
|
||||
}
|
||||
|
||||
addLink() {
|
||||
this.dashboard.links.push(this.link);
|
||||
this.mode = 'list';
|
||||
}
|
||||
|
||||
editLink(link) {
|
||||
this.link = link;
|
||||
this.mode = 'edit';
|
||||
console.log(this.link);
|
||||
}
|
||||
|
||||
saveLink() {
|
||||
this.backToList();
|
||||
}
|
||||
|
||||
moveLink(index, dir) {
|
||||
_.move(this.dashboard.links, index, index + dir);
|
||||
}
|
||||
|
||||
deleteLink(index) {
|
||||
this.dashboard.links.splice(index, 1);
|
||||
this.dashboard.updateSubmenuVisibility();
|
||||
}
|
||||
}
|
||||
|
||||
function dashLinksEditor() {
|
||||
return {
|
||||
restrict: 'E',
|
||||
controller: DashLinkEditorCtrl,
|
||||
templateUrl: 'public/app/features/dashboard/dashlinks/editor.html',
|
||||
bindToController: true,
|
||||
controllerAs: 'ctrl',
|
||||
scope: {
|
||||
dashboard: '=',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
angular.module('grafana.directives').directive('dashLinksEditor', dashLinksEditor);
|
||||
177
public/app/features/dashboard/dashlinks/module.ts
Normal file
177
public/app/features/dashboard/dashlinks/module.ts
Normal file
@@ -0,0 +1,177 @@
|
||||
import angular from 'angular';
|
||||
import _ from 'lodash';
|
||||
import { iconMap } from './editor';
|
||||
|
||||
function dashLinksContainer() {
|
||||
return {
|
||||
scope: {
|
||||
links: '=',
|
||||
},
|
||||
restrict: 'E',
|
||||
controller: 'DashLinksContainerCtrl',
|
||||
template: '<dash-link ng-repeat="link in generatedLinks" link="link"></dash-link>',
|
||||
link: () => {},
|
||||
};
|
||||
}
|
||||
|
||||
/** @ngInject */
|
||||
function dashLink($compile, $sanitize, linkSrv) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
link: (scope, elem) => {
|
||||
const link = scope.link;
|
||||
let template =
|
||||
'<div class="gf-form">' +
|
||||
'<a class="pointer gf-form-label" data-placement="bottom"' +
|
||||
(link.asDropdown ? ' ng-click="fillDropdown(link)" data-toggle="dropdown"' : '') +
|
||||
'>' +
|
||||
'<i></i> <span></span></a>';
|
||||
|
||||
if (link.asDropdown) {
|
||||
template +=
|
||||
'<ul class="dropdown-menu" role="menu">' +
|
||||
'<li ng-repeat="dash in link.searchHits">' +
|
||||
'<a href="{{dash.url}}" target="{{dash.target}}">{{dash.title}}</a>' +
|
||||
'</li>' +
|
||||
'</ul>';
|
||||
}
|
||||
|
||||
template += '</div>';
|
||||
|
||||
elem.html(template);
|
||||
$compile(elem.contents())(scope);
|
||||
|
||||
function update() {
|
||||
const linkInfo = linkSrv.getAnchorInfo(link);
|
||||
|
||||
const anchor = elem.find('a');
|
||||
const span = elem.find('span');
|
||||
span.text(linkInfo.title);
|
||||
|
||||
if (!link.asDropdown) {
|
||||
anchor.attr('href', linkInfo.href);
|
||||
sanitizeAnchor();
|
||||
}
|
||||
anchor.attr('data-placement', 'bottom');
|
||||
// tooltip
|
||||
anchor.tooltip({
|
||||
title: $sanitize(scope.link.tooltip),
|
||||
html: true,
|
||||
container: 'body',
|
||||
});
|
||||
}
|
||||
|
||||
function sanitizeAnchor() {
|
||||
const anchor = elem.find('a');
|
||||
const anchorSanitized = $sanitize(anchor.parent().html());
|
||||
anchor.parent().html(anchorSanitized);
|
||||
}
|
||||
|
||||
elem.find('i').attr('class', 'fa fa-fw ' + scope.link.icon);
|
||||
elem.find('a').attr('target', scope.link.target);
|
||||
|
||||
// fix for menus on the far right
|
||||
if (link.asDropdown && scope.$last) {
|
||||
elem.find('.dropdown-menu').addClass('pull-right');
|
||||
}
|
||||
|
||||
update();
|
||||
scope.$on('refresh', update);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export class DashLinksContainerCtrl {
|
||||
/** @ngInject */
|
||||
constructor($scope, $rootScope, $q, backendSrv, dashboardSrv, linkSrv) {
|
||||
const currentDashId = dashboardSrv.getCurrent().id;
|
||||
|
||||
function buildLinks(linkDef) {
|
||||
if (linkDef.type === 'dashboards') {
|
||||
if (!linkDef.tags) {
|
||||
console.log('Dashboard link missing tag');
|
||||
return $q.when([]);
|
||||
}
|
||||
|
||||
if (linkDef.asDropdown) {
|
||||
return $q.when([
|
||||
{
|
||||
title: linkDef.title,
|
||||
tags: linkDef.tags,
|
||||
keepTime: linkDef.keepTime,
|
||||
includeVars: linkDef.includeVars,
|
||||
target: linkDef.targetBlank ? '_blank' : '_self',
|
||||
icon: 'fa fa-bars',
|
||||
asDropdown: true,
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
return $scope.searchDashboards(linkDef, 7);
|
||||
}
|
||||
|
||||
if (linkDef.type === 'link') {
|
||||
return $q.when([
|
||||
{
|
||||
url: linkDef.url,
|
||||
title: linkDef.title,
|
||||
icon: iconMap[linkDef.icon],
|
||||
tooltip: linkDef.tooltip,
|
||||
target: linkDef.targetBlank ? '_blank' : '_self',
|
||||
keepTime: linkDef.keepTime,
|
||||
includeVars: linkDef.includeVars,
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
return $q.when([]);
|
||||
}
|
||||
|
||||
function updateDashLinks() {
|
||||
const promises = _.map($scope.links, buildLinks);
|
||||
|
||||
$q.all(promises).then(results => {
|
||||
$scope.generatedLinks = _.flatten(results);
|
||||
});
|
||||
}
|
||||
|
||||
$scope.searchDashboards = (link, limit) => {
|
||||
return backendSrv.search({ tag: link.tags, limit: limit }).then(results => {
|
||||
return _.reduce(
|
||||
results,
|
||||
(memo, dash) => {
|
||||
// do not add current dashboard
|
||||
if (dash.id !== currentDashId) {
|
||||
memo.push({
|
||||
title: dash.title,
|
||||
url: dash.url,
|
||||
target: link.target === '_self' ? '' : link.target,
|
||||
icon: 'fa fa-th-large',
|
||||
keepTime: link.keepTime,
|
||||
includeVars: link.includeVars,
|
||||
});
|
||||
}
|
||||
return memo;
|
||||
},
|
||||
[]
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.fillDropdown = link => {
|
||||
$scope.searchDashboards(link, 100).then(results => {
|
||||
_.each(results, hit => {
|
||||
hit.url = linkSrv.getLinkUrl(hit);
|
||||
});
|
||||
link.searchHits = results;
|
||||
});
|
||||
};
|
||||
|
||||
updateDashLinks();
|
||||
$rootScope.onAppEvent('dash-links-updated', updateDashLinks, $scope);
|
||||
}
|
||||
}
|
||||
|
||||
angular.module('grafana.directives').directive('dashLinksContainer', dashLinksContainer);
|
||||
angular.module('grafana.directives').directive('dashLink', dashLink);
|
||||
angular.module('grafana.directives').controller('DashLinksContainerCtrl', DashLinksContainerCtrl);
|
||||
@@ -8,14 +8,14 @@
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="navbar__spacer"></div>
|
||||
|
||||
<div class="navbar-buttons navbar-buttons--playlist" ng-if="ctrl.playlistSrv.isPlaying">
|
||||
<a class="navbar-button navbar-button--tight" ng-click="ctrl.playlistSrv.prev()"><i class="fa fa-step-backward"></i></a>
|
||||
<a class="navbar-button navbar-button--tight" ng-click="ctrl.playlistSrv.stop()"><i class="fa fa-stop"></i></a>
|
||||
<a class="navbar-button navbar-button--tight" ng-click="ctrl.playlistSrv.next()"><i class="fa fa-step-forward"></i></a>
|
||||
</div>
|
||||
|
||||
<div class="navbar__spacer"></div>
|
||||
|
||||
<div class="navbar-buttons navbar-buttons--actions">
|
||||
<button class="btn navbar-button navbar-button--add-panel" ng-show="::ctrl.dashboard.meta.canSave" bs-tooltip="'Add panel'" data-placement="bottom" ng-click="ctrl.addPanel()">
|
||||
<i class="gicon gicon-add-panel"></i>
|
||||
@@ -25,11 +25,11 @@
|
||||
<i class="fa" ng-class="{'fa-star-o': !ctrl.dashboard.meta.isStarred, 'fa-star': ctrl.dashboard.meta.isStarred}"></i>
|
||||
</button>
|
||||
|
||||
<button class="btn navbar-button navbar-button--share" ng-show="::ctrl.dashboard.meta.canShare" ng-click="ctrl.shareDashboard(0)" bs-tooltip="'Share dashboard'" data-placement="bottom">
|
||||
<button class="btn navbar-button navbar-button--share" ng-show="::ctrl.dashboard.meta.canShare" ng-click="ctrl.shareDashboard(0)" bs-tooltip="'Share dashboard'" data-placement="bottom">
|
||||
<i class="fa fa-share-square-o"></i></a>
|
||||
</button>
|
||||
|
||||
<button class="btn navbar-button navbar-button--save" ng-show="ctrl.dashboard.meta.canSave" ng-click="ctrl.saveDashboard()" bs-tooltip="'Save dashboard <br> CTRL+S'" data-placement="bottom">
|
||||
<button class="btn navbar-button navbar-button--save" ng-show="ctrl.dashboard.meta.canSave" ng-click="ctrl.saveDashboard()" bs-tooltip="'Save dashboard <br> CTRL+S'" data-placement="bottom">
|
||||
<i class="fa fa-save"></i>
|
||||
</button>
|
||||
|
||||
@@ -42,6 +42,12 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="navbar-buttons navbar-buttons--tv">
|
||||
<button class="btn navbar-button navbar-button--tv" ng-click="ctrl.toggleViewMode()" bs-tooltip="'Cycle view mode'" data-placement="bottom">
|
||||
<i class="fa fa-desktop"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<gf-time-picker class="gf-timepicker-nav" dashboard="ctrl.dashboard" ng-if="!ctrl.dashboard.timepicker.hidden"></gf-time-picker>
|
||||
|
||||
<div class="navbar-buttons navbar-buttons--close">
|
||||
|
||||
@@ -13,7 +13,7 @@ export class DashNavCtrl {
|
||||
appEvents.on('save-dashboard', this.saveDashboard.bind(this), $scope);
|
||||
|
||||
if (this.dashboard.meta.isSnapshot) {
|
||||
var meta = this.dashboard.meta;
|
||||
const meta = this.dashboard.meta;
|
||||
this.titleTooltip = 'Created: ' + moment(meta.created).calendar();
|
||||
if (meta.expires) {
|
||||
this.titleTooltip += '<br>Expires: ' + moment(meta.expires).fromNow() + '<br>';
|
||||
@@ -22,7 +22,7 @@ export class DashNavCtrl {
|
||||
}
|
||||
|
||||
toggleSettings() {
|
||||
let search = this.$location.search();
|
||||
const search = this.$location.search();
|
||||
if (search.editview) {
|
||||
delete search.editview;
|
||||
} else {
|
||||
@@ -31,8 +31,12 @@ export class DashNavCtrl {
|
||||
this.$location.search(search);
|
||||
}
|
||||
|
||||
toggleViewMode() {
|
||||
appEvents.emit('toggle-kiosk-mode');
|
||||
}
|
||||
|
||||
close() {
|
||||
let search = this.$location.search();
|
||||
const search = this.$location.search();
|
||||
if (search.editview) {
|
||||
delete search.editview;
|
||||
} else if (search.fullscreen) {
|
||||
@@ -51,7 +55,7 @@ export class DashNavCtrl {
|
||||
}
|
||||
|
||||
shareDashboard(tabIndex) {
|
||||
var modalScope = this.$scope.$new();
|
||||
const modalScope = this.$scope.$new();
|
||||
modalScope.tabIndex = tabIndex;
|
||||
modalScope.dashboard = this.dashboard;
|
||||
|
||||
|
||||
@@ -21,15 +21,15 @@ export class DashExportCtrl {
|
||||
}
|
||||
|
||||
save() {
|
||||
var blob = new Blob([angular.toJson(this.dash, true)], {
|
||||
const blob = new Blob([angular.toJson(this.dash, true)], {
|
||||
type: 'application/json;charset=utf-8',
|
||||
});
|
||||
saveAs(blob, this.dash.title + '-' + new Date().getTime() + '.json');
|
||||
}
|
||||
|
||||
saveJson() {
|
||||
var clone = this.dash;
|
||||
let editScope = this.$rootScope.$new();
|
||||
const clone = this.dash;
|
||||
const editScope = this.$rootScope.$new();
|
||||
editScope.object = clone;
|
||||
editScope.enableCopy = true;
|
||||
|
||||
|
||||
@@ -12,23 +12,23 @@ export class DashboardExporter {
|
||||
// this is pretty hacky and needs to be changed
|
||||
dashboard.cleanUpRepeats();
|
||||
|
||||
var saveModel = dashboard.getSaveModelClone();
|
||||
const saveModel = dashboard.getSaveModelClone();
|
||||
saveModel.id = null;
|
||||
|
||||
// undo repeat cleanup
|
||||
dashboard.processRepeats();
|
||||
|
||||
var inputs = [];
|
||||
var requires = {};
|
||||
var datasources = {};
|
||||
var promises = [];
|
||||
var variableLookup: any = {};
|
||||
const inputs = [];
|
||||
const requires = {};
|
||||
const datasources = {};
|
||||
const promises = [];
|
||||
const variableLookup: any = {};
|
||||
|
||||
for (let variable of saveModel.templating.list) {
|
||||
for (const variable of saveModel.templating.list) {
|
||||
variableLookup[variable.name] = variable;
|
||||
}
|
||||
|
||||
var templateizeDatasourceUsage = obj => {
|
||||
const templateizeDatasourceUsage = obj => {
|
||||
// ignore data source properties that contain a variable
|
||||
if (obj.datasource && obj.datasource.indexOf('$') === 0) {
|
||||
if (variableLookup[obj.datasource.substring(1)]) {
|
||||
@@ -42,7 +42,7 @@ export class DashboardExporter {
|
||||
return;
|
||||
}
|
||||
|
||||
var refName = 'DS_' + ds.name.replace(' ', '_').toUpperCase();
|
||||
const refName = 'DS_' + ds.name.replace(' ', '_').toUpperCase();
|
||||
datasources[refName] = {
|
||||
name: refName,
|
||||
label: ds.name,
|
||||
@@ -69,14 +69,14 @@ export class DashboardExporter {
|
||||
}
|
||||
|
||||
if (panel.targets) {
|
||||
for (let target of panel.targets) {
|
||||
for (const target of panel.targets) {
|
||||
if (target.datasource !== undefined) {
|
||||
templateizeDatasourceUsage(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var panelDef = config.panels[panel.type];
|
||||
const panelDef = config.panels[panel.type];
|
||||
if (panelDef) {
|
||||
requires['panel' + panelDef.id] = {
|
||||
type: 'panel',
|
||||
@@ -88,19 +88,19 @@ export class DashboardExporter {
|
||||
};
|
||||
|
||||
// check up panel data sources
|
||||
for (let panel of saveModel.panels) {
|
||||
for (const panel of saveModel.panels) {
|
||||
processPanel(panel);
|
||||
|
||||
// handle collapsed rows
|
||||
if (panel.collapsed !== undefined && panel.collapsed === true && panel.panels) {
|
||||
for (let rowPanel of panel.panels) {
|
||||
for (const rowPanel of panel.panels) {
|
||||
processPanel(rowPanel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// templatize template vars
|
||||
for (let variable of saveModel.templating.list) {
|
||||
for (const variable of saveModel.templating.list) {
|
||||
if (variable.type === 'query') {
|
||||
templateizeDatasourceUsage(variable);
|
||||
variable.options = [];
|
||||
@@ -110,7 +110,7 @@ export class DashboardExporter {
|
||||
}
|
||||
|
||||
// templatize annotations vars
|
||||
for (let annotationDef of saveModel.annotations.list) {
|
||||
for (const annotationDef of saveModel.annotations.list) {
|
||||
templateizeDatasourceUsage(annotationDef);
|
||||
}
|
||||
|
||||
@@ -129,9 +129,9 @@ export class DashboardExporter {
|
||||
});
|
||||
|
||||
// templatize constants
|
||||
for (let variable of saveModel.templating.list) {
|
||||
for (const variable of saveModel.templating.list) {
|
||||
if (variable.type === 'constant') {
|
||||
var refName = 'VAR_' + variable.name.replace(' ', '_').toUpperCase();
|
||||
const refName = 'VAR_' + variable.name.replace(' ', '_').toUpperCase();
|
||||
inputs.push({
|
||||
name: refName,
|
||||
type: 'constant',
|
||||
@@ -149,7 +149,7 @@ export class DashboardExporter {
|
||||
}
|
||||
|
||||
// make inputs and requires a top thing
|
||||
var newObj = {};
|
||||
const newObj = {};
|
||||
newObj['__inputs'] = inputs;
|
||||
newObj['__requires'] = _.sortBy(requires, ['id']);
|
||||
|
||||
|
||||
@@ -5,9 +5,9 @@ import appEvents from 'app/core/app_events';
|
||||
export class ExportDataModalCtrl {
|
||||
private data: any[];
|
||||
private panel: string;
|
||||
asRows: Boolean = true;
|
||||
asRows = true;
|
||||
dateTimeFormat = 'YYYY-MM-DDTHH:mm:ssZ';
|
||||
excel: false;
|
||||
excel = false;
|
||||
|
||||
export() {
|
||||
if (this.panel === 'table') {
|
||||
|
||||
@@ -131,6 +131,7 @@ export class FolderPickerCtrl {
|
||||
private loadInitialValue() {
|
||||
const resetFolder = { text: this.initialTitle, value: null };
|
||||
const rootFolder = { text: this.rootName, value: 0 };
|
||||
|
||||
this.getOptions('').then(result => {
|
||||
let folder;
|
||||
if (this.initialFolderId) {
|
||||
@@ -150,7 +151,7 @@ export class FolderPickerCtrl {
|
||||
this.folder = folder;
|
||||
|
||||
// if this is not the same as our initial value notify parent
|
||||
if (this.folder.id !== this.initialFolderId) {
|
||||
if (this.folder.value !== this.initialFolderId) {
|
||||
this.onChange({ $folder: { id: this.folder.value, title: this.folder.text } });
|
||||
}
|
||||
});
|
||||
|
||||
@@ -67,7 +67,7 @@ export class HistoryListCtrl {
|
||||
}
|
||||
|
||||
revisionSelectionChanged() {
|
||||
let selected = _.filter(this.revisions, { checked: true }).length;
|
||||
const selected = _.filter(this.revisions, { checked: true }).length;
|
||||
this.canCompare = selected === 2;
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ export class HistoryListCtrl {
|
||||
.getHistoryList(this.dashboard, options)
|
||||
.then(revisions => {
|
||||
// set formatted dates & default values
|
||||
for (let rev of revisions) {
|
||||
for (const rev of revisions) {
|
||||
rev.createdDateString = this.formatDate(rev.created);
|
||||
rev.ageString = this.formatBasicDate(rev.created);
|
||||
rev.checked = false;
|
||||
|
||||
@@ -46,7 +46,7 @@ export class PanelModel {
|
||||
this.events = new Emitter();
|
||||
|
||||
// copy properties from persisted model
|
||||
for (var property in model) {
|
||||
for (const property in model) {
|
||||
this[property] = model[property];
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ export class PanelModel {
|
||||
|
||||
getSaveModel() {
|
||||
const model: any = {};
|
||||
for (var property in this) {
|
||||
for (const property in this) {
|
||||
if (notPersistedProperties[property] || !this.hasOwnProperty(property)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
116
public/app/features/dashboard/panellinks/link_srv.ts
Normal file
116
public/app/features/dashboard/panellinks/link_srv.ts
Normal file
@@ -0,0 +1,116 @@
|
||||
import angular from 'angular';
|
||||
import _ from 'lodash';
|
||||
import kbn from 'app/core/utils/kbn';
|
||||
|
||||
export class LinkSrv {
|
||||
/** @ngInject */
|
||||
constructor(private templateSrv, private timeSrv) {}
|
||||
|
||||
getLinkUrl(link) {
|
||||
const url = this.templateSrv.replace(link.url || '');
|
||||
const params = {};
|
||||
|
||||
if (link.keepTime) {
|
||||
const range = this.timeSrv.timeRangeForUrl();
|
||||
params['from'] = range.from;
|
||||
params['to'] = range.to;
|
||||
}
|
||||
|
||||
if (link.includeVars) {
|
||||
this.templateSrv.fillVariableValuesForUrl(params);
|
||||
}
|
||||
|
||||
return this.addParamsToUrl(url, params);
|
||||
}
|
||||
|
||||
addParamsToUrl(url, params) {
|
||||
const paramsArray = [];
|
||||
|
||||
_.each(params, (value, key) => {
|
||||
if (value === null) {
|
||||
return;
|
||||
}
|
||||
if (value === true) {
|
||||
paramsArray.push(key);
|
||||
} else if (_.isArray(value)) {
|
||||
_.each(value, instance => {
|
||||
paramsArray.push(key + '=' + encodeURIComponent(instance));
|
||||
});
|
||||
} else {
|
||||
paramsArray.push(key + '=' + encodeURIComponent(value));
|
||||
}
|
||||
});
|
||||
|
||||
if (paramsArray.length === 0) {
|
||||
return url;
|
||||
}
|
||||
|
||||
return this.appendToQueryString(url, paramsArray.join('&'));
|
||||
}
|
||||
|
||||
appendToQueryString(url, stringToAppend) {
|
||||
if (!_.isUndefined(stringToAppend) && stringToAppend !== null && stringToAppend !== '') {
|
||||
const pos = url.indexOf('?');
|
||||
if (pos !== -1) {
|
||||
if (url.length - pos > 1) {
|
||||
url += '&';
|
||||
}
|
||||
} else {
|
||||
url += '?';
|
||||
}
|
||||
url += stringToAppend;
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
getAnchorInfo(link) {
|
||||
const info: any = {};
|
||||
info.href = this.getLinkUrl(link);
|
||||
info.title = this.templateSrv.replace(link.title || '');
|
||||
return info;
|
||||
}
|
||||
|
||||
getPanelLinkAnchorInfo(link, scopedVars) {
|
||||
const info: any = {};
|
||||
if (link.type === 'absolute') {
|
||||
info.target = link.targetBlank ? '_blank' : '_self';
|
||||
info.href = this.templateSrv.replace(link.url || '', scopedVars);
|
||||
info.title = this.templateSrv.replace(link.title || '', scopedVars);
|
||||
} else if (link.url) {
|
||||
info.href = link.url;
|
||||
info.title = this.templateSrv.replace(link.title || '', scopedVars);
|
||||
info.target = link.targetBlank ? '_blank' : '';
|
||||
} else if (link.dashUri) {
|
||||
info.href = 'dashboard/' + link.dashUri + '?';
|
||||
info.title = this.templateSrv.replace(link.title || '', scopedVars);
|
||||
info.target = link.targetBlank ? '_blank' : '';
|
||||
} else {
|
||||
info.title = this.templateSrv.replace(link.title || '', scopedVars);
|
||||
const slug = kbn.slugifyForUrl(link.dashboard || '');
|
||||
info.href = 'dashboard/db/' + slug + '?';
|
||||
}
|
||||
|
||||
const params = {};
|
||||
|
||||
if (link.keepTime) {
|
||||
const range = this.timeSrv.timeRangeForUrl();
|
||||
params['from'] = range.from;
|
||||
params['to'] = range.to;
|
||||
}
|
||||
|
||||
if (link.includeVars) {
|
||||
this.templateSrv.fillVariableValuesForUrl(params, scopedVars);
|
||||
}
|
||||
|
||||
info.href = this.addParamsToUrl(info.href, params);
|
||||
|
||||
if (link.params) {
|
||||
info.href = this.appendToQueryString(info.href, this.templateSrv.replace(link.params, scopedVars));
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
}
|
||||
|
||||
angular.module('grafana.services').service('linkSrv', LinkSrv);
|
||||
51
public/app/features/dashboard/panellinks/module.html
Normal file
51
public/app/features/dashboard/panellinks/module.html
Normal file
@@ -0,0 +1,51 @@
|
||||
<div class="editor-row">
|
||||
<h5 class="section-heading">
|
||||
Drilldown / detail link<tip>These links appear in the dropdown menu in the panel menu. </tip></h5>
|
||||
</h5>
|
||||
|
||||
<div class="gf-form-group" ng-repeat="link in panel.links">
|
||||
<div class="section">
|
||||
<div class="gf-form max-width-25">
|
||||
<span class="gf-form-label width-7">Type</span>
|
||||
<div class="gf-form-select-wrapper gf-form--grow">
|
||||
<select class="gf-form-input" ng-model="link.type" ng-options="f for f in ['dashboard','absolute']"></select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="gf-form max-width-25">
|
||||
<span class="gf-form-label width-7" ng-show="link.type === 'dashboard'">Dashboard</span>
|
||||
<input ng-show="link.type === 'dashboard'" type="text" ng-model="link.dashboard" bs-typeahead="searchDashboards" class="gf-form-input" ng-blur="dashboardChanged(link)">
|
||||
|
||||
<span class="gf-form-label width-7" ng-show="link.type === 'absolute'">Url</span>
|
||||
<input ng-show="link.type === 'absolute'" type="text" ng-model="link.url" class="gf-form-input max-width-14">
|
||||
</div>
|
||||
|
||||
<div class="gf-form max-width-25">
|
||||
<div class="gf-form-label width-7">Title</div>
|
||||
<input type="text" ng-model="link.title" class="gf-form-input">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label width-10">Url params</span>
|
||||
<input type="text" ng-model="link.params" class="gf-form-input width-10">
|
||||
</div>
|
||||
|
||||
<gf-form-switch class="gf-form" label-class="width-10" label="Include time range" checked="link.keepTime"></gf-form-switch>
|
||||
<gf-form-switch class="gf-form" label-class="width-10" label="Include variables" checked="link.includeVars"></gf-form-switch>
|
||||
<gf-form-switch class="gf-form" label-class="width-10" label="Open in new tab " checked="link.targetBlank"></gf-form-switch>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<div class="gf-form">
|
||||
<button class="btn btn-inverse gf-form-btn" ng-click="deleteLink(link)"><i class="fa fa-trash"></i> Remove Link</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="editor-row">
|
||||
<button class="btn btn-inverse" ng-click="addLink()"><i class="fa fa-plus"></i> Add link</button>
|
||||
</div>
|
||||
62
public/app/features/dashboard/panellinks/module.ts
Normal file
62
public/app/features/dashboard/panellinks/module.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import angular from 'angular';
|
||||
import _ from 'lodash';
|
||||
import './link_srv';
|
||||
|
||||
function panelLinksEditor() {
|
||||
return {
|
||||
scope: {
|
||||
panel: '=',
|
||||
},
|
||||
restrict: 'E',
|
||||
controller: 'PanelLinksEditorCtrl',
|
||||
templateUrl: 'public/app/features/dashboard/panellinks/module.html',
|
||||
link: () => {},
|
||||
};
|
||||
}
|
||||
|
||||
export class PanelLinksEditorCtrl {
|
||||
/** @ngInject */
|
||||
constructor($scope, backendSrv) {
|
||||
$scope.panel.links = $scope.panel.links || [];
|
||||
|
||||
$scope.addLink = () => {
|
||||
$scope.panel.links.push({
|
||||
type: 'dashboard',
|
||||
});
|
||||
};
|
||||
|
||||
$scope.searchDashboards = (queryStr, callback) => {
|
||||
backendSrv.search({ query: queryStr }).then(hits => {
|
||||
const dashboards = _.map(hits, dash => {
|
||||
return dash.title;
|
||||
});
|
||||
|
||||
callback(dashboards);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.dashboardChanged = link => {
|
||||
backendSrv.search({ query: link.dashboard }).then(hits => {
|
||||
const dashboard = _.find(hits, { title: link.dashboard });
|
||||
if (dashboard) {
|
||||
if (dashboard.url) {
|
||||
link.url = dashboard.url;
|
||||
} else {
|
||||
// To support legacy url's
|
||||
link.dashUri = dashboard.uri;
|
||||
}
|
||||
link.title = dashboard.title;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$scope.deleteLink = link => {
|
||||
$scope.panel.links = _.without($scope.panel.links, link);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
angular
|
||||
.module('grafana.directives')
|
||||
.directive('panelLinksEditor', panelLinksEditor)
|
||||
.controller('PanelLinksEditorCtrl', PanelLinksEditorCtrl);
|
||||
@@ -0,0 +1,47 @@
|
||||
import { LinkSrv } from '../link_srv';
|
||||
import _ from 'lodash';
|
||||
|
||||
jest.mock('angular', () => {
|
||||
const AngularJSMock = require('test/mocks/angular');
|
||||
return new AngularJSMock();
|
||||
});
|
||||
|
||||
describe('linkSrv', () => {
|
||||
let linkSrv;
|
||||
const templateSrvMock = {};
|
||||
const timeSrvMock = {};
|
||||
|
||||
beforeEach(() => {
|
||||
linkSrv = new LinkSrv(templateSrvMock, timeSrvMock);
|
||||
});
|
||||
|
||||
describe('when appending query strings', () => {
|
||||
it('add ? to URL if not present', () => {
|
||||
const url = linkSrv.appendToQueryString('http://example.com', 'foo=bar');
|
||||
expect(url).toBe('http://example.com?foo=bar');
|
||||
});
|
||||
|
||||
it('do not add & to URL if ? is present but query string is empty', () => {
|
||||
const url = linkSrv.appendToQueryString('http://example.com?', 'foo=bar');
|
||||
expect(url).toBe('http://example.com?foo=bar');
|
||||
});
|
||||
|
||||
it('add & to URL if query string is present', () => {
|
||||
const url = linkSrv.appendToQueryString('http://example.com?foo=bar', 'hello=world');
|
||||
expect(url).toBe('http://example.com?foo=bar&hello=world');
|
||||
});
|
||||
|
||||
it('do not change the URL if there is nothing to append', () => {
|
||||
_.each(['', undefined, null], toAppend => {
|
||||
const url1 = linkSrv.appendToQueryString('http://example.com', toAppend);
|
||||
expect(url1).toBe('http://example.com');
|
||||
|
||||
const url2 = linkSrv.appendToQueryString('http://example.com?', toAppend);
|
||||
expect(url2).toBe('http://example.com?');
|
||||
|
||||
const url3 = linkSrv.appendToQueryString('http://example.com?foo=bar', toAppend);
|
||||
expect(url3).toBe('http://example.com?foo=bar');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,5 +0,0 @@
|
||||
<page-header model="ctrl.navModel"></page-header>
|
||||
|
||||
<div class="page-container page-body">
|
||||
<manage-dashboards />
|
||||
</div>
|
||||
@@ -1,13 +1,13 @@
|
||||
import { coreModule } from 'app/core/core';
|
||||
|
||||
var template = `
|
||||
const template = `
|
||||
<div class="gf-form-select-wrapper max-width-18">
|
||||
<select class="gf-form-input" ng-model="panel.repeat" ng-options="f.value as f.text for f in variables" ng-change="optionChanged()">
|
||||
<option value=""></option>
|
||||
</div>
|
||||
`;
|
||||
|
||||
/** @ngInject **/
|
||||
/** @ngInject */
|
||||
function dashRepeatOptionDirective(variableSrv) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
@@ -15,7 +15,7 @@ function dashRepeatOptionDirective(variableSrv) {
|
||||
scope: {
|
||||
panel: '=',
|
||||
},
|
||||
link: function(scope, element) {
|
||||
link: (scope, element) => {
|
||||
element.css({ display: 'block', width: '100%' });
|
||||
|
||||
scope.variables = variableSrv.variables.map(item => {
|
||||
@@ -36,7 +36,7 @@ function dashRepeatOptionDirective(variableSrv) {
|
||||
scope.panel.repeatDirection = 'h';
|
||||
}
|
||||
|
||||
scope.optionChanged = function() {
|
||||
scope.optionChanged = () => {
|
||||
if (scope.panel.repeat) {
|
||||
scope.panel.repeatDirection = 'h';
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ export class SaveDashboardAsModalCtrl {
|
||||
|
||||
/** @ngInject */
|
||||
constructor(private dashboardSrv) {
|
||||
var dashboard = this.dashboardSrv.getCurrent();
|
||||
const dashboard = this.dashboardSrv.getCurrent();
|
||||
this.clone = dashboard.getSaveModelClone();
|
||||
this.clone.id = null;
|
||||
this.clone.uid = '';
|
||||
|
||||
@@ -94,14 +94,14 @@ export class SaveDashboardModalCtrl {
|
||||
return;
|
||||
}
|
||||
|
||||
var options = {
|
||||
const options = {
|
||||
saveVariables: this.saveVariables,
|
||||
saveTimerange: this.saveTimerange,
|
||||
message: this.message,
|
||||
};
|
||||
|
||||
var dashboard = this.dashboardSrv.getCurrent();
|
||||
var saveModel = dashboard.getSaveModelClone(options);
|
||||
const dashboard = this.dashboardSrv.getCurrent();
|
||||
const saveModel = dashboard.getSaveModelClone(options);
|
||||
|
||||
this.isSaving = true;
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ export class SaveProvisionedDashboardModalCtrl {
|
||||
}
|
||||
|
||||
save() {
|
||||
var blob = new Blob([angular.toJson(this.dash, true)], {
|
||||
const blob = new Blob([angular.toJson(this.dash, true)], {
|
||||
type: 'application/json;charset=utf-8',
|
||||
});
|
||||
saveAs(blob, this.dash.title + '-' + new Date().getTime() + '.json');
|
||||
|
||||
@@ -109,7 +109,7 @@ export class SettingsCtrl {
|
||||
const params = this.$location.search();
|
||||
const url = this.$location.path();
|
||||
|
||||
for (let section of this.sections) {
|
||||
for (const section of this.sections) {
|
||||
const sectionParams = _.defaults({ editview: section.id }, params);
|
||||
section.url = config.appSubUrl + url + '?' + $.param(sectionParams);
|
||||
}
|
||||
@@ -156,7 +156,7 @@ export class SettingsCtrl {
|
||||
}
|
||||
|
||||
hideSettings() {
|
||||
var urlParams = this.$location.search();
|
||||
const urlParams = this.$location.search();
|
||||
delete urlParams.editview;
|
||||
setTimeout(() => {
|
||||
this.$rootScope.$apply(() => {
|
||||
@@ -179,8 +179,8 @@ export class SettingsCtrl {
|
||||
}
|
||||
|
||||
deleteDashboard() {
|
||||
var confirmText = '';
|
||||
var text2 = this.dashboard.title;
|
||||
let confirmText = '';
|
||||
let text2 = this.dashboard.title;
|
||||
|
||||
const alerts = _.sumBy(this.dashboard.panels, panel => {
|
||||
return panel.alert ? 1 : 0;
|
||||
|
||||
@@ -11,7 +11,7 @@ export function ShareModalCtrl($scope, $rootScope, $location, $timeout, timeSrv,
|
||||
};
|
||||
$scope.editor = { index: $scope.tabIndex || 0 };
|
||||
|
||||
$scope.init = function() {
|
||||
$scope.init = () => {
|
||||
$scope.modeSharePanel = $scope.panel ? true : false;
|
||||
|
||||
$scope.tabs = [{ title: 'Link', src: 'shareLink.html' }];
|
||||
@@ -34,17 +34,17 @@ export function ShareModalCtrl($scope, $rootScope, $location, $timeout, timeSrv,
|
||||
$scope.buildUrl();
|
||||
};
|
||||
|
||||
$scope.buildUrl = function() {
|
||||
var baseUrl = $location.absUrl();
|
||||
var queryStart = baseUrl.indexOf('?');
|
||||
$scope.buildUrl = () => {
|
||||
let baseUrl = $location.absUrl();
|
||||
const queryStart = baseUrl.indexOf('?');
|
||||
|
||||
if (queryStart !== -1) {
|
||||
baseUrl = baseUrl.substring(0, queryStart);
|
||||
}
|
||||
|
||||
var params = angular.copy($location.search());
|
||||
const params = angular.copy($location.search());
|
||||
|
||||
var range = timeSrv.timeRange();
|
||||
const range = timeSrv.timeRange();
|
||||
params.from = range.from.valueOf();
|
||||
params.to = range.to.valueOf();
|
||||
params.orgId = config.bootData.user.orgId;
|
||||
@@ -72,7 +72,7 @@ export function ShareModalCtrl($scope, $rootScope, $location, $timeout, timeSrv,
|
||||
|
||||
$scope.shareUrl = linkSrv.addParamsToUrl(baseUrl, params);
|
||||
|
||||
var soloUrl = baseUrl.replace(config.appSubUrl + '/dashboard/', config.appSubUrl + '/dashboard-solo/');
|
||||
let soloUrl = baseUrl.replace(config.appSubUrl + '/dashboard/', config.appSubUrl + '/dashboard-solo/');
|
||||
soloUrl = soloUrl.replace(config.appSubUrl + '/d/', config.appSubUrl + '/d-solo/');
|
||||
delete params.fullscreen;
|
||||
delete params.edit;
|
||||
@@ -90,15 +90,15 @@ export function ShareModalCtrl($scope, $rootScope, $location, $timeout, timeSrv,
|
||||
|
||||
// This function will try to return the proper full name of the local timezone
|
||||
// Chrome does not handle the timezone offset (but phantomjs does)
|
||||
$scope.getLocalTimeZone = function() {
|
||||
let utcOffset = '&tz=UTC' + encodeURIComponent(moment().format('Z'));
|
||||
$scope.getLocalTimeZone = () => {
|
||||
const utcOffset = '&tz=UTC' + encodeURIComponent(moment().format('Z'));
|
||||
|
||||
// Older browser does not the internationalization API
|
||||
if (!(<any>window).Intl) {
|
||||
if (!(window as any).Intl) {
|
||||
return utcOffset;
|
||||
}
|
||||
|
||||
const dateFormat = (<any>window).Intl.DateTimeFormat();
|
||||
const dateFormat = (window as any).Intl.DateTimeFormat();
|
||||
if (!dateFormat.resolvedOptions) {
|
||||
return utcOffset;
|
||||
}
|
||||
@@ -111,7 +111,7 @@ export function ShareModalCtrl($scope, $rootScope, $location, $timeout, timeSrv,
|
||||
return '&tz=' + encodeURIComponent(options.timeZone);
|
||||
};
|
||||
|
||||
$scope.getShareUrl = function() {
|
||||
$scope.getShareUrl = () => {
|
||||
return $scope.shareUrl;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import angular from 'angular';
|
||||
import _ from 'lodash';
|
||||
|
||||
export class ShareSnapshotCtrl {
|
||||
/** @ngInject **/
|
||||
/** @ngInject */
|
||||
constructor($scope, $rootScope, $location, backendSrv, $timeout, timeSrv) {
|
||||
$scope.snapshot = {
|
||||
name: $scope.dashboard.title,
|
||||
@@ -25,8 +25,8 @@ export class ShareSnapshotCtrl {
|
||||
{ text: 'Public on the web', value: 3 },
|
||||
];
|
||||
|
||||
$scope.init = function() {
|
||||
backendSrv.get('/api/snapshot/shared-options').then(function(options) {
|
||||
$scope.init = () => {
|
||||
backendSrv.get('/api/snapshot/shared-options').then(options => {
|
||||
$scope.externalUrl = options['externalSnapshotURL'];
|
||||
$scope.sharingButtonText = options['externalSnapshotName'];
|
||||
$scope.externalEnabled = options['externalEnabled'];
|
||||
@@ -35,7 +35,7 @@ export class ShareSnapshotCtrl {
|
||||
|
||||
$scope.apiUrl = '/api/snapshots';
|
||||
|
||||
$scope.createSnapshot = function(external) {
|
||||
$scope.createSnapshot = external => {
|
||||
$scope.dashboard.snapshot = {
|
||||
timestamp: new Date(),
|
||||
};
|
||||
@@ -49,25 +49,25 @@ export class ShareSnapshotCtrl {
|
||||
|
||||
$rootScope.$broadcast('refresh');
|
||||
|
||||
$timeout(function() {
|
||||
$timeout(() => {
|
||||
$scope.saveSnapshot(external);
|
||||
}, $scope.snapshot.timeoutSeconds * 1000);
|
||||
};
|
||||
|
||||
$scope.saveSnapshot = function(external) {
|
||||
var dash = $scope.dashboard.getSaveModelClone();
|
||||
$scope.saveSnapshot = external => {
|
||||
const dash = $scope.dashboard.getSaveModelClone();
|
||||
$scope.scrubDashboard(dash);
|
||||
|
||||
var cmdData = {
|
||||
const cmdData = {
|
||||
dashboard: dash,
|
||||
name: dash.title,
|
||||
expires: $scope.snapshot.expires,
|
||||
};
|
||||
|
||||
var postUrl = external ? $scope.externalUrl + $scope.apiUrl : $scope.apiUrl;
|
||||
const postUrl = external ? $scope.externalUrl + $scope.apiUrl : $scope.apiUrl;
|
||||
|
||||
backendSrv.post(postUrl, cmdData).then(
|
||||
function(results) {
|
||||
results => {
|
||||
$scope.loading = false;
|
||||
|
||||
if (external) {
|
||||
@@ -75,8 +75,8 @@ export class ShareSnapshotCtrl {
|
||||
$scope.snapshotUrl = results.url;
|
||||
$scope.saveExternalSnapshotRef(cmdData, results);
|
||||
} else {
|
||||
var url = $location.url();
|
||||
var baseUrl = $location.absUrl();
|
||||
const url = $location.url();
|
||||
let baseUrl = $location.absUrl();
|
||||
|
||||
if (url !== '/') {
|
||||
baseUrl = baseUrl.replace(url, '') + '/';
|
||||
@@ -88,17 +88,17 @@ export class ShareSnapshotCtrl {
|
||||
|
||||
$scope.step = 2;
|
||||
},
|
||||
function() {
|
||||
() => {
|
||||
$scope.loading = false;
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
$scope.getSnapshotUrl = function() {
|
||||
$scope.getSnapshotUrl = () => {
|
||||
return $scope.snapshotUrl;
|
||||
};
|
||||
|
||||
$scope.scrubDashboard = function(dash) {
|
||||
$scope.scrubDashboard = dash => {
|
||||
// change title
|
||||
dash.title = $scope.snapshot.name;
|
||||
|
||||
@@ -106,7 +106,7 @@ export class ShareSnapshotCtrl {
|
||||
dash.time = timeSrv.timeRange();
|
||||
|
||||
// remove panel queries & links
|
||||
_.each(dash.panels, function(panel) {
|
||||
_.each(dash.panels, panel => {
|
||||
panel.targets = [];
|
||||
panel.links = [];
|
||||
panel.datasource = null;
|
||||
@@ -114,10 +114,10 @@ export class ShareSnapshotCtrl {
|
||||
|
||||
// remove annotation queries
|
||||
dash.annotations.list = _.chain(dash.annotations.list)
|
||||
.filter(function(annotation) {
|
||||
.filter(annotation => {
|
||||
return annotation.enable;
|
||||
})
|
||||
.map(function(annotation) {
|
||||
.map(annotation => {
|
||||
return {
|
||||
name: annotation.name,
|
||||
enable: annotation.enable,
|
||||
@@ -131,7 +131,7 @@ export class ShareSnapshotCtrl {
|
||||
.value();
|
||||
|
||||
// remove template queries
|
||||
_.each(dash.templating.list, function(variable) {
|
||||
_.each(dash.templating.list, variable => {
|
||||
variable.query = '';
|
||||
variable.options = variable.current;
|
||||
variable.refresh = false;
|
||||
@@ -139,7 +139,7 @@ export class ShareSnapshotCtrl {
|
||||
|
||||
// snapshot single panel
|
||||
if ($scope.modeSharePanel) {
|
||||
var singlePanel = $scope.panel.getSaveModel();
|
||||
const singlePanel = $scope.panel.getSaveModel();
|
||||
singlePanel.gridPos.w = 24;
|
||||
singlePanel.gridPos.x = 0;
|
||||
singlePanel.gridPos.y = 0;
|
||||
@@ -149,21 +149,21 @@ export class ShareSnapshotCtrl {
|
||||
|
||||
// cleanup snapshotData
|
||||
delete $scope.dashboard.snapshot;
|
||||
$scope.dashboard.forEachPanel(function(panel) {
|
||||
$scope.dashboard.forEachPanel(panel => {
|
||||
delete panel.snapshotData;
|
||||
});
|
||||
_.each($scope.dashboard.annotations.list, function(annotation) {
|
||||
_.each($scope.dashboard.annotations.list, annotation => {
|
||||
delete annotation.snapshotData;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.deleteSnapshot = function() {
|
||||
backendSrv.get($scope.deleteUrl).then(function() {
|
||||
$scope.deleteSnapshot = () => {
|
||||
backendSrv.get($scope.deleteUrl).then(() => {
|
||||
$scope.step = 3;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.saveExternalSnapshotRef = function(cmdData, results) {
|
||||
$scope.saveExternalSnapshotRef = (cmdData, results) => {
|
||||
// save external in local instance as well
|
||||
cmdData.external = true;
|
||||
cmdData.key = results.key;
|
||||
|
||||
@@ -12,7 +12,7 @@ jest.mock('app/core/services/context_srv', () => ({
|
||||
describe('ChangeTracker', () => {
|
||||
let rootScope;
|
||||
let location;
|
||||
let timeout;
|
||||
const timeout = () => {};
|
||||
let tracker: ChangeTracker;
|
||||
let dash;
|
||||
let scope;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { DashboardImportCtrl } from '../dashboard_import_ctrl';
|
||||
import config from '../../../core/config';
|
||||
|
||||
describe('DashboardImportCtrl', function() {
|
||||
var ctx: any = {};
|
||||
describe('DashboardImportCtrl', () => {
|
||||
const ctx: any = {};
|
||||
|
||||
let navModelSrv;
|
||||
let backendSrv;
|
||||
@@ -26,8 +26,8 @@ describe('DashboardImportCtrl', function() {
|
||||
ctx.ctrl = new DashboardImportCtrl(backendSrv, validationSrv, navModelSrv, {}, {});
|
||||
});
|
||||
|
||||
describe('when uploading json', function() {
|
||||
beforeEach(function() {
|
||||
describe('when uploading json', () => {
|
||||
beforeEach(() => {
|
||||
config.datasources = {
|
||||
ds: {
|
||||
type: 'test-db',
|
||||
@@ -46,19 +46,19 @@ describe('DashboardImportCtrl', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('should build input model', function() {
|
||||
it('should build input model', () => {
|
||||
expect(ctx.ctrl.inputs.length).toBe(1);
|
||||
expect(ctx.ctrl.inputs[0].name).toBe('ds');
|
||||
expect(ctx.ctrl.inputs[0].info).toBe('Select a Test DB data source');
|
||||
});
|
||||
|
||||
it('should set inputValid to false', function() {
|
||||
it('should set inputValid to false', () => {
|
||||
expect(ctx.ctrl.inputsValid).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when specifying grafana.com url', function() {
|
||||
beforeEach(function() {
|
||||
describe('when specifying grafana.com url', () => {
|
||||
beforeEach(() => {
|
||||
ctx.ctrl.gnetUrl = 'http://grafana.com/dashboards/123';
|
||||
// setup api mock
|
||||
backendSrv.get = jest.fn(() => {
|
||||
@@ -69,13 +69,13 @@ describe('DashboardImportCtrl', function() {
|
||||
return ctx.ctrl.checkGnetDashboard();
|
||||
});
|
||||
|
||||
it('should call gnet api with correct dashboard id', function() {
|
||||
it('should call gnet api with correct dashboard id', () => {
|
||||
expect(backendSrv.get.mock.calls[0][0]).toBe('api/gnet/dashboards/123');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when specifying dashboard id', function() {
|
||||
beforeEach(function() {
|
||||
describe('when specifying dashboard id', () => {
|
||||
beforeEach(() => {
|
||||
ctx.ctrl.gnetUrl = '2342';
|
||||
// setup api mock
|
||||
backendSrv.get = jest.fn(() => {
|
||||
@@ -86,7 +86,7 @@ describe('DashboardImportCtrl', function() {
|
||||
return ctx.ctrl.checkGnetDashboard();
|
||||
});
|
||||
|
||||
it('should call gnet api with correct dashboard id', function() {
|
||||
it('should call gnet api with correct dashboard id', () => {
|
||||
expect(backendSrv.get.mock.calls[0][0]).toBe('api/gnet/dashboards/2342');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,14 +6,14 @@ import { expect } from 'test/lib/common';
|
||||
|
||||
jest.mock('app/core/services/context_srv', () => ({}));
|
||||
|
||||
describe('DashboardModel', function() {
|
||||
describe('when creating dashboard with old schema', function() {
|
||||
var model;
|
||||
var graph;
|
||||
var singlestat;
|
||||
var table;
|
||||
describe('DashboardModel', () => {
|
||||
describe('when creating dashboard with old schema', () => {
|
||||
let model;
|
||||
let graph;
|
||||
let singlestat;
|
||||
let table;
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(() => {
|
||||
model = new DashboardModel({
|
||||
services: {
|
||||
filter: { time: { from: 'now-1d', to: 'now' }, list: [{}] },
|
||||
@@ -65,52 +65,52 @@ describe('DashboardModel', function() {
|
||||
table = model.panels[2];
|
||||
});
|
||||
|
||||
it('should have title', function() {
|
||||
it('should have title', () => {
|
||||
expect(model.title).toBe('No Title');
|
||||
});
|
||||
|
||||
it('should have panel id', function() {
|
||||
it('should have panel id', () => {
|
||||
expect(graph.id).toBe(1);
|
||||
});
|
||||
|
||||
it('should move time and filtering list', function() {
|
||||
it('should move time and filtering list', () => {
|
||||
expect(model.time.from).toBe('now-1d');
|
||||
expect(model.templating.list[0].allFormat).toBe('glob');
|
||||
});
|
||||
|
||||
it('graphite panel should change name too graph', function() {
|
||||
it('graphite panel should change name too graph', () => {
|
||||
expect(graph.type).toBe('graph');
|
||||
});
|
||||
|
||||
it('single stat panel should have two thresholds', function() {
|
||||
it('single stat panel should have two thresholds', () => {
|
||||
expect(singlestat.thresholds).toBe('20,30');
|
||||
});
|
||||
|
||||
it('queries without refId should get it', function() {
|
||||
it('queries without refId should get it', () => {
|
||||
expect(graph.targets[1].refId).toBe('B');
|
||||
});
|
||||
|
||||
it('update legend setting', function() {
|
||||
it('update legend setting', () => {
|
||||
expect(graph.legend.show).toBe(true);
|
||||
});
|
||||
|
||||
it('move aliasYAxis to series override', function() {
|
||||
it('move aliasYAxis to series override', () => {
|
||||
expect(graph.seriesOverrides[0].alias).toBe('test');
|
||||
expect(graph.seriesOverrides[0].yaxis).toBe(2);
|
||||
});
|
||||
|
||||
it('should move pulldowns to new schema', function() {
|
||||
it('should move pulldowns to new schema', () => {
|
||||
expect(model.annotations.list[1].name).toBe('old');
|
||||
});
|
||||
|
||||
it('table panel should only have two thresholds values', function() {
|
||||
it('table panel should only have two thresholds values', () => {
|
||||
expect(table.styles[0].thresholds[0]).toBe('20');
|
||||
expect(table.styles[0].thresholds[1]).toBe('30');
|
||||
expect(table.styles[1].thresholds[0]).toBe('200');
|
||||
expect(table.styles[1].thresholds[1]).toBe('300');
|
||||
});
|
||||
|
||||
it('graph grid to yaxes options', function() {
|
||||
it('graph grid to yaxes options', () => {
|
||||
expect(graph.yaxes[0].min).toBe(1);
|
||||
expect(graph.yaxes[0].max).toBe(10);
|
||||
expect(graph.yaxes[0].format).toBe('kbyte');
|
||||
@@ -126,11 +126,11 @@ describe('DashboardModel', function() {
|
||||
expect(graph.y_formats).toBe(undefined);
|
||||
});
|
||||
|
||||
it('dashboard schema version should be set to latest', function() {
|
||||
it('dashboard schema version should be set to latest', () => {
|
||||
expect(model.schemaVersion).toBe(16);
|
||||
});
|
||||
|
||||
it('graph thresholds should be migrated', function() {
|
||||
it('graph thresholds should be migrated', () => {
|
||||
expect(graph.thresholds.length).toBe(2);
|
||||
expect(graph.thresholds[0].op).toBe('gt');
|
||||
expect(graph.thresholds[0].value).toBe(200);
|
||||
@@ -140,29 +140,29 @@ describe('DashboardModel', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('when migrating to the grid layout', function() {
|
||||
describe('when migrating to the grid layout', () => {
|
||||
let model;
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(() => {
|
||||
model = {
|
||||
rows: [],
|
||||
};
|
||||
});
|
||||
|
||||
it('should create proper grid', function() {
|
||||
it('should create proper grid', () => {
|
||||
model.rows = [createRow({ collapse: false, height: 8 }, [[6], [6]])];
|
||||
let dashboard = new DashboardModel(model);
|
||||
let panelGridPos = getGridPositions(dashboard);
|
||||
let expectedGrid = [{ x: 0, y: 0, w: 12, h: 8 }, { x: 12, y: 0, w: 12, h: 8 }];
|
||||
const dashboard = new DashboardModel(model);
|
||||
const panelGridPos = getGridPositions(dashboard);
|
||||
const expectedGrid = [{ x: 0, y: 0, w: 12, h: 8 }, { x: 12, y: 0, w: 12, h: 8 }];
|
||||
|
||||
expect(panelGridPos).toEqual(expectedGrid);
|
||||
});
|
||||
|
||||
it('should add special "row" panel if row is collapsed', function() {
|
||||
it('should add special "row" panel if row is collapsed', () => {
|
||||
model.rows = [createRow({ collapse: true, height: 8 }, [[6], [6]]), createRow({ height: 8 }, [[12]])];
|
||||
let dashboard = new DashboardModel(model);
|
||||
let panelGridPos = getGridPositions(dashboard);
|
||||
let expectedGrid = [
|
||||
const dashboard = new DashboardModel(model);
|
||||
const panelGridPos = getGridPositions(dashboard);
|
||||
const expectedGrid = [
|
||||
{ x: 0, y: 0, w: 24, h: 8 }, // row
|
||||
{ x: 0, y: 1, w: 24, h: 8 }, // row
|
||||
{ x: 0, y: 2, w: 24, h: 8 },
|
||||
@@ -171,14 +171,14 @@ describe('DashboardModel', function() {
|
||||
expect(panelGridPos).toEqual(expectedGrid);
|
||||
});
|
||||
|
||||
it('should add special "row" panel if row has visible title', function() {
|
||||
it('should add special "row" panel if row has visible title', () => {
|
||||
model.rows = [
|
||||
createRow({ showTitle: true, title: 'Row', height: 8 }, [[6], [6]]),
|
||||
createRow({ height: 8 }, [[12]]),
|
||||
];
|
||||
let dashboard = new DashboardModel(model);
|
||||
let panelGridPos = getGridPositions(dashboard);
|
||||
let expectedGrid = [
|
||||
const dashboard = new DashboardModel(model);
|
||||
const panelGridPos = getGridPositions(dashboard);
|
||||
const expectedGrid = [
|
||||
{ x: 0, y: 0, w: 24, h: 8 }, // row
|
||||
{ x: 0, y: 1, w: 12, h: 8 },
|
||||
{ x: 12, y: 1, w: 12, h: 8 },
|
||||
@@ -189,16 +189,16 @@ describe('DashboardModel', function() {
|
||||
expect(panelGridPos).toEqual(expectedGrid);
|
||||
});
|
||||
|
||||
it('should not add "row" panel if row has not visible title or not collapsed', function() {
|
||||
it('should not add "row" panel if row has not visible title or not collapsed', () => {
|
||||
model.rows = [
|
||||
createRow({ collapse: true, height: 8 }, [[12]]),
|
||||
createRow({ height: 8 }, [[12]]),
|
||||
createRow({ height: 8 }, [[12], [6], [6]]),
|
||||
createRow({ collapse: true, height: 8 }, [[12]]),
|
||||
];
|
||||
let dashboard = new DashboardModel(model);
|
||||
let panelGridPos = getGridPositions(dashboard);
|
||||
let expectedGrid = [
|
||||
const dashboard = new DashboardModel(model);
|
||||
const panelGridPos = getGridPositions(dashboard);
|
||||
const expectedGrid = [
|
||||
{ x: 0, y: 0, w: 24, h: 8 }, // row
|
||||
{ x: 0, y: 1, w: 24, h: 8 }, // row
|
||||
{ x: 0, y: 2, w: 24, h: 8 },
|
||||
@@ -212,11 +212,11 @@ describe('DashboardModel', function() {
|
||||
expect(panelGridPos).toEqual(expectedGrid);
|
||||
});
|
||||
|
||||
it('should add all rows if even one collapsed or titled row is present', function() {
|
||||
it('should add all rows if even one collapsed or titled row is present', () => {
|
||||
model.rows = [createRow({ collapse: true, height: 8 }, [[6], [6]]), createRow({ height: 8 }, [[12]])];
|
||||
let dashboard = new DashboardModel(model);
|
||||
let panelGridPos = getGridPositions(dashboard);
|
||||
let expectedGrid = [
|
||||
const dashboard = new DashboardModel(model);
|
||||
const panelGridPos = getGridPositions(dashboard);
|
||||
const expectedGrid = [
|
||||
{ x: 0, y: 0, w: 24, h: 8 }, // row
|
||||
{ x: 0, y: 1, w: 24, h: 8 }, // row
|
||||
{ x: 0, y: 2, w: 24, h: 8 },
|
||||
@@ -225,14 +225,14 @@ describe('DashboardModel', function() {
|
||||
expect(panelGridPos).toEqual(expectedGrid);
|
||||
});
|
||||
|
||||
it('should properly place panels with fixed height', function() {
|
||||
it('should properly place panels with fixed height', () => {
|
||||
model.rows = [
|
||||
createRow({ height: 6 }, [[6], [6, 3], [6, 3]]),
|
||||
createRow({ height: 6 }, [[4], [4], [4, 3], [4, 3]]),
|
||||
];
|
||||
let dashboard = new DashboardModel(model);
|
||||
let panelGridPos = getGridPositions(dashboard);
|
||||
let expectedGrid = [
|
||||
const dashboard = new DashboardModel(model);
|
||||
const panelGridPos = getGridPositions(dashboard);
|
||||
const expectedGrid = [
|
||||
{ x: 0, y: 0, w: 12, h: 6 },
|
||||
{ x: 12, y: 0, w: 12, h: 3 },
|
||||
{ x: 12, y: 3, w: 12, h: 3 },
|
||||
@@ -245,11 +245,11 @@ describe('DashboardModel', function() {
|
||||
expect(panelGridPos).toEqual(expectedGrid);
|
||||
});
|
||||
|
||||
it('should place panel to the right side of panel having bigger height', function() {
|
||||
it('should place panel to the right side of panel having bigger height', () => {
|
||||
model.rows = [createRow({ height: 6 }, [[4], [2, 3], [4, 6], [2, 3], [2, 3]])];
|
||||
let dashboard = new DashboardModel(model);
|
||||
let panelGridPos = getGridPositions(dashboard);
|
||||
let expectedGrid = [
|
||||
const dashboard = new DashboardModel(model);
|
||||
const panelGridPos = getGridPositions(dashboard);
|
||||
const expectedGrid = [
|
||||
{ x: 0, y: 0, w: 8, h: 6 },
|
||||
{ x: 8, y: 0, w: 4, h: 3 },
|
||||
{ x: 12, y: 0, w: 8, h: 6 },
|
||||
@@ -260,11 +260,11 @@ describe('DashboardModel', function() {
|
||||
expect(panelGridPos).toEqual(expectedGrid);
|
||||
});
|
||||
|
||||
it('should fill current row if it possible', function() {
|
||||
it('should fill current row if it possible', () => {
|
||||
model.rows = [createRow({ height: 9 }, [[4], [2, 3], [4, 6], [2, 3], [2, 3], [8, 3]])];
|
||||
let dashboard = new DashboardModel(model);
|
||||
let panelGridPos = getGridPositions(dashboard);
|
||||
let expectedGrid = [
|
||||
const dashboard = new DashboardModel(model);
|
||||
const panelGridPos = getGridPositions(dashboard);
|
||||
const expectedGrid = [
|
||||
{ x: 0, y: 0, w: 8, h: 9 },
|
||||
{ x: 8, y: 0, w: 4, h: 3 },
|
||||
{ x: 12, y: 0, w: 8, h: 6 },
|
||||
@@ -276,11 +276,11 @@ describe('DashboardModel', function() {
|
||||
expect(panelGridPos).toEqual(expectedGrid);
|
||||
});
|
||||
|
||||
it('should fill current row if it possible (2)', function() {
|
||||
it('should fill current row if it possible (2)', () => {
|
||||
model.rows = [createRow({ height: 8 }, [[4], [2, 3], [4, 6], [2, 3], [2, 3], [8, 3]])];
|
||||
let dashboard = new DashboardModel(model);
|
||||
let panelGridPos = getGridPositions(dashboard);
|
||||
let expectedGrid = [
|
||||
const dashboard = new DashboardModel(model);
|
||||
const panelGridPos = getGridPositions(dashboard);
|
||||
const expectedGrid = [
|
||||
{ x: 0, y: 0, w: 8, h: 8 },
|
||||
{ x: 8, y: 0, w: 4, h: 3 },
|
||||
{ x: 12, y: 0, w: 8, h: 6 },
|
||||
@@ -292,11 +292,11 @@ describe('DashboardModel', function() {
|
||||
expect(panelGridPos).toEqual(expectedGrid);
|
||||
});
|
||||
|
||||
it('should fill current row if panel height more than row height', function() {
|
||||
it('should fill current row if panel height more than row height', () => {
|
||||
model.rows = [createRow({ height: 6 }, [[4], [2, 3], [4, 8], [2, 3], [2, 3]])];
|
||||
let dashboard = new DashboardModel(model);
|
||||
let panelGridPos = getGridPositions(dashboard);
|
||||
let expectedGrid = [
|
||||
const dashboard = new DashboardModel(model);
|
||||
const panelGridPos = getGridPositions(dashboard);
|
||||
const expectedGrid = [
|
||||
{ x: 0, y: 0, w: 8, h: 6 },
|
||||
{ x: 8, y: 0, w: 4, h: 3 },
|
||||
{ x: 12, y: 0, w: 8, h: 8 },
|
||||
@@ -307,11 +307,11 @@ describe('DashboardModel', function() {
|
||||
expect(panelGridPos).toEqual(expectedGrid);
|
||||
});
|
||||
|
||||
it('should wrap panels to multiple rows', function() {
|
||||
it('should wrap panels to multiple rows', () => {
|
||||
model.rows = [createRow({ height: 6 }, [[6], [6], [12], [6], [3], [3]])];
|
||||
let dashboard = new DashboardModel(model);
|
||||
let panelGridPos = getGridPositions(dashboard);
|
||||
let expectedGrid = [
|
||||
const dashboard = new DashboardModel(model);
|
||||
const panelGridPos = getGridPositions(dashboard);
|
||||
const expectedGrid = [
|
||||
{ x: 0, y: 0, w: 12, h: 6 },
|
||||
{ x: 12, y: 0, w: 12, h: 6 },
|
||||
{ x: 0, y: 6, w: 24, h: 6 },
|
||||
@@ -323,14 +323,14 @@ describe('DashboardModel', function() {
|
||||
expect(panelGridPos).toEqual(expectedGrid);
|
||||
});
|
||||
|
||||
it('should add repeated row if repeat set', function() {
|
||||
it('should add repeated row if repeat set', () => {
|
||||
model.rows = [
|
||||
createRow({ showTitle: true, title: 'Row', height: 8, repeat: 'server' }, [[6]]),
|
||||
createRow({ height: 8 }, [[12]]),
|
||||
];
|
||||
let dashboard = new DashboardModel(model);
|
||||
let panelGridPos = getGridPositions(dashboard);
|
||||
let expectedGrid = [
|
||||
const dashboard = new DashboardModel(model);
|
||||
const panelGridPos = getGridPositions(dashboard);
|
||||
const expectedGrid = [
|
||||
{ x: 0, y: 0, w: 24, h: 8 },
|
||||
{ x: 0, y: 1, w: 12, h: 8 },
|
||||
{ x: 0, y: 9, w: 24, h: 8 },
|
||||
@@ -344,7 +344,7 @@ describe('DashboardModel', function() {
|
||||
expect(dashboard.panels[3].repeat).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should ignore repeated row', function() {
|
||||
it('should ignore repeated row', () => {
|
||||
model.rows = [
|
||||
createRow({ showTitle: true, title: 'Row1', height: 8, repeat: 'server' }, [[6]]),
|
||||
createRow(
|
||||
@@ -359,24 +359,24 @@ describe('DashboardModel', function() {
|
||||
),
|
||||
];
|
||||
|
||||
let dashboard = new DashboardModel(model);
|
||||
const dashboard = new DashboardModel(model);
|
||||
expect(dashboard.panels[0].repeat).toBe('server');
|
||||
expect(dashboard.panels.length).toBe(2);
|
||||
});
|
||||
|
||||
it('minSpan should be twice', function() {
|
||||
it('minSpan should be twice', () => {
|
||||
model.rows = [createRow({ height: 8 }, [[6]])];
|
||||
model.rows[0].panels[0] = { minSpan: 12 };
|
||||
|
||||
let dashboard = new DashboardModel(model);
|
||||
const dashboard = new DashboardModel(model);
|
||||
expect(dashboard.panels[0].minSpan).toBe(24);
|
||||
});
|
||||
|
||||
it('should assign id', function() {
|
||||
it('should assign id', () => {
|
||||
model.rows = [createRow({ collapse: true, height: 8 }, [[6], [6]])];
|
||||
model.rows[0].panels[0] = {};
|
||||
|
||||
let dashboard = new DashboardModel(model);
|
||||
const dashboard = new DashboardModel(model);
|
||||
expect(dashboard.panels[0].id).toBe(1);
|
||||
});
|
||||
});
|
||||
@@ -384,17 +384,18 @@ describe('DashboardModel', function() {
|
||||
|
||||
function createRow(options, panelDescriptions: any[]) {
|
||||
const PANEL_HEIGHT_STEP = GRID_CELL_HEIGHT + GRID_CELL_VMARGIN;
|
||||
let { collapse, height, showTitle, title, repeat, repeatIteration } = options;
|
||||
const { collapse, showTitle, title, repeat, repeatIteration } = options;
|
||||
let { height } = options;
|
||||
height = height * PANEL_HEIGHT_STEP;
|
||||
let panels = [];
|
||||
const panels = [];
|
||||
_.each(panelDescriptions, panelDesc => {
|
||||
let panel = { span: panelDesc[0] };
|
||||
const panel = { span: panelDesc[0] };
|
||||
if (panelDesc.length > 1) {
|
||||
panel['height'] = panelDesc[1] * PANEL_HEIGHT_STEP;
|
||||
}
|
||||
panels.push(panel);
|
||||
});
|
||||
let row = {
|
||||
const row = {
|
||||
collapse,
|
||||
height,
|
||||
showTitle,
|
||||
|
||||
@@ -4,54 +4,54 @@ import { PanelModel } from '../panel_model';
|
||||
|
||||
jest.mock('app/core/services/context_srv', () => ({}));
|
||||
|
||||
describe('DashboardModel', function() {
|
||||
describe('when creating new dashboard model defaults only', function() {
|
||||
var model;
|
||||
describe('DashboardModel', () => {
|
||||
describe('when creating new dashboard model defaults only', () => {
|
||||
let model;
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(() => {
|
||||
model = new DashboardModel({}, {});
|
||||
});
|
||||
|
||||
it('should have title', function() {
|
||||
it('should have title', () => {
|
||||
expect(model.title).toBe('No Title');
|
||||
});
|
||||
|
||||
it('should have meta', function() {
|
||||
it('should have meta', () => {
|
||||
expect(model.meta.canSave).toBe(true);
|
||||
expect(model.meta.canShare).toBe(true);
|
||||
});
|
||||
|
||||
it('should have default properties', function() {
|
||||
it('should have default properties', () => {
|
||||
expect(model.panels.length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when getting next panel id', function() {
|
||||
var model;
|
||||
describe('when getting next panel id', () => {
|
||||
let model;
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(() => {
|
||||
model = new DashboardModel({
|
||||
panels: [{ id: 5 }],
|
||||
});
|
||||
});
|
||||
|
||||
it('should return max id + 1', function() {
|
||||
it('should return max id + 1', () => {
|
||||
expect(model.getNextPanelId()).toBe(6);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getSaveModelClone', function() {
|
||||
describe('getSaveModelClone', () => {
|
||||
it('should sort keys', () => {
|
||||
var model = new DashboardModel({});
|
||||
var saveModel = model.getSaveModelClone();
|
||||
var keys = _.keys(saveModel);
|
||||
const model = new DashboardModel({});
|
||||
const saveModel = model.getSaveModelClone();
|
||||
const keys = _.keys(saveModel);
|
||||
|
||||
expect(keys[0]).toBe('annotations');
|
||||
expect(keys[1]).toBe('autoUpdate');
|
||||
});
|
||||
|
||||
it('should remove add panel panels', () => {
|
||||
var model = new DashboardModel({});
|
||||
const model = new DashboardModel({});
|
||||
model.addPanel({
|
||||
type: 'add-panel',
|
||||
});
|
||||
@@ -61,28 +61,28 @@ describe('DashboardModel', function() {
|
||||
model.addPanel({
|
||||
type: 'add-panel',
|
||||
});
|
||||
var saveModel = model.getSaveModelClone();
|
||||
var panels = saveModel.panels;
|
||||
const saveModel = model.getSaveModelClone();
|
||||
const panels = saveModel.panels;
|
||||
|
||||
expect(panels.length).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('row and panel manipulation', function() {
|
||||
var dashboard;
|
||||
describe('row and panel manipulation', () => {
|
||||
let dashboard;
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(() => {
|
||||
dashboard = new DashboardModel({});
|
||||
});
|
||||
|
||||
it('adding panel should new up panel model', function() {
|
||||
it('adding panel should new up panel model', () => {
|
||||
dashboard.addPanel({ type: 'test', title: 'test' });
|
||||
|
||||
expect(dashboard.panels[0] instanceof PanelModel).toBe(true);
|
||||
});
|
||||
|
||||
it('duplicate panel should try to add to the right if there is space', function() {
|
||||
var panel = { id: 10, gridPos: { x: 0, y: 0, w: 6, h: 2 } };
|
||||
it('duplicate panel should try to add to the right if there is space', () => {
|
||||
const panel = { id: 10, gridPos: { x: 0, y: 0, w: 6, h: 2 } };
|
||||
|
||||
dashboard.addPanel(panel);
|
||||
dashboard.duplicatePanel(dashboard.panels[0]);
|
||||
@@ -95,8 +95,8 @@ describe('DashboardModel', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('duplicate panel should remove repeat data', function() {
|
||||
var panel = {
|
||||
it('duplicate panel should remove repeat data', () => {
|
||||
const panel = {
|
||||
id: 10,
|
||||
gridPos: { x: 0, y: 0, w: 6, h: 2 },
|
||||
repeat: 'asd',
|
||||
@@ -111,29 +111,29 @@ describe('DashboardModel', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Given editable false dashboard', function() {
|
||||
var model;
|
||||
describe('Given editable false dashboard', () => {
|
||||
let model;
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(() => {
|
||||
model = new DashboardModel({ editable: false });
|
||||
});
|
||||
|
||||
it('Should set meta canEdit and canSave to false', function() {
|
||||
it('Should set meta canEdit and canSave to false', () => {
|
||||
expect(model.meta.canSave).toBe(false);
|
||||
expect(model.meta.canEdit).toBe(false);
|
||||
});
|
||||
|
||||
it('getSaveModelClone should remove meta', function() {
|
||||
var clone = model.getSaveModelClone();
|
||||
it('getSaveModelClone should remove meta', () => {
|
||||
const clone = model.getSaveModelClone();
|
||||
expect(clone.meta).toBe(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when loading dashboard with old influxdb query schema', function() {
|
||||
var model;
|
||||
var target;
|
||||
describe('when loading dashboard with old influxdb query schema', () => {
|
||||
let model;
|
||||
let target;
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(() => {
|
||||
model = new DashboardModel({
|
||||
panels: [
|
||||
{
|
||||
@@ -185,7 +185,7 @@ describe('DashboardModel', function() {
|
||||
target = model.panels[0].targets[0];
|
||||
});
|
||||
|
||||
it('should update query schema', function() {
|
||||
it('should update query schema', () => {
|
||||
expect(target.fields).toBe(undefined);
|
||||
expect(target.select.length).toBe(2);
|
||||
expect(target.select[0].length).toBe(4);
|
||||
@@ -196,10 +196,10 @@ describe('DashboardModel', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('when creating dashboard model with missing list for annoations or templating', function() {
|
||||
var model;
|
||||
describe('when creating dashboard model with missing list for annoations or templating', () => {
|
||||
let model;
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(() => {
|
||||
model = new DashboardModel({
|
||||
annotations: {
|
||||
enable: true,
|
||||
@@ -210,54 +210,54 @@ describe('DashboardModel', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('should add empty list', function() {
|
||||
it('should add empty list', () => {
|
||||
expect(model.annotations.list.length).toBe(1);
|
||||
expect(model.templating.list.length).toBe(0);
|
||||
});
|
||||
|
||||
it('should add builtin annotation query', function() {
|
||||
it('should add builtin annotation query', () => {
|
||||
expect(model.annotations.list[0].builtIn).toBe(1);
|
||||
expect(model.templating.list.length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Formatting epoch timestamp when timezone is set as utc', function() {
|
||||
var dashboard;
|
||||
describe('Formatting epoch timestamp when timezone is set as utc', () => {
|
||||
let dashboard;
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(() => {
|
||||
dashboard = new DashboardModel({ timezone: 'utc' });
|
||||
});
|
||||
|
||||
it('Should format timestamp with second resolution by default', function() {
|
||||
it('Should format timestamp with second resolution by default', () => {
|
||||
expect(dashboard.formatDate(1234567890000)).toBe('2009-02-13 23:31:30');
|
||||
});
|
||||
|
||||
it('Should format timestamp with second resolution even if second format is passed as parameter', function() {
|
||||
it('Should format timestamp with second resolution even if second format is passed as parameter', () => {
|
||||
expect(dashboard.formatDate(1234567890007, 'YYYY-MM-DD HH:mm:ss')).toBe('2009-02-13 23:31:30');
|
||||
});
|
||||
|
||||
it('Should format timestamp with millisecond resolution if format is passed as parameter', function() {
|
||||
it('Should format timestamp with millisecond resolution if format is passed as parameter', () => {
|
||||
expect(dashboard.formatDate(1234567890007, 'YYYY-MM-DD HH:mm:ss.SSS')).toBe('2009-02-13 23:31:30.007');
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateSubmenuVisibility with empty lists', function() {
|
||||
var model;
|
||||
describe('updateSubmenuVisibility with empty lists', () => {
|
||||
let model;
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(() => {
|
||||
model = new DashboardModel({});
|
||||
model.updateSubmenuVisibility();
|
||||
});
|
||||
|
||||
it('should not enable submmenu', function() {
|
||||
it('should not enable submmenu', () => {
|
||||
expect(model.meta.submenuEnabled).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateSubmenuVisibility with annotation', function() {
|
||||
var model;
|
||||
describe('updateSubmenuVisibility with annotation', () => {
|
||||
let model;
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(() => {
|
||||
model = new DashboardModel({
|
||||
annotations: {
|
||||
list: [{}],
|
||||
@@ -266,15 +266,15 @@ describe('DashboardModel', function() {
|
||||
model.updateSubmenuVisibility();
|
||||
});
|
||||
|
||||
it('should enable submmenu', function() {
|
||||
it('should enable submmenu', () => {
|
||||
expect(model.meta.submenuEnabled).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateSubmenuVisibility with template var', function() {
|
||||
var model;
|
||||
describe('updateSubmenuVisibility with template var', () => {
|
||||
let model;
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(() => {
|
||||
model = new DashboardModel({
|
||||
templating: {
|
||||
list: [{}],
|
||||
@@ -283,15 +283,15 @@ describe('DashboardModel', function() {
|
||||
model.updateSubmenuVisibility();
|
||||
});
|
||||
|
||||
it('should enable submmenu', function() {
|
||||
it('should enable submmenu', () => {
|
||||
expect(model.meta.submenuEnabled).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateSubmenuVisibility with hidden template var', function() {
|
||||
var model;
|
||||
describe('updateSubmenuVisibility with hidden template var', () => {
|
||||
let model;
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(() => {
|
||||
model = new DashboardModel({
|
||||
templating: {
|
||||
list: [{ hide: 2 }],
|
||||
@@ -300,15 +300,15 @@ describe('DashboardModel', function() {
|
||||
model.updateSubmenuVisibility();
|
||||
});
|
||||
|
||||
it('should not enable submmenu', function() {
|
||||
it('should not enable submmenu', () => {
|
||||
expect(model.meta.submenuEnabled).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateSubmenuVisibility with hidden annotation toggle', function() {
|
||||
var dashboard;
|
||||
describe('updateSubmenuVisibility with hidden annotation toggle', () => {
|
||||
let dashboard;
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(() => {
|
||||
dashboard = new DashboardModel({
|
||||
annotations: {
|
||||
list: [{ hide: true }],
|
||||
@@ -317,15 +317,15 @@ describe('DashboardModel', function() {
|
||||
dashboard.updateSubmenuVisibility();
|
||||
});
|
||||
|
||||
it('should not enable submmenu', function() {
|
||||
it('should not enable submmenu', () => {
|
||||
expect(dashboard.meta.submenuEnabled).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('When collapsing row', function() {
|
||||
var dashboard;
|
||||
describe('When collapsing row', () => {
|
||||
let dashboard;
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(() => {
|
||||
dashboard = new DashboardModel({
|
||||
panels: [
|
||||
{ id: 1, type: 'graph', gridPos: { x: 0, y: 0, w: 24, h: 2 } },
|
||||
@@ -338,36 +338,36 @@ describe('DashboardModel', function() {
|
||||
dashboard.toggleRow(dashboard.panels[1]);
|
||||
});
|
||||
|
||||
it('should remove panels and put them inside collapsed row', function() {
|
||||
it('should remove panels and put them inside collapsed row', () => {
|
||||
expect(dashboard.panels.length).toBe(3);
|
||||
expect(dashboard.panels[1].panels.length).toBe(2);
|
||||
});
|
||||
|
||||
describe('and when removing row and its panels', function() {
|
||||
beforeEach(function() {
|
||||
describe('and when removing row and its panels', () => {
|
||||
beforeEach(() => {
|
||||
dashboard.removeRow(dashboard.panels[1], true);
|
||||
});
|
||||
|
||||
it('should remove row and its panels', function() {
|
||||
it('should remove row and its panels', () => {
|
||||
expect(dashboard.panels.length).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('and when removing only the row', function() {
|
||||
beforeEach(function() {
|
||||
describe('and when removing only the row', () => {
|
||||
beforeEach(() => {
|
||||
dashboard.removeRow(dashboard.panels[1], false);
|
||||
});
|
||||
|
||||
it('should only remove row', function() {
|
||||
it('should only remove row', () => {
|
||||
expect(dashboard.panels.length).toBe(4);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('When expanding row', function() {
|
||||
var dashboard;
|
||||
describe('When expanding row', () => {
|
||||
let dashboard;
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(() => {
|
||||
dashboard = new DashboardModel({
|
||||
panels: [
|
||||
{ id: 1, type: 'graph', gridPos: { x: 0, y: 0, w: 24, h: 6 } },
|
||||
@@ -387,16 +387,16 @@ describe('DashboardModel', function() {
|
||||
dashboard.toggleRow(dashboard.panels[1]);
|
||||
});
|
||||
|
||||
it('should add panels back', function() {
|
||||
it('should add panels back', () => {
|
||||
expect(dashboard.panels.length).toBe(5);
|
||||
});
|
||||
|
||||
it('should add them below row in array', function() {
|
||||
it('should add them below row in array', () => {
|
||||
expect(dashboard.panels[2].id).toBe(3);
|
||||
expect(dashboard.panels[3].id).toBe(4);
|
||||
});
|
||||
|
||||
it('should position them below row', function() {
|
||||
it('should position them below row', () => {
|
||||
expect(dashboard.panels[2].gridPos).toMatchObject({
|
||||
x: 0,
|
||||
y: 7,
|
||||
@@ -405,7 +405,7 @@ describe('DashboardModel', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('should move panels below down', function() {
|
||||
it('should move panels below down', () => {
|
||||
expect(dashboard.panels[4].gridPos).toMatchObject({
|
||||
x: 0,
|
||||
y: 9,
|
||||
@@ -414,22 +414,22 @@ describe('DashboardModel', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('and when removing row and its panels', function() {
|
||||
beforeEach(function() {
|
||||
describe('and when removing row and its panels', () => {
|
||||
beforeEach(() => {
|
||||
dashboard.removeRow(dashboard.panels[1], true);
|
||||
});
|
||||
|
||||
it('should remove row and its panels', function() {
|
||||
it('should remove row and its panels', () => {
|
||||
expect(dashboard.panels.length).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('and when removing only the row', function() {
|
||||
beforeEach(function() {
|
||||
describe('and when removing only the row', () => {
|
||||
beforeEach(() => {
|
||||
dashboard.removeRow(dashboard.panels[1], false);
|
||||
});
|
||||
|
||||
it('should only remove row', function() {
|
||||
it('should only remove row', () => {
|
||||
expect(dashboard.panels.length).toBe(4);
|
||||
});
|
||||
});
|
||||
@@ -457,16 +457,16 @@ describe('DashboardModel', function() {
|
||||
});
|
||||
|
||||
it('getSaveModelClone should return original time when saveTimerange=false', () => {
|
||||
let options = { saveTimerange: false };
|
||||
let saveModel = model.getSaveModelClone(options);
|
||||
const options = { saveTimerange: false };
|
||||
const saveModel = model.getSaveModelClone(options);
|
||||
|
||||
expect(saveModel.time.from).toBe('now-6h');
|
||||
expect(saveModel.time.to).toBe('now');
|
||||
});
|
||||
|
||||
it('getSaveModelClone should return updated time when saveTimerange=true', () => {
|
||||
let options = { saveTimerange: true };
|
||||
let saveModel = model.getSaveModelClone(options);
|
||||
const options = { saveTimerange: true };
|
||||
const saveModel = model.getSaveModelClone(options);
|
||||
|
||||
expect(saveModel.time.from).toBe('now-3h');
|
||||
expect(saveModel.time.to).toBe('now-1h');
|
||||
@@ -478,16 +478,16 @@ describe('DashboardModel', function() {
|
||||
});
|
||||
|
||||
it('getSaveModelClone should return original time when saveTimerange=false', () => {
|
||||
let options = { saveTimerange: false };
|
||||
let saveModel = model.getSaveModelClone(options);
|
||||
const options = { saveTimerange: false };
|
||||
const saveModel = model.getSaveModelClone(options);
|
||||
|
||||
expect(saveModel.time.from).toBe('now-6h');
|
||||
expect(saveModel.time.to).toBe('now');
|
||||
});
|
||||
|
||||
it('getSaveModelClone should return updated time when saveTimerange=true', () => {
|
||||
let options = { saveTimerange: true };
|
||||
let saveModel = model.getSaveModelClone(options);
|
||||
const options = { saveTimerange: true };
|
||||
const saveModel = model.getSaveModelClone(options);
|
||||
|
||||
expect(saveModel.time.from).toBe('now-3h');
|
||||
expect(saveModel.time.to).toBe('now-1h');
|
||||
@@ -542,8 +542,8 @@ describe('DashboardModel', function() {
|
||||
it('getSaveModelClone should return original variable when saveVariables=false', () => {
|
||||
model.templating.list[0].current.text = 'server_002';
|
||||
|
||||
let options = { saveVariables: false };
|
||||
let saveModel = model.getSaveModelClone(options);
|
||||
const options = { saveVariables: false };
|
||||
const saveModel = model.getSaveModelClone(options);
|
||||
|
||||
expect(saveModel.templating.list[0].current.text).toBe('server_001');
|
||||
});
|
||||
@@ -551,8 +551,8 @@ describe('DashboardModel', function() {
|
||||
it('getSaveModelClone should return updated variable when saveVariables=true', () => {
|
||||
model.templating.list[0].current.text = 'server_002';
|
||||
|
||||
let options = { saveVariables: true };
|
||||
let saveModel = model.getSaveModelClone(options);
|
||||
const options = { saveVariables: true };
|
||||
const saveModel = model.getSaveModelClone(options);
|
||||
|
||||
expect(saveModel.templating.list[0].current.text).toBe('server_002');
|
||||
});
|
||||
@@ -620,8 +620,8 @@ describe('DashboardModel', function() {
|
||||
it('getSaveModelClone should return original variable when saveVariables=false', () => {
|
||||
model.templating.list[0].filters[0].value = 'server 1';
|
||||
|
||||
let options = { saveVariables: false };
|
||||
let saveModel = model.getSaveModelClone(options);
|
||||
const options = { saveVariables: false };
|
||||
const saveModel = model.getSaveModelClone(options);
|
||||
|
||||
expect(saveModel.templating.list[0].filters[0].value).toBe('server 20');
|
||||
});
|
||||
@@ -629,8 +629,8 @@ describe('DashboardModel', function() {
|
||||
it('getSaveModelClone should return updated variable when saveVariables=true', () => {
|
||||
model.templating.list[0].filters[0].value = 'server 1';
|
||||
|
||||
let options = { saveVariables: true };
|
||||
let saveModel = model.getSaveModelClone(options);
|
||||
const options = { saveVariables: true };
|
||||
const saveModel = model.getSaveModelClone(options);
|
||||
|
||||
expect(saveModel.templating.list[0].filters[0].value).toBe('server 1');
|
||||
});
|
||||
|
||||
@@ -10,7 +10,7 @@ import { DashboardExporter } from '../export/exporter';
|
||||
import { DashboardModel } from '../dashboard_model';
|
||||
|
||||
describe('given dashboard with repeated panels', () => {
|
||||
var dash, exported;
|
||||
let dash, exported;
|
||||
|
||||
beforeEach(done => {
|
||||
dash = {
|
||||
@@ -89,7 +89,7 @@ describe('given dashboard with repeated panels', () => {
|
||||
config.buildInfo.version = '3.0.2';
|
||||
|
||||
//Stubs test function calls
|
||||
var datasourceSrvStub = { get: jest.fn(arg => getStub(arg)) };
|
||||
const datasourceSrvStub = { get: jest.fn(arg => getStub(arg)) };
|
||||
|
||||
config.panels['graph'] = {
|
||||
id: 'graph',
|
||||
@@ -110,7 +110,7 @@ describe('given dashboard with repeated panels', () => {
|
||||
};
|
||||
|
||||
dash = new DashboardModel(dash, {});
|
||||
var exporter = new DashboardExporter(datasourceSrvStub);
|
||||
const exporter = new DashboardExporter(datasourceSrvStub);
|
||||
exporter.makeExportable(dash).then(clean => {
|
||||
exported = clean;
|
||||
done();
|
||||
@@ -118,12 +118,12 @@ describe('given dashboard with repeated panels', () => {
|
||||
});
|
||||
|
||||
it('should replace datasource refs', () => {
|
||||
var panel = exported.panels[0];
|
||||
const panel = exported.panels[0];
|
||||
expect(panel.datasource).toBe('${DS_GFDB}');
|
||||
});
|
||||
|
||||
it('should replace datasource refs in collapsed row', () => {
|
||||
var panel = exported.panels[5].panels[0];
|
||||
const panel = exported.panels[5].panels[0];
|
||||
expect(panel.datasource).toBe('${DS_GFDB}');
|
||||
});
|
||||
|
||||
@@ -145,7 +145,7 @@ describe('given dashboard with repeated panels', () => {
|
||||
});
|
||||
|
||||
it('should add datasource to required', () => {
|
||||
var require = _.find(exported.__requires, { name: 'TestDB' });
|
||||
const require = _.find(exported.__requires, { name: 'TestDB' });
|
||||
expect(require.name).toBe('TestDB');
|
||||
expect(require.id).toBe('testdb');
|
||||
expect(require.type).toBe('datasource');
|
||||
@@ -153,52 +153,52 @@ describe('given dashboard with repeated panels', () => {
|
||||
});
|
||||
|
||||
it('should not add built in datasources to required', () => {
|
||||
var require = _.find(exported.__requires, { name: 'Mixed' });
|
||||
const require = _.find(exported.__requires, { name: 'Mixed' });
|
||||
expect(require).toBe(undefined);
|
||||
});
|
||||
|
||||
it('should add datasources used in mixed mode', () => {
|
||||
var require = _.find(exported.__requires, { name: 'OtherDB' });
|
||||
const require = _.find(exported.__requires, { name: 'OtherDB' });
|
||||
expect(require).not.toBe(undefined);
|
||||
});
|
||||
|
||||
it('should add graph panel to required', () => {
|
||||
var require = _.find(exported.__requires, { name: 'Graph' });
|
||||
const require = _.find(exported.__requires, { name: 'Graph' });
|
||||
expect(require.name).toBe('Graph');
|
||||
expect(require.id).toBe('graph');
|
||||
expect(require.version).toBe('1.1.0');
|
||||
});
|
||||
|
||||
it('should add table panel to required', () => {
|
||||
var require = _.find(exported.__requires, { name: 'Table' });
|
||||
const require = _.find(exported.__requires, { name: 'Table' });
|
||||
expect(require.name).toBe('Table');
|
||||
expect(require.id).toBe('table');
|
||||
expect(require.version).toBe('1.1.1');
|
||||
});
|
||||
|
||||
it('should add heatmap panel to required', () => {
|
||||
var require = _.find(exported.__requires, { name: 'Heatmap' });
|
||||
const require = _.find(exported.__requires, { name: 'Heatmap' });
|
||||
expect(require.name).toBe('Heatmap');
|
||||
expect(require.id).toBe('heatmap');
|
||||
expect(require.version).toBe('1.1.2');
|
||||
});
|
||||
|
||||
it('should add grafana version', () => {
|
||||
var require = _.find(exported.__requires, { name: 'Grafana' });
|
||||
const require = _.find(exported.__requires, { name: 'Grafana' });
|
||||
expect(require.type).toBe('grafana');
|
||||
expect(require.id).toBe('grafana');
|
||||
expect(require.version).toBe('3.0.2');
|
||||
});
|
||||
|
||||
it('should add constant template variables as inputs', () => {
|
||||
var input = _.find(exported.__inputs, { name: 'VAR_PREFIX' });
|
||||
const input = _.find(exported.__inputs, { name: 'VAR_PREFIX' });
|
||||
expect(input.type).toBe('constant');
|
||||
expect(input.label).toBe('prefix');
|
||||
expect(input.value).toBe('collectd');
|
||||
});
|
||||
|
||||
it('should templatize constant variables', () => {
|
||||
var variable = _.find(exported.templating.list, { name: 'prefix' });
|
||||
const variable = _.find(exported.templating.list, { name: 'prefix' });
|
||||
expect(variable.query).toBe('${VAR_PREFIX}');
|
||||
expect(variable.current.text).toBe('${VAR_PREFIX}');
|
||||
expect(variable.current.value).toBe('${VAR_PREFIX}');
|
||||
@@ -208,7 +208,7 @@ describe('given dashboard with repeated panels', () => {
|
||||
});
|
||||
|
||||
// Stub responses
|
||||
var stubs = [];
|
||||
const stubs = [];
|
||||
stubs['gfdb'] = {
|
||||
name: 'gfdb',
|
||||
meta: { id: 'testdb', info: { version: '1.2.1' }, name: 'TestDB' },
|
||||
|
||||
@@ -70,7 +70,7 @@ describe('HistoryListCtrl', () => {
|
||||
});
|
||||
|
||||
it('should add a checked property to each revision', () => {
|
||||
let actual = _.filter(historyListCtrl.revisions, rev => rev.hasOwnProperty('checked'));
|
||||
const actual = _.filter(historyListCtrl.revisions, rev => rev.hasOwnProperty('checked'));
|
||||
expect(actual.length).toBe(4);
|
||||
});
|
||||
|
||||
@@ -78,7 +78,7 @@ describe('HistoryListCtrl', () => {
|
||||
historyListCtrl.revisions[0].checked = true;
|
||||
historyListCtrl.revisions[2].checked = true;
|
||||
historyListCtrl.reset();
|
||||
let actual = _.filter(historyListCtrl.revisions, rev => !rev.checked);
|
||||
const actual = _.filter(historyListCtrl.revisions, rev => !rev.checked);
|
||||
expect(actual.length).toBe(4);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,11 +4,11 @@ import { HistorySrv } from '../history/history_srv';
|
||||
import { DashboardModel } from '../dashboard_model';
|
||||
jest.mock('app/core/store');
|
||||
|
||||
describe('historySrv', function() {
|
||||
describe('historySrv', () => {
|
||||
const versionsResponse = versions();
|
||||
const restoreResponse = restore;
|
||||
|
||||
let backendSrv = {
|
||||
const backendSrv = {
|
||||
get: jest.fn(() => Promise.resolve({})),
|
||||
post: jest.fn(() => Promise.resolve({})),
|
||||
};
|
||||
@@ -19,42 +19,42 @@ describe('historySrv', function() {
|
||||
const emptyDash = new DashboardModel({});
|
||||
const historyListOpts = { limit: 10, start: 0 };
|
||||
|
||||
describe('getHistoryList', function() {
|
||||
it('should return a versions array for the given dashboard id', function() {
|
||||
describe('getHistoryList', () => {
|
||||
it('should return a versions array for the given dashboard id', () => {
|
||||
backendSrv.get = jest.fn(() => Promise.resolve(versionsResponse));
|
||||
historySrv = new HistorySrv(backendSrv);
|
||||
|
||||
return historySrv.getHistoryList(dash, historyListOpts).then(function(versions) {
|
||||
return historySrv.getHistoryList(dash, historyListOpts).then(versions => {
|
||||
expect(versions).toEqual(versionsResponse);
|
||||
});
|
||||
});
|
||||
|
||||
it('should return an empty array when not given an id', function() {
|
||||
return historySrv.getHistoryList(emptyDash, historyListOpts).then(function(versions) {
|
||||
it('should return an empty array when not given an id', () => {
|
||||
return historySrv.getHistoryList(emptyDash, historyListOpts).then(versions => {
|
||||
expect(versions).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
it('should return an empty array when not given a dashboard', function() {
|
||||
return historySrv.getHistoryList(null, historyListOpts).then(function(versions) {
|
||||
it('should return an empty array when not given a dashboard', () => {
|
||||
return historySrv.getHistoryList(null, historyListOpts).then(versions => {
|
||||
expect(versions).toEqual([]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('restoreDashboard', () => {
|
||||
it('should return a success response given valid parameters', function() {
|
||||
let version = 6;
|
||||
it('should return a success response given valid parameters', () => {
|
||||
const version = 6;
|
||||
backendSrv.post = jest.fn(() => Promise.resolve(restoreResponse(version)));
|
||||
historySrv = new HistorySrv(backendSrv);
|
||||
return historySrv.restoreDashboard(dash, version).then(function(response) {
|
||||
return historySrv.restoreDashboard(dash, version).then(response => {
|
||||
expect(response).toEqual(restoreResponse(version));
|
||||
});
|
||||
});
|
||||
|
||||
it('should return an empty object when not given an id', async () => {
|
||||
historySrv = new HistorySrv(backendSrv);
|
||||
let rsp = await historySrv.restoreDashboard(emptyDash, 6);
|
||||
const rsp = await historySrv.restoreDashboard(emptyDash, 6);
|
||||
expect(rsp).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,11 +4,11 @@ import { expect } from 'test/lib/common';
|
||||
|
||||
jest.mock('app/core/services/context_srv', () => ({}));
|
||||
|
||||
describe('given dashboard with panel repeat', function() {
|
||||
var dashboard;
|
||||
describe('given dashboard with panel repeat', () => {
|
||||
let dashboard;
|
||||
|
||||
beforeEach(function() {
|
||||
let dashboardJSON = {
|
||||
beforeEach(() => {
|
||||
const dashboardJSON = {
|
||||
panels: [
|
||||
{ id: 1, type: 'row', gridPos: { x: 0, y: 0, h: 1, w: 24 } },
|
||||
{ id: 2, repeat: 'apps', repeatDirection: 'h', gridPos: { x: 0, y: 1, h: 2, w: 8 } },
|
||||
@@ -35,7 +35,7 @@ describe('given dashboard with panel repeat', function() {
|
||||
dashboard.processRepeats();
|
||||
});
|
||||
|
||||
it('should repeat panels when row is expanding', function() {
|
||||
it('should repeat panels when row is expanding', () => {
|
||||
expect(dashboard.panels.length).toBe(4);
|
||||
|
||||
// toggle row
|
||||
@@ -55,10 +55,10 @@ describe('given dashboard with panel repeat', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('given dashboard with panel repeat in horizontal direction', function() {
|
||||
var dashboard;
|
||||
describe('given dashboard with panel repeat in horizontal direction', () => {
|
||||
let dashboard;
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(() => {
|
||||
dashboard = new DashboardModel({
|
||||
panels: [
|
||||
{
|
||||
@@ -89,22 +89,22 @@ describe('given dashboard with panel repeat in horizontal direction', function()
|
||||
dashboard.processRepeats();
|
||||
});
|
||||
|
||||
it('should repeat panel 3 times', function() {
|
||||
it('should repeat panel 3 times', () => {
|
||||
expect(dashboard.panels.length).toBe(3);
|
||||
});
|
||||
|
||||
it('should mark panel repeated', function() {
|
||||
it('should mark panel repeated', () => {
|
||||
expect(dashboard.panels[0].repeat).toBe('apps');
|
||||
expect(dashboard.panels[1].repeatPanelId).toBe(2);
|
||||
});
|
||||
|
||||
it('should set scopedVars on panels', function() {
|
||||
it('should set scopedVars on panels', () => {
|
||||
expect(dashboard.panels[0].scopedVars.apps.value).toBe('se1');
|
||||
expect(dashboard.panels[1].scopedVars.apps.value).toBe('se2');
|
||||
expect(dashboard.panels[2].scopedVars.apps.value).toBe('se3');
|
||||
});
|
||||
|
||||
it('should place on first row and adjust width so all fit', function() {
|
||||
it('should place on first row and adjust width so all fit', () => {
|
||||
expect(dashboard.panels[0].gridPos).toMatchObject({
|
||||
x: 0,
|
||||
y: 0,
|
||||
@@ -125,23 +125,23 @@ describe('given dashboard with panel repeat in horizontal direction', function()
|
||||
});
|
||||
});
|
||||
|
||||
describe('After a second iteration', function() {
|
||||
beforeEach(function() {
|
||||
describe('After a second iteration', () => {
|
||||
beforeEach(() => {
|
||||
dashboard.panels[0].fill = 10;
|
||||
dashboard.processRepeats();
|
||||
});
|
||||
|
||||
it('reused panel should copy properties from source', function() {
|
||||
it('reused panel should copy properties from source', () => {
|
||||
expect(dashboard.panels[1].fill).toBe(10);
|
||||
});
|
||||
|
||||
it('should have same panel count', function() {
|
||||
it('should have same panel count', () => {
|
||||
expect(dashboard.panels.length).toBe(3);
|
||||
});
|
||||
});
|
||||
|
||||
describe('After a second iteration with different variable', function() {
|
||||
beforeEach(function() {
|
||||
describe('After a second iteration with different variable', () => {
|
||||
beforeEach(() => {
|
||||
dashboard.templating.list.push({
|
||||
name: 'server',
|
||||
current: { text: 'se1, se2, se3', value: ['se1'] },
|
||||
@@ -151,46 +151,46 @@ describe('given dashboard with panel repeat in horizontal direction', function()
|
||||
dashboard.processRepeats();
|
||||
});
|
||||
|
||||
it('should remove scopedVars value for last variable', function() {
|
||||
it('should remove scopedVars value for last variable', () => {
|
||||
expect(dashboard.panels[0].scopedVars.apps).toBe(undefined);
|
||||
});
|
||||
|
||||
it('should have new variable value in scopedVars', function() {
|
||||
it('should have new variable value in scopedVars', () => {
|
||||
expect(dashboard.panels[0].scopedVars.server.value).toBe('se1');
|
||||
});
|
||||
});
|
||||
|
||||
describe('After a second iteration and selected values reduced', function() {
|
||||
beforeEach(function() {
|
||||
describe('After a second iteration and selected values reduced', () => {
|
||||
beforeEach(() => {
|
||||
dashboard.templating.list[0].options[1].selected = false;
|
||||
dashboard.processRepeats();
|
||||
});
|
||||
|
||||
it('should clean up repeated panel', function() {
|
||||
it('should clean up repeated panel', () => {
|
||||
expect(dashboard.panels.length).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('After a second iteration and panel repeat is turned off', function() {
|
||||
beforeEach(function() {
|
||||
describe('After a second iteration and panel repeat is turned off', () => {
|
||||
beforeEach(() => {
|
||||
dashboard.panels[0].repeat = null;
|
||||
dashboard.processRepeats();
|
||||
});
|
||||
|
||||
it('should clean up repeated panel', function() {
|
||||
it('should clean up repeated panel', () => {
|
||||
expect(dashboard.panels.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should remove scoped vars from reused panel', function() {
|
||||
it('should remove scoped vars from reused panel', () => {
|
||||
expect(dashboard.panels[0].scopedVars).toBe(undefined);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('given dashboard with panel repeat in vertical direction', function() {
|
||||
var dashboard;
|
||||
describe('given dashboard with panel repeat in vertical direction', () => {
|
||||
let dashboard;
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(() => {
|
||||
dashboard = new DashboardModel({
|
||||
panels: [
|
||||
{ id: 1, type: 'row', gridPos: { x: 0, y: 0, h: 1, w: 24 } },
|
||||
@@ -218,7 +218,7 @@ describe('given dashboard with panel repeat in vertical direction', function() {
|
||||
dashboard.processRepeats();
|
||||
});
|
||||
|
||||
it('should place on items on top of each other and keep witdh', function() {
|
||||
it('should place on items on top of each other and keep witdh', () => {
|
||||
expect(dashboard.panels[0].gridPos).toMatchObject({ x: 0, y: 0, h: 1, w: 24 }); // first row
|
||||
|
||||
expect(dashboard.panels[1].gridPos).toMatchObject({ x: 5, y: 1, h: 2, w: 8 });
|
||||
@@ -271,8 +271,8 @@ describe('given dashboard with row repeat and panel repeat in horizontal directi
|
||||
});
|
||||
|
||||
it('should panels in self row', () => {
|
||||
const panel_types = _.map(dashboard.panels, 'type');
|
||||
expect(panel_types).toEqual([
|
||||
const panelTypes = _.map(dashboard.panels, 'type');
|
||||
expect(panelTypes).toEqual([
|
||||
'row',
|
||||
'graph',
|
||||
'graph',
|
||||
@@ -290,7 +290,7 @@ describe('given dashboard with row repeat and panel repeat in horizontal directi
|
||||
]);
|
||||
});
|
||||
|
||||
it('should be placed in their places', function() {
|
||||
it('should be placed in their places', () => {
|
||||
expect(dashboard.panels[0].gridPos).toMatchObject({ x: 0, y: 0, h: 1, w: 24 }); // 1st row
|
||||
|
||||
expect(dashboard.panels[1].gridPos).toMatchObject({ x: 0, y: 1, h: 2, w: 6 });
|
||||
@@ -311,10 +311,10 @@ describe('given dashboard with row repeat and panel repeat in horizontal directi
|
||||
});
|
||||
});
|
||||
|
||||
describe('given dashboard with row repeat', function() {
|
||||
describe('given dashboard with row repeat', () => {
|
||||
let dashboard, dashboardJSON;
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(() => {
|
||||
dashboardJSON = {
|
||||
panels: [
|
||||
{
|
||||
@@ -349,12 +349,12 @@ describe('given dashboard with row repeat', function() {
|
||||
dashboard.processRepeats();
|
||||
});
|
||||
|
||||
it('should not repeat only row', function() {
|
||||
const panel_types = _.map(dashboard.panels, 'type');
|
||||
expect(panel_types).toEqual(['row', 'graph', 'graph', 'row', 'graph', 'graph', 'row', 'graph']);
|
||||
it('should not repeat only row', () => {
|
||||
const panelTypes = _.map(dashboard.panels, 'type');
|
||||
expect(panelTypes).toEqual(['row', 'graph', 'graph', 'row', 'graph', 'graph', 'row', 'graph']);
|
||||
});
|
||||
|
||||
it('should set scopedVars for each panel', function() {
|
||||
it('should set scopedVars for each panel', () => {
|
||||
dashboardJSON.templating.list[0].options[2].selected = true;
|
||||
dashboard = new DashboardModel(dashboardJSON);
|
||||
dashboard.processRepeats();
|
||||
@@ -375,12 +375,12 @@ describe('given dashboard with row repeat', function() {
|
||||
expect(scopedVars).toEqual(['se1', 'se1', 'se1', 'se2', 'se2', 'se2', 'se3', 'se3', 'se3']);
|
||||
});
|
||||
|
||||
it('should repeat only configured row', function() {
|
||||
it('should repeat only configured row', () => {
|
||||
expect(dashboard.panels[6].id).toBe(4);
|
||||
expect(dashboard.panels[7].id).toBe(5);
|
||||
});
|
||||
|
||||
it('should repeat only row if it is collapsed', function() {
|
||||
it('should repeat only row if it is collapsed', () => {
|
||||
dashboardJSON.panels = [
|
||||
{
|
||||
id: 1,
|
||||
@@ -399,13 +399,13 @@ describe('given dashboard with row repeat', function() {
|
||||
dashboard = new DashboardModel(dashboardJSON);
|
||||
dashboard.processRepeats();
|
||||
|
||||
const panel_types = _.map(dashboard.panels, 'type');
|
||||
expect(panel_types).toEqual(['row', 'row', 'row', 'graph']);
|
||||
const panelTypes = _.map(dashboard.panels, 'type');
|
||||
expect(panelTypes).toEqual(['row', 'row', 'row', 'graph']);
|
||||
expect(dashboard.panels[0].panels).toHaveLength(2);
|
||||
expect(dashboard.panels[1].panels).toHaveLength(2);
|
||||
});
|
||||
|
||||
it('should properly repeat multiple rows', function() {
|
||||
it('should properly repeat multiple rows', () => {
|
||||
dashboardJSON.panels = [
|
||||
{
|
||||
id: 1,
|
||||
@@ -441,8 +441,8 @@ describe('given dashboard with row repeat', function() {
|
||||
dashboard = new DashboardModel(dashboardJSON);
|
||||
dashboard.processRepeats();
|
||||
|
||||
const panel_types = _.map(dashboard.panels, 'type');
|
||||
expect(panel_types).toEqual([
|
||||
const panelTypes = _.map(dashboard.panels, 'type');
|
||||
expect(panelTypes).toEqual([
|
||||
'row',
|
||||
'graph',
|
||||
'graph',
|
||||
@@ -469,7 +469,7 @@ describe('given dashboard with row repeat', function() {
|
||||
expect(dashboard.panels[12].scopedVars['hosts'].value).toBe('backend02');
|
||||
});
|
||||
|
||||
it('should assign unique ids for repeated panels', function() {
|
||||
it('should assign unique ids for repeated panels', () => {
|
||||
dashboardJSON.panels = [
|
||||
{
|
||||
id: 1,
|
||||
@@ -488,7 +488,7 @@ describe('given dashboard with row repeat', function() {
|
||||
dashboard = new DashboardModel(dashboardJSON);
|
||||
dashboard.processRepeats();
|
||||
|
||||
const panel_ids = _.flattenDeep(
|
||||
const panelIds = _.flattenDeep(
|
||||
_.map(dashboard.panels, panel => {
|
||||
let ids = [];
|
||||
if (panel.panels && panel.panels.length) {
|
||||
@@ -498,10 +498,10 @@ describe('given dashboard with row repeat', function() {
|
||||
return ids;
|
||||
})
|
||||
);
|
||||
expect(panel_ids.length).toEqual(_.uniq(panel_ids).length);
|
||||
expect(panelIds.length).toEqual(_.uniq(panelIds).length);
|
||||
});
|
||||
|
||||
it('should place new panels in proper order', function() {
|
||||
it('should place new panels in proper order', () => {
|
||||
dashboardJSON.panels = [
|
||||
{ id: 1, type: 'row', gridPos: { x: 0, y: 0, h: 1, w: 24 }, repeat: 'apps' },
|
||||
{ id: 2, type: 'graph', gridPos: { x: 0, y: 1, h: 3, w: 12 } },
|
||||
@@ -511,10 +511,10 @@ describe('given dashboard with row repeat', function() {
|
||||
dashboard = new DashboardModel(dashboardJSON);
|
||||
dashboard.processRepeats();
|
||||
|
||||
const panel_types = _.map(dashboard.panels, 'type');
|
||||
expect(panel_types).toEqual(['row', 'graph', 'graph', 'graph', 'row', 'graph', 'graph', 'graph']);
|
||||
const panel_y_positions = _.map(dashboard.panels, p => p.gridPos.y);
|
||||
expect(panel_y_positions).toEqual([0, 1, 1, 5, 7, 8, 8, 12]);
|
||||
const panelTypes = _.map(dashboard.panels, 'type');
|
||||
expect(panelTypes).toEqual(['row', 'graph', 'graph', 'graph', 'row', 'graph', 'graph', 'graph']);
|
||||
const panelYPositions = _.map(dashboard.panels, p => p.gridPos.y);
|
||||
expect(panelYPositions).toEqual([0, 1, 1, 5, 7, 8, 8, 12]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -566,8 +566,8 @@ describe('given dashboard with row and panel repeat', () => {
|
||||
});
|
||||
|
||||
it('should repeat row and panels for each row', () => {
|
||||
const panel_types = _.map(dashboard.panels, 'type');
|
||||
expect(panel_types).toEqual(['row', 'graph', 'graph', 'row', 'graph', 'graph']);
|
||||
const panelTypes = _.map(dashboard.panels, 'type');
|
||||
expect(panelTypes).toEqual(['row', 'graph', 'graph', 'row', 'graph', 'graph']);
|
||||
});
|
||||
|
||||
it('should clean up old repeated panels', () => {
|
||||
@@ -592,8 +592,8 @@ describe('given dashboard with row and panel repeat', () => {
|
||||
dashboard = new DashboardModel(dashboardJSON);
|
||||
dashboard.processRepeats();
|
||||
|
||||
const panel_types = _.map(dashboard.panels, 'type');
|
||||
expect(panel_types).toEqual(['row', 'graph', 'graph', 'row', 'graph', 'graph']);
|
||||
const panelTypes = _.map(dashboard.panels, 'type');
|
||||
expect(panelTypes).toEqual(['row', 'graph', 'graph', 'row', 'graph', 'graph']);
|
||||
});
|
||||
|
||||
it('should set scopedVars for each row', () => {
|
||||
@@ -646,7 +646,7 @@ describe('given dashboard with row and panel repeat', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should repeat panels when row is expanding', function() {
|
||||
it('should repeat panels when row is expanding', () => {
|
||||
dashboard = new DashboardModel(dashboardJSON);
|
||||
dashboard.processRepeats();
|
||||
|
||||
|
||||
@@ -4,25 +4,25 @@ import { describe, it, expect } from 'test/lib/common';
|
||||
describe('saving dashboard as', () => {
|
||||
function scenario(name, panel, verify) {
|
||||
describe(name, () => {
|
||||
var json = {
|
||||
const json = {
|
||||
title: 'name',
|
||||
panels: [panel],
|
||||
};
|
||||
|
||||
var mockDashboardSrv = {
|
||||
getCurrent: function() {
|
||||
const mockDashboardSrv = {
|
||||
getCurrent: () => {
|
||||
return {
|
||||
id: 5,
|
||||
meta: {},
|
||||
getSaveModelClone: function() {
|
||||
getSaveModelClone: () => {
|
||||
return json;
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
var ctrl = new SaveDashboardAsModalCtrl(mockDashboardSrv);
|
||||
var ctx: any = {
|
||||
const ctrl = new SaveDashboardAsModalCtrl(mockDashboardSrv);
|
||||
const ctx: any = {
|
||||
clone: ctrl.clone,
|
||||
ctrl: ctrl,
|
||||
panel: panel,
|
||||
@@ -35,14 +35,14 @@ describe('saving dashboard as', () => {
|
||||
}
|
||||
|
||||
scenario('default values', {}, ctx => {
|
||||
var clone = ctx.clone;
|
||||
const clone = ctx.clone;
|
||||
expect(clone.id).toBe(null);
|
||||
expect(clone.title).toBe('name Copy');
|
||||
expect(clone.editable).toBe(true);
|
||||
expect(clone.hideControls).toBe(false);
|
||||
});
|
||||
|
||||
var graphPanel = {
|
||||
const graphPanel = {
|
||||
id: 1,
|
||||
type: 'graph',
|
||||
alert: { rule: 1 },
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
import { SaveProvisionedDashboardModalCtrl } from '../save_provisioned_modal';
|
||||
|
||||
describe('SaveProvisionedDashboardModalCtrl', () => {
|
||||
var json = {
|
||||
const json = {
|
||||
title: 'name',
|
||||
id: 5,
|
||||
};
|
||||
|
||||
var mockDashboardSrv = {
|
||||
getCurrent: function() {
|
||||
const mockDashboardSrv = {
|
||||
getCurrent: () => {
|
||||
return {
|
||||
id: 5,
|
||||
meta: {},
|
||||
getSaveModelClone: function() {
|
||||
getSaveModelClone: () => {
|
||||
return json;
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
var ctrl = new SaveProvisionedDashboardModalCtrl(mockDashboardSrv);
|
||||
const ctrl = new SaveProvisionedDashboardModalCtrl(mockDashboardSrv);
|
||||
|
||||
it('should remove id from dashboard model', () => {
|
||||
expect(ctrl.dash.id).toBeUndefined();
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import '../shareModalCtrl';
|
||||
import { ShareModalCtrl } from '../shareModalCtrl';
|
||||
import config from 'app/core/config';
|
||||
import { LinkSrv } from 'app/features/panellinks/link_srv';
|
||||
import { LinkSrv } from 'app/features/dashboard/panellinks/link_srv';
|
||||
|
||||
describe('ShareModalCtrl', () => {
|
||||
var ctx = <any>{
|
||||
const ctx = {
|
||||
timeSrv: {
|
||||
timeRange: () => {
|
||||
return { from: new Date(1000), to: new Date(2000) };
|
||||
@@ -26,9 +26,9 @@ describe('ShareModalCtrl', () => {
|
||||
templateSrv: {
|
||||
fillVariableValuesForUrl: () => {},
|
||||
},
|
||||
};
|
||||
} as any;
|
||||
|
||||
(<any>window).Intl.DateTimeFormat = () => {
|
||||
(window as any).Intl.DateTimeFormat = () => {
|
||||
return {
|
||||
resolvedOptions: () => {
|
||||
return { timeZone: 'UTC' };
|
||||
@@ -68,8 +68,8 @@ describe('ShareModalCtrl', () => {
|
||||
ctx.scope.panel = { id: 22 };
|
||||
|
||||
ctx.scope.init();
|
||||
var base = 'http://dashboards.grafana.com/render/d-solo/abcdefghi/my-dash';
|
||||
var params = '?from=1000&to=2000&orgId=1&panelId=22&width=1000&height=500&tz=UTC';
|
||||
const base = 'http://dashboards.grafana.com/render/d-solo/abcdefghi/my-dash';
|
||||
const params = '?from=1000&to=2000&orgId=1&panelId=22&width=1000&height=500&tz=UTC';
|
||||
expect(ctx.scope.imageUrl).toContain(base + params);
|
||||
});
|
||||
|
||||
@@ -79,8 +79,8 @@ describe('ShareModalCtrl', () => {
|
||||
ctx.scope.panel = { id: 22 };
|
||||
|
||||
ctx.scope.init();
|
||||
var base = 'http://dashboards.grafana.com/render/dashboard-solo/script/my-dash.js';
|
||||
var params = '?from=1000&to=2000&orgId=1&panelId=22&width=1000&height=500&tz=UTC';
|
||||
const base = 'http://dashboards.grafana.com/render/dashboard-solo/script/my-dash.js';
|
||||
const params = '?from=1000&to=2000&orgId=1&panelId=22&width=1000&height=500&tz=UTC';
|
||||
expect(ctx.scope.imageUrl).toContain(base + params);
|
||||
});
|
||||
|
||||
@@ -136,7 +136,7 @@ describe('ShareModalCtrl', () => {
|
||||
ctx.$location.absUrl = () => 'http://server/#!/test';
|
||||
ctx.scope.options.includeTemplateVars = true;
|
||||
|
||||
ctx.templateSrv.fillVariableValuesForUrl = function(params) {
|
||||
ctx.templateSrv.fillVariableValuesForUrl = params => {
|
||||
params['var-app'] = 'mupp';
|
||||
params['var-server'] = 'srv-01';
|
||||
};
|
||||
|
||||
@@ -2,53 +2,53 @@ import { TimeSrv } from '../time_srv';
|
||||
import '../time_srv';
|
||||
import moment from 'moment';
|
||||
|
||||
describe('timeSrv', function() {
|
||||
var rootScope = {
|
||||
describe('timeSrv', () => {
|
||||
const rootScope = {
|
||||
$on: jest.fn(),
|
||||
onAppEvent: jest.fn(),
|
||||
appEvent: jest.fn(),
|
||||
};
|
||||
|
||||
var timer = {
|
||||
const timer = {
|
||||
register: jest.fn(),
|
||||
cancel: jest.fn(),
|
||||
cancelAll: jest.fn(),
|
||||
};
|
||||
|
||||
var location = {
|
||||
let location = {
|
||||
search: jest.fn(() => ({})),
|
||||
};
|
||||
|
||||
var timeSrv;
|
||||
let timeSrv;
|
||||
|
||||
var _dashboard: any = {
|
||||
const _dashboard: any = {
|
||||
time: { from: 'now-6h', to: 'now' },
|
||||
getTimezone: jest.fn(() => 'browser'),
|
||||
};
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(() => {
|
||||
timeSrv = new TimeSrv(rootScope, jest.fn(), location, timer, { isGrafanaVisibile: jest.fn() });
|
||||
timeSrv.init(_dashboard);
|
||||
});
|
||||
|
||||
describe('timeRange', function() {
|
||||
it('should return unparsed when parse is false', function() {
|
||||
describe('timeRange', () => {
|
||||
it('should return unparsed when parse is false', () => {
|
||||
timeSrv.setTime({ from: 'now', to: 'now-1h' });
|
||||
var time = timeSrv.timeRange();
|
||||
const time = timeSrv.timeRange();
|
||||
expect(time.raw.from).toBe('now');
|
||||
expect(time.raw.to).toBe('now-1h');
|
||||
});
|
||||
|
||||
it('should return parsed when parse is true', function() {
|
||||
it('should return parsed when parse is true', () => {
|
||||
timeSrv.setTime({ from: 'now', to: 'now-1h' });
|
||||
var time = timeSrv.timeRange();
|
||||
const time = timeSrv.timeRange();
|
||||
expect(moment.isMoment(time.from)).toBe(true);
|
||||
expect(moment.isMoment(time.to)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('init time from url', function() {
|
||||
it('should handle relative times', function() {
|
||||
describe('init time from url', () => {
|
||||
it('should handle relative times', () => {
|
||||
location = {
|
||||
search: jest.fn(() => ({
|
||||
from: 'now-2d',
|
||||
@@ -58,12 +58,12 @@ describe('timeSrv', function() {
|
||||
|
||||
timeSrv = new TimeSrv(rootScope, jest.fn(), location, timer, { isGrafanaVisibile: jest.fn() });
|
||||
timeSrv.init(_dashboard);
|
||||
var time = timeSrv.timeRange();
|
||||
const time = timeSrv.timeRange();
|
||||
expect(time.raw.from).toBe('now-2d');
|
||||
expect(time.raw.to).toBe('now');
|
||||
});
|
||||
|
||||
it('should handle formatted dates', function() {
|
||||
it('should handle formatted dates', () => {
|
||||
location = {
|
||||
search: jest.fn(() => ({
|
||||
from: '20140410T052010',
|
||||
@@ -74,12 +74,12 @@ describe('timeSrv', function() {
|
||||
timeSrv = new TimeSrv(rootScope, jest.fn(), location, timer, { isGrafanaVisibile: jest.fn() });
|
||||
|
||||
timeSrv.init(_dashboard);
|
||||
var time = timeSrv.timeRange();
|
||||
const time = timeSrv.timeRange();
|
||||
expect(time.from.valueOf()).toEqual(new Date('2014-04-10T05:20:10Z').getTime());
|
||||
expect(time.to.valueOf()).toEqual(new Date('2014-05-20T03:10:22Z').getTime());
|
||||
});
|
||||
|
||||
it('should handle formatted dates without time', function() {
|
||||
it('should handle formatted dates without time', () => {
|
||||
location = {
|
||||
search: jest.fn(() => ({
|
||||
from: '20140410',
|
||||
@@ -90,12 +90,12 @@ describe('timeSrv', function() {
|
||||
timeSrv = new TimeSrv(rootScope, jest.fn(), location, timer, { isGrafanaVisibile: jest.fn() });
|
||||
|
||||
timeSrv.init(_dashboard);
|
||||
var time = timeSrv.timeRange();
|
||||
const time = timeSrv.timeRange();
|
||||
expect(time.from.valueOf()).toEqual(new Date('2014-04-10T00:00:00Z').getTime());
|
||||
expect(time.to.valueOf()).toEqual(new Date('2014-05-20T00:00:00Z').getTime());
|
||||
});
|
||||
|
||||
it('should handle epochs', function() {
|
||||
it('should handle epochs', () => {
|
||||
location = {
|
||||
search: jest.fn(() => ({
|
||||
from: '1410337646373',
|
||||
@@ -106,12 +106,12 @@ describe('timeSrv', function() {
|
||||
timeSrv = new TimeSrv(rootScope, jest.fn(), location, timer, { isGrafanaVisibile: jest.fn() });
|
||||
|
||||
timeSrv.init(_dashboard);
|
||||
var time = timeSrv.timeRange();
|
||||
const time = timeSrv.timeRange();
|
||||
expect(time.from.valueOf()).toEqual(1410337646373);
|
||||
expect(time.to.valueOf()).toEqual(1410337665699);
|
||||
});
|
||||
|
||||
it('should handle bad dates', function() {
|
||||
it('should handle bad dates', () => {
|
||||
location = {
|
||||
search: jest.fn(() => ({
|
||||
from: '20151126T00010%3C%2Fp%3E%3Cspan%20class',
|
||||
@@ -128,22 +128,22 @@ describe('timeSrv', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('setTime', function() {
|
||||
it('should return disable refresh if refresh is disabled for any range', function() {
|
||||
describe('setTime', () => {
|
||||
it('should return disable refresh if refresh is disabled for any range', () => {
|
||||
_dashboard.refresh = false;
|
||||
|
||||
timeSrv.setTime({ from: '2011-01-01', to: '2015-01-01' });
|
||||
expect(_dashboard.refresh).toBe(false);
|
||||
});
|
||||
|
||||
it('should restore refresh for absolute time range', function() {
|
||||
it('should restore refresh for absolute time range', () => {
|
||||
_dashboard.refresh = '30s';
|
||||
|
||||
timeSrv.setTime({ from: '2011-01-01', to: '2015-01-01' });
|
||||
expect(_dashboard.refresh).toBe('30s');
|
||||
});
|
||||
|
||||
it('should restore refresh after relative time range is set', function() {
|
||||
it('should restore refresh after relative time range is set', () => {
|
||||
_dashboard.refresh = '10s';
|
||||
timeSrv.setTime({
|
||||
from: moment([2011, 1, 1]),
|
||||
@@ -154,7 +154,7 @@ describe('timeSrv', function() {
|
||||
expect(_dashboard.refresh).toBe('10s');
|
||||
});
|
||||
|
||||
it('should keep refresh after relative time range is changed and now delay exists', function() {
|
||||
it('should keep refresh after relative time range is changed and now delay exists', () => {
|
||||
_dashboard.refresh = '10s';
|
||||
timeSrv.setTime({ from: 'now-1h', to: 'now-10s' });
|
||||
expect(_dashboard.refresh).toBe('10s');
|
||||
|
||||
@@ -4,12 +4,12 @@ import config from 'app/core/config';
|
||||
import { DashboardViewState } from '../view_state_srv';
|
||||
|
||||
describe('when updating view state', () => {
|
||||
let location = {
|
||||
const location = {
|
||||
replace: jest.fn(),
|
||||
search: jest.fn(),
|
||||
};
|
||||
|
||||
let $scope = {
|
||||
const $scope = {
|
||||
onAppEvent: jest.fn(() => {}),
|
||||
dashboard: {
|
||||
meta: {},
|
||||
@@ -17,7 +17,6 @@ describe('when updating view state', () => {
|
||||
},
|
||||
};
|
||||
|
||||
let $rootScope = {};
|
||||
let viewState;
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -33,11 +32,11 @@ describe('when updating view state', () => {
|
||||
location.search = jest.fn(() => {
|
||||
return { fullscreen: true, edit: true, panelId: 1 };
|
||||
});
|
||||
viewState = new DashboardViewState($scope, location, {}, $rootScope);
|
||||
viewState = new DashboardViewState($scope, location, {});
|
||||
});
|
||||
|
||||
it('should update querystring and view state', () => {
|
||||
var updateState = { fullscreen: true, edit: true, panelId: 1 };
|
||||
const updateState = { fullscreen: true, edit: true, panelId: 1 };
|
||||
|
||||
viewState.update(updateState);
|
||||
|
||||
@@ -55,7 +54,7 @@ describe('when updating view state', () => {
|
||||
|
||||
describe('to fullscreen false', () => {
|
||||
beforeEach(() => {
|
||||
viewState = new DashboardViewState($scope, location, {}, $rootScope);
|
||||
viewState = new DashboardViewState($scope, location, {});
|
||||
});
|
||||
it('should remove params from query string', () => {
|
||||
viewState.update({ fullscreen: true, panelId: 1, edit: true });
|
||||
|
||||
@@ -21,7 +21,7 @@ export class SubmenuCtrl {
|
||||
}
|
||||
|
||||
openEditView(editview) {
|
||||
var search = _.extend(this.$location.search(), { editview: editview });
|
||||
const search = _.extend(this.$location.search(), { editview: editview });
|
||||
this.$location.search(search);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ export class TimeSrv {
|
||||
timeAtLoad: any;
|
||||
private autoRefreshBlocked: boolean;
|
||||
|
||||
/** @ngInject **/
|
||||
/** @ngInject */
|
||||
constructor(private $rootScope, private $timeout, private $location, private timer, private contextSrv) {
|
||||
// default time
|
||||
this.time = { from: '6h', to: 'now' };
|
||||
@@ -69,7 +69,7 @@ export class TimeSrv {
|
||||
}
|
||||
|
||||
if (!isNaN(value)) {
|
||||
var epoch = parseInt(value);
|
||||
const epoch = parseInt(value, 10);
|
||||
return moment.utc(epoch);
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ export class TimeSrv {
|
||||
}
|
||||
|
||||
private initTimeFromUrl() {
|
||||
var params = this.$location.search();
|
||||
const params = this.$location.search();
|
||||
if (params.from) {
|
||||
this.time.from = this.parseUrlParam(params.from) || this.time.from;
|
||||
}
|
||||
@@ -90,8 +90,8 @@ export class TimeSrv {
|
||||
}
|
||||
|
||||
private routeUpdated() {
|
||||
var params = this.$location.search();
|
||||
var urlRange = this.timeRangeForUrl();
|
||||
const params = this.$location.search();
|
||||
const urlRange = this.timeRangeForUrl();
|
||||
// check if url has time range
|
||||
if (params.from && params.to) {
|
||||
// is it different from what our current time range?
|
||||
@@ -113,7 +113,7 @@ export class TimeSrv {
|
||||
this.dashboard.refresh = interval;
|
||||
this.cancelNextRefresh();
|
||||
if (interval) {
|
||||
var intervalMs = kbn.interval_to_ms(interval);
|
||||
const intervalMs = kbn.interval_to_ms(interval);
|
||||
|
||||
this.refreshTimer = this.timer.register(
|
||||
this.$timeout(() => {
|
||||
@@ -124,7 +124,7 @@ export class TimeSrv {
|
||||
}
|
||||
|
||||
// update url
|
||||
var params = this.$location.search();
|
||||
const params = this.$location.search();
|
||||
if (interval) {
|
||||
params.refresh = interval;
|
||||
this.$location.search(params);
|
||||
@@ -170,8 +170,8 @@ export class TimeSrv {
|
||||
|
||||
// update url
|
||||
if (fromRouteUpdate !== true) {
|
||||
var urlRange = this.timeRangeForUrl();
|
||||
var urlParams = this.$location.search();
|
||||
const urlRange = this.timeRangeForUrl();
|
||||
const urlParams = this.$location.search();
|
||||
urlParams.from = urlRange.from;
|
||||
urlParams.to = urlRange.to;
|
||||
this.$location.search(urlParams);
|
||||
@@ -182,7 +182,7 @@ export class TimeSrv {
|
||||
}
|
||||
|
||||
timeRangeForUrl() {
|
||||
var range = this.timeRange().raw;
|
||||
const range = this.timeRange().raw;
|
||||
|
||||
if (moment.isMoment(range.from)) {
|
||||
range.from = range.from.valueOf().toString();
|
||||
@@ -196,12 +196,12 @@ export class TimeSrv {
|
||||
|
||||
timeRange() {
|
||||
// make copies if they are moment (do not want to return out internal moment, because they are mutable!)
|
||||
var raw = {
|
||||
const raw = {
|
||||
from: moment.isMoment(this.time.from) ? moment(this.time.from) : this.time.from,
|
||||
to: moment.isMoment(this.time.to) ? moment(this.time.to) : this.time.to,
|
||||
};
|
||||
|
||||
var timezone = this.dashboard && this.dashboard.getTimezone();
|
||||
const timezone = this.dashboard && this.dashboard.getTimezone();
|
||||
|
||||
return {
|
||||
from: dateMath.parse(raw.from, false, timezone),
|
||||
@@ -211,16 +211,16 @@ export class TimeSrv {
|
||||
}
|
||||
|
||||
zoomOut(e, factor) {
|
||||
var range = this.timeRange();
|
||||
const range = this.timeRange();
|
||||
|
||||
var timespan = range.to.valueOf() - range.from.valueOf();
|
||||
var center = range.to.valueOf() - timespan / 2;
|
||||
const timespan = range.to.valueOf() - range.from.valueOf();
|
||||
const center = range.to.valueOf() - timespan / 2;
|
||||
|
||||
var to = center + timespan * factor / 2;
|
||||
var from = center - timespan * factor / 2;
|
||||
let to = center + timespan * factor / 2;
|
||||
let from = center - timespan * factor / 2;
|
||||
|
||||
if (to > Date.now() && range.to <= Date.now()) {
|
||||
var offset = to - Date.now();
|
||||
const offset = to - Date.now();
|
||||
from = from - offset;
|
||||
to = Date.now();
|
||||
}
|
||||
|
||||
@@ -5,10 +5,10 @@ export function inputDateDirective() {
|
||||
return {
|
||||
restrict: 'A',
|
||||
require: 'ngModel',
|
||||
link: function($scope, $elem, attrs, ngModel) {
|
||||
var format = 'YYYY-MM-DD HH:mm:ss';
|
||||
link: ($scope, $elem, attrs, ngModel) => {
|
||||
const format = 'YYYY-MM-DD HH:mm:ss';
|
||||
|
||||
var fromUser = function(text) {
|
||||
const fromUser = text => {
|
||||
if (text.indexOf('now') !== -1) {
|
||||
if (!dateMath.isValid(text)) {
|
||||
ngModel.$setValidity('error', false);
|
||||
@@ -18,7 +18,7 @@ export function inputDateDirective() {
|
||||
return text;
|
||||
}
|
||||
|
||||
var parsed;
|
||||
let parsed;
|
||||
if ($scope.ctrl.isUtc) {
|
||||
parsed = moment.utc(text, format);
|
||||
} else {
|
||||
@@ -34,7 +34,7 @@ export function inputDateDirective() {
|
||||
return parsed;
|
||||
};
|
||||
|
||||
var toUser = function(currentValue) {
|
||||
const toUser = currentValue => {
|
||||
if (moment.isMoment(currentValue)) {
|
||||
return currentValue.format(format);
|
||||
} else {
|
||||
|
||||
@@ -1,18 +1,8 @@
|
||||
<div class="navbar-buttons navbar-buttons--zoom">
|
||||
<button class="btn navbar-button navbar-button--tight" ng-click='ctrl.move(-1)'>
|
||||
<div class="navbar-buttons">
|
||||
<button class="btn navbar-button navbar-button--tight" ng-click='ctrl.move(-1)' ng-if="ctrl.isAbsolute">
|
||||
<i class="fa fa-chevron-left"></i>
|
||||
</button>
|
||||
|
||||
<button class="btn navbar-button" bs-tooltip="'Time range zoom out <br> CTRL+Z'" data-placement="bottom" ng-click='ctrl.zoom(2)'>
|
||||
<i class="fa fa-search-minus"></i>
|
||||
</button>
|
||||
|
||||
<button class="btn navbar-button navbar-button--tight" ng-click='ctrl.move(1)'>
|
||||
<i class="fa fa-chevron-right"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="navbar-buttons">
|
||||
<button bs-tooltip="ctrl.tooltip" data-placement="bottom" ng-click="ctrl.openDropdown()" class="btn navbar-button gf-timepicker-nav-btn">
|
||||
<i class="fa fa-clock-o"></i>
|
||||
<span ng-bind="ctrl.rangeString"></span>
|
||||
@@ -20,7 +10,15 @@
|
||||
<span ng-show="ctrl.dashboard.refresh" class="text-warning"> Refresh every {{ctrl.dashboard.refresh}}</span>
|
||||
</button>
|
||||
|
||||
<button class="btn navbar-button navbar-button--refresh" ng-click="ctrl.timeSrv.refreshDashboard()">
|
||||
<button class="btn navbar-button navbar-button--tight" ng-click='ctrl.move(1)' ng-if="ctrl.isAbsolute">
|
||||
<i class="fa fa-chevron-right"></i>
|
||||
</button>
|
||||
|
||||
<button class="btn navbar-button navbar-button--zoom" bs-tooltip="'Time range zoom out <br> CTRL+Z'" data-placement="bottom" ng-click='ctrl.zoom(2)'>
|
||||
<i class="fa fa-search-minus"></i>
|
||||
</button>
|
||||
|
||||
<button class="btn navbar-button navbar-button--refresh" ng-click="ctrl.timeSrv.refreshDashboard()">
|
||||
<i class="fa fa-refresh"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -23,6 +23,7 @@ export class TimePickerCtrl {
|
||||
isUtc: boolean;
|
||||
firstDayOfWeek: number;
|
||||
isOpen: boolean;
|
||||
isAbsolute: boolean;
|
||||
|
||||
/** @ngInject */
|
||||
constructor(private $scope, private $rootScope, private timeSrv) {
|
||||
@@ -44,8 +45,8 @@ export class TimePickerCtrl {
|
||||
}
|
||||
|
||||
onRefresh() {
|
||||
var time = angular.copy(this.timeSrv.timeRange());
|
||||
var timeRaw = angular.copy(time.raw);
|
||||
const time = angular.copy(this.timeSrv.timeRange());
|
||||
const timeRaw = angular.copy(time.raw);
|
||||
|
||||
if (!this.dashboard.isTimezoneUtc()) {
|
||||
time.from.local();
|
||||
@@ -66,6 +67,7 @@ export class TimePickerCtrl {
|
||||
this.tooltip = this.dashboard.formatDate(time.from) + ' <br>to<br>';
|
||||
this.tooltip += this.dashboard.formatDate(time.to);
|
||||
this.timeRaw = timeRaw;
|
||||
this.isAbsolute = moment.isMoment(this.timeRaw.to);
|
||||
}
|
||||
|
||||
zoom(factor) {
|
||||
@@ -73,10 +75,10 @@ export class TimePickerCtrl {
|
||||
}
|
||||
|
||||
move(direction) {
|
||||
var range = this.timeSrv.timeRange();
|
||||
const range = this.timeSrv.timeRange();
|
||||
|
||||
var timespan = (range.to.valueOf() - range.from.valueOf()) / 2;
|
||||
var to, from;
|
||||
const timespan = (range.to.valueOf() - range.from.valueOf()) / 2;
|
||||
let to, from;
|
||||
if (direction === -1) {
|
||||
to = range.to.valueOf() - timespan;
|
||||
from = range.from.valueOf() - timespan;
|
||||
@@ -143,7 +145,7 @@ export class TimePickerCtrl {
|
||||
}
|
||||
|
||||
setRelativeFilter(timespan) {
|
||||
var range = { from: timespan.from, to: timespan.to };
|
||||
const range = { from: timespan.from, to: timespan.to };
|
||||
|
||||
if (this.panel.nowDelay && range.to === 'now') {
|
||||
range.to = 'now-' + this.panel.nowDelay;
|
||||
|
||||
@@ -2,7 +2,7 @@ import angular from 'angular';
|
||||
import { ChangeTracker } from './change_tracker';
|
||||
|
||||
/** @ngInject */
|
||||
export function unsavedChangesSrv($rootScope, $q, $location, $timeout, contextSrv, dashboardSrv, $window) {
|
||||
export function unsavedChangesSrv(this: any, $rootScope, $q, $location, $timeout, contextSrv, dashboardSrv, $window) {
|
||||
this.init = function(dashboard, scope) {
|
||||
this.tracker = new ChangeTracker(dashboard, scope, 1000, $location, $window, $timeout, contextSrv, $rootScope);
|
||||
return this.tracker;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import coreModule from 'app/core/core_module';
|
||||
|
||||
var template = `
|
||||
const template = `
|
||||
<input type="file" id="dashupload" name="dashupload" class="hide"/>
|
||||
<label class="btn btn-success" for="dashupload">
|
||||
<i class="fa fa-upload"></i>
|
||||
@@ -16,12 +16,12 @@ function uploadDashboardDirective(timer, alertSrv, $location) {
|
||||
scope: {
|
||||
onUpload: '&',
|
||||
},
|
||||
link: function(scope) {
|
||||
link: scope => {
|
||||
function file_selected(evt) {
|
||||
var files = evt.target.files; // FileList object
|
||||
var readerOnload = function() {
|
||||
return function(e) {
|
||||
var dash;
|
||||
const files = evt.target.files; // FileList object
|
||||
const readerOnload = () => {
|
||||
return e => {
|
||||
let dash;
|
||||
try {
|
||||
dash = JSON.parse(e.target.result);
|
||||
} catch (err) {
|
||||
@@ -30,20 +30,25 @@ function uploadDashboardDirective(timer, alertSrv, $location) {
|
||||
return;
|
||||
}
|
||||
|
||||
scope.$apply(function() {
|
||||
scope.$apply(() => {
|
||||
scope.onUpload({ dash: dash });
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
for (var i = 0, f; (f = files[i]); i++) {
|
||||
var reader = new FileReader();
|
||||
let i = 0;
|
||||
let file = files[i];
|
||||
|
||||
while (file) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = readerOnload();
|
||||
reader.readAsText(f);
|
||||
reader.readAsText(file);
|
||||
i += 1;
|
||||
file = files[i];
|
||||
}
|
||||
}
|
||||
|
||||
var wnd: any = window;
|
||||
const wnd: any = window;
|
||||
// Check for the various File API support.
|
||||
if (wnd.File && wnd.FileReader && wnd.FileList && wnd.Blob) {
|
||||
// Something
|
||||
|
||||
@@ -37,7 +37,7 @@ export class ValidationSrv {
|
||||
});
|
||||
}
|
||||
|
||||
let deferred = this.$q.defer();
|
||||
const deferred = this.$q.defer();
|
||||
|
||||
const promises = [];
|
||||
promises.push(this.backendSrv.search({ type: hitTypes.FOLDER, folderIds: [folderId], query: name }));
|
||||
@@ -54,7 +54,7 @@ export class ValidationSrv {
|
||||
hits = hits.concat(res[1]);
|
||||
}
|
||||
|
||||
for (let hit of hits) {
|
||||
for (const hit of hits) {
|
||||
if (nameLowerCased === hit.title.toLowerCase()) {
|
||||
deferred.reject({
|
||||
type: 'EXISTING',
|
||||
|
||||
@@ -17,20 +17,20 @@ export class DashboardViewState {
|
||||
|
||||
/** @ngInject */
|
||||
constructor($scope, private $location, private $timeout) {
|
||||
var self = this;
|
||||
const self = this;
|
||||
self.state = {};
|
||||
self.panelScopes = [];
|
||||
self.$scope = $scope;
|
||||
self.dashboard = $scope.dashboard;
|
||||
|
||||
$scope.onAppEvent('$routeUpdate', function() {
|
||||
var urlState = self.getQueryStringState();
|
||||
$scope.onAppEvent('$routeUpdate', () => {
|
||||
const urlState = self.getQueryStringState();
|
||||
if (self.needsSync(urlState)) {
|
||||
self.update(urlState, true);
|
||||
}
|
||||
});
|
||||
|
||||
$scope.onAppEvent('panel-change-view', function(evt, payload) {
|
||||
$scope.onAppEvent('panel-change-view', (evt, payload) => {
|
||||
self.update(payload);
|
||||
});
|
||||
|
||||
@@ -45,8 +45,8 @@ export class DashboardViewState {
|
||||
}
|
||||
|
||||
getQueryStringState() {
|
||||
var state = this.$location.search();
|
||||
state.panelId = parseInt(state.panelId) || null;
|
||||
const state = this.$location.search();
|
||||
state.panelId = parseInt(state.panelId, 10) || null;
|
||||
state.fullscreen = state.fullscreen ? true : null;
|
||||
state.edit = state.edit === 'true' || state.edit === true || null;
|
||||
state.editview = state.editview || null;
|
||||
@@ -55,7 +55,7 @@ export class DashboardViewState {
|
||||
}
|
||||
|
||||
serializeToUrl() {
|
||||
var urlState = _.clone(this.state);
|
||||
const urlState = _.clone(this.state);
|
||||
urlState.fullscreen = this.state.fullscreen ? true : null;
|
||||
urlState.edit = this.state.edit ? true : null;
|
||||
return urlState;
|
||||
@@ -108,9 +108,9 @@ export class DashboardViewState {
|
||||
}
|
||||
|
||||
toggleCollapsedPanelRow(panelId) {
|
||||
for (let panel of this.dashboard.panels) {
|
||||
for (const panel of this.dashboard.panels) {
|
||||
if (panel.collapsed) {
|
||||
for (let rowPanel of panel.panels) {
|
||||
for (const rowPanel of panel.panels) {
|
||||
if (rowPanel.id === panelId) {
|
||||
this.dashboard.toggleRow(panel);
|
||||
return;
|
||||
@@ -122,7 +122,7 @@ export class DashboardViewState {
|
||||
|
||||
syncState() {
|
||||
if (this.dashboard.meta.fullscreen) {
|
||||
var panel = this.dashboard.getPanelById(this.state.panelId);
|
||||
const panel = this.dashboard.getPanelById(this.state.panelId);
|
||||
|
||||
if (!panel) {
|
||||
return;
|
||||
@@ -178,7 +178,7 @@ export class DashboardViewState {
|
||||
/** @ngInject */
|
||||
export function dashboardViewStateSrv($location, $timeout) {
|
||||
return {
|
||||
create: function($scope) {
|
||||
create: $scope => {
|
||||
return new DashboardViewState($scope, $location, $timeout);
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user