4601880f87f22ed0343320a28c616e7d18e1d0d2
[ccsdk/cds.git] /
1 import { Component, EventEmitter, OnDestroy, OnInit, Output, ViewChild, AfterViewInit, ElementRef } from '@angular/core';
2 import { FileSystemFileEntry, NgxFileDropEntry } from 'ngx-file-drop';
3 import { PackageCreationStore } from '../../package-creation.store';
4 import { TemplateInfo, TemplateStore } from '../../template.store';
5 import { Subject } from 'rxjs';
6 import { ResourceDictionary } from '../../mapping-models/ResourceDictionary.model';
7 import { DataTableDirective } from 'angular-datatables';
8 import { Mapping, MappingAdapter } from '../../mapping-models/mappingAdapter.model';
9 import { PackageCreationUtils } from '../../package-creation.utils';
10 import { JsonConvert, Any } from 'json2typescript';
11 import { ToastrService } from 'ngx-toastr';
12
13 @Component({
14     selector: 'app-templ-mapp-creation',
15     templateUrl: './templ-mapp-creation.component.html',
16     styleUrls: ['./templ-mapp-creation.component.css']
17 })
18 export class TemplMappCreationComponent implements OnInit, OnDestroy {
19     @Output() showListViewParent = new EventEmitter<any>();
20     @Output() openList = new EventEmitter<any>();
21     public uploadedFiles: FileSystemFileEntry[] = [];
22     private fileNames: Set<string> = new Set();
23     private jsonConvert = new JsonConvert();
24     public files: NgxFileDropEntry[] = [];
25     fileName: any;
26     templateInfo = new TemplateInfo();
27     variables: string[] = [];
28     dtOptions: DataTables.Settings = {};
29     // We use this trigger because fetching the list of persons can be quite long,
30     // thus we ensure the data is fetched before rendering
31     dtTrigger = new Subject();
32     resTableDtTrigger = new Subject();
33     resourceDictionaryRes: ResourceDictionary[] = [];
34     allowedExt = ['.vtl'];
35     @ViewChild(DataTableDirective, { static: false })
36     dtElement: DataTableDirective;
37     MappingAdapter: MappingAdapter;
38     mapping = new Map();
39     templateFileContent: string;
40     templateExt = 'Velcoity';
41     dependancies = new Map<string, Array<string>>();
42     dependanciesSource = new Map<string, string>();
43     mappingRes = [];
44     currentTemplate: any;
45     currentMapping: any;
46
47     constructor(
48         private packageCreationStore: PackageCreationStore,
49         private templateStore: TemplateStore,
50         private packageCreationUtils: PackageCreationUtils,
51         private toastr: ToastrService
52     ) {
53     }
54
55     ngOnInit() {
56         this.templateStore.state$.subscribe(templateInfo => {
57             // init Template&mapping vars
58             console.log('----------');
59             console.log(templateInfo);
60             this.templateInfo = templateInfo;
61             this.fileName = templateInfo.fileName.split('/')[1];
62             if (this.fileName) {
63                 this.fileName = this.fileName.split('-')[0];
64             }
65             if (templateInfo.type === 'mapping' || templateInfo.type.includes('mapping')) {
66                 this.mappingRes = templateInfo.mapping;
67                 this.currentMapping = Object.assign({}, templateInfo);
68                 this.resourceDictionaryRes = [];
69                 this.resTableDtTrigger.next();
70             } else {
71                 this.mappingRes = [];
72                 this.currentMapping = Any;
73             }
74             this.templateFileContent = templateInfo.fileContent;
75             this.currentTemplate = Object.assign({}, templateInfo);
76
77             if (templateInfo.type === 'template' || templateInfo.type.includes('template')) {
78                 this.currentTemplate.fileName = 'Templates/' + this.fileName + '-template.vtl';
79             } else {
80                 this.currentTemplate = Any;
81             }
82
83         });
84
85         this.dtOptions = {
86             pagingType: 'full_numbers',
87             pageLength: 25,
88             destroy: true,
89             retrieve: true,
90         };
91     }
92
93     getFileExtension() {
94         switch (this.templateExt) {
95             case 'Velcoity':
96                 return '.vtl';
97             case 'Koltin':
98                 return '.ktl';
99             case 'Jinja':
100                 return '.j2';
101             default:
102                 return '.vtl';
103         }
104     }
105
106     public getTemplateVariable(fileContent: string) {
107         const variables: string[] = [];
108         const stringsSlittedByBraces = fileContent.split('${');
109         const stringsDefaultByDollarSignOnly = fileContent.split('"$');
110
111         for (let i = 1; i < stringsSlittedByBraces.length; i++) {
112             const element = stringsSlittedByBraces[i];
113             if (element) {
114                 const firstElement = element.split('}')[0];
115                 if (!variables.includes(firstElement)) {
116                     variables.push(firstElement);
117                 } else {
118                     console.log(firstElement);
119                 }
120             }
121         }
122
123         for (let i = 1; i < stringsDefaultByDollarSignOnly.length; i++) {
124             const element = stringsDefaultByDollarSignOnly[i];
125             if (element && !element.includes('$')) {
126                 const firstElement = element.split('"')[0]
127                     .replace('{', '')
128                     .replace('}', '').trim();
129                 if (!variables.includes(firstElement)) {
130                     variables.push(firstElement);
131                 }
132             }
133         }
134         return variables;
135     }
136
137     public dropped(files: NgxFileDropEntry[]) {
138         this.files = files;
139         for (const droppedFile of files) {
140             // Is it a file? & Not added before
141             if (droppedFile.fileEntry.isFile && !this.fileNames.has(droppedFile.fileEntry.name)) {
142                 const fileEntry = droppedFile.fileEntry as FileSystemFileEntry;
143                 this.uploadedFiles.push(fileEntry);
144                 this.fileNames.add(fileEntry.name);
145
146             }
147         }
148     }
149
150     uploadFile() {
151         this.dependancies.clear();
152         this.dependanciesSource.clear();
153         if (this.allowedExt.includes('.csv')) {
154             this.fetchCSVkeys();
155         } else {
156             this.setTemplateFilesToStore();
157         }
158     }
159
160     fetchCSVkeys() {
161         for (const droppedFile of this.uploadedFiles) {
162             droppedFile.file((file: File) => {
163                 const fileReader = new FileReader();
164                 fileReader.onload = (e) => {
165                     this.variables = fileReader.result.toString().split(',');
166                     console.log(this.variables);
167                     this.getMappingTableFromTemplate(null);
168                 };
169                 fileReader.readAsText(file);
170             });
171         }
172         this.uploadedFiles = [];
173     }
174
175     private convertDictionaryToMap(resourceDictionaries: ResourceDictionary[]): Mapping[] {
176         const mapArray: Mapping[] = [];
177         for (const resourceDictionary of resourceDictionaries) {
178             this.MappingAdapter = new MappingAdapter(resourceDictionary, this.dependancies, this.dependanciesSource);
179             mapArray.push(this.MappingAdapter.ToMapping());
180         }
181         console.log(mapArray);
182         return mapArray;
183     }
184
185     setTemplateFilesToStore() {
186         for (const droppedFile of this.uploadedFiles) {
187             droppedFile.file((file: File) => {
188                 const fileReader = new FileReader();
189                 fileReader.onload = (e) => {
190                     this.templateFileContent = fileReader.result.toString();
191                     this.variables = this.getTemplateVariable(this.templateFileContent);
192
193                 };
194                 fileReader.readAsText(file);
195             });
196         }
197         this.uploadedFiles = [];
198     }
199
200     textChanges(code: any, fileName: string) {
201         //  this.packageCreationStore.addTemplate(fileName, code);
202         this.templateFileContent = code;
203     }
204
205     public fileOver(event) {
206         console.log(event);
207     }
208
209     public fileLeave(event) {
210         console.log(event);
211     }
212     //
213     resetTheUploadedFiles() {
214         this.uploadedFiles = [];
215     }
216
217     openListView() {
218         this.showListViewParent.emit('tell parent to open create views');
219     }
220
221     closeCreationForm() {
222         this.openList.emit('close create form and open list');
223     }
224
225     getMappingTableFromTemplate(e) {
226         console.log('-' + this.templateFileContent + '-');
227         this.resourceDictionaryRes = [];
228         if (e) {
229             e.preventDefault();
230         }
231         if (this.variables && this.variables.length > 0) {
232             console.log('base');
233             this.packageCreationStore.getTemplateAndMapping(this.variables).subscribe(res => {
234                 let message = 'Attributes are Fetched';
235                 this.mappingRes = [];
236                 this.resourceDictionaryRes = res;
237                 console.log(this.resourceDictionaryRes);
238                 this.rerender();
239                 if (this.resourceDictionaryRes && this.resourceDictionaryRes.length <= 0) {
240                     message = 'No values for those attributes';
241                 }
242                 this.toastr.success(message, 'Success');
243             }, err => {
244                 this.toastr.error('Error');
245             });
246         }
247     }
248
249     initMap(key, map) {
250         if (!this.dependanciesSource.has(key)) {
251             this.dependanciesSource.set(key, map.key);
252         }
253         return map.key;
254     }
255     cancel() {
256         this.fileName = '';
257         this.templateFileContent = '';
258         this.resourceDictionaryRes = [];
259         this.mappingRes = [];
260         this.currentMapping = {};
261         this.currentTemplate = {};
262     }
263     saveToStore() {
264         if (this.fileName) {
265             // check file duplication
266             if (!(this.packageCreationStore.fileExist('Templates/' + this.fileName + '-mapping.json')
267                 || this.packageCreationStore.fileExist('Templates/' + this.fileName + '-template' + this.getFileExtension()))) {
268                 // Save Mapping to Store
269                 if (this.resourceDictionaryRes && this.resourceDictionaryRes.length > 0) {
270                     const mapArray = this.convertDictionaryToMap(this.resourceDictionaryRes);
271                     this.packageCreationStore.addMapping('Templates/' + this.fileName + '-mapping.json',
272                         this.packageCreationUtils.transformToJson(this.jsonConvert.serialize(mapArray)));
273                     this.resourceDictionaryRes = [];
274                 }
275                 // Save Template to store
276                 if (this.templateFileContent) {
277                     this.packageCreationStore.addTemplate('Templates/' + this.fileName + '-template' + this.getFileExtension(),
278                         this.templateFileContent);
279                     this.templateFileContent = '';
280                 }
281                 this.fileName = '';
282                 this.toastr.success('File is created', 'success');
283                 this.closeCreationForm();
284             } else {
285                 console.log('this file already exist');
286                 this.toastr.error('File name already exist', 'Error');
287             }
288         } else {
289             this.toastr.error('Add the file name', 'Error');
290         }
291     }
292
293
294     selectSource(dict, e) {
295         const source = e.target.value;
296         let keyDepend = null;
297         try {
298             keyDepend = dict.definition.sources[source].properties['key-dependencies'] || null;
299         } catch (e) { }
300         console.log(dict);
301         console.log(source);
302         if (keyDepend) {
303             this.dependancies.set(dict.name, keyDepend);
304         } else {
305             // this.dependancies.delete(dict.name);
306             // this.dependanciesSource.delete(dict.name);
307         }
308         this.dependanciesSource.set(dict.name, source);
309         console.log(this.dependancies);
310         console.log(this.dependanciesSource);
311     }
312
313     getKeys(map: Map<string, any>) {
314         return Array.from(map.keys());
315     }
316
317     getValue(key) {
318         return this.dependancies.get(key);
319     }
320
321     rerender(): void {
322         if (this.dtElement.dtInstance) {
323             console.log('rerender');
324             this.dtElement.dtInstance.then((dtInstance: DataTables.Api) => {
325                 dtInstance.destroy();
326                 this.dtElement.dtOptions = this.dtOptions;
327                 this.dtElement.dtTrigger.next();
328                 dtInstance.draw();
329             });
330         } else {
331             this.dtTrigger.next();
332         }
333     }
334
335     ngOnDestroy(): void {
336         // Do not forget to unsubscribe the event
337         this.dtTrigger.unsubscribe();
338     }
339 }
340
341 class DependancyVal {
342     source: string;
343     keyDepend: any;
344     constructor(
345         source: string,
346         keyDepend: any
347     ) {
348         this.source = source;
349         this.keyDepend = keyDepend;
350     }
351 }