fix(templating): work on fixing exporting issues when using templating variables, like data source variables, and panel repeats, requires more work #6189

This commit is contained in:
Torkel Ödegaard 2016-11-17 12:32:11 +01:00
parent 9d5928ddd6
commit 98d1748e43
11 changed files with 51 additions and 27 deletions

View File

@ -47,7 +47,7 @@ function (coreModule, kbn, rangeUtil) {
if (ctrl.$isEmpty(modelValue)) {
return true;
}
if (viewValue.indexOf('$') === 0) {
if (viewValue.indexOf('$') === 0 || viewValue.indexOf('+$') === 0) {
return true; // allow template variable
}
var info = rangeUtil.describeTextRange(viewValue);

View File

@ -52,7 +52,7 @@ export class DashboardCtrl {
.catch($scope.onInitFailed.bind(this, 'Templating init failed', false))
// continue
.finally(function() {
dynamicDashboardSrv.init(dashboard, variableSrv);
dynamicDashboardSrv.init(dashboard);
dynamicDashboardSrv.process();
unsavedChangesSrv.init(dashboard, $scope);

View File

@ -12,12 +12,12 @@ export class DynamicDashboardSrv {
dashboard: any;
variables: any;
init(dashboard, variableSrv) {
init(dashboard) {
this.dashboard = dashboard;
this.variables = variableSrv.variables;
this.variables = dashboard.templating.list;
}
process(options) {
process(options?) {
if (this.dashboard.snapshot || this.variables.length === 0) {
return;
}
@ -31,6 +31,8 @@ export class DynamicDashboardSrv {
// cleanup scopedVars
for (i = 0; i < this.dashboard.rows.length; i++) {
row = this.dashboard.rows[i];
delete row.scopedVars;
for (j = 0; j < row.panels.length; j++) {
delete row.panels[j].scopedVars;
}

View File

@ -17,9 +17,7 @@ export class DashExportCtrl {
constructor(private backendSrv, dashboardSrv, datasourceSrv, $scope) {
this.exporter = new DashboardExporter(datasourceSrv);
var current = dashboardSrv.getCurrent().getSaveModelClone();
this.exporter.makeExportable(current).then(dash => {
this.exporter.makeExportable(dashboardSrv.getCurrent()).then(dash => {
$scope.$apply(() => {
this.dash = dash;
});

View File

@ -11,19 +11,40 @@ export class DashboardExporter {
constructor(private datasourceSrv) {
}
makeExportable(dash) {
makeExportable(dashboard) {
var dynSrv = new DynamicDashboardSrv();
dynSrv.init(dash, {variables: dash.templating.list});
// clean up repeated rows and panels,
// this is done on the live real dashboard instance, not on a clone
// so we need to undo this
// this is pretty hacky and needs to be changed
dynSrv.init(dashboard);
dynSrv.process({cleanUpOnly: true});
dash.id = null;
var saveModel = dashboard.getSaveModelClone();
saveModel.id = null;
// undo repeat cleanup
dynSrv.process();
var inputs = [];
var requires = {};
var datasources = {};
var promises = [];
var variableLookup: any = {};
for (let variable of saveModel.templating.list) {
variableLookup[variable.name] = variable;
}
var templateizeDatasourceUsage = obj => {
// ignore data source properties that contain a variable
if (obj.datasource && obj.datasource.indexOf('$') === 0) {
if (variableLookup[obj.datasource.substring(1)]){
return;
}
}
promises.push(this.datasourceSrv.get(obj.datasource).then(ds => {
if (ds.meta.builtIn) {
return;
@ -50,7 +71,7 @@ export class DashboardExporter {
};
// check up panel data sources
for (let row of dash.rows) {
for (let row of saveModel.rows) {
for (let panel of row.panels) {
if (panel.datasource !== undefined) {
templateizeDatasourceUsage(panel);
@ -77,7 +98,7 @@ export class DashboardExporter {
}
// templatize template vars
for (let variable of dash.templating.list) {
for (let variable of saveModel.templating.list) {
if (variable.type === 'query') {
templateizeDatasourceUsage(variable);
variable.options = [];
@ -87,7 +108,7 @@ export class DashboardExporter {
}
// templatize annotations vars
for (let annotationDef of dash.annotations.list) {
for (let annotationDef of saveModel.annotations.list) {
templateizeDatasourceUsage(annotationDef);
}
@ -105,7 +126,7 @@ export class DashboardExporter {
});
// templatize constants
for (let variable of dash.templating.list) {
for (let variable of saveModel.templating.list) {
if (variable.type === 'constant') {
var refName = 'VAR_' + variable.name.replace(' ', '_').toUpperCase();
inputs.push({
@ -133,7 +154,7 @@ export class DashboardExporter {
newObj["__inputs"] = inputs;
newObj["__requires"] = requires;
_.defaults(newObj, dash);
_.defaults(newObj, saveModel);
return newObj;
}).catch(err => {

View File

@ -105,7 +105,7 @@ export class DashboardModel {
// prepare save model
this.rows = _.map(rows, row => row.getSaveModel());
this.templating.list = _.map(variables, variable => variable.getSaveModel());
this.templating.list = _.map(variables, variable => variable.getSaveModel ? variable.getSaveModel() : variable);
var copy = $.extend(true, {}, this);

View File

@ -33,11 +33,11 @@ export class DashboardRow {
}
getSaveModel() {
this.model = {};
assignModelProperties(this.model, this, this.defaults);
// remove properties that dont server persisted purpose
delete this.model.isNew;
return this.model;
}

View File

@ -20,7 +20,6 @@ function dynamicDashScenario(desc, func) {
beforeEach(angularMocks.inject(function(dashboardSrv) {
ctx.dashboardSrv = dashboardSrv;
ctx.variableSrv = {};
var model = {
rows: [],
@ -29,9 +28,8 @@ function dynamicDashScenario(desc, func) {
setupFunc(model);
ctx.dash = ctx.dashboardSrv.create(model);
ctx.variableSrv.variables = ctx.dash.templating.list;
ctx.dynamicDashboardSrv = new DynamicDashboardSrv();
ctx.dynamicDashboardSrv.init(ctx.dash, ctx.variableSrv);
ctx.dynamicDashboardSrv.init(ctx.dash);
ctx.dynamicDashboardSrv.process();
ctx.rows = ctx.dash.rows;
}));

View File

@ -34,6 +34,14 @@ describe('given dashboard with repeated panels', function() {
options: []
});
dash.templating.list.push({
name: 'ds',
type: 'datasource',
query: 'testdb',
current: {value: 'prod', text: 'prod'},
options: []
});
dash.annotations.list.push({
name: 'logs',
datasource: 'gfdb',
@ -49,6 +57,7 @@ describe('given dashboard with repeated panels', function() {
datasource: '-- Mixed --',
targets: [{datasource: 'other'}],
},
{id: 5, datasource: '$ds'},
]
});
@ -87,7 +96,7 @@ describe('given dashboard with repeated panels', function() {
});
it('exported dashboard should not contain repeated panels', function() {
expect(exported.rows[0].panels.length).to.be(2);
expect(exported.rows[0].panels.length).to.be(3);
});
it('exported dashboard should not contain repeated rows', function() {

View File

@ -34,10 +34,7 @@ export class DatasourceVariable implements Variable {
assignModelProperties(this.model, this, this.defaults);
// dont persist options
if (this.refresh !== 0) {
this.model.options = [];
}
return this.model;
}

View File

@ -41,7 +41,6 @@ describe('QueryVariable', function() {
var model = variable.getSaveModel();
expect(model.options.length).to.be(0);
});
});
});