diff --git a/public/app/core/components/manage_dashboards/manage_dashboards.ts b/public/app/core/components/manage_dashboards/manage_dashboards.ts
index 5b74a0e50fc..1aa8a3f014a 100644
--- a/public/app/core/components/manage_dashboards/manage_dashboards.ts
+++ b/public/app/core/components/manage_dashboards/manage_dashboards.ts
@@ -134,12 +134,12 @@ export class ManageDashboardsCtrl {
const selectedDashboards = this.getDashboardsToMove();
const template = '' +
+ 'dashboards="model.dashboards" from-folder-id="model.fromFolderId" after-save="model.afterSave()">' +
'`';
appEvents.emit('show-modal', {
templateHtml: template,
modalClass: 'modal--narrow',
- model: { dashboards: selectedDashboards, afterSave: this.getDashboards.bind(this) }
+ model: { dashboards: selectedDashboards, fromFolderId: this.folderId ? Number(this.folderId) : 0, afterSave: this.getDashboards.bind(this) }
});
}
diff --git a/public/app/features/dashboard/dashboardLoaderSrv.js b/public/app/features/dashboard/dashboardLoaderSrv.js
index 588df632e9b..708e6b563e4 100644
--- a/public/app/features/dashboard/dashboardLoaderSrv.js
+++ b/public/app/features/dashboard/dashboardLoaderSrv.js
@@ -43,6 +43,13 @@ function (angular, moment, _, $, kbn, dateMath, impressionSrv) {
});
} else {
promise = backendSrv.getDashboard($routeParams.type, $routeParams.slug)
+ .then(result => {
+ if (result.meta.isFolder) {
+ $rootScope.appEvent("alert-error", ['Dashboard not found']);
+ throw new Error("Dashboard not found");
+ }
+ return result;
+ })
.catch(function() {
return self._dashboardLoadFailed("Not found");
});
diff --git a/public/app/features/dashboard/folder_picker/picker.ts b/public/app/features/dashboard/folder_picker/picker.ts
index 97666365696..ffde1dacc88 100644
--- a/public/app/features/dashboard/folder_picker/picker.ts
+++ b/public/app/features/dashboard/folder_picker/picker.ts
@@ -5,9 +5,10 @@ import _ from 'lodash';
export class FolderPickerCtrl {
initialTitle: string;
- initialFolderId: number;
+ initialFolderId?: number;
labelClass: string;
onChange: any;
+ onLoad: any;
rootName = 'Root';
folder: any;
@@ -17,12 +18,19 @@ export class FolderPickerCtrl {
this.labelClass = "width-7";
}
- if (this.initialFolderId > 0) {
+ if (this.initialFolderId && this.initialFolderId > 0) {
this.getOptions('').then(result => {
this.folder = _.find(result, {value: this.initialFolderId});
+ this.onFolderLoad();
});
} else {
- this.folder = {text: this.initialTitle, value: null};
+ if (this.initialTitle) {
+ this.folder = {text: this.initialTitle, value: null};
+ } else {
+ this.folder = {text: this.rootName, value: 0};
+ }
+
+ this.onFolderLoad();
}
}
@@ -33,8 +41,12 @@ export class FolderPickerCtrl {
};
return this.backendSrv.search(params).then(result => {
- if (query === "") {
- result.unshift({title: this.rootName, value: 0});
+ 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 => {
@@ -43,6 +55,12 @@ export class FolderPickerCtrl {
});
}
+ 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}});
}
@@ -69,11 +87,12 @@ export function folderPicker() {
bindToController: true,
controllerAs: 'ctrl',
scope: {
- initialTitle: "<",
+ initialTitle: '<',
initialFolderId: '<',
labelClass: '@',
rootName: '@',
- onChange: '&'
+ onChange: '&',
+ onLoad: '&'
}
};
}
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 429d6439e57..8f04d393a5d 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
@@ -15,7 +15,8 @@
-
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 ce110b3e2a2..4761969662e 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
@@ -7,6 +7,7 @@ export class MoveToFolderCtrl {
folder: any;
dismiss: any;
afterSave: any;
+ fromFolderId: number;
/** @ngInject */
constructor(private backendSrv, private $q) {}
@@ -16,10 +17,16 @@ export class MoveToFolderCtrl {
}
save() {
+ if (this.folder.id === this.fromFolderId) {
+ appEvents.emit('alert-error', ['Dashboard(s) already belong to this folder']);
+ return;
+ }
+
const promises = [];
for (let dash of this.dashboards) {
const promise = this.backendSrv.get('/api/dashboards/' + dash).then(fullDash => {
const model = new DashboardModel(fullDash.dashboard, fullDash.meta);
+
model.folderId = this.folder.id;
model.meta.folderId = this.folder.id;
model.meta.folderTitle = this.folder.title;
@@ -53,6 +60,7 @@ export function moveToFolderModal() {
scope: {
dismiss: "&",
dashboards: "=",
+ fromFolderId: '<',
afterSave: "&"
}
};
diff --git a/public/app/features/dashboard/partials/settings.html b/public/app/features/dashboard/partials/settings.html
index 6a8f4792f72..77d6691f8f9 100644
--- a/public/app/features/dashboard/partials/settings.html
+++ b/public/app/features/dashboard/partials/settings.html
@@ -37,9 +37,8 @@
-
diff --git a/public/app/features/dashboard/save_as_modal.ts b/public/app/features/dashboard/save_as_modal.ts
index bbb2899f665..643d6a36f67 100644
--- a/public/app/features/dashboard/save_as_modal.ts
+++ b/public/app/features/dashboard/save_as_modal.ts
@@ -22,7 +22,7 @@ const template = `
-
@@ -39,7 +39,7 @@ const template = `
export class SaveDashboardAsModalCtrl {
clone: any;
- folderTitle: any;
+ folderId: any;
dismiss: () => void;
/** @ngInject */
@@ -50,7 +50,7 @@ export class SaveDashboardAsModalCtrl {
this.clone.title += ' Copy';
this.clone.editable = true;
this.clone.hideControls = false;
- this.folderTitle = dashboard.meta.folderTitle || 'Root';
+ this.folderId = dashboard.folderId;
// remove alerts if source dashboard is already persisted
// do not want to create alert dupes
diff --git a/public/app/features/dashboard/view_state_srv.ts b/public/app/features/dashboard/view_state_srv.ts
index dec507d2002..0c4c510b4fc 100644
--- a/public/app/features/dashboard/view_state_srv.ts
+++ b/public/app/features/dashboard/view_state_srv.ts
@@ -75,7 +75,7 @@ export class DashboardViewState {
}
// remember if editStateChanged
- this.editStateChanged = state.edit !== this.state.edit;
+ this.editStateChanged = (state.edit || false) !== (this.state.edit || false);
_.extend(this.state, state);
this.dashboard.meta.fullscreen = this.state.fullscreen;
diff --git a/public/app/features/panel/panel_ctrl.ts b/public/app/features/panel/panel_ctrl.ts
index 91c1b06cbf4..ab74a006fce 100644
--- a/public/app/features/panel/panel_ctrl.ts
+++ b/public/app/features/panel/panel_ctrl.ts
@@ -52,12 +52,9 @@ export class PanelCtrl {
this.events.emit('panel-teardown');
this.events.removeAllListeners();
});
-
- this.calculatePanelHeight();
}
init() {
- this.events.on('panel-size-changed', this.onSizeChanged.bind(this));
this.events.emit('panel-initialized');
this.publishAppEvent('panel-initialized', {scope: this.$scope});
}
@@ -184,13 +181,6 @@ export class PanelCtrl {
this.events.emit('render', payload);
}
- private onSizeChanged() {
- this.calculatePanelHeight();
- this.$timeout(() => {
- this.render();
- }, 100);
- }
-
duplicate() {
this.dashboard.duplicatePanel(this.panel);
this.$timeout(() => {
diff --git a/public/app/features/panel/panel_directive.ts b/public/app/features/panel/panel_directive.ts
index 323cd4e6f6b..626e7c151e9 100644
--- a/public/app/features/panel/panel_directive.ts
+++ b/public/app/features/panel/panel_directive.ts
@@ -53,7 +53,7 @@ var panelTemplate = `
`;
-module.directive('grafanaPanel', function($rootScope, $document) {
+module.directive('grafanaPanel', function($rootScope, $document, $timeout) {
return {
restrict: 'E',
template: panelTemplate,
@@ -73,7 +73,6 @@ module.directive('grafanaPanel', function($rootScope, $document) {
var lastHasAlertRule = false;
var lastAlertState;
var hasAlertRule;
- var lastHeight = 0;
function mouseEnter() {
panelContainer.toggleClass('panel-hover-highlight', true);
@@ -90,7 +89,6 @@ module.directive('grafanaPanel', function($rootScope, $document) {
if (panelScrollbar) {
panelScrollbar.update();
}
- lastHeight = ctrl.height;
}
// set initial transparency
@@ -106,11 +104,19 @@ module.directive('grafanaPanel', function($rootScope, $document) {
}
});
- ctrl.events.on('render', () => {
- if (lastHeight !== ctrl.height) {
- panelHeightUpdated();
- }
+ ctrl.events.on('panel-size-changed', () => {
+ ctrl.calculatePanelHeight();
+ panelHeightUpdated();
+ $timeout(() => {
+ ctrl.render();
+ });
+ });
+ // set initial height
+ ctrl.calculatePanelHeight();
+ panelHeightUpdated();
+
+ ctrl.events.on('render', () => {
if (transparentLastState !== ctrl.panel.transparent) {
panelContainer.toggleClass('panel-transparent', ctrl.panel.transparent === true);
transparentLastState = ctrl.panel.transparent;
diff --git a/public/app/features/panel/panel_header.ts b/public/app/features/panel/panel_header.ts
index 5429a992a71..ef32c43fbb0 100644
--- a/public/app/features/panel/panel_header.ts
+++ b/public/app/features/panel/panel_header.ts
@@ -84,8 +84,6 @@ function panelHeader($compile) {
restrict: 'E',
template: template,
link: function(scope, elem, attrs) {
- console.log(elem.html());
-
let menuElem = elem.find('.panel-menu');
let menuScope;
let isDragged;
diff --git a/public/app/plugins/panel/permissionlist/editor.html b/public/app/plugins/panel/permissionlist/editor.html
index fc29351f4d2..3f0708642dc 100644
--- a/public/app/plugins/panel/permissionlist/editor.html
+++ b/public/app/plugins/panel/permissionlist/editor.html
@@ -2,8 +2,7 @@