Merge import device/asset functionality

This commit is contained in:
Igor Kulikov 2020-02-20 16:35:11 +02:00
parent f1ca4c7cfd
commit 05f0619a2d
11 changed files with 99 additions and 14 deletions

View File

@ -805,14 +805,28 @@ export class EntityService {
case EntityType.DEVICE:
const device: Device = {
name: entityData.name,
type: entityData.type
type: entityData.type,
label: entityData.label,
additionalInfo: {
description: entityData.description
}
};
if (entityData.gateway !== null) {
device.additionalInfo = {
...device.additionalInfo,
gateway: entityData.gateway
};
}
saveEntityObservable = this.deviceService.saveDevice(device, config);
break;
case EntityType.ASSET:
const asset: Asset = {
name: entityData.name,
type: entityData.type
type: entityData.type,
label: entityData.label,
additionalInfo: {
description: entityData.description
}
};
saveEntityObservable = this.assetService.saveAsset(asset, config);
break;
@ -839,7 +853,31 @@ export class EntityService {
}
return findEntityObservable.pipe(
mergeMap((entity) => {
return this.saveEntityData(entity.id, entityData, config).pipe(
const tasks: Observable<any>[] = [];
const result: Device | Asset = entity as (Device | Asset);
const additionalInfo = result.additionalInfo || {};
if(result.label !== entityData.label ||
result.type !== entityData.type ||
additionalInfo.description !== entityData.description ||
(result.id.entityType === EntityType.DEVICE && (additionalInfo.gateway !== entityData.gateway)) ) {
result.label = entityData.label;
result.type = entityData.type;
result.additionalInfo = additionalInfo;
result.additionalInfo.description = entityData.description;
if (result.id.entityType === EntityType.DEVICE) {
result.additionalInfo.gateway = entityData.gateway;
}
switch (result.id.entityType) {
case EntityType.DEVICE:
tasks.push(this.deviceService.saveDevice(result, config));
break;
case EntityType.ASSET:
tasks.push(this.assetService.saveAsset(result, config));
break;
}
}
tasks.push(this.saveEntityData(entity.id, entityData, config));
return forkJoin(tasks).pipe(
map(() => {
return { update: { entity: 1 } } as ImportEntitiesResultInfo;
}),

View File

@ -168,7 +168,7 @@ export class ImportDialogCsvComponent extends DialogComponent<ImportDialogCsvCom
const isHeader: boolean = this.importParametersFormGroup.get('isHeader').value;
for (let i = 0; i < this.parseData.headers.length; i++) {
let columnParam: CsvColumnParam;
if (isHeader && this.parseData.headers[i].search(/^(name|type)$/im) === 0) {
if (isHeader && this.parseData.headers[i].search(/^(name|type|label)$/im) === 0) {
columnParam = {
type: ImportEntityColumnType[this.parseData.headers[i].toLowerCase()],
key: this.parseData.headers[i].toLowerCase(),
@ -195,6 +195,9 @@ export class ImportDialogCsvComponent extends DialogComponent<ImportDialogCsvCom
const entityData: ImportEntityData = {
name: '',
type: '',
description: '',
gateway: null,
label: '',
accessToken: '',
attributes: {
server: [],
@ -232,6 +235,15 @@ export class ImportDialogCsvComponent extends DialogComponent<ImportDialogCsvCom
case ImportEntityColumnType.type:
entityData.type = importData.rows[i][j];
break;
case ImportEntityColumnType.label:
entityData.label = importData.rows[i][j];
break;
case ImportEntityColumnType.isGateway:
entityData.gateway = importData.rows[i][j];
break;
case ImportEntityColumnType.description:
entityData.description = importData.rows[i][j];
break;
}
}
entitiesData.push(entityData);

View File

@ -44,12 +44,15 @@ export interface CsvToJsonResult {
export enum ImportEntityColumnType {
name = 'NAME',
type = 'TYPE',
label = 'LABEL',
clientAttribute = 'CLIENT_ATTRIBUTE',
sharedAttribute = 'SHARED_ATTRIBUTE',
serverAttribute = 'SERVER_ATTRIBUTE',
timeseries = 'TIMESERIES',
entityField = 'ENTITY_FIELD',
accessToken = 'ACCESS_TOKEN'
accessToken = 'ACCESS_TOKEN',
isGateway = 'IS_GATEWAY',
description = 'DESCRIPTION'
}
export const importEntityObjectColumns =
@ -59,12 +62,15 @@ export const importEntityColumnTypeTranslations = new Map<ImportEntityColumnType
[
[ImportEntityColumnType.name, 'import.column-type.name'],
[ImportEntityColumnType.type, 'import.column-type.type'],
[ImportEntityColumnType.label, 'import.column-type.label'],
[ImportEntityColumnType.clientAttribute, 'import.column-type.client-attribute'],
[ImportEntityColumnType.sharedAttribute, 'import.column-type.shared-attribute'],
[ImportEntityColumnType.serverAttribute, 'import.column-type.server-attribute'],
[ImportEntityColumnType.timeseries, 'import.column-type.timeseries'],
[ImportEntityColumnType.entityField, 'import.column-type.entity-field'],
[ImportEntityColumnType.accessToken, 'import.column-type.access-token'],
[ImportEntityColumnType.isGateway, 'import.column-type.isgateway'],
[ImportEntityColumnType.description, 'import.column-type.description'],
]
);
@ -136,7 +142,7 @@ function convertStringToJSType(str: string): any {
return parseFloat(str.replace(',', '.'));
}
if (str.search(/^(true|false)$/im) === 0) {
return str === 'true';
return str.toLowerCase() === 'true';
}
if (str === '') {
return null;

View File

@ -42,9 +42,7 @@
<mat-header-cell *matHeaderCellDef style="width: 30%"> {{ 'import.column-key' | translate }} </mat-header-cell>
<mat-cell *matCellDef="let column">
<mat-form-field floatLabel="always" hideRequiredMarker
*ngIf="column.type !== importEntityColumnType.name &&
column.type !== importEntityColumnType.type &&
column.type !== importEntityColumnType.accessToken">
*ngIf="isColumnTypeDiffers(column.type)">
<mat-label></mat-label>
<input matInput required
[(ngModel)]="column.key" (ngModelChange)="columnsUpdated()"

View File

@ -72,6 +72,8 @@ export class TableColumnsAssignmentComponent implements OnInit, ControlValueAcce
this.columnTypes.push(
{ value: ImportEntityColumnType.name },
{ value: ImportEntityColumnType.type },
{ value: ImportEntityColumnType.label },
{ value: ImportEntityColumnType.description },
);
switch (this.entityType) {
case EntityType.DEVICE:
@ -79,7 +81,8 @@ export class TableColumnsAssignmentComponent implements OnInit, ControlValueAcce
{ value: ImportEntityColumnType.sharedAttribute },
{ value: ImportEntityColumnType.serverAttribute },
{ value: ImportEntityColumnType.timeseries },
{ value: ImportEntityColumnType.accessToken }
{ value: ImportEntityColumnType.accessToken },
{ value: ImportEntityColumnType.isGateway }
);
break;
case EntityType.ASSET:
@ -109,13 +112,20 @@ export class TableColumnsAssignmentComponent implements OnInit, ControlValueAcce
columnsUpdated() {
const isSelectName = this.columns.findIndex((column) => column.type === ImportEntityColumnType.name) > -1;
const isSelectType = this.columns.findIndex((column) => column.type === ImportEntityColumnType.type) > -1;
const isSelectLabel = this.columns.findIndex((column) => column.type === ImportEntityColumnType.label) > -1;
const isSelectCredentials = this.columns.findIndex((column) => column.type === ImportEntityColumnType.accessToken) > -1;
const isSelectGateway = this.columns.findIndex((column) => column.type === ImportEntityColumnType.isGateway) > -1;
const isSelectDescription = this.columns.findIndex((column) => column.type === ImportEntityColumnType.description) > -1;
const hasInvalidColumn = this.columns.findIndex((column) => !this.columnValid(column)) > -1;
this.valid = isSelectName && isSelectType && !hasInvalidColumn;
this.columnTypes.find((columnType) => columnType.value === ImportEntityColumnType.name).disabled = isSelectName;
this.columnTypes.find((columnType) => columnType.value === ImportEntityColumnType.type).disabled = isSelectType;
this.columnTypes.find((columnType) => columnType.value === ImportEntityColumnType.label).disabled = isSelectLabel;
this.columnTypes.find((columnType) => columnType.value === ImportEntityColumnType.isGateway).disabled = isSelectGateway;
this.columnTypes.find((columnType) => columnType.value === ImportEntityColumnType.description).disabled = isSelectDescription;
const accessTokenColumnType = this.columnTypes.find((columnType) => columnType.value === ImportEntityColumnType.accessToken);
if (accessTokenColumnType) {
accessTokenColumnType.disabled = isSelectCredentials;
@ -127,6 +137,15 @@ export class TableColumnsAssignmentComponent implements OnInit, ControlValueAcce
}
}
public isColumnTypeDiffers(columnType: ImportEntityColumnType): boolean {
return columnType !== ImportEntityColumnType.name &&
columnType !== ImportEntityColumnType.type &&
columnType !== ImportEntityColumnType.label &&
columnType !== ImportEntityColumnType.accessToken &&
columnType !== ImportEntityColumnType.isGateway &&
columnType !== ImportEntityColumnType.description;
}
private columnValid(column: CsvColumnParam): boolean {
if (!importEntityObjectColumns.includes(column.type)) {
return column.key && column.key.trim().length > 0;

View File

@ -77,6 +77,10 @@
[entityType]="entityType.ASSET"
>
</tb-entity-subtype-autocomplete>
<mat-form-field class="mat-block">
<mat-label translate>asset.label</mat-label>
<input matInput formControlName="label">
</mat-form-field>
<div formGroupName="additionalInfo">
<mat-form-field class="mat-block">
<mat-label translate>asset.description</mat-label>

View File

@ -64,6 +64,7 @@ export class AssetComponent extends EntityComponent<AssetInfo> {
{
name: [entity ? entity.name : '', [Validators.required]],
type: [entity ? entity.type : null, [Validators.required]],
label: [entity ? entity.label : ''],
additionalInfo: this.fb.group(
{
description: [entity && entity.additionalInfo ? entity.additionalInfo.description : ''],
@ -76,6 +77,7 @@ export class AssetComponent extends EntityComponent<AssetInfo> {
updateForm(entity: AssetInfo) {
this.entityForm.patchValue({name: entity.name});
this.entityForm.patchValue({type: entity.type});
this.entityForm.patchValue({label: entity.label});
this.entityForm.patchValue({additionalInfo: {description: entity.additionalInfo ? entity.additionalInfo.description : ''}});
}

View File

@ -57,6 +57,7 @@ import { AssetTableHeaderComponent } from '@modules/home/pages/asset/asset-table
import { AssetId } from '@app/shared/models/id/asset-id';
import { AssetTabsComponent } from '@home/pages/asset/asset-tabs.component';
import { HomeDialogsService } from '@home/dialogs/home-dialogs.service';
import { DeviceInfo } from '@shared/models/device.models';
@Injectable()
export class AssetsTableConfigResolver implements Resolve<EntityTableConfig<AssetInfo>> {
@ -146,12 +147,13 @@ export class AssetsTableConfigResolver implements Resolve<EntityTableConfig<Asse
configureColumns(assetScope: string): Array<EntityTableColumn<AssetInfo>> {
const columns: Array<EntityTableColumn<AssetInfo>> = [
new DateEntityTableColumn<AssetInfo>('createdTime', 'asset.created-time', this.datePipe, '150px'),
new EntityTableColumn<AssetInfo>('name', 'asset.name', '33%'),
new EntityTableColumn<AssetInfo>('type', 'asset.asset-type', '33%'),
new EntityTableColumn<AssetInfo>('name', 'asset.name', '25%'),
new EntityTableColumn<AssetInfo>('type', 'asset.asset-type', '25%'),
new EntityTableColumn<DeviceInfo>('label', 'asset.label', '25%'),
];
if (assetScope === 'tenant') {
columns.push(
new EntityTableColumn<AssetInfo>('customerTitle', 'customer.customer', '33%'),
new EntityTableColumn<AssetInfo>('customerTitle', 'customer.customer', '25%'),
new EntityTableColumn<AssetInfo>('customerIsPublic', 'asset.public', '60px',
entity => {
return checkBoxCell(entity.customerIsPublic);

View File

@ -26,6 +26,7 @@ export interface Asset extends BaseData<AssetId> {
customerId?: CustomerId;
name: string;
type: string;
label: string;
additionalInfo?: any;
}

View File

@ -26,7 +26,7 @@ export interface Device extends BaseData<DeviceId> {
customerId?: CustomerId;
name: string;
type: string;
label?: string;
label: string;
additionalInfo?: any;
}

View File

@ -31,6 +31,9 @@ export interface EntityInfo {
export interface ImportEntityData {
name: string;
type: string;
label: string;
gateway: boolean;
description: string;
accessToken: string;
attributes: {
server: AttributeData[],