mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
feat(plugins): made panels work as plugins
This commit is contained in:
parent
bd6e2d6ca4
commit
4a69de1f30
@ -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{}{
|
||||
|
@ -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"`
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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
public/app/plugins/external/example/readme.md
vendored
Normal file
13
public/app/plugins/external/example/readme.md
vendored
Normal 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
|
||||
```
|
||||
|
||||
|
||||
|
@ -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.
|
@ -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,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
}
|
@ -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
public/app/plugins/panels/dashlist/plugin.json
Normal file
8
public/app/plugins/panels/dashlist/plugin.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"pluginType": "panel",
|
||||
|
||||
"name": "Dashboard list",
|
||||
"type": "dashlist",
|
||||
|
||||
"module": "app/plugins/panels/dashlist/module"
|
||||
}
|
@ -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
|
||||
});
|
||||
}
|
@ -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
public/app/plugins/panels/graph/plugin.json
Normal file
8
public/app/plugins/panels/graph/plugin.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"pluginType": "panel",
|
||||
|
||||
"name": "Graph",
|
||||
"type": "graph",
|
||||
|
||||
"module": "app/plugins/panels/graph/module"
|
||||
}
|
@ -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
public/app/plugins/panels/singlestat/plugin.json
Normal file
8
public/app/plugins/panels/singlestat/plugin.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"pluginType": "panel",
|
||||
|
||||
"name": "Singlestat",
|
||||
"type": "singlestat",
|
||||
|
||||
"module": "app/plugins/panels/singlestat/module"
|
||||
}
|
@ -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 = {
|
@ -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();
|
@ -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;
|
8
public/app/plugins/panels/table/plugin.json
Normal file
8
public/app/plugins/panels/table/plugin.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"pluginType": "panel",
|
||||
|
||||
"name": "Table",
|
||||
"type": "table",
|
||||
|
||||
"module": "app/plugins/panels/table/module"
|
||||
}
|
@ -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');
|
@ -1,4 +1,4 @@
|
||||
///<reference path="../../headers/common.d.ts" />
|
||||
///<reference path="../../../headers/common.d.ts" />
|
||||
|
||||
import moment = require('moment');
|
||||
import _ = require('lodash');
|
@ -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
public/app/plugins/panels/text/plugin.json
Normal file
8
public/app/plugins/panels/text/plugin.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"pluginType": "panel",
|
||||
|
||||
"name": "Text",
|
||||
"type": "text",
|
||||
|
||||
"module": "app/plugins/panels/text/module"
|
||||
}
|
@ -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';
|
||||
|
||||
|
@ -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,6 +1,6 @@
|
||||
define([
|
||||
'jquery',
|
||||
'app/panels/graph/graph.tooltip'
|
||||
'app/plugins/panels/graph/graph.tooltip'
|
||||
], function($, GraphTooltip) {
|
||||
'use strict';
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
define([
|
||||
'./helpers',
|
||||
'app/panels/graph/seriesOverridesCtrl'
|
||||
'app/plugins/panels/graph/seriesOverridesCtrl'
|
||||
], function(helpers) {
|
||||
'use strict';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user