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