Merge pull request #3749 from vvlladd28/improvement/device-profile/protobuf
UI: Refactoring device-profile payload type protobuf; Refactoring view
This commit is contained in:
commit
9e8e46f139
@ -88,7 +88,7 @@ export class DeviceProfileComponent extends EntityComponent<DeviceProfile> {
|
|||||||
this.displayTransportConfiguration = entity && entity.transportType &&
|
this.displayTransportConfiguration = entity && entity.transportType &&
|
||||||
deviceTransportTypeConfigurationInfoMap.get(entity.transportType).hasProfileConfiguration;
|
deviceTransportTypeConfigurationInfoMap.get(entity.transportType).hasProfileConfiguration;
|
||||||
const deviceProvisionConfiguration: DeviceProvisionConfiguration = {
|
const deviceProvisionConfiguration: DeviceProvisionConfiguration = {
|
||||||
type: entity?.provisionType ? entity?.provisionType : DeviceProvisionType.DISABLED,
|
type: entity?.provisionType ? entity.provisionType : DeviceProvisionType.DISABLED,
|
||||||
provisionDeviceKey: entity?.provisionDeviceKey,
|
provisionDeviceKey: entity?.provisionDeviceKey,
|
||||||
provisionDeviceSecret: entity?.profileData?.provisionConfiguration?.provisionDeviceSecret
|
provisionDeviceSecret: entity?.profileData?.provisionConfiguration?.provisionDeviceSecret
|
||||||
};
|
};
|
||||||
@ -162,7 +162,7 @@ export class DeviceProfileComponent extends EntityComponent<DeviceProfile> {
|
|||||||
this.displayTransportConfiguration = entity.transportType &&
|
this.displayTransportConfiguration = entity.transportType &&
|
||||||
deviceTransportTypeConfigurationInfoMap.get(entity.transportType).hasProfileConfiguration;
|
deviceTransportTypeConfigurationInfoMap.get(entity.transportType).hasProfileConfiguration;
|
||||||
const deviceProvisionConfiguration: DeviceProvisionConfiguration = {
|
const deviceProvisionConfiguration: DeviceProvisionConfiguration = {
|
||||||
type: entity?.provisionType ? entity?.provisionType : DeviceProvisionType.DISABLED,
|
type: entity?.provisionType ? entity.provisionType : DeviceProvisionType.DISABLED,
|
||||||
provisionDeviceKey: entity?.provisionDeviceKey,
|
provisionDeviceKey: entity?.provisionDeviceKey,
|
||||||
provisionDeviceSecret: entity?.profileData?.provisionConfiguration?.provisionDeviceSecret
|
provisionDeviceSecret: entity?.profileData?.provisionConfiguration?.provisionDeviceSecret
|
||||||
};
|
};
|
||||||
|
|||||||
@ -16,86 +16,80 @@
|
|||||||
|
|
||||||
-->
|
-->
|
||||||
<form [formGroup]="mqttDeviceProfileTransportConfigurationFormGroup" style="padding-bottom: 16px;">
|
<form [formGroup]="mqttDeviceProfileTransportConfigurationFormGroup" style="padding-bottom: 16px;">
|
||||||
<section formGroupName="configuration">
|
<fieldset class="fields-group">
|
||||||
|
<legend class="group-title" translate>device-profile.mqtt-device-topic-filters</legend>
|
||||||
|
<div fxLayoutGap="8px" fxLayout="column">
|
||||||
|
<div fxLayout="row" fxLayoutGap="8px" fxLayout.xs="column">
|
||||||
|
<mat-form-field fxFlex>
|
||||||
|
<mat-label translate>device-profile.telemetry-topic-filter</mat-label>
|
||||||
|
<input matInput required
|
||||||
|
formControlName="deviceTelemetryTopic"
|
||||||
|
type="text">
|
||||||
|
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('deviceTelemetryTopic').hasError('required')">
|
||||||
|
{{ 'device-profile.telemetry-topic-filter-required' | translate}}
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('deviceTelemetryTopic').hasError('invalidSingleTopicCharacter')">
|
||||||
|
{{ 'device-profile.not-valid-single-character' | translate}}
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('deviceTelemetryTopic').hasError('invalidMultiTopicCharacter')">
|
||||||
|
{{ 'device-profile.not-valid-multi-character' | translate}}
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field fxFlex>
|
||||||
|
<mat-label translate>device-profile.attributes-topic-filter</mat-label>
|
||||||
|
<input matInput required
|
||||||
|
formControlName="deviceAttributesTopic"
|
||||||
|
type="text">
|
||||||
|
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('deviceAttributesTopic').hasError('required')">
|
||||||
|
{{ 'device-profile.attributes-topic-filter-required' | translate}}
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('deviceAttributesTopic').hasError('invalidSingleTopicCharacter')">
|
||||||
|
{{ 'device-profile.not-valid-single-character' | translate}}
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('deviceAttributesTopic').hasError('invalidMultiTopicCharacter')">
|
||||||
|
{{ 'device-profile.not-valid-multi-character' | translate}}
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.hasError('unique')">
|
||||||
|
{{ 'device-profile.mqtt-device-topic-filters-unique' | translate }}
|
||||||
|
</mat-error>
|
||||||
|
<div class="tb-hint" innerHTML="{{ 'device-profile.support-level-wildcards' | translate }}"></div>
|
||||||
|
<div class="tb-hint" innerHTML="{{ 'device-profile.single-level-wildcards-hint' | translate }}"></div>
|
||||||
|
<div class="tb-hint" innerHTML="{{ 'device-profile.multi-level-wildcards-hint' | translate }}"></div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
<section formGroupName="transportPayloadTypeConfiguration">
|
||||||
<fieldset class="fields-group">
|
<fieldset class="fields-group">
|
||||||
<legend class="group-title" translate>device-profile.mqtt-device-topic-filters</legend>
|
<legend class="group-title" translate>device-profile.mqtt-device-payload-type</legend>
|
||||||
<div fxLayoutGap="8px" fxLayout="column">
|
<div fxLayoutGap="8px" fxLayout="column">
|
||||||
<div fxLayout="row" fxLayoutGap="8px" fxLayout.xs="column">
|
<mat-form-field class="mat-block">
|
||||||
|
<mat-select formControlName="transportPayloadType" required>
|
||||||
|
<mat-option *ngFor="let type of mqttTransportPayloadTypes" [value]="type">
|
||||||
|
{{mqttTransportPayloadTypeTranslations.get(type) | translate}}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('transportPayloadTypeConfiguration.transportPayloadType').hasError('required')">
|
||||||
|
{{ 'device-profile.mqtt-payload-type-required' | translate }}
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
<div *ngIf="protoPayloadType" fxLayout="column">
|
||||||
<mat-form-field fxFlex>
|
<mat-form-field fxFlex>
|
||||||
<mat-label translate>device-profile.telemetry-topic-filter</mat-label>
|
<mat-label translate>device-profile.telemetry-proto-schema</mat-label>
|
||||||
<input matInput required
|
<textarea matInput required formControlName="deviceTelemetryProtoSchema" rows="5"></textarea>
|
||||||
formControlName="deviceTelemetryTopic"
|
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('transportPayloadTypeConfiguration.deviceTelemetryProtoSchema').hasError('required')">
|
||||||
type="text">
|
{{ 'device-profile.telemetry-proto-schema-required' | translate}}
|
||||||
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.deviceTelemetryTopic').hasError('required')">
|
|
||||||
{{ 'device-profile.telemetry-topic-filter-required' | translate}}
|
|
||||||
</mat-error>
|
|
||||||
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.deviceTelemetryTopic').hasError('invalidSingleTopicCharacter')">
|
|
||||||
{{ 'device-profile.not-valid-single-character' | translate}}
|
|
||||||
</mat-error>
|
|
||||||
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.deviceTelemetryTopic').hasError('invalidMultiTopicCharacter')">
|
|
||||||
{{ 'device-profile.not-valid-multi-character' | translate}}
|
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-form-field fxFlex>
|
<mat-form-field fxFlex>
|
||||||
<mat-label translate>device-profile.attributes-topic-filter</mat-label>
|
<mat-label translate>device-profile.attributes-proto-schema</mat-label>
|
||||||
<input matInput required
|
<textarea matInput required formControlName="deviceAttributesProtoSchema" rows="5"></textarea>
|
||||||
formControlName="deviceAttributesTopic"
|
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('transportPayloadTypeConfiguration.deviceAttributesProtoSchema').hasError('required')">
|
||||||
type="text">
|
{{ 'device-profile.attributes-proto-schema-required' | translate}}
|
||||||
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.deviceAttributesTopic').hasError('required')">
|
|
||||||
{{ 'device-profile.attributes-topic-filter-required' | translate}}
|
|
||||||
</mat-error>
|
|
||||||
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.deviceAttributesTopic').hasError('invalidSingleTopicCharacter')">
|
|
||||||
{{ 'device-profile.not-valid-single-character' | translate}}
|
|
||||||
</mat-error>
|
|
||||||
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.deviceAttributesTopic').hasError('invalidMultiTopicCharacter')">
|
|
||||||
{{ 'device-profile.not-valid-multi-character' | translate}}
|
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration').hasError('unique')">
|
|
||||||
{{ 'device-profile.mqtt-device-topic-filters-unique' | translate }}
|
|
||||||
</mat-error>
|
|
||||||
<div class="tb-hint" innerHTML="{{ 'device-profile.support-level-wildcards' | translate }}"></div>
|
|
||||||
<div class="tb-hint" innerHTML="{{ 'device-profile.single-level-wildcards-hint' | translate }}"></div>
|
|
||||||
<div class="tb-hint" innerHTML="{{ 'device-profile.multi-level-wildcards-hint' | translate }}"></div>
|
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<section formGroupName="transportPayloadTypeConfiguration">
|
|
||||||
<fieldset class="fields-group">
|
|
||||||
<legend class="group-title" translate>device-profile.mqtt-device-payload-type</legend>
|
|
||||||
<div fxLayoutGap="8px" fxLayout="column">
|
|
||||||
<mat-form-field class="mat-block">
|
|
||||||
<mat-select formControlName="transportPayloadType" required>
|
|
||||||
<mat-option *ngFor="let type of mqttTransportPayloadTypes" [value]="type">
|
|
||||||
{{mqttTransportPayloadTypeTranslations.get(type) | translate}}
|
|
||||||
</mat-option>
|
|
||||||
</mat-select>
|
|
||||||
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.transportPayloadTypeConfiguration.transportPayloadType').hasError('required')">
|
|
||||||
{{ 'device-profile.mqtt-payload-type-required' | translate }}
|
|
||||||
</mat-error>
|
|
||||||
</mat-form-field>
|
|
||||||
<div *ngIf="protoPayloadType" fxLayout="column">
|
|
||||||
<mat-form-field fxFlex>
|
|
||||||
<mat-label translate>device-profile.telemetry-proto-schema</mat-label>
|
|
||||||
<textarea matInput required
|
|
||||||
formControlName="deviceTelemetryProtoSchema"
|
|
||||||
rows="5"></textarea>
|
|
||||||
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.transportPayloadTypeConfiguration.deviceTelemetryProtoSchema').hasError('required')">
|
|
||||||
{{ 'device-profile.telemetry-proto-schema-required' | translate}}
|
|
||||||
</mat-error>
|
|
||||||
</mat-form-field>
|
|
||||||
<mat-form-field fxFlex>
|
|
||||||
<mat-label translate>device-profile.attributes-proto-schema</mat-label>
|
|
||||||
<textarea matInput required
|
|
||||||
formControlName="deviceAttributesProtoSchema"
|
|
||||||
rows="5"></textarea>
|
|
||||||
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.transportPayloadTypeConfiguration.deviceAttributesProtoSchema').hasError('required')">
|
|
||||||
{{ 'device-profile.attributes-proto-schema-required' | translate}}
|
|
||||||
</mat-error>
|
|
||||||
</mat-form-field>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
|
||||||
</section>
|
|
||||||
</section>
|
</section>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@ -54,6 +54,34 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control
|
|||||||
|
|
||||||
mqttDeviceProfileTransportConfigurationFormGroup: FormGroup;
|
mqttDeviceProfileTransportConfigurationFormGroup: FormGroup;
|
||||||
|
|
||||||
|
private defaultTelemetrySchema =
|
||||||
|
'syntax ="proto3";\n' +
|
||||||
|
'package telemetry;\n' +
|
||||||
|
'\n' +
|
||||||
|
'message SensorDataReading {\n' +
|
||||||
|
'\n' +
|
||||||
|
' double temperature = 1;\n' +
|
||||||
|
' double humidity = 2;\n' +
|
||||||
|
' InnerObject innerObject = 3;\n' +
|
||||||
|
'\n' +
|
||||||
|
' message InnerObject {\n' +
|
||||||
|
' string key1 = 1;\n' +
|
||||||
|
' bool key2 = 2;\n' +
|
||||||
|
' double key3 = 3;\n' +
|
||||||
|
' int32 key4 = 4;\n' +
|
||||||
|
' string key5 = 5;\n' +
|
||||||
|
' }\n' +
|
||||||
|
'}\n';
|
||||||
|
|
||||||
|
private defaultAttributesSchema =
|
||||||
|
'syntax ="proto3";\n' +
|
||||||
|
'package attributes;\n' +
|
||||||
|
'\n' +
|
||||||
|
'message SensorConfiguration {\n' +
|
||||||
|
' string firmwareVersion = 1;\n' +
|
||||||
|
' string serialNumber = 2;\n' +
|
||||||
|
'}';
|
||||||
|
|
||||||
private requiredValue: boolean;
|
private requiredValue: boolean;
|
||||||
|
|
||||||
get required(): boolean {
|
get required(): boolean {
|
||||||
@ -83,17 +111,18 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control
|
|||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.mqttDeviceProfileTransportConfigurationFormGroup = this.fb.group({
|
this.mqttDeviceProfileTransportConfigurationFormGroup = this.fb.group({
|
||||||
configuration: this.fb.group({
|
|
||||||
deviceAttributesTopic: [null, [Validators.required, this.validationMQTTTopic()]],
|
deviceAttributesTopic: [null, [Validators.required, this.validationMQTTTopic()]],
|
||||||
deviceTelemetryTopic: [null, [Validators.required, this.validationMQTTTopic()]],
|
deviceTelemetryTopic: [null, [Validators.required, this.validationMQTTTopic()]],
|
||||||
transportPayloadTypeConfiguration: this.fb.group({
|
transportPayloadTypeConfiguration: this.fb.group({
|
||||||
transportPayloadType: [MqttTransportPayloadType.JSON, Validators.required]
|
transportPayloadType: [MqttTransportPayloadType.JSON, Validators.required],
|
||||||
|
deviceTelemetryProtoSchema: [this.defaultTelemetrySchema, Validators.required],
|
||||||
|
deviceAttributesProtoSchema: [this.defaultAttributesSchema, Validators.required]
|
||||||
})
|
})
|
||||||
}, {validator: this.uniqueDeviceTopicValidator})
|
}, {validator: this.uniqueDeviceTopicValidator}
|
||||||
});
|
);
|
||||||
this.mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.transportPayloadTypeConfiguration.transportPayloadType').valueChanges.subscribe(payloadType => {
|
this.mqttDeviceProfileTransportConfigurationFormGroup.get('transportPayloadTypeConfiguration.transportPayloadType')
|
||||||
this.updateTransportPayloadBasedControls(payloadType);
|
.valueChanges.subscribe(payloadType => {
|
||||||
this.mqttDeviceProfileTransportConfigurationFormGroup.updateValueAndValidity();
|
this.updateTransportPayloadBasedControls(payloadType, true);
|
||||||
});
|
});
|
||||||
this.mqttDeviceProfileTransportConfigurationFormGroup.valueChanges.subscribe(() => {
|
this.mqttDeviceProfileTransportConfigurationFormGroup.valueChanges.subscribe(() => {
|
||||||
this.updateModel();
|
this.updateModel();
|
||||||
@ -110,58 +139,41 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control
|
|||||||
}
|
}
|
||||||
|
|
||||||
get protoPayloadType(): boolean {
|
get protoPayloadType(): boolean {
|
||||||
let transportPayloadType = this.mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.transportPayloadTypeConfiguration.transportPayloadType').value;
|
const transportPayloadType = this.mqttDeviceProfileTransportConfigurationFormGroup.get('transportPayloadTypeConfiguration.transportPayloadType').value;
|
||||||
return transportPayloadType === MqttTransportPayloadType.PROTOBUF;
|
return transportPayloadType === MqttTransportPayloadType.PROTOBUF;
|
||||||
}
|
}
|
||||||
|
|
||||||
writeValue(value: MqttDeviceProfileTransportConfiguration | null): void {
|
writeValue(value: MqttDeviceProfileTransportConfiguration | null): void {
|
||||||
if (isDefinedAndNotNull(value)) {
|
if (isDefinedAndNotNull(value)) {
|
||||||
this.updateTransportPayloadBasedControls(value.transportPayloadTypeConfiguration.transportPayloadType);
|
this.mqttDeviceProfileTransportConfigurationFormGroup.patchValue(value, {emitEvent: false});
|
||||||
this.mqttDeviceProfileTransportConfigurationFormGroup.patchValue({configuration: value}, {emitEvent: false});
|
this.updateTransportPayloadBasedControls(value.transportPayloadTypeConfiguration?.transportPayloadType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateModel() {
|
private updateModel() {
|
||||||
let configuration: DeviceProfileTransportConfiguration = null;
|
let configuration: DeviceProfileTransportConfiguration = null;
|
||||||
if (this.mqttDeviceProfileTransportConfigurationFormGroup.valid) {
|
if (this.mqttDeviceProfileTransportConfigurationFormGroup.valid) {
|
||||||
configuration = this.mqttDeviceProfileTransportConfigurationFormGroup.getRawValue().configuration;
|
configuration = this.mqttDeviceProfileTransportConfigurationFormGroup.value;
|
||||||
configuration.type = DeviceTransportType.MQTT;
|
configuration.type = DeviceTransportType.MQTT;
|
||||||
}
|
}
|
||||||
this.propagateChange(configuration);
|
this.propagateChange(configuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateTransportPayloadBasedControls(type: MqttTransportPayloadType) {
|
private updateTransportPayloadBasedControls(type: MqttTransportPayloadType, forceUpdated = false) {
|
||||||
const transportPayloadTypeConfigurationFormGroup = this.mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.transportPayloadTypeConfiguration') as FormGroup;
|
const transportPayloadTypeForm = this.mqttDeviceProfileTransportConfigurationFormGroup
|
||||||
if (type === MqttTransportPayloadType.PROTOBUF) {
|
.get('transportPayloadTypeConfiguration') as FormGroup;
|
||||||
const defaultTelemetrySchema = "syntax =\"proto3\";\n" +
|
if (forceUpdated) {
|
||||||
"package telemetry;\n" +
|
transportPayloadTypeForm.patchValue({
|
||||||
"\n" +
|
deviceTelemetryProtoSchema: this.defaultTelemetrySchema,
|
||||||
"message SensorDataReading {\n" +
|
deviceAttributesProtoSchema: this.defaultAttributesSchema
|
||||||
"\n" +
|
}, {emitEvent: false});
|
||||||
" double temperature = 1;\n" +
|
}
|
||||||
" double humidity = 2;\n" +
|
if (type === MqttTransportPayloadType.PROTOBUF && !this.disabled) {
|
||||||
" InnerObject innerObject = 3;\n" +
|
transportPayloadTypeForm.get('deviceTelemetryProtoSchema').enable({emitEvent: false});
|
||||||
"\n" +
|
transportPayloadTypeForm.get('deviceAttributesProtoSchema').enable({emitEvent: false});
|
||||||
" message InnerObject {\n" +
|
|
||||||
" string key1 = 1;\n" +
|
|
||||||
" bool key2 = 2;\n" +
|
|
||||||
" double key3 = 3;\n" +
|
|
||||||
" int32 key4 = 4;\n" +
|
|
||||||
" string key5 = 5;\n" +
|
|
||||||
" }\n" +
|
|
||||||
"}\n";
|
|
||||||
const defaultAttributesSchema = "syntax =\"proto3\";\n" +
|
|
||||||
"package attributes;\n" +
|
|
||||||
"\n" +
|
|
||||||
"message SensorConfiguration {\n" +
|
|
||||||
" string firmwareVersion = 1;\n" +
|
|
||||||
" string serialNumber = 2;\n" +
|
|
||||||
"}";
|
|
||||||
transportPayloadTypeConfigurationFormGroup.registerControl('deviceTelemetryProtoSchema', this.fb.control(defaultTelemetrySchema, Validators.required));
|
|
||||||
transportPayloadTypeConfigurationFormGroup.registerControl('deviceAttributesProtoSchema', this.fb.control(defaultAttributesSchema, Validators.required));
|
|
||||||
} else {
|
} else {
|
||||||
transportPayloadTypeConfigurationFormGroup.removeControl('deviceTelemetryProtoSchema');
|
transportPayloadTypeForm.get('deviceTelemetryProtoSchema').disable({emitEvent: false});
|
||||||
transportPayloadTypeConfigurationFormGroup.removeControl('deviceAttributesProtoSchema');
|
transportPayloadTypeForm.get('deviceAttributesProtoSchema').disable({emitEvent: false});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -41,9 +41,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</mat-tab>
|
</mat-tab>
|
||||||
<mat-tab *ngIf="entity"
|
<mat-tab *ngIf="entity"
|
||||||
label="{{'device-profile.alarm-rules' | translate:
|
label="{{'device-profile.alarm-rules-with-count' | translate:
|
||||||
{count: entity.profileData.alarms && entity.profileData.alarms.length ?
|
{count: entity.profileData?.alarms?.length ? entity.profileData.alarms.length : 0}
|
||||||
entity.profileData.alarms.length : 0} }}" #alarmRules="matTab">
|
}}" #alarmRules="matTab">
|
||||||
<div class="mat-padding" [formGroup]="detailsForm">
|
<div class="mat-padding" [formGroup]="detailsForm">
|
||||||
<div formGroupName="profileData">
|
<div formGroupName="profileData">
|
||||||
<tb-device-profile-alarms formControlName="alarms"></tb-device-profile-alarms>
|
<tb-device-profile-alarms formControlName="alarms"></tb-device-profile-alarms>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user