UI: Dashboard layout improvements.
This commit is contained in:
parent
13a6c9a142
commit
f93dc9058f
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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%';
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user