Fixed Issue of viewing Out of Sync Connector and gateway-connectors component refactoring
This commit is contained in:
parent
bce943cb5b
commit
4d992bff70
@ -154,15 +154,15 @@
|
||||
<section [formGroup]="connectorForm" class="tb-form-panel section-container flex">
|
||||
<div class="tb-form-panel-title tb-flex no-flex space-between align-center">
|
||||
<div class="tb-form-panel-title">
|
||||
{{ initialConnector?.type ? gatewayConnectorDefaultTypes.get(initialConnector.type) : '' }}
|
||||
{{ initialConnector?.type ? GatewayConnectorTypesTranslatesMap.get(initialConnector.type) : '' }}
|
||||
{{ 'gateway.configuration' | translate }}
|
||||
</div>
|
||||
<tb-toggle-select *ngIf="initialConnector && allowBasicConfig.has(initialConnector.type)"
|
||||
formControlName="mode" appearance="fill">
|
||||
<tb-toggle-option [value]="connectorConfigurationModes.BASIC">
|
||||
<tb-toggle-option [value]="ConnectorConfigurationModes.BASIC">
|
||||
{{ 'gateway.basic' | translate }}
|
||||
</tb-toggle-option>
|
||||
<tb-toggle-option [value]="connectorConfigurationModes.ADVANCED">
|
||||
<tb-toggle-option [value]="ConnectorConfigurationModes.ADVANCED">
|
||||
{{ 'gateway.advanced' | translate }}
|
||||
</tb-toggle-option>
|
||||
</tb-toggle-select>
|
||||
@ -173,17 +173,17 @@
|
||||
gateway.select-connector
|
||||
</span>
|
||||
<section class="tb-form-panel section-container no-border no-padding tb-flex space-between" *ngIf="initialConnector">
|
||||
<ng-container *ngIf="connectorForm.get('mode')?.value === connectorConfigurationModes.BASIC else defaultConfig">
|
||||
<ng-container *ngIf="connectorForm.get('mode')?.value === ConnectorConfigurationModes.BASIC else defaultConfig">
|
||||
<ng-container [ngSwitch]="initialConnector.type">
|
||||
<tb-mqtt-basic-config *ngSwitchCase="connectorType.MQTT"
|
||||
<tb-mqtt-basic-config *ngSwitchCase="ConnectorType.MQTT"
|
||||
formControlName="basicConfig"
|
||||
[generalTabContent]="generalTabContent">
|
||||
</tb-mqtt-basic-config>
|
||||
<tb-opc-ua-basic-config *ngSwitchCase="connectorType.OPCUA"
|
||||
<tb-opc-ua-basic-config *ngSwitchCase="ConnectorType.OPCUA"
|
||||
formControlName="basicConfig"
|
||||
[generalTabContent]="generalTabContent">
|
||||
</tb-opc-ua-basic-config>
|
||||
<tb-modbus-basic-config *ngSwitchCase="connectorType.MODBUS"
|
||||
<tb-modbus-basic-config *ngSwitchCase="ConnectorType.MODBUS"
|
||||
formControlName="basicConfig"
|
||||
[generalTabContent]="generalTabContent">
|
||||
</tb-modbus-basic-config>
|
||||
@ -237,7 +237,7 @@
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="connectorForm.get('type').value === connectorType.CUSTOM" class="tb-form-row column-xs" fxLayoutAlign="space-between center">
|
||||
<div *ngIf="connectorForm.get('type').value === ConnectorType.CUSTOM" class="tb-form-row column-xs" fxLayoutAlign="space-between center">
|
||||
<div class="fixed-title-width" translate>gateway.connectors-table-class</div>
|
||||
<div class="tb-flex no-gap">
|
||||
<mat-form-field class="tb-flex no-gap" appearance="outline" subscriptSizing="dynamic">
|
||||
@ -245,7 +245,7 @@
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="connectorForm.get('type').value === connectorType.GRPC" class="tb-form-row column-xs" fxLayoutAlign="space-between center">
|
||||
<div *ngIf="connectorForm.get('type').value === ConnectorType.GRPC" class="tb-form-row column-xs" fxLayoutAlign="space-between center">
|
||||
<div class="fixed-title-width" translate>gateway.connectors-table-key</div>
|
||||
<div class="tb-flex no-gap">
|
||||
<mat-form-field class="tb-flex no-gap" appearance="outline" subscriptSizing="dynamic">
|
||||
@ -273,7 +273,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="connectorForm.get('type').value === connectorType.MQTT" class="tb-form-row column-xs" fxLayoutAlign="space-between center">
|
||||
<div *ngIf="connectorForm.get('type').value === ConnectorType.MQTT" class="tb-form-row column-xs" fxLayoutAlign="space-between center">
|
||||
<mat-slide-toggle class="mat-slide" formControlName="sendDataOnlyOnChange">
|
||||
<mat-label tb-hint-tooltip-icon="{{ 'gateway.send-change-data-hint' | translate }}">
|
||||
{{ 'gateway.send-change-data' | translate }}
|
||||
|
||||
@ -81,61 +81,39 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
|
||||
|
||||
@Input()
|
||||
ctx: WidgetContext;
|
||||
|
||||
@Input()
|
||||
device: EntityId;
|
||||
|
||||
@ViewChild('nameInput') nameInput: ElementRef;
|
||||
@ViewChild(MatSort, {static: false}) sort: MatSort;
|
||||
|
||||
pageLink: PageLink;
|
||||
|
||||
connectorType = ConnectorType;
|
||||
|
||||
allowBasicConfig = new Set<ConnectorType>([
|
||||
readonly ConnectorType = ConnectorType;
|
||||
readonly allowBasicConfig = new Set<ConnectorType>([
|
||||
ConnectorType.MQTT,
|
||||
ConnectorType.OPCUA,
|
||||
ConnectorType.MODBUS,
|
||||
]);
|
||||
readonly gatewayLogLevel = Object.values(GatewayLogLevel);
|
||||
readonly displayedColumns = ['enabled', 'key', 'type', 'syncStatus', 'errors', 'actions'];
|
||||
readonly GatewayConnectorTypesTranslatesMap = GatewayConnectorDefaultTypesTranslatesMap;
|
||||
readonly ConnectorConfigurationModes = ConnectorConfigurationModes;
|
||||
|
||||
gatewayLogLevel = Object.values(GatewayLogLevel);
|
||||
|
||||
pageLink: PageLink;
|
||||
dataSource: MatTableDataSource<AttributeData>;
|
||||
|
||||
displayedColumns = ['enabled', 'key', 'type', 'syncStatus', 'errors', 'actions'];
|
||||
|
||||
gatewayConnectorDefaultTypes = GatewayConnectorDefaultTypesTranslatesMap;
|
||||
|
||||
connectorConfigurationModes = ConnectorConfigurationModes;
|
||||
|
||||
connectorForm: FormGroup;
|
||||
|
||||
textSearchMode: boolean;
|
||||
|
||||
activeConnectors: Array<string>;
|
||||
|
||||
mode: ConnectorConfigurationModes = this.connectorConfigurationModes.BASIC;
|
||||
|
||||
mode: ConnectorConfigurationModes = this.ConnectorConfigurationModes.BASIC;
|
||||
initialConnector: GatewayConnector;
|
||||
|
||||
private inactiveConnectors: Array<string>;
|
||||
|
||||
private attributeDataSource: AttributeDatasource;
|
||||
|
||||
private inactiveConnectorsDataSource: AttributeDatasource;
|
||||
|
||||
private serverDataSource: AttributeDatasource;
|
||||
|
||||
private activeData: Array<any> = [];
|
||||
|
||||
private inactiveData: Array<any> = [];
|
||||
|
||||
private sharedAttributeData: Array<AttributeData> = [];
|
||||
|
||||
private basicConfigSub: Subscription;
|
||||
|
||||
private jsonConfigSub: Subscription;
|
||||
|
||||
private subscriptionOptions: WidgetSubscriptionOptions = {
|
||||
callbacks: {
|
||||
onDataUpdated: () => this.ctx.ngZone.run(() => {
|
||||
@ -146,7 +124,6 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
private destroy$ = new Subject<void>();
|
||||
private subscription: IWidgetSubscription;
|
||||
private attributeUpdateSubject = new Subject<AttributeData>();
|
||||
@ -162,101 +139,19 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
|
||||
private utils: UtilsService,
|
||||
private cd: ChangeDetectorRef) {
|
||||
super(store);
|
||||
const sortOrder: SortOrder = {property: 'key', direction: Direction.ASC};
|
||||
this.pageLink = new PageLink(1000, 0, null, sortOrder);
|
||||
this.attributeDataSource = new AttributeDatasource(this.attributeService, this.telemetryWsService, this.zone, this.translate);
|
||||
this.inactiveConnectorsDataSource = new AttributeDatasource(this.attributeService, this.telemetryWsService, this.zone, this.translate);
|
||||
this.serverDataSource = new AttributeDatasource(this.attributeService, this.telemetryWsService, this.zone, this.translate);
|
||||
this.dataSource = new MatTableDataSource<AttributeData>([]);
|
||||
this.connectorForm = this.fb.group({
|
||||
mode: [ConnectorConfigurationModes.BASIC, []],
|
||||
name: ['', [Validators.required, this.uniqNameRequired(), Validators.pattern(noLeadTrailSpacesRegex)]],
|
||||
type: ['', [Validators.required]],
|
||||
enableRemoteLogging: [false, []],
|
||||
logLevel: ['', [Validators.required]],
|
||||
sendDataOnlyOnChange: [false, []],
|
||||
key: ['auto'],
|
||||
class: [''],
|
||||
configuration: [''],
|
||||
configurationJson: [{}, [Validators.required]],
|
||||
basicConfig: [{}]
|
||||
});
|
||||
this.connectorForm.disable();
|
||||
|
||||
this.initDataSources();
|
||||
this.initConnectorForm();
|
||||
this.observeAttributeChange();
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
this.connectorForm.get('type').valueChanges.pipe(
|
||||
takeUntil(this.destroy$)
|
||||
).subscribe(type => {
|
||||
if (type && !this.initialConnector) {
|
||||
this.attributeService.getEntityAttributes(this.device, AttributeScope.CLIENT_SCOPE,
|
||||
[`${type.toUpperCase()}_DEFAULT_CONFIG`], {ignoreErrors: true}).subscribe(defaultConfig=>{
|
||||
if (defaultConfig && defaultConfig.length) {
|
||||
this.connectorForm.get('configurationJson').setValue(
|
||||
isString(defaultConfig[0].value) ?
|
||||
JSON.parse(defaultConfig[0].value) :
|
||||
defaultConfig[0].value);
|
||||
this.cd.detectChanges();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.connectorForm.get('name').valueChanges.pipe(
|
||||
takeUntil(this.destroy$)
|
||||
).subscribe((name) => {
|
||||
if (this.connectorForm.get('type').value === ConnectorType.MQTT) {
|
||||
this.connectorForm.get('basicConfig').get('broker.name')?.setValue(name);
|
||||
}
|
||||
});
|
||||
this.observeName();
|
||||
|
||||
this.dataSource.sort = this.sort;
|
||||
this.dataSource.sortingDataAccessor = (data: AttributeData, sortHeaderId: string) => {
|
||||
switch (sortHeaderId) {
|
||||
case 'syncStatus':
|
||||
return this.isConnectorSynced(data) ? 1 : 0;
|
||||
|
||||
case 'enabled':
|
||||
return this.activeConnectors.includes(data.key) ? 1 : 0;
|
||||
|
||||
case 'errors':
|
||||
const errors = this.getErrorsCount(data);
|
||||
if (typeof errors === 'string') {
|
||||
return this.sort.direction.toUpperCase() === Direction.DESC ? -1 : Infinity;
|
||||
}
|
||||
return errors;
|
||||
|
||||
default:
|
||||
return data[sortHeaderId] || data.value[sortHeaderId];
|
||||
}
|
||||
};
|
||||
|
||||
if (this.device) {
|
||||
if (this.device.id === NULL_UUID) {
|
||||
return;
|
||||
}
|
||||
forkJoin([
|
||||
this.attributeService.getEntityAttributes(this.device, AttributeScope.SHARED_SCOPE, ['active_connectors']),
|
||||
this.attributeService.getEntityAttributes(this.device, AttributeScope.SERVER_SCOPE, ['inactive_connectors'])
|
||||
]).subscribe(attributes => {
|
||||
if (attributes.length) {
|
||||
this.activeConnectors = attributes[0].length ? attributes[0][0].value : [];
|
||||
this.activeConnectors = isString(this.activeConnectors) ? JSON.parse(this.activeConnectors as any) : this.activeConnectors;
|
||||
this.inactiveConnectors = attributes[1].length ? attributes[1][0].value : [];
|
||||
this.inactiveConnectors = isString(this.inactiveConnectors)
|
||||
? JSON.parse(this.inactiveConnectors as any)
|
||||
: this.inactiveConnectors;
|
||||
this.updateData(true);
|
||||
} else {
|
||||
this.activeConnectors = [];
|
||||
this.inactiveConnectors = [];
|
||||
this.updateData(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
this.dataSource.sortingDataAccessor = this.getSortingDataAccessor();
|
||||
|
||||
this.loadConnectors();
|
||||
this.observeModeChange();
|
||||
}
|
||||
|
||||
@ -267,57 +162,12 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
|
||||
}
|
||||
|
||||
saveConnector(): void {
|
||||
const value = { ...this.connectorForm.value };
|
||||
value.configuration = camelCase(value.name) + '.json';
|
||||
delete value.basicConfig;
|
||||
if (value.type !== ConnectorType.GRPC) {
|
||||
delete value.key;
|
||||
}
|
||||
if (value.type !== ConnectorType.CUSTOM) {
|
||||
delete value.class;
|
||||
}
|
||||
value.ts = new Date().getTime();
|
||||
const attributesToSave = [{
|
||||
key: value.name,
|
||||
value
|
||||
}];
|
||||
const attributesToDelete = [];
|
||||
const value = this.getConnectorData();
|
||||
const scope = (!this.initialConnector || this.activeConnectors.includes(this.initialConnector.name))
|
||||
? AttributeScope.SHARED_SCOPE
|
||||
: AttributeScope.SERVER_SCOPE;
|
||||
let updateActiveConnectors = false;
|
||||
if (this.initialConnector && this.initialConnector.name !== value.name) {
|
||||
attributesToDelete.push({key: this.initialConnector.name});
|
||||
updateActiveConnectors = true;
|
||||
const activeIndex = this.activeConnectors.indexOf(this.initialConnector.name);
|
||||
const inactiveIndex = this.inactiveConnectors.indexOf(this.initialConnector.name);
|
||||
if (activeIndex !== -1) {
|
||||
this.activeConnectors.splice(activeIndex, 1);
|
||||
}
|
||||
if (inactiveIndex !== -1) {
|
||||
this.inactiveConnectors.splice(inactiveIndex, 1);
|
||||
}
|
||||
}
|
||||
if (!this.activeConnectors.includes(value.name) && scope === AttributeScope.SHARED_SCOPE) {
|
||||
this.activeConnectors.push(value.name);
|
||||
updateActiveConnectors = true;
|
||||
}
|
||||
if (!this.inactiveConnectors.includes(value.name) && scope === AttributeScope.SERVER_SCOPE) {
|
||||
this.inactiveConnectors.push(value.name);
|
||||
updateActiveConnectors = true;
|
||||
}
|
||||
const tasks = [this.attributeService.saveEntityAttributes(this.device, scope, attributesToSave)];
|
||||
if (updateActiveConnectors) {
|
||||
tasks.push(this.attributeService.saveEntityAttributes(this.device, scope, [{
|
||||
key: scope === AttributeScope.SHARED_SCOPE ? 'active_connectors' : 'inactive_connectors',
|
||||
value: scope === AttributeScope.SHARED_SCOPE ? this.activeConnectors : this.inactiveConnectors
|
||||
}]));
|
||||
}
|
||||
|
||||
if (attributesToDelete.length) {
|
||||
tasks.push(this.attributeService.deleteEntityAttributes(this.device, scope, attributesToDelete));
|
||||
}
|
||||
forkJoin(tasks).subscribe(_ => {
|
||||
forkJoin(this.getEntityAttributeTasks(value, scope)).pipe(take(1)).subscribe(_ => {
|
||||
this.showToast(!this.initialConnector
|
||||
? this.translate.instant('gateway.connector-created')
|
||||
: this.translate.instant('gateway.connector-updated')
|
||||
@ -328,6 +178,69 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
|
||||
});
|
||||
}
|
||||
|
||||
private getEntityAttributeTasks(value: GatewayConnector, scope: AttributeScope): Observable<any>[] {
|
||||
const tasks = [];
|
||||
const attributesToSave = [{ key: value.name, value }];
|
||||
const attributesToDelete = [];
|
||||
const shouldAddToConnectorsList = !this.activeConnectors.includes(value.name) && scope === AttributeScope.SHARED_SCOPE
|
||||
|| !this.inactiveConnectors.includes(value.name) && scope === AttributeScope.SERVER_SCOPE;
|
||||
const isNewConnector = this.initialConnector && this.initialConnector.name !== value.name;
|
||||
|
||||
if (isNewConnector) {
|
||||
attributesToDelete.push({ key: this.initialConnector.name });
|
||||
this.removeConnectorFromList(this.initialConnector.name, true);
|
||||
this.removeConnectorFromList(this.initialConnector.name, false);
|
||||
}
|
||||
|
||||
if (shouldAddToConnectorsList) {
|
||||
if (scope === AttributeScope.SHARED_SCOPE) {
|
||||
this.activeConnectors.push(value.name);
|
||||
} else {
|
||||
this.inactiveConnectors.push(value.name);
|
||||
}
|
||||
}
|
||||
|
||||
if (isNewConnector || shouldAddToConnectorsList) {
|
||||
tasks.push(this.attributeService.saveEntityAttributes(this.device, scope, [{
|
||||
key: scope === AttributeScope.SHARED_SCOPE ? 'active_connectors' : 'inactive_connectors',
|
||||
value: scope === AttributeScope.SHARED_SCOPE ? this.activeConnectors : this.inactiveConnectors
|
||||
}]));
|
||||
}
|
||||
|
||||
tasks.push(this.attributeService.saveEntityAttributes(this.device, scope, attributesToSave));
|
||||
|
||||
if (attributesToDelete.length) {
|
||||
tasks.push(this.attributeService.deleteEntityAttributes(this.device, scope, attributesToDelete));
|
||||
}
|
||||
|
||||
return tasks;
|
||||
}
|
||||
|
||||
private removeConnectorFromList(connectorName: string, isActive: boolean): void {
|
||||
const list = isActive? this.activeConnectors : this.inactiveConnectors;
|
||||
const index = list.indexOf(connectorName);
|
||||
if (index !== -1) {
|
||||
list.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
private getConnectorData(): GatewayConnector {
|
||||
const value = { ...this.connectorForm.value };
|
||||
value.configuration = `${camelCase(value.name)}.json`;
|
||||
delete value.basicConfig;
|
||||
|
||||
if (value.type !== ConnectorType.GRPC) {
|
||||
delete value.key;
|
||||
}
|
||||
if (value.type !== ConnectorType.CUSTOM) {
|
||||
delete value.class;
|
||||
}
|
||||
|
||||
value.ts = Date.now();
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private updateData(reload: boolean = false): void {
|
||||
this.pageLink.sortOrder.property = this.sort.active;
|
||||
this.pageLink.sortOrder.direction = Direction[this.sort.direction.toUpperCase()];
|
||||
@ -349,11 +262,11 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
|
||||
|
||||
isConnectorSynced(attribute: AttributeData) {
|
||||
const connectorData = attribute.value;
|
||||
if (!connectorData.ts) {
|
||||
if (!connectorData.ts || attribute.skipSync) {
|
||||
return false;
|
||||
}
|
||||
const clientIndex = this.activeData.findIndex(data => {
|
||||
const sharedData = data.value;
|
||||
const sharedData = typeof data.value === 'string' ? JSON.parse(data.value) : data.value;
|
||||
return sharedData.name === connectorData.name;
|
||||
});
|
||||
if (clientIndex === -1) {
|
||||
@ -384,12 +297,31 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
|
||||
}
|
||||
|
||||
private combineData(): void {
|
||||
this.dataSource.data = [...this.activeData, ...this.inactiveData, ...this.sharedAttributeData].filter((item, index, self) =>
|
||||
index === self.findIndex((t) => t.key === item.key)
|
||||
).map(attribute => {
|
||||
attribute.value = typeof attribute.value === 'string' ? JSON.parse(attribute.value) : attribute.value;
|
||||
return attribute;
|
||||
});
|
||||
const combinedData = [
|
||||
...this.activeData,
|
||||
...this.inactiveData,
|
||||
...this.sharedAttributeData
|
||||
];
|
||||
|
||||
const latestData = combinedData.reduce((acc, attribute) => {
|
||||
const existingItemIndex = acc.findIndex(item => item.key === attribute.key);
|
||||
|
||||
if (existingItemIndex === -1) {
|
||||
acc.push(attribute);
|
||||
} else if (
|
||||
attribute.lastUpdateTs > acc[existingItemIndex].lastUpdateTs &&
|
||||
!this.isConnectorSynced(acc[existingItemIndex])
|
||||
) {
|
||||
acc[existingItemIndex] = { ...attribute, skipSync: true };
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
this.dataSource.data = latestData.map(attribute => ({
|
||||
...attribute,
|
||||
value: typeof attribute.value === 'string' ? JSON.parse(attribute.value) : attribute.value
|
||||
}));
|
||||
}
|
||||
|
||||
private clearOutConnectorForm(): void {
|
||||
@ -447,7 +379,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
|
||||
|
||||
returnType(attribute: AttributeData): string {
|
||||
const value = attribute.value;
|
||||
return this.gatewayConnectorDefaultTypes.get(value.type);
|
||||
return this.GatewayConnectorTypesTranslatesMap.get(value.type);
|
||||
}
|
||||
|
||||
deleteConnector(attribute: AttributeData, $event: Event): void {
|
||||
@ -560,24 +492,95 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
|
||||
}
|
||||
|
||||
uniqNameRequired(): ValidatorFn {
|
||||
return (c: UntypedFormControl) => {
|
||||
const newName = c.value.trim().toLowerCase();
|
||||
const found = this.dataSource.data.find((connectorAttr) => {
|
||||
const connectorData = connectorAttr.value;
|
||||
return connectorData.name.toLowerCase() === newName;
|
||||
return (control: UntypedFormControl) => {
|
||||
const newName = control.value?.trim().toLowerCase();
|
||||
const isDuplicate = this.dataSource.data.some(connectorAttr => connectorAttr.value.name.toLowerCase() === newName);
|
||||
const isSameAsInitial = this.initialConnector?.name.toLowerCase() === newName;
|
||||
|
||||
if (isDuplicate && !isSameAsInitial) {
|
||||
return { duplicateName: { valid: false } };
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
private initDataSources(): void {
|
||||
const sortOrder: SortOrder = {property: 'key', direction: Direction.ASC};
|
||||
this.pageLink = new PageLink(1000, 0, null, sortOrder);
|
||||
this.attributeDataSource = new AttributeDatasource(this.attributeService, this.telemetryWsService, this.zone, this.translate);
|
||||
this.inactiveConnectorsDataSource = new AttributeDatasource(this.attributeService, this.telemetryWsService, this.zone, this.translate);
|
||||
this.serverDataSource = new AttributeDatasource(this.attributeService, this.telemetryWsService, this.zone, this.translate);
|
||||
this.dataSource = new MatTableDataSource<AttributeData>([]);
|
||||
}
|
||||
|
||||
private initConnectorForm(): void {
|
||||
this.connectorForm = this.fb.group({
|
||||
mode: [ConnectorConfigurationModes.BASIC],
|
||||
name: ['', [Validators.required, this.uniqNameRequired(), Validators.pattern(noLeadTrailSpacesRegex)]],
|
||||
type: ['', [Validators.required]],
|
||||
enableRemoteLogging: [false],
|
||||
logLevel: ['', [Validators.required]],
|
||||
sendDataOnlyOnChange: [false],
|
||||
key: ['auto'],
|
||||
class: [''],
|
||||
configuration: [''],
|
||||
configurationJson: [{}, [Validators.required]],
|
||||
basicConfig: [{}]
|
||||
});
|
||||
if (found) {
|
||||
if (this.initialConnector && this.initialConnector.name.toLowerCase() === newName) {
|
||||
return null;
|
||||
this.connectorForm.disable();
|
||||
}
|
||||
return {
|
||||
duplicateName: {
|
||||
valid: false
|
||||
|
||||
private observeName(): void {
|
||||
this.connectorForm.get('name').valueChanges
|
||||
.pipe(
|
||||
filter(() => this.connectorForm.get('type').value === ConnectorType.MQTT),
|
||||
takeUntil(this.destroy$)
|
||||
)
|
||||
.subscribe(name => this.connectorForm.get('basicConfig').get('broker.name')?.setValue(name));
|
||||
}
|
||||
|
||||
private getSortingDataAccessor(): (data: AttributeData, sortHeaderId: string) => string | number {
|
||||
return (data: AttributeData, sortHeaderId: string) => {
|
||||
switch (sortHeaderId) {
|
||||
case 'syncStatus':
|
||||
return this.isConnectorSynced(data) ? 1 : 0;
|
||||
|
||||
case 'enabled':
|
||||
return this.activeConnectors.includes(data.key) ? 1 : 0;
|
||||
|
||||
case 'errors':
|
||||
const errors = this.getErrorsCount(data);
|
||||
if (typeof errors === 'string') {
|
||||
return this.sort.direction.toUpperCase() === Direction.DESC ? -1 : Infinity;
|
||||
}
|
||||
return errors;
|
||||
|
||||
default:
|
||||
return data[sortHeaderId] || data.value[sortHeaderId];
|
||||
}
|
||||
};
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
private loadConnectors(): void {
|
||||
if (!this.device || this.device.id === NULL_UUID) {
|
||||
return;
|
||||
}
|
||||
|
||||
forkJoin([
|
||||
this.attributeService.getEntityAttributes(this.device, AttributeScope.SHARED_SCOPE, ['active_connectors']),
|
||||
this.attributeService.getEntityAttributes(this.device, AttributeScope.SERVER_SCOPE, ['inactive_connectors'])
|
||||
]).pipe(takeUntil(this.destroy$)).subscribe(attributes => {
|
||||
this.activeConnectors = this.parseConnectors(attributes[0]);
|
||||
this.inactiveConnectors = this.parseConnectors(attributes[1]);
|
||||
|
||||
this.updateData(true);
|
||||
});
|
||||
}
|
||||
|
||||
private parseConnectors(attribute: AttributeData[]): string[] {
|
||||
const connectors = attribute?.[0]?.value || [];
|
||||
return isString(connectors) ? JSON.parse(connectors) : connectors;
|
||||
}
|
||||
|
||||
private observeModeChange(): void {
|
||||
@ -636,7 +639,8 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
|
||||
value: this.inactiveConnectors
|
||||
}]),
|
||||
this.attributeService.deleteEntityAttributes(this.device, scopeOld, [attribute]),
|
||||
this.attributeService.saveEntityAttributes(this.device, scopeNew, [attribute])];
|
||||
this.attributeService.saveEntityAttributes(this.device, scopeNew, [attribute])
|
||||
];
|
||||
}
|
||||
|
||||
private onDataUpdateError(e: any): void {
|
||||
@ -725,20 +729,17 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
|
||||
if (this.connectorForm.disabled) {
|
||||
this.connectorForm.enable();
|
||||
}
|
||||
if (!connector.configuration) {
|
||||
connector.configuration = '';
|
||||
}
|
||||
if (!connector.key) {
|
||||
connector.key = 'auto';
|
||||
}
|
||||
if (!connector.configurationJson) {
|
||||
connector.configurationJson = {} as ConnectorBaseConfig;
|
||||
}
|
||||
connector.basicConfig = connector.configurationJson;
|
||||
|
||||
this.initialConnector = connector;
|
||||
const connectorState = {
|
||||
configuration: '',
|
||||
key: 'auto',
|
||||
configurationJson: {} as ConnectorBaseConfig,
|
||||
...connector,
|
||||
};
|
||||
|
||||
this.updateConnector(connector);
|
||||
connectorState.basicConfig = connectorState.configurationJson;
|
||||
this.initialConnector = connectorState;
|
||||
this.updateConnector(connectorState);
|
||||
}
|
||||
|
||||
private updateConnector(connector: GatewayConnector): void {
|
||||
|
||||
@ -118,6 +118,7 @@ export const timeseriesDeleteStrategyTranslations = new Map<TimeseriesDeleteStra
|
||||
|
||||
export interface AttributeData {
|
||||
lastUpdateTs?: number;
|
||||
skipSync?: boolean;
|
||||
key: string;
|
||||
value: any;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user