Quellcode durchsuchen

Merge pull request #12169 from alexanderzobnin/feat-10796

Import dashboard to folder
Marcus Efraimsson vor 7 Jahren
Ursprung
Commit
2288e01752

+ 1 - 0
pkg/api/dtos/plugins.go

@@ -57,4 +57,5 @@ type ImportDashboardCommand struct {
 	Overwrite bool                           `json:"overwrite"`
 	Dashboard *simplejson.Json               `json:"dashboard"`
 	Inputs    []plugins.ImportDashboardInput `json:"inputs"`
+	FolderId  int64                          `json:"folderId"`
 }

+ 2 - 1
pkg/api/index.go

@@ -99,9 +99,10 @@ func setIndexViewData(c *m.ReqContext) (*dtos.IndexViewData, error) {
 
 		if c.OrgRole == m.ROLE_ADMIN || c.OrgRole == m.ROLE_EDITOR {
 			children = append(children, &dtos.NavLink{Text: "Folder", SubTitle: "Create a new folder to organize your dashboards", Id: "folder", Icon: "gicon gicon-folder-new", Url: setting.AppSubUrl + "/dashboards/folder/new"})
-			children = append(children, &dtos.NavLink{Text: "Import", SubTitle: "Import dashboard from file or Grafana.com", Id: "import", Icon: "gicon gicon-dashboard-import", Url: setting.AppSubUrl + "/dashboard/import"})
 		}
 
+		children = append(children, &dtos.NavLink{Text: "Import", SubTitle: "Import dashboard from file or Grafana.com", Id: "import", Icon: "gicon gicon-dashboard-import", Url: setting.AppSubUrl + "/dashboard/import"})
+
 		data.NavTree = append(data.NavTree, &dtos.NavLink{
 			Text:     "Create",
 			Id:       "create",

+ 1 - 0
pkg/api/plugins.go

@@ -174,6 +174,7 @@ func ImportDashboard(c *m.ReqContext, apiCmd dtos.ImportDashboardCommand) Respon
 		Path:      apiCmd.Path,
 		Inputs:    apiCmd.Inputs,
 		Overwrite: apiCmd.Overwrite,
+		FolderId:  apiCmd.FolderId,
 		Dashboard: apiCmd.Dashboard,
 	}
 

+ 3 - 1
pkg/plugins/dashboard_importer.go

@@ -16,6 +16,7 @@ type ImportDashboardCommand struct {
 	Path      string
 	Inputs    []ImportDashboardInput
 	Overwrite bool
+	FolderId  int64
 
 	OrgId    int64
 	User     *m.SignedInUser
@@ -70,7 +71,7 @@ func ImportDashboard(cmd *ImportDashboardCommand) error {
 		UserId:    cmd.User.UserId,
 		Overwrite: cmd.Overwrite,
 		PluginId:  cmd.PluginId,
-		FolderId:  dashboard.FolderId,
+		FolderId:  cmd.FolderId,
 	}
 
 	dto := &dashboards.SaveDashboardDTO{
@@ -91,6 +92,7 @@ func ImportDashboard(cmd *ImportDashboardCommand) error {
 		Title:            savedDash.Title,
 		Path:             cmd.Path,
 		Revision:         savedDash.Data.Get("revision").MustInt64(1),
+		FolderId:         savedDash.FolderId,
 		ImportedUri:      "db/" + savedDash.Slug,
 		ImportedUrl:      savedDash.GetUrl(),
 		ImportedRevision: dashboard.Data.Get("revision").MustInt64(1),

+ 1 - 0
pkg/plugins/dashboards.go

@@ -17,6 +17,7 @@ type PluginDashboardInfoDTO struct {
 	ImportedUrl      string `json:"importedUrl"`
 	Slug             string `json:"slug"`
 	DashboardId      int64  `json:"dashboardId"`
+	FolderId         int64  `json:"folderId"`
 	ImportedRevision int64  `json:"importedRevision"`
 	Revision         int64  `json:"revision"`
 	Description      string `json:"description"`

+ 4 - 0
public/app/core/components/manage_dashboards/manage_dashboards.html

@@ -13,6 +13,10 @@
       <i class="fa fa-plus"></i>
       Folder
     </a>
+    <a class="btn btn-success" href="{{ctrl.importDashboardUrl()}}" ng-if="ctrl.hasEditPermissionInFolders || ctrl.canSave">
+      <i class="fa fa-plus"></i>
+      Import
+    </a>
   </div>
 
   <div class="page-action-bar page-action-bar--narrow" ng-show="ctrl.hasFilters">

+ 10 - 0
public/app/core/components/manage_dashboards/manage_dashboards.ts

@@ -294,6 +294,16 @@ export class ManageDashboardsCtrl {
 
     return url;
   }
+
+  importDashboardUrl() {
+    let url = 'dashboard/import';
+
+    if (this.folderId) {
+      url += `?folderId=${this.folderId}`;
+    }
+
+    return url;
+  }
 }
 
 export function manageDashboardsDirective() {

+ 2 - 2
public/app/core/components/search/search.html

@@ -52,11 +52,11 @@
         <a href="dashboards/folder/new" class="search-filter-box-link" ng-if="ctrl.isEditor">
           <i class="gicon gicon-folder-new"></i> New folder
         </a>
-        <a href="dashboard/import" class="search-filter-box-link" ng-if="ctrl.isEditor">
+        <a href="dashboard/import" class="search-filter-box-link" ng-if="ctrl.isEditor || ctrl.hasEditPermissionInFolders">
           <i class="gicon gicon-dashboard-import"></i> Import dashboard
         </a>
         <a class="search-filter-box-link" target="_blank" href="https://grafana.com/dashboards?utm_source=grafana_search">
-          <img src="public/img/icn-dashboard-tiny.svg" width="20" /> Find  dashboards on Grafana.com
+          <img src="public/img/icn-dashboard-tiny.svg" width="20" /> Find dashboards on Grafana.com
         </a>
       </div>
     </div>

+ 25 - 1
public/app/features/dashboard/dashboard_import_ctrl.ts

@@ -21,6 +21,9 @@ export class DashboardImportCtrl {
   uidValidationError: any;
   autoGenerateUid: boolean;
   autoGenerateUidValue: string;
+  folderId: number;
+  initialFolderTitle: string;
+  isValidFolderSelection: boolean;
 
   /** @ngInject */
   constructor(private backendSrv, private validationSrv, navModelSrv, private $location, $routeParams) {
@@ -31,6 +34,8 @@ export class DashboardImportCtrl {
     this.uidExists = false;
     this.autoGenerateUid = true;
     this.autoGenerateUidValue = 'auto-generated';
+    this.folderId = $routeParams.folderId ? Number($routeParams.folderId) || 0 : null;
+    this.initialFolderTitle = 'Select a folder';
 
     // check gnetId in url
     if ($routeParams.gnetId) {
@@ -102,8 +107,9 @@ export class DashboardImportCtrl {
     this.nameExists = false;
 
     this.validationSrv
-      .validateNewDashboardName(0, this.dash.title)
+      .validateNewDashboardName(this.folderId, this.dash.title)
       .then(() => {
+        this.nameExists = false;
         this.hasNameValidationError = false;
       })
       .catch(err => {
@@ -138,6 +144,23 @@ export class DashboardImportCtrl {
       });
   }
 
+  onFolderChange(folder) {
+    this.folderId = folder.id;
+    this.titleChanged();
+  }
+
+  onEnterFolderCreation() {
+    this.inputsValid = false;
+  }
+
+  onExitFolderCreation() {
+    this.inputValueChanged();
+  }
+
+  isValid() {
+    return this.inputsValid && this.folderId !== null;
+  }
+
   saveDashboard() {
     var inputs = this.inputs.map(input => {
       return {
@@ -153,6 +176,7 @@ export class DashboardImportCtrl {
         dashboard: this.dash,
         overwrite: true,
         inputs: inputs,
+        folderId: this.folderId,
       })
       .then(res => {
         this.$location.url(res.importedUrl);

+ 17 - 14
public/app/features/dashboard/folder_picker/folder_picker.ts

@@ -132,23 +132,26 @@ export class FolderPickerCtrl {
   }
 
   private loadInitialValue() {
-    if (this.initialFolderId && this.initialFolderId > 0) {
-      this.getOptions('').then(result => {
-        this.folder = _.find(result, { value: this.initialFolderId });
-        if (!this.folder) {
-          this.folder = { text: this.initialTitle, value: this.initialFolderId };
-        }
-        this.onFolderLoad();
-      });
-    } else {
-      if (this.initialTitle && this.initialFolderId === null) {
-        this.folder = { text: this.initialTitle, value: null };
-      } else {
-        this.folder = { text: this.rootName, value: 0 };
+    const resetFolder = { text: this.initialTitle, value: null };
+    const rootFolder = { text: this.rootName, value: 0 };
+    this.getOptions('').then(result => {
+      let folder;
+      if (this.initialFolderId) {
+        folder = _.find(result, { value: this.initialFolderId });
+      } else if (this.enableReset && this.initialTitle && this.initialFolderId === null) {
+        folder = resetFolder;
       }
 
+      if (!folder) {
+        if (this.isEditor) {
+          folder = rootFolder;
+        } else {
+          folder = result.length > 0 ? result[0] : resetFolder;
+        }
+      }
+      this.folder = folder;
       this.onFolderLoad();
-    }
+    });
   }
 
   private onFolderLoad() {

+ 16 - 2
public/app/features/dashboard/partials/dashboard_import.html

@@ -80,6 +80,20 @@
         </div>
       </div>
 
+      <div class="gf-form-inline">
+        <div class="gf-form gf-form--grow">
+          <folder-picker  label-class="width-15"
+                          initial-folder-id="ctrl.folderId"
+                          initial-title="ctrl.initialFolderTitle"
+                          on-change="ctrl.onFolderChange($folder)"
+                          on-load="ctrl.onFolderChange($folder)"
+                          enter-folder-creation="ctrl.onEnterFolderCreation()"
+                          exit-folder-creation="ctrl.onExitFolderCreation()"
+                          enable-create-new="true">
+          </folder-picker>
+        </div>
+      </div>
+
       <div class="gf-form-inline">
         <div class="gf-form gf-form--grow">
           <span class="gf-form-label width-15">
@@ -132,10 +146,10 @@
     </div>
 
     <div class="gf-form-button-row">
-      <button type="button" class="btn btn-success width-12" ng-click="ctrl.saveDashboard()" ng-hide="ctrl.nameExists || ctrl.uidExists" ng-disabled="!ctrl.inputsValid">
+      <button type="button" class="btn btn-success width-12" ng-click="ctrl.saveDashboard()" ng-hide="ctrl.nameExists || ctrl.uidExists" ng-disabled="!ctrl.isValid()">
         <i class="fa fa-save"></i> Import
       </button>
-      <button type="button" class="btn btn-danger width-12" ng-click="ctrl.saveDashboard()" ng-show="ctrl.nameExists || ctrl.uidExists" ng-disabled="!ctrl.inputsValid">
+      <button type="button" class="btn btn-danger width-12" ng-click="ctrl.saveDashboard()" ng-show="ctrl.nameExists || ctrl.uidExists" ng-disabled="!ctrl.isValid()">
         <i class="fa fa-save"></i> Import (Overwrite)
       </button>
       <a class="btn btn-link" ng-click="ctrl.back()">Cancel</a>