Commit 008b9bb3 by Torkel Ödegaard

ux: dashboard settings work progress

parent c4b759fe
......@@ -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';
......
///<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>
<h3 class="dashboard-settings__header">Save As</h3>
<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>
<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 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>
<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 SaveDashboardAsModalCtrl {
export class SaveDashboardAsCtrl {
clone: any;
folderId: any;
dismiss: () => void;
......@@ -85,11 +71,11 @@ export function saveDashboardAsDirective() {
return {
restrict: 'E',
template: template,
controller: SaveDashboardAsModalCtrl,
controller: SaveDashboardAsCtrl,
bindToController: true,
controllerAs: 'ctrl',
scope: {dismiss: "&"}
scope: {}
};
}
coreModule.directive('saveDashboardAsModal', saveDashboardAsDirective);
coreModule.directive('saveDashboardAs', saveDashboardAsDirective);
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');
}
......
......@@ -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>
......
......@@ -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>
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;
......
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,
......
......@@ -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();' });
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment