UI: Fixed widget config forms validation.
This commit is contained in:
parent
49f5931f1b
commit
59adb5f6a4
@ -17,7 +17,7 @@
|
||||
"settingsDirective": "tb-liquid-level-card-widget-settings",
|
||||
"hasBasicMode": true,
|
||||
"basicModeDirective": "tb-liquid-level-card-basic-config",
|
||||
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"return Math.floor(Math.random() * 101);\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null}],\"alarmFilterConfig\":{\"statusList\":[\"ACTIVE\"]}}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"tankSelectionType\":\"static\",\"selectedShape\":\"Vertical Cylinder\",\"shapeAttributeName\":\"tankShape\",\"tankColor\":{\"type\":\"range\",\"color\":\"#242770\",\"rangeList\":[{\"from\":null,\"to\":20,\"color\":\"#E73535DE\"},{\"from\":20,\"to\":null,\"color\":\"#242770\"}],\"colorFunction\":\"var percent = value;\\nif (typeof percent !== undefined) {\\n if (percent < 20) {\\n return '#E73535DE';\\n }\\n}\\nreturn '#242770';\"},\"datasourceUnits\":\"%\",\"layout\":\"percentage\",\"volumeSource\":\"static\",\"volumeConstant\":500,\"volumeAttributeName\":\"volume\",\"volumeUnits\":\"L\",\"volumeFont\":{\"family\":\"Roboto\",\"size\":14,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"100%\"},\"volumeColor\":\"rgba(255, 255, 255, 0.18)\",\"units\":\"%\",\"widgetUnitsSource\":\"static\",\"widgetUnitsAttributeName\":\"units\",\"liquidColor\":{\"type\":\"range\",\"color\":\"#7A8BFF\",\"rangeList\":[{\"from\":null,\"to\":20,\"color\":\"#E27C7CDE\"},{\"from\":20,\"to\":null,\"color\":\"#7A8BFF\"}],\"colorFunction\":\"var percent = value;\\nif (typeof percent !== undefined) {\\n if (percent < 20) {\\n return '#E27C7CDE';\\n }\\n}\\nreturn '#7A8BFF';\"},\"valueFont\":{\"family\":\"Roboto\",\"size\":24,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"100%\"},\"valueColor\":{\"type\":\"range\",\"color\":\"#000000DE\",\"rangeList\":[{\"from\":null,\"to\":20,\"color\":\"#FF0000DE\"},{\"from\":20,\"to\":null,\"color\":\"rgba(0,0,0,0.87)\"}],\"colorFunction\":\"var percent = value;\\nif (typeof percent !== undefined) {\\n if (percent < 20) {\\n return '#FF0000DE';\\n }\\n}\\nreturn '#000000DE';\"},\"showBackgroundOverlay\":true,\"backgroundOverlayColor\":{\"type\":\"range\",\"color\":\"rgba(255, 255, 255, 0.76)\",\"rangeList\":[{\"from\":null,\"to\":20,\"color\":\"#FFEFEFDE\"},{\"from\":20,\"to\":null,\"color\":\"#FFFFFFC2\"}],\"colorFunction\":\"var percent = value;\\nif (typeof percent !== undefined) {\\n if (percent < 20) {\\n return '#FFEFEFDE';\\n }\\n}\\nreturn '#FFFFFFC2';\"},\"showTooltip\":true,\"showTooltipLevel\":true,\"tooltipUnits\":\"%\",\"tooltipLevelDecimals\":0,\"tooltipLevelFont\":{\"family\":\"Roboto\",\"size\":13,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"100%\"},\"tooltipLevelColor\":{\"type\":\"constant\",\"color\":\"rgba(0, 0, 0, 0.76)\",\"rangeList\":[],\"colorFunction\":\"var percent = value;\\nif (typeof percent !== undefined) {\\n if (percent < 20) {\\n return '#E27C7CDE';\\n }\\n}\\nreturn '#7A8BFF';\"},\"showTooltipDate\":true,\"tooltipDateFormat\":{\"format\":null,\"lastUpdateAgo\":true,\"custom\":false},\"tooltipDateFont\":{\"family\":\"Roboto\",\"size\":13,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"100%\"},\"tooltipDateColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipBackgroundColor\":\"rgba(255, 255, 255, 0.76)\",\"tooltipBackgroundBlur\":3,\"background\":{\"type\":\"color\",\"color\":\"#fff\",\"overlay\":{\"enabled\":false,\"color\":\"rgba(255,255,255,0.72)\",\"blur\":3}}},\"title\":\"Liquid level\",\"useDashboardTimewindow\":true,\"displayTimewindow\":true,\"configMode\":\"basic\",\"titleFont\":{\"family\":\"Roboto\",\"size\":16,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"1.5\"},\"titleColor\":\"rgba(0, 0, 0, 0.87)\",\"showTitleIcon\":false,\"titleIcon\":\"water_drop\",\"iconColor\":\"#5469FF\",\"decimals\":0,\"enableDataExport\":false,\"enableFullscreen\":false,\"borderRadius\":\"0px\",\"actions\":{},\"iconSize\":\"24px\",\"titleTooltip\":\"\",\"dropShadow\":true,\"margin\":\"0px\",\"widgetStyle\":{},\"widgetCss\":\"\",\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"pageSize\":1024,\"noDataDisplayMessage\":\"\"}"
|
||||
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"return Math.floor(Math.random() * 101);\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null}],\"alarmFilterConfig\":{\"statusList\":[\"ACTIVE\"]}}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"tankSelectionType\":\"static\",\"selectedShape\":\"Vertical Cylinder\",\"shapeAttributeName\":\"tankShape\",\"tankColor\":{\"type\":\"range\",\"color\":\"#242770\",\"rangeList\":[{\"from\":null,\"to\":20,\"color\":\"#E73535DE\"},{\"from\":20,\"to\":null,\"color\":\"#242770\"}],\"colorFunction\":\"var percent = value;\\nif (typeof percent !== undefined) {\\n if (percent < 20) {\\n return '#E73535DE';\\n }\\n}\\nreturn '#242770';\"},\"datasourceUnits\":\"%\",\"layout\":\"percentage\",\"volumeSource\":\"static\",\"volumeConstant\":500,\"volumeAttributeName\":\"volume\",\"volumeUnits\":\"L\",\"volumeFont\":{\"family\":\"Roboto\",\"size\":14,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"100%\"},\"volumeColor\":\"rgba(0, 0, 0, 0.18)\",\"units\":\"%\",\"widgetUnitsSource\":\"static\",\"widgetUnitsAttributeName\":\"units\",\"liquidColor\":{\"type\":\"range\",\"color\":\"#7A8BFF\",\"rangeList\":[{\"from\":null,\"to\":20,\"color\":\"#E27C7CDE\"},{\"from\":20,\"to\":null,\"color\":\"#7A8BFF\"}],\"colorFunction\":\"var percent = value;\\nif (typeof percent !== undefined) {\\n if (percent < 20) {\\n return '#E27C7CDE';\\n }\\n}\\nreturn '#7A8BFF';\"},\"valueFont\":{\"family\":\"Roboto\",\"size\":24,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"100%\"},\"valueColor\":{\"type\":\"range\",\"color\":\"#000000DE\",\"rangeList\":[{\"from\":null,\"to\":20,\"color\":\"#FF0000DE\"},{\"from\":20,\"to\":null,\"color\":\"rgba(0,0,0,0.87)\"}],\"colorFunction\":\"var percent = value;\\nif (typeof percent !== undefined) {\\n if (percent < 20) {\\n return '#FF0000DE';\\n }\\n}\\nreturn '#000000DE';\"},\"showBackgroundOverlay\":true,\"backgroundOverlayColor\":{\"type\":\"range\",\"color\":\"rgba(255, 255, 255, 0.76)\",\"rangeList\":[{\"from\":null,\"to\":20,\"color\":\"#FFEFEFDE\"},{\"from\":20,\"to\":null,\"color\":\"#FFFFFFC2\"}],\"colorFunction\":\"var percent = value;\\nif (typeof percent !== undefined) {\\n if (percent < 20) {\\n return '#FFEFEFDE';\\n }\\n}\\nreturn '#FFFFFFC2';\"},\"showTooltip\":true,\"showTooltipLevel\":true,\"tooltipUnits\":\"%\",\"tooltipLevelDecimals\":0,\"tooltipLevelFont\":{\"family\":\"Roboto\",\"size\":13,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"100%\"},\"tooltipLevelColor\":{\"type\":\"constant\",\"color\":\"rgba(0, 0, 0, 0.76)\",\"rangeList\":[],\"colorFunction\":\"var percent = value;\\nif (typeof percent !== undefined) {\\n if (percent < 20) {\\n return '#E27C7CDE';\\n }\\n}\\nreturn '#7A8BFF';\"},\"showTooltipDate\":true,\"tooltipDateFormat\":{\"format\":null,\"lastUpdateAgo\":true,\"custom\":false},\"tooltipDateFont\":{\"family\":\"Roboto\",\"size\":13,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"100%\"},\"tooltipDateColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipBackgroundColor\":\"rgba(255, 255, 255, 0.76)\",\"tooltipBackgroundBlur\":3,\"background\":{\"type\":\"color\",\"color\":\"#fff\",\"overlay\":{\"enabled\":false,\"color\":\"rgba(255,255,255,0.72)\",\"blur\":3}}},\"title\":\"Liquid level\",\"useDashboardTimewindow\":true,\"displayTimewindow\":true,\"configMode\":\"basic\",\"titleFont\":{\"family\":\"Roboto\",\"size\":16,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"1.5\"},\"titleColor\":\"rgba(0, 0, 0, 0.87)\",\"showTitleIcon\":false,\"titleIcon\":\"water_drop\",\"iconColor\":\"#5469FF\",\"decimals\":0,\"enableDataExport\":false,\"enableFullscreen\":false,\"borderRadius\":\"0px\",\"actions\":{},\"iconSize\":\"24px\",\"titleTooltip\":\"\",\"dropShadow\":true,\"margin\":\"0px\",\"widgetStyle\":{},\"widgetCss\":\"\",\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"pageSize\":1024,\"noDataDisplayMessage\":\"\"}"
|
||||
},
|
||||
"externalId": null,
|
||||
"tags": [
|
||||
|
||||
@ -75,14 +75,14 @@
|
||||
<button *ngIf="!previewMode"
|
||||
mat-button color="primary"
|
||||
type="button"
|
||||
[disabled]="widgetFormGroup.invalid"
|
||||
[disabled]="!widgetFormGroup.valid"
|
||||
(click)="previewMode = true"
|
||||
cdkFocusInitial>
|
||||
{{ 'widget-config.preview' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button color="primary"
|
||||
(click)="add()"
|
||||
[disabled]="widgetFormGroup.invalid">
|
||||
[disabled]="!widgetFormGroup.valid">
|
||||
{{ 'action.add' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@ -34,7 +34,7 @@
|
||||
</button>
|
||||
<button *ngIf="!previewMode"
|
||||
fxHide.gt-sm
|
||||
[disabled]="widgetFormGroup.invalid"
|
||||
[disabled]="!widgetFormGroup.valid"
|
||||
mat-button color="primary"
|
||||
(click)="previewMode = true">
|
||||
<mat-icon>visibility</mat-icon>
|
||||
@ -44,7 +44,7 @@
|
||||
<div fxFlex.lt-md class="tb-widget-config-header-suffix" fxLayout="row" fxLayoutAlign="end center" fxLayoutGap="12px">
|
||||
<button *ngIf="!previewMode"
|
||||
fxHide.lt-md
|
||||
[disabled]="widgetFormGroup.invalid"
|
||||
[disabled]="!widgetFormGroup.valid"
|
||||
mat-button color="primary"
|
||||
(click)="previewMode = true">
|
||||
<mat-icon>visibility</mat-icon>
|
||||
@ -57,7 +57,7 @@
|
||||
<mat-icon>close</mat-icon>
|
||||
{{ 'action.decline' | translate }}
|
||||
</button>
|
||||
<button [disabled]="widgetFormGroup.invalid || !widgetFormGroup.dirty"
|
||||
<button [disabled]="!widgetFormGroup.valid || !widgetFormGroup.dirty"
|
||||
mat-flat-button color="primary"
|
||||
(click)="onApplyWidgetConfig()">
|
||||
<mat-icon>done</mat-icon>
|
||||
|
||||
@ -41,13 +41,14 @@ import {
|
||||
widgetType
|
||||
} from '@shared/models/widget.models';
|
||||
import {
|
||||
AsyncValidator,
|
||||
ControlValueAccessor,
|
||||
NG_VALIDATORS,
|
||||
NG_ASYNC_VALIDATORS,
|
||||
NG_VALUE_ACCESSOR,
|
||||
UntypedFormBuilder,
|
||||
UntypedFormControl,
|
||||
UntypedFormGroup,
|
||||
Validator,
|
||||
ValidationErrors,
|
||||
Validators
|
||||
} from '@angular/forms';
|
||||
import { WidgetConfigComponentData } from '@home/models/widget-component.models';
|
||||
@ -59,7 +60,7 @@ import { UtilsService } from '@core/services/utils.service';
|
||||
import { DataKeyType } from '@shared/models/telemetry/telemetry.models';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { EntityType } from '@shared/models/entity-type.models';
|
||||
import { Observable, of, Subscription } from 'rxjs';
|
||||
import { Observable, of, Subject, Subscription } from 'rxjs';
|
||||
import {
|
||||
IBasicWidgetConfigComponent,
|
||||
WidgetConfigCallbacks
|
||||
@ -68,7 +69,7 @@ import {
|
||||
EntityAliasDialogComponent,
|
||||
EntityAliasDialogData
|
||||
} from '@home/components/alias/entity-alias-dialog.component';
|
||||
import { catchError, mergeMap, tap } from 'rxjs/operators';
|
||||
import { catchError, map, mergeMap, tap } from 'rxjs/operators';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { EntityService } from '@core/http/entity.service';
|
||||
import { JsonFormComponentData } from '@shared/components/json-form/json-form-component.models';
|
||||
@ -102,13 +103,13 @@ const defaultSettingsForm = [
|
||||
multi: true
|
||||
},
|
||||
{
|
||||
provide: NG_VALIDATORS,
|
||||
provide: NG_ASYNC_VALIDATORS,
|
||||
useExisting: forwardRef(() => WidgetConfigComponent),
|
||||
multi: true,
|
||||
}
|
||||
]
|
||||
})
|
||||
export class WidgetConfigComponent extends PageComponent implements OnInit, OnDestroy, ControlValueAccessor, Validator {
|
||||
export class WidgetConfigComponent extends PageComponent implements OnInit, OnDestroy, ControlValueAccessor, AsyncValidator {
|
||||
|
||||
@ViewChild('basicModeContainer', {read: ViewContainerRef, static: false}) basicModeContainer: ViewContainerRef;
|
||||
|
||||
@ -181,6 +182,7 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, OnDe
|
||||
private createBasicModeComponentTimeout: Timeout;
|
||||
private basicModeComponentRef: ComponentRef<IBasicWidgetConfigComponent>;
|
||||
private basicModeComponent: IBasicWidgetConfigComponent;
|
||||
private basicModeComponent$: Subject<IBasicWidgetConfigComponent> = null;
|
||||
private basicModeComponentChangeSubscription: Subscription;
|
||||
|
||||
private dataSettingsChangesSubscription: Subscription;
|
||||
@ -437,6 +439,11 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, OnDe
|
||||
this.propagateChange(this.modelValue);
|
||||
this.cd.markForCheck();
|
||||
});
|
||||
if (this.basicModeComponent$) {
|
||||
this.basicModeComponent$.next(this.basicModeComponent);
|
||||
this.basicModeComponent$.complete();
|
||||
this.basicModeComponent$ = null;
|
||||
}
|
||||
this.cd.markForCheck();
|
||||
}, 0);
|
||||
}
|
||||
@ -876,40 +883,65 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, OnDe
|
||||
return stateId => stateId.toLowerCase().indexOf(lowercaseQuery) === 0;
|
||||
}
|
||||
|
||||
public validate(c: UntypedFormControl) {
|
||||
if (this.basicModeComponent) {
|
||||
if (!this.basicModeComponent.validateConfig()) {
|
||||
public validate(c: UntypedFormControl): Observable<ValidationErrors | null> {
|
||||
const basicComponentMode = this.hasBasicModeDirective && this.widgetConfigMode === WidgetConfigMode.basic;
|
||||
let comp$: Observable<IBasicWidgetConfigComponent>;
|
||||
if (basicComponentMode) {
|
||||
if (this.basicModeComponent) {
|
||||
comp$ = of(this.basicModeComponent);
|
||||
} else {
|
||||
if (this.useDefinedBasicModeDirective) {
|
||||
this.basicModeComponent$ = new Subject();
|
||||
comp$ = this.basicModeComponent$;
|
||||
} else {
|
||||
comp$ = of(null);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
comp$ = of(null);
|
||||
}
|
||||
return comp$.pipe(
|
||||
map((comp) => this.doValidate(basicComponentMode, comp))
|
||||
);
|
||||
}
|
||||
|
||||
private doValidate(basicComponentMode: boolean, basicModeComponent?: IBasicWidgetConfigComponent): ValidationErrors | null {
|
||||
if (basicComponentMode) {
|
||||
if (!basicModeComponent || !basicModeComponent.validateConfig()) {
|
||||
return {
|
||||
basicWidgetConfig: {
|
||||
valid: false
|
||||
}
|
||||
};
|
||||
}
|
||||
} else if (!this.dataSettings.valid) {
|
||||
return {
|
||||
dataSettings: {
|
||||
valid: false
|
||||
}
|
||||
};
|
||||
} else if (!this.widgetSettings.valid) {
|
||||
return {
|
||||
widgetSettings: {
|
||||
valid: false
|
||||
}
|
||||
};
|
||||
} else if (!this.layoutSettings.valid) {
|
||||
return {
|
||||
widgetSettings: {
|
||||
valid: false
|
||||
}
|
||||
};
|
||||
} else if (!this.advancedSettings.valid) {
|
||||
return {
|
||||
advancedSettings: {
|
||||
valid: false
|
||||
}
|
||||
};
|
||||
} else if (this.modelValue) {
|
||||
} else {
|
||||
if (!this.dataSettings.valid) {
|
||||
return {
|
||||
dataSettings: {
|
||||
valid: false
|
||||
}
|
||||
};
|
||||
} else if (!this.widgetSettings.valid) {
|
||||
return {
|
||||
widgetSettings: {
|
||||
valid: false
|
||||
}
|
||||
};
|
||||
} else if (!this.layoutSettings.valid) {
|
||||
return {
|
||||
widgetSettings: {
|
||||
valid: false
|
||||
}
|
||||
};
|
||||
} else if (!this.advancedSettings.valid) {
|
||||
return {
|
||||
advancedSettings: {
|
||||
valid: false
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
if (this.modelValue) {
|
||||
const config = this.modelValue.config;
|
||||
if (this.widgetType === widgetType.rpc && this.modelValue.isDataEnabled) {
|
||||
if (!this.widgetEditMode && (!config.targetDeviceAliasIds || !config.targetDeviceAliasIds.length)) {
|
||||
@ -923,4 +955,5 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, OnDe
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user