Commit 05f0619a2d9b6c8a5d036a7db3260a7319c299a8

Authored by Igor Kulikov
1 parent f1ca4c7c

Merge import device/asset functionality

... ... @@ -805,14 +805,28 @@ export class EntityService {
805 805 case EntityType.DEVICE:
806 806 const device: Device = {
807 807 name: entityData.name,
808   - type: entityData.type
  808 + type: entityData.type,
  809 + label: entityData.label,
  810 + additionalInfo: {
  811 + description: entityData.description
  812 + }
809 813 };
  814 + if (entityData.gateway !== null) {
  815 + device.additionalInfo = {
  816 + ...device.additionalInfo,
  817 + gateway: entityData.gateway
  818 + };
  819 + }
810 820 saveEntityObservable = this.deviceService.saveDevice(device, config);
811 821 break;
812 822 case EntityType.ASSET:
813 823 const asset: Asset = {
814 824 name: entityData.name,
815   - type: entityData.type
  825 + type: entityData.type,
  826 + label: entityData.label,
  827 + additionalInfo: {
  828 + description: entityData.description
  829 + }
816 830 };
817 831 saveEntityObservable = this.assetService.saveAsset(asset, config);
818 832 break;
... ... @@ -839,7 +853,31 @@ export class EntityService {
839 853 }
840 854 return findEntityObservable.pipe(
841 855 mergeMap((entity) => {
842   - return this.saveEntityData(entity.id, entityData, config).pipe(
  856 + const tasks: Observable<any>[] = [];
  857 + const result: Device | Asset = entity as (Device | Asset);
  858 + const additionalInfo = result.additionalInfo || {};
  859 + if(result.label !== entityData.label ||
  860 + result.type !== entityData.type ||
  861 + additionalInfo.description !== entityData.description ||
  862 + (result.id.entityType === EntityType.DEVICE && (additionalInfo.gateway !== entityData.gateway)) ) {
  863 + result.label = entityData.label;
  864 + result.type = entityData.type;
  865 + result.additionalInfo = additionalInfo;
  866 + result.additionalInfo.description = entityData.description;
  867 + if (result.id.entityType === EntityType.DEVICE) {
  868 + result.additionalInfo.gateway = entityData.gateway;
  869 + }
  870 + switch (result.id.entityType) {
  871 + case EntityType.DEVICE:
  872 + tasks.push(this.deviceService.saveDevice(result, config));
  873 + break;
  874 + case EntityType.ASSET:
  875 + tasks.push(this.assetService.saveAsset(result, config));
  876 + break;
  877 + }
  878 + }
  879 + tasks.push(this.saveEntityData(entity.id, entityData, config));
  880 + return forkJoin(tasks).pipe(
843 881 map(() => {
844 882 return { update: { entity: 1 } } as ImportEntitiesResultInfo;
845 883 }),
... ...
... ... @@ -168,7 +168,7 @@ export class ImportDialogCsvComponent extends DialogComponent<ImportDialogCsvCom
168 168 const isHeader: boolean = this.importParametersFormGroup.get('isHeader').value;
169 169 for (let i = 0; i < this.parseData.headers.length; i++) {
170 170 let columnParam: CsvColumnParam;
171   - if (isHeader && this.parseData.headers[i].search(/^(name|type)$/im) === 0) {
  171 + if (isHeader && this.parseData.headers[i].search(/^(name|type|label)$/im) === 0) {
172 172 columnParam = {
173 173 type: ImportEntityColumnType[this.parseData.headers[i].toLowerCase()],
174 174 key: this.parseData.headers[i].toLowerCase(),
... ... @@ -195,6 +195,9 @@ export class ImportDialogCsvComponent extends DialogComponent<ImportDialogCsvCom
195 195 const entityData: ImportEntityData = {
196 196 name: '',
197 197 type: '',
  198 + description: '',
  199 + gateway: null,
  200 + label: '',
198 201 accessToken: '',
199 202 attributes: {
200 203 server: [],
... ... @@ -232,6 +235,15 @@ export class ImportDialogCsvComponent extends DialogComponent<ImportDialogCsvCom
232 235 case ImportEntityColumnType.type:
233 236 entityData.type = importData.rows[i][j];
234 237 break;
  238 + case ImportEntityColumnType.label:
  239 + entityData.label = importData.rows[i][j];
  240 + break;
  241 + case ImportEntityColumnType.isGateway:
  242 + entityData.gateway = importData.rows[i][j];
  243 + break;
  244 + case ImportEntityColumnType.description:
  245 + entityData.description = importData.rows[i][j];
  246 + break;
235 247 }
236 248 }
237 249 entitiesData.push(entityData);
... ...
... ... @@ -44,12 +44,15 @@ export interface CsvToJsonResult {
44 44 export enum ImportEntityColumnType {
45 45 name = 'NAME',
46 46 type = 'TYPE',
  47 + label = 'LABEL',
47 48 clientAttribute = 'CLIENT_ATTRIBUTE',
48 49 sharedAttribute = 'SHARED_ATTRIBUTE',
49 50 serverAttribute = 'SERVER_ATTRIBUTE',
50 51 timeseries = 'TIMESERIES',
51 52 entityField = 'ENTITY_FIELD',
52   - accessToken = 'ACCESS_TOKEN'
  53 + accessToken = 'ACCESS_TOKEN',
  54 + isGateway = 'IS_GATEWAY',
  55 + description = 'DESCRIPTION'
53 56 }
54 57
55 58 export const importEntityObjectColumns =
... ... @@ -59,12 +62,15 @@ export const importEntityColumnTypeTranslations = new Map<ImportEntityColumnType
59 62 [
60 63 [ImportEntityColumnType.name, 'import.column-type.name'],
61 64 [ImportEntityColumnType.type, 'import.column-type.type'],
  65 + [ImportEntityColumnType.label, 'import.column-type.label'],
62 66 [ImportEntityColumnType.clientAttribute, 'import.column-type.client-attribute'],
63 67 [ImportEntityColumnType.sharedAttribute, 'import.column-type.shared-attribute'],
64 68 [ImportEntityColumnType.serverAttribute, 'import.column-type.server-attribute'],
65 69 [ImportEntityColumnType.timeseries, 'import.column-type.timeseries'],
66 70 [ImportEntityColumnType.entityField, 'import.column-type.entity-field'],
67 71 [ImportEntityColumnType.accessToken, 'import.column-type.access-token'],
  72 + [ImportEntityColumnType.isGateway, 'import.column-type.isgateway'],
  73 + [ImportEntityColumnType.description, 'import.column-type.description'],
68 74 ]
69 75 );
70 76
... ... @@ -136,7 +142,7 @@ function convertStringToJSType(str: string): any {
136 142 return parseFloat(str.replace(',', '.'));
137 143 }
138 144 if (str.search(/^(true|false)$/im) === 0) {
139   - return str === 'true';
  145 + return str.toLowerCase() === 'true';
140 146 }
141 147 if (str === '') {
142 148 return null;
... ...
... ... @@ -42,9 +42,7 @@
42 42 <mat-header-cell *matHeaderCellDef style="width: 30%"> {{ 'import.column-key' | translate }} </mat-header-cell>
43 43 <mat-cell *matCellDef="let column">
44 44 <mat-form-field floatLabel="always" hideRequiredMarker
45   - *ngIf="column.type !== importEntityColumnType.name &&
46   - column.type !== importEntityColumnType.type &&
47   - column.type !== importEntityColumnType.accessToken">
  45 + *ngIf="isColumnTypeDiffers(column.type)">
48 46 <mat-label></mat-label>
49 47 <input matInput required
50 48 [(ngModel)]="column.key" (ngModelChange)="columnsUpdated()"
... ...
... ... @@ -72,6 +72,8 @@ export class TableColumnsAssignmentComponent implements OnInit, ControlValueAcce
72 72 this.columnTypes.push(
73 73 { value: ImportEntityColumnType.name },
74 74 { value: ImportEntityColumnType.type },
  75 + { value: ImportEntityColumnType.label },
  76 + { value: ImportEntityColumnType.description },
75 77 );
76 78 switch (this.entityType) {
77 79 case EntityType.DEVICE:
... ... @@ -79,7 +81,8 @@ export class TableColumnsAssignmentComponent implements OnInit, ControlValueAcce
79 81 { value: ImportEntityColumnType.sharedAttribute },
80 82 { value: ImportEntityColumnType.serverAttribute },
81 83 { value: ImportEntityColumnType.timeseries },
82   - { value: ImportEntityColumnType.accessToken }
  84 + { value: ImportEntityColumnType.accessToken },
  85 + { value: ImportEntityColumnType.isGateway }
83 86 );
84 87 break;
85 88 case EntityType.ASSET:
... ... @@ -109,13 +112,20 @@ export class TableColumnsAssignmentComponent implements OnInit, ControlValueAcce
109 112 columnsUpdated() {
110 113 const isSelectName = this.columns.findIndex((column) => column.type === ImportEntityColumnType.name) > -1;
111 114 const isSelectType = this.columns.findIndex((column) => column.type === ImportEntityColumnType.type) > -1;
  115 + const isSelectLabel = this.columns.findIndex((column) => column.type === ImportEntityColumnType.label) > -1;
112 116 const isSelectCredentials = this.columns.findIndex((column) => column.type === ImportEntityColumnType.accessToken) > -1;
  117 + const isSelectGateway = this.columns.findIndex((column) => column.type === ImportEntityColumnType.isGateway) > -1;
  118 + const isSelectDescription = this.columns.findIndex((column) => column.type === ImportEntityColumnType.description) > -1;
113 119 const hasInvalidColumn = this.columns.findIndex((column) => !this.columnValid(column)) > -1;
114 120
115 121 this.valid = isSelectName && isSelectType && !hasInvalidColumn;
116 122
117 123 this.columnTypes.find((columnType) => columnType.value === ImportEntityColumnType.name).disabled = isSelectName;
118 124 this.columnTypes.find((columnType) => columnType.value === ImportEntityColumnType.type).disabled = isSelectType;
  125 + this.columnTypes.find((columnType) => columnType.value === ImportEntityColumnType.label).disabled = isSelectLabel;
  126 + this.columnTypes.find((columnType) => columnType.value === ImportEntityColumnType.isGateway).disabled = isSelectGateway;
  127 + this.columnTypes.find((columnType) => columnType.value === ImportEntityColumnType.description).disabled = isSelectDescription;
  128 +
119 129 const accessTokenColumnType = this.columnTypes.find((columnType) => columnType.value === ImportEntityColumnType.accessToken);
120 130 if (accessTokenColumnType) {
121 131 accessTokenColumnType.disabled = isSelectCredentials;
... ... @@ -127,6 +137,15 @@ export class TableColumnsAssignmentComponent implements OnInit, ControlValueAcce
127 137 }
128 138 }
129 139
  140 + public isColumnTypeDiffers(columnType: ImportEntityColumnType): boolean {
  141 + return columnType !== ImportEntityColumnType.name &&
  142 + columnType !== ImportEntityColumnType.type &&
  143 + columnType !== ImportEntityColumnType.label &&
  144 + columnType !== ImportEntityColumnType.accessToken &&
  145 + columnType !== ImportEntityColumnType.isGateway &&
  146 + columnType !== ImportEntityColumnType.description;
  147 + }
  148 +
130 149 private columnValid(column: CsvColumnParam): boolean {
131 150 if (!importEntityObjectColumns.includes(column.type)) {
132 151 return column.key && column.key.trim().length > 0;
... ...
... ... @@ -77,6 +77,10 @@
77 77 [entityType]="entityType.ASSET"
78 78 >
79 79 </tb-entity-subtype-autocomplete>
  80 + <mat-form-field class="mat-block">
  81 + <mat-label translate>asset.label</mat-label>
  82 + <input matInput formControlName="label">
  83 + </mat-form-field>
80 84 <div formGroupName="additionalInfo">
81 85 <mat-form-field class="mat-block">
82 86 <mat-label translate>asset.description</mat-label>
... ...
... ... @@ -64,6 +64,7 @@ export class AssetComponent extends EntityComponent<AssetInfo> {
64 64 {
65 65 name: [entity ? entity.name : '', [Validators.required]],
66 66 type: [entity ? entity.type : null, [Validators.required]],
  67 + label: [entity ? entity.label : ''],
67 68 additionalInfo: this.fb.group(
68 69 {
69 70 description: [entity && entity.additionalInfo ? entity.additionalInfo.description : ''],
... ... @@ -76,6 +77,7 @@ export class AssetComponent extends EntityComponent<AssetInfo> {
76 77 updateForm(entity: AssetInfo) {
77 78 this.entityForm.patchValue({name: entity.name});
78 79 this.entityForm.patchValue({type: entity.type});
  80 + this.entityForm.patchValue({label: entity.label});
79 81 this.entityForm.patchValue({additionalInfo: {description: entity.additionalInfo ? entity.additionalInfo.description : ''}});
80 82 }
81 83
... ...
... ... @@ -57,6 +57,7 @@ import { AssetTableHeaderComponent } from '@modules/home/pages/asset/asset-table
57 57 import { AssetId } from '@app/shared/models/id/asset-id';
58 58 import { AssetTabsComponent } from '@home/pages/asset/asset-tabs.component';
59 59 import { HomeDialogsService } from '@home/dialogs/home-dialogs.service';
  60 +import { DeviceInfo } from '@shared/models/device.models';
60 61
61 62 @Injectable()
62 63 export class AssetsTableConfigResolver implements Resolve<EntityTableConfig<AssetInfo>> {
... ... @@ -146,12 +147,13 @@ export class AssetsTableConfigResolver implements Resolve<EntityTableConfig<Asse
146 147 configureColumns(assetScope: string): Array<EntityTableColumn<AssetInfo>> {
147 148 const columns: Array<EntityTableColumn<AssetInfo>> = [
148 149 new DateEntityTableColumn<AssetInfo>('createdTime', 'asset.created-time', this.datePipe, '150px'),
149   - new EntityTableColumn<AssetInfo>('name', 'asset.name', '33%'),
150   - new EntityTableColumn<AssetInfo>('type', 'asset.asset-type', '33%'),
  150 + new EntityTableColumn<AssetInfo>('name', 'asset.name', '25%'),
  151 + new EntityTableColumn<AssetInfo>('type', 'asset.asset-type', '25%'),
  152 + new EntityTableColumn<DeviceInfo>('label', 'asset.label', '25%'),
151 153 ];
152 154 if (assetScope === 'tenant') {
153 155 columns.push(
154   - new EntityTableColumn<AssetInfo>('customerTitle', 'customer.customer', '33%'),
  156 + new EntityTableColumn<AssetInfo>('customerTitle', 'customer.customer', '25%'),
155 157 new EntityTableColumn<AssetInfo>('customerIsPublic', 'asset.public', '60px',
156 158 entity => {
157 159 return checkBoxCell(entity.customerIsPublic);
... ...
... ... @@ -26,6 +26,7 @@ export interface Asset extends BaseData<AssetId> {
26 26 customerId?: CustomerId;
27 27 name: string;
28 28 type: string;
  29 + label: string;
29 30 additionalInfo?: any;
30 31 }
31 32
... ...
... ... @@ -26,7 +26,7 @@ export interface Device extends BaseData<DeviceId> {
26 26 customerId?: CustomerId;
27 27 name: string;
28 28 type: string;
29   - label?: string;
  29 + label: string;
30 30 additionalInfo?: any;
31 31 }
32 32
... ...
... ... @@ -31,6 +31,9 @@ export interface EntityInfo {
31 31 export interface ImportEntityData {
32 32 name: string;
33 33 type: string;
  34 + label: string;
  35 + gateway: boolean;
  36 + description: string;
34 37 accessToken: string;
35 38 attributes: {
36 39 server: AttributeData[],
... ...