From 19cbff658bb53bc33ccfcaa84cc5d01fd7d76705 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 11 Sep 2018 17:36:23 +0200 Subject: [PATCH] wip: folder settings page to redux progress --- public/app/core/reducers/location.ts | 4 +- public/app/core/services/backend_srv.ts | 10 -- public/app/features/dashboard/all.ts | 2 - .../dashboard/folder_settings_ctrl.ts | 94 ----------- .../manage-dashboards/FolderSettingsPage.tsx | 152 +++++------------- .../manage-dashboards/state/actions.ts | 24 ++- .../manage-dashboards/state/reducers.ts | 7 +- public/app/stores/FolderStore/FolderStore.ts | 60 ------- public/app/types/dashboard.ts | 1 + public/app/types/index.ts | 1 + 10 files changed, 72 insertions(+), 283 deletions(-) delete mode 100644 public/app/features/dashboard/folder_settings_ctrl.ts delete mode 100644 public/app/stores/FolderStore/FolderStore.ts diff --git a/public/app/core/reducers/location.ts b/public/app/core/reducers/location.ts index 4591448d082..6a356c4ea5a 100644 --- a/public/app/core/reducers/location.ts +++ b/public/app/core/reducers/location.ts @@ -9,8 +9,8 @@ export const initialState: LocationState = { routeParams: {}, }; -function renderUrl(path: string, query: UrlQueryMap): string { - if (Object.keys(query).length > 0) { +function renderUrl(path: string, query: UrlQueryMap | undefined): string { + if (query && Object.keys(query).length > 0) { path += '?' + toUrlParams(query); } return path; diff --git a/public/app/core/services/backend_srv.ts b/public/app/core/services/backend_srv.ts index 2a50a1b1f12..3e8132a695b 100644 --- a/public/app/core/services/backend_srv.ts +++ b/public/app/core/services/backend_srv.ts @@ -252,16 +252,6 @@ export class BackendSrv { return this.post('/api/folders', payload); } - updateFolder(folder, options) { - options = options || {}; - - return this.put(`/api/folders/${folder.uid}`, { - title: folder.title, - version: folder.version, - overwrite: options.overwrite === true, - }); - } - deleteFolder(uid: string, showSuccessAlert) { return this.request({ method: 'DELETE', url: `/api/folders/${uid}`, showSuccessAlert: showSuccessAlert === true }); } diff --git a/public/app/features/dashboard/all.ts b/public/app/features/dashboard/all.ts index 1e28a3c9a80..adb665c47b5 100644 --- a/public/app/features/dashboard/all.ts +++ b/public/app/features/dashboard/all.ts @@ -32,11 +32,9 @@ import './dashlinks/module'; import coreModule from 'app/core/core_module'; import { FolderDashboardsCtrl } from './folder_dashboards_ctrl'; -import { FolderSettingsCtrl } from './folder_settings_ctrl'; import { DashboardImportCtrl } from './dashboard_import_ctrl'; import { CreateFolderCtrl } from './create_folder_ctrl'; coreModule.controller('FolderDashboardsCtrl', FolderDashboardsCtrl); -coreModule.controller('FolderSettingsCtrl', FolderSettingsCtrl); coreModule.controller('DashboardImportCtrl', DashboardImportCtrl); coreModule.controller('CreateFolderCtrl', CreateFolderCtrl); diff --git a/public/app/features/dashboard/folder_settings_ctrl.ts b/public/app/features/dashboard/folder_settings_ctrl.ts deleted file mode 100644 index a847c29ac56..00000000000 --- a/public/app/features/dashboard/folder_settings_ctrl.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { FolderPageLoader } from './folder_page_loader'; -import appEvents from 'app/core/app_events'; - -export class FolderSettingsCtrl { - folderPageLoader: FolderPageLoader; - navModel: any; - folderId: number; - uid: string; - canSave = false; - folder: any; - title: string; - hasChanged: boolean; - - /** @ngInject */ - constructor(private backendSrv, navModelSrv, private $routeParams, private $location) { - if (this.$routeParams.uid) { - this.uid = $routeParams.uid; - - this.folderPageLoader = new FolderPageLoader(this.backendSrv); - this.folderPageLoader.load(this, this.uid, 'manage-folder-settings').then(folder => { - if ($location.path() !== folder.meta.url) { - $location.path(`${folder.meta.url}/settings`).replace(); - } - - this.folder = folder; - this.canSave = this.folder.canSave; - this.title = this.folder.title; - }); - } - } - - save() { - this.titleChanged(); - - if (!this.hasChanged) { - return; - } - - this.folder.title = this.title.trim(); - - return this.backendSrv - .updateFolder(this.folder) - .then(result => { - if (result.url !== this.$location.path()) { - this.$location.url(result.url + '/settings'); - } - - appEvents.emit('dashboard-saved'); - appEvents.emit('alert-success', ['Folder saved']); - }) - .catch(this.handleSaveFolderError); - } - - titleChanged() { - this.hasChanged = this.folder.title.toLowerCase() !== this.title.trim().toLowerCase(); - } - - delete(evt) { - if (evt) { - evt.stopPropagation(); - evt.preventDefault(); - } - - appEvents.emit('confirm-modal', { - title: 'Delete', - text: `Do you want to delete this folder and all its dashboards?`, - icon: 'fa-trash', - yesText: 'Delete', - onConfirm: () => { - return this.backendSrv.deleteFolder(this.uid).then(() => { - appEvents.emit('alert-success', ['Folder Deleted', `${this.folder.title} has been deleted`]); - this.$location.url('dashboards'); - }); - }, - }); - } - - handleSaveFolderError(err) { - if (err.data && err.data.status === 'version-mismatch') { - err.isHandled = true; - - appEvents.emit('confirm-modal', { - title: 'Conflict', - text: 'Someone else has updated this folder.', - text2: 'Would you still like to save this folder?', - yesText: 'Save & Overwrite', - icon: 'fa-warning', - onConfirm: () => { - this.backendSrv.updateFolder(this.folder, { overwrite: true }); - }, - }); - } - } -} diff --git a/public/app/features/manage-dashboards/FolderSettingsPage.tsx b/public/app/features/manage-dashboards/FolderSettingsPage.tsx index 90528a8798d..a23e495fd3c 100644 --- a/public/app/features/manage-dashboards/FolderSettingsPage.tsx +++ b/public/app/features/manage-dashboards/FolderSettingsPage.tsx @@ -4,121 +4,53 @@ import { connect } from 'react-redux'; import PageHeader from 'app/core/components/PageHeader/PageHeader'; import appEvents from 'app/core/app_events'; import { getNavModel } from 'app/core/selectors/navModel'; -import { NavModel, StoreState } from 'app/types'; -import { getFolderByUid } from './state/actions'; +import { NavModel, StoreState, FolderState } from 'app/types'; +import { getFolderByUid, setFolderTitle, saveFolder, deleteFolder } from './state/actions'; export interface Props { navModel: NavModel; folderUid: string; + folder: FolderState; getFolderByUid: typeof getFolderByUid; + setFolderTitle: typeof setFolderTitle; + saveFolder: typeof saveFolder; + deleteFolder: typeof deleteFolder; } export class FolderSettingsPage extends PureComponent { - // formSnapshot: any; - // componentDidMount() { this.props.getFolderByUid(this.props.folderUid); } - // - // loadStore() { - // const { nav, folder, view } = this.props; - // - // return folder.load(view.routeParams.get('uid') as string).then(res => { - // this.formSnapshot = getSnapshot(folder); - // view.updatePathAndQuery(`${res.url}/settings`, {}, {}); - // - // return nav.initFolderNav(toJS(folder.folder), 'manage-folder-settings'); - // }); - // } - // onTitleChange(evt) { - // this.props.folder.setTitle(this.getFormSnapshot().folder.title, evt.target.value); - // } - // - // getFormSnapshot() { - // if (!this.formSnapshot) { - // this.formSnapshot = getSnapshot(this.props.folder); - // } - // - // return this.formSnapshot; - // } - // - // save(evt) { - // if (evt) { - // evt.stopPropagation(); - // evt.preventDefault(); - // } - // - // const { nav, folder, view } = this.props; - // - // folder - // .saveFolder({ overwrite: false }) - // .then(newUrl => { - // view.updatePathAndQuery(newUrl, {}, {}); - // - // appEvents.emit('dashboard-saved'); - // appEvents.emit('alert-success', ['Folder saved']); - // }) - // .then(() => { - // return nav.initFolderNav(toJS(folder.folder), 'manage-folder-settings'); - // }) - // .catch(this.handleSaveFolderError.bind(this)); - // } - // - // delete(evt) { - // if (evt) { - // evt.stopPropagation(); - // evt.preventDefault(); - // } - // - // const { folder, view } = this.props; - // const title = folder.folder.title; - // - // appEvents.emit('confirm-modal', { - // title: 'Delete', - // text: `Do you want to delete this folder and all its dashboards?`, - // icon: 'fa-trash', - // yesText: 'Delete', - // onConfirm: () => { - // return folder.deleteFolder().then(() => { - // appEvents.emit('alert-success', ['Folder Deleted', `${title} has been deleted`]); - // view.updatePathAndQuery('dashboards', '', ''); - // }); - // }, - // }); - // } - // - // handleSaveFolderError(err) { - // if (err.data && err.data.status === 'version-mismatch') { - // err.isHandled = true; - // - // const { nav, folder, view } = this.props; - // - // appEvents.emit('confirm-modal', { - // title: 'Conflict', - // text: 'Someone else has updated this folder.', - // text2: 'Would you still like to save this folder?', - // yesText: 'Save & Overwrite', - // icon: 'fa-warning', - // onConfirm: () => { - // folder - // .saveFolder({ overwrite: true }) - // .then(newUrl => { - // view.updatePathAndQuery(newUrl, {}, {}); - // - // appEvents.emit('dashboard-saved'); - // appEvents.emit('alert-success', ['Folder saved']); - // }) - // .then(() => { - // return nav.initFolderNav(toJS(folder.folder), 'manage-folder-settings'); - // }); - // }, - // }); - // } - // } + onTitleChange = evt => { + this.props.setFolderTitle(evt.target.value); + }; + + onSave = async evt => { + evt.preventDefault(); + evt.stopPropagation(); + + await this.props.saveFolder(this.props.folder); + appEvents.emit('alert-success', ['Folder saved']); + }; + + onDelete = evt => { + evt.stopPropagation(); + evt.preventDefault(); + + appEvents.emit('confirm-modal', { + title: 'Delete', + text: `Do you want to delete this folder and all its dashboards?`, + icon: 'fa-trash', + yesText: 'Delete', + onConfirm: () => { + this.props.deleteFolder(this.props.folder.uid); + }, + }); + }; render() { - const { navModel } = this.props; + const { navModel, folder } = this.props; return (
@@ -127,25 +59,21 @@ export class FolderSettingsPage extends PureComponent {

Folder Settings

-
+
- -
@@ -159,7 +87,6 @@ export class FolderSettingsPage extends PureComponent { const mapStateToProps = (state: StoreState) => { const uid = state.location.routeParams.uid; - return { navModel: getNavModel(state.navIndex, `folder-settings-${uid}`), folderUid: uid, @@ -169,6 +96,9 @@ const mapStateToProps = (state: StoreState) => { const mapDispatchToProps = { getFolderByUid, + saveFolder, + setFolderTitle, + deleteFolder, }; export default hot(module)(connect(mapStateToProps, mapDispatchToProps)(FolderSettingsPage)); diff --git a/public/app/features/manage-dashboards/state/actions.ts b/public/app/features/manage-dashboards/state/actions.ts index acd5571aa95..84fe97f22ab 100644 --- a/public/app/features/manage-dashboards/state/actions.ts +++ b/public/app/features/manage-dashboards/state/actions.ts @@ -1,8 +1,8 @@ import { getBackendSrv } from 'app/core/services/backend_srv'; import { StoreState } from 'app/types'; import { ThunkAction } from 'redux-thunk'; -import { FolderDTO, NavModelItem } from 'app/types'; -import { updateNavIndex, UpdateNavIndexAction } from 'app/core/actions'; +import { FolderDTO, FolderState, NavModelItem } from 'app/types'; +import { updateNavIndex, updateLocation } from 'app/core/actions'; export enum ActionTypes { LoadFolder = 'LOAD_FOLDER', @@ -32,7 +32,7 @@ export const setFolderTitle = (newTitle: string): SetFolderTitleAction => ({ export type Action = LoadFolderAction | SetFolderTitleAction; -type ThunkResult = ThunkAction; +type ThunkResult = ThunkAction; function buildNavModel(folder: FolderDTO): NavModelItem { return { @@ -67,6 +67,7 @@ function buildNavModel(folder: FolderDTO): NavModelItem { ], }; } + export function getFolderByUid(uid: string): ThunkResult { return async dispatch => { const folder = await getBackendSrv().getFolderByUid(uid); @@ -74,3 +75,20 @@ export function getFolderByUid(uid: string): ThunkResult { dispatch(updateNavIndex(buildNavModel(folder))); }; } + +export function saveFolder(folder: FolderState): ThunkResult { + return async dispatch => { + const res = await getBackendSrv().put(`/api/folders/${folder.uid}`, { + title: folder.title, + version: folder.version, + }); + dispatch(updateLocation({ path: `${res.url}/settings` })); + }; +} + +export function deleteFolder(uid: string): ThunkResult { + return async dispatch => { + await getBackendSrv().deleteFolder(uid, true); + dispatch(updateLocation({ path: `dashboards` })); + }; +} diff --git a/public/app/features/manage-dashboards/state/reducers.ts b/public/app/features/manage-dashboards/state/reducers.ts index 4844b465dfb..ada5b1812ad 100644 --- a/public/app/features/manage-dashboards/state/reducers.ts +++ b/public/app/features/manage-dashboards/state/reducers.ts @@ -16,9 +16,14 @@ export const folderReducer = (state = inititalState, action: Action): FolderStat case ActionTypes.LoadFolder: return { ...action.payload, - canSave: false, hasChanged: false, }; + case ActionTypes.SetFolderTitle: + return { + ...state, + title: action.payload, + hasChanged: true, + }; } return state; }; diff --git a/public/app/stores/FolderStore/FolderStore.ts b/public/app/stores/FolderStore/FolderStore.ts deleted file mode 100644 index 90932cbe46f..00000000000 --- a/public/app/stores/FolderStore/FolderStore.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { types, getEnv, flow } from 'mobx-state-tree'; - -export const Folder = types.model('Folder', { - id: types.identifier(types.number), - uid: types.string, - title: types.string, - url: types.string, - canSave: types.boolean, - hasChanged: types.boolean, - version: types.number, -}); - -export const FolderStore = types - .model('FolderStore', { - folder: types.maybe(Folder), - }) - .actions(self => ({ - load: flow(function* load(uid: string) { - // clear folder state - if (self.folder && self.folder.uid !== uid) { - self.folder = null; - } - - const backendSrv = getEnv(self).backendSrv; - const res = yield backendSrv.getFolderByUid(uid); - self.folder = Folder.create({ - id: res.id, - uid: res.uid, - title: res.title, - url: res.url, - canSave: res.canSave, - hasChanged: false, - version: res.version, - }); - - return res; - }), - - setTitle: (originalTitle: string, title: string) => { - self.folder.title = title; - self.folder.hasChanged = originalTitle.toLowerCase() !== title.trim().toLowerCase() && title.trim().length > 0; - }, - - saveFolder: flow(function* saveFolder(options: any) { - const backendSrv = getEnv(self).backendSrv; - self.folder.title = self.folder.title.trim(); - - const res = yield backendSrv.updateFolder(self.folder, options); - self.folder.url = res.url; - self.folder.version = res.version; - - return `${self.folder.url}/settings`; - }), - - deleteFolder: flow(function* deleteFolder() { - const backendSrv = getEnv(self).backendSrv; - - return backendSrv.deleteFolder(self.folder.uid); - }), - })); diff --git a/public/app/types/dashboard.ts b/public/app/types/dashboard.ts index 576432d413e..6fbe79cce8c 100644 --- a/public/app/types/dashboard.ts +++ b/public/app/types/dashboard.ts @@ -4,6 +4,7 @@ export interface FolderDTO { title: string; url: string; version: number; + canSave: boolean; } export interface FolderState { diff --git a/public/app/types/index.ts b/public/app/types/index.ts index 0ddb8f7cd0f..b1096c4827c 100644 --- a/public/app/types/index.ts +++ b/public/app/types/index.ts @@ -30,4 +30,5 @@ export interface StoreState { alertRules: AlertRulesState; teams: TeamsState; team: TeamState; + folder: FolderState; }