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