folders: change the front end route for browsing folders

Change the front end route for folders to /dashboards/f/<uid>/<slug of folder title>.
Use new route for deleting dashboard/folder by uid.
Retrieve dashboard/folder by uid when moving or deleting dashboards/folders.
This commit is contained in:
Marcus Efraimsson 2018-01-31 17:15:00 +01:00
parent b23560ed5a
commit 92a0171a9b
14 changed files with 56 additions and 55 deletions

View File

@ -13,6 +13,7 @@ const (
type Hit struct { type Hit struct {
Id int64 `json:"id"` Id int64 `json:"id"`
Uid string `json:"uid"`
Title string `json:"title"` Title string `json:"title"`
Uri string `json:"uri"` Uri string `json:"uri"`
Url string `json:"url"` Url string `json:"url"`

View File

@ -266,6 +266,7 @@ func makeQueryResult(query *search.FindPersistedDashboardsQuery, res []Dashboard
} }
hit = &search.Hit{ hit = &search.Hit{
Id: item.Id, Id: item.Id,
Uid: item.Uid,
Title: item.Title, Title: item.Title,
Uri: "db/" + item.Slug, Uri: "db/" + item.Slug,
Url: url, Url: url,

View File

@ -146,7 +146,7 @@ func TestDashboardDataAccess(t *testing.T) {
So(len(query.Result), ShouldEqual, 1) So(len(query.Result), ShouldEqual, 1)
hit := query.Result[0] hit := query.Result[0]
So(hit.Type, ShouldEqual, search.DashHitFolder) So(hit.Type, ShouldEqual, search.DashHitFolder)
So(hit.Url, ShouldEqual, fmt.Sprintf("/f/%s/%s", savedFolder.Uid, savedFolder.Slug)) So(hit.Url, ShouldEqual, fmt.Sprintf("/dashboards/f/%s/%s", savedFolder.Uid, savedFolder.Slug))
}) })
Convey("Should be able to search for a dashboard folder's children", func() { Convey("Should be able to search for a dashboard folder's children", func() {

View File

@ -91,10 +91,10 @@ export class ManageDashboardsCtrl {
for (const section of this.sections) { for (const section of this.sections) {
if (section.checked && section.id !== 0) { if (section.checked && section.id !== 0) {
selectedDashboards.folders.push(section.slug); selectedDashboards.folders.push(section.uid);
} else { } else {
const selected = _.filter(section.items, { checked: true }); const selected = _.filter(section.items, { checked: true });
selectedDashboards.dashboards.push(..._.map(selected, 'slug')); selectedDashboards.dashboards.push(..._.map(selected, 'uid'));
} }
} }
@ -185,7 +185,7 @@ export class ManageDashboardsCtrl {
for (const section of this.sections) { for (const section of this.sections) {
const selected = _.filter(section.items, { checked: true }); const selected = _.filter(section.items, { checked: true });
selectedDashboards.push(..._.map(selected, 'slug')); selectedDashboards.push(..._.map(selected, 'uid'));
} }
return selectedDashboards; return selectedDashboards;

View File

@ -257,11 +257,11 @@ export class BackendSrv {
}); });
} }
deleteDashboard(slug) { deleteDashboard(uid) {
let deferred = this.$q.defer(); let deferred = this.$q.defer();
this.getDashboard('db', slug).then(fullDash => { this.getDashboardByUid(uid).then(fullDash => {
this.delete(`/api/dashboards/db/${slug}`) this.delete(`/api/dashboards/uid/${uid}`)
.then(() => { .then(() => {
deferred.resolve(fullDash); deferred.resolve(fullDash);
}) })
@ -273,21 +273,21 @@ export class BackendSrv {
return deferred.promise; return deferred.promise;
} }
deleteDashboards(dashboardSlugs) { deleteDashboards(dashboardUids) {
const tasks = []; const tasks = [];
for (let slug of dashboardSlugs) { for (let uid of dashboardUids) {
tasks.push(this.createTask(this.deleteDashboard.bind(this), true, slug)); tasks.push(this.createTask(this.deleteDashboard.bind(this), true, uid));
} }
return this.executeInOrder(tasks, []); return this.executeInOrder(tasks, []);
} }
moveDashboards(dashboardSlugs, toFolder) { moveDashboards(dashboardUids, toFolder) {
const tasks = []; const tasks = [];
for (let slug of dashboardSlugs) { for (let uid of dashboardUids) {
tasks.push(this.createTask(this.moveDashboard.bind(this), true, slug, toFolder)); tasks.push(this.createTask(this.moveDashboard.bind(this), true, uid, toFolder));
} }
return this.executeInOrder(tasks, []).then(result => { return this.executeInOrder(tasks, []).then(result => {
@ -299,10 +299,10 @@ export class BackendSrv {
}); });
} }
private moveDashboard(slug, toFolder) { private moveDashboard(uid, toFolder) {
let deferred = this.$q.defer(); let deferred = this.$q.defer();
this.getDashboard('db', slug).then(fullDash => { this.getDashboardByUid(uid).then(fullDash => {
const model = new DashboardModel(fullDash.dashboard, fullDash.meta); const model = new DashboardModel(fullDash.dashboard, fullDash.meta);
if ((!fullDash.meta.folderId && toFolder.id === 0) || fullDash.meta.folderId === toFolder.id) { if ((!fullDash.meta.folderId && toFolder.id === 0) || fullDash.meta.folderId === toFolder.id) {

View File

@ -128,11 +128,12 @@ export class SearchSrv {
if (hit.type === 'dash-folder') { if (hit.type === 'dash-folder') {
sections[hit.id] = { sections[hit.id] = {
id: hit.id, id: hit.id,
uid: hit.uid,
title: hit.title, title: hit.title,
expanded: false, expanded: false,
items: [], items: [],
toggle: this.toggleFolder.bind(this), toggle: this.toggleFolder.bind(this),
url: `dashboards/folder/${hit.id}/${hit.slug}`, url: hit.url,
slug: hit.slug, slug: hit.slug,
icon: 'fa fa-folder', icon: 'fa fa-folder',
score: _.keys(sections).length, score: _.keys(sections).length,
@ -150,8 +151,9 @@ export class SearchSrv {
if (hit.folderId) { if (hit.folderId) {
section = { section = {
id: hit.folderId, id: hit.folderId,
uid: hit.uid,
title: hit.folderTitle, title: hit.folderTitle,
url: `dashboards/folder/${hit.folderId}/${hit.folderSlug}`, url: hit.url,
slug: hit.slug, slug: hit.slug,
items: [], items: [],
icon: 'fa fa-folder-open', icon: 'fa fa-folder-open',

View File

@ -483,22 +483,22 @@ describe('ManageDashboards', () => {
ctrl.sections = [ ctrl.sections = [
{ {
id: 1, id: 1,
uid: 'folder',
title: 'folder', title: 'folder',
items: [{ id: 2, checked: true, slug: 'folder-dash' }], items: [{ id: 2, checked: true, uid: 'folder-dash' }],
checked: true, checked: true,
slug: 'folder',
}, },
{ {
id: 3, id: 3,
title: 'folder-2', title: 'folder-2',
items: [{ id: 3, checked: true, slug: 'folder-2-dash' }], items: [{ id: 3, checked: true, uid: 'folder-2-dash' }],
checked: false, checked: false,
slug: 'folder-2', uid: 'folder-2',
}, },
{ {
id: 0, id: 0,
title: 'Root', title: 'Root',
items: [{ id: 3, checked: true, slug: 'root-dash' }], items: [{ id: 3, checked: true, uid: 'root-dash' }],
checked: true, checked: true,
}, },
]; ];
@ -535,14 +535,14 @@ describe('ManageDashboards', () => {
{ {
id: 1, id: 1,
title: 'folder', title: 'folder',
items: [{ id: 2, checked: true, slug: 'dash' }], items: [{ id: 2, checked: true, uid: 'dash' }],
checked: false, checked: false,
slug: 'folder', uid: 'folder',
}, },
{ {
id: 0, id: 0,
title: 'Root', title: 'Root',
items: [{ id: 3, checked: true, slug: 'dash-2' }], items: [{ id: 3, checked: true, uid: 'dash-2' }],
checked: false, checked: false,
}, },
]; ];

View File

@ -19,9 +19,7 @@ export class CreateFolderCtrl {
return this.backendSrv.createDashboardFolder(this.title).then(result => { return this.backendSrv.createDashboardFolder(this.title).then(result => {
appEvents.emit('alert-success', ['Folder Created', 'OK']); appEvents.emit('alert-success', ['Folder Created', 'OK']);
this.$location.url(result.meta.url);
var folderUrl = `dashboards/folder/${result.dashboard.id}/${result.meta.slug}`;
this.$location.url(folderUrl);
}); });
} }

View File

@ -3,15 +3,16 @@ import { FolderPageLoader } from './folder_page_loader';
export class FolderDashboardsCtrl { export class FolderDashboardsCtrl {
navModel: any; navModel: any;
folderId: number; folderId: number;
uid: string;
/** @ngInject */ /** @ngInject */
constructor(private backendSrv, navModelSrv, private $routeParams) { constructor(private backendSrv, navModelSrv, private $routeParams) {
if (this.$routeParams.folderId && this.$routeParams.slug) { if (this.$routeParams.uid) {
this.folderId = $routeParams.folderId; this.uid = $routeParams.uid;
const loader = new FolderPageLoader(this.backendSrv, this.$routeParams); const loader = new FolderPageLoader(this.backendSrv);
loader.load(this, this.folderId, 'manage-folder-dashboards'); loader.load(this, this.uid, 'manage-folder-dashboards');
} }
} }
} }

View File

@ -1,9 +1,9 @@
import _ from 'lodash'; import _ from 'lodash';
export class FolderPageLoader { export class FolderPageLoader {
constructor(private backendSrv, private $routeParams) {} constructor(private backendSrv) {}
load(ctrl, folderId, activeChildId) { load(ctrl, uid, activeChildId) {
ctrl.navModel = { ctrl.navModel = {
main: { main: {
icon: 'fa fa-folder-open', icon: 'fa fa-folder-open',
@ -38,12 +38,13 @@ export class FolderPageLoader {
}, },
}; };
return this.backendSrv.getDashboard('db', this.$routeParams.slug).then(result => { return this.backendSrv.getDashboardByUid(uid).then(result => {
ctrl.folderId = result.dashboard.id;
const folderTitle = result.dashboard.title; const folderTitle = result.dashboard.title;
ctrl.navModel.main.text = ''; ctrl.navModel.main.text = '';
ctrl.navModel.main.breadcrumbs = [{ title: 'Dashboards', url: 'dashboards' }, { title: folderTitle }]; ctrl.navModel.main.breadcrumbs = [{ title: 'Dashboards', url: 'dashboards' }, { title: folderTitle }];
const folderUrl = this.createFolderUrl(folderId, result.meta.type, result.meta.slug); const folderUrl = result.meta.url;
const dashTab = _.find(ctrl.navModel.main.children, { const dashTab = _.find(ctrl.navModel.main.children, {
id: 'manage-folder-dashboards', id: 'manage-folder-dashboards',
@ -63,8 +64,4 @@ export class FolderPageLoader {
return result; return result;
}); });
} }
createFolderUrl(folderId: number, type: string, slug: string) {
return `dashboards/folder/${folderId}/${slug}`;
}
} }

View File

@ -3,13 +3,14 @@ import { FolderPageLoader } from './folder_page_loader';
export class FolderPermissionsCtrl { export class FolderPermissionsCtrl {
navModel: any; navModel: any;
folderId: number; folderId: number;
uid: string;
/** @ngInject */ /** @ngInject */
constructor(private backendSrv, navModelSrv, private $routeParams) { constructor(private backendSrv, navModelSrv, private $routeParams) {
if (this.$routeParams.folderId && this.$routeParams.slug) { if (this.$routeParams.uid) {
this.folderId = $routeParams.folderId; this.uid = $routeParams.uid;
new FolderPageLoader(this.backendSrv, this.$routeParams).load(this, this.folderId, 'manage-folder-permissions'); new FolderPageLoader(this.backendSrv).load(this, this.uid, 'manage-folder-permissions');
} }
} }
} }

View File

@ -5,6 +5,7 @@ export class FolderSettingsCtrl {
folderPageLoader: FolderPageLoader; folderPageLoader: FolderPageLoader;
navModel: any; navModel: any;
folderId: number; folderId: number;
uid: string;
canSave = false; canSave = false;
dashboard: any; dashboard: any;
meta: any; meta: any;
@ -13,11 +14,11 @@ export class FolderSettingsCtrl {
/** @ngInject */ /** @ngInject */
constructor(private backendSrv, navModelSrv, private $routeParams, private $location) { constructor(private backendSrv, navModelSrv, private $routeParams, private $location) {
if (this.$routeParams.folderId && this.$routeParams.slug) { if (this.$routeParams.uid) {
this.folderId = $routeParams.folderId; this.uid = $routeParams.uid;
this.folderPageLoader = new FolderPageLoader(this.backendSrv, this.$routeParams); this.folderPageLoader = new FolderPageLoader(this.backendSrv);
this.folderPageLoader.load(this, this.folderId, 'manage-folder-settings').then(result => { this.folderPageLoader.load(this, this.uid, 'manage-folder-settings').then(result => {
this.dashboard = result.dashboard; this.dashboard = result.dashboard;
this.meta = result.meta; this.meta = result.meta;
this.canSave = result.meta.canSave; this.canSave = result.meta.canSave;
@ -38,9 +39,8 @@ export class FolderSettingsCtrl {
return this.backendSrv return this.backendSrv
.saveDashboard(this.dashboard, { overwrite: false }) .saveDashboard(this.dashboard, { overwrite: false })
.then(result => { .then(result => {
var folderUrl = this.folderPageLoader.createFolderUrl(this.folderId, this.meta.type, result.slug); if (result.url !== this.$location.path()) {
if (folderUrl !== this.$location.path()) { this.$location.url(result.url + '/settings');
this.$location.url(folderUrl + '/settings');
} }
appEvents.emit('dashboard-saved'); appEvents.emit('dashboard-saved');
@ -65,7 +65,7 @@ export class FolderSettingsCtrl {
icon: 'fa-trash', icon: 'fa-trash',
yesText: 'Delete', yesText: 'Delete',
onConfirm: () => { onConfirm: () => {
return this.backendSrv.deleteDashboard(this.meta.slug).then(() => { return this.backendSrv.deleteDashboard(this.dashboard.uid).then(() => {
appEvents.emit('alert-success', ['Folder Deleted', `${this.dashboard.title} has been deleted`]); appEvents.emit('alert-success', ['Folder Deleted', `${this.dashboard.title} has been deleted`]);
this.$location.url('dashboards'); this.$location.url('dashboards');
}); });

View File

@ -174,7 +174,7 @@ export class SettingsCtrl {
} }
deleteDashboardConfirmed() { deleteDashboardConfirmed() {
this.backendSrv.deleteDashboard(this.dashboard.meta.slug).then(() => { this.backendSrv.deleteDashboard(this.dashboard.uid).then(() => {
appEvents.emit('alert-success', ['Dashboard Deleted', this.dashboard.title + ' has been deleted']); appEvents.emit('alert-success', ['Dashboard Deleted', this.dashboard.title + ' has been deleted']);
this.$location.url('/'); this.$location.url('/');
}); });

View File

@ -74,17 +74,17 @@ export function setupAngularRoutes($routeProvider, $locationProvider) {
controller: 'CreateFolderCtrl', controller: 'CreateFolderCtrl',
controllerAs: 'ctrl', controllerAs: 'ctrl',
}) })
.when('/dashboards/folder/:folderId/:slug/permissions', { .when('/dashboards/f/:uid/:slug/permissions', {
templateUrl: 'public/app/features/dashboard/partials/folder_permissions.html', templateUrl: 'public/app/features/dashboard/partials/folder_permissions.html',
controller: 'FolderPermissionsCtrl', controller: 'FolderPermissionsCtrl',
controllerAs: 'ctrl', controllerAs: 'ctrl',
}) })
.when('/dashboards/folder/:folderId/:slug/settings', { .when('/dashboards/f/:uid/:slug/settings', {
templateUrl: 'public/app/features/dashboard/partials/folder_settings.html', templateUrl: 'public/app/features/dashboard/partials/folder_settings.html',
controller: 'FolderSettingsCtrl', controller: 'FolderSettingsCtrl',
controllerAs: 'ctrl', controllerAs: 'ctrl',
}) })
.when('/dashboards/folder/:folderId/:slug', { .when('/dashboards/f/:uid/:slug', {
templateUrl: 'public/app/features/dashboard/partials/folder_dashboards.html', templateUrl: 'public/app/features/dashboard/partials/folder_dashboards.html',
controller: 'FolderDashboardsCtrl', controller: 'FolderDashboardsCtrl',
controllerAs: 'ctrl', controllerAs: 'ctrl',