Stop clearing angular store after deploy to avoid script problem.
[ccsdk/cds.git] / cds-ui / designer-client / src / app / modules / feature-modules / packages / designer / functions-attribute / functions-attribute.component.ts
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';
12
13 @Component({
14     selector: 'app-functions-attribute',
15     templateUrl: './functions-attribute.component.html',
16     styleUrls: ['./functions-attribute.component.css']
17 })
18 export class FunctionsAttributeComponent implements OnInit, OnDestroy {
19
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>();
26     fileToDelete: string;
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;
35     actionName = '';
36     functionName = '';
37     interfaceChildName = '';
38     @Output() saveEvent = new EventEmitter<string>();
39
40
41     constructor(
42         private designerStore: DesignerStore,
43         private packageCreationStore: PackageCreationStore,
44         private functionStore: FunctionsStore
45     ) {
46     }
47
48     ngOnInit() {
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();
54             try {
55                 console.log(action);
56                 if (action) {
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);
72                     this.onInitMapping();
73                 }
74             } catch (e) { }
75         });
76
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);
88                 });
89
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);
95                 });
96             });
97
98     }
99
100     onInitMapping() {
101         // selectedTemplates , templateAndMappingMap
102         // this.selectedTemplates = new Map<string, TemplateAndMapping>();
103         try {
104             const functionMap = this.designerState.template.node_templates[this.functionName].artifacts;
105             console.log(this.templateAndMappingMap);
106
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));
113                 }
114             });
115
116
117         } catch (e) { }
118     }
119
120     init() {
121         this.selectedTemplates = new Map(this.finalTemplates);
122     }
123
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'];
136
137             // console.log(inputs);
138
139             if (inputs) {
140                 for (const [key, value] of Object.entries(inputs)) {
141                     console.log(key + ' - ' + value);
142                     if (typeof value === 'object') {
143                         this.currentFuncion.inputs[key] = JSON.stringify(value);
144                     } else {
145                         this.currentFuncion.inputs[key] = value;
146                     }
147                 }
148             }
149             if (outputs) {
150                 for (const [key, value] of Object.entries(outputs)) {
151                     console.log(key + '-' + value);
152                     this.currentFuncion.outputs[key] = value;
153                 }
154             }
155         }
156     }
157     ngOnDestroy() {
158         this.ngUnsubscribe.next();
159         this.ngUnsubscribe.complete();
160     }
161
162     addTemplates() {
163         this.finalTemplates = new Map(this.selectedTemplates);
164     }
165     cancel() {
166         this.selectedTemplates = new Map<string, TemplateAndMapping>();
167     }
168
169     saveFunctionData() {
170         this.nodeTemplates = new NodeTemplate('');
171         // tslint:disable-next-line: variable-name
172         const node_templates = {};
173         const finalFunctionData = this.currentFuncion;
174         // tslint:disable-next-line: no-string-literal
175         const type = finalFunctionData['type'];
176         const instanceName = finalFunctionData['instance-name'];
177         // insert selected templates in nodeTemplates.artifacts
178         this.selectedTemplates.forEach((value, key) => {
179             console.log(key);
180             console.log(value);
181             console.log(finalFunctionData.inputs['artifact-prefix-names']);
182
183             if (finalFunctionData.inputs['artifact-prefix-names'] === undefined) {
184                 finalFunctionData.inputs['artifact-prefix-names'] = [key];
185             } else if (
186                 Array.isArray(finalFunctionData.inputs['artifact-prefix-names']) &&
187                 !finalFunctionData.inputs['artifact-prefix-names'].includes(key)
188             ) {
189                 finalFunctionData.inputs['artifact-prefix-names'].push(key);
190             }
191
192             if (value.isMapping) {
193                 this.nodeTemplates.artifacts[key + '-mapping'] = {
194                     type: 'artifact-mapping-resource',
195                     file: 'Templates/' + key + '-mapping.json'
196                 };
197             }
198
199             if (value.isTemplate) {
200                 this.nodeTemplates.artifacts[key + '-template'] = {
201                     type: 'artifact-template-velocity',
202                     file: 'Templates/' + key + '-template.vtl'
203                 };
204             }
205         });
206         // instantiate the final node_template object to save
207
208         this.nodeTemplates.type = type;
209         delete this.nodeTemplates.properties;
210         node_templates[finalFunctionData['instance-name']] = this.nodeTemplates;
211
212         delete finalFunctionData['instance-name'];
213         // tslint:disable-next-line: no-string-literal
214         delete finalFunctionData['type'];
215
216         if (finalFunctionData.outputs === {} || Object.keys(finalFunctionData.outputs).length <= 0) {
217             delete finalFunctionData.outputs;
218         }
219
220         this.nodeTemplates.interfaces = {
221             [this.interfaceChildName]: {
222                 operations: {
223                     process: {
224                         ...finalFunctionData,
225                     }
226                 }
227             }
228         };
229         console.log(finalFunctionData);
230         console.log(node_templates);
231         // save function to store
232         // tslint:disable-next-line: no-unused-expression
233         this.designerStore.addNodeTemplate(instanceName, type, node_templates[instanceName]);
234         // create a new package
235         this.saveEvent.emit('save');
236     }
237     // Template logic
238     private setIsMappingOrTemplate(key: string, templateAndMapping: TemplateAndMapping, isFromTemplate: boolean) {
239         const nameOfFile = isFromTemplate ?
240             key.split('/')[1].split('.')[0].split('-template')[0]
241             : key.split('/')[1].split('.')[0].split('-mapping')[0];
242         // const fullName = nameOfFile + ',' + key.split('.');
243         if (this.templateAndMappingMap.has(nameOfFile)) {
244             const templateAndMappingExisted = this.templateAndMappingMap.get(nameOfFile);
245             !isFromTemplate ? templateAndMappingExisted.isMapping = true : templateAndMappingExisted.isTemplate = true;
246             this.templateAndMappingMap.set(nameOfFile, templateAndMappingExisted);
247         } else {
248             this.templateAndMappingMap.set(nameOfFile, templateAndMapping);
249         }
250
251     }
252
253     setArtifact(predefined: boolean) {
254         if (predefined) {
255             this.currentFuncion.inputs['artifact-prefix-names'] = [];
256         } else {
257             this.currentFuncion.inputs['artifact-prefix-names'] = { get_input: 'template-prefix' };
258         }
259     }
260     addToInputs(optionalInput) {
261         this.requiredInputs.set(optionalInput, this.OptionalInputs.get(optionalInput));
262         this.OptionalInputs.delete(optionalInput);
263     }
264
265     setTemplate(file: string) {
266         if (this.selectedTemplates.has(file)) {
267             this.selectedTemplates.delete(file);
268         } else {
269             this.selectedTemplates.set(file, this.templateAndMappingMap.get(file));
270         }
271         console.log(this.selectedTemplates);
272     }
273
274     getKeys(map: Map<string, any>) {
275         return Array.from(map.keys());
276     }
277     getValue(file: string, map: Map<string, any>) {
278         return map.get(file);
279     }
280
281     getObjectKey(object) {
282         // console.log(object);
283         return Object.keys(object);
284     }
285     getObjectValue(object) {
286         return Object.values(object);
287     }
288
289     getNodeType(nodeName: string) {
290         this.functionStore.state$
291             .subscribe(state => {
292                 console.log(state);
293                 console.log(nodeName);
294                 const functions = state.serverFunctions;
295                 // tslint:disable-next-line: prefer-for-of
296                 for (let i = 0; i < functions.length; i++) {
297                     if (functions[i].modelName === nodeName) {
298                         // tslint:disable: no-string-literal
299                         console.log(functions[i].definition['interfaces']);
300                         this.getInputFields(functions[i].definition['interfaces'], 'outputs');
301                         this.getInputFields(functions[i].definition['interfaces'], 'inputs');
302                         break;
303                     }
304                 }
305             });
306     }
307
308     getInputFields(interfaces, type) {
309
310         if (type === 'inputs') {
311             this.requiredInputs = new Map<string, {}>();
312             this.OptionalInputs = new Map<string, {}>();
313         } else {
314             this.requiredOutputs = new Map<string, {}>();
315             this.optionalOutputs = new Map<string, {}>();
316
317         }
318         const nodeName = Object.keys(interfaces)[0];
319         this.interfaceChildName = nodeName;
320         console.log(nodeName + ' ------ ' + type);
321         console.log(interfaces[nodeName]['operations']['process'][type]);
322         const fields = interfaces[nodeName]['operations']['process'][type];
323         this.artifactPrefix = false;
324         for (const [key, value] of Object.entries(fields)) {
325             if (key === 'artifact-prefix-names') {
326                 this.artifactPrefix = true;
327                 // in edit&view mode need to check first if this input||output already exists
328             } else if (key in this.currentFuncion.inputs) {
329                 this.requiredInputs.set(key, Object.assign({}, value));
330             } else if (key in this.currentFuncion.outputs) {
331                 this.requiredOutputs.set(key, Object.assign({}, value));
332             } else if (value['required']) {
333                 console.log('This field is required = ' + key);
334                 if (type === 'inputs') {
335                     this.requiredInputs.set(key, Object.assign({}, value));
336                 } else {
337                     this.requiredOutputs.set(key, Object.assign({}, value));
338                 }
339             } else {
340                 console.log('This field is Optional ' + key);
341                 if (type === 'inputs') {
342                     this.OptionalInputs.set(key, Object.assign({}, value));
343                 } else {
344                     this.optionalOutputs.set(key, Object.assign({}, value));
345                 }
346             }
347         }
348
349         // console.log(this.requiredOutputs);
350     }
351
352
353 }