Commit 98d1748e by Torkel Ödegaard

fix(templating): work on fixing exporting issues when using templating…

fix(templating): work on fixing exporting issues when using templating variables, like data source variables, and panel repeats, requires more work #6189
parent 9d5928dd
...@@ -47,7 +47,7 @@ function (coreModule, kbn, rangeUtil) { ...@@ -47,7 +47,7 @@ function (coreModule, kbn, rangeUtil) {
if (ctrl.$isEmpty(modelValue)) { if (ctrl.$isEmpty(modelValue)) {
return true; return true;
} }
if (viewValue.indexOf('$') === 0) { if (viewValue.indexOf('$') === 0 || viewValue.indexOf('+$') === 0) {
return true; // allow template variable return true; // allow template variable
} }
var info = rangeUtil.describeTextRange(viewValue); var info = rangeUtil.describeTextRange(viewValue);
......
...@@ -52,7 +52,7 @@ export class DashboardCtrl { ...@@ -52,7 +52,7 @@ export class DashboardCtrl {
.catch($scope.onInitFailed.bind(this, 'Templating init failed', false)) .catch($scope.onInitFailed.bind(this, 'Templating init failed', false))
// continue // continue
.finally(function() { .finally(function() {
dynamicDashboardSrv.init(dashboard, variableSrv); dynamicDashboardSrv.init(dashboard);
dynamicDashboardSrv.process(); dynamicDashboardSrv.process();
unsavedChangesSrv.init(dashboard, $scope); unsavedChangesSrv.init(dashboard, $scope);
......
...@@ -12,12 +12,12 @@ export class DynamicDashboardSrv { ...@@ -12,12 +12,12 @@ export class DynamicDashboardSrv {
dashboard: any; dashboard: any;
variables: any; variables: any;
init(dashboard, variableSrv) { init(dashboard) {
this.dashboard = 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) { if (this.dashboard.snapshot || this.variables.length === 0) {
return; return;
} }
...@@ -31,6 +31,8 @@ export class DynamicDashboardSrv { ...@@ -31,6 +31,8 @@ export class DynamicDashboardSrv {
// cleanup scopedVars // cleanup scopedVars
for (i = 0; i < this.dashboard.rows.length; i++) { for (i = 0; i < this.dashboard.rows.length; i++) {
row = this.dashboard.rows[i]; row = this.dashboard.rows[i];
delete row.scopedVars;
for (j = 0; j < row.panels.length; j++) { for (j = 0; j < row.panels.length; j++) {
delete row.panels[j].scopedVars; delete row.panels[j].scopedVars;
} }
......
...@@ -17,9 +17,7 @@ export class DashExportCtrl { ...@@ -17,9 +17,7 @@ export class DashExportCtrl {
constructor(private backendSrv, dashboardSrv, datasourceSrv, $scope) { constructor(private backendSrv, dashboardSrv, datasourceSrv, $scope) {
this.exporter = new DashboardExporter(datasourceSrv); this.exporter = new DashboardExporter(datasourceSrv);
var current = dashboardSrv.getCurrent().getSaveModelClone(); this.exporter.makeExportable(dashboardSrv.getCurrent()).then(dash => {
this.exporter.makeExportable(current).then(dash => {
$scope.$apply(() => { $scope.$apply(() => {
this.dash = dash; this.dash = dash;
}); });
......
...@@ -11,19 +11,40 @@ export class DashboardExporter { ...@@ -11,19 +11,40 @@ export class DashboardExporter {
constructor(private datasourceSrv) { constructor(private datasourceSrv) {
} }
makeExportable(dash) { makeExportable(dashboard) {
var dynSrv = new DynamicDashboardSrv(); 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}); dynSrv.process({cleanUpOnly: true});
dash.id = null; var saveModel = dashboard.getSaveModelClone();
saveModel.id = null;
// undo repeat cleanup
dynSrv.process();
var inputs = []; var inputs = [];
var requires = {}; var requires = {};
var datasources = {}; var datasources = {};
var promises = []; var promises = [];
var variableLookup: any = {};
for (let variable of saveModel.templating.list) {
variableLookup[variable.name] = variable;
}
var templateizeDatasourceUsage = obj => { 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 => { promises.push(this.datasourceSrv.get(obj.datasource).then(ds => {
if (ds.meta.builtIn) { if (ds.meta.builtIn) {
return; return;
...@@ -50,7 +71,7 @@ export class DashboardExporter { ...@@ -50,7 +71,7 @@ export class DashboardExporter {
}; };
// check up panel data sources // check up panel data sources
for (let row of dash.rows) { for (let row of saveModel.rows) {
for (let panel of row.panels) { for (let panel of row.panels) {
if (panel.datasource !== undefined) { if (panel.datasource !== undefined) {
templateizeDatasourceUsage(panel); templateizeDatasourceUsage(panel);
...@@ -77,7 +98,7 @@ export class DashboardExporter { ...@@ -77,7 +98,7 @@ export class DashboardExporter {
} }
// templatize template vars // templatize template vars
for (let variable of dash.templating.list) { for (let variable of saveModel.templating.list) {
if (variable.type === 'query') { if (variable.type === 'query') {
templateizeDatasourceUsage(variable); templateizeDatasourceUsage(variable);
variable.options = []; variable.options = [];
...@@ -87,7 +108,7 @@ export class DashboardExporter { ...@@ -87,7 +108,7 @@ export class DashboardExporter {
} }
// templatize annotations vars // templatize annotations vars
for (let annotationDef of dash.annotations.list) { for (let annotationDef of saveModel.annotations.list) {
templateizeDatasourceUsage(annotationDef); templateizeDatasourceUsage(annotationDef);
} }
...@@ -105,7 +126,7 @@ export class DashboardExporter { ...@@ -105,7 +126,7 @@ export class DashboardExporter {
}); });
// templatize constants // templatize constants
for (let variable of dash.templating.list) { for (let variable of saveModel.templating.list) {
if (variable.type === 'constant') { if (variable.type === 'constant') {
var refName = 'VAR_' + variable.name.replace(' ', '_').toUpperCase(); var refName = 'VAR_' + variable.name.replace(' ', '_').toUpperCase();
inputs.push({ inputs.push({
...@@ -133,7 +154,7 @@ export class DashboardExporter { ...@@ -133,7 +154,7 @@ export class DashboardExporter {
newObj["__inputs"] = inputs; newObj["__inputs"] = inputs;
newObj["__requires"] = requires; newObj["__requires"] = requires;
_.defaults(newObj, dash); _.defaults(newObj, saveModel);
return newObj; return newObj;
}).catch(err => { }).catch(err => {
......
...@@ -105,7 +105,7 @@ export class DashboardModel { ...@@ -105,7 +105,7 @@ export class DashboardModel {
// prepare save model // prepare save model
this.rows = _.map(rows, row => row.getSaveModel()); 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); var copy = $.extend(true, {}, this);
......
...@@ -33,11 +33,11 @@ export class DashboardRow { ...@@ -33,11 +33,11 @@ export class DashboardRow {
} }
getSaveModel() { getSaveModel() {
this.model = {};
assignModelProperties(this.model, this, this.defaults); assignModelProperties(this.model, this, this.defaults);
// remove properties that dont server persisted purpose // remove properties that dont server persisted purpose
delete this.model.isNew; delete this.model.isNew;
return this.model; return this.model;
} }
......
...@@ -20,7 +20,6 @@ function dynamicDashScenario(desc, func) { ...@@ -20,7 +20,6 @@ function dynamicDashScenario(desc, func) {
beforeEach(angularMocks.inject(function(dashboardSrv) { beforeEach(angularMocks.inject(function(dashboardSrv) {
ctx.dashboardSrv = dashboardSrv; ctx.dashboardSrv = dashboardSrv;
ctx.variableSrv = {};
var model = { var model = {
rows: [], rows: [],
...@@ -29,9 +28,8 @@ function dynamicDashScenario(desc, func) { ...@@ -29,9 +28,8 @@ function dynamicDashScenario(desc, func) {
setupFunc(model); setupFunc(model);
ctx.dash = ctx.dashboardSrv.create(model); ctx.dash = ctx.dashboardSrv.create(model);
ctx.variableSrv.variables = ctx.dash.templating.list;
ctx.dynamicDashboardSrv = new DynamicDashboardSrv(); ctx.dynamicDashboardSrv = new DynamicDashboardSrv();
ctx.dynamicDashboardSrv.init(ctx.dash, ctx.variableSrv); ctx.dynamicDashboardSrv.init(ctx.dash);
ctx.dynamicDashboardSrv.process(); ctx.dynamicDashboardSrv.process();
ctx.rows = ctx.dash.rows; ctx.rows = ctx.dash.rows;
})); }));
......
...@@ -34,6 +34,14 @@ describe('given dashboard with repeated panels', function() { ...@@ -34,6 +34,14 @@ describe('given dashboard with repeated panels', function() {
options: [] options: []
}); });
dash.templating.list.push({
name: 'ds',
type: 'datasource',
query: 'testdb',
current: {value: 'prod', text: 'prod'},
options: []
});
dash.annotations.list.push({ dash.annotations.list.push({
name: 'logs', name: 'logs',
datasource: 'gfdb', datasource: 'gfdb',
...@@ -49,6 +57,7 @@ describe('given dashboard with repeated panels', function() { ...@@ -49,6 +57,7 @@ describe('given dashboard with repeated panels', function() {
datasource: '-- Mixed --', datasource: '-- Mixed --',
targets: [{datasource: 'other'}], targets: [{datasource: 'other'}],
}, },
{id: 5, datasource: '$ds'},
] ]
}); });
...@@ -87,7 +96,7 @@ describe('given dashboard with repeated panels', function() { ...@@ -87,7 +96,7 @@ describe('given dashboard with repeated panels', function() {
}); });
it('exported dashboard should not contain 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() { it('exported dashboard should not contain repeated rows', function() {
......
...@@ -34,10 +34,7 @@ export class DatasourceVariable implements Variable { ...@@ -34,10 +34,7 @@ export class DatasourceVariable implements Variable {
assignModelProperties(this.model, this, this.defaults); assignModelProperties(this.model, this, this.defaults);
// dont persist options // dont persist options
if (this.refresh !== 0) { this.model.options = [];
this.model.options = [];
}
return this.model; return this.model;
} }
......
...@@ -41,7 +41,6 @@ describe('QueryVariable', function() { ...@@ -41,7 +41,6 @@ describe('QueryVariable', function() {
var model = variable.getSaveModel(); var model = variable.getSaveModel();
expect(model.options.length).to.be(0); expect(model.options.length).to.be(0);
}); });
}); });
}); });
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment