瀏覽代碼

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

Torkel Ödegaard 9 年之前
父節點
當前提交
98d1748e43

+ 1 - 1
public/app/core/directives/ng_model_on_blur.js

@@ -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);

+ 1 - 1
public/app/features/dashboard/dashboard_ctrl.ts

@@ -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);

+ 5 - 3
public/app/features/dashboard/dynamic_dashboard_srv.ts

@@ -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;
       }

+ 1 - 3
public/app/features/dashboard/export/export_modal.ts

@@ -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;
       });

+ 29 - 8
public/app/features/dashboard/export/exporter.ts

@@ -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 => {

+ 1 - 1
public/app/features/dashboard/model.ts

@@ -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);
 

+ 1 - 1
public/app/features/dashboard/row/row_model.ts

@@ -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;
   }
 

+ 1 - 3
public/app/features/dashboard/specs/dynamic_dashboard_srv_specs.ts

@@ -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;
       }));

+ 10 - 1
public/app/features/dashboard/specs/exporter_specs.ts

@@ -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() {

+ 1 - 4
public/app/features/templating/datasource_variable.ts

@@ -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 = [];
-    }
-
+    this.model.options = [];
     return this.model;
   }
 

+ 0 - 1
public/app/features/templating/specs/query_variable_specs.ts

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