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