UI: Improved layout manage dialog (breakpoints table) and added new dialog add new breakpoint

This commit is contained in:
Vladyslav_Prykhodko 2024-08-09 18:37:54 +03:00
parent 38ecf3526b
commit 796e9c44ad
8 changed files with 260 additions and 220 deletions

View File

@ -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();
}

View File

@ -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.
-->
<mat-toolbar color="primary">
<h2 translate>layout.add-new-breakpoint</h2>
<span fxFlex></span>
<button mat-icon-button
(click)="cancel()"
type="button">
<mat-icon class="material-icons">close</mat-icon>
</button>
</mat-toolbar>
<div mat-dialog-content style="width: 400px">
<form [formGroup]="addBreakpointFormGroup">
<mat-form-field appearance="outline">
<mat-label translate>layout.breakpoint</mat-label>
<mat-select formControlName="newBreakpointId">
<mat-option *ngFor="let breakpoint of allowBreakpointIds" [value]="breakpoint">
{{ breakpoint }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="outline" subscriptSizing="dynamic">
<mat-label translate>layout.copy-from</mat-label>
<mat-select formControlName="copyFrom">
<mat-option *ngFor="let breakpoint of selectedBreakpointIds" [value]="breakpoint">
{{ breakpoint }}
</mat-option>
</mat-select>
</mat-form-field>
</form>
</div>
<div mat-dialog-actions fxLayoutAlign="end center">
<button mat-button
color="primary"
type="button"
(click)="cancel()">
{{ 'action.cancel' | translate }}
</button>
<button mat-raised-button color="primary"
type="button"
(click)="save()"
[disabled]="addBreakpointFormGroup.invalid">
{{ 'action.add' | translate }}
</button>
</div>

View File

@ -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<AddNewBreakpointDialogComponent, AddNewBreakpointDialogResult> {
addBreakpointFormGroup: FormGroup;
allowBreakpointIds = [];
selectedBreakpointIds = [];
constructor(protected store: Store<AppState>,
protected router: Router,
private fb: FormBuilder,
@Inject(MAT_DIALOG_DATA) private data: AddNewBreakpointDialogData,
protected dialogRef: MatDialogRef<AddNewBreakpointDialogComponent, AddNewBreakpointDialogResult>,) {
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());
}
}

View File

@ -36,155 +36,58 @@
</mat-select>
</mat-form-field>
</div>
<!-- <div fxLayout="row" fxLayoutAlign="start center">-->
<!-- <mat-slide-toggle formControlName="right" color="accent">-->
<!-- {{ 'layout.divider' | translate }}-->
<!-- </mat-slide-toggle>-->
<!-- </div>-->
<div *ngIf="!isDividerLayout; else dividerLayout" class="tb-form-panel no-padding no-border">
<!-- <div class="tb-form-table tb-layout-breakpoints">-->
<!-- <div class="tb-form-table-header">-->
<!-- <div class="tb-form-table-header-cell tb-icon-breakpoint"></div>-->
<!-- <div class="tb-form-table-header-cell tb-devices-header">Devices</div>-->
<!-- <div class="tb-form-table-header-cell tb-size-header">Size</div>-->
<!-- <div class="tb-form-table-header-cell tb-actions-header"></div>-->
<!-- </div>-->
<!-- <div class="tb-form-table-body">-->
<!-- <div class="tb-form-table-row">-->
<!-- <div class="tb-form-table-row-cell tb-icon-breakpoint"></div>-->
<!-- <div class="tb-form-table-row-cell tb-devices-header">Default</div>-->
<!-- <div class="tb-form-table-row-cell tb-size-header"></div>-->
<!-- <div class="tb-form-table-row-cell tb-actions-header">-->
<!-- <button mat-icon-button class="tb-mat-20"-->
<!-- (click)="openLayoutSettings('main')"-->
<!-- type="button" >-->
<!-- <mat-icon>settings</mat-icon>-->
<!-- </button>-->
<!-- </div>-->
<!-- </div>-->
<!-- <div class="tb-form-table-row">-->
<!-- <div class="tb-form-table-row-cell tb-icon-breakpoint"></div>-->
<!-- <div class="tb-form-table-row-cell tb-devices-header">Md</div>-->
<!-- <div class="tb-form-table-row-cell tb-size-header"></div>-->
<!-- <div class="tb-form-table-row-cell tb-actions-header">-->
<!-- <button mat-icon-button class="tb-mat-20"-->
<!-- (click)="openLayoutSettings('main')"-->
<!-- type="button" >-->
<!-- <mat-icon>settings</mat-icon>-->
<!-- </button>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<div class="table-container" style="width: 600px">
<table mat-table [dataSource]="dataSource">
<ng-container [matColumnDef]="'icon'">
<mat-header-cell *matHeaderCellDef [style]="{ minWidth: '48px', maxWidth: '48px', width: '48px', textAlign: 'center'}">
</mat-header-cell>
<mat-cell *matCellDef="let breakpoint" [style]="{ minWidth: '48px', maxWidth: '48px', width: '48px', textAlign: 'center'}">
<tb-icon>{{ breakpoint.icon }}</tb-icon>
</mat-cell>
</ng-container>
<ng-container [matColumnDef]="'name'">
<mat-header-cell *matHeaderCellDef style="width: 15%;min-width: 15%;max-width: 15%;padding-left:0">
Breakpoints
</mat-header-cell>
<mat-cell *matCellDef="let breakpoint" style="width: 15%;min-width: 15%;max-width: 15%;">
{{ breakpoint.name }}
</mat-cell>
</ng-container>
<ng-container [matColumnDef]="'descriptionSize'" style="width: 85%;min-width: 85%;max-width: 85%;">
<mat-header-cell *matHeaderCellDef>
Size
</mat-header-cell>
<mat-cell *matCellDef="let breakpoint" style="width: 85%;min-width: 85%;max-width: 85%;">
{{ breakpoint.descriptionSize }}
</mat-cell>
</ng-container>
<ng-container matColumnDef="actions" stickyEnd>
<mat-header-cell *matHeaderCellDef
[ngStyle.gt-md]="{ minWidth: '96px', maxWidth: '96px', width: '96px', textAlign: 'center'}">
</mat-header-cell>
<mat-cell *matCellDef="let breakpoint"
[ngStyle.gt-md]="{ minWidth: '96px', maxWidth: '96px', width: '96px'}">
<div fxHide fxShow.gt-md fxFlex fxLayout="row" fxLayoutAlign="end">
<div *ngIf="!isDividerLayout; else dividerLayout" class="tb-form-panel stroked" style="width: 500px">
<div class="tb-form-table tb-layout-breakpoints">
<div class="tb-form-table-header no-padding-right">
<div class="tb-form-table-header-cell tb-icon"></div>
<div class="tb-form-table-header-cell tb-breakpoint" translate>layout.breakpoints</div>
<div class="tb-form-table-header-cell tb-size" translate>layout.size</div>
<div class="tb-form-table-header-cell tb-actions"></div>
</div>
<div class="tb-form-table-body no-gap">
<ng-container *ngFor="let breakpoint of layoutBreakpoints; let last = last">
<div class="tb-form-table-row no-padding-right">
<div class="tb-form-table-row-cell tb-icon">
<tb-icon>{{ breakpoint.icon }}</tb-icon>
</div>
<div class="tb-form-table-row-cell tb-breakpoint">
{{ breakpoint.name }}
</div>
<div class="tb-form-table-row-cell tb-size">
{{ breakpoint.descriptionSize }}
</div>
<div class="tb-form-table-row-cell-buttons tb-actions">
<button mat-icon-button
matTooltip="{{ 'dashboard.layout-settings' | translate }}"
matTooltipPosition="above"
(click)="openLayoutSettings('main', breakpoint.breakpoint)"
type="button" >
<mat-icon>settings</mat-icon>
</button>
<button mat-icon-button
matTooltip="{{ 'action.delete' | translate }}"
matTooltipPosition="above"
[disabled]="breakpoint.breakpoint === 'default'"
(click)="deleteBreakpoint(breakpoint.breakpoint)"
[class.tb-hidden]="breakpoint.breakpoint === 'default'"
(click)="deleteBreakpoint($event, breakpoint.breakpoint)"
type="button" >
<tb-icon>delete</tb-icon>
</button>
</div>
<div fxHide fxShow.lt-lg fxFlex fxLayout="row" fxLayoutAlign="end">
<button mat-icon-button
(click)="$event.stopPropagation()"
[matMenuTriggerFor]="cellActionsMenu">
<mat-icon class="material-icons">more_vert</mat-icon>
</button>
<mat-menu #cellActionsMenu="matMenu" xPosition="before">
<button mat-icon-button
(click)="openLayoutSettings('main', breakpoint.breakpoint)"
type="button" >
<mat-icon>settings</mat-icon>
</button>
<button mat-icon-button
(click)="openLayoutSettings('main')"
type="button" >
<tb-icon>delete</tb-icon>-->
</button>
</mat-menu>
</div>
</mat-cell>
</div>
<mat-divider *ngIf="!last"></mat-divider>
</ng-container>
<mat-header-row class="mat-row-select" *matHeaderRowDef="['icon', 'name', 'descriptionSize', 'actions']; sticky: true"></mat-header-row>
<mat-row *matRowDef="let breakpoint; columns: ['icon', 'name', 'descriptionSize', 'actions']"></mat-row>
</table>
</div>
</div>
<button mat-button fxFlex class="tb-add-breakpoint-button"
matTooltip="Add breakpoint"
matTooltip="{{ 'layout.add-new-breakpoint' | translate }}"
matTooltipPosition="above"
color="primary"
type="button"
*ngIf="!addBreakpointMode"
[disabled]="!allowBreakpointIds.length"
(click)="addBreakpoint()">
<mat-icon>add</mat-icon>
</button>
<div *ngIf="addBreakpointMode" class="tb-form-row space-between column-lt-md" [formGroup]="addBreakpointFormGroup">
<div fxLayout="row" fxFlex.lt-md fxLayoutAlign="start center" fxLayoutGap="8px">
<div>Add breakpoint</div>
<mat-form-field fxFlex.lt-md appearance="outline" subscriptSizing="dynamic">
<mat-select formControlName="new">
<mat-option *ngFor="let breakpoint of allowBreakpointIds" [value]="breakpoint">
{{ breakpoint }}
</mat-option>
</mat-select>
</mat-form-field>
</div>
<div fxLayout="row" fxFlex.lt-md fxLayoutAlign="start center" fxLayoutGap="8px">
<div>Copy from</div>
<mat-form-field fxFlex.lt-md appearance="outline" subscriptSizing="dynamic">
<mat-select formControlName="copyFrom">
<mat-option *ngFor="let breakpoint of selectedBreakpointIds" [value]="breakpoint">
{{ breakpoint }}
</mat-option>
</mat-select>
</mat-form-field>
</div>
<div fxLayoutGap="8px">
<button mat-icon-button class="tb-mat-20"
type="button" (click)="createdBreakPoint()">
<tb-icon>check</tb-icon>
</button>
<button mat-icon-button class="tb-mat-20"
type="button" (click)="addBreakpoint()">
<tb-icon>close</tb-icon>
</button>
</div>
</div>
</div>
<ng-template #dividerLayout>
<div fxLayout="column" fxLayoutAlign="start center" fxLayoutGap="20px">

View File

@ -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;
}
}

View File

@ -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<Manag
@ViewChild('tooltip') tooltip: MatTooltip;
layoutsFormGroup: UntypedFormGroup;
addBreakpointFormGroup: UntypedFormGroup;
layoutWidthType = LayoutWidthType;
@ -90,19 +91,15 @@ export class ManageDashboardLayoutsDialogComponent extends DialogComponent<Manag
layoutTypes = layoutTypes;
layoutTypeTranslations = layoutTypeTranslationMap;
dataSource: DashboardLayoutDatasource;
addBreakpointMode = false;
private layoutBreakpoints: DashboardLayoutSettings[] = [];
layoutBreakpoints: DashboardLayoutSettings[] = [];
private readonly layouts: DashboardStateLayouts;
private subscriptions: Array<Subscription> = [];
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<Manag
@SkipSelf() private errorStateMatcher: ErrorStateMatcher,
protected dialogRef: MatDialogRef<ManageDashboardLayoutsDialogComponent, DashboardStateLayouts>,
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<Manag
}
);
this.addBreakpointFormGroup = this.fb.group({
new: [],
copyFrom: []
});
this.subscriptions.push(
this.layoutsFormGroup.get('type').valueChanges.subscribe(
(value) => {
@ -219,8 +210,6 @@ export class ManageDashboardLayoutsDialogComponent extends DialogComponent<Manag
this.allowBreakpointIds = Object.keys(this.breakpointsData)
.filter((item) => !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<Manag
return originalErrorState || customErrorState;
}
openLayoutSettings(layoutId: DashboardLayoutId, breakpoint?: string) {
let gridSettings;
if (isDefined(breakpoint) && breakpoint !== 'default') {
gridSettings = deepClone(this.layouts[layoutId].breakpoints[breakpoint].gridSettings);
} else {
gridSettings = deepClone(this.layouts[layoutId].gridSettings);
}
openLayoutSettings(layoutId: DashboardLayoutId, breakpointId = 'default') {
const layout = this.dashboardUtils.getDashboardLayoutConfig(this.layouts[layoutId], breakpointId);
const gridSettings = layout.gridSettings;
this.dialog.open<DashboardSettingsDialogComponent, DashboardSettingsDialogData,
DashboardSettingsDialogData>(DashboardSettingsDialogComponent, {
disableClose: true,
@ -290,7 +275,7 @@ export class ManageDashboardLayoutsDialogComponent extends DialogComponent<Manag
}
}).afterClosed().subscribe((data) => {
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<Manag
return this.layoutsFormGroup.get('layoutType').value === LayoutType.divider;
}
deleteBreakpoint(breakpointId: string): void {
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.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, AddNewBreakpointDialogData,
AddNewBreakpointDialogResult>(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<Manag
private createDescriptionSize(breakpointId: string): string {
const currentData = this.breakpointsData[breakpointId];
const minStr = isDefined(currentData.minWidth) ? `min-width: ${currentData.minWidth}px` : '';
const maxStr = isDefined(currentData.maxWidth) ? `min-width: ${currentData.maxWidth}px` : '';
return minStr && maxStr ? `${minStr} and ${maxStr}` : `${minStr}${maxStr}`;
}
}
export class DashboardLayoutDatasource extends TbTableDatasource<DashboardLayoutSettings> {
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}`;
}
}

View File

@ -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,

View File

@ -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",