| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305 |
- import angular from "angular";
- import _ from "lodash";
- import config from "app/core/config";
- import coreModule from "app/core/core_module";
- import { importPluginModule } from "./plugin_loader";
- import { UnknownPanelCtrl } from "app/plugins/panel/unknown/module";
- import { DashboardRowCtrl } from "./row_ctrl";
- /** @ngInject **/
- function pluginDirectiveLoader(
- $compile,
- datasourceSrv,
- $rootScope,
- $q,
- $http,
- $templateCache
- ) {
- function getTemplate(component) {
- if (component.template) {
- return $q.when(component.template);
- }
- var cached = $templateCache.get(component.templateUrl);
- if (cached) {
- return $q.when(cached);
- }
- return $http.get(component.templateUrl).then(res => {
- return res.data;
- });
- }
- function relativeTemplateUrlToAbs(templateUrl, baseUrl) {
- if (!templateUrl) {
- return undefined;
- }
- if (templateUrl.indexOf("public") === 0) {
- return templateUrl;
- }
- return baseUrl + "/" + templateUrl;
- }
- function getPluginComponentDirective(options) {
- // handle relative template urls for plugin templates
- options.Component.templateUrl = relativeTemplateUrlToAbs(
- options.Component.templateUrl,
- options.baseUrl
- );
- return function() {
- return {
- templateUrl: options.Component.templateUrl,
- template: options.Component.template,
- restrict: "E",
- controller: options.Component,
- controllerAs: "ctrl",
- bindToController: true,
- scope: options.bindings,
- link: (scope, elem, attrs, ctrl) => {
- if (ctrl.link) {
- ctrl.link(scope, elem, attrs, ctrl);
- }
- if (ctrl.init) {
- ctrl.init();
- }
- }
- };
- };
- }
- function loadPanelComponentInfo(scope, attrs) {
- if (scope.panel.type === "row") {
- return $q.when({
- name: "dashboard-row",
- bindings: { dashboard: "=", panel: "=" },
- attrs: { dashboard: "ctrl.dashboard", panel: "panel" },
- Component: DashboardRowCtrl
- });
- }
- var componentInfo: any = {
- name: "panel-plugin-" + scope.panel.type,
- bindings: { dashboard: "=", panel: "=", row: "=" },
- attrs: {
- dashboard: "dashboard",
- panel: "panel",
- class: "panel-height-helper"
- }
- };
- let panelInfo = config.panels[scope.panel.type];
- var panelCtrlPromise = Promise.resolve(UnknownPanelCtrl);
- if (panelInfo) {
- panelCtrlPromise = importPluginModule(panelInfo.module).then(function(
- panelModule
- ) {
- return panelModule.PanelCtrl;
- });
- }
- return panelCtrlPromise.then(function(PanelCtrl: any) {
- componentInfo.Component = PanelCtrl;
- if (!PanelCtrl || PanelCtrl.registered) {
- return componentInfo;
- }
- if (PanelCtrl.templatePromise) {
- return PanelCtrl.templatePromise.then(res => {
- return componentInfo;
- });
- }
- if (panelInfo) {
- PanelCtrl.templateUrl = relativeTemplateUrlToAbs(
- PanelCtrl.templateUrl,
- panelInfo.baseUrl
- );
- }
- PanelCtrl.templatePromise = getTemplate(PanelCtrl).then(template => {
- PanelCtrl.templateUrl = null;
- PanelCtrl.template = `<grafana-panel ctrl="ctrl" class="panel-height-helper">${template}</grafana-panel>`;
- return componentInfo;
- });
- return PanelCtrl.templatePromise;
- });
- }
- function getModule(scope, attrs) {
- switch (attrs.type) {
- // QueryCtrl
- case "query-ctrl": {
- let datasource = scope.target.datasource || scope.ctrl.panel.datasource;
- return datasourceSrv.get(datasource).then(ds => {
- scope.datasource = ds;
- return importPluginModule(ds.meta.module).then(dsModule => {
- return {
- baseUrl: ds.meta.baseUrl,
- name: "query-ctrl-" + ds.meta.id,
- bindings: { target: "=", panelCtrl: "=", datasource: "=" },
- attrs: {
- target: "target",
- "panel-ctrl": "ctrl.panelCtrl",
- datasource: "datasource"
- },
- Component: dsModule.QueryCtrl
- };
- });
- });
- }
- // QueryOptionsCtrl
- case "query-options-ctrl": {
- return datasourceSrv.get(scope.ctrl.panel.datasource).then(ds => {
- return importPluginModule(ds.meta.module).then((dsModule): any => {
- if (!dsModule.QueryOptionsCtrl) {
- return { notFound: true };
- }
- return {
- baseUrl: ds.meta.baseUrl,
- name: "query-options-ctrl-" + ds.meta.id,
- bindings: { panelCtrl: "=" },
- attrs: { "panel-ctrl": "ctrl.panelCtrl" },
- Component: dsModule.QueryOptionsCtrl
- };
- });
- });
- }
- // Annotations
- case "annotations-query-ctrl": {
- return importPluginModule(
- scope.ctrl.currentDatasource.meta.module
- ).then(function(dsModule) {
- return {
- baseUrl: scope.ctrl.currentDatasource.meta.baseUrl,
- name:
- "annotations-query-ctrl-" + scope.ctrl.currentDatasource.meta.id,
- bindings: { annotation: "=", datasource: "=" },
- attrs: {
- annotation: "ctrl.currentAnnotation",
- datasource: "ctrl.currentDatasource"
- },
- Component: dsModule.AnnotationsQueryCtrl
- };
- });
- }
- // Datasource ConfigCtrl
- case "datasource-config-ctrl": {
- var dsMeta = scope.ctrl.datasourceMeta;
- return importPluginModule(dsMeta.module).then(function(dsModule): any {
- if (!dsModule.ConfigCtrl) {
- return { notFound: true };
- }
- return {
- baseUrl: dsMeta.baseUrl,
- name: "ds-config-" + dsMeta.id,
- bindings: { meta: "=", current: "=" },
- attrs: { meta: "ctrl.datasourceMeta", current: "ctrl.current" },
- Component: dsModule.ConfigCtrl
- };
- });
- }
- // AppConfigCtrl
- case "app-config-ctrl": {
- let model = scope.ctrl.model;
- return importPluginModule(model.module).then(function(appModule) {
- return {
- baseUrl: model.baseUrl,
- name: "app-config-" + model.id,
- bindings: { appModel: "=", appEditCtrl: "=" },
- attrs: { "app-model": "ctrl.model", "app-edit-ctrl": "ctrl" },
- Component: appModule.ConfigCtrl
- };
- });
- }
- // App Page
- case "app-page": {
- let appModel = scope.ctrl.appModel;
- return importPluginModule(appModel.module).then(function(appModule) {
- return {
- baseUrl: appModel.baseUrl,
- name: "app-page-" + appModel.id + "-" + scope.ctrl.page.slug,
- bindings: { appModel: "=" },
- attrs: { "app-model": "ctrl.appModel" },
- Component: appModule[scope.ctrl.page.component]
- };
- });
- }
- // Panel
- case "panel": {
- return loadPanelComponentInfo(scope, attrs);
- }
- default: {
- return $q.reject({
- message: "Could not find component type: " + attrs.type
- });
- }
- }
- }
- function appendAndCompile(scope, elem, componentInfo) {
- var child = angular.element(document.createElement(componentInfo.name));
- _.each(componentInfo.attrs, (value, key) => {
- child.attr(key, value);
- });
- $compile(child)(scope);
- elem.empty();
- // let a binding digest cycle complete before adding to dom
- setTimeout(function() {
- elem.append(child);
- scope.$applyAsync(function() {
- scope.$broadcast("component-did-mount");
- scope.$broadcast("refresh");
- });
- });
- }
- function registerPluginComponent(scope, elem, attrs, componentInfo) {
- if (componentInfo.notFound) {
- elem.empty();
- return;
- }
- if (!componentInfo.Component) {
- throw {
- message:
- "Failed to find exported plugin component for " + componentInfo.name
- };
- }
- if (!componentInfo.Component.registered) {
- var directiveName = attrs.$normalize(componentInfo.name);
- var directiveFn = getPluginComponentDirective(componentInfo);
- coreModule.directive(directiveName, directiveFn);
- componentInfo.Component.registered = true;
- }
- appendAndCompile(scope, elem, componentInfo);
- }
- return {
- restrict: "E",
- link: function(scope, elem, attrs) {
- getModule(scope, attrs)
- .then(function(componentInfo) {
- registerPluginComponent(scope, elem, attrs, componentInfo);
- })
- .catch(err => {
- $rootScope.appEvent("alert-error", [
- "Plugin Error",
- err.message || err
- ]);
- console.log("Plugin component error", err);
- });
- }
- };
- }
- coreModule.directive("pluginComponent", pluginDirectiveLoader);
|