Browse Source

feat(plugins): made panels work as plugins

Torkel Ödegaard 10 years ago
parent
commit
4a69de1f30
51 changed files with 113 additions and 79 deletions
  1. 9 0
      pkg/api/frontendsettings.go
  2. 7 0
      pkg/plugins/models.go
  3. 17 0
      pkg/plugins/plugins.go
  4. 1 7
      public/app/core/settings.js
  5. 2 2
      public/app/features/panel/panel_directive.js
  6. 13 0
      public/app/plugins/external/example/readme.md
  7. 0 3
      public/app/plugins/externalPlugins/example/README.TXT
  8. 0 42
      public/app/plugins/externalPlugins/example/_plugin.json
  9. 0 0
      public/app/plugins/panels/dashlist/editor.html
  10. 0 0
      public/app/plugins/panels/dashlist/module.html
  11. 2 2
      public/app/plugins/panels/dashlist/module.js
  12. 8 0
      public/app/plugins/panels/dashlist/plugin.json
  13. 0 0
      public/app/plugins/panels/graph/axisEditor.html
  14. 0 0
      public/app/plugins/panels/graph/graph.js
  15. 0 0
      public/app/plugins/panels/graph/graph.tooltip.js
  16. 1 1
      public/app/plugins/panels/graph/legend.js
  17. 0 0
      public/app/plugins/panels/graph/legend.popover.html
  18. 0 0
      public/app/plugins/panels/graph/module.html
  19. 3 3
      public/app/plugins/panels/graph/module.js
  20. 8 0
      public/app/plugins/panels/graph/plugin.json
  21. 0 0
      public/app/plugins/panels/graph/seriesOverridesCtrl.js
  22. 0 0
      public/app/plugins/panels/graph/styleEditor.html
  23. 0 0
      public/app/plugins/panels/singlestat/editor.html
  24. 0 0
      public/app/plugins/panels/singlestat/module.html
  25. 2 2
      public/app/plugins/panels/singlestat/module.js
  26. 8 0
      public/app/plugins/panels/singlestat/plugin.json
  27. 0 0
      public/app/plugins/panels/singlestat/singleStatPanel.js
  28. 2 2
      public/app/plugins/panels/table/controller.ts
  29. 0 0
      public/app/plugins/panels/table/editor.html
  30. 2 3
      public/app/plugins/panels/table/editor.ts
  31. 0 0
      public/app/plugins/panels/table/module.html
  32. 2 2
      public/app/plugins/panels/table/module.ts
  33. 0 0
      public/app/plugins/panels/table/options.html
  34. 8 0
      public/app/plugins/panels/table/plugin.json
  35. 1 1
      public/app/plugins/panels/table/renderer.ts
  36. 0 0
      public/app/plugins/panels/table/specs/renderer_specs.ts
  37. 0 0
      public/app/plugins/panels/table/specs/table_model_specs.ts
  38. 0 0
      public/app/plugins/panels/table/specs/transformers_specs.ts
  39. 0 0
      public/app/plugins/panels/table/table_model.ts
  40. 1 1
      public/app/plugins/panels/table/transformers.ts
  41. 0 0
      public/app/plugins/panels/text/editor.html
  42. 0 0
      public/app/plugins/panels/text/module.html
  43. 3 3
      public/app/plugins/panels/text/module.js
  44. 8 0
      public/app/plugins/panels/text/plugin.json
  45. 0 0
      public/app/plugins/plugin_api.md
  46. 1 1
      public/test/specs/graph-ctrl-specs.js
  47. 1 1
      public/test/specs/graph-specs.js
  48. 1 1
      public/test/specs/graph-tooltip-specs.js
  49. 1 1
      public/test/specs/seriesOverridesCtrl-specs.js
  50. 1 1
      public/test/specs/singlestat-specs.js
  51. 0 0
      public/vendor/showdown.js

+ 9 - 0
pkg/api/frontendsettings.go

@@ -106,9 +106,18 @@ func getFrontendSettingsMap(c *middleware.Context) (map[string]interface{}, erro
 		defaultDatasource = "-- Grafana --"
 	}
 
+	panels := map[string]interface{}{}
+	for _, panel := range plugins.Panels {
+		panels[panel.Type] = map[string]interface{}{
+			"module": panel.Module,
+			"name":   panel.Name,
+		}
+	}
+
 	jsonObj := map[string]interface{}{
 		"defaultDatasource": defaultDatasource,
 		"datasources":       datasources,
+		"panels":            panels,
 		"appSubUrl":         setting.AppSubUrl,
 		"allowOrgCreate":    (setting.AllowUserOrgCreate && c.IsSignedIn) || c.IsGrafanaAdmin,
 		"buildInfo": map[string]interface{}{

+ 7 - 0
pkg/plugins/models.go

@@ -15,6 +15,13 @@ type DataSourcePlugin struct {
 	StaticRootConfig   *StaticRootConfig      `json:"staticRoot"`
 }
 
+type PanelPlugin struct {
+	Type             string            `json:"type"`
+	Name             string            `json:"name"`
+	Module           string            `json:"module"`
+	StaticRootConfig *StaticRootConfig `json:"staticRoot"`
+}
+
 type StaticRootConfig struct {
 	Url  string `json:"url"`
 	Path string `json:"path"`

+ 17 - 0
pkg/plugins/plugins.go

@@ -14,6 +14,7 @@ import (
 
 var (
 	DataSources     map[string]DataSourcePlugin
+	Panels          []PanelPlugin
 	ExternalPlugins []ExternalPlugin
 	StaticRoutes    []*StaticRootConfig
 )
@@ -27,6 +28,7 @@ func Init() error {
 	DataSources = make(map[string]DataSourcePlugin)
 	ExternalPlugins = make([]ExternalPlugin, 0)
 	StaticRoutes = make([]*StaticRootConfig, 0)
+	Panels = make([]PanelPlugin, 0)
 
 	scan(path.Join(setting.StaticRootPath, "app/plugins"))
 	checkExternalPluginPaths()
@@ -124,6 +126,21 @@ func (scanner *PluginScanner) loadPluginJson(pluginJsonFilePath string) error {
 		addStaticRoot(p.StaticRootConfig, currentDir)
 	}
 
+	if pluginType == "panel" {
+		p := PanelPlugin{}
+		reader.Seek(0, 0)
+		if err := jsonParser.Decode(&p); err != nil {
+			return err
+		}
+
+		if p.Type == "" {
+			return errors.New("Did not find type property in plugin.json")
+		}
+
+		Panels = append(Panels, p)
+		addStaticRoot(p.StaticRootConfig, currentDir)
+	}
+
 	if pluginType == "external" {
 		p := ExternalPlugin{}
 		reader.Seek(0, 0)

+ 1 - 7
public/app/core/settings.js

@@ -8,13 +8,7 @@ function (_) {
     var defaults = {
       datasources                   : {},
       window_title_prefix           : 'Grafana - ',
-      panels                        : {
-        'graph':      { path: 'app/panels/graph',      name: 'Graph' },
-        'table':      { path: 'app/panels/table',      name: 'Table' },
-        'singlestat': { path: 'app/panels/singlestat', name: 'Single stat' },
-        'text':       { path: 'app/panels/text',       name: 'Text' },
-        'dashlist':   { path: 'app/panels/dashlist',   name: 'Dashboard list' },
-      },
+      panels                        : {},
       new_panel_title: 'Panel Title',
       playlist_timespan: "1m",
       unsaved_changes_warning: true,

+ 2 - 2
public/app/features/panel/panel_directive.js

@@ -13,9 +13,9 @@ function (angular, $, config) {
       restrict: 'E',
       link: function(scope, elem, attr) {
         var getter = $parse(attr.type), panelType = getter(scope);
-        var panelPath = config.panels[panelType].path;
+        var module = config.panels[panelType].module;
 
-        scope.require([panelPath + "/module"], function () {
+        scope.require([module], function () {
           var panelEl = angular.element(document.createElement('grafana-panel-' + panelType));
           elem.append(panelEl);
           $compile(panelEl)(scope);

+ 13 - 0
public/app/plugins/external/example/readme.md

@@ -0,0 +1,13 @@
+Example app is available at https://github.com/raintank/grafana-plugin-example
+
+* Clone plugin repo git@github.com:raintank/grafana-plugin-example.git
+
+* Modify grafana.ini (or custom.ini if your developing Grafana locally)
+
+```ini
+[plugin.external-test]
+path = /<the_path_were_you_cloned_it>/grafana-plugin-example
+```
+
+
+

+ 0 - 3
public/app/plugins/externalPlugins/example/README.TXT

@@ -1,3 +0,0 @@
-Example app is available at https://github.com/raintank/grafana-plugin-example
-
-To use, download the example app from github and run it (requires python Flask). Then rename the "_plugin.json" file in this director to "plugin.json" and restart Grafana.

+ 0 - 42
public/app/plugins/externalPlugins/example/_plugin.json

@@ -1,42 +0,0 @@
-{
-  "pluginType": "externalPlugin",
-  "settings": {
-    "routes": [
-      {
-        "path": "/example/static/*",
-        "method": "*",
-        "req_signed_in": false,
-        "req_grafana_admin": false,
-        "req_role": "Admin",
-        "url": "http://localhost:5000/static"
-      },
-      {
-        "path": "/example/api/*",
-        "method": "*",
-        "req_signed_in": true,
-        "req_grafana_admin": false,
-        "req_role": "Admin",
-        "url": "http://localhost:5000/api"
-      }
-    ],
-    "css": [
-      {
-        "href": "/example/static/css/example.css"
-      }
-    ],
-    "js": [
-      {
-        "src": "/example/static/js/app.js"
-      }
-    ],
-    "menu_items": [
-      {
-        "text": "Example Plugin",
-        "icon": "fa fa-fw fa-smile-o",
-        "href": "/example/servers",
-        "adminOnly": false,
-      }
-    ]
-  }
-
-}

+ 0 - 0
public/app/panels/dashlist/editor.html → public/app/plugins/panels/dashlist/editor.html


+ 0 - 0
public/app/panels/dashlist/module.html → public/app/plugins/panels/dashlist/module.html


+ 2 - 2
public/app/panels/dashlist/module.js → public/app/plugins/panels/dashlist/module.js

@@ -14,7 +14,7 @@ function (angular, app, _, config, PanelMeta) {
   module.directive('grafanaPanelDashlist', function() {
     return {
       controller: 'DashListPanelCtrl',
-      templateUrl: 'app/panels/dashlist/module.html',
+      templateUrl: 'app/plugins/panels/dashlist/module.html',
     };
   });
 
@@ -26,7 +26,7 @@ function (angular, app, _, config, PanelMeta) {
       fullscreen: true,
     });
 
-    $scope.panelMeta.addEditorTab('Options', 'app/panels/dashlist/editor.html');
+    $scope.panelMeta.addEditorTab('Options', 'app/plugins/panels/dashlist/editor.html');
 
     var defaults = {
       mode: 'starred',

+ 8 - 0
public/app/plugins/panels/dashlist/plugin.json

@@ -0,0 +1,8 @@
+{
+  "pluginType": "panel",
+
+  "name": "Dashboard list",
+  "type": "dashlist",
+
+  "module": "app/plugins/panels/dashlist/module"
+}

+ 0 - 0
public/app/panels/graph/axisEditor.html → public/app/plugins/panels/graph/axisEditor.html


+ 0 - 0
public/app/panels/graph/graph.js → public/app/plugins/panels/graph/graph.js


+ 0 - 0
public/app/panels/graph/graph.tooltip.js → public/app/plugins/panels/graph/graph.tooltip.js


+ 1 - 1
public/app/panels/graph/legend.js → public/app/plugins/panels/graph/legend.js

@@ -45,7 +45,7 @@ function (angular, _, $) {
           popoverScope.series = seriesInfo;
           popoverSrv.show({
             element: el,
-            templateUrl:  'app/panels/graph/legend.popover.html',
+            templateUrl:  'app/plugins/panels/graph/legend.popover.html',
             scope: popoverScope
           });
         }

+ 0 - 0
public/app/panels/graph/legend.popover.html → public/app/plugins/panels/graph/legend.popover.html


+ 0 - 0
public/app/panels/graph/module.html → public/app/plugins/panels/graph/module.html


+ 3 - 3
public/app/panels/graph/module.js → public/app/plugins/panels/graph/module.js

@@ -17,7 +17,7 @@ function (angular, _, moment, kbn, TimeSeries, PanelMeta) {
   module.directive('grafanaPanelGraph', function() {
     return {
       controller: 'GraphCtrl',
-      templateUrl: 'app/panels/graph/module.html',
+      templateUrl: 'app/plugins/panels/graph/module.html',
     };
   });
 
@@ -30,8 +30,8 @@ function (angular, _, moment, kbn, TimeSeries, PanelMeta) {
       metricsEditor: true,
     });
 
-    $scope.panelMeta.addEditorTab('Axes & Grid', 'app/panels/graph/axisEditor.html');
-    $scope.panelMeta.addEditorTab('Display Styles', 'app/panels/graph/styleEditor.html');
+    $scope.panelMeta.addEditorTab('Axes & Grid', 'app/plugins/panels/graph/axisEditor.html');
+    $scope.panelMeta.addEditorTab('Display Styles', 'app/plugins/panels/graph/styleEditor.html');
     $scope.panelMeta.addEditorTab('Time range', 'app/features/panel/partials/panelTime.html');
 
     $scope.panelMeta.addExtendedMenuItem('Export CSV', '', 'exportCsv()');

+ 8 - 0
public/app/plugins/panels/graph/plugin.json

@@ -0,0 +1,8 @@
+{
+  "pluginType": "panel",
+
+  "name": "Graph",
+  "type": "graph",
+
+  "module": "app/plugins/panels/graph/module"
+}

+ 0 - 0
public/app/panels/graph/seriesOverridesCtrl.js → public/app/plugins/panels/graph/seriesOverridesCtrl.js


+ 0 - 0
public/app/panels/graph/styleEditor.html → public/app/plugins/panels/graph/styleEditor.html


+ 0 - 0
public/app/panels/singlestat/editor.html → public/app/plugins/panels/singlestat/editor.html


+ 0 - 0
public/app/panels/singlestat/module.html → public/app/plugins/panels/singlestat/module.html


+ 2 - 2
public/app/panels/singlestat/module.js → public/app/plugins/panels/singlestat/module.js

@@ -16,7 +16,7 @@ function (angular, app, _, kbn, TimeSeries, PanelMeta) {
   module.directive('grafanaPanelSinglestat', function() {
     return {
       controller: 'SingleStatCtrl',
-      templateUrl: 'app/panels/singlestat/module.html',
+      templateUrl: 'app/plugins/panels/singlestat/module.html',
     };
   });
 
@@ -31,7 +31,7 @@ function (angular, app, _, kbn, TimeSeries, PanelMeta) {
 
     $scope.fontSizes = ['20%', '30%','50%','70%','80%','100%', '110%', '120%', '150%', '170%', '200%'];
 
-    $scope.panelMeta.addEditorTab('Options', 'app/panels/singlestat/editor.html');
+    $scope.panelMeta.addEditorTab('Options', 'app/plugins/panels/singlestat/editor.html');
     $scope.panelMeta.addEditorTab('Time range', 'app/features/panel/partials/panelTime.html');
 
     // Set and populate defaults

+ 8 - 0
public/app/plugins/panels/singlestat/plugin.json

@@ -0,0 +1,8 @@
+{
+  "pluginType": "panel",
+
+  "name": "Singlestat",
+  "type": "singlestat",
+
+  "module": "app/plugins/panels/singlestat/module"
+}

+ 0 - 0
public/app/panels/singlestat/singleStatPanel.js → public/app/plugins/panels/singlestat/singleStatPanel.js


+ 2 - 2
public/app/panels/table/controller.ts → public/app/plugins/panels/table/controller.ts

@@ -1,4 +1,4 @@
-///<reference path="../../headers/common.d.ts" />
+///<reference path="../../../headers/common.d.ts" />
 
 import angular = require('angular');
 import _ = require('lodash');
@@ -21,7 +21,7 @@ export class TablePanelCtrl {
       metricsEditor: true,
     });
 
-    $scope.panelMeta.addEditorTab('Options', 'app/panels/table/options.html');
+    $scope.panelMeta.addEditorTab('Options', 'app/plugins/panels/table/options.html');
     $scope.panelMeta.addEditorTab('Time range', 'app/features/panel/partials/panelTime.html');
 
     var panelDefaults = {

+ 0 - 0
public/app/panels/table/editor.html → public/app/plugins/panels/table/editor.html


+ 2 - 3
public/app/panels/table/editor.ts → public/app/plugins/panels/table/editor.ts

@@ -1,5 +1,4 @@
-
-///<reference path="../../headers/common.d.ts" />
+///<reference path="../../../headers/common.d.ts" />
 
 import angular = require('angular');
 import $ = require('jquery');
@@ -14,7 +13,7 @@ export function tablePanelEditor() {
   return {
     restrict: 'E',
     scope: true,
-    templateUrl: 'app/panels/table/editor.html',
+    templateUrl: 'app/plugins/panels/table/editor.html',
     link: function(scope, elem) {
       scope.transformers = transformers;
       scope.unitFormats = kbn.getUnitFormats();

+ 0 - 0
public/app/panels/table/module.html → public/app/plugins/panels/table/module.html


+ 2 - 2
public/app/panels/table/module.ts → public/app/plugins/panels/table/module.ts

@@ -1,4 +1,4 @@
-///<reference path="../../headers/common.d.ts" />
+///<reference path="../../../headers/common.d.ts" />
 
 import angular = require('angular');
 import $ = require('jquery');
@@ -14,7 +14,7 @@ export function tablePanel() {
   'use strict';
   return {
     restrict: 'E',
-    templateUrl: 'app/panels/table/module.html',
+    templateUrl: 'app/plugins/panels/table/module.html',
     controller: TablePanelCtrl,
     link: function(scope, elem) {
       var data;

+ 0 - 0
public/app/panels/table/options.html → public/app/plugins/panels/table/options.html


+ 8 - 0
public/app/plugins/panels/table/plugin.json

@@ -0,0 +1,8 @@
+{
+  "pluginType": "panel",
+
+  "name": "Table",
+  "type": "table",
+
+  "module": "app/plugins/panels/table/module"
+}

+ 1 - 1
public/app/panels/table/renderer.ts → public/app/plugins/panels/table/renderer.ts

@@ -1,4 +1,4 @@
-///<reference path="../../headers/common.d.ts" />
+///<reference path="../../../headers/common.d.ts" />
 
 import _ = require('lodash');
 import kbn = require('app/core/utils/kbn');

+ 0 - 0
public/app/panels/table/specs/renderer_specs.ts → public/app/plugins/panels/table/specs/renderer_specs.ts


+ 0 - 0
public/app/panels/table/specs/table_model_specs.ts → public/app/plugins/panels/table/specs/table_model_specs.ts


+ 0 - 0
public/app/panels/table/specs/transformers_specs.ts → public/app/plugins/panels/table/specs/transformers_specs.ts


+ 0 - 0
public/app/panels/table/table_model.ts → public/app/plugins/panels/table/table_model.ts


+ 1 - 1
public/app/panels/table/transformers.ts → public/app/plugins/panels/table/transformers.ts

@@ -1,4 +1,4 @@
-///<reference path="../../headers/common.d.ts" />
+///<reference path="../../../headers/common.d.ts" />
 
 import moment = require('moment');
 import _ = require('lodash');

+ 0 - 0
public/app/panels/text/editor.html → public/app/plugins/panels/text/editor.html


+ 0 - 0
public/app/panels/text/module.html → public/app/plugins/panels/text/module.html


+ 3 - 3
public/app/panels/text/module.js → public/app/plugins/panels/text/module.js

@@ -16,7 +16,7 @@ function (angular, app, _, require, PanelMeta) {
   module.directive('grafanaPanelText', function() {
     return {
       controller: 'TextPanelCtrl',
-      templateUrl: 'app/panels/text/module.html',
+      templateUrl: 'app/plugins/panels/text/module.html',
     };
   });
 
@@ -28,7 +28,7 @@ function (angular, app, _, require, PanelMeta) {
       fullscreen: true,
     });
 
-    $scope.panelMeta.addEditorTab('Edit text', 'app/panels/text/editor.html');
+    $scope.panelMeta.addEditorTab('Edit text', 'app/plugins/panels/text/editor.html');
 
     // Set and populate defaults
     var _d = {
@@ -84,7 +84,7 @@ function (angular, app, _, require, PanelMeta) {
         $scope.updateContent(converter.makeHtml(text));
       }
       else {
-        require(['./lib/showdown'], function (Showdown) {
+        require(['vendor/showdown'], function (Showdown) {
           converter = new Showdown.converter();
           $scope.updateContent(converter.makeHtml(text));
         });

+ 8 - 0
public/app/plugins/panels/text/plugin.json

@@ -0,0 +1,8 @@
+{
+  "pluginType": "panel",
+
+  "name": "Text",
+  "type": "text",
+
+  "module": "app/plugins/panels/text/module"
+}

+ 0 - 0
public/app/plugins/PLUGIN_CHANGES.md → public/app/plugins/plugin_api.md


+ 1 - 1
public/test/specs/graph-ctrl-specs.js

@@ -2,7 +2,7 @@ define([
   './helpers',
   'app/features/panel/panel_srv',
   'app/features/panel/panel_helper',
-  'app/panels/graph/module'
+  'app/plugins/panels/graph/module'
 ], function(helpers) {
   'use strict';
 

+ 1 - 1
public/test/specs/graph-specs.js

@@ -3,7 +3,7 @@ define([
   'angular',
   'jquery',
   'app/core/time_series',
-  'app/panels/graph/graph'
+  'app/plugins/panels/graph/graph'
 ], function(helpers, angular, $, TimeSeries) {
   'use strict';
 

+ 1 - 1
public/test/specs/graph-tooltip-specs.js

@@ -1,6 +1,6 @@
 define([
   'jquery',
-  'app/panels/graph/graph.tooltip'
+  'app/plugins/panels/graph/graph.tooltip'
 ], function($, GraphTooltip) {
   'use strict';
 

+ 1 - 1
public/test/specs/seriesOverridesCtrl-specs.js

@@ -1,6 +1,6 @@
 define([
   './helpers',
-  'app/panels/graph/seriesOverridesCtrl'
+  'app/plugins/panels/graph/seriesOverridesCtrl'
 ], function(helpers) {
   'use strict';
 

+ 1 - 1
public/test/specs/singlestat-specs.js

@@ -2,7 +2,7 @@ define([
   './helpers',
   'app/features/panel/panel_srv',
   'app/features/panel/panel_helper',
-  'app/panels/singlestat/module'
+  'app/plugins/panels/singlestat/module'
 ], function(helpers) {
   'use strict';
 

+ 0 - 0
public/app/panels/text/lib/showdown.js → public/vendor/showdown.js