From 796e9c44ad3bb25d86c16c74d20a0b62be2008b3 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Fri, 9 Aug 2024 18:37:54 +0300 Subject: [PATCH] UI: Improved layout manage dialog (breakpoints table) and added new dialog add new breakpoint --- .../dashboard-page.component.ts | 2 +- .../add-new-breakpoint-dialog.component.html | 60 +++++++ .../add-new-breakpoint-dialog.component.ts | 70 ++++++++ ...ge-dashboard-layouts-dialog.component.html | 163 ++++-------------- ...ge-dashboard-layouts-dialog.component.scss | 36 ++-- ...nage-dashboard-layouts-dialog.component.ts | 135 +++++++-------- .../home/components/home-components.module.ts | 5 + .../assets/locale/locale.constant-en_US.json | 9 +- 8 files changed, 260 insertions(+), 220 deletions(-) create mode 100644 ui-ngx/src/app/modules/home/components/dashboard-page/layout/add-new-breakpoint-dialog.component.html create mode 100644 ui-ngx/src/app/modules/home/components/dashboard-page/layout/add-new-breakpoint-dialog.component.ts diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts index ea837fb055..9b6471e3d2 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts @@ -1145,7 +1145,7 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC private updateLayout(layout: DashboardPageLayout, layoutInfo: DashboardLayoutInfo) { layout.layoutCtx.layoutData = layoutInfo; layout.layoutCtx.layoutDataChanged.next(); - layout.layoutCtx.ctrl?.updatedCurrentBreakpoint(null, layout.show); + layout.layoutCtx.ctrl?.updatedCurrentBreakpoint(this.isEdit ? layout.layoutCtx.breakpoint : null, layout.show); this.updateLayoutSizes(); } diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/layout/add-new-breakpoint-dialog.component.html b/ui-ngx/src/app/modules/home/components/dashboard-page/layout/add-new-breakpoint-dialog.component.html new file mode 100644 index 0000000000..f0d037de4e --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/layout/add-new-breakpoint-dialog.component.html @@ -0,0 +1,60 @@ + + +

layout.add-new-breakpoint

+ + +
+
+
+ + layout.breakpoint + + + {{ breakpoint }} + + + + + layout.copy-from + + + {{ breakpoint }} + + + +
+
+
+ + +
diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/layout/add-new-breakpoint-dialog.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/layout/add-new-breakpoint-dialog.component.ts new file mode 100644 index 0000000000..cdcbe4e2a5 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/layout/add-new-breakpoint-dialog.component.ts @@ -0,0 +1,70 @@ +/// +/// 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, Inject } from '@angular/core'; +import { DialogComponent } from '@shared/components/dialog.component'; +import { FormBuilder, FormGroup } from '@angular/forms'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/core.state'; +import { Router } from '@angular/router'; + +export interface AddNewBreakpointDialogData { + allowBreakpointIds: string[]; + selectedBreakpointIds: string[]; +} + +export interface AddNewBreakpointDialogResult { + newBreakpointId: string; + copyFrom: string; +} + +@Component({ + selector: 'add-new-breakpoint-dialog', + templateUrl: './add-new-breakpoint-dialog.component.html', +}) +export class AddNewBreakpointDialogComponent extends DialogComponent { + + addBreakpointFormGroup: FormGroup; + + allowBreakpointIds = []; + selectedBreakpointIds = []; + + constructor(protected store: Store, + protected router: Router, + private fb: FormBuilder, + @Inject(MAT_DIALOG_DATA) private data: AddNewBreakpointDialogData, + protected dialogRef: MatDialogRef,) { + + super(store, router, dialogRef); + + this.allowBreakpointIds = data.allowBreakpointIds; + this.selectedBreakpointIds = data.selectedBreakpointIds; + + this.addBreakpointFormGroup = this.fb.group({ + newBreakpointId: [{value: this.allowBreakpointIds[0], disabled: this.allowBreakpointIds.length === 1}], + copyFrom: [{value: 'default', disabled: this.selectedBreakpointIds.length === 1}], + }); + } + + cancel(): void { + this.dialogRef.close(null); + } + + save(): void { + this.dialogRef.close(this.addBreakpointFormGroup.getRawValue()); + } +} diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/layout/manage-dashboard-layouts-dialog.component.html b/ui-ngx/src/app/modules/home/components/dashboard-page/layout/manage-dashboard-layouts-dialog.component.html index 6d7313bf6c..84059b8b0c 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/layout/manage-dashboard-layouts-dialog.component.html +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/layout/manage-dashboard-layouts-dialog.component.html @@ -36,155 +36,58 @@ - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - {{ breakpoint.icon }} - - - - - Breakpoints - - - {{ breakpoint.name }} - - - - - Size - - - {{ breakpoint.descriptionSize }} - - - - - - -
+
+
+
+
+
layout.breakpoints
+
layout.size
+
+
+
+ +
+
+ {{ breakpoint.icon }} +
+
+ {{ breakpoint.name }} +
+
+ {{ breakpoint.descriptionSize }} +
+
-
- - - - - -
- +
+
- - -
+
-
-
-
Add breakpoint
- - - - {{ breakpoint }} - - - -
-
-
Copy from
- - - - {{ breakpoint }} - - - -
-
- - -
-
diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/layout/manage-dashboard-layouts-dialog.component.scss b/ui-ngx/src/app/modules/home/components/dashboard-page/layout/manage-dashboard-layouts-dialog.component.scss index cff90739ba..0b7219aea5 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/layout/manage-dashboard-layouts-dialog.component.scss +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/layout/manage-dashboard-layouts-dialog.component.scss @@ -125,27 +125,42 @@ $tb-warn: mat.get-color-from-palette(map-get($tb-theme, warn), text); .tb-layout-breakpoints { .tb-form-table-header-cell, .tb-form-table-row-cell { - &.tb-icon-breakpoint { - width: 48px; - min-width: 48px; + &.tb-icon { + width: 29px; + min-width: 29px; + max-width: 29px; + display: flex; + place-content: center; } - &.tb-devices-header, &.tb-size-header { - flex: 1; - min-width: 120px; + &.tb-breakpoint { + flex: 1 1 15%; + width: 15%; + min-width: 100px; } - &.tb-actions-header { - width: 80px; - min-width: 80px; + &.tb-size { + flex: 1 1 85%; + width: 85%; + min-width: 150px; + } + + &.tb-actions { + width: 96pxpx; + min-width: 96px; + max-width: 96px; display: flex; justify-content: end; } } + + .mat-divider { + margin-top: 6px; + margin-bottom: 6px; + } } .tb-add-breakpoint-button { - cursor: pointer; display: flex; flex-direction: column; justify-content: center; @@ -154,7 +169,6 @@ $tb-warn: mat.get-color-from-palette(map-get($tb-theme, warn), text); padding: 8px; border: 2px dashed rgba(0, 0, 0, 0.08); border-radius: 10px; - min-height: 56px; } } diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/layout/manage-dashboard-layouts-dialog.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/layout/manage-dashboard-layouts-dialog.component.ts index 11e81c332f..389a86f0da 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/layout/manage-dashboard-layouts-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/layout/manage-dashboard-layouts-dialog.component.ts @@ -30,7 +30,6 @@ import { } from '@angular/forms'; import { Router } from '@angular/router'; import { DialogComponent } from '@app/shared/components/dialog.component'; -import { UtilsService } from '@core/services/utils.service'; import { TranslateService } from '@ngx-translate/core'; import { BreakpointInfo, @@ -53,7 +52,10 @@ import { } from '@home/components/dashboard-page/layout/layout.models'; import { Subscription } from 'rxjs'; import { MatTooltip } from '@angular/material/tooltip'; -import { TbTableDatasource } from '@shared/components/table/table-datasource.abstract'; +import { + AddNewBreakpointDialogComponent, AddNewBreakpointDialogData, AddNewBreakpointDialogResult +} from '@home/components/dashboard-page/layout/add-new-breakpoint-dialog.component'; +import { DialogService } from '@core/services/dialog.service'; export interface ManageDashboardLayoutsDialogData { layouts: DashboardStateLayouts; @@ -79,7 +81,6 @@ export class ManageDashboardLayoutsDialogComponent extends DialogComponent = []; private submitted = false; - breakpoints: BreakpointInfo[]; - breakpointsData: {[breakpointId in string]: BreakpointInfo} = {}; + private breakpoints: BreakpointInfo[]; + private breakpointsData: {[breakpointId in string]: BreakpointInfo} = {}; allowBreakpointIds = []; selectedBreakpointIds = ['default']; @@ -113,14 +110,13 @@ export class ManageDashboardLayoutsDialogComponent extends DialogComponent, private fb: UntypedFormBuilder, - private utils: UtilsService, private dashboardUtils: DashboardUtilsService, private translate: TranslateService, - private dialog: MatDialog,) { + private dialog: MatDialog, + private dialogs: DialogService) { super(store, router, dialogRef); this.layouts = this.data.layouts; - this.dataSource = new DashboardLayoutDatasource(); this.breakpoints = this.dashboardUtils.getListBreakpoint(); this.breakpoints.forEach((breakpoint) => { @@ -150,11 +146,6 @@ export class ManageDashboardLayoutsDialogComponent extends DialogComponent { @@ -219,8 +210,6 @@ export class ManageDashboardLayoutsDialogComponent extends DialogComponent !this.selectedBreakpointIds.includes(item)); - this.dataSource.loadData(this.layoutBreakpoints); - this.subscriptions.push( this.layoutsFormGroup.get('sliderPercentage').valueChanges .subscribe( @@ -272,13 +261,9 @@ export class ManageDashboardLayoutsDialogComponent extends DialogComponent(DashboardSettingsDialogComponent, { disableClose: true, @@ -290,7 +275,7 @@ export class ManageDashboardLayoutsDialogComponent extends DialogComponent { if (data && data.gridSettings) { - this.dashboardUtils.updateLayoutSettings(this.layouts[layoutId], data.gridSettings); + this.dashboardUtils.updateLayoutSettings(layout, data.gridSettings); this.layoutsFormGroup.markAsDirty(); } }); @@ -438,51 +423,60 @@ export class ManageDashboardLayoutsDialogComponent extends DialogComponent item.breakpoint !== breakpointId); - this.allowBreakpointIds.push(breakpointId); - this.selectedBreakpointIds = this.selectedBreakpointIds.filter((item) => item !== breakpointId); - this.dataSource.loadData(this.layoutBreakpoints); - this.layoutsFormGroup.markAsDirty(); - } - addBreakpoint() { - this.addBreakpointMode = !this.addBreakpointMode; - if (this.addBreakpointMode) { - this.addBreakpointFormGroup.reset({ - new: this.allowBreakpointIds[0], - copyFrom: 'default' - }); - } + this.dialog.open(AddNewBreakpointDialogComponent, { + disableClose: true, + panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], + data: { + allowBreakpointIds: this.allowBreakpointIds, + selectedBreakpointIds: this.selectedBreakpointIds + } + }).afterClosed().subscribe((data) => { + if (data) { + this.createdNewBreakpoint(data.newBreakpointId, data.copyFrom); + this.layoutsFormGroup.markAsDirty(); + } + }); } - createdBreakPoint() { + deleteBreakpoint($event: Event, breakpointId: string): void { + if ($event) { + $event.stopPropagation(); + } + const title = this.translate.instant('layout.delete-breakpoint-title', {name: breakpointId}); + const content = this.translate.instant('layout.delete-breakpoint-text'); + this.dialogs.confirm(title, content, this.translate.instant('action.no'), + this.translate.instant('action.yes')).subscribe((res) => { + if (res) { + delete this.layouts.main.breakpoints[breakpointId]; + if (isEqual(this.layouts.main.breakpoints, {})) { + delete this.layouts.main.breakpoints; + } + this.layoutBreakpoints = this.layoutBreakpoints.filter((item) => item.breakpoint !== breakpointId); + this.allowBreakpointIds.push(breakpointId); + this.selectedBreakpointIds = this.selectedBreakpointIds.filter((item) => item !== breakpointId); + this.layoutsFormGroup.markAsDirty(); + } + } + ); + } + + private createdNewBreakpoint(newBreakpointId: string, copyFromBreakpointId: string): void { const layoutConfig = this.layouts.main; - const newBreakpoint = this.addBreakpointFormGroup.value.new; - const sourceBreakpoint = this.addBreakpointFormGroup.value.copyFrom; - const sourceLayout = sourceBreakpoint === 'default' ? layoutConfig : layoutConfig.breakpoints[sourceBreakpoint]; + const sourceLayout = copyFromBreakpointId === 'default' ? layoutConfig : layoutConfig.breakpoints[copyFromBreakpointId]; if (!layoutConfig.breakpoints) { layoutConfig.breakpoints = {}; } - layoutConfig.breakpoints[newBreakpoint] = { + layoutConfig.breakpoints[newBreakpointId] = { gridSettings: deepClone(sourceLayout.gridSettings), widgets: deepClone(sourceLayout.widgets), }; - this.selectedBreakpointIds.push(newBreakpoint); - this.allowBreakpointIds = this.allowBreakpointIds.filter((item) => item !== newBreakpoint); - this.addLayoutConfiguration(newBreakpoint); - - this.dataSource.loadData(this.layoutBreakpoints); - - this.addBreakpointMode = false; - - this.layoutsFormGroup.markAsDirty(); + this.selectedBreakpointIds.push(newBreakpointId); + this.allowBreakpointIds = this.allowBreakpointIds.filter((item) => item !== newBreakpointId); + this.addLayoutConfiguration(newBreakpointId); } private addLayoutConfiguration(breakpointId: string) { @@ -499,21 +493,8 @@ export class ManageDashboardLayoutsDialogComponent extends DialogComponent { - constructor() { - super(); - } - - connect() { - if (this.dataSubject.isStopped) { - this.dataSubject.isStopped = false; - } - return this.dataSubject.asObservable(); + const minStr = isDefined(currentData.minWidth) ? `min ${currentData.minWidth}px` : ''; + const maxStr = isDefined(currentData.maxWidth) ? `max ${currentData.maxWidth}px` : ''; + return minStr && maxStr ? `${minStr} - ${maxStr}` : `${minStr}${maxStr}`; } } diff --git a/ui-ngx/src/app/modules/home/components/home-components.module.ts b/ui-ngx/src/app/modules/home/components/home-components.module.ts index 94d58d767c..64d9e816bd 100644 --- a/ui-ngx/src/app/modules/home/components/home-components.module.ts +++ b/ui-ngx/src/app/modules/home/components/home-components.module.ts @@ -114,6 +114,9 @@ import { EditWidgetComponent } from '@home/components/dashboard-page/edit-widget import { DashboardWidgetSelectComponent } from '@home/components/dashboard-page/dashboard-widget-select.component'; import { AddWidgetDialogComponent } from '@home/components/dashboard-page/add-widget-dialog.component'; import { ManageDashboardLayoutsDialogComponent } from '@home/components/dashboard-page/layout/manage-dashboard-layouts-dialog.component'; +import { + AddNewBreakpointDialogComponent +} from '@home/components/dashboard-page/layout/add-new-breakpoint-dialog.component'; import { DashboardSettingsDialogComponent } from '@home/components/dashboard-page/dashboard-settings-dialog.component'; import { ManageDashboardStatesDialogComponent } from '@home/components/dashboard-page/states/manage-dashboard-states-dialog.component'; import { DashboardStateDialogComponent } from '@home/components/dashboard-page/states/dashboard-state-dialog.component'; @@ -294,6 +297,7 @@ import { AddWidgetDialogComponent, MoveWidgetsDialogComponent, ManageDashboardLayoutsDialogComponent, + AddNewBreakpointDialogComponent, DashboardSettingsDialogComponent, ManageDashboardStatesDialogComponent, DashboardStateDialogComponent, @@ -428,6 +432,7 @@ import { AddWidgetDialogComponent, MoveWidgetsDialogComponent, ManageDashboardLayoutsDialogComponent, + AddNewBreakpointDialogComponent, DashboardSettingsDialogComponent, ManageDashboardStatesDialogComponent, DashboardStateDialogComponent, diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index 54baf60aa2..7d1519126b 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -3778,7 +3778,14 @@ "left-width-percentage-required": "Left percentage is required", "divider": "Divider", "right-side": "Right side layout", - "left-side": "Left side layout" + "left-side": "Left side layout", + "add-new-breakpoint": "Add new breakpoint", + "breakpoint": "Breakpoint", + "breakpoints": "Breakpoints", + "copy-from": "Copy from", + "size": "Size", + "delete-breakpoint-title": "Are you sure you want to delete the breakpoint '{{name}}'?", + "delete-breakpoint-text": "Please note, after confirmation, the breakpoint will become unrecoverable, and the settings will revert to the default breakpoint." }, "legend": { "direction": "Direction",