Merge pull request #2356 from kravets-levko/fix/dashboard-auto-height

Dashboard fixes and improvements
This commit is contained in:
Arik Fraimovich 2018-03-04 14:50:48 +02:00 committed by GitHub
commit 6049e2df17
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 97 additions and 43 deletions

View File

@ -1,15 +1,37 @@
import * as _ from 'underscore';
import { requestAnimationFrame } from './utils';
function gridsterAutoHeight($timeout) {
function gridsterAutoHeight($timeout, $parse) {
return {
restrict: 'A',
require: 'gridsterItem',
link($scope, $element, attr, controller) {
let destroyed = false;
let autoSized = true;
const itemGetter = $parse(attr.gridsterItem);
$scope.$watch(attr.gridsterItem, (newValue, oldValue) => {
const item = _.extend({}, itemGetter($scope));
if (_.isObject(newValue) && _.isObject(oldValue)) {
if ((newValue.sizeY !== oldValue.sizeY) && !autoSized) {
item.autoHeight = false;
if (_.isFunction(itemGetter.assign)) {
itemGetter.assign($scope, item);
}
}
}
if (item.autoHeight) {
$element.addClass('gridster-auto-height-enabled');
} else {
$element.removeClass('gridster-auto-height-enabled');
}
autoSized = false;
}, true);
function updateHeight() {
if (controller.gridster) {
const item = _.extend({}, itemGetter($scope));
if (controller.gridster && item.autoHeight) {
const wrapper = $element[0];
// Query element, but keep selector order
const element = _.chain(attr.gridsterAutoHeight.split(','))
@ -31,25 +53,22 @@ function gridsterAutoHeight($timeout) {
const additionalHeight = 100 + _.last(controller.gridster.margins);
const contentsHeight = childrenBounds.bottom - childrenBounds.top;
$timeout(() => {
controller.sizeY = Math.ceil((contentsHeight + additionalHeight) /
const sizeY = Math.ceil((contentsHeight + additionalHeight) /
controller.gridster.curRowHeight);
if (controller.sizeY !== sizeY) {
autoSized = true;
controller.sizeY = sizeY;
} else {
autoSized = false;
}
});
}
if (!destroyed) {
requestAnimationFrame(updateHeight);
}
requestAnimationFrame(updateHeight);
}
}
if (controller.sizeY < 0) {
$element.addClass('gridster-auto-height-enabled');
updateHeight();
$scope.$on('$destroy', () => {
destroyed = true;
});
}
updateHeight();
},
};
}

View File

@ -5,6 +5,30 @@ import template from './dashboard.html';
import shareDashboardTemplate from './share-dashboard.html';
import './dashboard.less';
function isWidgetPositionChanged(oldPosition, newPosition) {
const fields = ['col', 'row', 'sizeX', 'sizeY', 'autoHeight'];
oldPosition = _.pick(oldPosition, fields);
newPosition = _.pick(newPosition, fields);
return !!_.find(fields, key => newPosition[key] !== oldPosition[key]);
}
function collectWidgetPositions(widgets) {
return _.chain(widgets)
.map(widget => [widget.id, _.clone(widget.options.position)])
.object()
.value();
}
function getWidgetsWithChangedPositions(widgets, savedPositions) {
return _.filter(widgets, (widget) => {
const savedPosition = savedPositions[widget.id];
if (!_.isObject(savedPosition)) {
return true;
}
return isWidgetPositionChanged(savedPosition, widget.options.position);
});
}
function DashboardCtrl(
$rootScope,
$routeParams,
@ -22,7 +46,11 @@ function DashboardCtrl(
toastr,
) {
this.saveInProgress = false;
const saveDashboardLayout = () => {
// This variable should always be in sync with widgets
let savedWidgetPositions = {};
const saveDashboardLayout = (widgets) => {
if (!this.dashboard.canEdit()) {
return;
}
@ -33,7 +61,7 @@ function DashboardCtrl(
this.dashboardGridOptions.draggable.enabled = false;
this.dashboardGridOptions.resizable.enabled = false;
return $q
.all(_.map(this.dashboard.widgets, widget => widget.$save()))
.all(_.map(widgets, widget => widget.$save()))
.then(() => {
if (showMessages) {
toastr.success('Changes saved.');
@ -181,6 +209,8 @@ function DashboardCtrl(
$location.search('edit', null);
this.editLayout(true);
}
savedWidgetPositions = collectWidgetPositions(dashboard.widgets);
},
(rejection) => {
const statusGroup = Math.floor(rejection.status / 100);
@ -233,26 +263,26 @@ function DashboardCtrl(
if (enableEditing) {
if (!this.layoutEditing) {
// Save current positions of widgets
_.each(this.dashboard.widgets, (widget) => {
widget.$savedPosition = _.clone(widget.options.position);
});
savedWidgetPositions = collectWidgetPositions(this.dashboard.widgets);
}
} else {
if (applyChanges) {
// Clear saved data and save layout
_.each(this.dashboard.widgets, (widget) => {
widget.$savedPosition = undefined;
const changedWidgets = getWidgetsWithChangedPositions(
this.dashboard.widgets,
savedWidgetPositions,
);
saveDashboardLayout(changedWidgets).finally(() => {
savedWidgetPositions = collectWidgetPositions(this.dashboard.widgets);
});
saveDashboardLayout();
} else {
// Revert changes
_.each(this.dashboard.widgets, (widget) => {
if (_.isObject(widget.$savedPosition)) {
widget.options.position = widget.$savedPosition;
if (_.isObject(savedWidgetPositions[widget.id])) {
widget.options.position = savedWidgetPositions[widget.id];
}
widget.$savedPosition = undefined;
});
}
savedWidgetPositions = collectWidgetPositions(this.dashboard.widgets);
}
this.layoutEditing = enableEditing;
@ -297,19 +327,14 @@ function DashboardCtrl(
})
.result.then(() => {
this.extractGlobalParameters();
if (this.layoutEditing) {
// Save position of newly added widget (but not entire layout)
const widget = _.last(this.dashboard.widgets);
if (_.isObject(widget)) {
return widget.$save().then(() => {
if (this.layoutEditing) {
widget.$savedPosition = _.clone(widget.options.position);
}
});
}
} else {
// Update entire layout
return saveDashboardLayout();
// Save position of newly added widget (but not entire layout)
const widget = _.last(this.dashboard.widgets);
if (_.isObject(widget)) {
return widget.$save().then(() => {
if (this.layoutEditing) {
savedWidgetPositions[widget.id] = _.clone(widget.options.position);
}
});
}
});
};
@ -320,7 +345,13 @@ function DashboardCtrl(
// We need to wait a bit for `angular-gridster` before it updates widgets,
// and only then save new layout
$timeout(() => {
saveDashboardLayout();
const changedWidgets = getWidgetsWithChangedPositions(
this.dashboard.widgets,
savedWidgetPositions,
);
saveDashboardLayout(changedWidgets).finally(() => {
savedWidgetPositions = collectWidgetPositions(this.dashboard.widgets);
});
}, 50);
}
};

View File

@ -103,9 +103,13 @@ function Widget($resource, $http, Query, Visualization, dashboardGridOptions) {
widget.options.position = extend(
{},
visualizationOptions,
pick(widget.options.position, ['col', 'row', 'sizeX', 'sizeY']),
pick(widget.options.position, ['col', 'row', 'sizeX', 'sizeY', 'autoHeight']),
);
if (widget.options.position.sizeY < 0) {
widget.options.position.autoHeight = true;
}
return new WidgetResource(widget);
}

View File

@ -20,7 +20,7 @@ const DISPLAY_AS_OPTIONS = [
const DEFAULT_OPTIONS = {
itemsPerPage: 15,
defaultRows: -1,
defaultColumns: 4,
defaultColumns: 3,
minColumns: 2,
};