Ver código fonte

dashboard_folders: refactoring picker and folder selection in dashboard settings & save as menu

Torkel Ödegaard 8 anos atrás
pai
commit
d9dca72ee4

+ 30 - 18
pkg/api/dashboard.go

@@ -40,8 +40,8 @@ func GetDashboard(c *middleware.Context) Response {
 	slug := strings.ToLower(c.Params(":slug"))
 	slug := strings.ToLower(c.Params(":slug"))
 
 
 	query := m.GetDashboardQuery{Slug: slug, OrgId: c.OrgId}
 	query := m.GetDashboardQuery{Slug: slug, OrgId: c.OrgId}
-	err := bus.Dispatch(&query)
-	if err != nil {
+
+	if err := bus.Dispatch(&query); err != nil {
 		return ApiError(404, "Dashboard not found", err)
 		return ApiError(404, "Dashboard not found", err)
 	}
 	}
 
 
@@ -70,27 +70,39 @@ func GetDashboard(c *middleware.Context) Response {
 		creator = getUserLogin(dash.CreatedBy)
 		creator = getUserLogin(dash.CreatedBy)
 	}
 	}
 
 
+	meta := dtos.DashboardMeta{
+		IsStarred:   isStarred,
+		Slug:        slug,
+		Type:        m.DashTypeDB,
+		CanStar:     c.IsSignedIn,
+		CanSave:     canSave,
+		CanEdit:     canEdit,
+		Created:     dash.Created,
+		Updated:     dash.Updated,
+		UpdatedBy:   updater,
+		CreatedBy:   creator,
+		Version:     dash.Version,
+		HasAcl:      dash.HasAcl,
+		IsFolder:    dash.IsFolder,
+		FolderId:    dash.ParentId,
+		FolderTitle: "Root",
+	}
+
+	// lookup folder title
+	if dash.ParentId > 0 {
+		query := m.GetDashboardQuery{Id: dash.ParentId, OrgId: c.OrgId}
+		if err := bus.Dispatch(&query); err != nil {
+			return ApiError(500, "Dashboard folder could not be read", err)
+		}
+		meta.FolderTitle = query.Result.Title
+	}
+
 	// make sure db version is in sync with json model version
 	// make sure db version is in sync with json model version
 	dash.Data.Set("version", dash.Version)
 	dash.Data.Set("version", dash.Version)
 
 
 	dto := dtos.DashboardFullWithMeta{
 	dto := dtos.DashboardFullWithMeta{
 		Dashboard: dash.Data,
 		Dashboard: dash.Data,
-		Meta: dtos.DashboardMeta{
-			IsStarred: isStarred,
-			Slug:      slug,
-			Type:      m.DashTypeDB,
-			CanStar:   c.IsSignedIn,
-			CanSave:   canSave,
-			CanEdit:   canEdit,
-			Created:   dash.Created,
-			Updated:   dash.Updated,
-			UpdatedBy: updater,
-			CreatedBy: creator,
-			Version:   dash.Version,
-			HasAcl:    dash.HasAcl,
-			IsFolder:  dash.IsFolder,
-			ParentId:  dash.ParentId,
-		},
+		Meta:      meta,
 	}
 	}
 
 
 	c.TimeRequest(metrics.M_Api_Dashboard_Get)
 	c.TimeRequest(metrics.M_Api_Dashboard_Get)

+ 18 - 17
pkg/api/dtos/dashboard.go

@@ -7,23 +7,24 @@ import (
 )
 )
 
 
 type DashboardMeta struct {
 type DashboardMeta struct {
-	IsStarred  bool      `json:"isStarred,omitempty"`
-	IsHome     bool      `json:"isHome,omitempty"`
-	IsSnapshot bool      `json:"isSnapshot,omitempty"`
-	Type       string    `json:"type,omitempty"`
-	CanSave    bool      `json:"canSave"`
-	CanEdit    bool      `json:"canEdit"`
-	CanStar    bool      `json:"canStar"`
-	Slug       string    `json:"slug"`
-	Expires    time.Time `json:"expires"`
-	Created    time.Time `json:"created"`
-	Updated    time.Time `json:"updated"`
-	UpdatedBy  string    `json:"updatedBy"`
-	CreatedBy  string    `json:"createdBy"`
-	Version    int       `json:"version"`
-	HasAcl     bool      `json:"hasAcl"`
-	IsFolder   bool      `json:"isFolder"`
-	ParentId   int64     `json:"parentId"`
+	IsStarred   bool      `json:"isStarred,omitempty"`
+	IsHome      bool      `json:"isHome,omitempty"`
+	IsSnapshot  bool      `json:"isSnapshot,omitempty"`
+	Type        string    `json:"type,omitempty"`
+	CanSave     bool      `json:"canSave"`
+	CanEdit     bool      `json:"canEdit"`
+	CanStar     bool      `json:"canStar"`
+	Slug        string    `json:"slug"`
+	Expires     time.Time `json:"expires"`
+	Created     time.Time `json:"created"`
+	Updated     time.Time `json:"updated"`
+	UpdatedBy   string    `json:"updatedBy"`
+	CreatedBy   string    `json:"createdBy"`
+	Version     int       `json:"version"`
+	HasAcl      bool      `json:"hasAcl"`
+	IsFolder    bool      `json:"isFolder"`
+	FolderId    int64     `json:"folderId"`
+	FolderTitle string    `json:"folderTitle"`
 }
 }
 
 
 type DashboardFullWithMeta struct {
 type DashboardFullWithMeta struct {

+ 1 - 1
public/app/core/nav_model_srv.ts

@@ -197,7 +197,7 @@ export class NavModelSrv {
       clickHandler: () => dashNavCtrl.showHelpModal()
       clickHandler: () => dashNavCtrl.showHelpModal()
     });
     });
 
 
-    if (this.contextSrv.isEditor) {
+    if (this.contextSrv.isEditor && !dashboard.meta.isFolder) {
       menu.push({
       menu.push({
         title: 'Save As ...',
         title: 'Save As ...',
         icon: 'fa fa-fw fa-save',
         icon: 'fa fa-fw fa-save',

+ 4 - 2
public/app/features/dashboard/dashboard_ctrl.ts

@@ -128,8 +128,10 @@ export class DashboardCtrl {
         $rootScope.$broadcast("refresh");
         $rootScope.$broadcast("refresh");
       };
       };
 
 
-      $scope.onFolderChange = function(parentId) {
-        $scope.dashboard.parentId = parentId;
+      $scope.onFolderChange = function(folder) {
+        $scope.dashboard.parentId = folder.id;
+        $scope.dashboard.meta.folderId = folder.id;
+        $scope.dashboard.meta.folderTitle= folder.title;
       };
       };
     }
     }
 
 

+ 0 - 10
public/app/features/dashboard/dashboard_srv.ts

@@ -113,17 +113,8 @@ export class DashboardSrv {
   }
   }
 
 
   showSaveAsModal() {
   showSaveAsModal() {
-    var newScope = this.$rootScope.$new();
-    newScope.clone = this.dash.getSaveModelClone();
-    newScope.clone.editable = true;
-    newScope.clone.hideControls = false;
-    newScope.clone.meta = {};
-    newScope.clone.meta.parentId = this.dash.meta.parentId;
-    newScope.clone.meta.isFolder = this.dash.meta.isFolder;
-
     this.$rootScope.appEvent('show-modal', {
     this.$rootScope.appEvent('show-modal', {
       templateHtml: '<save-dashboard-as-modal dismiss="dismiss()"></save-dashboard-as-modal>',
       templateHtml: '<save-dashboard-as-modal dismiss="dismiss()"></save-dashboard-as-modal>',
-      scope: newScope,
       modalClass: 'modal--narrow'
       modalClass: 'modal--narrow'
     });
     });
   }
   }
@@ -131,7 +122,6 @@ export class DashboardSrv {
   showSaveModal() {
   showSaveModal() {
     this.$rootScope.appEvent('show-modal', {
     this.$rootScope.appEvent('show-modal', {
       templateHtml: '<save-dashboard-modal dismiss="dismiss()"></save-dashboard-modal>',
       templateHtml: '<save-dashboard-modal dismiss="dismiss()"></save-dashboard-modal>',
-      scope: this.$rootScope.$new(),
       modalClass: 'modal--narrow'
       modalClass: 'modal--narrow'
     });
     });
   }
   }

+ 0 - 8
public/app/features/dashboard/folder_picker/picker.html

@@ -1,8 +0,0 @@
-<div class="gf-form">
-  <label class="gf-form-label width-7">Folder</label>
-  <div class="dropdown">
-    <metric-segment segment="ctrl.selectedFolderSegment"
-      get-options="ctrl.getOptions()"
-      on-change="ctrl.folderChanged()"></metric-segment>
-  </div>
-</div>

+ 33 - 30
public/app/features/dashboard/folder_picker/picker.ts

@@ -6,47 +6,38 @@ import _ from 'lodash';
 
 
 export class FolderPickerCtrl {
 export class FolderPickerCtrl {
   folders: Folder[];
   folders: Folder[];
-  selectedFolder: number;
-  selectedFolderSegment: any;
+  selectedOption: any;
+  initialTitle: string;
   onChange: any;
   onChange: any;
-  rootFolderName: string;
+  labelClass: string;
 
 
   /** @ngInject */
   /** @ngInject */
-  constructor(private backendSrv, private $scope, private $sce, private uiSegmentSrv) {
-    this.selectedFolderSegment = this.uiSegmentSrv.newSegment({value: this.rootFolderName || 'Root', selectMode: true});
-    this.get();
+  constructor(private backendSrv, private $scope, private $sce) {
+    if (!this.labelClass) {
+      this.labelClass = "width-7";
+    }
+
+    this.selectedOption = {text: this.initialTitle, value: null};
   }
   }
 
 
-  get() {
+  getOptions(query) {
     var params = {
     var params = {
+      query: query,
       type: 'dash-folder',
       type: 'dash-folder',
     };
     };
 
 
     return this.backendSrv.search(params).then(result => {
     return this.backendSrv.search(params).then(result => {
-      this.folders = [{id: 0, title: this.rootFolderName || 'Root', type: 'dash-folder'}];
-      this.folders.push(...result);
-
-      if (this.selectedFolder) {
-        const selected = _.find(this.folders, {id: this.selectedFolder});
-
-        this.selectedFolderSegment.value = selected.title;
-        this.selectedFolderSegment.text = selected.title;
-        this.selectedFolderSegment.html = this.$sce.trustAsHtml(selected.title);
+      if (query === "") {
+        result.unshift({title: "Root", value: 0});
       }
       }
+      return _.map(result, item => {
+        return {text: item.title, value: item.id};
+      });
     });
     });
   }
   }
 
 
-  getOptions() {
-    return Promise.resolve(this.folders.map(folder => {
-      return this.uiSegmentSrv.newSegment(folder.title);
-    }));
-  }
-
-  folderChanged() {
-    const selected = _.find(this.folders, {title: this.selectedFolderSegment.value});
-    if (selected) {
-      this.onChange({$folderId: selected.id});
-    }
+  folderChanged(option) {
+    this.onChange({$folder: {id: option.value, title: option.text}});
   }
   }
 }
 }
 
 
@@ -61,17 +52,29 @@ export interface Folder {
   dashboards?: any;
   dashboards?: any;
 }
 }
 
 
+const template = `
+<div class="gf-form">
+  <label class="gf-form-label {{ctrl.labelClass}}">Folder</label>
+  <div class="dropdown">
+    <gf-form-dropdown model="ctrl.selectedOption"
+      get-options="ctrl.getOptions($query)"
+      on-change="ctrl.folderChanged($option)">
+    </gf-form-dropdown>
+  </div>
+</div>
+`;
+
 export function folderPicker() {
 export function folderPicker() {
   return {
   return {
     restrict: 'E',
     restrict: 'E',
-    templateUrl: 'public/app/features/dashboard/folder_picker/picker.html',
+    template: template,
     controller: FolderPickerCtrl,
     controller: FolderPickerCtrl,
     bindToController: true,
     bindToController: true,
     controllerAs: 'ctrl',
     controllerAs: 'ctrl',
     scope: {
     scope: {
-      selectedFolder: "<",
+      initialTitle: "<",
       onChange: "&",
       onChange: "&",
-      rootFolderName: "@"
+      labelClass: "@",
     }
     }
   };
   };
 }
 }

+ 5 - 1
public/app/features/dashboard/partials/settings.html

@@ -45,7 +45,11 @@
 				</div>
 				</div>
 			</div>
 			</div>
 
 
-      <folder-picker ng-if="!dashboardMeta.isFolder" selected-folder="dashboardMeta.parentId" on-change="onFolderChange($folderId)"></folder-picker>
+      <folder-picker ng-if="!dashboardMeta.isFolder"
+										 initial-title="dashboardMeta.folderTitle"
+										 on-change="onFolderChange($folder)"
+										 label-class="width-7">
+			</folder-picker>
 		</div>
 		</div>
 
 
     <div class="section">
     <div class="section">

+ 8 - 4
public/app/features/dashboard/save_as_modal.ts

@@ -18,11 +18,13 @@ const  template = `
 	<form name="ctrl.saveForm" ng-submit="ctrl.save()" class="modal-content" novalidate>
 	<form name="ctrl.saveForm" ng-submit="ctrl.save()" class="modal-content" novalidate>
 		<div class="p-t-2">
 		<div class="p-t-2">
 			<div class="gf-form">
 			<div class="gf-form">
-				<label class="gf-form-label">New name</label>
+				<label class="gf-form-label width-7">New name</label>
 				<input type="text" class="gf-form-input" ng-model="ctrl.clone.title" give-focus="true" required>
 				<input type="text" class="gf-form-input" ng-model="ctrl.clone.title" give-focus="true" required>
 			</div>
 			</div>
       <div class="gf-form">
       <div class="gf-form">
-        <folder-picker ng-if="!ctrl.clone.meta.isFolder" selected-folder="ctrl.clone.meta.parentId" on-change="ctrl.onFolderChange($folderId)">
+        <folder-picker initial-title="ctrl.folderTitle"
+                       on-change="ctrl.onFolderChange($folder)"
+                       label-class="width-7">
         </folder-picker>
         </folder-picker>
       </div>
       </div>
 		</div>
 		</div>
@@ -37,6 +39,7 @@ const  template = `
 
 
 export class SaveDashboardAsModalCtrl {
 export class SaveDashboardAsModalCtrl {
   clone: any;
   clone: any;
+  folderTitle: any;
   dismiss: () => void;
   dismiss: () => void;
 
 
   /** @ngInject */
   /** @ngInject */
@@ -47,6 +50,7 @@ export class SaveDashboardAsModalCtrl {
     this.clone.title += ' Copy';
     this.clone.title += ' Copy';
     this.clone.editable = true;
     this.clone.editable = true;
     this.clone.hideControls = false;
     this.clone.hideControls = false;
+    this.folderTitle = dashboard.meta.folderTitle || 'Root';
 
 
     // remove alerts
     // remove alerts
     this.clone.rows.forEach(row => {
     this.clone.rows.forEach(row => {
@@ -68,8 +72,8 @@ export class SaveDashboardAsModalCtrl {
     }
     }
   }
   }
 
 
-  onFolderChange(parentId) {
-    this.clone.parentId = parentId;
+  onFolderChange(folder) {
+    this.clone.parentId = folder.id;
   }
   }
 }
 }
 
 

+ 4 - 2
public/app/plugins/panel/dashlist/editor.html

@@ -23,8 +23,10 @@
     </div>
     </div>
 
 
     <div class="gf-form">
     <div class="gf-form">
-      <span class="gf-form-label width-6">Folder</span>
-      <folder-picker selected-folder="ctrl.panel.folderId" on-change="ctrl.onFolderChange" root-folder-name="All"></folder-picker>
+      <folder-picker  initial-text="ctrl.folderTitle"
+											on-change="ctrl.onFolderChange($folder)"
+											label-class="width-6">
+			</folder-picker>
     </div>
     </div>
 
 
     <div class="gf-form">
     <div class="gf-form">

+ 10 - 4
public/app/plugins/panel/dashlist/module.ts

@@ -10,6 +10,7 @@ class DashListCtrl extends PanelCtrl {
 
 
   groups: any[];
   groups: any[];
   modes: any[];
   modes: any[];
+  folderTitle: any;
 
 
   panelDefaults = {
   panelDefaults = {
     query: '',
     query: '',
@@ -19,7 +20,7 @@ class DashListCtrl extends PanelCtrl {
     search: false,
     search: false,
     starred: true,
     starred: true,
     headings: true,
     headings: true,
-    folderId: 0
+    folderId: 0,
   };
   };
 
 
   /** @ngInject */
   /** @ngInject */
@@ -65,6 +66,10 @@ class DashListCtrl extends PanelCtrl {
     this.editorTabIndex = 1;
     this.editorTabIndex = 1;
     this.modes = ['starred', 'search', 'recently viewed'];
     this.modes = ['starred', 'search', 'recently viewed'];
     this.addEditorTab('Options', 'public/app/plugins/panel/dashlist/editor.html');
     this.addEditorTab('Options', 'public/app/plugins/panel/dashlist/editor.html');
+
+    if (!this.panel.folderId) {
+      this.folderTitle = "All";
+    }
   }
   }
 
 
   onRefresh() {
   onRefresh() {
@@ -126,9 +131,10 @@ class DashListCtrl extends PanelCtrl {
     });
     });
   }
   }
 
 
-  onFolderChange(parentId) {
-    this.$scope.$parent.ctrl.panel.folderId = parentId;
-    this.$scope.$parent.ctrl.refresh();
+  onFolderChange(folder) {
+    this.panel.folderId = folder.id;
+    this.panel.folderTitle = folder.title;
+    this.refresh();
   }
   }
 }
 }