1 import { AfterViewInit, 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 import { MatPaginator, MatSort, MatTableDataSource } from '@angular/material';
19 import { ChangeDetectorRef } from '@angular/core';
24 selector: 'app-templ-mapp-creation',
25 templateUrl: './templ-mapp-creation.component.html',
26 styleUrls: ['./templ-mapp-creation.component.css']
28 export class TemplMappCreationComponent implements OnInit, OnDestroy, AfterViewInit {
29 @Output() showListView = new EventEmitter<any>();
30 @Output() showCreationView = new EventEmitter<any>();
31 public uploadedFiles: FileSystemFileEntry[] = [];
32 fileNames: Set<string> = new Set();
33 jsonConvert = new JsonConvert();
34 public files: NgxFileDropEntry[] = [];
36 templateInfo = new TemplateInfo();
37 variables: string[] = [];
38 dtOptions: DataTables.Settings = {};
39 initDtOptions: DataTables.Settings = {};
40 // We use this trigger because fetching the list of persons can be quite long,
41 // thus we ensure the data is fetched before rendering
42 dtTrigger = new Subject();
43 resTableDtTrigger = new Subject();
44 resourceDictionaryRes: ResourceDictionary[] = [];
45 allowedExt = ['.vtl'];
46 @ViewChild(DataTableDirective, { static: false })
47 dtElement: DataTableDirective;
48 MappingAdapter: MappingAdapter;
50 templateFileContent: string;
52 dependancies = new Map<string, Array<string>>();
53 dependanciesSource = new Map<string, string>();
58 templatesExist = false;
59 fileToDelete: any = {};
60 parserFactory: ParserFactory;
61 selectedProps: Set<string>;
62 resColumns: string[] = [
63 'Required', 'Template Input',
64 'name', 'Dictionary Name',
65 'dictionary-source', 'dependencies',
66 'default', 'Velocity', 'Data Type',
69 initColumn: string[] = ['select', ...this.resColumns];
73 // displayedColumns: string[] = ['id', 'name', 'progress', 'color'];
74 dataSource: MatTableDataSource<{}>;
75 initDataSource: MatTableDataSource<{}>;
76 // dataSource = new MatTableDataSource();
77 @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
78 @ViewChild(MatSort, { static: true }) sort: MatSort;
79 @ViewChild(MatPaginator, { static: true }) initPaginator: MatPaginator;
80 @ViewChild(MatSort, { static: true }) initSort: MatSort;
83 private packageCreationStore: PackageCreationStore,
84 private templateStore: TemplateStore,
85 private packageCreationUtils: PackageCreationUtils,
86 private toastr: ToastrService,
87 private sharedService: SharedService,
88 private packageCreationService: PackageCreationService,
89 private tourService: TourService,
90 private cdr: ChangeDetectorRef
96 this.dataSource.paginator = this.paginator;
97 this.dataSource.sort = this.sort;
98 this.initDataSource.paginator = this.initPaginator;
99 this.initDataSource.sort = this.initSort;
105 this.selectedProps = new Set<string>();
106 this.parserFactory = new ParserFactory();
107 this.templateStore.state$.subscribe(templateInfo => {
108 // init Template&mapping vars
109 console.log('Oninit');
110 console.log(templateInfo);
111 this.templateInfo = templateInfo;
112 this.fileToDelete = templateInfo.fileName;
113 this.fileName = templateInfo.fileName.split('/')[1];
115 this.fileName = this.fileName.substr(0, this.fileName.lastIndexOf('-'));
117 if (templateInfo.type === 'mapping' || templateInfo.type.includes('mapping')) {
118 this.mappingRes = templateInfo.mapping;
119 this.currentMapping = Object.assign({}, templateInfo);
120 this.resourceDictionaryRes = [];
121 // Assign the data to the data source for the table to render
122 this.dataSource = new MatTableDataSource(this.mappingRes);
123 // this.cdr.detectChanges();
124 this.dataSource.paginator = this.paginator;
125 this.dataSource.sort = this.sort;
129 this.mappingRes = [];
130 this.currentMapping = Any;
131 this.resourceDictionaryRes = [];
133 this.templateFileContent = templateInfo.fileContent;
134 this.templateExt = this.templateInfo.ext || this.templateExt;
135 this.currentTemplate = Object.assign({}, templateInfo);
137 if (templateInfo.type === 'template' || templateInfo.type.includes('template')) {
138 console.log('template extension ' + this.templateExt);
139 this.currentTemplate.fileName = 'Templates/' + this.fileName + '-template.' + this.templateExt;
140 console.log(this.currentTemplate.fileName);
142 this.currentTemplate = Any;
148 this.sharedService.isEdit().subscribe(res => {
149 console.log('------------------------....');
150 this.templatesExist = this.packageCreationStore.state.templates.files.size > 0
151 || this.packageCreationStore.state.mapping.files.size > 0;
156 console.log('remove ----');
157 this.currentMapping = {};
158 this.currentTemplate = {};
160 this.templateFileContent = '';
161 this.resourceDictionaryRes = [];
162 this.mappingRes = [];
168 setProp(e, propName, index) {
169 this.resourceDictionaryRes[index][propName] = e.checked;
170 console.log(this.resourceDictionaryRes[index]);
174 if (this.selectedProps.has(value)) {
175 this.selectedProps.delete(value);
177 this.selectedProps.add(value);
181 applyFilter(event: Event) {
182 const filterValue = (event.target as HTMLInputElement).value;
183 this.dataSource.filter = filterValue.trim().toLowerCase();
184 if (this.dataSource.paginator) {
185 this.dataSource.paginator.firstPage();
189 initApplyFilter(event: Event) {
190 const filterValue = (event.target as HTMLInputElement).value;
191 this.initDataSource.filter = filterValue.trim().toLowerCase();
192 if (this.initDataSource.paginator) {
193 this.initDataSource.paginator.firstPage();
198 console.log(this.selectedProps);
199 this.selectedProps.forEach(prop => {
200 this.resourceDictionaryRes.forEach((res, index) => {
201 if (res.name === prop) {
202 console.log('delete...');
203 this.resourceDictionaryRes.splice(index, 1);
204 this.selectedProps.delete(prop);
211 if (this.resourceDictionaryRes.length === this.selectedProps.size) {
212 this.selectedProps = new Set<string>();
214 this.resourceDictionaryRes.forEach(prop => {
216 this.selectedProps.add(prop.name);
222 let currentResDictionary = [];
223 if (this.selectedProps && this.selectedProps.size > 0) {
225 this.packageCreationService.getTemplateAndMapping([...this.selectedProps]).subscribe(res => {
226 let message = 'Re-Auto mapping';
227 this.mappingRes = [];
228 currentResDictionary = res;
229 console.log(currentResDictionary);
230 if (currentResDictionary && currentResDictionary.length <= 0) {
231 message = 'No values for those attributes';
234 // Replcae new values with the old ones
235 currentResDictionary.forEach(curr => {
236 for (let i = 0; i < this.resourceDictionaryRes.length; i++) {
237 if (this.resourceDictionaryRes[i].name === curr.name) {
238 this.resourceDictionaryRes[i] = curr;
243 this.toastr.success(message, 'Success');
245 this.toastr.error('Error');
252 switch (this.templateExt) {
264 fileExtensionFromString(filename: string): string {
265 const fileExtension = filename.substring(filename.lastIndexOf('.') + 1);
266 return fileExtension;
269 public getTemplateVariable(fileContent: string) {
270 // TODO: implement factory Pattern for parser
271 console.log('start parsing........ ' + this.templateExt);
272 const parser = this.parserFactory.getParser(fileContent, this.templateExt);
273 return parser.getVariables(fileContent);
276 public dropped(files: NgxFileDropEntry[]) {
278 for (const droppedFile of files) {
279 // Is it a file? & Not added before
280 if (droppedFile.fileEntry.isFile) {
281 const fileEntry = droppedFile.fileEntry as FileSystemFileEntry;
282 this.uploadedFiles.push(fileEntry);
283 this.fileNames.add(fileEntry.name);
289 this.uploadedFiles.splice(index, 1);
293 // Delete from templates
294 this.sharedService.deleteFromList(this.fileName);
295 this.packageCreationStore.state.templates.files.delete(this.fileToDelete);
296 // Delete from Mapping
297 this.packageCreationStore.state.mapping.files.delete(this.fileToDelete);
299 this.packageCreationStore.state.templates.files.size > 0 ||
300 this.packageCreationStore.state.mapping.files.size > 0
307 this.dependancies.clear();
308 this.dependanciesSource.clear();
309 if (this.allowedExt.includes('.csv') || this.allowedExt.includes('.xml')) {
310 this.fetchkeysfromfile();
312 this.setTemplateFilesToStore();
314 $('.btn-cancel').click();
317 fetchkeysfromfile() {
318 for (const droppedFile of this.uploadedFiles) {
319 droppedFile.file((file: File) => {
320 const fileReader = new FileReader();
321 fileReader.onload = (e) => {
322 const fileExt = this.fileExtensionFromString(droppedFile.name);
323 if (fileExt === 'csv') {
324 this.variables = fileReader.result.toString().split(',');
326 const parser = new XmlParser();
327 this.variables = parser.getVariables(fileReader.result.toString());
329 console.log('variables = ' + this.variables);
330 this.getMappingTableFromTemplate(null);
333 fileReader.readAsText(file);
336 this.uploadedFiles = [];
339 private convertDictionaryToMap(resourceDictionaries: ResourceDictionary[]): Mapping[] {
340 const mapArray: Mapping[] = [];
341 for (const resourceDictionary of resourceDictionaries) {
342 this.MappingAdapter = new MappingAdapter(resourceDictionary, this.dependancies, this.dependanciesSource);
343 mapArray.push(this.MappingAdapter.ToMapping());
345 console.log(mapArray);
349 setTemplateFilesToStore() {
350 for (const droppedFile of this.uploadedFiles) {
351 droppedFile.file((file: File) => {
352 const fileReader = new FileReader();
353 fileReader.onload = (e) => {
354 this.templateFileContent = fileReader.result.toString();
355 // this.variables = this.getTemplateVariable(this.templateFileContent);
356 // console.log(this.variables);
359 fileReader.readAsText(file);
362 this.uploadedFiles = [];
365 textChanges(code: any, fileName: string) {
366 // this.packageCreationStore.addTemplate(fileName, code);
367 // this.templateFileContent = code;
370 public fileOver(event) {
374 public fileLeave(event) {
378 resetTheUploadedFiles() {
379 this.uploadedFiles = [];
383 console.log('open List view');
384 this.showListView.emit('tell parent to open create views');
388 console.log('close creation view');
389 this.showCreationView.emit('close create form and open list');
392 identify(index, item) {
395 setVelocity(index, value) {
396 // console.log('velocity value = ' + value);
397 // console.log(this.resourceDictionaryRes[index]);
398 // tslint:disable-next-line: no-string-literal
399 this.resourceDictionaryRes[index].definition.property['metadata'] = {
400 'transform-template': value
402 console.log(this.resourceDictionaryRes[index]);
405 getMappingTableFromTemplate(e) {
406 console.log('-' + this.templateFileContent + '-');
407 this.resourceDictionaryRes = [];
411 this.variables = this.getTemplateVariable(this.templateFileContent);
412 console.log('variables = ' + this.variables);
413 if (this.variables && this.variables.length > 0) {
415 this.packageCreationService.getTemplateAndMapping(this.variables).subscribe(res => {
416 let message = 'Attributes are Fetched';
417 this.mappingRes = [];
418 this.resourceDictionaryRes = res;
419 console.log(this.resourceDictionaryRes);
421 if (this.resourceDictionaryRes && this.resourceDictionaryRes.length <= 0) {
422 message = 'No values for those attributes';
424 this.toastr.success(message, 'Success');
426 this.toastr.error('Error');
429 this.toastr.error('Empty or Invalid file format. Validate your file first');
434 if (!this.dependanciesSource.has(key)) {
435 this.dependanciesSource.set(key, map.key);
441 this.templateFileContent = '';
442 this.resourceDictionaryRes = [];
443 this.mappingRes = [];
444 this.currentMapping = {};
445 this.currentTemplate = {};
446 // this.closeCreationForm();
452 const filename = this.fileName;
454 // check file duplication
455 console.log('----------- mode ' + this.edit);
456 const fileContent = this.templateFileContent;
458 (!(this.packageCreationStore.fileExist('Templates/' + this.fileName + '-mapping.json')
459 || this.packageCreationStore.fileExist('Templates/' + this.fileName + '-template' + this.getFileExtension())))
462 // Save Mapping to Store
463 if (this.resourceDictionaryRes && this.resourceDictionaryRes.length > 0) {
464 const mapArray = this.convertDictionaryToMap(this.resourceDictionaryRes);
465 this.packageCreationStore.addMapping('Templates/' + this.fileName + '-mapping.json',
466 this.packageCreationUtils.transformToJson(this.jsonConvert.serialize(mapArray)));
467 this.resourceDictionaryRes = [];
469 // Save Template to store
470 // if (this.templateFileContent) {
471 this.packageCreationStore.addTemplate('Templates/' + filename + '-template' + this.getFileExtension(),
473 this.templateFileContent = '';
476 this.toastr.success('File is created', 'success');
478 if (localStorage.getItem('tour-guide') !== 'end' && localStorage.getItem('tour-guide') !== 'false') {
479 this.tourService.goto('tm-templateEdit');
482 console.log('this file already exist');
483 this.toastr.error('File name already exist', 'Error');
486 this.toastr.error('Add the file name', 'Error');
491 selectSource(dict, e) {
492 const source = e.target.value;
493 let keyDepend = null;
494 this.dependancies.set(dict.name, null);
496 keyDepend = dict.definition.sources[source].properties['key-dependencies'] || null;
501 this.dependancies.set(dict.name, keyDepend);
503 // this.dependancies.delete(dict.name);
504 // this.dependanciesSource.delete(dict.name);
506 this.dependanciesSource.set(dict.name, source);
507 console.log(this.dependancies);
508 console.log(this.dependanciesSource);
511 getKeys(map: Map<string, any>) {
512 return Array.from(map.keys());
516 return this.dependancies.get(key);
520 this.initDataSource = new MatTableDataSource(this.resourceDictionaryRes);
521 // this.cdr.detectChanges();
522 this.initDataSource.paginator = this.initPaginator;
523 this.initDataSource.sort = this.initSort;
526 ngOnDestroy(): void {
527 // Do not forget to unsubscribe the event
528 this.dtTrigger.unsubscribe();
529 this.resTableDtTrigger.unsubscribe();
530 // this.templateStore.unsubscribe();
534 class DependancyVal {
541 this.source = source;
542 this.keyDepend = keyDepend;