Merge import device/asset functionality
This commit is contained in:
		
							parent
							
								
									f1ca4c7cfd
								
							
						
					
					
						commit
						05f0619a2d
					
				@ -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;
 | 
			
		||||
                }),
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -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()"
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -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>
 | 
			
		||||
 | 
			
		||||
@ -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 : ''}});
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
@ -26,6 +26,7 @@ export interface Asset extends BaseData<AssetId> {
 | 
			
		||||
  customerId?: CustomerId;
 | 
			
		||||
  name: string;
 | 
			
		||||
  type: string;
 | 
			
		||||
  label: string;
 | 
			
		||||
  additionalInfo?: any;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -26,7 +26,7 @@ export interface Device extends BaseData<DeviceId> {
 | 
			
		||||
  customerId?: CustomerId;
 | 
			
		||||
  name: string;
 | 
			
		||||
  type: string;
 | 
			
		||||
  label?: string;
 | 
			
		||||
  label: string;
 | 
			
		||||
  additionalInfo?: any;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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[],
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user