diff --git a/pkg/api/frontendsettings.go b/pkg/api/frontendsettings.go
index 7bea0b6338c..256ff15e881 100644
--- a/pkg/api/frontendsettings.go
+++ b/pkg/api/frontendsettings.go
@@ -123,6 +123,7 @@ func getFrontendSettingsMap(c *middleware.Context) (map[string]interface{}, erro
panels[panel.Id] = map[string]interface{}{
"module": panel.Module,
"name": panel.Name,
+ "info": panel.Info,
}
}
diff --git a/public/app/core/filters/filters.ts b/public/app/core/filters/filters.ts
index 57b2b1bd9ba..6122a010182 100644
--- a/public/app/core/filters/filters.ts
+++ b/public/app/core/filters/filters.ts
@@ -59,11 +59,14 @@ coreModule.filter('noXml', function() {
coreModule.filter('interpolateTemplateVars', function (templateSrv) {
var filterFunc: any = function(text, scope) {
- if (scope.panel) {
- return templateSrv.replaceWithText(text, scope.panel.scopedVars);
+ var scopedVars;
+ if (scope.ctrl && scope.ctrl.panel) {
+ scopedVars = scope.ctrl.panel.scopedVars;
} else {
- return templateSrv.replaceWithText(text, scope.row.scopedVars);
+ scopedVars = scope.row.scopedVars;
}
+
+ return templateSrv.replaceWithText(text, scopedVars);
};
filterFunc.$stateful = true;
diff --git a/public/app/features/panel/all.js b/public/app/features/panel/all.js
index ef3ea9b9b0f..ad635d83f07 100644
--- a/public/app/features/panel/all.js
+++ b/public/app/features/panel/all.js
@@ -6,4 +6,5 @@ define([
'./solo_panel_ctrl',
'./panel_loader',
'./query_editor',
+ './panel_editor_tab',
], function () {});
diff --git a/public/app/features/panel/panel_ctrl.ts b/public/app/features/panel/panel.ts
similarity index 55%
rename from public/app/features/panel/panel_ctrl.ts
rename to public/app/features/panel/panel.ts
index cc020c23423..a3bf35db9a4 100644
--- a/public/app/features/panel/panel_ctrl.ts
+++ b/public/app/features/panel/panel.ts
@@ -1,15 +1,17 @@
///
-import PanelMeta from './panel_meta2';
+import PanelMeta from './panel_meta3';
export class PanelCtrl {
meta: any;
panel: any;
row: any;
dashboard: any;
+ tabIndex: number;
constructor(private scope) {
this.meta = new PanelMeta(this.panel);
+ this.tabIndex = 0;
this.publishAppEvent('panel-instantiated', {scope: scope});
}
@@ -36,4 +38,28 @@ export class PanelCtrl {
}
}
+export class PanelDirective {
+ template: string;
+ templateUrl: string;
+ bindToController: boolean;
+ scope: any;
+ controller: any;
+ controllerAs: string;
+
+ getDirective() {
+ return {
+ template: this.template,
+ templateUrl: this.templateUrl,
+ controller: this.controller,
+ controllerAs: 'ctrl',
+ bindToController: true,
+ scope: {dashboard: "=", panel: "=", row: "="},
+ link: this.link
+ };
+ }
+
+ link(scope) {
+ return null;
+ }
+}
diff --git a/public/app/features/panel/panel_editor_tab.ts b/public/app/features/panel/panel_editor_tab.ts
new file mode 100644
index 00000000000..56e3078962e
--- /dev/null
+++ b/public/app/features/panel/panel_editor_tab.ts
@@ -0,0 +1,24 @@
+///
+
+import angular from 'angular';
+import config from 'app/core/config';
+
+var directiveModule = angular.module('grafana.directives');
+
+/** @ngInject */
+function panelEditorTab(dynamicDirectiveSrv) {
+ return dynamicDirectiveSrv.create({
+ scope: {
+ panelCtrl: "=",
+ editorTab: "=",
+ },
+ directive: scope => {
+ return Promise.resolve({
+ name: 'panel-editor-tab-' + scope.editorTab.title,
+ fn: scope.editorTab.directiveFn,
+ });
+ }
+ });
+}
+
+directiveModule.directive('panelEditorTab', panelEditorTab);
diff --git a/public/app/features/panel/panel_loader.ts b/public/app/features/panel/panel_loader.ts
index dd0284138ab..cf42458a9a7 100644
--- a/public/app/features/panel/panel_loader.ts
+++ b/public/app/features/panel/panel_loader.ts
@@ -3,12 +3,12 @@
import angular from 'angular';
import config from 'app/core/config';
-import {unknownPanelDirective} from '../../plugins/panel/unknown/module';
+import {UnknownPanel} from '../../plugins/panel/unknown/module';
var directiveModule = angular.module('grafana.directives');
/** @ngInject */
-function panelLoader($compile, dynamicDirectiveSrv, $http, $q) {
+function panelLoader($compile, dynamicDirectiveSrv, $http, $q, $injector) {
return {
restrict: 'E',
scope: {
@@ -18,11 +18,11 @@ function panelLoader($compile, dynamicDirectiveSrv, $http, $q) {
},
link: function(scope, elem, attrs) {
- function getTemplate(component) {
- if (component.template) {
- return $q.when(component.template);
+ function getTemplate(directive) {
+ if (directive.template) {
+ return $q.when(directive.template);
}
- return $http.get(component.templateUrl).then(res => {
+ return $http.get(directive.templateUrl).then(res => {
return res.data;
});
}
@@ -38,37 +38,42 @@ function panelLoader($compile, dynamicDirectiveSrv, $http, $q) {
elem.append(child);
}
- function addPanel(name, directive) {
- if (!directive.registered) {
- getTemplate(directive).then(template => {
- directive.templateUrl = null;
- directive.template = `${template}`;
- directive.controllerAs = 'ctrl';
- directive.bindToController = true;
- directive.scope = {
- dashboard: "=",
- panel: "=",
- row: "="
- };
+ function addPanel(name, Panel) {
+ if (Panel.registered) {
+ addPanelAndCompile(name);
+ }
- directiveModule.directive(attrs.$normalize(name), function() {
- return directive;
- });
- directive.registered = true;
+ if (Panel.promise) {
+ Panel.promise.then(() => {
addPanelAndCompile(name);
});
+ return;
}
- addPanelAndCompile(name);
+
+ var panelInstance = $injector.instantiate(Panel);
+ var directive = panelInstance.getDirective();
+
+ Panel.promise = getTemplate(directive).then(template => {
+ directive.templateUrl = null;
+ directive.template = `${template}`;
+ directiveModule.directive(attrs.$normalize(name), function() {
+ return directive;
+ });
+ Panel.registered = true;
+ addPanelAndCompile(name);
+ });
+
+ return;
}
var panelElemName = 'panel-directive-' + scope.panel.type;
let panelInfo = config.panels[scope.panel.type];
if (!panelInfo) {
- addPanel(panelElemName, unknownPanelDirective);
+ addPanel(panelElemName, UnknownPanel);
}
System.import(panelInfo.module).then(function(panelModule) {
- addPanel(panelElemName, panelModule.panel);
+ addPanel(panelElemName, panelModule.Panel);
}).catch(err => {
console.log('Panel err: ', err);
});
@@ -76,4 +81,4 @@ function panelLoader($compile, dynamicDirectiveSrv, $http, $q) {
};
}
-angular.module('grafana.directives').directive('panelLoader', panelLoader);
+directiveModule.directive('panelLoader', panelLoader);
diff --git a/public/app/features/panel/panel_menu.js b/public/app/features/panel/panel_menu.js
index bea8d27d2fa..16ee311ff52 100644
--- a/public/app/features/panel/panel_menu.js
+++ b/public/app/features/panel/panel_menu.js
@@ -11,9 +11,9 @@ function (angular, $, _) {
.directive('panelMenu', function($compile, linkSrv) {
var linkTemplate =
'' +
- '{{ctrl.panel.title}}' +
+ '{{ctrl.panel.title | interpolateTemplateVars:this}}' +
'' +
- ' {{ctrl.panelMeta.timeInfo}}' +
+ ' {{ctrl.panelMeta.timeInfo}}' +
'';
function createExternalLinkMenu(ctrl) {
@@ -44,7 +44,7 @@ function (angular, $, _) {
template += '