|
|
@ -21,7 +21,7 @@ import { AppState } from '@core/core.state'; |
|
|
import { |
|
|
import { |
|
|
DataKey, |
|
|
DataKey, |
|
|
Datasource, |
|
|
Datasource, |
|
|
DatasourceType, |
|
|
DatasourceType, datasourceTypeTranslationMap, |
|
|
LegendConfig, |
|
|
LegendConfig, |
|
|
WidgetActionDescriptor, |
|
|
WidgetActionDescriptor, |
|
|
WidgetActionSource, |
|
|
WidgetActionSource, |
|
|
@ -30,6 +30,7 @@ import { |
|
|
WidgetTypeParameters |
|
|
WidgetTypeParameters |
|
|
} from '@shared/models/widget.models'; |
|
|
} from '@shared/models/widget.models'; |
|
|
import { |
|
|
import { |
|
|
|
|
|
AbstractControl, |
|
|
ControlValueAccessor, |
|
|
ControlValueAccessor, |
|
|
FormArray, |
|
|
FormArray, |
|
|
FormBuilder, |
|
|
FormBuilder, |
|
|
@ -44,10 +45,19 @@ import { WidgetConfigComponentData } from '@home/models/widget-component.models' |
|
|
import { deepClone, isDefined, isObject } from '@app/core/utils'; |
|
|
import { deepClone, isDefined, isObject } from '@app/core/utils'; |
|
|
import { alarmFields, AlarmSearchStatus } from '@shared/models/alarm.models'; |
|
|
import { alarmFields, AlarmSearchStatus } from '@shared/models/alarm.models'; |
|
|
import { IAliasController } from '@core/api/widget-api.models'; |
|
|
import { IAliasController } from '@core/api/widget-api.models'; |
|
|
import { EntityAlias } from '@shared/models/alias.models'; |
|
|
import { EntityAlias, EntityAliases } from '@shared/models/alias.models'; |
|
|
import { UtilsService } from '@core/services/utils.service'; |
|
|
import { UtilsService } from '@core/services/utils.service'; |
|
|
import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; |
|
|
import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; |
|
|
import { TranslateService } from '@ngx-translate/core'; |
|
|
import { TranslateService } from '@ngx-translate/core'; |
|
|
|
|
|
import { EntityType } from '@shared/models/entity-type.models'; |
|
|
|
|
|
import { Observable, of, Subscription } from 'rxjs'; |
|
|
|
|
|
import { WidgetConfigCallbacks } from '@home/components/widget/widget-config.component.models'; |
|
|
|
|
|
import { |
|
|
|
|
|
EntityAliasDialogComponent, |
|
|
|
|
|
EntityAliasDialogData |
|
|
|
|
|
} from '@home/components/alias/entity-alias-dialog.component'; |
|
|
|
|
|
import { tap } from 'rxjs/operators'; |
|
|
|
|
|
import { MatDialog } from '@angular/material/dialog'; |
|
|
|
|
|
|
|
|
@Component({ |
|
|
@Component({ |
|
|
selector: 'tb-widget-config', |
|
|
selector: 'tb-widget-config', |
|
|
@ -70,6 +80,8 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, Cont |
|
|
|
|
|
|
|
|
widgetTypes = widgetType; |
|
|
widgetTypes = widgetType; |
|
|
|
|
|
|
|
|
|
|
|
entityTypes = EntityType; |
|
|
|
|
|
|
|
|
alarmSearchStatuses = Object.keys(AlarmSearchStatus); |
|
|
alarmSearchStatuses = Object.keys(AlarmSearchStatus); |
|
|
|
|
|
|
|
|
@Input() |
|
|
@Input() |
|
|
@ -87,6 +99,9 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, Cont |
|
|
@Input() |
|
|
@Input() |
|
|
aliasController: IAliasController; |
|
|
aliasController: IAliasController; |
|
|
|
|
|
|
|
|
|
|
|
@Input() |
|
|
|
|
|
entityAliases: EntityAliases; |
|
|
|
|
|
|
|
|
@Input() |
|
|
@Input() |
|
|
widgetSettingsSchema: any; |
|
|
widgetSettingsSchema: any; |
|
|
|
|
|
|
|
|
@ -100,6 +115,17 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, Cont |
|
|
|
|
|
|
|
|
widgetType: widgetType; |
|
|
widgetType: widgetType; |
|
|
|
|
|
|
|
|
|
|
|
datasourceType = DatasourceType; |
|
|
|
|
|
datasourceTypes: Array<DatasourceType>; |
|
|
|
|
|
datasourceTypesTranslations = datasourceTypeTranslationMap; |
|
|
|
|
|
|
|
|
|
|
|
widgetConfigCallbacks: WidgetConfigCallbacks = { |
|
|
|
|
|
createEntityAlias: this.createEntityAlias.bind(this), |
|
|
|
|
|
generateDataKey: this.generateDataKey.bind(this) |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
widgetEditMode = this.utils.widgetEditMode; |
|
|
|
|
|
|
|
|
selectedTab: number; |
|
|
selectedTab: number; |
|
|
title: string; |
|
|
title: string; |
|
|
showTitleIcon: boolean; |
|
|
showTitleIcon: boolean; |
|
|
@ -120,7 +146,6 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, Cont |
|
|
showLegend: boolean; |
|
|
showLegend: boolean; |
|
|
legendConfig: LegendConfig; |
|
|
legendConfig: LegendConfig; |
|
|
actions: {[actionSourceId: string]: Array<WidgetActionDescriptor>}; |
|
|
actions: {[actionSourceId: string]: Array<WidgetActionDescriptor>}; |
|
|
targetDeviceAlias: EntityAlias; |
|
|
|
|
|
alarmSource: Datasource; |
|
|
alarmSource: Datasource; |
|
|
settings: WidgetConfigSettings; |
|
|
settings: WidgetConfigSettings; |
|
|
mobileOrder: number; |
|
|
mobileOrder: number; |
|
|
@ -149,20 +174,50 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, Cont |
|
|
private propagateChange = null; |
|
|
private propagateChange = null; |
|
|
|
|
|
|
|
|
public dataSettings: FormGroup; |
|
|
public dataSettings: FormGroup; |
|
|
|
|
|
public targetDeviceSettings: FormGroup; |
|
|
|
|
|
|
|
|
|
|
|
private dataSettingsChangesSubscription: Subscription; |
|
|
|
|
|
private targetDeviceSettingsSubscription: Subscription; |
|
|
|
|
|
|
|
|
constructor(protected store: Store<AppState>, |
|
|
constructor(protected store: Store<AppState>, |
|
|
private utils: UtilsService, |
|
|
private utils: UtilsService, |
|
|
|
|
|
private dialog: MatDialog, |
|
|
private translate: TranslateService, |
|
|
private translate: TranslateService, |
|
|
private fb: FormBuilder) { |
|
|
private fb: FormBuilder) { |
|
|
super(store); |
|
|
super(store); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
ngOnInit(): void { |
|
|
ngOnInit(): void { |
|
|
|
|
|
if (this.functionsOnly) { |
|
|
|
|
|
this.datasourceTypes = [DatasourceType.function]; |
|
|
|
|
|
} else { |
|
|
|
|
|
this.datasourceTypes = [DatasourceType.function, DatasourceType.entity]; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private removeChangeSubscriptions() { |
|
|
|
|
|
if (this.dataSettingsChangesSubscription) { |
|
|
|
|
|
this.dataSettingsChangesSubscription.unsubscribe(); |
|
|
|
|
|
this.dataSettingsChangesSubscription = null; |
|
|
|
|
|
} |
|
|
|
|
|
if (this.targetDeviceSettingsSubscription) { |
|
|
|
|
|
this.targetDeviceSettingsSubscription.unsubscribe(); |
|
|
|
|
|
this.targetDeviceSettingsSubscription = null; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private createChangeSubscriptions() { |
|
|
|
|
|
this.dataSettingsChangesSubscription = this.dataSettings.valueChanges.subscribe( |
|
|
|
|
|
() => this.updateDataSettings() |
|
|
|
|
|
); |
|
|
|
|
|
this.targetDeviceSettingsSubscription = this.targetDeviceSettings.valueChanges.subscribe( |
|
|
|
|
|
() => this.updateTargetDeviceSettings() |
|
|
|
|
|
); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private buildForms() { |
|
|
private buildForms() { |
|
|
this.dataSettings = this.fb.group({}); |
|
|
this.dataSettings = this.fb.group({}); |
|
|
|
|
|
this.targetDeviceSettings = this.fb.group({}); |
|
|
if (this.widgetType === widgetType.timeseries || this.widgetType === widgetType.alarm) { |
|
|
if (this.widgetType === widgetType.timeseries || this.widgetType === widgetType.alarm) { |
|
|
this.dataSettings.addControl('useDashboardTimewindow', this.fb.control(null)); |
|
|
this.dataSettings.addControl('useDashboardTimewindow', this.fb.control(null)); |
|
|
this.dataSettings.addControl('displayTimewindow', this.fb.control(null)); |
|
|
this.dataSettings.addControl('displayTimewindow', this.fb.control(null)); |
|
|
@ -188,11 +243,12 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, Cont |
|
|
this.widgetType !== widgetType.static) { |
|
|
this.widgetType !== widgetType.static) { |
|
|
this.dataSettings.addControl('datasources', |
|
|
this.dataSettings.addControl('datasources', |
|
|
this.fb.array([])); |
|
|
this.fb.array([])); |
|
|
|
|
|
} else if (this.widgetType === widgetType.rpc) { |
|
|
|
|
|
this.targetDeviceSettings.addControl('targetDeviceAliasId', |
|
|
|
|
|
this.fb.control(null, |
|
|
|
|
|
this.widgetEditMode ? [] : [Validators.required])); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
this.dataSettings.valueChanges.subscribe( |
|
|
|
|
|
() => this.updateModel() |
|
|
|
|
|
); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
registerOnChange(fn: any): void { |
|
|
registerOnChange(fn: any): void { |
|
|
@ -208,6 +264,7 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, Cont |
|
|
|
|
|
|
|
|
writeValue(value: WidgetConfigComponentData): void { |
|
|
writeValue(value: WidgetConfigComponentData): void { |
|
|
this.modelValue = value; |
|
|
this.modelValue = value; |
|
|
|
|
|
this.removeChangeSubscriptions(); |
|
|
if (this.modelValue) { |
|
|
if (this.modelValue) { |
|
|
if (this.widgetType !== this.modelValue.widgetType) { |
|
|
if (this.widgetType !== this.modelValue.widgetType) { |
|
|
this.widgetType = this.modelValue.widgetType; |
|
|
this.widgetType = this.modelValue.widgetType; |
|
|
@ -268,25 +325,28 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, Cont |
|
|
this.widgetType !== widgetType.alarm && |
|
|
this.widgetType !== widgetType.alarm && |
|
|
this.widgetType !== widgetType.static) { |
|
|
this.widgetType !== widgetType.static) { |
|
|
const datasourcesFormArray = this.dataSettings.get('datasources') as FormArray; |
|
|
const datasourcesFormArray = this.dataSettings.get('datasources') as FormArray; |
|
|
datasourcesFormArray.controls.length = 0; |
|
|
datasourcesFormArray.clear(); |
|
|
if (config.datasources) { |
|
|
if (config.datasources) { |
|
|
config.datasources.forEach((datasource) => { |
|
|
config.datasources.forEach((datasource) => { |
|
|
datasourcesFormArray.controls.push(this.fb.control(datasource)); |
|
|
datasourcesFormArray.push(this.buildDatasourceForm(datasource)); |
|
|
}); |
|
|
}); |
|
|
datasourcesFormArray.setValue(config.datasources, {emitEvent: false}); |
|
|
|
|
|
} |
|
|
} |
|
|
} else if (this.widgetType === widgetType.rpc) { |
|
|
} else if (this.widgetType === widgetType.rpc) { |
|
|
|
|
|
let targetDeviceAliasId: string; |
|
|
if (config.targetDeviceAliasIds && config.targetDeviceAliasIds.length > 0) { |
|
|
if (config.targetDeviceAliasIds && config.targetDeviceAliasIds.length > 0) { |
|
|
const aliasId = config.targetDeviceAliasIds[0]; |
|
|
const aliasId = config.targetDeviceAliasIds[0]; |
|
|
const entityAliases = this.aliasController.getEntityAliases(); |
|
|
const entityAliases = this.aliasController.getEntityAliases(); |
|
|
if (entityAliases[aliasId]) { |
|
|
if (entityAliases[aliasId]) { |
|
|
this.targetDeviceAlias = entityAliases[aliasId]; |
|
|
targetDeviceAliasId = entityAliases[aliasId].id; |
|
|
} else { |
|
|
} else { |
|
|
this.targetDeviceAlias = null; |
|
|
targetDeviceAliasId = null; |
|
|
} |
|
|
} |
|
|
} else { |
|
|
} else { |
|
|
this.targetDeviceAlias = null; |
|
|
targetDeviceAliasId = null; |
|
|
} |
|
|
} |
|
|
|
|
|
this.targetDeviceSettings.patchValue({ |
|
|
|
|
|
targetDeviceAliasId |
|
|
|
|
|
}, {emitEvent: false}); |
|
|
} else if (this.widgetType === widgetType.alarm) { |
|
|
} else if (this.widgetType === widgetType.alarm) { |
|
|
this.dataSettings.patchValue( |
|
|
this.dataSettings.patchValue( |
|
|
{ alarmSearchStatus: isDefined(config.alarmSearchStatus) ? |
|
|
{ alarmSearchStatus: isDefined(config.alarmSearchStatus) ? |
|
|
@ -315,9 +375,38 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, Cont |
|
|
this.mobileHeight = undefined; |
|
|
this.mobileHeight = undefined; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
this.createChangeSubscriptions(); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private buildDatasourceForm(datasource?: Datasource): AbstractControl { |
|
|
|
|
|
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] : []], |
|
|
|
|
|
dataKeys: [datasource ? datasource.name : null, []] |
|
|
|
|
|
} |
|
|
|
|
|
); |
|
|
|
|
|
datasourceFormGroup.get('type').valueChanges.subscribe((type: DatasourceType) => { |
|
|
|
|
|
let dataKeys; |
|
|
|
|
|
if (this.widgetType === widgetType.alarm) { |
|
|
|
|
|
dataKeys = this.utils.getDefaultAlarmDataKeys(); |
|
|
|
|
|
} else { |
|
|
|
|
|
dataKeys = []; |
|
|
|
|
|
} |
|
|
|
|
|
datasourceFormGroup.patchValue({ |
|
|
|
|
|
dataKeys |
|
|
|
|
|
}); |
|
|
|
|
|
datasourceFormGroup.get('entityAliasId').setValidators( |
|
|
|
|
|
type === DatasourceType.entity ? [Validators.required] : [] |
|
|
|
|
|
); |
|
|
|
|
|
datasourceFormGroup.get('entityAliasId').updateValueAndValidity(); |
|
|
|
|
|
}); |
|
|
|
|
|
return datasourceFormGroup; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
private updateSchemaForm() { |
|
|
private updateSchemaForm() { |
|
|
if (this.widgetSettingsSchema && this.widgetSettingsSchema.schema) { |
|
|
if (this.widgetSettingsSchema && this.widgetSettingsSchema.schema) { |
|
|
this.currentSettingsSchema = this.widgetSettingsSchema.schema; |
|
|
this.currentSettingsSchema = this.widgetSettingsSchema.schema; |
|
|
@ -332,7 +421,7 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, Cont |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private updateModel() { |
|
|
private updateDataSettings() { |
|
|
if (this.modelValue) { |
|
|
if (this.modelValue) { |
|
|
if (this.modelValue.config) { |
|
|
if (this.modelValue.config) { |
|
|
Object.assign(this.modelValue.config, this.dataSettings.value); |
|
|
Object.assign(this.modelValue.config, this.dataSettings.value); |
|
|
@ -341,6 +430,20 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, Cont |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
public displayAdvanced(): boolean { |
|
|
public displayAdvanced(): boolean { |
|
|
return this.widgetSettingsSchema && this.widgetSettingsSchema.schema; |
|
|
return this.widgetSettingsSchema && this.widgetSettingsSchema.schema; |
|
|
} |
|
|
} |
|
|
@ -360,7 +463,7 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, Cont |
|
|
}; |
|
|
}; |
|
|
} |
|
|
} |
|
|
const datasourcesFormArray = this.dataSettings.get('datasources') as FormArray; |
|
|
const datasourcesFormArray = this.dataSettings.get('datasources') as FormArray; |
|
|
datasourcesFormArray.push(this.fb.control(newDatasource)); |
|
|
datasourcesFormArray.push(this.buildDatasourceForm(newDatasource)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public generateDataKey(chip: any, type: DataKeyType): DataKey { |
|
|
public generateDataKey(chip: any, type: DataKeyType): DataKey { |
|
|
@ -435,6 +538,28 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, Cont |
|
|
return this.utils.getMaterialColor(i); |
|
|
return this.utils.getMaterialColor(i); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
|
} |
|
|
|
|
|
}) |
|
|
|
|
|
); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
public validate(c: FormControl) { |
|
|
public validate(c: FormControl) { |
|
|
if (!this.dataSettings.valid) { |
|
|
if (!this.dataSettings.valid) { |
|
|
return { |
|
|
return { |
|
|
|