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

folders: use new folder api in frontend

Marcus Efraimsson 8 лет назад
Родитель
Сommit
d217688d5e

+ 1 - 1
public/app/containers/ManageDashboards/FolderPermissions.tsx

@@ -20,7 +20,7 @@ export class FolderPermissions extends Component<IContainerProps, any> {
   loadStore() {
     const { nav, folder, view } = this.props;
     return folder.load(view.routeParams.get('uid') as string).then(res => {
-      view.updatePathAndQuery(`${res.meta.url}/permissions`, {}, {});
+      view.updatePathAndQuery(`${res.url}/permissions`, {}, {});
       return nav.initFolderNav(toJS(folder.folder), 'manage-folder-permissions');
     });
   }

+ 7 - 9
public/app/containers/ManageDashboards/FolderSettings.jest.tsx

@@ -9,16 +9,14 @@ describe('FolderSettings', () => {
   let page;
 
   beforeAll(() => {
-    backendSrv.getDashboardByUid.mockReturnValue(
+    backendSrv.getFolderByUid.mockReturnValue(
       Promise.resolve({
-        dashboard: {
-          id: 1,
-          title: 'Folder Name',
-        },
-        meta: {
-          url: '/dashboards/f/uid/folder-name',
-          canSave: true,
-        },
+        id: 1,
+        uid: 'uid',
+        title: 'Folder Name',
+        url: '/dashboards/f/uid/folder-name',
+        canSave: true,
+        version: 1,
       })
     );
 

+ 17 - 14
public/app/containers/ManageDashboards/FolderSettings.tsx

@@ -10,7 +10,6 @@ import appEvents from 'app/core/app_events';
 @observer
 export class FolderSettings extends React.Component<IContainerProps, any> {
   formSnapshot: any;
-  dashboard: any;
 
   constructor(props) {
     super(props);
@@ -22,9 +21,7 @@ export class FolderSettings extends React.Component<IContainerProps, any> {
 
     return folder.load(view.routeParams.get('uid') as string).then(res => {
       this.formSnapshot = getSnapshot(folder);
-      this.dashboard = res.dashboard;
-
-      view.updatePathAndQuery(`${res.meta.url}/settings`, {}, {});
+      view.updatePathAndQuery(`${res.url}/settings`, {}, {});
 
       return nav.initFolderNav(toJS(folder.folder), 'manage-folder-settings');
     });
@@ -51,7 +48,7 @@ export class FolderSettings extends React.Component<IContainerProps, any> {
     const { nav, folder, view } = this.props;
 
     folder
-      .saveFolder(this.dashboard, { overwrite: false })
+      .saveFolder({ overwrite: false })
       .then(newUrl => {
         view.updatePathAndQuery(newUrl, {}, {});
 
@@ -61,7 +58,7 @@ export class FolderSettings extends React.Component<IContainerProps, any> {
       .then(() => {
         return nav.initFolderNav(toJS(folder.folder), 'manage-folder-settings');
       })
-      .catch(this.handleSaveFolderError);
+      .catch(this.handleSaveFolderError.bind(this));
   }
 
   delete(evt) {
@@ -79,7 +76,7 @@ export class FolderSettings extends React.Component<IContainerProps, any> {
       icon: 'fa-trash',
       yesText: 'Delete',
       onConfirm: () => {
-        return this.props.folder.deleteFolder().then(() => {
+        return folder.deleteFolder().then(() => {
           appEvents.emit('alert-success', ['Folder Deleted', `${title} has been deleted`]);
           view.updatePathAndQuery('dashboards', '', '');
         });
@@ -91,6 +88,8 @@ export class FolderSettings extends React.Component<IContainerProps, any> {
     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.',
@@ -98,16 +97,20 @@ export class FolderSettings extends React.Component<IContainerProps, any> {
         yesText: 'Save & Overwrite',
         icon: 'fa-warning',
         onConfirm: () => {
-          this.props.folder.saveFolder(this.dashboard, { overwrite: true });
+          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');
+            });
         },
       });
     }
-
-    if (err.data && err.data.status === 'name-exists') {
-      err.isHandled = true;
-
-      appEvents.emit('alert-error', ['A folder or dashboard with this name exists already.']);
-    }
   }
 
   render() {

+ 6 - 7
public/app/core/components/manage_dashboards/manage_dashboards.ts

@@ -173,17 +173,16 @@ export class ManageDashboardsCtrl {
       icon: 'fa-trash',
       yesText: 'Delete',
       onConfirm: () => {
-        const foldersAndDashboards = data.folders.concat(data.dashboards);
-        this.deleteFoldersAndDashboards(foldersAndDashboards);
+        this.deleteFoldersAndDashboards(data.folders, data.dashboards);
       },
     });
   }
 
-  private deleteFoldersAndDashboards(uids) {
-    this.backendSrv.deleteDashboards(uids).then(result => {
-      const folders = _.filter(result, dash => dash.meta.isFolder);
+  private deleteFoldersAndDashboards(folderUids, dashboardUids) {
+    this.backendSrv.deleteFoldersAndDashboards(folderUids, dashboardUids).then(result => {
+      const folders = _.filter(result, dash => !dash.dashboard);
       const folderCount = folders.length;
-      const dashboards = _.filter(result, dash => !dash.meta.isFolder);
+      const dashboards = _.filter(result, dash => dash.dashboard);
       const dashCount = dashboards.length;
 
       if (result.length > 0) {
@@ -198,7 +197,7 @@ export class ManageDashboardsCtrl {
           header = `Folder${folderCount === 1 ? '' : 's'} Deleted`;
 
           if (folderCount === 1) {
-            msg = `${folders[0].dashboard.title} has been deleted`;
+            msg = `${folders[0].title} has been deleted`;
           } else {
             msg = `${folderCount} folder${folderCount === 1 ? '' : 's'} has been deleted`;
           }

+ 33 - 23
public/app/core/services/backend_srv.ts

@@ -229,6 +229,10 @@ export class BackendSrv {
     return this.get(`/api/dashboards/uid/${uid}`);
   }
 
+  getFolderByUid(uid: string) {
+    return this.get(`/api/folders/${uid}`);
+  }
+
   saveDashboard(dash, options) {
     options = options || {};
 
@@ -240,34 +244,36 @@ export class BackendSrv {
     });
   }
 
-  createDashboardFolder(name) {
-    const dash = {
-      schemaVersion: 16,
-      title: name.trim(),
-      editable: true,
-      panels: [],
-    };
-
-    return this.post('/api/dashboards/db/', {
-      dashboard: dash,
-      isFolder: true,
-      overwrite: false,
-    }).then(res => {
-      return this.getDashboard('db', res.slug);
-    });
+  createFolder(payload: any) {
+    return this.post('/api/folders', payload);
   }
 
-  saveFolder(dash, options) {
+  updateFolder(folder, options) {
     options = options || {};
 
-    return this.post('/api/dashboards/db/', {
-      dashboard: dash,
-      isFolder: true,
+    return this.put(`/api/folders/${folder.uid}`, {
+      title: folder.title,
+      version: folder.version,
       overwrite: options.overwrite === true,
-      message: options.message || '',
     });
   }
 
+  deleteFolder(uid: string) {
+    let deferred = this.$q.defer();
+
+    this.getFolderByUid(uid).then(folder => {
+      this.delete(`/api/folders/${uid}`)
+        .then(() => {
+          deferred.resolve(folder);
+        })
+        .catch(err => {
+          deferred.reject(err);
+        });
+    });
+
+    return deferred.promise;
+  }
+
   deleteDashboard(uid) {
     let deferred = this.$q.defer();
 
@@ -284,11 +290,15 @@ export class BackendSrv {
     return deferred.promise;
   }
 
-  deleteDashboards(dashboardUids) {
+  deleteFoldersAndDashboards(folderUids, dashboardUids) {
     const tasks = [];
 
-    for (let uid of dashboardUids) {
-      tasks.push(this.createTask(this.deleteDashboard.bind(this), true, uid));
+    for (let folderUid of folderUids) {
+      tasks.push(this.createTask(this.deleteFolder.bind(this), true, folderUid));
+    }
+
+    for (let dashboardUid of dashboardUids) {
+      tasks.push(this.createTask(this.deleteDashboard.bind(this), true, dashboardUid));
     }
 
     return this.executeInOrder(tasks, []);

+ 2 - 2
public/app/features/dashboard/create_folder_ctrl.ts

@@ -17,9 +17,9 @@ export class CreateFolderCtrl {
       return;
     }
 
-    return this.backendSrv.createDashboardFolder(this.title).then(result => {
+    return this.backendSrv.createFolder({ title: this.title }).then(result => {
       appEvents.emit('alert-success', ['Folder Created', 'OK']);
-      this.$location.url(result.meta.url);
+      this.$location.url(result.url);
     });
   }
 

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

@@ -14,7 +14,7 @@ export class FolderDashboardsCtrl {
       const loader = new FolderPageLoader(this.backendSrv);
 
       loader.load(this, this.uid, 'manage-folder-dashboards').then(folder => {
-        const url = locationUtil.stripBaseFromUrl(folder.meta.url);
+        const url = locationUtil.stripBaseFromUrl(folder.url);
 
         if (url !== $location.path()) {
           $location.path(url).replace();

+ 6 - 6
public/app/features/dashboard/folder_page_loader.ts

@@ -36,16 +36,16 @@ export class FolderPageLoader {
       },
     };
 
-    return this.backendSrv.getDashboardByUid(uid).then(result => {
-      ctrl.folderId = result.dashboard.id;
-      const folderTitle = result.dashboard.title;
-      const folderUrl = result.meta.url;
+    return this.backendSrv.getFolderByUid(uid).then(folder => {
+      ctrl.folderId = folder.id;
+      const folderTitle = folder.title;
+      const folderUrl = folder.url;
       ctrl.navModel.main.text = folderTitle;
 
       const dashTab = ctrl.navModel.main.children.find(child => child.id === 'manage-folder-dashboards');
       dashTab.url = folderUrl;
 
-      if (result.meta.canAdmin) {
+      if (folder.canAdmin) {
         const permTab = ctrl.navModel.main.children.find(child => child.id === 'manage-folder-permissions');
         permTab.url = folderUrl + '/permissions';
 
@@ -55,7 +55,7 @@ export class FolderPageLoader {
         ctrl.navModel.main.children = [dashTab];
       }
 
-      return result;
+      return folder;
     });
   }
 }

+ 10 - 18
public/app/features/dashboard/folder_settings_ctrl.ts

@@ -7,8 +7,7 @@ export class FolderSettingsCtrl {
   folderId: number;
   uid: string;
   canSave = false;
-  dashboard: any;
-  meta: any;
+  folder: any;
   title: string;
   hasChanged: boolean;
 
@@ -23,10 +22,9 @@ export class FolderSettingsCtrl {
           $location.path(`${folder.meta.url}/settings`).replace();
         }
 
-        this.dashboard = folder.dashboard;
-        this.meta = folder.meta;
-        this.canSave = folder.meta.canSave;
-        this.title = this.dashboard.title;
+        this.folder = folder;
+        this.canSave = this.folder.canSave;
+        this.title = this.folder.title;
       });
     }
   }
@@ -38,10 +36,10 @@ export class FolderSettingsCtrl {
       return;
     }
 
-    this.dashboard.title = this.title.trim();
+    this.folder.title = this.title.trim();
 
     return this.backendSrv
-      .updateDashboardFolder(this.dashboard, { overwrite: false })
+      .updateFolder(this.folder)
       .then(result => {
         if (result.url !== this.$location.path()) {
           this.$location.url(result.url + '/settings');
@@ -54,7 +52,7 @@ export class FolderSettingsCtrl {
   }
 
   titleChanged() {
-    this.hasChanged = this.dashboard.title.toLowerCase() !== this.title.trim().toLowerCase();
+    this.hasChanged = this.folder.title.toLowerCase() !== this.title.trim().toLowerCase();
   }
 
   delete(evt) {
@@ -69,8 +67,8 @@ export class FolderSettingsCtrl {
       icon: 'fa-trash',
       yesText: 'Delete',
       onConfirm: () => {
-        return this.backendSrv.deleteDashboard(this.dashboard.uid).then(() => {
-          appEvents.emit('alert-success', ['Folder Deleted', `${this.dashboard.title} has been deleted`]);
+        return this.backendSrv.deleteFolder(this.uid).then(() => {
+          appEvents.emit('alert-success', ['Folder Deleted', `${this.folder.title} has been deleted`]);
           this.$location.url('dashboards');
         });
       },
@@ -88,15 +86,9 @@ export class FolderSettingsCtrl {
         yesText: 'Save & Overwrite',
         icon: 'fa-warning',
         onConfirm: () => {
-          this.backendSrv.updateDashboardFolder(this.dashboard, { overwrite: true });
+          this.backendSrv.updateFolder(this.folder, { overwrite: true });
         },
       });
     }
-
-    if (err.data && err.data.status === 'name-exists') {
-      err.isHandled = true;
-
-      appEvents.emit('alert-error', ['A folder or dashboard with this name exists already.']);
-    }
   }
 }

+ 14 - 9
public/app/stores/FolderStore/FolderStore.ts

@@ -2,10 +2,12 @@ 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
@@ -15,13 +17,15 @@ export const FolderStore = types
   .actions(self => ({
     load: flow(function* load(uid: string) {
       const backendSrv = getEnv(self).backendSrv;
-      const res = yield backendSrv.getDashboardByUid(uid);
+      const res = yield backendSrv.getFolderByUid(uid);
       self.folder = Folder.create({
-        id: res.dashboard.id,
-        title: res.dashboard.title,
-        url: res.meta.url,
-        canSave: res.meta.canSave,
+        id: res.id,
+        uid: res.uid,
+        title: res.title,
+        url: res.url,
+        canSave: res.canSave,
         hasChanged: false,
+        version: res.version,
       });
       return res;
     }),
@@ -31,12 +35,13 @@ export const FolderStore = types
       self.folder.hasChanged = originalTitle.toLowerCase() !== title.trim().toLowerCase() && title.trim().length > 0;
     },
 
-    saveFolder: flow(function* saveFolder(dashboard: any, options: any) {
+    saveFolder: flow(function* saveFolder(options: any) {
       const backendSrv = getEnv(self).backendSrv;
-      dashboard.title = self.folder.title.trim();
+      self.folder.title = self.folder.title.trim();
 
-      const res = yield backendSrv.saveFolder(dashboard, options);
+      const res = yield backendSrv.updateFolder(self.folder, options);
       self.folder.url = res.url;
+      self.folder.version = res.version;
 
       return `${self.folder.url}/settings`;
     }),
@@ -44,6 +49,6 @@ export const FolderStore = types
     deleteFolder: flow(function* deleteFolder() {
       const backendSrv = getEnv(self).backendSrv;
 
-      return backendSrv.deleteDashboard(self.folder.url);
+      return backendSrv.deleteFolder(self.folder.uid);
     }),
   }));

+ 1 - 0
public/test/mocks/common.ts

@@ -2,6 +2,7 @@ export const backendSrv = {
   get: jest.fn(),
   getDashboard: jest.fn(),
   getDashboardByUid: jest.fn(),
+  getFolderByUid: jest.fn(),
   post: jest.fn(),
 };