Просмотр исходного кода

ux: dashboard settings work progress

Torkel Ödegaard 8 лет назад
Родитель
Сommit
008b9bb3e9

+ 1 - 1
public/app/features/dashboard/all.ts

@@ -4,7 +4,7 @@ import './history/history';
 import './dashboardLoaderSrv';
 import './dashnav/dashnav';
 import './submenu/submenu';
-import './save_as_modal';
+import './dashboard_save_as';
 import './save_modal';
 import './shareModalCtrl';
 import './shareSnapshotCtrl';

+ 81 - 0
public/app/features/dashboard/dashboard_save_as.ts

@@ -0,0 +1,81 @@
+import coreModule from 'app/core/core_module';
+
+const  template = `
+<h3 class="dashboard-settings__header">Save As</h3>
+
+<form name="ctrl.saveForm" ng-submit="ctrl.save()" novalidate>
+  <div class="p-t-2">
+    <div class="gf-form">
+      <label class="gf-form-label width-6">New name</label>
+      <input type="text" class="gf-form-input max-width-25" ng-model="ctrl.clone.title" give-focus="true" required>
+    </div>
+    <div class="gf-form">
+      <folder-picker initial-folder-id="ctrl.folderId"
+                      on-change="ctrl.onFolderChange($folder)"
+                      label-class="width-6">
+      </folder-picker>
+    </div>
+  </div>
+
+  <div class="gf-form-button-row">
+    <button type="submit" class="btn btn-success" ng-disabled="ctrl.saveForm.$invalid">Save As</button>
+  </div>
+</form>
+`;
+
+export class SaveDashboardAsCtrl {
+  clone: any;
+  folderId: any;
+  dismiss: () => void;
+
+  /** @ngInject */
+  constructor(private dashboardSrv) {
+    var dashboard = this.dashboardSrv.getCurrent();
+    this.clone = dashboard.getSaveModelClone();
+    this.clone.id = null;
+    this.clone.title += ' Copy';
+    this.clone.editable = true;
+    this.clone.hideControls = false;
+    this.folderId = dashboard.folderId;
+
+    // remove alerts if source dashboard is already persisted
+    // do not want to create alert dupes
+    if (dashboard.id > 0) {
+      this.clone.panels.forEach(panel => {
+        if (panel.type === "graph" && panel.alert) {
+          delete panel.thresholds;
+        }
+        delete panel.alert;
+      });
+    }
+
+    delete this.clone.autoUpdate;
+  }
+
+  save() {
+    return this.dashboardSrv.save(this.clone).then(this.dismiss);
+  }
+
+  keyDown(evt) {
+    if (evt.keyCode === 13) {
+      this.save();
+    }
+  }
+
+  onFolderChange(folder) {
+    this.clone.folderId = folder.id;
+  }
+}
+
+export function saveDashboardAsDirective() {
+  return {
+    restrict: 'E',
+    template: template,
+    controller: SaveDashboardAsCtrl,
+    bindToController: true,
+    controllerAs: 'ctrl',
+    scope: {}
+  };
+}
+
+coreModule.directive('saveDashboardAs',  saveDashboardAsDirective);

+ 0 - 54
public/app/features/dashboard/dashnav/dashnav.ts

@@ -1,4 +1,3 @@
-import _ from 'lodash';
 import moment from 'moment';
 import angular from 'angular';
 import {appEvents, NavModel} from 'app/core/core';
@@ -15,13 +14,11 @@ export class DashNavCtrl {
     private $rootScope,
     private dashboardSrv,
     private $location,
-    private backendSrv,
     public playlistSrv,
     navModelSrv) {
       this.navModel = navModelSrv.getDashboardNav(this.dashboard, this);
 
       appEvents.on('save-dashboard', this.saveDashboard.bind(this), $scope);
-      appEvents.on('delete-dashboard', this.deleteDashboard.bind(this), $scope);
 
       if (this.dashboard.meta.isSnapshot) {
         var meta = this.dashboard.meta;
@@ -76,61 +73,10 @@ export class DashNavCtrl {
       angular.element(evt.currentTarget).tooltip('hide');
     }
 
-    makeEditable() {
-      this.dashboard.editable = true;
-
-      return this.dashboardSrv.saveDashboard({makeEditable: true, overwrite: false}).then(() => {
-        // force refresh whole page
-        window.location.href = window.location.href;
-      });
-    }
-
-    exitFullscreen() {
-      this.$rootScope.appEvent('panel-change-view', {fullscreen: false, edit: false});
-    }
-
     saveDashboard() {
       return this.dashboardSrv.saveDashboard();
     }
 
-    deleteDashboard() {
-      var confirmText = '';
-      var text2 = this.dashboard.title;
-
-      const alerts = _.sumBy(this.dashboard.panels, panel => {
-         return panel.alert ? 1 : 0;
-      });
-
-      if (alerts > 0) {
-        confirmText = 'DELETE';
-        text2 = `This dashboard contains ${alerts} alerts. Deleting this dashboard will also delete those alerts`;
-      }
-
-      appEvents.emit('confirm-modal', {
-        title: 'Delete',
-        text: 'Do you want to delete this dashboard?',
-        text2: text2,
-        icon: 'fa-trash',
-        confirmText: confirmText,
-        yesText: 'Delete',
-        onConfirm: () => {
-          this.dashboard.meta.canSave = false;
-          this.deleteDashboardConfirmed();
-        }
-      });
-    }
-
-    deleteDashboardConfirmed() {
-      this.backendSrv.delete('/api/dashboards/db/' + this.dashboard.meta.slug).then(() => {
-        appEvents.emit('alert-success', ['Dashboard Deleted', this.dashboard.title + ' has been deleted']);
-        this.$location.url('/');
-      });
-    }
-
-    saveDashboardAs() {
-      return this.dashboardSrv.showSaveAsModal();
-    }
-
     showSearch() {
       this.$rootScope.appEvent('show-dash-search');
     }

+ 11 - 15
public/app/features/dashboard/history/history.html

@@ -8,18 +8,6 @@
   </span>
 </h3>
 
-<div class="page-action-bar" ng-show="ctrl.mode === 'list'">
-  <div class="page-action-bar__spacer"></div>
-  <button type="button"
-          class="btn btn-success"
-          ng-if="ctrl.revisions.length > 1"
-          ng-disabled="!ctrl.canCompare"
-          ng-click="ctrl.getDiff(ctrl.diff)"
-          bs-tooltip="ctrl.canCompare ? '' : 'Select 2 versions to start comparing'" data-placement="bottom">
-    <i class="fa fa-code-fork" ></i>&nbsp;&nbsp;Compare versions
-  </button>
-</div>
-
 <div ng-if="ctrl.mode === 'list'">
   <div ng-if="ctrl.loading">
     <i class="fa fa-spinner fa-spin"></i>
@@ -75,6 +63,14 @@
                    ng-disabled="ctrl.isLastPage()">
             Show more versions
           </button>
+          <button type="button"
+                  class="btn btn-success"
+                  ng-if="ctrl.revisions.length > 1"
+                  ng-disabled="!ctrl.canCompare"
+                  ng-click="ctrl.getDiff(ctrl.diff)"
+                  bs-tooltip="ctrl.canCompare ? '' : 'Select 2 versions to start comparing'" data-placement="bottom">
+            <i class="fa fa-code-fork" ></i>&nbsp;&nbsp;Compare versions
+          </button>
         </div>
       </div>
     </div>
@@ -89,9 +85,9 @@
 
   <div ng-if="!ctrl.loading">
     <button  type="button"
-        class="btn btn-danger pull-right"
-        ng-click="ctrl.restore(ctrl.baseInfo.version)"
-        ng-if="ctrl.isNewLatest">
+             class="btn btn-danger pull-right"
+             ng-click="ctrl.restore(ctrl.baseInfo.version)"
+             ng-if="ctrl.isNewLatest">
       <i class="fa fa-history" ></i>&nbsp;&nbsp;Restore to version {{ctrl.baseInfo.version}}
     </button>
     <section>

+ 0 - 95
public/app/features/dashboard/save_as_modal.ts

@@ -1,95 +0,0 @@
-///<reference path="../../headers/common.d.ts" />
-
-import coreModule from 'app/core/core_module';
-
-const  template = `
-<div class="modal-body">
-	<div class="modal-header">
-		<h2 class="modal-header-title">
-			<i class="fa fa-copy"></i>
-			<span class="p-l-1">Save As...</span>
-		</h2>
-
-		<a class="modal-header-close" ng-click="ctrl.dismiss();">
-			<i class="fa fa-remove"></i>
-		</a>
-	</div>
-
-	<form name="ctrl.saveForm" ng-submit="ctrl.save()" class="modal-content" novalidate>
-		<div class="p-t-2">
-			<div class="gf-form">
-				<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>
-			</div>
-      <div class="gf-form">
-        <folder-picker initial-folder-id="ctrl.folderId"
-                       on-change="ctrl.onFolderChange($folder)"
-                       label-class="width-7">
-        </folder-picker>
-      </div>
-		</div>
-
-		<div class="gf-form-button-row text-center">
-			<button type="submit" class="btn btn-success" ng-disabled="ctrl.saveForm.$invalid">Save</button>
-			<a class="btn-text" ng-click="ctrl.dismiss();">Cancel</a>
-		</div>
-	</form>
-</div>
-`;
-
-export class SaveDashboardAsModalCtrl {
-  clone: any;
-  folderId: any;
-  dismiss: () => void;
-
-  /** @ngInject */
-  constructor(private dashboardSrv) {
-    var dashboard = this.dashboardSrv.getCurrent();
-    this.clone = dashboard.getSaveModelClone();
-    this.clone.id = null;
-    this.clone.title += ' Copy';
-    this.clone.editable = true;
-    this.clone.hideControls = false;
-    this.folderId = dashboard.folderId;
-
-    // remove alerts if source dashboard is already persisted
-    // do not want to create alert dupes
-    if (dashboard.id > 0) {
-      this.clone.panels.forEach(panel => {
-        if (panel.type === "graph" && panel.alert) {
-          delete panel.thresholds;
-        }
-        delete panel.alert;
-      });
-    }
-
-    delete this.clone.autoUpdate;
-  }
-
-  save() {
-    return this.dashboardSrv.save(this.clone).then(this.dismiss);
-  }
-
-  keyDown(evt) {
-    if (evt.keyCode === 13) {
-      this.save();
-    }
-  }
-
-  onFolderChange(folder) {
-    this.clone.folderId = folder.id;
-  }
-}
-
-export function saveDashboardAsDirective() {
-  return {
-    restrict: 'E',
-    template: template,
-    controller: SaveDashboardAsModalCtrl,
-    bindToController: true,
-    controllerAs: 'ctrl',
-    scope: {dismiss: "&"}
-  };
-}
-
-coreModule.directive('saveDashboardAsModal',  saveDashboardAsDirective);

+ 26 - 0
public/app/features/dashboard/settings/settings.html

@@ -78,3 +78,29 @@
     <textarea class="gf-form-input" ng-model="ctrl.json" rows="30" spellcheck="false"></textarea>
   </div>
 </div>
+
+<div class="dashboard-settings__content" ng-if="ctrl.viewId === 'save_as'">
+  <save-dashboard-as></save-dashboard-as>
+</div>
+
+<div class="dashboard-settings__content" ng-if="ctrl.viewId === 'delete'">
+  <h3 class="dashboard-settings__header">Delete dashboard</h3>
+
+  <div ng-if="ctrl.dashboard.meta.canSave">
+    <div class="p-b-2" ng-if="ctrl.alertCount > 1">
+      <h5>This dashboard contains {{ctrl.alertCount}} alerts. Deleting this dashboard will also delete those alerts</h5>
+      <input type="text" class="gf-form-input width-16" style="display: inline-block;" placeholder="Type DELETE to confirm"
+            ng-model="ctrl.confirmText" ng-change="ctrl.confirmTextChanged()">
+    </div>
+
+    <button class="btn btn-danger" ng-click="ctrl.deleteDashboard()" ng-disabled="ctrl.confirmValid" >
+      <i class="fa fa-trash"></i>
+      Delete
+    </button>
+  </div>
+
+  <div ng-if="!ctrl.dashboard.meta.canSave">
+    <h5>You cannot delete this dashboard</h5>
+  </div>
+
+</div>

+ 29 - 2
public/app/features/dashboard/settings/settings.ts

@@ -1,4 +1,4 @@
-import {coreModule} from 'app/core/core';
+import {coreModule, appEvents} from 'app/core/core';
 import {DashboardModel} from '../dashboard_model';
 import $ from 'jquery';
 import _ from 'lodash';
@@ -8,6 +8,9 @@ export class SettingsCtrl {
   isOpen: boolean;
   viewId: string;
   json: string;
+  alertCount: number;
+  confirmValid: boolean;
+  confirmText: string;
 
   sections: any[] = [
     {title: 'General',     id: 'settings', icon: "fa fa-fw fa-sliders"},
@@ -21,7 +24,7 @@ export class SettingsCtrl {
   ];
 
   /** @ngInject */
-  constructor(private $scope, private $location, private $rootScope) {
+  constructor(private $scope, private $location, private $rootScope, private backendSrv, private dashboardSrv) {
     // temp hack for annotations and variables editors
     // that rely on inherited scope
     $scope.dashboard = this.dashboard;
@@ -39,6 +42,10 @@ export class SettingsCtrl {
       this.$rootScope.$broadcast("refresh");
     });
 
+    this.alertCount = _.sumBy(this.dashboard.panels, panel => {
+      return panel.alert ? 1 : 0;
+    });
+
     this.onRouteUpdated();
     $rootScope.onAppEvent("$routeUpdate", this.onRouteUpdated.bind(this), $scope);
   }
@@ -61,6 +68,26 @@ export class SettingsCtrl {
     });
   }
 
+  makeEditable() {
+    this.dashboard.editable = true;
+
+    return this.dashboardSrv.saveDashboard({makeEditable: true, overwrite: false}).then(() => {
+      // force refresh whole page
+      window.location.href = window.location.href;
+    });
+  }
+
+  confirmTextChanged() {
+    this.confirmValid = this.confirmText === "DELETE";
+  }
+
+  deleteDashboard() {
+    this.backendSrv.delete('/api/dashboards/db/' + this.dashboard.meta.slug).then(() => {
+      appEvents.emit('alert-success', ['Dashboard Deleted', this.dashboard.title + ' has been deleted']);
+      this.$location.url('/');
+    });
+  }
+
   onFolderChange(folder) {
     this.dashboard.folderId = folder.id;
     this.dashboard.meta.folderId = folder.id;

+ 2 - 2
public/app/features/dashboard/specs/save_as_modal.jest.ts → public/app/features/dashboard/specs/dashboard_save_as.jest.ts

@@ -1,4 +1,4 @@
-import { SaveDashboardAsModalCtrl } from '../save_as_modal';
+import { SaveDashboardAsCtrl } from '../dashboard_save_as';
 import { describe, it, expect } from 'test/lib/common';
 
 describe('saving dashboard as', () => {
@@ -21,7 +21,7 @@ describe('saving dashboard as', () => {
         },
       };
 
-      var ctrl = new SaveDashboardAsModalCtrl(mockDashboardSrv);
+      var ctrl = new SaveDashboardAsCtrl(mockDashboardSrv);
       var ctx: any = {
         clone: ctrl.clone,
         ctrl: ctrl,

+ 11 - 4
public/app/features/panel/panel_ctrl.ts

@@ -134,20 +134,27 @@ export class PanelCtrl {
   getMenu() {
     let menu = [];
     menu.push({text: 'View', click: 'ctrl.viewPanel();', icon: "fa fa-fw fa-eye", shortcut: "v"});
-    menu.push({text: 'Edit', click: 'ctrl.editPanel();', role: 'Editor', icon: "fa fa-fw fa-edit", shortcut: "e"});
+
+    if (this.dashboard.meta.canEdit) {
+      menu.push({text: 'Edit', click: 'ctrl.editPanel();', role: 'Editor', icon: "fa fa-fw fa-edit", shortcut: "e"});
+    }
+
     menu.push({text: 'Share', click: 'ctrl.sharePanel();', icon: "fa fa-fw fa-share", shortcut: "p s"});
 
     let extendedMenu = this.getExtendedMenu();
     menu.push({text: 'More ...', click: 'ctrl.removePanel();', icon: "fa fa-fw fa-cube", submenu: extendedMenu});
 
-    menu.push({divider: true, role: 'Editor'});
-    menu.push({text: 'Remove', click: 'ctrl.removePanel();', role: 'Editor', icon: "fa fa-fw fa-trash", shortcut: "p r"});
+    if (this.dashboard.meta.canEdit) {
+      menu.push({divider: true, role: 'Editor'});
+      menu.push({text: 'Remove', click: 'ctrl.removePanel();', role: 'Editor', icon: "fa fa-fw fa-trash", shortcut: "p r"});
+    }
+
     return menu;
   }
 
   getExtendedMenu() {
     let menu = [];
-    if (!this.fullscreen) {
+    if (!this.fullscreen && this.dashboard.meta.canEdit) {
       menu.push({ text: 'Duplicate', click: 'ctrl.duplicate()', role: 'Editor' });
     }
     menu.push({text: 'Panel JSON', click: 'ctrl.editPanelJson(); dismiss();' });