Browse Source

UI: Fix/improve dashboard layouts. Add help links for SCADA.

pull/11644/head
Igor Kulikov 2 years ago
parent
commit
86c2f1bb16
  1. 6
      ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts
  2. 172
      ui-ngx/src/app/modules/home/models/dashboard-component.models.ts
  3. 1
      ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol.component.html
  4. 9
      ui-ngx/src/app/shared/components/image/image-gallery.component.html
  5. 5
      ui-ngx/src/app/shared/components/image/image-gallery.component.scss
  6. 6
      ui-ngx/src/app/shared/models/constants.ts

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

@ -437,15 +437,15 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
).pipe( ).pipe(
map(value => this.parseBreakpointsResponse(value.breakpoints)), map(value => this.parseBreakpointsResponse(value.breakpoints)),
tap((value) => { tap((value) => {
this.dashboardCtx.breakpoint = value.id; this.dashboardCtx.breakpoint = value ? value.id : 'default';
this.changeMobileSize.next(this.isMobileSize(value)); this.changeMobileSize.next(value ? this.isMobileSize(value) : false);
}), }),
distinctUntilChanged((_, next) => { distinctUntilChanged((_, next) => {
if (this.layouts.right.show || this.isEdit) { if (this.layouts.right.show || this.isEdit) {
return true; return true;
} }
let nextBreakpointConfiguration: BreakpointId = 'default'; let nextBreakpointConfiguration: BreakpointId = 'default';
if (!!this.layouts.main.layoutCtx.layoutData?.[next.id]) { if (next && !!this.layouts.main.layoutCtx.layoutData?.[next.id]) {
nextBreakpointConfiguration = next.id; nextBreakpointConfiguration = next.id;
} }
return this.layouts.main.layoutCtx.breakpoint === nextBreakpointConfiguration; return this.layouts.main.layoutCtx.breakpoint === nextBreakpointConfiguration;

172
ui-ngx/src/app/modules/home/models/dashboard-component.models.ts

@ -204,8 +204,7 @@ export class DashboardWidgets implements Iterable<DashboardWidget> {
index = this.dashboardWidgets.findIndex((dashboardWidget) => dashboardWidget.widgetId === record.widgetId); index = this.dashboardWidgets.findIndex((dashboardWidget) => dashboardWidget.widgetId === record.widgetId);
if (index > -1) { if (index > -1) {
const prevDashboardWidget = this.dashboardWidgets[index]; const prevDashboardWidget = this.dashboardWidgets[index];
if (!isEqual(prevDashboardWidget.widget, record.widget) || if (!isEqual(prevDashboardWidget.widget, record.widget)) {
!isEqual(prevDashboardWidget.widgetLayout, record.widgetLayout)) {
this.dashboardWidgets[index] = new DashboardWidget(this.dashboard, record.widget, record.widgetLayout, this.dashboardWidgets[index] = new DashboardWidget(this.dashboard, record.widget, record.widgetLayout,
this.parentDashboard, this.popoverComponent); this.parentDashboard, this.popoverComponent);
this.dashboardWidgets[index].highlighted = prevDashboardWidget.highlighted; this.dashboardWidgets[index].highlighted = prevDashboardWidget.highlighted;
@ -391,7 +390,7 @@ export class DashboardWidget implements GridsterItem, IDashboardWidget {
private gridsterItemComponentSubject = new Subject<GridsterItemComponentInterface>(); private gridsterItemComponentSubject = new Subject<GridsterItemComponentInterface>();
private gridsterItemComponentValue: GridsterItemComponentInterface; private gridsterItemComponentValue: GridsterItemComponentInterface;
private readonly aspectRatio: number; private aspectRatio: number;
private heightValue: number; private heightValue: number;
private widthValue: number; private widthValue: number;
@ -419,85 +418,97 @@ export class DashboardWidget implements GridsterItem, IDashboardWidget {
this.gridsterItemComponentSubject.complete(); this.gridsterItemComponentSubject.complete();
} }
private preserveAspectRatioApplied = false;
private applyPreserveAspectRatio(item: GridsterItemComponentInterface) { private applyPreserveAspectRatio(item: GridsterItemComponentInterface) {
this.resizableHandles.ne = false;
this.resizableHandles.sw = false;
this.resizableHandles.nw = false;
const $item = item.$item; if (this.widgetLayout?.preserveAspectRatio) {
this.resizableHandles.ne = false;
this.resizableHandles.sw = false;
this.resizableHandles.nw = false;
} else {
this.resizableHandles.ne = true;
this.resizableHandles.sw = true;
this.resizableHandles.nw = true;
}
if (!this.preserveAspectRatioApplied) {
const $item = item.$item;
this.rowsValue = $item.rows; this.rowsValue = $item.rows;
this.colsValue = $item.cols; this.colsValue = $item.cols;
Object.defineProperty($item, 'rows', { Object.defineProperty($item, 'rows', {
get: () => this.rowsValue, get: () => this.rowsValue,
set: v => { set: v => {
if (this.rowsValue !== v) { if (this.rowsValue !== v) {
if (this.preserveAspectRatio) { if (this.preserveAspectRatio) {
this.colsValue = v * this.aspectRatio; this.colsValue = v * this.aspectRatio;
}
this.rowsValue = v;
} }
this.rowsValue = v;
} }
} });
});
Object.defineProperty($item, 'cols', { Object.defineProperty($item, 'cols', {
get: () => this.colsValue, get: () => this.colsValue,
set: v => { set: v => {
if (this.colsValue !== v) { if (this.colsValue !== v) {
if (this.preserveAspectRatio) { if (this.preserveAspectRatio) {
this.rowsValue = v / this.aspectRatio; this.rowsValue = v / this.aspectRatio;
}
this.colsValue = v;
} }
this.colsValue = v;
} }
} });
});
const resizable = item.resize; const resizable = item.resize;
this.heightValue = resizable.height; this.heightValue = resizable.height;
this.widthValue = resizable.width; this.widthValue = resizable.width;
const setItemHeight = resizable.setItemHeight.bind(resizable); const setItemHeight = resizable.setItemHeight.bind(resizable);
const setItemWidth = resizable.setItemWidth.bind(resizable); const setItemWidth = resizable.setItemWidth.bind(resizable);
resizable.setItemHeight = (height) => { resizable.setItemHeight = (height) => {
setItemHeight(height); setItemHeight(height);
this.heightValue = height; this.heightValue = height;
if (this.preserveAspectRatio) { if (this.preserveAspectRatio) {
setItemWidth(height * this.aspectRatio); setItemWidth(height * this.aspectRatio);
} }
}; };
resizable.setItemWidth = (width) => { resizable.setItemWidth = (width) => {
setItemWidth(width); setItemWidth(width);
this.widthValue = width; this.widthValue = width;
if (this.preserveAspectRatio) { if (this.preserveAspectRatio) {
setItemHeight(width / this.aspectRatio); setItemHeight(width / this.aspectRatio);
} }
}; };
Object.defineProperty(resizable, 'height', { Object.defineProperty(resizable, 'height', {
get: () => this.heightValue, get: () => this.heightValue,
set: v => { set: v => {
if (this.heightValue !== v) { if (this.heightValue !== v) {
if (this.preserveAspectRatio) { if (this.preserveAspectRatio) {
this.widthValue = v * this.aspectRatio; this.widthValue = v * this.aspectRatio;
}
this.heightValue = v;
} }
this.heightValue = v;
} }
} });
});
Object.defineProperty(resizable, 'width', { Object.defineProperty(resizable, 'width', {
get: () => this.widthValue, get: () => this.widthValue,
set: v => { set: v => {
if (this.widthValue !== v) { if (this.widthValue !== v) {
if (this.preserveAspectRatio) { if (this.preserveAspectRatio) {
this.heightValue = v / this.aspectRatio; this.heightValue = v / this.aspectRatio;
}
this.widthValue = v;
} }
this.widthValue = v;
} }
} });
}); this.preserveAspectRatioApplied = true;
}
} }
get highlighted() { get highlighted() {
@ -527,19 +538,36 @@ export class DashboardWidget implements GridsterItem, IDashboardWidget {
} }
} }
get widgetLayout(): WidgetLayout {
return this.widgetLayoutValue;
}
set widgetLayout(value: WidgetLayout) {
this.widgetLayoutValue = value;
this._widgetLayoutUpdated();
}
private _widgetLayoutUpdated() {
if (isDefined(this.widgetLayout?.resizable)) {
this.resizeEnabled = this.widgetLayout.resizable;
}
if (this.widgetLayout?.preserveAspectRatio) {
this.aspectRatio = this.widgetLayout.sizeX / this.widgetLayout.sizeY;
}
if (this.gridsterItemComponentValue) {
this.applyPreserveAspectRatio(this.gridsterItemComponentValue);
}
}
constructor( constructor(
private dashboard: IDashboardComponent, private dashboard: IDashboardComponent,
public widget: Widget, public widget: Widget,
public widgetLayout?: WidgetLayout, private widgetLayoutValue?: WidgetLayout,
private parentDashboard?: IDashboardComponent, private parentDashboard?: IDashboardComponent,
private popoverComponent?: TbPopoverComponent) { private popoverComponent?: TbPopoverComponent) {
if (isDefined(widgetLayout?.resizable)) { this.widgetLayout = widgetLayoutValue;
this.resizeEnabled = widgetLayout.resizable;
}
if (widgetLayout?.preserveAspectRatio) {
this.aspectRatio = this.widgetLayout.sizeX / this.widgetLayout.sizeY;
}
if (!widget.id) { if (!widget.id) {
widget.id = guid(); widget.id = guid();
} }

1
ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol.component.html

@ -30,6 +30,7 @@
headerHeightPx="64" headerHeightPx="64"
headerTitle="{{symbolData?.imageResource?.title}}"> headerTitle="{{symbolData?.imageResource?.title}}">
<div class="details-buttons" fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="16px"> <div class="details-buttons" fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="16px">
<div tb-help="scadaSymbolDev"></div>
<button mat-stroked-button <button mat-stroked-button
[disabled]="scadaSymbolFormGroup.invalid" [disabled]="scadaSymbolFormGroup.invalid"
(click)="createWidget()"> (click)="createWidget()">

9
ui-ngx/src/app/shared/components/image/image-gallery.component.html

@ -22,7 +22,10 @@
[fxShow]="!textSearchMode && (mode === 'grid' || dataSource?.selection.isEmpty())" [ngClass.lt-lg]="{'multi-row': !isSysAdmin}"> [fxShow]="!textSearchMode && (mode === 'grid' || dataSource?.selection.isEmpty())" [ngClass.lt-lg]="{'multi-row': !isSysAdmin}">
<div fxFlex fxLayout="row" fxLayoutAlign="start center"> <div fxFlex fxLayout="row" fxLayoutAlign="start center">
<div class="mat-toolbar-tools"> <div class="mat-toolbar-tools">
<span fxHide fxShow.gt-sm class="tb-images-title">{{ (isScada ? 'scada.symbols' : 'image.gallery') | translate }}</span> <div fxHide fxShow.gt-sm class="tb-images-title">
<div tbTruncateWithTooltip>{{ (isScada ? 'scada.symbols' : 'image.gallery') | translate }}</div>
<div *ngIf="isScada" tb-help="scada"></div>
</div>
<div class="tb-images-view-type-toolbar" <div class="tb-images-view-type-toolbar"
fxLayout="row" fxLayout="row"
fxLayoutAlign="start center"> fxLayoutAlign="start center">
@ -72,7 +75,7 @@
matTooltipPosition="above"> matTooltipPosition="above">
<tb-icon>mdi:file-import</tb-icon> <tb-icon>mdi:file-import</tb-icon>
</button> </button>
<button fxHide fxShow.lt-lg <button [fxHide]="!(dialogMode && isScada)" fxShow.lt-lg
[disabled]="isLoading$ | async" [disabled]="isLoading$ | async"
mat-icon-button mat-icon-button
color="primary" color="primary"
@ -82,7 +85,7 @@
<mat-icon>add</mat-icon> <mat-icon>add</mat-icon>
</button> </button>
</section> </section>
<button fxHide fxShow.gt-md <button fxHide [fxShow.gt-md]="!(dialogMode && isScada)"
[disabled]="isLoading$ | async" [disabled]="isLoading$ | async"
mat-flat-button mat-flat-button
color="primary" color="primary"

5
ui-ngx/src/app/shared/components/image/image-gallery.component.scss

@ -54,9 +54,8 @@ $tb-button-selected-color: rgb(255, 110, 64) !default;
.tb-images-title { .tb-images-title {
padding-right: 20px; padding-right: 20px;
white-space: nowrap; display: flex;
overflow: hidden; align-items: center;
text-overflow: ellipsis;
} }
.tb-images-view-type-toolbar { .tb-images-view-type-toolbar {

6
ui-ngx/src/app/shared/models/constants.ts

@ -183,8 +183,10 @@ export const HelpLinks = {
templateNotifications: `${helpBaseUrl}/docs${docPlatformPrefix}/user-guide/notifications/#templates`, templateNotifications: `${helpBaseUrl}/docs${docPlatformPrefix}/user-guide/notifications/#templates`,
recipientNotifications: `${helpBaseUrl}/docs${docPlatformPrefix}/user-guide/notifications/#recipients`, recipientNotifications: `${helpBaseUrl}/docs${docPlatformPrefix}/user-guide/notifications/#recipients`,
ruleNotifications: `${helpBaseUrl}/docs${docPlatformPrefix}/user-guide/notifications/#rules`, ruleNotifications: `${helpBaseUrl}/docs${docPlatformPrefix}/user-guide/notifications/#rules`,
jwtSecuritySettings: `${helpBaseUrl}/docs${docPlatformPrefix}/user-guide/ui/jwt-security-settings/`, jwtSecuritySettings: `${helpBaseUrl}/docs${docPlatformPrefix}/user-guide/ui/jwt-security-settings`,
gatewayInstall: `${helpBaseUrl}/docs/iot-gateway/install/docker-installation/`, gatewayInstall: `${helpBaseUrl}/docs/iot-gateway/install/docker-installation`,
scada: `${helpBaseUrl}/docs${docPlatformPrefix}/user-guide/scada`,
scadaSymbolDev: `${helpBaseUrl}/docs${docPlatformPrefix}/user-guide/scada/symbols-dev-guide`,
} }
}; };
/* eslint-enable max-len */ /* eslint-enable max-len */

Loading…
Cancel
Save