Commit 05f0619a2d9b6c8a5d036a7db3260a7319c299a8

Authored by Igor Kulikov
1 parent f1ca4c7c

Merge import device/asset functionality

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