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