feat(plugins): made panels work as plugins

This commit is contained in:
Torkel Ödegaard 2015-11-21 13:46:18 +01:00
parent bd6e2d6ca4
commit 4a69de1f30
51 changed files with 113 additions and 79 deletions

View File

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

View File

@ -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"`

View File

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

View File

@ -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,

View File

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

View File

@ -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
```

View File

@ -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.

View File

@ -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,
}
]
}
}

View File

@ -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',

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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