15f2ce45696ffee09f57eb42195cc539846d05ea
[ccsdk/cds.git] / cds-ui / designer-client / src / app / modules / feature-modules / packages / designer / action-attributes / action-attributes.component.ts
1 import {Component, OnInit} from '@angular/core';
2 import {InputActionAttribute, OutputActionAttribute} from './models/InputActionAttribute';
3 import {DesignerStore} from '../designer.store';
4 import {DesignerDashboardState} from '../model/designer.dashboard.state';
5 import {Action} from './models/Action';
6 import {FunctionsStore} from '../functions.store';
7 import {FunctionsState} from '../model/functions.state';
8 import {PackageCreationStore} from '../../package-creation/package-creation.store';
9 import {CBAPackage} from '../../package-creation/mapping-models/CBAPacakge.model';
10
11 @Component({
12     selector: 'app-action-attributes',
13     templateUrl: './action-attributes.component.html',
14     styleUrls: ['./action-attributes.component.css']
15 })
16 export class ActionAttributesComponent implements OnInit {
17
18     inputs = [];
19     outputs = [];
20     newInputs = [];
21     newOutputs = [];
22     actionAttributesSideBar: boolean;
23     inputActionAttribute = new InputActionAttribute();
24     outputActionAttribute = new OutputActionAttribute();
25     isInputOtherType: boolean;
26     isOutputOtherType: boolean;
27     outputOtherType = '';
28     inputOtherType = '';
29     actionName = '';
30     designerState: DesignerDashboardState;
31     isFunctionAttributeActive = false;
32     functions: FunctionsState;
33     steps: string[];
34     suggestedInputs: string[] = [];
35     suggestedOutputs: string[] = [];
36
37     tempInputs: string[] = [];
38     tempOutputs: string[] = [];
39     currentInterfaceName: string;
40     functionAndAttributesInput: Map<string, string[]> = new Map<string, string[]>();
41     private currentTargetFunctionName: any;
42     private functionAndAttributesOutput: Map<string, string[]> = new Map<string, string[]>();
43     suggestedAttributes: string[] = [];
44     selectedFunctionName = '';
45     selectedAttributeName = '';
46     isNotComponentResourceResolution = true;
47     currentArtifacts: string[] = [];
48     isParametersHidden = true;
49     cbaPackage: CBAPackage;
50     suggestedMappingParameters: string[] = [];
51     selectedParameterList: string[] = [];
52     currentSuggestedArtifact: string;
53     suggestedDeletedInput: any = {};
54     suggestedEditedAttribute: any = {};
55
56     constructor(private designerStore: DesignerStore,
57                 private functionsStore: FunctionsStore,
58                 private packageCreationStore: PackageCreationStore) {
59
60     }
61
62     ngOnInit() {
63         console.log('is paramters hidden' + this.isParametersHidden);
64         console.log('is artifacts hidden' + this.isNotComponentResourceResolution);
65         this.designerStore.state$.subscribe(designerState => {
66             this.designerState = designerState;
67             if (this.designerState && this.designerState.actionName) {
68                 this.actionName = this.designerState.actionName;
69                 console.log(this.actionName);
70                 const action = this.designerState.template.workflows[this.actionName] as Action;
71                 if (action.steps) {
72                     const steps = Object.keys(action.steps);
73                     this.isFunctionAttributeActive = steps && steps.length > 0;
74                     this.steps = steps;
75                     this.suggestedOutputs = [];
76                     this.suggestedInputs = [];
77                 }
78                 this.inputs = [];
79                 if (action.inputs) {
80                     const namesOfInput = Object.keys(action.inputs);
81                     this.inputs = this.extractFields(namesOfInput, action.inputs);
82                 }
83                 this.outputs = [];
84                 if (action.outputs) {
85                     const namesOfOutput = Object.keys(action.outputs);
86                     this.outputs = this.extractFields(namesOfOutput, action.outputs);
87                 }
88             }
89         });
90
91         this.functionsStore.state$.subscribe(functions => {
92             this.functions = functions;
93         });
94
95         this.packageCreationStore.state$
96             .subscribe(cbaPackage => {
97                 this.cbaPackage = cbaPackage;
98
99             });
100     }
101
102
103     private extractFields(namesOfOutput: string[], container: {}) {
104         const fields = [];
105         for (const nameOutput of namesOfOutput) {
106             const fieldAttribute = new OutputActionAttribute();
107             fieldAttribute.name = nameOutput;
108             fieldAttribute.description = container[nameOutput].description;
109             fieldAttribute.required = container[nameOutput].required;
110             fieldAttribute.type = container[nameOutput].type;
111             fieldAttribute.value = container[nameOutput].value;
112             console.log(fieldAttribute.value);
113             const insertedOutputActionAttribute = Object.assign({}, fieldAttribute);
114             fields.push(insertedOutputActionAttribute);
115         }
116         return fields;
117     }
118
119     addInput(input: InputActionAttribute) {
120         console.log(input);
121         if (input && input.type && input.name) {
122             const insertedInputActionAttribute = Object.assign({}, input);
123             this.newInputs.push(insertedInputActionAttribute);
124         }
125     }
126
127     addOutput(output: OutputActionAttribute) {
128         console.log(output);
129         if (output && output.type && output.name) {
130             const insertedOutputActionAttribute = Object.assign({}, output);
131             this.newOutputs.push(insertedOutputActionAttribute);
132         }
133     }
134
135     setInputType(type: string) {
136         this.inputActionAttribute.type = type;
137         this.isInputOtherType = this.checkIfTypeIsOther(type);
138     }
139
140     setInputRequired(isRequired) {
141         this.inputActionAttribute.required = isRequired;
142     }
143
144     setOutputRequired(isRequired) {
145         this.outputActionAttribute.required = isRequired;
146     }
147
148     setOutputType(type: string) {
149         this.outputActionAttribute.type = type;
150         this.isOutputOtherType = this.checkIfTypeIsOther(type);
151     }
152
153     checkIfTypeIsOther(type) {
154         return type.includes('Other');
155     }
156
157     submitAttributes() {
158         this.addInput(this.inputActionAttribute);
159         if (this.selectedFunctionName && this.selectedAttributeName) {
160             console.log(this.getValue());
161             this.outputActionAttribute.value =
162                 this.getValue();
163         }
164         this.addOutput(this.outputActionAttribute);
165         this.clearFormInputs();
166         this.storeOutputs(this.newOutputs);
167         this.storeInputs((this.newInputs));
168         this.newInputs.forEach(input => {
169             if (!this.inputs.includes(input)) {
170                 this.inputs.push(input);
171             }
172         });
173
174         this.newOutputs.forEach(output => {
175             if (!this.outputs.includes(output)) {
176                 this.outputs.push(output);
177             }
178         });
179     }
180
181     private getValue() {
182         let value = '["' + this.selectedFunctionName + '", "' + '","' + this.selectedAttributeName;
183
184         if (!this.isParametersHidden) {
185             let currentSelected = '';
186             for (const selectedParameter of this.selectedParameterList) {
187                 currentSelected += '"' + selectedParameter + '",';
188             }
189             value += '","' + this.currentSuggestedArtifact + '",'
190                 + currentSelected.substr(0, currentSelected.length - 2) + '';
191         } else if (!this.isNotComponentResourceResolution && this.currentSuggestedArtifact) {
192             value += '","' + this.currentSuggestedArtifact + '';
193
194         }
195
196         return value += '"]';
197     }
198
199     public clearFormInputs() {
200         console.log('trying to clear ');
201         this.inputActionAttribute = new InputActionAttribute();
202         this.outputActionAttribute = new OutputActionAttribute();
203         this.outputOtherType = '';
204         this.inputOtherType = '';
205     }
206
207     private storeInputs(InputActionAttributes: InputActionAttribute[]) {
208
209         let inputs = '';
210         InputActionAttributes.forEach(input => {
211             inputs += this.appendAttributes(input);
212             console.log(inputs);
213         });
214         if (inputs.length > 0) {
215             this.writeAttribute(inputs, 'inputs');
216         }
217     }
218
219     private storeOutputs(OutputActionAttributes: OutputActionAttribute[]) {
220         let outputs = '';
221         OutputActionAttributes.forEach(output => {
222             outputs += this.appendOutputAttributes(output);
223         });
224         if (outputs.length > 0) {
225             this.writeAttribute(outputs, 'outputs');
226         }
227
228     }
229
230     private appendAttributes(inputActionAttribute: InputActionAttribute) {
231         const entrySchema: string = this.getEntrySchema(inputActionAttribute);
232         const input = '"' + inputActionAttribute.name + '" : {\n' +
233             '            "required" : ' + inputActionAttribute.required + ',\n' +
234             '            "type" : "' + inputActionAttribute.type + '",\n' +
235             '            "description" : "' + inputActionAttribute.description + '"';
236         return input + entrySchema;
237     }
238
239     private getEntrySchema(inputActionAttribute: InputActionAttribute) {
240         return inputActionAttribute.type.includes('list') ?
241             ',\n\t' + '"entry_schema" : {\n' +
242             '              "type" : "string"\n' +
243             '            }\n},'
244             :
245             '\n },';
246     }
247
248     setInputAndOutputs(targetName) {
249         console.log(targetName);
250         const nodeTemplate = this.designerState.template.node_templates[targetName];
251         console.log(this.designerState.template.node_templates);
252         console.log(nodeTemplate);
253         /* tslint:disable:no-string-literal */
254         console.log(nodeTemplate['type']);
255         this.functions.serverFunctions
256             /* tslint:disable:no-string-literal */
257             .filter(currentFunction => currentFunction.modelName.includes(nodeTemplate['type']))
258             .forEach(currentFunction => {
259                 console.log(currentFunction);
260                 /* tslint:disable:no-string-literal */
261                 if (currentFunction['definition'] && currentFunction['definition']['interfaces']) {
262                     const interfaces = Object.keys(currentFunction['definition']['interfaces']);
263                     if (interfaces && interfaces.length > 0) {
264                         const interfaceName = interfaces[0];
265                         console.log(interfaceName);
266                         this.currentInterfaceName = interfaceName;
267
268                         if (!this.functionAndAttributesInput.has(targetName)) {
269                             this.currentTargetFunctionName = targetName;
270                             this.functionAndAttributesInput.set(targetName, []);
271                         }
272
273                         if (!this.functionAndAttributesOutput.has(targetName)) {
274                             this.currentTargetFunctionName = targetName;
275                             this.functionAndAttributesOutput.set(targetName, []);
276                         }
277
278                         if (nodeTemplate['interfaces'] &&
279                             nodeTemplate['interfaces'][interfaceName]['operations'] &&
280                             nodeTemplate['interfaces'][interfaceName]['operations']['process']
281                         ) {
282                             console.log('here');
283                             if (nodeTemplate['interfaces'][interfaceName]['operations']['process']['inputs']) {
284                                 /* tslint:disable:no-string-literal */
285                                 this.suggestedInputs = Object.keys(nodeTemplate['interfaces']
286                                     [interfaceName]['operations']['process']['inputs']);
287                                 this.filterTwoCollections(this.suggestedInputs, this.inputs);
288
289                             }
290                             if (nodeTemplate['interfaces'][interfaceName]['operations']['process']['outputs']) {
291                                 /* tslint:disable:no-string-literal */
292                                 this.suggestedOutputs = Object.keys(nodeTemplate['interfaces']
293                                     [interfaceName]['operations']['process']['outputs']);
294                                 this.filterTwoCollections(this.suggestedOutputs, this.outputs);
295                             }
296
297                         }
298                     }
299                 }
300             });
301         console.log(nodeTemplate);
302     }
303
304     private filterTwoCollections(suggestedInputs: string[], inputs: any[]) {
305         inputs.forEach(input => {
306             if (suggestedInputs.includes(input.name)) {
307                 this.deleteAttribute(suggestedInputs, input.name);
308             }
309         });
310     }
311
312     printSomethings() {
313         this.setInputAndOutputs(
314             this.designerState.template.workflows[this.actionName]['steps'][this.steps[0]]['target']
315         );
316     }
317
318     addTempInput(suggestedInput: string) {
319         this.addAttribute(this.tempInputs, suggestedInput);
320         this.deleteAttribute(this.suggestedInputs, suggestedInput);
321         this.addAttribute(this.functionAndAttributesInput.get(this.currentTargetFunctionName), suggestedInput);
322     }
323
324     addTempOutput(suggestedOutput: string) {
325         this.addAttribute(this.tempOutputs, suggestedOutput);
326         this.deleteAttribute(this.suggestedOutputs, suggestedOutput);
327         this.addAttribute(this.functionAndAttributesOutput.get(this.currentTargetFunctionName), suggestedOutput);
328     }
329
330     deleteAttribute(container: string[], suggestedAttribute: string) {
331         if (container && suggestedAttribute && container.includes(suggestedAttribute)) {
332             const index: number = container.indexOf(suggestedAttribute);
333             console.log(index);
334             if (index !== -1) {
335                 container.splice(index, 1);
336             }
337         }
338     }
339
340     addAttribute(container: string[], suggestedAttribute: string) {
341         if (container && suggestedAttribute && !container.includes(suggestedAttribute)) {
342             container.push(suggestedAttribute);
343         }
344     }
345
346
347     submitTempAttributes() {
348         this.writeSelectedAttribute(this.functionAndAttributesInput, 'inputs');
349         this.writeSelectedAttribute(this.functionAndAttributesOutput, 'outputs');
350     }
351
352     private writeSelectedAttribute(map: Map<string, string[]>, attributeType: string) {
353         map.forEach((value, key) => {
354             const nodeTemplate = this.getNodeTemplate(key);
355             this.functions.serverFunctions
356                 /* tslint:disable:no-string-literal */
357                 .filter(currentFunction => currentFunction.modelName.includes(nodeTemplate['type']))
358                 .forEach(currentFunction => {
359
360                     if (currentFunction['definition'] && currentFunction['definition']['interfaces']
361                         [Object.keys(currentFunction['definition'] && currentFunction['definition']['interfaces'])]
362                         ['operations']['process'][attributeType]) {
363                         let newAttributes = '';
364                         const attributes = currentFunction['definition'] && currentFunction['definition']['interfaces']
365                             [Object.keys(currentFunction['definition'] && currentFunction['definition']['interfaces'])]
366                             ['operations']['process'][attributeType];
367                         value.forEach(attribute => {
368                             newAttributes += '"' + attribute + '": ' + this.convertToString(attributes[attribute]) + ',';
369                         });
370                         if (value.length > 0) {
371                             this.writeAttribute(newAttributes, attributeType);
372                         }
373                     }
374                 });
375         });
376     }
377
378     private writeAttribute(newAttributes: string, attributeType: string) {
379         newAttributes = this.removeTheLastComma(newAttributes);
380         console.log(newAttributes);
381         let originalAttributes = this.convertToString(this.designerState.template.workflows[this.actionName]
382             [attributeType]);
383         this.createAttributeTypeIfNotExisted(originalAttributes, attributeType);
384         originalAttributes = this.convertToString(this.designerState.template.workflows[this.actionName]
385             [attributeType]);
386         if (originalAttributes.length > 2) {
387             this.designerState.template.workflows[this.actionName][attributeType] =
388                 this.convertToObject(originalAttributes.substr(0, originalAttributes.length - 1)
389                     + ',' + newAttributes + '}');
390         } else {
391             this.designerState.template.workflows[this.actionName][attributeType] =
392                 this.convertToObject(originalAttributes.substr(0, originalAttributes.length - 1)
393                     + newAttributes + '}');
394         }
395         const action = this.designerState.template.workflows[this.actionName] as Action;
396         this.inputs = [];
397         if (action.inputs) {
398             const namesOfInput = Object.keys(action.inputs);
399             this.inputs = this.extractFields(namesOfInput, action.inputs);
400         }
401         /* console.log(originalAttributes.substr(0, originalAttributes.length - 1) + ',' + newAttributes + '}');
402          this.designerState.template.workflows[this.actionName][attributeType] =
403              this.convertToObject(originalAttributes.substr(0, originalAttributes.length - 1)
404                  + ',' + newAttributes + '}');*/
405     }
406
407     private removeTheLastComma(newInputs: string): string {
408         if (newInputs.endsWith(',')) {
409             newInputs = newInputs.substr(0, newInputs.length - 1);
410         }
411         return newInputs;
412     }
413
414     private convertToString = object => JSON.stringify(object);
415
416     private convertToObject = stringValue => JSON.parse(stringValue);
417
418     private getNodeTemplate = (value: string) => this.designerState.template.node_templates[value];
419
420
421     getAttributesAndOutputs(functionName: string) {
422         this.suggestedAttributes = [];
423         console.log(functionName);
424
425         const nodeTemplate = this.designerState.template.node_templates[functionName];
426         if (nodeTemplate['type'].includes('component-resource-resolution')) {
427             this.isNotComponentResourceResolution = false;
428             this.isParametersHidden = true;
429         } else {
430             this.isNotComponentResourceResolution = true;
431             this.isParametersHidden = true;
432         }
433         /* tslint:disable:no-string-literal */
434         console.log(nodeTemplate['type']);
435         this.functions.serverFunctions
436             /* tslint:disable:no-string-literal */
437             .filter(currentFunction => currentFunction.modelName.includes(nodeTemplate['type']))
438             .forEach(currentFunction => {
439                 if (currentFunction.definition['attributes']) {
440                     Object.keys(currentFunction.definition['attributes']).forEach(attribute => {
441                         this.suggestedAttributes.push(attribute);
442                     });
443                 }
444                 console.log(this.suggestedAttributes);
445
446                 this.selectedFunctionName = functionName;
447
448
449             });
450     }
451
452     addTempOutputAttr(suggestedOutputAndAttribute: string) {
453         console.log('ssss');
454         this.selectedAttributeName = suggestedOutputAndAttribute;
455         this.currentArtifacts = [];
456         const nodeTemplate = this.designerState.template.node_templates[this.selectedFunctionName];
457         if (nodeTemplate['artifacts']
458         ) {
459             Object.keys(nodeTemplate['artifacts']).forEach(key => {
460                 const mappingName = key.split('-')[0];
461                 if (!this.currentArtifacts.includes(mappingName)) {
462                     this.currentArtifacts.push(mappingName);
463                 }
464             });
465         }
466         console.log('happend');
467
468     }
469
470
471     private appendOutputAttributes(outputActionAttribute: OutputActionAttribute) {
472         const entrySchema: string = this.getEntrySchema(outputActionAttribute);
473         const output = '"' + outputActionAttribute.name + '" : {\n' +
474             '            "required" : ' + outputActionAttribute.required + ',\n' +
475             '            "type" : "' + outputActionAttribute.type + '",\n' +
476             '            "description" : "' + outputActionAttribute.description + '",\n' +
477             '            "value\" :' + '{\n' +
478             '             "get_attribute" : ' + outputActionAttribute.value + '\n' +
479             '            }\n';
480
481         return output + entrySchema;
482
483     }
484
485     addArtifactFile(suggestedArtifact: string) {
486         this.currentSuggestedArtifact = suggestedArtifact;
487         this.isParametersHidden = !this.selectedAttributeName.includes('assignment-map');
488         if (!this.isParametersHidden) {
489             this.suggestedMappingParameters = this.getSuggestedMappingParameters(suggestedArtifact);
490         }
491     }
492
493     private getSuggestedMappingParameters(suggestedArtifact: string) {
494         const suggestedMappingParameters = [];
495
496         this.cbaPackage.mapping.files.forEach(((value, key) => {
497             if (key.includes(suggestedArtifact)) {
498
499                 JSON.parse(value).forEach(value2 => {
500                     suggestedMappingParameters.push(value2['name']);
501                 });
502             }
503         }));
504         return suggestedMappingParameters;
505     }
506
507     addSuggestedMappingParameter(suggestedMappingParameter: string) {
508         this.addAttribute(this.selectedParameterList, suggestedMappingParameter);
509         this.deleteAttribute(this.suggestedMappingParameters, suggestedMappingParameter);
510
511     }
512
513     editAttribute(input: any) {
514         this.suggestedEditedAttribute = input;
515     }
516
517     private createAttributeTypeIfNotExisted(originalAttributes: string, attributeType: string) {
518         if (!originalAttributes) {
519             this.designerState.template.workflows[this.actionName][attributeType] = {};
520         }
521     }
522
523     private checkIfTypeIsList(type: string) {
524         return type.includes('list');
525     }
526
527     markDeletedInput(input: any) {
528         this.suggestedDeletedInput = input;
529     }
530
531     deleteActionAttribute() {
532         delete this.designerState.template.workflows[this.actionName]
533             ['inputs'][this.suggestedDeletedInput.name];
534         this.deleteAttribute(this.inputs, this.suggestedDeletedInput);
535
536         delete this.designerState.template.workflows[this.actionName]
537             ['outputs'][this.suggestedDeletedInput.name];
538         this.deleteAttribute(this.outputs, this.suggestedDeletedInput);
539     }
540 }