2019-09-25 19:37:29 +03:00
|
|
|
///
|
2020-02-20 10:26:43 +02:00
|
|
|
/// Copyright © 2016-2020 The Thingsboard Authors
|
2019-09-25 19:37:29 +03:00
|
|
|
///
|
|
|
|
|
/// 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.
|
|
|
|
|
///
|
|
|
|
|
|
2019-10-24 19:52:19 +03:00
|
|
|
import { ChangeDetectionStrategy, Component, forwardRef, Input, OnInit } from '@angular/core';
|
2019-09-25 19:37:29 +03:00
|
|
|
import { PageComponent } from '@shared/components/page.component';
|
|
|
|
|
import { Store } from '@ngrx/store';
|
|
|
|
|
import { AppState } from '@core/core.state';
|
|
|
|
|
import {
|
2019-10-10 13:00:29 +03:00
|
|
|
DataKey,
|
2019-09-25 19:37:29 +03:00
|
|
|
Datasource,
|
2019-10-24 19:52:19 +03:00
|
|
|
DatasourceType,
|
|
|
|
|
datasourceTypeTranslationMap, defaultLegendConfig,
|
2019-09-25 19:37:29 +03:00
|
|
|
WidgetActionDescriptor,
|
2019-10-24 19:52:19 +03:00
|
|
|
widgetType
|
2019-09-25 19:37:29 +03:00
|
|
|
} from '@shared/models/widget.models';
|
2019-10-10 13:00:29 +03:00
|
|
|
import {
|
2019-10-11 19:22:03 +03:00
|
|
|
AbstractControl,
|
2019-10-10 13:00:29 +03:00
|
|
|
ControlValueAccessor,
|
|
|
|
|
FormArray,
|
|
|
|
|
FormBuilder,
|
|
|
|
|
FormControl,
|
|
|
|
|
FormGroup,
|
|
|
|
|
NG_VALIDATORS,
|
|
|
|
|
NG_VALUE_ACCESSOR,
|
2019-10-24 19:52:19 +03:00
|
|
|
Validator,
|
2019-10-10 13:00:29 +03:00
|
|
|
Validators
|
|
|
|
|
} from '@angular/forms';
|
2019-09-25 19:37:29 +03:00
|
|
|
import { WidgetConfigComponentData } from '@home/models/widget-component.models';
|
2019-10-10 13:00:29 +03:00
|
|
|
import { deepClone, isDefined, isObject } from '@app/core/utils';
|
|
|
|
|
import { alarmFields, AlarmSearchStatus } from '@shared/models/alarm.models';
|
2019-09-25 19:37:29 +03:00
|
|
|
import { IAliasController } from '@core/api/widget-api.models';
|
2019-10-11 19:22:03 +03:00
|
|
|
import { EntityAlias, EntityAliases } from '@shared/models/alias.models';
|
2019-10-10 13:00:29 +03:00
|
|
|
import { UtilsService } from '@core/services/utils.service';
|
|
|
|
|
import { DataKeyType } from '@shared/models/telemetry/telemetry.models';
|
|
|
|
|
import { TranslateService } from '@ngx-translate/core';
|
2019-10-11 19:22:03 +03:00
|
|
|
import { EntityType } from '@shared/models/entity-type.models';
|
2019-10-17 18:23:53 +03:00
|
|
|
import { forkJoin, Observable, of, Subscription } from 'rxjs';
|
2019-10-11 19:22:03 +03:00
|
|
|
import { WidgetConfigCallbacks } from '@home/components/widget/widget-config.component.models';
|
|
|
|
|
import {
|
|
|
|
|
EntityAliasDialogComponent,
|
|
|
|
|
EntityAliasDialogData
|
|
|
|
|
} from '@home/components/alias/entity-alias-dialog.component';
|
2019-10-24 19:52:19 +03:00
|
|
|
import { catchError, map, mergeMap, tap } from 'rxjs/operators';
|
2019-10-11 19:22:03 +03:00
|
|
|
import { MatDialog } from '@angular/material/dialog';
|
2019-10-17 18:23:53 +03:00
|
|
|
import { EntityService } from '@core/http/entity.service';
|
2019-10-21 19:57:18 +03:00
|
|
|
import { JsonFormComponentData } from '@shared/components/json-form/json-form-component.models';
|
2019-10-24 19:52:19 +03:00
|
|
|
import { WidgetActionsData } from './action/manage-widget-actions.component.models';
|
2020-02-04 15:14:17 +02:00
|
|
|
import { Dashboard, DashboardState } from '@shared/models/dashboard.models';
|
2019-10-21 19:57:18 +03:00
|
|
|
|
|
|
|
|
const emptySettingsSchema = {
|
|
|
|
|
type: 'object',
|
|
|
|
|
properties: {}
|
|
|
|
|
};
|
|
|
|
|
const emptySettingsGroupInfoes = [];
|
|
|
|
|
const defaultSettingsForm = [
|
|
|
|
|
'*'
|
|
|
|
|
];
|
2019-09-25 19:37:29 +03:00
|
|
|
|
|
|
|
|
@Component({
|
|
|
|
|
selector: 'tb-widget-config',
|
|
|
|
|
templateUrl: './widget-config.component.html',
|
|
|
|
|
styleUrls: ['./widget-config.component.scss'],
|
|
|
|
|
providers: [
|
|
|
|
|
{
|
|
|
|
|
provide: NG_VALUE_ACCESSOR,
|
|
|
|
|
useExisting: forwardRef(() => WidgetConfigComponent),
|
|
|
|
|
multi: true
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
provide: NG_VALIDATORS,
|
|
|
|
|
useExisting: forwardRef(() => WidgetConfigComponent),
|
|
|
|
|
multi: true,
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
})
|
|
|
|
|
export class WidgetConfigComponent extends PageComponent implements OnInit, ControlValueAccessor, Validator {
|
|
|
|
|
|
|
|
|
|
widgetTypes = widgetType;
|
|
|
|
|
|
2019-10-11 19:22:03 +03:00
|
|
|
entityTypes = EntityType;
|
|
|
|
|
|
2019-10-10 13:00:29 +03:00
|
|
|
alarmSearchStatuses = Object.keys(AlarmSearchStatus);
|
|
|
|
|
|
2019-09-25 19:37:29 +03:00
|
|
|
@Input()
|
|
|
|
|
forceExpandDatasources: boolean;
|
|
|
|
|
|
|
|
|
|
@Input()
|
|
|
|
|
aliasController: IAliasController;
|
|
|
|
|
|
2019-10-11 19:22:03 +03:00
|
|
|
@Input()
|
|
|
|
|
entityAliases: EntityAliases;
|
|
|
|
|
|
2019-09-25 19:37:29 +03:00
|
|
|
@Input()
|
|
|
|
|
functionsOnly: boolean;
|
|
|
|
|
|
2019-10-24 19:52:19 +03:00
|
|
|
@Input()
|
2020-02-04 15:14:17 +02:00
|
|
|
dashboardStates: {[id: string]: DashboardState };
|
2019-10-24 19:52:19 +03:00
|
|
|
|
2019-09-25 19:37:29 +03:00
|
|
|
@Input() disabled: boolean;
|
|
|
|
|
|
2019-10-10 13:00:29 +03:00
|
|
|
widgetType: widgetType;
|
|
|
|
|
|
2019-10-11 19:22:03 +03:00
|
|
|
datasourceType = DatasourceType;
|
|
|
|
|
datasourceTypes: Array<DatasourceType>;
|
|
|
|
|
datasourceTypesTranslations = datasourceTypeTranslationMap;
|
|
|
|
|
|
|
|
|
|
widgetConfigCallbacks: WidgetConfigCallbacks = {
|
|
|
|
|
createEntityAlias: this.createEntityAlias.bind(this),
|
2019-10-17 18:23:53 +03:00
|
|
|
generateDataKey: this.generateDataKey.bind(this),
|
2019-10-24 19:52:19 +03:00
|
|
|
fetchEntityKeys: this.fetchEntityKeys.bind(this),
|
|
|
|
|
fetchDashboardStates: this.fetchDashboardStates.bind(this)
|
2019-10-11 19:22:03 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
widgetEditMode = this.utils.widgetEditMode;
|
|
|
|
|
|
2019-09-25 19:37:29 +03:00
|
|
|
selectedTab: number;
|
|
|
|
|
|
2019-12-23 14:36:44 +02:00
|
|
|
modelValue: WidgetConfigComponentData;
|
2019-09-25 19:37:29 +03:00
|
|
|
|
|
|
|
|
private propagateChange = null;
|
|
|
|
|
|
2019-10-10 13:00:29 +03:00
|
|
|
public dataSettings: FormGroup;
|
2019-10-11 19:22:03 +03:00
|
|
|
public targetDeviceSettings: FormGroup;
|
2019-10-24 19:52:19 +03:00
|
|
|
public alarmSourceSettings: FormGroup;
|
|
|
|
|
public widgetSettings: FormGroup;
|
|
|
|
|
public layoutSettings: FormGroup;
|
2019-10-21 19:57:18 +03:00
|
|
|
public advancedSettings: FormGroup;
|
2019-10-24 19:52:19 +03:00
|
|
|
public actionsSettings: FormGroup;
|
2019-10-11 19:22:03 +03:00
|
|
|
|
|
|
|
|
private dataSettingsChangesSubscription: Subscription;
|
|
|
|
|
private targetDeviceSettingsSubscription: Subscription;
|
2019-10-24 19:52:19 +03:00
|
|
|
private alarmSourceSettingsSubscription: Subscription;
|
|
|
|
|
private widgetSettingsSubscription: Subscription;
|
|
|
|
|
private layoutSettingsSubscription: Subscription;
|
2019-10-21 19:57:18 +03:00
|
|
|
private advancedSettingsSubscription: Subscription;
|
2019-10-24 19:52:19 +03:00
|
|
|
private actionsSettingsSubscription: Subscription;
|
2019-10-10 13:00:29 +03:00
|
|
|
|
|
|
|
|
constructor(protected store: Store<AppState>,
|
|
|
|
|
private utils: UtilsService,
|
2019-10-17 18:23:53 +03:00
|
|
|
private entityService: EntityService,
|
2019-10-11 19:22:03 +03:00
|
|
|
private dialog: MatDialog,
|
2019-10-10 13:00:29 +03:00
|
|
|
private translate: TranslateService,
|
|
|
|
|
private fb: FormBuilder) {
|
2019-09-25 19:37:29 +03:00
|
|
|
super(store);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ngOnInit(): void {
|
2019-10-11 19:22:03 +03:00
|
|
|
if (this.functionsOnly) {
|
|
|
|
|
this.datasourceTypes = [DatasourceType.function];
|
|
|
|
|
} else {
|
|
|
|
|
this.datasourceTypes = [DatasourceType.function, DatasourceType.entity];
|
|
|
|
|
}
|
2019-10-31 18:33:51 +02:00
|
|
|
this.dataSettings = this.fb.group({});
|
|
|
|
|
this.targetDeviceSettings = this.fb.group({});
|
|
|
|
|
this.alarmSourceSettings = this.fb.group({});
|
|
|
|
|
this.advancedSettings = this.fb.group({});
|
2019-10-24 19:52:19 +03:00
|
|
|
this.widgetSettings = this.fb.group({
|
|
|
|
|
title: [null, []],
|
|
|
|
|
showTitleIcon: [null, []],
|
|
|
|
|
titleIcon: [null, []],
|
|
|
|
|
iconColor: [null, []],
|
|
|
|
|
iconSize: [null, []],
|
|
|
|
|
showTitle: [null, []],
|
|
|
|
|
dropShadow: [null, []],
|
|
|
|
|
enableFullscreen: [null, []],
|
|
|
|
|
backgroundColor: [null, []],
|
|
|
|
|
color: [null, []],
|
|
|
|
|
padding: [null, []],
|
|
|
|
|
margin: [null, []],
|
|
|
|
|
widgetStyle: [null, []],
|
|
|
|
|
titleStyle: [null, []],
|
|
|
|
|
units: [null, []],
|
|
|
|
|
decimals: [null, [Validators.min(0), Validators.max(15), Validators.pattern(/^\d*$/)]],
|
|
|
|
|
showLegend: [null, []],
|
|
|
|
|
legendConfig: [null, []]
|
|
|
|
|
});
|
|
|
|
|
this.widgetSettings.get('showTitleIcon').valueChanges.subscribe((value: boolean) => {
|
|
|
|
|
if (value) {
|
|
|
|
|
this.widgetSettings.get('titleIcon').enable({emitEvent: false});
|
|
|
|
|
} else {
|
|
|
|
|
this.widgetSettings.get('titleIcon').disable({emitEvent: false});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
this.widgetSettings.get('showLegend').valueChanges.subscribe((value: boolean) => {
|
|
|
|
|
if (value) {
|
|
|
|
|
this.widgetSettings.get('legendConfig').enable({emitEvent: false});
|
|
|
|
|
} else {
|
|
|
|
|
this.widgetSettings.get('legendConfig').disable({emitEvent: false});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
this.layoutSettings = this.fb.group({
|
|
|
|
|
mobileOrder: [null, [Validators.pattern(/^-?[0-9]+$/)]],
|
|
|
|
|
mobileHeight: [null, [Validators.min(1), Validators.max(10), Validators.pattern(/^\d*$/)]]
|
|
|
|
|
});
|
|
|
|
|
this.actionsSettings = this.fb.group({
|
|
|
|
|
actionsData: [null, []]
|
|
|
|
|
});
|
2019-10-11 19:22:03 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private removeChangeSubscriptions() {
|
|
|
|
|
if (this.dataSettingsChangesSubscription) {
|
|
|
|
|
this.dataSettingsChangesSubscription.unsubscribe();
|
|
|
|
|
this.dataSettingsChangesSubscription = null;
|
|
|
|
|
}
|
|
|
|
|
if (this.targetDeviceSettingsSubscription) {
|
|
|
|
|
this.targetDeviceSettingsSubscription.unsubscribe();
|
|
|
|
|
this.targetDeviceSettingsSubscription = null;
|
|
|
|
|
}
|
2019-10-24 19:52:19 +03:00
|
|
|
if (this.alarmSourceSettingsSubscription) {
|
|
|
|
|
this.alarmSourceSettingsSubscription.unsubscribe();
|
|
|
|
|
this.alarmSourceSettingsSubscription = null;
|
|
|
|
|
}
|
|
|
|
|
if (this.widgetSettingsSubscription) {
|
|
|
|
|
this.widgetSettingsSubscription.unsubscribe();
|
|
|
|
|
this.widgetSettingsSubscription = null;
|
|
|
|
|
}
|
|
|
|
|
if (this.layoutSettingsSubscription) {
|
|
|
|
|
this.layoutSettingsSubscription.unsubscribe();
|
|
|
|
|
this.layoutSettingsSubscription = null;
|
|
|
|
|
}
|
2019-10-21 19:57:18 +03:00
|
|
|
if (this.advancedSettingsSubscription) {
|
|
|
|
|
this.advancedSettingsSubscription.unsubscribe();
|
|
|
|
|
this.advancedSettingsSubscription = null;
|
|
|
|
|
}
|
2019-10-24 19:52:19 +03:00
|
|
|
if (this.actionsSettingsSubscription) {
|
|
|
|
|
this.actionsSettingsSubscription.unsubscribe();
|
|
|
|
|
this.actionsSettingsSubscription = null;
|
|
|
|
|
}
|
2019-10-11 19:22:03 +03:00
|
|
|
}
|
2019-10-10 13:00:29 +03:00
|
|
|
|
2019-10-11 19:22:03 +03:00
|
|
|
private createChangeSubscriptions() {
|
|
|
|
|
this.dataSettingsChangesSubscription = this.dataSettings.valueChanges.subscribe(
|
|
|
|
|
() => this.updateDataSettings()
|
|
|
|
|
);
|
|
|
|
|
this.targetDeviceSettingsSubscription = this.targetDeviceSettings.valueChanges.subscribe(
|
|
|
|
|
() => this.updateTargetDeviceSettings()
|
|
|
|
|
);
|
2019-10-24 19:52:19 +03:00
|
|
|
this.alarmSourceSettingsSubscription = this.alarmSourceSettings.valueChanges.subscribe(
|
|
|
|
|
() => this.updateAlarmSourceSettings()
|
|
|
|
|
);
|
|
|
|
|
this.widgetSettingsSubscription = this.widgetSettings.valueChanges.subscribe(
|
|
|
|
|
() => this.updateWidgetSettings()
|
|
|
|
|
);
|
|
|
|
|
this.layoutSettingsSubscription = this.layoutSettings.valueChanges.subscribe(
|
|
|
|
|
() => this.updateLayoutSettings()
|
|
|
|
|
);
|
2019-10-21 19:57:18 +03:00
|
|
|
this.advancedSettingsSubscription = this.advancedSettings.valueChanges.subscribe(
|
|
|
|
|
() => this.updateAdvancedSettings()
|
|
|
|
|
);
|
2019-10-24 19:52:19 +03:00
|
|
|
this.actionsSettingsSubscription = this.actionsSettings.valueChanges.subscribe(
|
|
|
|
|
() => this.updateActionSettings()
|
|
|
|
|
);
|
2019-10-10 13:00:29 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private buildForms() {
|
|
|
|
|
this.dataSettings = this.fb.group({});
|
2019-10-11 19:22:03 +03:00
|
|
|
this.targetDeviceSettings = this.fb.group({});
|
2019-10-24 19:52:19 +03:00
|
|
|
this.alarmSourceSettings = this.fb.group({});
|
2019-10-21 19:57:18 +03:00
|
|
|
this.advancedSettings = this.fb.group({});
|
2019-10-10 13:00:29 +03:00
|
|
|
if (this.widgetType === widgetType.timeseries || this.widgetType === widgetType.alarm) {
|
|
|
|
|
this.dataSettings.addControl('useDashboardTimewindow', this.fb.control(null));
|
|
|
|
|
this.dataSettings.addControl('displayTimewindow', this.fb.control(null));
|
|
|
|
|
this.dataSettings.addControl('timewindow', this.fb.control(null));
|
|
|
|
|
this.dataSettings.get('useDashboardTimewindow').valueChanges.subscribe((value: boolean) => {
|
|
|
|
|
if (value) {
|
|
|
|
|
this.dataSettings.get('displayTimewindow').disable({emitEvent: false});
|
|
|
|
|
this.dataSettings.get('timewindow').disable({emitEvent: false});
|
|
|
|
|
} else {
|
|
|
|
|
this.dataSettings.get('displayTimewindow').enable({emitEvent: false});
|
|
|
|
|
this.dataSettings.get('timewindow').enable({emitEvent: false});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
if (this.widgetType === widgetType.alarm) {
|
|
|
|
|
this.dataSettings.addControl('alarmSearchStatus', this.fb.control(null));
|
|
|
|
|
this.dataSettings.addControl('alarmsPollingInterval', this.fb.control(null,
|
|
|
|
|
[Validators.required, Validators.min(1)]));
|
2020-02-21 16:31:03 +02:00
|
|
|
this.dataSettings.addControl('alarmsMaxCountLoad', this.fb.control(null,
|
|
|
|
|
[Validators.required, Validators.min(0)]));
|
|
|
|
|
this.dataSettings.addControl('alarmsFetchSize', this.fb.control(null,
|
|
|
|
|
[Validators.required, Validators.min(10)]));
|
2019-10-10 13:00:29 +03:00
|
|
|
}
|
|
|
|
|
}
|
2019-10-21 19:57:18 +03:00
|
|
|
if (this.modelValue.isDataEnabled) {
|
2019-10-10 13:00:29 +03:00
|
|
|
if (this.widgetType !== widgetType.rpc &&
|
|
|
|
|
this.widgetType !== widgetType.alarm &&
|
|
|
|
|
this.widgetType !== widgetType.static) {
|
|
|
|
|
this.dataSettings.addControl('datasources',
|
|
|
|
|
this.fb.array([]));
|
2019-10-11 19:22:03 +03:00
|
|
|
} else if (this.widgetType === widgetType.rpc) {
|
|
|
|
|
this.targetDeviceSettings.addControl('targetDeviceAliasId',
|
|
|
|
|
this.fb.control(null,
|
|
|
|
|
this.widgetEditMode ? [] : [Validators.required]));
|
2019-10-24 19:52:19 +03:00
|
|
|
} else if (this.widgetType === widgetType.alarm) {
|
|
|
|
|
this.alarmSourceSettings = this.buildDatasourceForm();
|
2019-10-10 13:00:29 +03:00
|
|
|
}
|
|
|
|
|
}
|
2019-10-21 19:57:18 +03:00
|
|
|
this.advancedSettings.addControl('settings',
|
|
|
|
|
this.fb.control(null, []));
|
2019-09-25 19:37:29 +03:00
|
|
|
}
|
|
|
|
|
|
2019-12-23 14:36:44 +02:00
|
|
|
datasourcesFormArray(): FormArray {
|
|
|
|
|
return this.dataSettings.get('datasources') as FormArray;
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-25 19:37:29 +03:00
|
|
|
registerOnChange(fn: any): void {
|
|
|
|
|
this.propagateChange = fn;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
registerOnTouched(fn: any): void {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setDisabledState(isDisabled: boolean): void {
|
|
|
|
|
this.disabled = isDisabled;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
writeValue(value: WidgetConfigComponentData): void {
|
|
|
|
|
this.modelValue = value;
|
2019-10-11 19:22:03 +03:00
|
|
|
this.removeChangeSubscriptions();
|
2019-09-25 19:37:29 +03:00
|
|
|
if (this.modelValue) {
|
2019-10-10 13:00:29 +03:00
|
|
|
if (this.widgetType !== this.modelValue.widgetType) {
|
|
|
|
|
this.widgetType = this.modelValue.widgetType;
|
|
|
|
|
this.buildForms();
|
|
|
|
|
}
|
2019-09-25 19:37:29 +03:00
|
|
|
const config = this.modelValue.config;
|
|
|
|
|
const layout = this.modelValue.layout;
|
|
|
|
|
if (config) {
|
|
|
|
|
this.selectedTab = 0;
|
2019-10-24 19:52:19 +03:00
|
|
|
this.widgetSettings.patchValue({
|
|
|
|
|
title: config.title,
|
|
|
|
|
showTitleIcon: isDefined(config.showTitleIcon) ? config.showTitleIcon : false,
|
|
|
|
|
titleIcon: isDefined(config.titleIcon) ? config.titleIcon : '',
|
|
|
|
|
iconColor: isDefined(config.iconColor) ? config.iconColor : 'rgba(0, 0, 0, 0.87)',
|
|
|
|
|
iconSize: isDefined(config.iconSize) ? config.iconSize : '24px',
|
|
|
|
|
showTitle: config.showTitle,
|
|
|
|
|
dropShadow: isDefined(config.dropShadow) ? config.dropShadow : true,
|
|
|
|
|
enableFullscreen: isDefined(config.enableFullscreen) ? config.enableFullscreen : true,
|
|
|
|
|
backgroundColor: config.backgroundColor,
|
|
|
|
|
color: config.color,
|
|
|
|
|
padding: config.padding,
|
|
|
|
|
margin: config.margin,
|
|
|
|
|
widgetStyle: isDefined(config.widgetStyle) ? config.widgetStyle : {},
|
|
|
|
|
titleStyle: isDefined(config.titleStyle) ? config.titleStyle : {
|
|
|
|
|
fontSize: '16px',
|
|
|
|
|
fontWeight: 400
|
|
|
|
|
},
|
|
|
|
|
units: config.units,
|
|
|
|
|
decimals: config.decimals,
|
|
|
|
|
showLegend: isDefined(config.showLegend) ? config.showLegend :
|
|
|
|
|
this.widgetType === widgetType.timeseries,
|
|
|
|
|
legendConfig: config.legendConfig || defaultLegendConfig(this.widgetType)
|
|
|
|
|
},
|
|
|
|
|
{emitEvent: false}
|
|
|
|
|
);
|
|
|
|
|
const showTitleIcon: boolean = this.widgetSettings.get('showTitleIcon').value;
|
|
|
|
|
if (showTitleIcon) {
|
|
|
|
|
this.widgetSettings.get('titleIcon').enable({emitEvent: false});
|
|
|
|
|
} else {
|
|
|
|
|
this.widgetSettings.get('titleIcon').disable({emitEvent: false});
|
|
|
|
|
}
|
|
|
|
|
const showLegend: boolean = this.widgetSettings.get('showLegend').value;
|
|
|
|
|
if (showLegend) {
|
|
|
|
|
this.widgetSettings.get('legendConfig').enable({emitEvent: false});
|
|
|
|
|
} else {
|
|
|
|
|
this.widgetSettings.get('legendConfig').disable({emitEvent: false});
|
2019-09-25 19:37:29 +03:00
|
|
|
}
|
2019-10-24 19:52:19 +03:00
|
|
|
const actionsData: WidgetActionsData = {
|
|
|
|
|
actionsMap: config.actions || {},
|
|
|
|
|
actionSources: this.modelValue.actionSources || {}
|
|
|
|
|
};
|
|
|
|
|
this.actionsSettings.patchValue(
|
|
|
|
|
{
|
|
|
|
|
actionsData
|
|
|
|
|
},
|
|
|
|
|
{emitEvent: false}
|
|
|
|
|
);
|
2019-10-10 13:00:29 +03:00
|
|
|
if (this.widgetType === widgetType.timeseries || this.widgetType === widgetType.alarm) {
|
|
|
|
|
const useDashboardTimewindow = isDefined(config.useDashboardTimewindow) ?
|
|
|
|
|
config.useDashboardTimewindow : true;
|
|
|
|
|
this.dataSettings.patchValue(
|
|
|
|
|
{ useDashboardTimewindow }, {emitEvent: false}
|
|
|
|
|
);
|
|
|
|
|
if (useDashboardTimewindow) {
|
|
|
|
|
this.dataSettings.get('displayTimewindow').disable({emitEvent: false});
|
|
|
|
|
this.dataSettings.get('timewindow').disable({emitEvent: false});
|
|
|
|
|
} else {
|
|
|
|
|
this.dataSettings.get('displayTimewindow').enable({emitEvent: false});
|
|
|
|
|
this.dataSettings.get('timewindow').enable({emitEvent: false});
|
|
|
|
|
}
|
|
|
|
|
this.dataSettings.patchValue(
|
|
|
|
|
{ displayTimewindow: isDefined(config.displayTimewindow) ?
|
|
|
|
|
config.displayTimewindow : true }, {emitEvent: false}
|
|
|
|
|
);
|
|
|
|
|
this.dataSettings.patchValue(
|
|
|
|
|
{ timewindow: config.timewindow }, {emitEvent: false}
|
|
|
|
|
);
|
|
|
|
|
}
|
2019-10-21 19:57:18 +03:00
|
|
|
if (this.modelValue.isDataEnabled) {
|
2019-09-25 19:37:29 +03:00
|
|
|
if (this.widgetType !== widgetType.rpc &&
|
|
|
|
|
this.widgetType !== widgetType.alarm &&
|
|
|
|
|
this.widgetType !== widgetType.static) {
|
2019-10-10 13:00:29 +03:00
|
|
|
const datasourcesFormArray = this.dataSettings.get('datasources') as FormArray;
|
2019-10-11 19:22:03 +03:00
|
|
|
datasourcesFormArray.clear();
|
2019-09-25 19:37:29 +03:00
|
|
|
if (config.datasources) {
|
2019-10-10 13:00:29 +03:00
|
|
|
config.datasources.forEach((datasource) => {
|
2019-10-11 19:22:03 +03:00
|
|
|
datasourcesFormArray.push(this.buildDatasourceForm(datasource));
|
2019-10-10 13:00:29 +03:00
|
|
|
});
|
2019-09-25 19:37:29 +03:00
|
|
|
}
|
|
|
|
|
} else if (this.widgetType === widgetType.rpc) {
|
2019-10-11 19:22:03 +03:00
|
|
|
let targetDeviceAliasId: string;
|
2019-09-25 19:37:29 +03:00
|
|
|
if (config.targetDeviceAliasIds && config.targetDeviceAliasIds.length > 0) {
|
|
|
|
|
const aliasId = config.targetDeviceAliasIds[0];
|
|
|
|
|
const entityAliases = this.aliasController.getEntityAliases();
|
|
|
|
|
if (entityAliases[aliasId]) {
|
2019-10-11 19:22:03 +03:00
|
|
|
targetDeviceAliasId = entityAliases[aliasId].id;
|
2019-09-25 19:37:29 +03:00
|
|
|
} else {
|
2019-10-11 19:22:03 +03:00
|
|
|
targetDeviceAliasId = null;
|
2019-09-25 19:37:29 +03:00
|
|
|
}
|
|
|
|
|
} else {
|
2019-10-11 19:22:03 +03:00
|
|
|
targetDeviceAliasId = null;
|
2019-09-25 19:37:29 +03:00
|
|
|
}
|
2019-10-11 19:22:03 +03:00
|
|
|
this.targetDeviceSettings.patchValue({
|
|
|
|
|
targetDeviceAliasId
|
|
|
|
|
}, {emitEvent: false});
|
2019-09-25 19:37:29 +03:00
|
|
|
} else if (this.widgetType === widgetType.alarm) {
|
2019-10-10 13:00:29 +03:00
|
|
|
this.dataSettings.patchValue(
|
|
|
|
|
{ alarmSearchStatus: isDefined(config.alarmSearchStatus) ?
|
|
|
|
|
config.alarmSearchStatus : AlarmSearchStatus.ANY }, {emitEvent: false}
|
|
|
|
|
);
|
|
|
|
|
this.dataSettings.patchValue(
|
|
|
|
|
{ alarmsPollingInterval: isDefined(config.alarmsPollingInterval) ?
|
|
|
|
|
config.alarmsPollingInterval : 5}, {emitEvent: false}
|
|
|
|
|
);
|
2020-02-21 16:31:03 +02:00
|
|
|
this.dataSettings.patchValue(
|
|
|
|
|
{ alarmsMaxCountLoad: isDefined(config.alarmsMaxCountLoad) ?
|
|
|
|
|
config.alarmsMaxCountLoad : 0}, {emitEvent: false}
|
|
|
|
|
);
|
|
|
|
|
this.dataSettings.patchValue(
|
|
|
|
|
{ alarmsFetchSize: isDefined(config.alarmsFetchSize) ?
|
|
|
|
|
config.alarmsFetchSize : 100}, {emitEvent: false}
|
|
|
|
|
);
|
2019-10-24 19:52:19 +03:00
|
|
|
this.alarmSourceSettings.patchValue(
|
|
|
|
|
config.alarmSource, {emitEvent: false}
|
|
|
|
|
);
|
|
|
|
|
const alarmSourceType: DatasourceType = this.alarmSourceSettings.get('type').value;
|
|
|
|
|
this.alarmSourceSettings.get('entityAliasId').setValidators(
|
|
|
|
|
alarmSourceType === DatasourceType.entity ? [Validators.required] : []
|
|
|
|
|
);
|
|
|
|
|
this.alarmSourceSettings.get('entityAliasId').updateValueAndValidity({emitEvent: false});
|
2019-09-25 19:37:29 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-21 19:57:18 +03:00
|
|
|
this.updateSchemaForm(config.settings);
|
2019-09-25 19:37:29 +03:00
|
|
|
|
|
|
|
|
if (layout) {
|
2019-10-24 19:52:19 +03:00
|
|
|
this.layoutSettings.patchValue(
|
|
|
|
|
{
|
|
|
|
|
mobileOrder: layout.mobileOrder,
|
|
|
|
|
mobileHeight: layout.mobileHeight
|
|
|
|
|
},
|
|
|
|
|
{emitEvent: false}
|
|
|
|
|
);
|
2019-09-25 19:37:29 +03:00
|
|
|
} else {
|
2019-10-24 19:52:19 +03:00
|
|
|
this.layoutSettings.patchValue(
|
|
|
|
|
{
|
|
|
|
|
mobileOrder: null,
|
|
|
|
|
mobileHeight: null
|
|
|
|
|
},
|
|
|
|
|
{emitEvent: false}
|
|
|
|
|
);
|
2019-09-25 19:37:29 +03:00
|
|
|
}
|
|
|
|
|
}
|
2019-10-11 19:22:03 +03:00
|
|
|
this.createChangeSubscriptions();
|
2019-09-25 19:37:29 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-24 19:52:19 +03:00
|
|
|
private buildDatasourceForm(datasource?: Datasource): FormGroup {
|
2019-10-21 19:57:18 +03:00
|
|
|
const dataKeysRequired = !this.modelValue.typeParameters || !this.modelValue.typeParameters.dataKeysOptional;
|
2019-10-11 19:22:03 +03:00
|
|
|
const datasourceFormGroup = this.fb.group(
|
|
|
|
|
{
|
|
|
|
|
type: [datasource ? datasource.type : null, [Validators.required]],
|
|
|
|
|
name: [datasource ? datasource.name : null, []],
|
|
|
|
|
entityAliasId: [datasource ? datasource.entityAliasId : null,
|
|
|
|
|
datasource && datasource.type === DatasourceType.entity ? [Validators.required] : []],
|
2019-10-17 18:23:53 +03:00
|
|
|
dataKeys: [datasource ? datasource.dataKeys : null, dataKeysRequired ? [Validators.required] : []]
|
2019-10-11 19:22:03 +03:00
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
datasourceFormGroup.get('type').valueChanges.subscribe((type: DatasourceType) => {
|
|
|
|
|
datasourceFormGroup.get('entityAliasId').setValidators(
|
|
|
|
|
type === DatasourceType.entity ? [Validators.required] : []
|
|
|
|
|
);
|
|
|
|
|
datasourceFormGroup.get('entityAliasId').updateValueAndValidity();
|
|
|
|
|
});
|
|
|
|
|
return datasourceFormGroup;
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-21 19:57:18 +03:00
|
|
|
private updateSchemaForm(settings?: any) {
|
|
|
|
|
const widgetSettingsFormData: JsonFormComponentData = {};
|
|
|
|
|
if (this.modelValue.settingsSchema && this.modelValue.settingsSchema.schema) {
|
|
|
|
|
widgetSettingsFormData.schema = this.modelValue.settingsSchema.schema;
|
|
|
|
|
widgetSettingsFormData.form = this.modelValue.settingsSchema.form || deepClone(defaultSettingsForm);
|
|
|
|
|
widgetSettingsFormData.groupInfoes = this.modelValue.settingsSchema.groupInfoes;
|
|
|
|
|
widgetSettingsFormData.model = settings;
|
2019-09-25 19:37:29 +03:00
|
|
|
} else {
|
2019-10-21 19:57:18 +03:00
|
|
|
widgetSettingsFormData.schema = deepClone(emptySettingsSchema);
|
|
|
|
|
widgetSettingsFormData.form = deepClone(defaultSettingsForm);
|
|
|
|
|
widgetSettingsFormData.groupInfoes = deepClone(emptySettingsGroupInfoes);
|
|
|
|
|
widgetSettingsFormData.model = {};
|
2019-09-25 19:37:29 +03:00
|
|
|
}
|
2019-10-21 19:57:18 +03:00
|
|
|
this.advancedSettings.patchValue({ settings: widgetSettingsFormData }, {emitEvent: false});
|
2019-09-25 19:37:29 +03:00
|
|
|
}
|
|
|
|
|
|
2019-10-11 19:22:03 +03:00
|
|
|
private updateDataSettings() {
|
2019-09-25 19:37:29 +03:00
|
|
|
if (this.modelValue) {
|
|
|
|
|
if (this.modelValue.config) {
|
2019-10-10 13:00:29 +03:00
|
|
|
Object.assign(this.modelValue.config, this.dataSettings.value);
|
2019-09-25 19:37:29 +03:00
|
|
|
}
|
|
|
|
|
this.propagateChange(this.modelValue);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-11 19:22:03 +03:00
|
|
|
private updateTargetDeviceSettings() {
|
|
|
|
|
if (this.modelValue) {
|
|
|
|
|
if (this.modelValue.config) {
|
|
|
|
|
const targetDeviceAliasId: string = this.targetDeviceSettings.get('targetDeviceAliasId').value;
|
|
|
|
|
if (targetDeviceAliasId) {
|
|
|
|
|
this.modelValue.config.targetDeviceAliasIds = [targetDeviceAliasId];
|
|
|
|
|
} else {
|
|
|
|
|
this.modelValue.config.targetDeviceAliasIds = [];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
this.propagateChange(this.modelValue);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-24 19:52:19 +03:00
|
|
|
private updateAlarmSourceSettings() {
|
|
|
|
|
if (this.modelValue) {
|
|
|
|
|
if (this.modelValue.config) {
|
|
|
|
|
const alarmSource: Datasource = this.alarmSourceSettings.value;
|
|
|
|
|
this.modelValue.config.alarmSource = alarmSource;
|
|
|
|
|
}
|
|
|
|
|
this.propagateChange(this.modelValue);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private updateWidgetSettings() {
|
|
|
|
|
if (this.modelValue) {
|
|
|
|
|
if (this.modelValue.config) {
|
|
|
|
|
Object.assign(this.modelValue.config, this.widgetSettings.value);
|
|
|
|
|
}
|
|
|
|
|
this.propagateChange(this.modelValue);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private updateLayoutSettings() {
|
|
|
|
|
if (this.modelValue) {
|
|
|
|
|
if (this.modelValue.layout) {
|
|
|
|
|
Object.assign(this.modelValue.layout, this.layoutSettings.value);
|
|
|
|
|
}
|
|
|
|
|
this.propagateChange(this.modelValue);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-21 19:57:18 +03:00
|
|
|
private updateAdvancedSettings() {
|
|
|
|
|
if (this.modelValue) {
|
|
|
|
|
if (this.modelValue.config) {
|
|
|
|
|
const settings = this.advancedSettings.get('settings').value.model;
|
|
|
|
|
this.modelValue.config.settings = settings;
|
|
|
|
|
}
|
|
|
|
|
this.propagateChange(this.modelValue);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-24 19:52:19 +03:00
|
|
|
private updateActionSettings() {
|
|
|
|
|
if (this.modelValue) {
|
|
|
|
|
if (this.modelValue.config) {
|
|
|
|
|
const actions = (this.actionsSettings.get('actionsData').value as WidgetActionsData).actionsMap;
|
|
|
|
|
this.modelValue.config.actions = actions;
|
|
|
|
|
}
|
|
|
|
|
this.propagateChange(this.modelValue);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-25 19:37:29 +03:00
|
|
|
public displayAdvanced(): boolean {
|
2019-10-31 18:33:51 +02:00
|
|
|
return this.modelValue && this.modelValue.settingsSchema && this.modelValue.settingsSchema.schema;
|
2019-09-25 19:37:29 +03:00
|
|
|
}
|
|
|
|
|
|
2019-10-10 13:00:29 +03:00
|
|
|
public removeDatasource(index: number) {
|
|
|
|
|
(this.dataSettings.get('datasources') as FormArray).removeAt(index);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public addDatasource() {
|
|
|
|
|
let newDatasource: Datasource;
|
|
|
|
|
if (this.functionsOnly) {
|
2019-10-21 19:57:18 +03:00
|
|
|
newDatasource = deepClone(this.utils.getDefaultDatasource(this.modelValue.dataKeySettingsSchema.schema));
|
2019-10-10 13:00:29 +03:00
|
|
|
newDatasource.dataKeys = [this.generateDataKey('Sin', DataKeyType.function)];
|
|
|
|
|
} else {
|
|
|
|
|
newDatasource = { type: DatasourceType.entity,
|
|
|
|
|
dataKeys: []
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
const datasourcesFormArray = this.dataSettings.get('datasources') as FormArray;
|
2019-10-11 19:22:03 +03:00
|
|
|
datasourcesFormArray.push(this.buildDatasourceForm(newDatasource));
|
2019-10-10 13:00:29 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public generateDataKey(chip: any, type: DataKeyType): DataKey {
|
|
|
|
|
if (isObject(chip)) {
|
|
|
|
|
(chip as DataKey)._hash = Math.random();
|
|
|
|
|
return chip;
|
|
|
|
|
} else {
|
|
|
|
|
let label: string = chip;
|
|
|
|
|
if (type === DataKeyType.alarm) {
|
|
|
|
|
const alarmField = alarmFields[label];
|
|
|
|
|
if (alarmField) {
|
|
|
|
|
label = this.translate.instant(alarmField.name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
label = this.genNextLabel(label);
|
|
|
|
|
const result: DataKey = {
|
|
|
|
|
name: chip,
|
|
|
|
|
type,
|
|
|
|
|
label,
|
|
|
|
|
color: this.genNextColor(),
|
|
|
|
|
settings: {},
|
|
|
|
|
_hash: Math.random()
|
|
|
|
|
};
|
|
|
|
|
if (type === DataKeyType.function) {
|
|
|
|
|
result.name = 'f(x)';
|
|
|
|
|
result.funcBody = this.utils.getPredefinedFunctionBody(chip);
|
|
|
|
|
if (!result.funcBody) {
|
|
|
|
|
result.funcBody = 'return prevValue + 1;';
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-10-21 19:57:18 +03:00
|
|
|
if (isDefined(this.modelValue.dataKeySettingsSchema.schema)) {
|
|
|
|
|
result.settings = this.utils.generateObjectFromJsonSchema(this.modelValue.dataKeySettingsSchema.schema);
|
2019-10-10 13:00:29 +03:00
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private genNextLabel(name: string): string {
|
|
|
|
|
let label = name;
|
|
|
|
|
let i = 1;
|
|
|
|
|
let matches = false;
|
|
|
|
|
const datasources = this.widgetType === widgetType.alarm ? [this.modelValue.config.alarmSource] : this.modelValue.config.datasources;
|
|
|
|
|
if (datasources) {
|
|
|
|
|
do {
|
|
|
|
|
matches = false;
|
|
|
|
|
datasources.forEach((datasource) => {
|
|
|
|
|
if (datasource && datasource.dataKeys) {
|
|
|
|
|
datasource.dataKeys.forEach((dataKey) => {
|
|
|
|
|
if (dataKey.label === label) {
|
|
|
|
|
i++;
|
|
|
|
|
label = name + ' ' + i;
|
|
|
|
|
matches = true;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} while (matches);
|
|
|
|
|
}
|
|
|
|
|
return label;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private genNextColor(): string {
|
|
|
|
|
let i = 0;
|
|
|
|
|
const datasources = this.widgetType === widgetType.alarm ? [this.modelValue.config.alarmSource] : this.modelValue.config.datasources;
|
|
|
|
|
if (datasources) {
|
|
|
|
|
datasources.forEach((datasource) => {
|
|
|
|
|
if (datasource && datasource.dataKeys) {
|
|
|
|
|
i += datasource.dataKeys.length;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
return this.utils.getMaterialColor(i);
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-11 19:22:03 +03:00
|
|
|
private createEntityAlias(alias: string, allowedEntityTypes: Array<EntityType>): Observable<EntityAlias> {
|
|
|
|
|
const singleEntityAlias: EntityAlias = {id: null, alias, filter: {resolveMultiple: false}};
|
|
|
|
|
return this.dialog.open<EntityAliasDialogComponent, EntityAliasDialogData,
|
|
|
|
|
EntityAlias>(EntityAliasDialogComponent, {
|
|
|
|
|
disableClose: true,
|
|
|
|
|
panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
|
|
|
|
|
data: {
|
|
|
|
|
isAdd: true,
|
|
|
|
|
allowedEntityTypes,
|
|
|
|
|
entityAliases: this.entityAliases,
|
|
|
|
|
alias: singleEntityAlias
|
|
|
|
|
}
|
|
|
|
|
}).afterClosed().pipe(
|
|
|
|
|
tap((entityAlias) => {
|
|
|
|
|
if (entityAlias) {
|
|
|
|
|
this.entityAliases[entityAlias.id] = entityAlias;
|
|
|
|
|
this.aliasController.updateEntityAliases(this.entityAliases);
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-17 18:23:53 +03:00
|
|
|
private fetchEntityKeys(entityAliasId: string, query: string, dataKeyTypes: Array<DataKeyType>): Observable<Array<DataKey>> {
|
|
|
|
|
return this.aliasController.getAliasInfo(entityAliasId).pipe(
|
|
|
|
|
mergeMap((aliasInfo) => {
|
|
|
|
|
const entity = aliasInfo.currentEntity;
|
|
|
|
|
if (entity) {
|
|
|
|
|
const fetchEntityTasks: Array<Observable<Array<DataKey>>> = [];
|
|
|
|
|
for (const dataKeyType of dataKeyTypes) {
|
|
|
|
|
fetchEntityTasks.push(
|
|
|
|
|
this.entityService.getEntityKeys(
|
|
|
|
|
{entityType: entity.entityType, id: entity.id},
|
|
|
|
|
query,
|
|
|
|
|
dataKeyType,
|
2019-11-15 12:22:14 +02:00
|
|
|
{ignoreLoading: true, ignoreErrors: true}
|
2019-10-17 18:23:53 +03:00
|
|
|
).pipe(
|
|
|
|
|
map((keys) => {
|
|
|
|
|
const dataKeys: Array<DataKey> = [];
|
|
|
|
|
for (const key of keys) {
|
|
|
|
|
dataKeys.push({name: key, type: dataKeyType});
|
|
|
|
|
}
|
|
|
|
|
return dataKeys;
|
|
|
|
|
}
|
|
|
|
|
),
|
|
|
|
|
catchError(val => of([]))
|
|
|
|
|
));
|
|
|
|
|
}
|
|
|
|
|
return forkJoin(fetchEntityTasks).pipe(
|
|
|
|
|
map(arrayOfDataKeys => {
|
|
|
|
|
const result = new Array<DataKey>();
|
|
|
|
|
arrayOfDataKeys.forEach((dataKeyArray) => {
|
|
|
|
|
result.push(...dataKeyArray);
|
|
|
|
|
});
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
));
|
|
|
|
|
} else {
|
|
|
|
|
return of([]);
|
|
|
|
|
}
|
|
|
|
|
}),
|
|
|
|
|
catchError(val => of([] as Array<DataKey>))
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-24 19:52:19 +03:00
|
|
|
private fetchDashboardStates(query: string): Array<string> {
|
|
|
|
|
const stateIds = Object.keys(this.dashboardStates);
|
|
|
|
|
const result = query ? stateIds.filter(this.createFilterForDashboardState(query)) : stateIds;
|
|
|
|
|
if (result && result.length) {
|
|
|
|
|
return result;
|
|
|
|
|
} else {
|
|
|
|
|
return [query];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private createFilterForDashboardState(query: string): (stateId: string) => boolean {
|
|
|
|
|
const lowercaseQuery = query.toLowerCase();
|
|
|
|
|
return stateId => stateId.toLowerCase().indexOf(lowercaseQuery) === 0;
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-25 19:37:29 +03:00
|
|
|
public validate(c: FormControl) {
|
2019-10-10 13:00:29 +03:00
|
|
|
if (!this.dataSettings.valid) {
|
|
|
|
|
return {
|
|
|
|
|
dataSettings: {
|
|
|
|
|
valid: false
|
|
|
|
|
}
|
|
|
|
|
};
|
2019-10-24 19:52:19 +03:00
|
|
|
} else if (!this.widgetSettings.valid) {
|
|
|
|
|
return {
|
|
|
|
|
widgetSettings: {
|
|
|
|
|
valid: false
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
} else if (!this.layoutSettings.valid) {
|
|
|
|
|
return {
|
|
|
|
|
widgetSettings: {
|
|
|
|
|
valid: false
|
|
|
|
|
}
|
|
|
|
|
};
|
2019-10-21 19:57:18 +03:00
|
|
|
} else if (!this.advancedSettings.valid) {
|
|
|
|
|
return {
|
|
|
|
|
advancedSettings: {
|
|
|
|
|
valid: false
|
|
|
|
|
}
|
|
|
|
|
};
|
2019-10-31 18:33:51 +02:00
|
|
|
} else if (this.modelValue) {
|
2019-10-10 13:00:29 +03:00
|
|
|
const config = this.modelValue.config;
|
2019-10-21 19:57:18 +03:00
|
|
|
if (this.widgetType === widgetType.rpc && this.modelValue.isDataEnabled) {
|
2019-10-10 13:00:29 +03:00
|
|
|
if (!config.targetDeviceAliasIds || !config.targetDeviceAliasIds.length) {
|
|
|
|
|
return {
|
|
|
|
|
targetDeviceAliasIds: {
|
|
|
|
|
valid: false
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
2019-10-21 19:57:18 +03:00
|
|
|
} else if (this.widgetType === widgetType.alarm && this.modelValue.isDataEnabled) {
|
2019-10-10 13:00:29 +03:00
|
|
|
if (!config.alarmSource) {
|
|
|
|
|
return {
|
|
|
|
|
alarmSource: {
|
|
|
|
|
valid: false
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
2019-10-21 19:57:18 +03:00
|
|
|
} else if (this.widgetType !== widgetType.static && this.modelValue.isDataEnabled) {
|
2019-10-10 13:00:29 +03:00
|
|
|
if (!config.datasources || !config.datasources.length) {
|
|
|
|
|
return {
|
|
|
|
|
datasources: {
|
|
|
|
|
valid: false
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return null;
|
2019-09-25 19:37:29 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|