blob: 55f6d18d81a68204c3c0ef982514ad473c4294e7 [file] [log] [blame]
/********************************************************************************
* 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);
}
}