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