UI: Dashboard layout improvements.

This commit is contained in:
Igor Kulikov 2017-06-23 12:59:10 +03:00
parent 13a6c9a142
commit f93dc9058f
9 changed files with 129 additions and 28 deletions

View File

@ -215,6 +215,12 @@ function DashboardUtils(types, utils, timeService) {
row: widget.row,
col: widget.col,
};
if (angular.isDefined(widget.config.mobileHeight)) {
mainLayout.widgets[id].mobileHeight = widget.config.mobileHeight;
}
if (angular.isDefined(widget.config.mobileOrder)) {
mainLayout.widgets[id].mobileOrder = widget.config.mobileOrder;
}
}
} else {
var states = dashboard.configuration.states;

View File

@ -60,6 +60,8 @@ function Dashboard() {
margins: '=',
isEdit: '=',
autofillHeight: '=',
mobileAutofillHeight: '=?',
mobileRowHeight: '=?',
isMobile: '=',
isMobileDisabled: '=?',
isEditActionEnabled: '=',
@ -124,8 +126,8 @@ function DashboardController($scope, $rootScope, $element, $timeout, $mdMedia, $
maxRows: 100,
columns: vm.columns ? vm.columns : 24,
margins: vm.margins ? vm.margins : [10, 10],
minSizeX: 2,
minSizeY: 2,
minSizeX: 1,
minSizeY: 1,
defaultSizeX: 8,
defaultSizeY: 6,
resizable: {
@ -170,6 +172,8 @@ function DashboardController($scope, $rootScope, $element, $timeout, $mdMedia, $
vm.onWidgetFullscreenChanged = onWidgetFullscreenChanged;
vm.isAutofillHeight = autofillHeight;
vm.widgetMouseDown = widgetMouseDown;
vm.widgetClicked = widgetClicked;
@ -177,9 +181,7 @@ function DashboardController($scope, $rootScope, $element, $timeout, $mdMedia, $
vm.widgetSizeY = widgetSizeY;
vm.widgetRow = widgetRow;
vm.widgetCol = widgetCol;
vm.widgetColor = widgetColor;
vm.widgetBackgroundColor = widgetBackgroundColor;
vm.widgetPadding = widgetPadding;
vm.widgetStyle = widgetStyle;
vm.showWidgetTitle = showWidgetTitle;
vm.hasWidgetTitleTemplate = hasWidgetTitleTemplate;
vm.widgetTitleTemplate = widgetTitleTemplate;
@ -236,7 +238,7 @@ function DashboardController($scope, $rootScope, $element, $timeout, $mdMedia, $
});
function onGirdsterParentResize() {
if (gridsterParent.height() && vm.autofillHeight) {
if (gridsterParent.height() && autofillHeight()) {
updateMobileOpts();
}
}
@ -279,7 +281,7 @@ function DashboardController($scope, $rootScope, $element, $timeout, $mdMedia, $
delete vm.widgetLayoutInfo[widgetId];
}
}
if (vm.autofillHeight) {
if (autofillHeight()) {
updateMobileOpts();
}
});
@ -295,15 +297,13 @@ function DashboardController($scope, $rootScope, $element, $timeout, $mdMedia, $
function updateMobileOpts() {
var isMobileDisabled = vm.isMobileDisabled === true;
var isMobile = vm.isMobile === true && !isMobileDisabled || vm.autofillHeight;
var isMobile = vm.isMobile === true && !isMobileDisabled;
var mobileBreakPoint = isMobileDisabled ? 0 : (isMobile ? 20000 : 960);
if (!isMobile && !isMobileDisabled) {
isMobile = !$mdMedia('gt-sm');
}
var rowHeight = detectRowSize(isMobile);
if (vm.gridsterOpts.isMobile != isMobile) {
vm.gridsterOpts.isMobile = isMobile;
vm.gridsterOpts.mobileModeEnabled = isMobile;
@ -311,6 +311,7 @@ function DashboardController($scope, $rootScope, $element, $timeout, $mdMedia, $
if (vm.gridsterOpts.mobileBreakPoint != mobileBreakPoint) {
vm.gridsterOpts.mobileBreakPoint = mobileBreakPoint;
}
var rowHeight = detectRowSize(isMobile);
if (vm.gridsterOpts.rowHeight != rowHeight) {
vm.gridsterOpts.rowHeight = rowHeight;
}
@ -339,6 +340,14 @@ function DashboardController($scope, $rootScope, $element, $timeout, $mdMedia, $
updateMobileOpts();
});
$scope.$watch('vm.mobileAutofillHeight', function () {
updateMobileOpts();
});
$scope.$watch('vm.mobileRowHeight', function () {
updateMobileOpts();
});
$scope.$watch('vm.isMobileDisabled', function () {
updateMobileOpts();
});
@ -408,32 +417,49 @@ function DashboardController($scope, $rootScope, $element, $timeout, $mdMedia, $
}
});
function autofillHeight() {
if (vm.gridsterOpts.isMobile) {
return angular.isDefined(vm.mobileAutofillHeight) ? vm.mobileAutofillHeight : false;
} else {
return angular.isDefined(vm.autofillHeight) ? vm.autofillHeight : false;
}
}
function detectRowSize(isMobile) {
var rowHeight = isMobile ? 70 : 'match';
if (vm.autofillHeight) {
var rowHeight;
if (autofillHeight()) {
var viewportHeight = gridsterParent.height();
var totalRows = 0;
for (var i = 0; i < vm.widgets.length; i++) {
var w = vm.widgets[i];
var sizeY = widgetSizeY(w);
if (isMobile) {
totalRows += sizeY;
} else {
var row = widgetRow(w);
var bottom = row + sizeY;
totalRows = Math.max(totalRows, bottom);
}
}
rowHeight = (viewportHeight - vm.gridsterOpts.margins[1]*(vm.widgets.length+1) + vm.gridsterOpts.margins[0]*vm.widgets.length) / totalRows;
} else if (isMobile) {
rowHeight = angular.isDefined(vm.mobileRowHeight) ? vm.mobileRowHeight : 70;
} else {
rowHeight = 'match';
}
return rowHeight;
}
function widgetOrder(widget) {
var order;
if (vm.widgetLayouts && vm.widgetLayouts[widget.id]) {
if (angular.isDefined(vm.widgetLayouts[widget.id].mobileOrder)
var hasLayout = vm.widgetLayouts && vm.widgetLayouts[widget.id];
if (hasLayout && angular.isDefined(vm.widgetLayouts[widget.id].mobileOrder)
&& vm.widgetLayouts[widget.id].mobileOrder >= 0) {
order = vm.widgetLayouts[widget.id].mobileOrder;
} else {
order = vm.widgetLayouts[widget.id].row;
}
} else if (angular.isDefined(widget.config.mobileOrder) && widget.config.mobileOrder >= 0) {
order = widget.config.mobileOrder;
} else if (hasLayout) {
order = vm.widgetLayouts[widget.id].row;
} else {
order = widget.row;
}
@ -722,7 +748,7 @@ function DashboardController($scope, $rootScope, $element, $timeout, $mdMedia, $
}
function widgetSizeY(widget) {
if (vm.gridsterOpts.isMobile && !vm.autofillHeight) {
if (vm.gridsterOpts.isMobile && !vm.mobileAutofillHeight) {
var mobileHeight;
if (vm.widgetLayouts && vm.widgetLayouts[widget.id]) {
mobileHeight = vm.widgetLayouts[widget.id].mobileHeight;
@ -790,6 +816,18 @@ function DashboardController($scope, $rootScope, $element, $timeout, $mdMedia, $
}
}
function widgetStyle(widget) {
var style = {cursor: 'pointer',
color: widgetColor(widget),
backgroundColor: widgetBackgroundColor(widget),
padding: widgetPadding(widget),
margin: widgetMargin(widget)};
if (angular.isDefined(widget.config.widgetStyle)) {
Object.assign(style, widget.config.widgetStyle);
}
return style;
}
function widgetColor(widget) {
if (widget.config.color) {
return widget.config.color;
@ -814,6 +852,14 @@ function DashboardController($scope, $rootScope, $element, $timeout, $mdMedia, $
}
}
function widgetMargin(widget) {
if (widget.config.margin) {
return widget.config.margin;
} else {
return '0px';
}
}
function showWidgetTitle(widget) {
if (angular.isDefined(widget.config.showTitle)) {
return widget.config.showTitle;

View File

@ -22,7 +22,8 @@
</md-progress-circular>
</md-content>
<md-menu md-position-mode="target target" tb-mousepoint-menu>
<md-content id="gridster-parent" class="tb-dashboard-content" flex layout-wrap ng-click="" tb-contextmenu="vm.openDashboardContextMenu($event, $mdOpenMousepointMenu)">
<md-content id="gridster-parent" class="tb-dashboard-content" flex layout-wrap ng-click="" ng-style="{'overflowY': vm.isAutofillHeight() ? 'hidden' : 'auto'}"
tb-contextmenu="vm.openDashboardContextMenu($event, $mdOpenMousepointMenu)">
<div ng-class="vm.dashboardClass" id="gridster-background" style="height: auto; min-height: 100%; display: inline;">
<div id="gridster-child" gridster="vm.gridsterOpts">
<ul>
@ -42,10 +43,7 @@
tb-mousedown="vm.widgetMouseDown($event, widget)"
ng-click="vm.widgetClicked($event, widget)"
tb-contextmenu="vm.openWidgetContextMenu($event, widget, $mdOpenMousepointMenu)"
ng-style="{cursor: 'pointer',
color: vm.widgetColor(widget),
backgroundColor: vm.widgetBackgroundColor(widget),
padding: vm.widgetPadding(widget)}">
ng-style="vm.widgetStyle(widget)">
<div class="tb-widget-title" layout="column" layout-align="center start" ng-show="vm.showWidgetTitlePanel(widget)">
<div ng-if="vm.hasWidgetTitleTemplate(widget)" ng-include="vm.widgetTitleTemplate(widget)"></div>
<span ng-show="vm.showWidgetTitle(widget)" ng-style="vm.widgetTitleStyle(widget)" class="md-subhead">{{vm.widgetTitle(widget)}}</span>

View File

@ -64,7 +64,7 @@ function WidgetConfig($compile, $templateCache, $rootScope, $translate, $timeout
'*'
];
scope.titleStyleEditorOptions = {
scope.styleEditorOptions = {
useWrapMode: true,
mode: 'json',
advanced: {
@ -106,6 +106,9 @@ function WidgetConfig($compile, $templateCache, $rootScope, $translate, $timeout
scope.backgroundColor = config.backgroundColor;
scope.color = config.color;
scope.padding = config.padding;
scope.margin = config.margin;
scope.widgetStyle =
angular.toJson(angular.isDefined(config.widgetStyle) ? config.widgetStyle : {}, true);
scope.titleStyle =
angular.toJson(angular.isDefined(config.titleStyle) ? config.titleStyle : {
fontSize: '16px',
@ -204,6 +207,12 @@ function WidgetConfig($compile, $templateCache, $rootScope, $translate, $timeout
valid = config && config.datasources && config.datasources.length > 0;
ngModelCtrl.$setValidity('datasources', valid);
}
try {
angular.fromJson(scope.widgetStyle);
ngModelCtrl.$setValidity('widgetStyle', true);
} catch (e) {
ngModelCtrl.$setValidity('widgetStyle', false);
}
try {
angular.fromJson(scope.titleStyle);
ngModelCtrl.$setValidity('titleStyle', true);
@ -215,7 +224,7 @@ function WidgetConfig($compile, $templateCache, $rootScope, $translate, $timeout
};
scope.$watch('title + showTitle + dropShadow + enableFullscreen + backgroundColor + color + ' +
'padding + titleStyle + mobileOrder + mobileHeight + units + decimals + useDashboardTimewindow + ' +
'padding + margin + widgetStyle + titleStyle + mobileOrder + mobileHeight + units + decimals + useDashboardTimewindow + ' +
'alarmSearchStatus + alarmsPollingInterval + showLegend', function () {
if (ngModelCtrl.$viewValue) {
var value = ngModelCtrl.$viewValue;
@ -228,6 +237,12 @@ function WidgetConfig($compile, $templateCache, $rootScope, $translate, $timeout
config.backgroundColor = scope.backgroundColor;
config.color = scope.color;
config.padding = scope.padding;
config.margin = scope.margin;
try {
config.widgetStyle = angular.fromJson(scope.widgetStyle);
} catch (e) {
config.widgetStyle = {};
}
try {
config.titleStyle = angular.fromJson(scope.titleStyle);
} catch (e) {

View File

@ -179,7 +179,7 @@
</md-input-container>
<div flex ng-show="showTitle">
<label translate>widget-config.title-style</label>
<div ui-ace="titleStyleEditorOptions" ng-model="titleStyle" ng-style="{ minHeight: '100px' }">
<div ui-ace="styleEditorOptions" ng-model="titleStyle" ng-style="{ minHeight: '100px' }">
</div>
</div>
</div>
@ -199,6 +199,11 @@
ng-model="enableFullscreen">{{ 'widget-config.enable-fullscreen' | translate }}
</md-checkbox>
</div>
<div flex>
<label translate>widget-config.widget-style</label>
<div ui-ace="styleEditorOptions" ng-model="widgetStyle" ng-style="{ minHeight: '100px' }">
</div>
</div>
</div>
<div layout='column' layout-align="center" layout-gt-sm='row' layout-align-gt-sm="start center">
<div flex
@ -227,6 +232,10 @@
<label translate>widget-config.padding</label>
<input ng-model="padding">
</md-input-container>
<md-input-container flex>
<label translate>widget-config.margin</label>
<input ng-model="margin">
</md-input-container>
</div>
<div layout='column' layout-align="center" layout-gt-sm='row' layout-align-gt-sm="start center">
<md-input-container flex>

View File

@ -69,6 +69,8 @@ export default function DashboardSettingsController($scope, $mdDialog, statesCon
vm.gridSettings.columns = vm.gridSettings.columns || 24;
vm.gridSettings.margins = vm.gridSettings.margins || [10, 10];
vm.gridSettings.autoFillHeight = angular.isDefined(vm.gridSettings.autoFillHeight) ? vm.gridSettings.autoFillHeight : false;
vm.gridSettings.mobileAutoFillHeight = angular.isDefined(vm.gridSettings.mobileAutoFillHeight) ? vm.gridSettings.mobileAutoFillHeight : false;
vm.gridSettings.mobileRowHeight = angular.isDefined(vm.gridSettings.mobileRowHeight) ? vm.gridSettings.mobileRowHeight : 70;
vm.hMargin = vm.gridSettings.margins[0];
vm.vMargin = vm.gridSettings.margins[1];
vm.gridSettings.backgroundSizeMode = vm.gridSettings.backgroundSizeMode || '100%';

View File

@ -171,6 +171,22 @@
<md-option value="auto">Original size</md-option>
</md-select>
</md-input-container>
<small translate>dashboard.mobile-layout</small>
<div flex layout="row" layout-align="start center">
<md-checkbox flex aria-label="{{ 'dashboard.autofill-height' | translate }}"
ng-model="vm.gridSettings.mobileAutoFillHeight">{{ 'dashboard.autofill-height' | translate }}
</md-checkbox>
<md-input-container flex class="md-block">
<label translate>dashboard.mobile-row-height</label>
<input ng-required="vm.gridSettings" type="number" step="any" name="mobileRowHeight" ng-model="vm.gridSettings.mobileRowHeight"
min="5" max="200" />
<div ng-messages="theForm.mobileRowHeight.$error" multiple md-auto-hide="false">
<div ng-message="required" translate>dashboard.mobile-row-height-required</div>
<div ng-message="min" translate>dashboard.min-mobile-row-height-message</div>
<div ng-message="max" translate>dashboard.max-mobile-row-height-message</div>
</div>
</md-input-container>
</div>
</div>
</fieldset>
</div>

View File

@ -50,6 +50,8 @@
dashboard-timewindow="vm.dashboardCtx.dashboardTimewindow"
is-edit="vm.isEdit"
autofill-height="vm.layoutCtx.gridSettings.autoFillHeight && !vm.isEdit"
mobile-autofill-height="vm.layoutCtx.gridSettings.mobileAutoFillHeight && !vm.isEdit"
mobile-row-height="vm.layoutCtx.gridSettings.mobileRowHeight"
is-mobile="vm.isMobile"
is-mobile-disabled="vm.widgetEditMode"
is-edit-action-enabled="vm.isEdit"

View File

@ -432,6 +432,11 @@ export default angular.module('thingsboard.locale', [])
"min-vertical-margin-message": "Only 0 is allowed as minimum vertical margin value.",
"max-vertical-margin-message": "Only 50 is allowed as maximum vertical margin value.",
"autofill-height": "Auto fill layout height",
"mobile-layout": "Mobile layout settings",
"mobile-row-height": "Mobile row height, px",
"mobile-row-height-required": "Mobile row height value is required.",
"min-mobile-row-height-message": "Only 5 pixels is allowed as minimum mobile row height value.",
"max-mobile-row-height-message": "Only 200 pixels is allowed as maximum mobile row height value.",
"display-title": "Display dashboard title",
"toolbar-always-open": "Keep toolbar opened",
"title-color": "Title color",
@ -1154,6 +1159,8 @@ export default angular.module('thingsboard.locale', [])
"background-color": "Background color",
"text-color": "Text color",
"padding": "Padding",
"margin": "Margin",
"widget-style": "Widget style",
"title-style": "Title style",
"mobile-mode-settings": "Mobile mode settings",
"order": "Order",