1 import { Component, EventEmitter, OnDestroy, OnInit, Output } from '@angular/core';
2 import { DesignerStore } from '../designer.store';
3 import { PackageCreationStore } from '../../package-creation/package-creation.store';
4 import { Subject } from 'rxjs';
5 import { distinctUntilChanged, takeUntil } from 'rxjs/operators';
6 import { CBAPackage } from '../../package-creation/mapping-models/CBAPacakge.model';
7 import { TemplateAndMapping } from '../../package-creation/template-mapping/TemplateAndMapping';
8 import { FunctionsStore } from '../functions.store';
9 import { NodeProcess, NodeTemplate } from '../model/desinger.nodeTemplate.model';
10 import { DesignerDashboardState } from '../model/designer.dashboard.state';
11 import { Action } from '../action-attributes/models/Action';
14 selector: 'app-functions-attribute',
15 templateUrl: './functions-attribute.component.html',
16 styleUrls: ['./functions-attribute.component.css']
18 export class FunctionsAttributeComponent implements OnInit, OnDestroy {
20 ngUnsubscribe = new Subject();
21 designerDashboardState: DecodeSuccessCallback;
22 cbaPackage: CBAPackage;
23 templateAndMappingMap = new Map<string, TemplateAndMapping>();
24 selectedTemplates = new Map<string, TemplateAndMapping>();
25 finalTemplates = new Map<string, TemplateAndMapping>();
27 requiredInputs = new Map<string, {}>();
28 requiredOutputs = new Map<string, {}>();
29 OptionalInputs = new Map<string, {}>();
30 optionalOutputs = new Map<string, {}>();
31 artifactPrefix = false;
32 currentFuncion = new NodeProcess();
33 nodeTemplates = new NodeTemplate('');
34 designerState: DesignerDashboardState;
37 interfaceChildName = '';
38 @Output() saveEvent = new EventEmitter<string>();
42 private designerStore: DesignerStore,
43 private packageCreationStore: PackageCreationStore,
44 private functionStore: FunctionsStore
49 this.designerStore.state$.subscribe(designerDashboardState => {
50 this.designerState = designerDashboardState;
51 this.actionName = this.designerState.actionName;
52 const action = this.designerState.template.workflows[this.actionName] as Action;
53 this.currentFuncion = new NodeProcess();
57 // this.designerState.functionName
58 const child = Object.keys(action.steps)[0];
59 this.functionName = this.designerState.functionName;
60 console.log(this.designerState.template.node_templates);
61 console.log(this.designerState);
62 console.log(this.designerState.template.node_templates[this.functionName]);
63 // this.currentFuncion = this.designerState.template.node_templates[this.functionName];
64 // reset inouts&outputs
65 this.requiredInputs = new Map<string, {}>();
66 this.requiredOutputs = new Map<string, {}>();
67 this.OptionalInputs = new Map<string, {}>();
68 this.optionalOutputs = new Map<string, {}>();
69 this.toNodeProcess(this.designerState.template.node_templates[this.functionName], this.functionName);
70 const type = this.designerState.template.node_templates[this.functionName].type;
71 this.getNodeType(type);
77 this.packageCreationStore.state$
78 .subscribe(cbaPackage => {
79 this.cbaPackage = cbaPackage;
80 console.log('File name =>================== ');
81 console.log(this.cbaPackage.templates.files);
82 this.cbaPackage.templates.files.forEach((value, key) => {
83 console.log('File name => ' + key);
84 const templateAndMapping = new TemplateAndMapping();
85 templateAndMapping.isTemplate = true;
86 const isFromTemplate = true;
87 this.setIsMappingOrTemplate(key, templateAndMapping, isFromTemplate);
90 this.cbaPackage.mapping.files.forEach((value, key) => {
91 const templateAndMapping = new TemplateAndMapping();
92 templateAndMapping.isMapping = true;
93 const isFromTemplate = false;
94 this.setIsMappingOrTemplate(key, templateAndMapping, isFromTemplate);
101 // selectedTemplates , templateAndMappingMap
102 // this.selectedTemplates = new Map<string, TemplateAndMapping>();
104 const functionMap = this.designerState.template.node_templates[this.functionName].artifacts;
105 console.log(this.templateAndMappingMap);
107 Object.keys(functionMap).forEach((file) => {
108 const filename = file.substring(0, file.lastIndexOf('-'));
109 console.log(filename);
110 if (this.templateAndMappingMap.has(filename)) {
111 this.selectedTemplates.set(filename, this.templateAndMappingMap.get(filename));
112 this.finalTemplates.set(filename, this.templateAndMappingMap.get(filename));
121 this.selectedTemplates = new Map(this.finalTemplates);
124 toNodeProcess(nodeTemplate, functionName) {
125 console.log(nodeTemplate);
126 this.currentFuncion['instance-name'] = functionName;
127 // tslint:disable-next-line: no-string-literal
128 this.currentFuncion['type'] = nodeTemplate['type'];
129 if (nodeTemplate.interfaces && Object.keys(nodeTemplate.interfaces).length > 0) {
130 const nodeName = Object.keys(nodeTemplate.interfaces)[0];
131 // console.log(Object.keys(nodeTemplate.interfaces));
132 // tslint:disable-next-line: no-string-literal
133 const inputs = nodeTemplate.interfaces[nodeName]['operations']['process']['inputs'];
134 // tslint:disable-next-line: no-string-literal
135 const outputs = nodeTemplate.interfaces[nodeName]['operations']['process']['outputs'];
137 // console.log(inputs);
140 for (const [key, value] of Object.entries(inputs)) {
141 console.log(key + ' - ' + value);
142 if (typeof value === 'object' || this.isValidJson(value)) {
143 this.currentFuncion.inputs[key] = JSON.stringify(value);
145 this.currentFuncion.inputs[key] = value;
150 for (const [key, value] of Object.entries(outputs)) {
151 console.log(key + '-' + value);
152 this.currentFuncion.outputs[key] = value;
161 JSON.parse(val + '');
170 return JSON.stringify(json);
174 const val = JSON.parse(e.target.value);
175 this.currentFuncion.inputs[key] = {
180 this.ngUnsubscribe.next();
181 this.ngUnsubscribe.complete();
185 this.finalTemplates = new Map(this.selectedTemplates);
188 this.selectedTemplates = new Map<string, TemplateAndMapping>();
192 this.nodeTemplates = new NodeTemplate('');
193 // tslint:disable-next-line: variable-name
194 const node_templates = {};
195 const finalFunctionData = this.currentFuncion;
196 // tslint:disable-next-line: no-string-literal
197 const type = finalFunctionData['type'];
198 const instanceName = finalFunctionData['instance-name'];
199 // insert selected templates in nodeTemplates.artifacts
200 this.selectedTemplates.forEach((value, key) => {
203 console.log(finalFunctionData.inputs['artifact-prefix-names']);
205 if (finalFunctionData.inputs['artifact-prefix-names'] === undefined) {
206 finalFunctionData.inputs['artifact-prefix-names'] = [key];
208 Array.isArray(finalFunctionData.inputs['artifact-prefix-names']) &&
209 !finalFunctionData.inputs['artifact-prefix-names'].includes(key)
211 finalFunctionData.inputs['artifact-prefix-names'].push(key);
214 if (value.isMapping) {
215 this.nodeTemplates.artifacts[key + '-mapping'] = {
216 type: 'artifact-mapping-resource',
217 file: 'Templates/' + key + '-mapping.json'
221 if (value.isTemplate) {
222 this.nodeTemplates.artifacts[key + '-template'] = {
223 type: 'artifact-template-velocity',
224 file: 'Templates/' + key + '-template.vtl'
228 // instantiate the final node_template object to save
230 this.nodeTemplates.type = type;
231 delete this.nodeTemplates.properties;
232 node_templates[finalFunctionData['instance-name']] = this.nodeTemplates;
234 delete finalFunctionData['instance-name'];
235 // tslint:disable-next-line: no-string-literal
236 delete finalFunctionData['type'];
238 if (finalFunctionData.outputs === {} || Object.keys(finalFunctionData.outputs).length <= 0) {
239 delete finalFunctionData.outputs;
242 this.nodeTemplates.interfaces = {
243 [this.interfaceChildName]: {
246 ...finalFunctionData,
251 console.log(finalFunctionData);
252 console.log(node_templates);
253 // save function to store
254 // tslint:disable-next-line: no-unused-expression
255 this.designerStore.addNodeTemplate(instanceName, type, node_templates[instanceName]);
256 // create a new package
257 this.saveEvent.emit('save');
260 private setIsMappingOrTemplate(key: string, templateAndMapping: TemplateAndMapping, isFromTemplate: boolean) {
261 const nameOfFile = isFromTemplate ?
262 key.split('/')[1].split('.')[0].split('-template')[0]
263 : key.split('/')[1].split('.')[0].split('-mapping')[0];
264 // const fullName = nameOfFile + ',' + key.split('.');
265 if (this.templateAndMappingMap.has(nameOfFile)) {
266 const templateAndMappingExisted = this.templateAndMappingMap.get(nameOfFile);
267 !isFromTemplate ? templateAndMappingExisted.isMapping = true : templateAndMappingExisted.isTemplate = true;
268 this.templateAndMappingMap.set(nameOfFile, templateAndMappingExisted);
270 this.templateAndMappingMap.set(nameOfFile, templateAndMapping);
275 setArtifact(predefined: boolean) {
277 this.currentFuncion.inputs['artifact-prefix-names'] = [];
279 this.currentFuncion.inputs['artifact-prefix-names'] = { get_input: 'template-prefix' };
282 addToInputs(optionalInput) {
283 this.requiredInputs.set(optionalInput, this.OptionalInputs.get(optionalInput));
284 this.OptionalInputs.delete(optionalInput);
287 setTemplate(file: string) {
288 if (this.selectedTemplates.has(file)) {
289 this.selectedTemplates.delete(file);
291 this.selectedTemplates.set(file, this.templateAndMappingMap.get(file));
293 console.log(this.selectedTemplates);
296 getKeys(map: Map<string, any>) {
297 return Array.from(map.keys());
299 getValue(file: string, map: Map<string, any>) {
300 return map.get(file);
303 getObjectKey(object) {
304 // console.log(object);
305 return Object.keys(object);
307 getObjectValue(object) {
308 return Object.values(object);
311 getNodeType(nodeName: string) {
312 this.functionStore.state$
313 .subscribe(state => {
315 console.log(nodeName);
316 const functions = state.serverFunctions;
317 // tslint:disable-next-line: prefer-for-of
318 for (let i = 0; i < functions.length; i++) {
319 if (functions[i].modelName === nodeName) {
320 // tslint:disable: no-string-literal
321 console.log(functions[i].definition['interfaces']);
322 this.getInputFields(functions[i].definition['interfaces'], 'outputs');
323 this.getInputFields(functions[i].definition['interfaces'], 'inputs');
330 getInputFields(interfaces, type) {
332 if (type === 'inputs') {
333 this.requiredInputs = new Map<string, {}>();
334 this.OptionalInputs = new Map<string, {}>();
336 this.requiredOutputs = new Map<string, {}>();
337 this.optionalOutputs = new Map<string, {}>();
340 const nodeName = Object.keys(interfaces)[0];
341 this.interfaceChildName = nodeName;
342 console.log(nodeName + ' ------ ' + type);
343 console.log(interfaces[nodeName]['operations']['process'][type]);
344 const fields = interfaces[nodeName]['operations']['process'][type];
345 this.artifactPrefix = false;
346 for (const [key, value] of Object.entries(fields)) {
347 if (key === 'artifact-prefix-names') {
348 this.artifactPrefix = true;
349 // in edit&view mode need to check first if this input||output already exists
350 } else if (key in this.currentFuncion.inputs) {
351 this.requiredInputs.set(key, Object.assign({}, value));
352 } else if (key in this.currentFuncion.outputs) {
353 this.requiredOutputs.set(key, Object.assign({}, value));
354 } else if (value['required']) {
355 console.log('This field is required = ' + key);
356 if (type === 'inputs') {
357 this.requiredInputs.set(key, Object.assign({}, value));
359 this.requiredOutputs.set(key, Object.assign({}, value));
362 console.log('This field is Optional ' + key);
363 if (type === 'inputs') {
364 this.OptionalInputs.set(key, Object.assign({}, value));
366 this.optionalOutputs.set(key, Object.assign({}, value));
371 // console.log(this.requiredOutputs);