| /******************************************************************************** |
| * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation |
| * |
| * See the NOTICE file(s) distributed with this work for additional |
| * information regarding copyright ownership. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| ********************************************************************************/ |
| |
| |
| import { Component, OnInit, ViewChild, Input, OnDestroy, Output, EventEmitter } from '@angular/core'; |
| import { FormGroup, FormControl, FormBuilder, FormArray, Validators } from '@angular/forms'; |
| import { ActivatedRoute } from '@angular/router'; |
| import { TranslateService } from '@ngx-translate/core'; |
| import { DropdownModule } from 'primeng/dropdown'; |
| import { TreeTableModule } from 'primeng/treetable'; |
| import { TreeNode, MenuItem, SelectItem } from 'primeng/api'; |
| import { ContextMenuModule } from 'primeng/contextmenu'; |
| import { TreeTable, TreeTableToggler, DataTable } from 'primeng/primeng'; |
| import { Observable, BehaviorSubject, of, forkJoin } from 'rxjs'; |
| import 'rxjs/add/operator/toPromise'; |
| |
| import { MDMNotificationService } from '../core/mdm-notification.service'; |
| import { ExtSystemService } from './extsystem.service'; |
| import { Node, Attribute, Relation } from '../navigator/node'; |
| import { plainToClass } from 'class-transformer'; |
| import { CatalogService } from './catalog.service'; |
| import { mergeMap, flatMap, map } from 'rxjs/operators'; |
| |
| @Component( { |
| selector: 'mdm-extsystem-editor', |
| templateUrl: './extsystem-editor.component.html', |
| styleUrls: ['./extsystem.component.css'] |
| }) |
| export class ExtSystemEditorComponent implements OnInit, OnDestroy { |
| |
| // passed down from parent |
| @Input() extSystems: Node[]; |
| @Input() selectedEnvironment: Node; |
| @Input() selectedES: string; |
| |
| @Output() editMode = new EventEmitter<boolean>(); |
| |
| // table selection |
| selectedExtSystem: Node; |
| selectedExtSystemAttr: Node; |
| tableExtSystems: Node[] = new Array(); |
| |
| // dropdown for table edit |
| mdmCompTypes: SelectItem[]; |
| mdmCompNames: Node[]; |
| mdmAttrNames: Node[]; |
| |
| // external system attributes |
| extSystemAttrs: Node[]; |
| bsExtSystemAttrs: BehaviorSubject<Node[]> = new BehaviorSubject<Node[]>(undefined); |
| |
| // loading states |
| loadingExtSystemAttr = false; |
| |
| // for immediate creation only |
| tmpExtSystemAttr: Node; |
| tmpExtSystemMDMAttr: Node; |
| |
| // dropdown boxes |
| availableSlctCtlgComps: any[][] = []; |
| availableSlctAttrComps: any[][] = []; |
| |
| loadedTemplateRoots: any[][] = []; |
| loadedCatalogComps: any[][] = []; |
| loadedAttributeComps: any[][] = []; |
| |
| constructor(private extSystemService: ExtSystemService, |
| private notificationService: MDMNotificationService, |
| private translateService: TranslateService, |
| private catalogService: CatalogService) { |
| |
| this.bsExtSystemAttrs.subscribe(value => { |
| this.extSystemAttrs = value; |
| }); |
| |
| this.mdmCompTypes = [ |
| { label: this.translateService.instant('administration.extsystem.dropdown-please-select'), value: '' }, |
| { label: this.translateService.instant('administration.extsystem.unit-under-test'), value: 'UnitUnderTest' }, |
| { label: this.translateService.instant('administration.extsystem.test-equipment'), value: 'TestEquipment' }, |
| { label: this.translateService.instant('administration.extsystem.test-sequence'), value: 'TestSequence' }, |
| { label: this.translateService.instant('administration.extsystem.sensor'), value: 'Sensor' } |
| ]; |
| } |
| |
| ngOnInit() { |
| for (let extSystem of this.extSystems) { |
| if (extSystem.type === 'ExtSystem' && extSystem.id === this.selectedES) { |
| this.selectedExtSystem = extSystem; |
| this.tableExtSystems.push(this.selectedExtSystem); |
| break; |
| } |
| } |
| |
| this.loadingExtSystemAttr = true; |
| this.extSystemService.getExtSystemAttributesForScope(this.selectedEnvironment.sourceName, this.selectedExtSystem.id) |
| .subscribe(attrs => { |
| this.bsExtSystemAttrs.next(attrs); |
| this.loadingExtSystemAttr = false; |
| }); |
| } |
| |
| ngOnDestroy() { |
| } |
| |
| getExternalSystemAttributes() { |
| if (!this.extSystemAttrs) { |
| return new Array(); |
| } |
| return this.extSystemAttrs.filter(attr => attr.type === 'ExtSystemAttribute'); |
| } |
| getMDMAttributes() { |
| let ids = new Array(); |
| if (this.selectedExtSystemAttr.relations) { |
| for (let relation of this.selectedExtSystemAttr.relations) { |
| if (relation.entityType === 'MDMAttribute') { |
| for (let relationid of relation.ids) { |
| ids.push(relationid); |
| } |
| } |
| } |
| } |
| let data = new Array(); |
| for (let attr of this.extSystemAttrs) { |
| if (attr.type === 'MDMAttribute' && ids.find(el => el === attr.id)) { |
| data.push(attr); |
| } |
| } |
| return data; |
| } |
| |
| getAttributeValueFromNode(node: Node, attribute: string) { |
| if (node && node.attributes !== undefined) { |
| for (let attr of node.attributes) { |
| if (attr.name === attribute) { |
| return attr.value; |
| } |
| } |
| } |
| return ''; |
| } |
| |
| getAttributeFromNode(node: Node, attribute: string) { |
| if (node && node.attributes !== undefined) { |
| for (let attr of node.attributes) { |
| if (attr.name === attribute) { |
| return attr; |
| } |
| } |
| } |
| return undefined; |
| } |
| |
| getNextTemporaryId() { |
| let id = -1; |
| for (let extSystem of this.extSystems) { |
| if (parseInt(extSystem.id, 10) < id) { |
| id = parseInt(extSystem.id, 10); |
| } |
| } |
| return --id; |
| } |
| |
| createAttribute(name: string, value?: string) { |
| let attr = new Attribute(); |
| attr.dataType = 'STRING'; |
| attr.unit = ''; |
| attr.value = value !== undefined ? value : ''; |
| attr.name = name; |
| return attr; |
| } |
| |
| getIndicesForIds(ids: string[]) { |
| let indices = new Array(); |
| for (let id of ids) { |
| for (let extSystem of this.extSystems) { |
| if (extSystem.id === ids[id]) { |
| indices.push(this.extSystems.indexOf(extSystem)); |
| } |
| } |
| } |
| return indices; |
| } |
| |
| /** |
| * Save the external system |
| */ |
| saveExtSystem() { |
| this.getAttributeFromNode(this.selectedExtSystem, 'Name').value = this.selectedExtSystem.name; |
| this.extSystemService.saveExtSystem(this.selectedEnvironment.sourceName, this.selectedExtSystem) |
| .subscribe( |
| response => { /* discard */ }, |
| error => this.notificationService.notifyError( |
| this.translateService.instant('administration.extsystem.err-cannot-update-ext-system'), error) |
| ); |
| } |
| |
| addExtSystemAttr() { |
| // initialze the node |
| this.tmpExtSystemAttr = new Node(); |
| this.tmpExtSystemAttr.type = 'ExtSystemAttribute'; |
| this.tmpExtSystemAttr.sourceType = 'ExtSystemAttr'; |
| this.tmpExtSystemAttr.sourceName = this.selectedEnvironment.sourceName; |
| this.tmpExtSystemAttr.attributes = new Array(); |
| this.tmpExtSystemAttr.attributes.push(this.createAttribute('Description')); |
| this.tmpExtSystemAttr.attributes.push(this.createAttribute('Name')); |
| this.tmpExtSystemAttr.attributes.push(this.createAttribute('ConverterClassname')); |
| this.tmpExtSystemAttr.attributes.push(this.createAttribute('ConverterParameter')); |
| this.tmpExtSystemAttr.attributes.push(this.createAttribute('MimeType', 'application/x-asam.aoany.extsystemattr')); |
| |
| // Initialize relations on the external system if it is not defined yet |
| if (this.selectedExtSystem.relations === undefined || this.selectedExtSystem.relations.length === 0) { |
| this.selectedExtSystem.relations = new Array(); |
| let relation = new Relation(); |
| relation.entityType = 'ExtSystemAttribute'; |
| relation.type = 'CHILDREN'; |
| relation.ids = new Array(); |
| this.selectedExtSystem.relations.push(relation); |
| } |
| if (this.selectedExtSystem.relations[0].ids === undefined) { |
| this.selectedExtSystem.relations[0].ids = new Array(); |
| } |
| |
| // Set initial name to persist the attribute |
| this.tmpExtSystemAttr.name = 'Attribut'; |
| this.getAttributeFromNode(this.tmpExtSystemAttr, 'Name').value = this.tmpExtSystemAttr.name; |
| this.saveExtSystemAttr(this.tmpExtSystemAttr); |
| } |
| |
| /** |
| * Remove the external system attribute |
| */ |
| removeExtSystemAttr(extSystemAttr?: Node) { |
| if (extSystemAttr != undefined) { |
| |
| if (extSystemAttr.id !== undefined && parseInt(extSystemAttr.id, 10) > 0 && this.extSystemAttrs.indexOf(extSystemAttr) !== -1) { |
| this.extSystemService.deleteExtSystemAttr(this.selectedEnvironment.sourceName, extSystemAttr.id).subscribe(); |
| let idxES: number = this.extSystemAttrs.indexOf(extSystemAttr); |
| if (idxES !== -1) { |
| this.extSystemAttrs.splice(idxES, 1); |
| if (extSystemAttr.relations !== undefined && extSystemAttr.relations.length > 0) { |
| // remove all children |
| let indices = new Array<number>(); |
| for (let h of extSystemAttr.relations) { |
| // the mdm attributes |
| indices = indices.concat(this.getIndicesForIds(h.ids)); |
| } |
| indices.sort((a, b) => b - a); |
| for (let i of indices) { |
| this.extSystemAttrs.splice(indices[i], 1); |
| } |
| } |
| } |
| } |
| } |
| this.selectedExtSystemAttr = undefined; |
| } |
| |
| /** |
| * Change listener on the name and description of the table element |
| */ |
| updateSystemAttrModel(rowData: Node) { |
| // update the name attribute |
| this.getAttributeFromNode(rowData, 'Name').value = rowData.name; |
| // persist the change |
| this.saveExtSystemAttr(rowData); |
| } |
| |
| /** |
| * Method invoked only if the save of the external system attribute succeeded |
| * This method is additional only successful if the node is a new node |
| */ |
| saveExtSystemAttrSuccess(nodes: Node[]) { |
| if (this.tmpExtSystemAttr) { |
| for (let node of nodes) { |
| if (node.name === this.tmpExtSystemAttr.name && this.tmpExtSystemAttr.id === undefined) { |
| this.tmpExtSystemAttr.id = node.id; |
| } |
| } |
| this.extSystemAttrs.push(this.tmpExtSystemAttr); |
| this.tmpExtSystemAttr = undefined; |
| } |
| } |
| |
| /** |
| * Save the external system attribute |
| */ |
| saveExtSystemAttr(tmpAttr: Node) { |
| this.extSystemService.saveExtSystemAttr(this.selectedEnvironment.sourceName, tmpAttr, this.selectedExtSystem) |
| .subscribe( |
| response => this.saveExtSystemAttrSuccess(plainToClass(Node, response.json().data)), |
| error => { |
| this.tmpExtSystemAttr = undefined; |
| this.notificationService.notifyError( |
| this.translateService.instant('administration.extsystem.err-cannot-save-ext-system-attr'), error); |
| } |
| ); |
| } |
| |
| onExtSystemAttrSelect(event) { |
| let mdmAttrs = this.getMDMAttributes(); |
| for (let attr of mdmAttrs) { |
| this.getCatalogComponentStr(attr); |
| this.getAttributeComponentStr(attr); |
| } |
| } |
| |
| addExtSystemMDMAttr() { |
| this.tmpExtSystemMDMAttr = new Node(); |
| this.tmpExtSystemMDMAttr.type = 'MDMAttribute'; |
| this.tmpExtSystemMDMAttr.sourceType = 'MDMAttr'; |
| this.tmpExtSystemMDMAttr.sourceName = this.selectedEnvironment.sourceName; |
| this.tmpExtSystemMDMAttr.attributes = new Array(); |
| this.tmpExtSystemMDMAttr.attributes.push(this.createAttribute('AttrName')); |
| this.tmpExtSystemMDMAttr.attributes.push(this.createAttribute('CompName')); |
| this.tmpExtSystemMDMAttr.attributes.push(this.createAttribute('CompType')); |
| this.tmpExtSystemMDMAttr.attributes.push(this.createAttribute('MimeType', 'application/x-asam.aoany.mdmattr')); |
| // the name is the hierarchy from the parent elements appended with the name, set in save method |
| this.tmpExtSystemMDMAttr.attributes.push(this.createAttribute('Name')); |
| |
| // add relation |
| if (this.selectedExtSystemAttr.relations === undefined || this.selectedExtSystemAttr.relations.length === 0) { |
| this.selectedExtSystemAttr.relations = new Array(); |
| let relation = new Relation(); |
| relation.entityType = 'MDMAttribute'; |
| relation.type = 'CHILDREN'; |
| relation.ids = new Array(); |
| this.selectedExtSystemAttr.relations.push(relation); |
| } |
| if (this.selectedExtSystemAttr.relations[0].ids === undefined) { |
| this.selectedExtSystemAttr.relations[0].ids = new Array(); |
| } |
| |
| // Set initial name to persist the attribute |
| this.getAttributeFromNode(this.tmpExtSystemMDMAttr, 'CompType').value = 'UnitUnderTest'; |
| this.getAttributeFromNode(this.tmpExtSystemMDMAttr, 'CompName').value = 'Komponente'; |
| this.getAttributeFromNode(this.tmpExtSystemMDMAttr, 'AttrName').value = 'Attribut'; |
| |
| this.saveExtSystemMDMAttr(this.tmpExtSystemMDMAttr); |
| } |
| |
| removeExtSystemMDMAttr(extSystemMDMAttr?: Node) { |
| if (extSystemMDMAttr != undefined) { |
| if (this.extSystemAttrs.indexOf(extSystemMDMAttr) !== -1) { |
| if (extSystemMDMAttr.id !== undefined && parseInt(extSystemMDMAttr.id, 10) > 0) { |
| this.extSystemService.deleteExtSystemMDMAttr(this.selectedEnvironment.sourceName, extSystemMDMAttr.id).subscribe(); |
| } |
| this.extSystemAttrs.splice(this.extSystemAttrs.indexOf(extSystemMDMAttr), 1); |
| } |
| } |
| } |
| |
| saveExtSystemMDMAttrSuccess(nodes: Node[]) { |
| if (this.tmpExtSystemMDMAttr) { |
| for (let node of nodes) { |
| if (node.name === this.tmpExtSystemMDMAttr.name && this.tmpExtSystemMDMAttr.id === undefined) { |
| this.tmpExtSystemMDMAttr.id = node.id; |
| for (let relation of this.selectedExtSystemAttr.relations) { |
| if (relation.entityType === 'MDMAttribute') { |
| if (relation.ids === undefined) { |
| relation.ids = new Array(); |
| } |
| relation.ids.push(node.id); |
| } |
| } |
| } |
| } |
| this.extSystemAttrs.push(this.tmpExtSystemMDMAttr); |
| this.tmpExtSystemMDMAttr = undefined; |
| } |
| } |
| |
| saveExtSystemMDMAttr(tmpAttr: Node) { |
| // update the name attribute with the hierarchy |
| tmpAttr.name = this.getAttributeValueFromNode(tmpAttr, 'CompType') |
| + '.' + this.getAttributeValueFromNode(tmpAttr, 'CompName') |
| + '.' + this.getAttributeValueFromNode(tmpAttr, 'AttrName'); |
| this.getAttributeFromNode(tmpAttr, 'Name').value = tmpAttr.name; |
| |
| this.extSystemService.saveExtSystemMDMAttr(this.selectedEnvironment.sourceName, tmpAttr, this.selectedExtSystemAttr) |
| .subscribe( |
| response => this.saveExtSystemMDMAttrSuccess(plainToClass(Node, response.json().data)), |
| error => { |
| this.tmpExtSystemMDMAttr = undefined; |
| this.notificationService.notifyError( |
| this.translateService.instant('administration.extsystem.err-cannot-save-ext-mdm-attr'), error); |
| } |
| ); |
| } |
| |
| async loadCatalogComps(type: string) { |
| if (type !== undefined && type != null && type.length > 0) { |
| |
| // load the template roots if not available |
| if (this.loadedTemplateRoots[type] === undefined) { |
| this.loadedTemplateRoots[type] = []; |
| try { |
| const response = await this.catalogService.getTplRootsForType(this.selectedEnvironment.sourceName, type).toPromise(); |
| this.loadedTemplateRoots[type] = response; |
| } catch (error) { |
| this.notificationService.notifyError( |
| this.translateService.instant('administration.extsystem.err-cannot-load-comp-types'), error); |
| } |
| } |
| |
| // load the catalog components if not already triggered |
| if (this.loadedTemplateRoots[type] !== undefined && this.loadedTemplateRoots[type].length > 0 |
| && this.loadedCatalogComps[type] === undefined) { |
| this.loadedCatalogComps[type] = []; |
| let tmpIds = this.loadedTemplateRoots[type].map(tr => tr.id); |
| |
| of(tmpIds).pipe( |
| flatMap(q => forkJoin(...q.map(id => this.catalogService.getTplCompForRoot(this.selectedEnvironment.sourceName, type, id)))), |
| map(nested => [].concat(...nested)) |
| ).subscribe( |
| templateComponentWithDuplicateVersions => { |
| const groupedByName = templateComponentWithDuplicateVersions.reduce((group: any[], templateComponent: any) => { |
| group[templateComponent.name] = group[templateComponent.name] || []; |
| group[templateComponent.name].push(templateComponent); |
| return group; |
| }, {}); |
| let templateComponents = []; |
| for (const name of Object.keys(groupedByName)) { |
| templateComponents.push(groupedByName[name].reduce((g: any, templateComponent: any) => |
| g.id <= templateComponent.id ? templateComponent : g, |
| { id: -1 } |
| )); |
| } |
| this.loadedCatalogComps[type] = templateComponents; |
| }, |
| error => this.notificationService.notifyError( |
| this.translateService.instant('administration.extsystem.err-cannot-load-comp-types'), error) |
| ); |
| |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| async loadAttributeComps(type: string, comp: string) { |
| if (type !== undefined && type != null && type.length > 0 && comp !== undefined && comp != null && comp.length > 0 |
| && this.loadedAttributeComps[type + comp] === undefined) { |
| let compId = ''; |
| let rootId = '0'; |
| if (this.loadedCatalogComps && this.loadedCatalogComps[type]) { |
| for (let catalogComp of this.loadedCatalogComps[type]) { |
| if (catalogComp.name === comp) { |
| compId = catalogComp.id; |
| break; |
| } |
| } |
| } |
| if (this.loadedTemplateRoots && this.loadedTemplateRoots[type]) { |
| for (let templateRoot of this.loadedTemplateRoots[type]) { |
| if (templateRoot.relations !== undefined) { |
| for (let relation of templateRoot.relations) { |
| if (relation.entityType === 'TemplateComponent' |
| && relation.ids !== undefined) { |
| for (let id of relation.ids) { |
| if (id === compId) { |
| rootId = templateRoot.id; |
| break; |
| } |
| } |
| if (rootId !== '0') { |
| break; |
| } |
| } |
| } |
| if (rootId !== '0') { |
| break; |
| } |
| } |
| } |
| } |
| if (rootId !== '0' && compId !== '') { |
| this.loadedAttributeComps[type + comp] = []; |
| try { |
| const response = await this.catalogService. |
| getTplAttrsForComp(this.selectedEnvironment.sourceName, type, rootId, compId).toPromise(); |
| for (let t of response) { |
| this.loadedAttributeComps[type + comp].push(t); |
| } |
| } catch (error) { |
| this.notificationService.notifyError( |
| this.translateService.instant('administration.extsystem.err-cannot-load-comp-types'), error); |
| } |
| return true; |
| } |
| } else { |
| return false; |
| } |
| } |
| |
| getCatalogComponentStr(rowData: Node) { |
| let type: string = <string> this.getAttributeValueFromNode(rowData, 'CompType'); |
| let data: string[] = new Array(); |
| // sensor does not have catalog elements |
| if (type !== undefined && type !== 'Sensor') { |
| let components = this.getCatalogComponents(type); |
| if (components) { |
| for (let component of components) { |
| data.push(component.name); |
| } |
| } |
| } |
| return data; |
| } |
| |
| getAttributeComponentStr(rowData: Node) { |
| let type: string = <string> this.getAttributeValueFromNode(rowData, 'CompType'); |
| let comp: string = <string> this.getAttributeValueFromNode(rowData, 'CompName'); |
| let data: string[] = new Array(); |
| if (type !== undefined && comp !== undefined) { |
| let components = this.getAttributeComponents(type, comp); |
| if (components) { |
| for (let component of components) { |
| data.push(component.name); |
| } |
| } |
| } |
| return data; |
| } |
| |
| getCatalogComponents(type: string) { |
| let data: Node[] = this.loadedCatalogComps[type]; |
| if (data === undefined || data == null || data.length === 0) { |
| if (this.loadCatalogComps(type)) { |
| data = this.loadedCatalogComps[type]; |
| } |
| } |
| return data; |
| } |
| |
| getAttributeComponents(type: string, comp: string) { |
| let data: Node[] = this.loadedAttributeComps[type + comp]; |
| if (data === undefined || data == null || data.length === 0) { |
| if (this.loadAttributeComps(type, comp)) { |
| data = this.loadedAttributeComps[type + comp]; |
| } |
| } |
| return data; |
| } |
| |
| /** |
| * |
| */ |
| availableCatalogComps(rowData: Node) { |
| let result = this.availableSlctCtlgComps[rowData.id]; |
| if (result === undefined) { |
| result = []; |
| result.push({ label: this.translateService.instant('administration.extsystem.dropdown-please-select'), value: '' }); |
| let items = this.getCatalogComponentStr(rowData); |
| for (let item of items) { |
| if (item !== undefined) { |
| result.push({ label: item, value: item}); |
| } |
| } |
| if (result.length > 1) { |
| this.availableSlctCtlgComps[rowData.id] = result; |
| } |
| } |
| return result; |
| } |
| |
| availableAttributeComps(rowData: Node) { |
| let result = this.availableSlctAttrComps[rowData.id]; |
| if (result === undefined) { |
| result = []; |
| result.push({ label: this.translateService.instant('administration.extsystem.dropdown-please-select'), value: '' }); |
| let items = this.getAttributeComponentStr(rowData); |
| for (let item of items) { |
| if (item !== undefined) { |
| result.push({ label: item, value: item}); |
| } |
| } |
| if (result.length > 1) { |
| this.availableSlctAttrComps[rowData.id] = result; |
| } |
| } |
| return result; |
| } |
| |
| handleCompTypeSelect(event, rowData: Node) { |
| this.availableSlctCtlgComps[rowData.id] = undefined; |
| this.availableSlctAttrComps[rowData.id] = undefined; |
| this.getAttributeFromNode(rowData, 'CompName').value = 'Komponente'; |
| this.getAttributeFromNode(rowData, 'AttrName').value = 'Attribut'; |
| this.getCatalogComponentStr(rowData); |
| this.saveExtSystemMDMAttr(rowData); |
| } |
| |
| handleCompSelect(event, rowData: Node) { |
| this.availableSlctAttrComps[rowData.id] = undefined; |
| this.getAttributeFromNode(rowData, 'AttrName').value = 'Attribut'; |
| this.getAttributeComponentStr(rowData); |
| this.saveExtSystemMDMAttr(rowData); |
| } |
| |
| handleAttrCompSelect(event, rowData: Node) { |
| this.saveExtSystemMDMAttr(rowData); |
| } |
| |
| } |