From 60d7e4308c03b3a7d825e000975231ed5fb311e6 Mon Sep 17 00:00:00 2001 From: Marcus Efraimsson Date: Tue, 19 Dec 2017 13:33:34 +0100 Subject: [PATCH 1/6] dashfolders: support creating new folder from the folder picker. #10197 --- public/app/core/services/backend_srv.ts | 2 +- public/app/features/dashboard/all.ts | 57 ++++--- .../folder_picker/folder_picker.html | 46 +++++ .../dashboard/folder_picker/folder_picker.ts | 161 ++++++++++++++++++ .../dashboard/folder_picker/picker.ts | 103 ----------- .../app/features/dashboard/validation_srv.ts | 48 ++++++ public/sass/components/_gf-form.scss | 4 + 7 files changed, 289 insertions(+), 132 deletions(-) create mode 100644 public/app/features/dashboard/folder_picker/folder_picker.html create mode 100644 public/app/features/dashboard/folder_picker/folder_picker.ts delete mode 100644 public/app/features/dashboard/folder_picker/picker.ts create mode 100644 public/app/features/dashboard/validation_srv.ts diff --git a/public/app/core/services/backend_srv.ts b/public/app/core/services/backend_srv.ts index 5b276a53e4f..bc34d9d37ab 100644 --- a/public/app/core/services/backend_srv.ts +++ b/public/app/core/services/backend_srv.ts @@ -251,7 +251,7 @@ export class BackendSrv { createDashboardFolder(name) { const dash = { schemaVersion: 16, - title: name, + title: name.trim(), editable: true, panels: [] }; diff --git a/public/app/features/dashboard/all.ts b/public/app/features/dashboard/all.ts index 7bf0a980205..14517bea7bb 100644 --- a/public/app/features/dashboard/all.ts +++ b/public/app/features/dashboard/all.ts @@ -1,31 +1,32 @@ -import "./dashboard_ctrl"; -import "./alerting_srv"; -import "./history/history"; -import "./dashboardLoaderSrv"; -import "./dashnav/dashnav"; -import "./submenu/submenu"; -import "./save_as_modal"; -import "./save_modal"; -import "./shareModalCtrl"; -import "./shareSnapshotCtrl"; -import "./dashboard_srv"; -import "./view_state_srv"; -import "./time_srv"; -import "./unsavedChangesSrv"; -import "./unsaved_changes_modal"; -import "./timepicker/timepicker"; -import "./upload"; -import "./export/export_modal"; -import "./export_data/export_data_modal"; -import "./ad_hoc_filters"; -import "./repeat_option/repeat_option"; -import "./dashgrid/DashboardGridDirective"; -import "./dashgrid/PanelLoader"; -import "./dashgrid/RowOptions"; -import "./acl/acl"; -import "./folder_picker/picker"; -import "./move_to_folder_modal/move_to_folder"; -import "./settings/settings"; +import './dashboard_ctrl'; +import './alerting_srv'; +import './history/history'; +import './dashboardLoaderSrv'; +import './dashnav/dashnav'; +import './submenu/submenu'; +import './save_as_modal'; +import './save_modal'; +import './shareModalCtrl'; +import './shareSnapshotCtrl'; +import './dashboard_srv'; +import './view_state_srv'; +import './validation_srv'; +import './time_srv'; +import './unsavedChangesSrv'; +import './unsaved_changes_modal'; +import './timepicker/timepicker'; +import './upload'; +import './export/export_modal'; +import './export_data/export_data_modal'; +import './ad_hoc_filters'; +import './repeat_option/repeat_option'; +import './dashgrid/DashboardGridDirective'; +import './dashgrid/PanelLoader'; +import './dashgrid/RowOptions'; +import './acl/acl'; +import './folder_picker/folder_picker'; +import './move_to_folder_modal/move_to_folder'; +import './settings/settings'; import coreModule from "app/core/core_module"; import { DashboardListCtrl } from "./dashboard_list_ctrl"; diff --git a/public/app/features/dashboard/folder_picker/folder_picker.html b/public/app/features/dashboard/folder_picker/folder_picker.html new file mode 100644 index 00000000000..b830e65b7e6 --- /dev/null +++ b/public/app/features/dashboard/folder_picker/folder_picker.html @@ -0,0 +1,46 @@ +
+
+ + + +
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+
\ No newline at end of file diff --git a/public/app/features/dashboard/folder_picker/folder_picker.ts b/public/app/features/dashboard/folder_picker/folder_picker.ts new file mode 100644 index 00000000000..72d1984634c --- /dev/null +++ b/public/app/features/dashboard/folder_picker/folder_picker.ts @@ -0,0 +1,161 @@ +/// + +import _ from 'lodash'; +import coreModule from 'app/core/core_module'; +import appEvents from 'app/core/app_events'; + +export class FolderPickerCtrl { + initialTitle: string; + initialFolderId?: number; + labelClass: string; + onChange: any; + onLoad: any; + onCreateFolder: any; + enterFolderCreation: any; + exitFolderCreation: any; + enableCreateNew: boolean; + rootName = 'Root'; + folder: any; + createNewFolder: boolean; + newFolderName: string; + newFolderNameTouched: boolean; + hasValidationError: boolean; + validationError: any; + + /** @ngInject */ + constructor(private backendSrv, private validationSrv) { + if (!this.labelClass) { + this.labelClass = "width-7"; + } + + this.loadInitialValue(); + } + + getOptions(query) { + var params = { + query: query, + type: 'dash-folder', + }; + + return this.backendSrv.search(params).then(result => { + if (query === '' || + query.toLowerCase() === "r" || + query.toLowerCase() === "ro" || + query.toLowerCase() === "roo" || + query.toLowerCase() === "root") { + result.unshift({title: this.rootName, id: 0}); + } + + if (this.enableCreateNew && query === '') { + result.unshift({title: '-- New Folder --', id: -1}); + } + + return _.map(result, item => { + return {text: item.title, value: item.id}; + }); + }); + } + + onFolderChange(option) { + if (option.value === -1) { + this.createNewFolder = true; + this.enterFolderCreation(); + return; + } + this.onChange({$folder: {id: option.value, title: option.text}}); + } + + newFolderNameChanged() { + this.newFolderNameTouched = true; + + this.validationSrv.validateNewDashboardOrFolderName(this.newFolderName) + .then(() => { + this.hasValidationError = false; + }) + .catch(err => { + this.hasValidationError = true; + this.validationError = err.message; + }); + } + + createFolder(evt) { + if (evt) { + evt.stopPropagation(); + evt.preventDefault(); + } + + return this.backendSrv.createDashboardFolder(this.newFolderName).then(result => { + appEvents.emit('alert-success', ['Folder Created', 'OK']); + + this.closeCreateFolder(); + this.folder = {text: result.dashboard.title, value: result.dashboard.id}; + this.onFolderChange(this.folder); + }); + } + + cancelCreateFolder(evt) { + if (evt) { + evt.stopPropagation(); + evt.preventDefault(); + } + + this.closeCreateFolder(); + this.loadInitialValue(); + } + + private closeCreateFolder() { + this.exitFolderCreation(); + this.createNewFolder = false; + this.hasValidationError = false; + this.validationError = null; + this.newFolderName = ''; + this.newFolderNameTouched = false; + } + + private loadInitialValue() { + if (this.initialFolderId && this.initialFolderId > 0) { + this.getOptions('').then(result => { + this.folder = _.find(result, {value: this.initialFolderId}); + this.onFolderLoad(); + }); + } else { + if (this.initialTitle) { + this.folder = {text: this.initialTitle, value: null}; + } else { + this.folder = {text: this.rootName, value: 0}; + } + + this.onFolderLoad(); + } + } + + private onFolderLoad() { + if (this.onLoad) { + this.onLoad({$folder: {id: this.folder.value, title: this.folder.text}}); + } + } +} + +export function folderPicker() { + return { + restrict: 'E', + templateUrl: 'public/app/features/dashboard/folder_picker/folder_picker.html', + controller: FolderPickerCtrl, + bindToController: true, + controllerAs: 'ctrl', + scope: { + initialTitle: '<', + initialFolderId: '<', + labelClass: '@', + rootName: '@', + onChange: '&', + onLoad: '&', + onCreateFolder: '&', + enterFolderCreation: '&', + exitFolderCreation: '&', + enableCreateNew: '@' + } + }; +} + +coreModule.directive('folderPicker', folderPicker); diff --git a/public/app/features/dashboard/folder_picker/picker.ts b/public/app/features/dashboard/folder_picker/picker.ts deleted file mode 100644 index f04065b36f5..00000000000 --- a/public/app/features/dashboard/folder_picker/picker.ts +++ /dev/null @@ -1,103 +0,0 @@ -/// - -import coreModule from "app/core/core_module"; -import _ from "lodash"; - -export class FolderPickerCtrl { - initialTitle: string; - initialFolderId?: number; - labelClass: string; - onChange: any; - onLoad: any; - rootName = "Root"; - folder: any; - - /** @ngInject */ - constructor(private backendSrv) { - if (!this.labelClass) { - this.labelClass = "width-7"; - } - - if (this.initialFolderId && this.initialFolderId > 0) { - this.getOptions("").then(result => { - this.folder = _.find(result, { value: this.initialFolderId }); - this.onFolderLoad(); - }); - } else { - if (this.initialTitle) { - this.folder = { text: this.initialTitle, value: null }; - } else { - this.folder = { text: this.rootName, value: 0 }; - } - - this.onFolderLoad(); - } - } - - getOptions(query) { - var params = { - query: query, - type: "dash-folder" - }; - - return this.backendSrv.search(params).then(result => { - if ( - query === "" || - query.toLowerCase() === "r" || - query.toLowerCase() === "ro" || - query.toLowerCase() === "roo" || - query.toLowerCase() === "root" - ) { - result.unshift({ title: this.rootName, id: 0 }); - } - - return _.map(result, item => { - return { text: item.title, value: item.id }; - }); - }); - } - - onFolderLoad() { - if (this.onLoad) { - this.onLoad({ - $folder: { id: this.folder.value, title: this.folder.text } - }); - } - } - - onFolderChange(option) { - this.onChange({ $folder: { id: option.value, title: option.text } }); - } -} - -const template = ` -
- - -
-`; - -export function folderPicker() { - return { - restrict: "E", - template: template, - controller: FolderPickerCtrl, - bindToController: true, - controllerAs: "ctrl", - scope: { - initialTitle: "<", - initialFolderId: "<", - labelClass: "@", - rootName: "@", - onChange: "&", - onLoad: "&" - } - }; -} - -coreModule.directive("folderPicker", folderPicker); diff --git a/public/app/features/dashboard/validation_srv.ts b/public/app/features/dashboard/validation_srv.ts new file mode 100644 index 00000000000..4e02b8a678f --- /dev/null +++ b/public/app/features/dashboard/validation_srv.ts @@ -0,0 +1,48 @@ +/// + +import coreModule from 'app/core/core_module'; + +export class ValidationSrv { + rootName = 'root'; + + /** @ngInject */ + constructor(private $q, private backendSrv) {} + + validateNewDashboardOrFolderName(name) { + name = (name || '').trim(); + + if (name.length === 0) { + return this.$q.reject({ + type: 'REQUIRED', + message: 'Name is required' + }); + } + + if (name.toLowerCase() === this.rootName) { + return this.$q.reject({ + type: 'EXISTING', + message: 'A folder or dashboard with the same name already exists' + }); + } + + let deferred = this.$q.defer(); + + this.backendSrv.search({ query: name }).then(res => { + for (let hit of res) { + if (name.toLowerCase() === hit.title.toLowerCase()) { + deferred.reject({ + type: 'EXISTING', + message: 'A folder or dashboard with the same name already exists' + }); + break; + } + } + + deferred.resolve(); + }); + + return deferred.promise; + } +} + +coreModule.service('validationSrv', ValidationSrv); diff --git a/public/sass/components/_gf-form.scss b/public/sass/components/_gf-form.scss index 3a61246c494..10a900f82f9 100644 --- a/public/sass/components/_gf-form.scss +++ b/public/sass/components/_gf-form.scss @@ -109,6 +109,10 @@ $input-border: 1px solid $input-border-color; &--error { color: $critical; } + + &:disabled { + color: $text-color-weak + } } .gf-form-label + .gf-form-label { From 7f9c0df4642f671dc6540a3d683c3512e996365f Mon Sep 17 00:00:00 2001 From: Marcus Efraimsson Date: Tue, 19 Dec 2017 13:36:02 +0100 Subject: [PATCH 2/6] dashfolders: support creating new folder in dashboard settings. #10197 --- public/app/features/dashboard/settings/settings.html | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/public/app/features/dashboard/settings/settings.html b/public/app/features/dashboard/settings/settings.html index 03d8b8592a9..0411850c543 100644 --- a/public/app/features/dashboard/settings/settings.html +++ b/public/app/features/dashboard/settings/settings.html @@ -45,9 +45,11 @@ + initial-folder-id="ctrl.dashboard.meta.folderId" + on-change="ctrl.onFolderChange($folder)" + enable-create-new="true" + is-valid-selection="true" + label-class="width-7"> From 2d0f5f06e4fd646458ac213001fedd5e9e6ad497 Mon Sep 17 00:00:00 2001 From: Marcus Efraimsson Date: Tue, 19 Dec 2017 13:36:52 +0100 Subject: [PATCH 3/6] dashfolders: support creating new folder when saving a dashboard. #10197 --- public/app/features/dashboard/save_as_modal.ts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/public/app/features/dashboard/save_as_modal.ts b/public/app/features/dashboard/save_as_modal.ts index a749b085b8b..ee9ef9cbc3c 100644 --- a/public/app/features/dashboard/save_as_modal.ts +++ b/public/app/features/dashboard/save_as_modal.ts @@ -22,13 +22,16 @@ const template = `
- + Cancel
@@ -38,6 +41,7 @@ const template = ` export class SaveDashboardAsModalCtrl { clone: any; folderId: any; + isValidFolderSelection = true; dismiss: () => void; /** @ngInject */ @@ -68,8 +72,16 @@ export class SaveDashboardAsModalCtrl { return this.dashboardSrv.save(this.clone).then(this.dismiss); } + onEnterFolderCreation() { + this.isValidFolderSelection = false; + } + + onExitFolderCreation() { + this.isValidFolderSelection = true; + } + keyDown(evt) { - if (evt.keyCode === 13) { + if (this.isValidFolderSelection && evt.keyCode === 13) { this.save(); } } From 4846125ec07d8ee73dcb0809d538205c1f3a867c Mon Sep 17 00:00:00 2001 From: Marcus Efraimsson Date: Tue, 19 Dec 2017 13:37:27 +0100 Subject: [PATCH 4/6] dashfolders: support creating new folder when moving dashboards. #10197 --- .../dashboard/move_to_folder_modal/move_to_folder.html | 5 ++++- .../dashboard/move_to_folder_modal/move_to_folder.ts | 9 +++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/public/app/features/dashboard/move_to_folder_modal/move_to_folder.html b/public/app/features/dashboard/move_to_folder_modal/move_to_folder.html index 8f04d393a5d..8a67517aa92 100644 --- a/public/app/features/dashboard/move_to_folder_modal/move_to_folder.html +++ b/public/app/features/dashboard/move_to_folder_modal/move_to_folder.html @@ -18,12 +18,15 @@
- + Cancel
diff --git a/public/app/features/dashboard/move_to_folder_modal/move_to_folder.ts b/public/app/features/dashboard/move_to_folder_modal/move_to_folder.ts index 9f252783cf7..84fc16833a1 100644 --- a/public/app/features/dashboard/move_to_folder_modal/move_to_folder.ts +++ b/public/app/features/dashboard/move_to_folder_modal/move_to_folder.ts @@ -6,6 +6,7 @@ export class MoveToFolderCtrl { folder: any; dismiss: any; afterSave: any; + isValidFolderSelection = true; /** @ngInject */ constructor(private backendSrv) {} @@ -39,6 +40,14 @@ export class MoveToFolderCtrl { return this.afterSave(); }); } + + onEnterFolderCreation() { + this.isValidFolderSelection = false; + } + + onExitFolderCreation() { + this.isValidFolderSelection = true; + } } export function moveToFolderModal() { From 0bfedfe4d6109c09b7071423948aac3f148a0023 Mon Sep 17 00:00:00 2001 From: Marcus Efraimsson Date: Tue, 19 Dec 2017 13:39:10 +0100 Subject: [PATCH 5/6] dashfolders: use validation service for folder creation and dashboard import. #10197 --- public/app/core/routes/routes.ts | 2 +- .../features/dashboard/create_folder_ctrl.ts | 32 +++++++++--------- .../dashboard/dashboard_import_ctrl.ts | 33 ++++++++++--------- .../dashboard/partials/create_folder.html | 21 ++++-------- ...boardImport.html => dashboard_import.html} | 15 ++------- .../specs/dashboard_import_ctrl.jest.ts | 7 +++- 6 files changed, 49 insertions(+), 61 deletions(-) rename public/app/features/dashboard/partials/{dashboardImport.html => dashboard_import.html} (89%) diff --git a/public/app/core/routes/routes.ts b/public/app/core/routes/routes.ts index f2e4fa1ec88..666ca811037 100644 --- a/public/app/core/routes/routes.ts +++ b/public/app/core/routes/routes.ts @@ -65,7 +65,7 @@ function setupAngularRoutes($routeProvider, $locationProvider) { }) .when("/dashboard/import", { templateUrl: - "public/app/features/dashboard/partials/dashboardImport.html", + "public/app/features/dashboard/partials/dashboard_import.html", controller: "DashboardImportCtrl", controllerAs: "ctrl" }) diff --git a/public/app/features/dashboard/create_folder_ctrl.ts b/public/app/features/dashboard/create_folder_ctrl.ts index c4a8429f45e..d9eaf95d693 100644 --- a/public/app/features/dashboard/create_folder_ctrl.ts +++ b/public/app/features/dashboard/create_folder_ctrl.ts @@ -3,23 +3,22 @@ import appEvents from "app/core/app_events"; export class CreateFolderCtrl { title = ""; navModel: any; - nameExists = false; titleTouched = false; + hasValidationError: boolean; + validationError: any; /** @ngInject **/ - constructor(private backendSrv, private $location, navModelSrv) { - this.navModel = navModelSrv.getNav("dashboards", "manage-dashboards", 0); + constructor(private backendSrv, private $location, private validationSrv, navModelSrv) { + this.navModel = navModelSrv.getNav('dashboards', 'manage-dashboards', 0); } create() { - if (!this.title || this.title.trim().length === 0) { + if (this.hasValidationError) { return; } - const title = this.title.trim(); - - return this.backendSrv.createDashboardFolder(title).then(result => { - appEvents.emit("alert-success", ["Folder Created", "OK"]); + return this.backendSrv.createDashboardFolder(this.title).then(result => { + appEvents.emit('alert-success', ['Folder Created', 'OK']); var folderUrl = `/dashboards/folder/${result.dashboard.id}/${ result.meta.slug @@ -31,14 +30,13 @@ export class CreateFolderCtrl { titleChanged() { this.titleTouched = true; - this.backendSrv.search({ query: this.title }).then(res => { - this.nameExists = false; - for (let hit of res) { - if (this.title === hit.title) { - this.nameExists = true; - break; - } - } - }); + this.validationSrv.validateNewDashboardOrFolderName(this.title) + .then(() => { + this.hasValidationError = false; + }) + .catch(err => { + this.hasValidationError = true; + this.validationError = err.message; + }); } } diff --git a/public/app/features/dashboard/dashboard_import_ctrl.ts b/public/app/features/dashboard/dashboard_import_ctrl.ts index 51b2d696dac..2dc33fe07f7 100644 --- a/public/app/features/dashboard/dashboard_import_ctrl.ts +++ b/public/app/features/dashboard/dashboard_import_ctrl.ts @@ -13,16 +13,13 @@ export class DashboardImportCtrl { gnetUrl: string; gnetError: string; gnetInfo: any; + titleTouched: boolean; + hasNameValidationError: boolean; + nameValidationError: any; /** @ngInject */ - constructor( - private backendSrv, - navModelSrv, - private $location, - private $scope, - $routeParams - ) { - this.navModel = navModelSrv.getNav("create", "import"); + constructor(private backendSrv, private validationSrv, navModelSrv, private $location, private $scope, $routeParams) { + this.navModel = navModelSrv.getNav('create', 'import'); this.step = 1; this.nameExists = false; @@ -93,15 +90,21 @@ export class DashboardImportCtrl { } titleChanged() { - this.backendSrv.search({ query: this.dash.title }).then(res => { - this.nameExists = false; - for (let hit of res) { - if (this.dash.title === hit.title) { + this.titleTouched = true; + this.nameExists = false; + + this.validationSrv.validateNewDashboardOrFolderName(this.dash.title) + .then(() => { + this.hasNameValidationError = false; + }) + .catch(err => { + if (err.type === 'EXISTING') { this.nameExists = true; - break; } - } - }); + + this.hasNameValidationError = true; + this.nameValidationError = err.message; + }); } saveDashboard() { diff --git a/public/app/features/dashboard/partials/create_folder.html b/public/app/features/dashboard/partials/create_folder.html index 22dbaab1419..21b6dfc1661 100644 --- a/public/app/features/dashboard/partials/create_folder.html +++ b/public/app/features/dashboard/partials/create_folder.html @@ -7,34 +7,25 @@
- - -
-
+
-
-
- -
-
-
-
diff --git a/public/app/features/dashboard/partials/dashboardImport.html b/public/app/features/dashboard/partials/dashboard_import.html similarity index 89% rename from public/app/features/dashboard/partials/dashboardImport.html rename to public/app/features/dashboard/partials/dashboard_import.html index b740b8f38bc..020bb98e8b0 100644 --- a/public/app/features/dashboard/partials/dashboardImport.html +++ b/public/app/features/dashboard/partials/dashboard_import.html @@ -65,26 +65,17 @@
-
-
+
-
-
- -
-
-
diff --git a/public/app/features/dashboard/specs/dashboard_import_ctrl.jest.ts b/public/app/features/dashboard/specs/dashboard_import_ctrl.jest.ts index a8590f5cbd3..0abef382de8 100644 --- a/public/app/features/dashboard/specs/dashboard_import_ctrl.jest.ts +++ b/public/app/features/dashboard/specs/dashboard_import_ctrl.jest.ts @@ -6,6 +6,7 @@ describe("DashboardImportCtrl", function() { let navModelSrv; let backendSrv; + let validationSrv; beforeEach(() => { navModelSrv = { @@ -17,7 +18,11 @@ describe("DashboardImportCtrl", function() { get: jest.fn() }; - ctx.ctrl = new DashboardImportCtrl(backendSrv, navModelSrv, {}, {}, {}); + validationSrv = { + validateNewDashboardOrFolderName: jest.fn().mockReturnValue(Promise.resolve()) + }; + + ctx.ctrl = new DashboardImportCtrl(backendSrv, validationSrv, navModelSrv, {}, {}, {}); }); describe("when uploading json", function() { From 1ddcaf5b6f7b0a3fe89c7e390bda2008b867d5a4 Mon Sep 17 00:00:00 2001 From: Marcus Efraimsson Date: Tue, 19 Dec 2017 17:53:07 +0100 Subject: [PATCH 6/6] minor fixes and formatting after review --- .../folder_picker/folder_picker.html | 2 +- .../dashboard/folder_picker/folder_picker.ts | 97 ++++++++++--------- .../app/features/dashboard/validation_srv.ts | 22 ++--- 3 files changed, 64 insertions(+), 57 deletions(-) diff --git a/public/app/features/dashboard/folder_picker/folder_picker.html b/public/app/features/dashboard/folder_picker/folder_picker.html index b830e65b7e6..8722a19a5f8 100644 --- a/public/app/features/dashboard/folder_picker/folder_picker.html +++ b/public/app/features/dashboard/folder_picker/folder_picker.html @@ -43,4 +43,4 @@ {{ctrl.validationError}}
- \ No newline at end of file + diff --git a/public/app/features/dashboard/folder_picker/folder_picker.ts b/public/app/features/dashboard/folder_picker/folder_picker.ts index 72d1984634c..150f29a0dac 100644 --- a/public/app/features/dashboard/folder_picker/folder_picker.ts +++ b/public/app/features/dashboard/folder_picker/folder_picker.ts @@ -1,8 +1,6 @@ -/// - -import _ from 'lodash'; -import coreModule from 'app/core/core_module'; -import appEvents from 'app/core/app_events'; +import _ from "lodash"; +import coreModule from "app/core/core_module"; +import appEvents from "app/core/app_events"; export class FolderPickerCtrl { initialTitle: string; @@ -14,7 +12,7 @@ export class FolderPickerCtrl { enterFolderCreation: any; exitFolderCreation: any; enableCreateNew: boolean; - rootName = 'Root'; + rootName = "Root"; folder: any; createNewFolder: boolean; newFolderName: string; @@ -34,24 +32,26 @@ export class FolderPickerCtrl { getOptions(query) { var params = { query: query, - type: 'dash-folder', + type: "dash-folder" }; return this.backendSrv.search(params).then(result => { - if (query === '' || - query.toLowerCase() === "r" || - query.toLowerCase() === "ro" || - query.toLowerCase() === "roo" || - query.toLowerCase() === "root") { - result.unshift({title: this.rootName, id: 0}); + if ( + query === "" || + query.toLowerCase() === "r" || + query.toLowerCase() === "ro" || + query.toLowerCase() === "roo" || + query.toLowerCase() === "root" + ) { + result.unshift({ title: this.rootName, id: 0 }); } - if (this.enableCreateNew && query === '') { - result.unshift({title: '-- New Folder --', id: -1}); + if (this.enableCreateNew && query === "") { + result.unshift({ title: "-- New Folder --", id: -1 }); } return _.map(result, item => { - return {text: item.title, value: item.id}; + return { text: item.title, value: item.id }; }); }); } @@ -62,13 +62,14 @@ export class FolderPickerCtrl { this.enterFolderCreation(); return; } - this.onChange({$folder: {id: option.value, title: option.text}}); + this.onChange({ $folder: { id: option.value, title: option.text } }); } newFolderNameChanged() { this.newFolderNameTouched = true; - this.validationSrv.validateNewDashboardOrFolderName(this.newFolderName) + this.validationSrv + .validateNewDashboardOrFolderName(this.newFolderName) .then(() => { this.hasValidationError = false; }) @@ -84,13 +85,18 @@ export class FolderPickerCtrl { evt.preventDefault(); } - return this.backendSrv.createDashboardFolder(this.newFolderName).then(result => { - appEvents.emit('alert-success', ['Folder Created', 'OK']); + return this.backendSrv + .createDashboardFolder(this.newFolderName) + .then(result => { + appEvents.emit("alert-success", ["Folder Created", "OK"]); - this.closeCreateFolder(); - this.folder = {text: result.dashboard.title, value: result.dashboard.id}; - this.onFolderChange(this.folder); - }); + this.closeCreateFolder(); + this.folder = { + text: result.dashboard.title, + value: result.dashboard.id + }; + this.onFolderChange(this.folder); + }); } cancelCreateFolder(evt) { @@ -108,21 +114,21 @@ export class FolderPickerCtrl { this.createNewFolder = false; this.hasValidationError = false; this.validationError = null; - this.newFolderName = ''; + this.newFolderName = ""; this.newFolderNameTouched = false; } private loadInitialValue() { if (this.initialFolderId && this.initialFolderId > 0) { - this.getOptions('').then(result => { - this.folder = _.find(result, {value: this.initialFolderId}); + this.getOptions("").then(result => { + this.folder = _.find(result, { value: this.initialFolderId }); this.onFolderLoad(); }); } else { if (this.initialTitle) { - this.folder = {text: this.initialTitle, value: null}; + this.folder = { text: this.initialTitle, value: null }; } else { - this.folder = {text: this.rootName, value: 0}; + this.folder = { text: this.rootName, value: 0 }; } this.onFolderLoad(); @@ -131,31 +137,34 @@ export class FolderPickerCtrl { private onFolderLoad() { if (this.onLoad) { - this.onLoad({$folder: {id: this.folder.value, title: this.folder.text}}); + this.onLoad({ + $folder: { id: this.folder.value, title: this.folder.text } + }); } } } export function folderPicker() { return { - restrict: 'E', - templateUrl: 'public/app/features/dashboard/folder_picker/folder_picker.html', + restrict: "E", + templateUrl: + "public/app/features/dashboard/folder_picker/folder_picker.html", controller: FolderPickerCtrl, bindToController: true, - controllerAs: 'ctrl', + controllerAs: "ctrl", scope: { - initialTitle: '<', - initialFolderId: '<', - labelClass: '@', - rootName: '@', - onChange: '&', - onLoad: '&', - onCreateFolder: '&', - enterFolderCreation: '&', - exitFolderCreation: '&', - enableCreateNew: '@' + initialTitle: "<", + initialFolderId: "<", + labelClass: "@", + rootName: "@", + onChange: "&", + onLoad: "&", + onCreateFolder: "&", + enterFolderCreation: "&", + exitFolderCreation: "&", + enableCreateNew: "@" } }; } -coreModule.directive('folderPicker', folderPicker); +coreModule.directive("folderPicker", folderPicker); diff --git a/public/app/features/dashboard/validation_srv.ts b/public/app/features/dashboard/validation_srv.ts index 4e02b8a678f..4200cf1b6ba 100644 --- a/public/app/features/dashboard/validation_srv.ts +++ b/public/app/features/dashboard/validation_srv.ts @@ -1,27 +1,25 @@ -/// - -import coreModule from 'app/core/core_module'; +import coreModule from "app/core/core_module"; export class ValidationSrv { - rootName = 'root'; + rootName = "root"; /** @ngInject */ constructor(private $q, private backendSrv) {} validateNewDashboardOrFolderName(name) { - name = (name || '').trim(); + name = (name || "").trim(); if (name.length === 0) { return this.$q.reject({ - type: 'REQUIRED', - message: 'Name is required' + type: "REQUIRED", + message: "Name is required" }); } if (name.toLowerCase() === this.rootName) { return this.$q.reject({ - type: 'EXISTING', - message: 'A folder or dashboard with the same name already exists' + type: "EXISTING", + message: "A folder or dashboard with the same name already exists" }); } @@ -31,8 +29,8 @@ export class ValidationSrv { for (let hit of res) { if (name.toLowerCase() === hit.title.toLowerCase()) { deferred.reject({ - type: 'EXISTING', - message: 'A folder or dashboard with the same name already exists' + type: "EXISTING", + message: "A folder or dashboard with the same name already exists" }); break; } @@ -45,4 +43,4 @@ export class ValidationSrv { } } -coreModule.service('validationSrv', ValidationSrv); +coreModule.service("validationSrv", ValidationSrv);