mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
feat(import): more import work
This commit is contained in:
parent
d9d46096dd
commit
7cd663bbe8
@ -1,6 +1,9 @@
|
|||||||
package dtos
|
package dtos
|
||||||
|
|
||||||
import "github.com/grafana/grafana/pkg/plugins"
|
import (
|
||||||
|
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||||
|
"github.com/grafana/grafana/pkg/plugins"
|
||||||
|
)
|
||||||
|
|
||||||
type PluginSetting struct {
|
type PluginSetting struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
@ -50,5 +53,6 @@ type ImportDashboardCommand struct {
|
|||||||
PluginId string `json:"pluginId"`
|
PluginId string `json:"pluginId"`
|
||||||
Path string `json:"path"`
|
Path string `json:"path"`
|
||||||
Overwrite bool `json:"overwrite"`
|
Overwrite bool `json:"overwrite"`
|
||||||
|
Dashboard *simplejson.Json `json:"dashboard"`
|
||||||
Inputs []plugins.ImportDashboardInput `json:"inputs"`
|
Inputs []plugins.ImportDashboardInput `json:"inputs"`
|
||||||
}
|
}
|
||||||
|
@ -168,10 +168,11 @@ func ImportDashboard(c *middleware.Context, apiCmd dtos.ImportDashboardCommand)
|
|||||||
Path: apiCmd.Path,
|
Path: apiCmd.Path,
|
||||||
Inputs: apiCmd.Inputs,
|
Inputs: apiCmd.Inputs,
|
||||||
Overwrite: apiCmd.Overwrite,
|
Overwrite: apiCmd.Overwrite,
|
||||||
|
Dashboard: apiCmd.Dashboard,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := bus.Dispatch(&cmd); err != nil {
|
if err := bus.Dispatch(&cmd); err != nil {
|
||||||
return ApiError(500, "Failed to install dashboard", err)
|
return ApiError(500, "Failed to import dashboard", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return Json(200, cmd.Result)
|
return Json(200, cmd.Result)
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type ImportDashboardCommand struct {
|
type ImportDashboardCommand struct {
|
||||||
|
Dashboard *simplejson.Json
|
||||||
Path string
|
Path string
|
||||||
Inputs []ImportDashboardInput
|
Inputs []ImportDashboardInput
|
||||||
Overwrite bool
|
Overwrite bool
|
||||||
@ -41,18 +42,16 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ImportDashboard(cmd *ImportDashboardCommand) error {
|
func ImportDashboard(cmd *ImportDashboardCommand) error {
|
||||||
plugin, exists := Plugins[cmd.PluginId]
|
|
||||||
|
|
||||||
if !exists {
|
|
||||||
return PluginNotFoundError{cmd.PluginId}
|
|
||||||
}
|
|
||||||
|
|
||||||
var dashboard *m.Dashboard
|
var dashboard *m.Dashboard
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if dashboard, err = loadPluginDashboard(plugin, cmd.Path); err != nil {
|
if cmd.PluginId != "" {
|
||||||
|
if dashboard, err = loadPluginDashboard(cmd.PluginId, cmd.Path); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
dashboard = m.NewDashboardFromJson(cmd.Dashboard)
|
||||||
|
}
|
||||||
|
|
||||||
evaluator := &DashTemplateEvaluator{
|
evaluator := &DashTemplateEvaluator{
|
||||||
template: dashboard.Data,
|
template: dashboard.Data,
|
||||||
@ -79,10 +78,10 @@ func ImportDashboard(cmd *ImportDashboardCommand) error {
|
|||||||
PluginId: cmd.PluginId,
|
PluginId: cmd.PluginId,
|
||||||
Title: dashboard.Title,
|
Title: dashboard.Title,
|
||||||
Path: cmd.Path,
|
Path: cmd.Path,
|
||||||
Revision: dashboard.GetString("revision", "1.0"),
|
Revision: dashboard.Data.Get("revision").MustInt64(1),
|
||||||
InstalledUri: "db/" + saveCmd.Result.Slug,
|
ImportedUri: "db/" + saveCmd.Result.Slug,
|
||||||
InstalledRevision: dashboard.GetString("revision", "1.0"),
|
ImportedRevision: dashboard.Data.Get("revision").MustInt64(1),
|
||||||
Installed: true,
|
Imported: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -12,10 +12,10 @@ import (
|
|||||||
type PluginDashboardInfoDTO struct {
|
type PluginDashboardInfoDTO struct {
|
||||||
PluginId string `json:"pluginId"`
|
PluginId string `json:"pluginId"`
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
Installed bool `json:"installed"`
|
Imported bool `json:"imported"`
|
||||||
InstalledUri string `json:"installedUri"`
|
ImportedUri string `json:"importedUri"`
|
||||||
InstalledRevision string `json:"installedRevision"`
|
ImportedRevision int64 `json:"importedRevision"`
|
||||||
Revision string `json:"revision"`
|
Revision int64 `json:"revision"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
Path string `json:"path"`
|
Path string `json:"path"`
|
||||||
}
|
}
|
||||||
@ -42,7 +42,12 @@ func GetPluginDashboards(orgId int64, pluginId string) ([]*PluginDashboardInfoDT
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadPluginDashboard(plugin *PluginBase, path string) (*m.Dashboard, error) {
|
func loadPluginDashboard(pluginId, path string) (*m.Dashboard, error) {
|
||||||
|
plugin, exists := Plugins[pluginId]
|
||||||
|
|
||||||
|
if !exists {
|
||||||
|
return nil, PluginNotFoundError{pluginId}
|
||||||
|
}
|
||||||
|
|
||||||
dashboardFilePath := filepath.Join(plugin.PluginDir, path)
|
dashboardFilePath := filepath.Join(plugin.PluginDir, path)
|
||||||
reader, err := os.Open(dashboardFilePath)
|
reader, err := os.Open(dashboardFilePath)
|
||||||
@ -66,14 +71,14 @@ func getDashboardImportStatus(orgId int64, plugin *PluginBase, path string) (*Pl
|
|||||||
var dashboard *m.Dashboard
|
var dashboard *m.Dashboard
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if dashboard, err = loadPluginDashboard(plugin, path); err != nil {
|
if dashboard, err = loadPluginDashboard(plugin.Id, path); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
res.Path = path
|
res.Path = path
|
||||||
res.PluginId = plugin.Id
|
res.PluginId = plugin.Id
|
||||||
res.Title = dashboard.Title
|
res.Title = dashboard.Title
|
||||||
res.Revision = dashboard.GetString("revision", "1.0")
|
res.Revision = dashboard.Data.Get("revision").MustInt64(1)
|
||||||
|
|
||||||
query := m.GetDashboardQuery{OrgId: orgId, Slug: dashboard.Slug}
|
query := m.GetDashboardQuery{OrgId: orgId, Slug: dashboard.Slug}
|
||||||
|
|
||||||
@ -82,9 +87,9 @@ func getDashboardImportStatus(orgId int64, plugin *PluginBase, path string) (*Pl
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
res.Installed = true
|
res.Imported = true
|
||||||
res.InstalledUri = "db/" + query.Result.Slug
|
res.ImportedUri = "db/" + query.Result.Slug
|
||||||
res.InstalledRevision = query.Result.GetString("revision", "1.0")
|
res.ImportedRevision = query.Result.Data.Get("revision").MustInt64(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
|
@ -67,7 +67,7 @@
|
|||||||
Create New
|
Create New
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a class="btn btn-inverse pull-left" ng-click="ctrl.import()" ng-show="ctrl.contextSrv.isEditor" ng-click="ctrl.isOpen = false;">
|
<a class="btn btn-inverse pull-left" href="dashboard/new/?editview=import" ng-show="ctrl.contextSrv.isEditor" ng-click="ctrl.isOpen = false;">
|
||||||
<i class="fa fa-upload"></i>
|
<i class="fa fa-upload"></i>
|
||||||
Import
|
Import
|
||||||
</a>
|
</a>
|
||||||
|
@ -149,11 +149,6 @@ export class SearchCtrl {
|
|||||||
this.searchDashboards();
|
this.searchDashboards();
|
||||||
};
|
};
|
||||||
|
|
||||||
import() {
|
|
||||||
appEvents.emit('show-modal', {
|
|
||||||
templateHtml: '<dash-import></dash-import>',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function searchDirective() {
|
export function searchDirective() {
|
||||||
|
@ -12,7 +12,7 @@ function ($, coreModule) {
|
|||||||
'import': { src: '<dash-import></dash-import>' }
|
'import': { src: '<dash-import></dash-import>' }
|
||||||
};
|
};
|
||||||
|
|
||||||
coreModule.default.directive('dashEditorView', function($compile, $location) {
|
coreModule.default.directive('dashEditorView', function($compile, $location, $rootScope) {
|
||||||
return {
|
return {
|
||||||
restrict: 'A',
|
restrict: 'A',
|
||||||
link: function(scope, elem) {
|
link: function(scope, elem) {
|
||||||
@ -57,6 +57,21 @@ function ($, coreModule) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (editview === 'import') {
|
||||||
|
var modalScope = $rootScope.$new();
|
||||||
|
modalScope.$on("$destroy", function() {
|
||||||
|
editorScope.dismiss();
|
||||||
|
});
|
||||||
|
|
||||||
|
$rootScope.appEvent('show-modal', {
|
||||||
|
templateHtml: '<dash-import></dash-import>',
|
||||||
|
scope: modalScope,
|
||||||
|
backdrop: 'static'
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var view = payload.src;
|
var view = payload.src;
|
||||||
if (view.indexOf('.html') > 0) {
|
if (view.indexOf('.html') > 0) {
|
||||||
view = $('<div class="tabbed-view" ng-include="' + "'" + view + "'" + '"></div>');
|
view = $('<div class="tabbed-view" ng-include="' + "'" + view + "'" + '"></div>');
|
||||||
|
@ -81,11 +81,11 @@ function (angular, _, coreModule, config) {
|
|||||||
|
|
||||||
_.each(config.datasources, function(value, key) {
|
_.each(config.datasources, function(value, key) {
|
||||||
if (value.meta && value.meta.metrics) {
|
if (value.meta && value.meta.metrics) {
|
||||||
metricSources.push({
|
metricSources.push({value: key, name: key, meta: value.meta});
|
||||||
value: key === config.defaultDatasource ? null : key,
|
|
||||||
name: key,
|
if (key === config.defaultDatasource) {
|
||||||
meta: value.meta,
|
metricSources.push({value: null, name: 'default', meta: value.meta});
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -30,7 +30,8 @@ export class UtilSrv {
|
|||||||
persist: false,
|
persist: false,
|
||||||
show: false,
|
show: false,
|
||||||
scope: options.scope,
|
scope: options.scope,
|
||||||
keyboard: false
|
keyboard: false,
|
||||||
|
backdrop: options.backdrop
|
||||||
});
|
});
|
||||||
|
|
||||||
Promise.resolve(modal).then(function(modalEl) {
|
Promise.resolve(modal).then(function(modalEl) {
|
||||||
|
@ -84,7 +84,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="gf-form-button-row">
|
<div class="gf-form-button-row">
|
||||||
<button type="button" class="btn gf-form-btn width-10" ng-click="ctrl.saveDashboard()" ng-class="{'btn-danger': ctrl.nameExists, 'btn-success': !ctrl.nameExists}" ng-disable="!ctrl.inputsOk">
|
<button type="button" class="btn gf-form-btn width-10" ng-click="ctrl.saveDashboard()" ng-class="{'btn-danger': ctrl.nameExists, 'btn-success': !ctrl.nameExists}" ng-disabled="!ctrl.inputsValid">
|
||||||
<i class="fa fa-save"></i> Save & Open
|
<i class="fa fa-save"></i> Save & Open
|
||||||
</button>
|
</button>
|
||||||
<a class="btn btn-link" ng-click="dismiss()">Cancel</a>
|
<a class="btn btn-link" ng-click="dismiss()">Cancel</a>
|
||||||
|
@ -12,7 +12,6 @@ export class DashImportCtrl {
|
|||||||
parseError: string;
|
parseError: string;
|
||||||
nameExists: boolean;
|
nameExists: boolean;
|
||||||
dash: any;
|
dash: any;
|
||||||
dismiss: any;
|
|
||||||
inputs: any[];
|
inputs: any[];
|
||||||
inputsValid: boolean;
|
inputsValid: boolean;
|
||||||
|
|
||||||
@ -33,6 +32,7 @@ export class DashImportCtrl {
|
|||||||
var inputModel = {
|
var inputModel = {
|
||||||
name: input.name,
|
name: input.name,
|
||||||
type: input.type,
|
type: input.type,
|
||||||
|
pluginId: input.pluginId,
|
||||||
options: []
|
options: []
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -64,7 +64,7 @@ export class DashImportCtrl {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
inputOptionChanged() {
|
inputValueChanged() {
|
||||||
this.inputsValid = true;
|
this.inputsValid = true;
|
||||||
for (let input of this.inputs) {
|
for (let input of this.inputs) {
|
||||||
if (!input.value) {
|
if (!input.value) {
|
||||||
@ -86,9 +86,22 @@ export class DashImportCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
saveDashboard() {
|
saveDashboard() {
|
||||||
return this.backendSrv.saveDashboard(this.dash, {overwrite: true}).then(res => {
|
var inputs = this.inputs.map(input => {
|
||||||
this.$location.url('dashboard/db/' + res.slug);
|
return {
|
||||||
this.dismiss();
|
name: input.name,
|
||||||
|
type: input.type,
|
||||||
|
pluginId: input.pluginId,
|
||||||
|
value: input.value
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return this.backendSrv.post('api/dashboards/import', {
|
||||||
|
dashboard: this.dash,
|
||||||
|
overwrite: true,
|
||||||
|
inputs: inputs
|
||||||
|
}).then(res => {
|
||||||
|
this.$location.url('dashboard/' + res.importedUri);
|
||||||
|
this.$scope.dismiss();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,27 +6,27 @@
|
|||||||
<i class="icon-gf icon-gf-dashboard"></i>
|
<i class="icon-gf icon-gf-dashboard"></i>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="dashboard/{{dash.installedUri}}" ng-show="dash.installed">
|
<a href="dashboard/{{dash.importedUri}}" ng-show="dash.imported">
|
||||||
{{dash.title}}
|
{{dash.title}}
|
||||||
</a>
|
</a>
|
||||||
<span ng-show="!dash.installed">
|
<span ng-show="!dash.imported">
|
||||||
{{dash.title}}
|
{{dash.title}}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
v{{dash.revision}}
|
v{{dash.revision}}
|
||||||
<span ng-if="dash.installed">
|
<span ng-if="dash.installed">
|
||||||
(Imported v{{dash.installedRevision}})
|
(Imported v{{dash.importedRevision}})
|
||||||
<span>
|
<span>
|
||||||
</td>
|
</td>
|
||||||
<td style="text-align: right">
|
<td style="text-align: right">
|
||||||
<button class="btn btn-secondary" ng-click="ctrl.import(dash, false)" ng-show="!dash.installed">
|
<button class="btn btn-secondary" ng-click="ctrl.import(dash, false)" ng-show="!dash.imported">
|
||||||
Import
|
Import
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-secondary" ng-click="ctrl.import(dash, true)" ng-show="dash.installed">
|
<button class="btn btn-secondary" ng-click="ctrl.import(dash, true)" ng-show="dash.imported">
|
||||||
Update
|
Update
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-danger" ng-click="ctrl.remove(dash)" ng-show="dash.installed">
|
<button class="btn btn-danger" ng-click="ctrl.remove(dash)" ng-show="dash.imported">
|
||||||
Delete
|
Delete
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
|
@ -61,15 +61,15 @@ export class DashImportListCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return this.backendSrv.post(`/api/dashboards/import`, installCmd).then(res => {
|
return this.backendSrv.post(`/api/dashboards/import`, installCmd).then(res => {
|
||||||
this.$rootScope.appEvent('alert-success', ['Dashboard Installed', dash.title]);
|
this.$rootScope.appEvent('alert-success', ['Dashboard Imported', dash.title]);
|
||||||
_.extend(dash, res);
|
_.extend(dash, res);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
remove(dash) {
|
remove(dash) {
|
||||||
this.backendSrv.delete('/api/dashboards/' + dash.installedUri).then(() => {
|
this.backendSrv.delete('/api/dashboards/' + dash.importedUri).then(() => {
|
||||||
this.$rootScope.appEvent('alert-success', ['Dashboard Deleted', dash.title]);
|
this.$rootScope.appEvent('alert-success', ['Dashboard Deleted', dash.title]);
|
||||||
dash.installed = false;
|
dash.imported = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user