Browse Source

UI: Improve dashboard layout settings.

pull/11391/head
Igor Kulikov 2 years ago
parent
commit
8fad8245df
  1. 44
      ui-ngx/patches/angular-gridster2+15.0.4.patch
  2. 69
      ui-ngx/src/app/core/services/dashboard-utils.service.ts
  3. 42
      ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts
  4. 2
      ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.models.ts
  5. 31
      ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-settings-dialog.component.html
  6. 16
      ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-settings-dialog.component.ts
  7. 4
      ui-ngx/src/app/modules/home/components/dashboard-page/layout/dashboard-layout.component.html
  8. 13
      ui-ngx/src/app/modules/home/components/dashboard-page/layout/dashboard-layout.component.ts
  9. 60
      ui-ngx/src/app/modules/home/components/dashboard-page/layout/move-widgets-dialog.component.html
  10. 62
      ui-ngx/src/app/modules/home/components/dashboard-page/layout/move-widgets-dialog.component.ts
  11. 66
      ui-ngx/src/app/modules/home/components/dashboard/dashboard.component.ts
  12. 3
      ui-ngx/src/app/modules/home/components/home-components.module.ts
  13. 1
      ui-ngx/src/app/shared/models/dashboard.models.ts
  14. 6
      ui-ngx/src/assets/locale/locale.constant-en_US.json

44
ui-ngx/patches/angular-gridster2+15.0.4.patch

@ -0,0 +1,44 @@
diff --git a/node_modules/angular-gridster2/fesm2020/angular-gridster2.mjs b/node_modules/angular-gridster2/fesm2020/angular-gridster2.mjs
index cf4e220..4275d11 100644
--- a/node_modules/angular-gridster2/fesm2020/angular-gridster2.mjs
+++ b/node_modules/angular-gridster2/fesm2020/angular-gridster2.mjs
@@ -208,6 +208,7 @@ const GridsterConfigService = {
useTransformPositioning: true,
scrollSensitivity: 10,
scrollSpeed: 20,
+ colWidthUpdateCallback: undefined,
initCallback: undefined,
destroyCallback: undefined,
gridSizeChangedCallback: undefined,
@@ -1243,6 +1244,9 @@ class GridsterComponent {
this.renderer.setStyle(this.el, 'padding-right', this.$options.margin + 'px');
}
this.curColWidth = (this.curWidth - marginWidth) / this.columns;
+ if (this.options.colWidthUpdateCallback) {
+ this.curColWidth = this.options.colWidthUpdateCallback(this.curColWidth);
+ }
let marginHeight = -this.$options.margin;
if (this.$options.outerMarginTop !== null) {
marginHeight += this.$options.outerMarginTop;
@@ -1266,6 +1270,9 @@ class GridsterComponent {
}
else {
this.curColWidth = (this.curWidth + this.$options.margin) / this.columns;
+ if (this.options.colWidthUpdateCallback) {
+ this.curColWidth = this.options.colWidthUpdateCallback(this.curColWidth);
+ }
this.curRowHeight =
((this.curHeight + this.$options.margin) / this.rows) *
this.$options.rowHeightRatio;
diff --git a/node_modules/angular-gridster2/lib/gridsterConfig.interface.d.ts b/node_modules/angular-gridster2/lib/gridsterConfig.interface.d.ts
index 1d7cdf0..a712b35 100644
--- a/node_modules/angular-gridster2/lib/gridsterConfig.interface.d.ts
+++ b/node_modules/angular-gridster2/lib/gridsterConfig.interface.d.ts
@@ -73,6 +73,7 @@ export interface GridsterConfig {
useTransformPositioning?: boolean;
scrollSensitivity?: number | null;
scrollSpeed?: number;
+ colWidthUpdateCallback?: (colWidth: number) => number;
initCallback?: (gridster: GridsterComponentInterface) => void;
destroyCallback?: (gridster: GridsterComponentInterface) => void;
gridSizeChangedCallback?: (gridster: GridsterComponentInterface) => void;

69
ui-ngx/src/app/core/services/dashboard-utils.service.ts

@ -610,17 +610,15 @@ export class DashboardUtilsService {
originalColumns = 24;
}
const gridSettings = layout.gridSettings;
if (!gridSettings.isScada) {
let columns = 24;
if (gridSettings && gridSettings.columns) {
columns = gridSettings.columns;
}
columns = columns * layoutCount;
if (columns !== originalColumns) {
const ratio = columns / originalColumns;
widgetLayout.sizeX *= ratio;
widgetLayout.sizeY *= ratio;
}
let columns = 24;
if (gridSettings && gridSettings.columns) {
columns = gridSettings.columns;
}
columns = columns * layoutCount;
if (columns !== originalColumns) {
const ratio = columns / originalColumns;
widgetLayout.sizeX *= ratio;
widgetLayout.sizeY *= ratio;
}
if (row > -1 && column > - 1) {
@ -686,35 +684,32 @@ export class DashboardUtilsService {
const columns = gridSettings.columns || 24;
const ratio = columns / prevColumns;
layout.gridSettings = gridSettings;
if (!gridSettings.isScada) {
let maxRow = 0;
for (const w of Object.keys(layout.widgets)) {
const widget = layout.widgets[w];
if (!widget.sizeX) {
widget.sizeX = 1;
}
if (!widget.sizeY) {
widget.sizeY = 1;
}
maxRow = Math.max(maxRow, widget.row + widget.sizeY);
for (const w of Object.keys(layout.widgets)) {
const widget = layout.widgets[w];
if (!widget.sizeX) {
widget.sizeX = 1;
}
const newMaxRow = Math.round(maxRow * ratio);
for (const w of Object.keys(layout.widgets)) {
const widget = layout.widgets[w];
if (widget.row + widget.sizeY === maxRow) {
widget.row = Math.round(widget.row * ratio);
widget.sizeY = newMaxRow - widget.row;
} else {
widget.row = Math.round(widget.row * ratio);
widget.sizeY = Math.round(widget.sizeY * ratio);
}
widget.sizeX = Math.round(widget.sizeX * ratio);
widget.col = Math.round(widget.col * ratio);
if (widget.col + widget.sizeX > columns) {
widget.sizeX = columns - widget.col;
}
if (!widget.sizeY) {
widget.sizeY = 1;
}
}
for (const w of Object.keys(layout.widgets)) {
const widget = layout.widgets[w];
widget.row = Math.round(widget.row * ratio);
widget.col = Math.round(widget.col * ratio);
widget.sizeX = Math.round(widget.sizeX * ratio);
widget.sizeY = Math.round(widget.sizeY * ratio);
}
}
public moveWidgets(layout: DashboardLayout, cols: number, rows: number) {
cols = isDefinedAndNotNull(cols) ? Math.round(cols) : 0;
rows = isDefinedAndNotNull(rows) ? Math.round(rows) : 0;
for (const w of Object.keys(layout.widgets)) {
const widget = layout.widgets[w];
widget.col = Math.max(0, widget.col + cols);
widget.row = Math.max(0, widget.row + rows);
}
}
public removeUnusedWidgets(dashboard: Dashboard) {

42
ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts

@ -150,6 +150,10 @@ import { LayoutFixedSize, LayoutWidthType } from '@home/components/dashboard-pag
import { TbPopoverComponent } from '@shared/components/popover.component';
import { ResizeObserver } from '@juggle/resize-observer';
import { HasDirtyFlag } from '@core/guards/confirm-on-exit.guard';
import {
MoveWidgetsDialogComponent,
MoveWidgetsDialogResult
} from '@home/components/dashboard-page/layout/move-widgets-dialog.component';
// @dynamic
@Component({
@ -285,7 +289,8 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
gridSettings: {},
ignoreLoading: true,
ctrl: null,
dashboardCtrl: this
dashboardCtrl: this,
displayGrid: 'onDrag&Resize'
}
},
right: {
@ -297,7 +302,8 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
gridSettings: {},
ignoreLoading: true,
ctrl: null,
dashboardCtrl: this
dashboardCtrl: this,
displayGrid: 'onDrag&Resize'
}
}
};
@ -913,6 +919,28 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
});
}
private moveWidgets($event: Event, layoutId: DashboardLayoutId) {
if ($event) {
$event.stopPropagation();
}
this.layouts[layoutId].layoutCtx.displayGrid = 'always';
this.cd.markForCheck();
this.dialog.open<MoveWidgetsDialogComponent, any,
MoveWidgetsDialogResult>(MoveWidgetsDialogComponent, {
disableClose: true,
panelClass: ['tb-dialog', 'tb-fullscreen-dialog']
}).afterClosed().subscribe((result) => {
this.layouts[layoutId].layoutCtx.displayGrid = 'onDrag&Resize';
if (result) {
const targetLayout = this.dashboardConfiguration.states[this.dashboardCtx.state].layouts[layoutId];
this.dashboardUtils.moveWidgets(targetLayout, result.cols, result.rows);
this.updateLayouts();
} else {
this.cd.markForCheck();
}
});
}
private updateDashboardLayouts(newLayouts: DashboardStateLayouts) {
this.dashboardUtils.setLayouts(this.dashboard, this.dashboardCtx.state, newLayouts);
this.updateLayouts();
@ -1422,6 +1450,16 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
shortcut: 'M-I'
}
);
dashboardContextActions.push(
{
action: ($event) => {
this.moveWidgets($event, layoutCtx.id);
},
enabled: true,
value: 'dashboard.move-all-widgets',
icon: 'open_with'
}
);
}
return dashboardContextActions;
}

2
ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.models.ts

@ -21,6 +21,7 @@ import { IAliasController, IStateController } from '@core/api/widget-api.models'
import { ILayoutController } from './layout/layout.models';
import { DashboardContextMenuItem, WidgetContextMenuItem } from '@home/models/dashboard-component.models';
import { Observable } from 'rxjs';
import { displayGrids } from 'angular-gridster2/lib/gridsterConfig.interface';
export declare type DashboardPageScope = 'tenant' | 'customer';
@ -69,6 +70,7 @@ export interface DashboardPageLayoutContext {
ctrl: ILayoutController;
dashboardCtrl: IDashboardController;
ignoreLoading: boolean;
displayGrid: displayGrids;
}
export interface DashboardPageLayout {

31
ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-settings-dialog.component.html

@ -114,8 +114,9 @@
<div class="tb-form-panel-title" translate>dashboard.layout-settings</div>
<div class="tb-form-row space-between">
<div translate>dashboard.columns-count</div>
<mat-form-field appearance="outline" class="number medium-width tb-suffix-absolute" subscriptSizing="dynamic">
<input matInput formControlName="columns" type="number" min="10" max="1000" step="1"
<mat-form-field *ngIf="!gridSettingsFormGroup.get('isScada').value"
appearance="outline" class="number medium-width tb-suffix-absolute" subscriptSizing="dynamic">
<input matInput formControlName="columns" type="number" min="10" max="1008" step="1"
required
placeholder="{{ 'widget-config.set' | translate }}">
<mat-icon matSuffix
@ -128,6 +129,32 @@
warning
</mat-icon>
</mat-form-field>
<mat-form-field *ngIf="gridSettingsFormGroup.get('isScada').value"
class="medium-width" appearance="outline" subscriptSizing="dynamic">
<mat-select required formControlName="columns">
<mat-option *ngFor="let columns of scadaColumns" [value]="columns">
{{ columns }}
</mat-option>
</mat-select>
</mat-form-field>
</div>
<div class="tb-form-row space-between">
<div translate>dashboard.min-layout-width</div>
<mat-form-field appearance="outline" class="number medium-width tb-suffix-absolute" subscriptSizing="dynamic">
<input matInput formControlName="minColumns" type="number" min="10" max="1008" step="1"
required
placeholder="{{ 'widget-config.set' | translate }}">
<mat-icon matSuffix
matTooltipPosition="above"
matTooltipClass="tb-error-tooltip"
[matTooltip]="(gridSettingsFormGroup.get('columns').hasError('required') ? 'dashboard.columns-count-required' :
(gridSettingsFormGroup.get('columns').hasError('min') ? 'dashboard.min-columns-count-message' : 'dashboard.max-columns-count-message')) | translate"
*ngIf="gridSettingsFormGroup.get('minColumns').invalid && gridSettingsFormGroup.get('minColumns').touched"
class="tb-error">
warning
</mat-icon>
<span translate matSuffix>dashboard.columns-suffix</span>
</mat-form-field>
</div>
<div *ngIf="!gridSettingsFormGroup.get('isScada').value" class="tb-form-row space-between">
<div translate>dashboard.widgets-margins</div>

16
ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-settings-dialog.component.ts

@ -54,6 +54,8 @@ export class DashboardSettingsDialogComponent extends DialogComponent<DashboardS
submitted = false;
scadaColumns: number[] = [];
private stateControllerTranslationMap = new Map<string, string>([
['default', 'dashboard.state-controller-default'],
]);
@ -155,10 +157,17 @@ export class DashboardSettingsDialogComponent extends DialogComponent<DashboardS
}
if (this.gridSettings) {
let columns = 24;
while (columns <= 1008) {
this.scadaColumns.push(columns);
columns += 24;
}
const mobileAutoFillHeight = isUndefined(this.gridSettings.mobileAutoFillHeight) ? false : this.gridSettings.mobileAutoFillHeight;
this.gridSettingsFormGroup = this.fb.group({
isScada: [this.gridSettings.isScada, []],
columns: [this.gridSettings.columns || 24, [Validators.required, Validators.min(10), Validators.max(1000)]],
columns: [this.gridSettings.columns || 24, [Validators.required, Validators.min(10), Validators.max(1008)]],
minColumns: [this.gridSettings.minColumns || this.gridSettings.columns || 24,
[Validators.required, Validators.min(10), Validators.max(1008)]],
margin: [isDefined(this.gridSettings.margin) ? this.gridSettings.margin : 10,
[Validators.required, Validators.min(0), Validators.max(50)]],
outerMargin: [isUndefined(this.gridSettings.outerMargin) ? true : this.gridSettings.outerMargin, []],
@ -228,6 +237,11 @@ export class DashboardSettingsDialogComponent extends DialogComponent<DashboardS
this.gridSettingsFormGroup.get('autoFillHeight').disable();
this.gridSettingsFormGroup.get('mobileAutoFillHeight').disable({emitEvent: false});
this.gridSettingsFormGroup.get('mobileRowHeight').disable();
const columns: number = this.gridSettingsFormGroup.get('columns').value;
if (columns % 24 !== 0) {
const newColumns = Math.min(1008, 24 * Math.ceil(columns / 24));
this.gridSettingsFormGroup.get('columns').patchValue(newColumns);
}
} else {
this.gridSettingsFormGroup.get('margin').enable();
this.gridSettingsFormGroup.get('outerMargin').enable();

4
ui-ngx/src/app/modules/home/components/dashboard-page/layout/dashboard-layout.component.html

@ -41,7 +41,9 @@
[backgroundImage]="backgroundImage$ | async"
[widgets]="layoutCtx.widgets"
[widgetLayouts]="layoutCtx.widgetLayouts"
[columns]="layoutCtx.gridSettings.columns"
[columns]="columns"
[displayGrid]="displayGrid"
[colWidthInteger]="colWidthInteger"
[outerMargin]="outerMargin"
[margin]="margin"
[aliasController]="dashboardCtx.aliasController"

13
ui-ngx/src/app/modules/home/components/dashboard-page/layout/dashboard-layout.component.ts

@ -36,6 +36,7 @@ import { TbCheatSheetComponent } from '@shared/components/cheatsheet.component';
import { TbPopoverComponent } from '@shared/components/popover.component';
import { ImagePipe } from '@shared/pipe/image.pipe';
import { map } from 'rxjs/operators';
import { displayGrids } from 'angular-gridster2/lib/gridsterConfig.interface';
@Component({
selector: 'tb-dashboard-layout',
@ -86,6 +87,18 @@ export class DashboardLayoutComponent extends PageComponent implements ILayoutCo
return this.widgetEditMode || this.layoutCtx.gridSettings.isScada;
}
get colWidthInteger(): boolean {
return this.layoutCtx.gridSettings.isScada;
}
get columns(): number {
return this.layoutCtx.gridSettings.minColumns || this.layoutCtx.gridSettings.columns || 24;
}
get displayGrid(): displayGrids {
return this.layoutCtx.displayGrid || 'onDrag&Resize';
}
@Input()
dashboardCtx: DashboardContext;

60
ui-ngx/src/app/modules/home/components/dashboard-page/layout/move-widgets-dialog.component.html

@ -0,0 +1,60 @@
<!--
Copyright © 2016-2024 The Thingsboard Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<form (ngSubmit)="move()">
<mat-toolbar color="primary">
<h2 translate>dashboard.move-all-widgets</h2>
<span fxFlex></span>
<button mat-icon-button
(click)="cancel()"
type="button">
<mat-icon class="material-icons">close</mat-icon>
</button>
</mat-toolbar>
<mat-progress-bar color="warn" mode="indeterminate" *ngIf="isLoading$ | async">
</mat-progress-bar>
<div mat-dialog-content class="tb-form-panel no-border no-padding" [formGroup]="moveWidgetsFormGroup">
<div class="tb-form-row space-between column-xs">
<div translate>dashboard.move-by</div>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px">
<mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
<input required matInput formControlName="cols"
type="number" step="1" placeholder="{{ 'widget-config.set' | translate }}">
<span translate matSuffix>dashboard.cols</span>
</mat-form-field>
<mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
<input required matInput formControlName="rows"
type="number" step="1" placeholder="{{ 'widget-config.set' | translate }}">
<span translate matSuffix>dashboard.rows</span>
</mat-form-field>
</div>
</div>
</div>
<div mat-dialog-actions fxLayoutAlign="end center">
<button mat-button color="primary"
type="button"
[disabled]="(isLoading$ | async)"
(click)="cancel()" cdkFocusInitial>
{{ 'action.cancel' | translate }}
</button>
<button mat-raised-button color="primary"
type="submit"
[disabled]="(isLoading$ | async) || moveWidgetsFormGroup.invalid || !moveWidgetsFormGroup.dirty">
{{ 'action.move' | translate }}
</button>
</div>
</form>

62
ui-ngx/src/app/modules/home/components/dashboard-page/layout/move-widgets-dialog.component.ts

@ -0,0 +1,62 @@
///
/// Copyright © 2016-2024 The Thingsboard Authors
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
import { Component } from '@angular/core';
import { MatDialog, MatDialogRef } from '@angular/material/dialog';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { DialogComponent } from '@app/shared/components/dialog.component';
export interface MoveWidgetsDialogResult {
cols: number;
rows: number;
}
@Component({
selector: 'tb-move-widgets-dialog',
templateUrl: './move-widgets-dialog.component.html',
providers: [],
styleUrls: []
})
export class MoveWidgetsDialogComponent extends DialogComponent<MoveWidgetsDialogComponent, MoveWidgetsDialogResult> {
moveWidgetsFormGroup: UntypedFormGroup;
constructor(protected store: Store<AppState>,
protected router: Router,
protected dialogRef: MatDialogRef<MoveWidgetsDialogComponent, MoveWidgetsDialogResult>,
private fb: UntypedFormBuilder,
private dialog: MatDialog) {
super(store, router, dialogRef);
this.moveWidgetsFormGroup = this.fb.group({
cols: [0, [Validators.required]],
rows: [0, [Validators.required]]
}
);
}
cancel(): void {
this.dialogRef.close(null);
}
move(): void {
const result: MoveWidgetsDialogResult = this.moveWidgetsFormGroup.value;
this.dialogRef.close(result);
}
}

66
ui-ngx/src/app/modules/home/components/dashboard/dashboard.component.ts

@ -90,6 +90,10 @@ export class DashboardComponent extends PageComponent implements IDashboardCompo
@Input()
columns: number;
@Input()
@coerceBoolean()
colWidthInteger = false;
@Input()
@coerceBoolean()
setGridSize = false;
@ -256,15 +260,22 @@ export class DashboardComponent extends PageComponent implements IDashboardCompo
itemChangeCallback: item => this.dashboardWidgets.sortWidgets(),
itemInitCallback: (item, itemComponent) => {
(itemComponent.item as DashboardWidget).gridsterItemComponent = itemComponent;
},
colWidthUpdateCallback: (colWidth) => {
if (this.colWidthInteger) {
return Math.floor(colWidth);
} else {
return colWidth;
}
}
};
this.updateMobileOpts();
this.updateGridOpts();
this.breakpointObserverSubscription = this.breakpointObserver
.observe(MediaBreakpoints['gt-sm']).subscribe(
() => {
this.updateMobileOpts();
this.updateGridOpts();
this.notifyGridsterOptionsChanged();
}
);
@ -291,20 +302,24 @@ export class DashboardComponent extends PageComponent implements IDashboardCompo
}
ngOnChanges(changes: SimpleChanges): void {
let updateMobileOpts = false;
let updateLayoutOpts = false;
let updateGridOpts = false;
let updateColumnOpts = false;
let updateEditingOpts = false;
let updateDisplayGridOpts = false;
let updateWidgets = false;
let updateDashboardTimewindow = false;
for (const propName of Object.keys(changes)) {
const change = changes[propName];
if (!change.firstChange && change.currentValue !== change.previousValue) {
if (['isMobile', 'isMobileDisabled', 'autofillHeight', 'mobileAutofillHeight', 'mobileRowHeight'].includes(propName)) {
updateMobileOpts = true;
if (['isMobile', 'isMobileDisabled', 'autofillHeight', 'mobileAutofillHeight',
'mobileRowHeight', 'colWidthInteger'].includes(propName)) {
updateGridOpts = true;
} else if (['outerMargin', 'margin', 'columns'].includes(propName)) {
updateLayoutOpts = true;
updateColumnOpts = true;
} else if (['isEdit', 'isEditingWidget'].includes(propName)) {
updateEditingOpts = true;
} else if (propName === 'displayGrid') {
updateDisplayGridOpts = true;
} else if (['widgets', 'widgetLayouts'].includes(propName)) {
updateWidgets = true;
} else if (propName === 'dashboardTimewindow') {
@ -318,16 +333,19 @@ export class DashboardComponent extends PageComponent implements IDashboardCompo
this.dashboardTimewindowChangedSubject.next(this.dashboardTimewindow);
}
if (updateLayoutOpts) {
this.updateLayoutOpts();
if (updateColumnOpts) {
this.updateColumnOpts();
}
if (updateMobileOpts) {
this.updateMobileOpts();
if (updateGridOpts) {
this.updateGridOpts();
}
if (updateEditingOpts) {
this.updateEditingOpts();
}
if (updateMobileOpts || updateLayoutOpts || updateEditingOpts) {
if (updateDisplayGridOpts) {
this.updateDisplayGridOpts();
}
if (updateGridOpts || updateColumnOpts || updateEditingOpts || updateDisplayGridOpts) {
this.notifyGridsterOptionsChanged();
}
}
@ -544,7 +562,15 @@ export class DashboardComponent extends PageComponent implements IDashboardCompo
});
}
private updateMobileOpts(parentHeight?: number) {
private onGridsterParentResize() {
const parentHeight = this.gridster.el.offsetHeight;
if (this.isMobileSize && this.mobileAutofillHeight && parentHeight) {
this.updateGridOpts(parentHeight);
}
this.notifyGridsterOptionsChanged();
}
private updateGridOpts(parentHeight?: number) {
let updateWidgetRowsAndSort = false;
const isMobileSize = this.checkIsMobileSize();
if (this.isMobileSize !== isMobileSize) {
@ -568,15 +594,7 @@ export class DashboardComponent extends PageComponent implements IDashboardCompo
}
}
private onGridsterParentResize() {
const parentHeight = this.gridster.el.offsetHeight;
if (this.isMobileSize && this.mobileAutofillHeight && parentHeight) {
this.updateMobileOpts(parentHeight);
}
this.notifyGridsterOptionsChanged();
}
private updateLayoutOpts() {
private updateColumnOpts() {
this.gridsterOpts.minCols = this.columns ? this.columns : 24;
this.gridsterOpts.outerMargin = isDefined(this.outerMargin) ? this.outerMargin : true;
this.gridsterOpts.margin = isDefined(this.margin) ? this.margin : 10;
@ -587,6 +605,10 @@ export class DashboardComponent extends PageComponent implements IDashboardCompo
this.gridsterOpts.draggable.enabled = this.isEdit && !this.isEditingWidget;
}
private updateDisplayGridOpts() {
this.gridsterOpts.displayGrid = this.displayGrid;
}
public notifyGridsterOptionsChanged() {
if (!this.optionsChangeNotificationsPaused) {
if (this.gridster && this.gridster.options) {

3
ui-ngx/src/app/modules/home/components/home-components.module.ts

@ -174,6 +174,7 @@ import {
import { WidgetConfigComponentsModule } from '@home/components/widget/config/widget-config-components.module';
import { BasicWidgetConfigModule } from '@home/components/widget/config/basic/basic-widget-config.module';
import { DeleteTimeseriesPanelComponent } from '@home/components/attribute/delete-timeseries-panel.component';
import { MoveWidgetsDialogComponent } from '@home/components/dashboard-page/layout/move-widgets-dialog.component';
@NgModule({
declarations:
@ -287,6 +288,7 @@ import { DeleteTimeseriesPanelComponent } from '@home/components/attribute/delet
EditWidgetComponent,
DashboardWidgetSelectComponent,
AddWidgetDialogComponent,
MoveWidgetsDialogComponent,
ManageDashboardLayoutsDialogComponent,
DashboardSettingsDialogComponent,
ManageDashboardStatesDialogComponent,
@ -419,6 +421,7 @@ import { DeleteTimeseriesPanelComponent } from '@home/components/attribute/delet
EditWidgetComponent,
DashboardWidgetSelectComponent,
AddWidgetDialogComponent,
MoveWidgetsDialogComponent,
ManageDashboardLayoutsDialogComponent,
DashboardSettingsDialogComponent,
ManageDashboardStatesDialogComponent,

1
ui-ngx/src/app/shared/models/dashboard.models.ts

@ -52,6 +52,7 @@ export interface WidgetLayouts {
export interface GridSettings {
backgroundColor?: string;
columns?: number;
minColumns?: number;
margin?: number;
outerMargin?: boolean;
backgroundSizeMode?: string;

6
ui-ngx/src/assets/locale/locale.constant-en_US.json

@ -1163,12 +1163,18 @@
"maximum-upload-file-size": "Maximum upload file size: {{ size }}",
"cannot-upload-file": "Cannot upload file",
"settings": "Settings",
"move-all-widgets": "Move all widgets",
"move-by": "Move by",
"cols": "cols",
"rows": "rows",
"scada-layout": "SCADA layout",
"layout-settings": "Layout settings",
"columns-count": "Columns count",
"columns-count-required": "Columns count is required.",
"min-columns-count-message": "Only 10 minimum column count is allowed.",
"max-columns-count-message": "Only 1000 maximum column count is allowed.",
"min-layout-width": "Minimum layout width",
"columns-suffix": "columns",
"widgets-margins": "Margin between widgets",
"margin-required": "Margin value is required.",
"min-margin-message": "Only 0 is allowed as minimum margin value.",

Loading…
Cancel
Save