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