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