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