folders: use new folder api in frontend

pull/10739/head
Marcus Efraimsson 7 years ago
parent 04a9a650e7
commit d217688d5e
  1. 2
      public/app/containers/ManageDashboards/FolderPermissions.tsx
  2. 16
      public/app/containers/ManageDashboards/FolderSettings.jest.tsx
  3. 31
      public/app/containers/ManageDashboards/FolderSettings.tsx
  4. 13
      public/app/core/components/manage_dashboards/manage_dashboards.ts
  5. 56
      public/app/core/services/backend_srv.ts
  6. 4
      public/app/features/dashboard/create_folder_ctrl.ts
  7. 2
      public/app/features/dashboard/folder_dashboards_ctrl.ts
  8. 12
      public/app/features/dashboard/folder_page_loader.ts
  9. 28
      public/app/features/dashboard/folder_settings_ctrl.ts
  10. 23
      public/app/stores/FolderStore/FolderStore.ts
  11. 1
      public/test/mocks/common.ts

@ -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');
});
}

@ -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,
})
);

@ -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() {

@ -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`;
}

@ -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, []);

@ -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);
});
}

@ -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();

@ -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;
});
}
}

@ -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.']);
}
}
}

@ -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);
}),
}));

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

Loading…
Cancel
Save