import { Component, OnInit, ViewChild, ElementRef, EventEmitter, Output, Input, QueryList, ViewChildren } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { TranslateService } from '@ngx-translate/core'; import { AppService } from '../../../service/app.service'; import { FunctionsService } from '../../../service/functions.service'; import { Observable, of } from 'rxjs'; import { FormControl } from '@angular/forms'; import { startWith, map, tap, filter, exhaustMap, catchError } from 'rxjs/operators'; import { LatinisePipe } from 'ngx-pipes'; import { MatExpansionPanel } from '@angular/material/expansion'; import { IndexingFieldsService } from '../../../service/indexing-fields.service'; import { ActivatedRoute } from '@angular/router'; import { MatDialog } from '@angular/material/dialog'; import { ConfirmComponent } from '../../../plugins/modal/confirm.component'; import { NotificationService } from '../../../service/notification/notification.service'; import { AddSearchTemplateModalComponent } from './search-template/search-template-modal.component'; import { DatePipe } from '@angular/common'; import { ContactAutocompleteComponent } from '@appRoot/contact/autocomplete/contact-autocomplete.component'; import { PluginSelectAutocompleteSearchComponent } from '@plugins/select-autocomplete-search/plugin-select-autocomplete-search.component'; import { FolderInputComponent } from '@appRoot/folder/indexing/folder-input.component'; import { TagInputComponent } from '@appRoot/tag/indexing/tag-input.component'; import { IssuingSiteInputComponent } from '@appRoot/administration/registered-mail/issuing-site/indexing/issuing-site-input.component'; @Component({ selector: 'app-criteria-tool', templateUrl: 'criteria-tool.component.html', styleUrls: ['criteria-tool.component.scss', '../../indexation/indexing-form/indexing-form.component.scss'], providers: [DatePipe] }) export class CriteriaToolComponent implements OnInit { loading: boolean = true; criteria: any = []; searchTemplates: any; currentCriteria: any = []; filteredCriteria: Observable<string[]>; searchTermControl = new FormControl(); searchCriteria = new FormControl(); hideCriteriaList: boolean = true; @Input() searchTerm: string = 'Foo'; @Input() defaultCriteria: any = []; @Output() searchUrlGenerated = new EventEmitter<any>(); @Output() loaded = new EventEmitter<any>(); @ViewChild('criteriaTool', { static: false }) criteriaTool: MatExpansionPanel; @ViewChild('searchCriteriaInput', { static: false }) searchCriteriaInput: ElementRef; @ViewChild('appFolderInput', { static: false }) appFolderInput: FolderInputComponent; @ViewChild('appTagInput', { static: false }) appTagInput: TagInputComponent; @ViewChild('appIssuingSiteInput', { static: false }) appIssuingSiteInput: IssuingSiteInputComponent; @ViewChildren('appContactAutocomplete') appContactAutocomplete: QueryList<ContactAutocompleteComponent>; @ViewChildren('pluginSelectAutocompleteSearch') pluginSelectAutocompleteSearch: QueryList<PluginSelectAutocompleteSearchComponent>; constructor( private _activatedRoute: ActivatedRoute, public translate: TranslateService, public http: HttpClient, public appService: AppService, public functions: FunctionsService, public indexingFields: IndexingFieldsService, private dialog: MatDialog, private notify: NotificationService, private datePipe: DatePipe, private latinisePipe: LatinisePipe) { _activatedRoute.queryParams.subscribe( params => { this.searchTerm = params.value; } ); } async ngOnInit(): Promise<void> { this.searchTermControl.setValue(this.searchTerm); this.criteria = await this.indexingFields.getAllFields(); this.criteria.forEach((element: any) => { if (this.defaultCriteria.indexOf(element.identifier) > -1) { element.control = new FormControl(''); this.addCriteria(element, false); } }); this.loaded.emit(true); this.filteredCriteria = this.searchCriteria.valueChanges .pipe( startWith(''), map(value => this._filter(value)) ); this.loading = false; setTimeout(() => { this.searchTermControl.valueChanges .pipe( startWith(''), map(value => { if (typeof value === 'string' && !this.functions.empty(value)) { this.searchTerm = value; } }) ).subscribe(); }, 500); this.getSearchTemplates(); } private _filter(value: string): string[] { if (typeof value === 'string') { const filterValue = this.latinisePipe.transform(value.toLowerCase()); return this.criteria.filter((option: any) => this.latinisePipe.transform(option['label'].toLowerCase()).includes(filterValue)); } else { return this.criteria; } } isCurrentCriteria(criteriaId: string) { return this.currentCriteria.filter((currCrit: any) => currCrit.identifier === criteriaId).length > 0; } async addCriteria(criteria: any, openPanel: boolean = true) { if (this.functions.empty(criteria.control) || this.functions.empty(criteria.control.value)) { criteria.control = criteria.type === 'date' ? new FormControl({}) : new FormControl(''); } this.initField(criteria); this.currentCriteria.push(criteria); this.searchTermControl.setValue(this.searchTerm); this.searchCriteria.reset(); // this.searchCriteriaInput.nativeElement.blur(); if (openPanel) { setTimeout(() => { this.criteriaTool.open(); }, 0); } } initField(field: any) { try { const regex = /role_[.]*/g; if (field.identifier.match(regex) !== null) { this['set_role_field'](field); } else { this['set_' + field.identifier + '_field'](field); } } catch (error) { // console.log(error); } } removeCriteria(index: number) { this.currentCriteria.splice(index, 1); if (this.currentCriteria.length === 0) { this.criteriaTool.close(); } } getFilterControl() { return this.searchCriteria; } getCriterias() { return this.criteria; } getFilteredCriterias() { return this.filteredCriteria; } focusFilter() { this.hideCriteriaList = false; setTimeout(() => { this.searchCriteriaInput.nativeElement.focus(); }, 100); } getCurrentCriteriaValues() { const objCriteria = {}; if (!this.functions.empty(this.searchTermControl.value)) { objCriteria['meta'] = { values: this.searchTermControl.value }; } this.currentCriteria.forEach((field: any) => { if (field.type === 'date') { if (!this.functions.empty(field.control.value.start) || !this.functions.empty(field.control.value.end)) { objCriteria[field.identifier] = { values: field.control.value }; } } else { if (!this.functions.empty(field.control.value)) { objCriteria[field.identifier] = { values: field.control.value }; } } }); this.searchUrlGenerated.emit(objCriteria); } toggleTool(state: boolean) { if (state) { this.criteriaTool.open(); } else { this.criteriaTool.close(); } } getLabelValue(identifier: string, value: any) { if (this.functions.empty(value)) { return this.translate.instant('lang.undefined'); } else if (['doctype', 'destination'].indexOf(identifier) > -1) { return this.criteria.filter((field: any) => field.identifier === identifier)[0].values.filter((val: any) => val.id === value)[0].title; } else { if (this.criteria.filter((field: any) => field.identifier === identifier)[0].type === 'contact' || ['registeredMail_recipient', 'senders', 'recipients'].indexOf(this.criteria.filter((field: any) => field.identifier === identifier)[0].identifier) > -1 ) { return this.appContactAutocomplete.toArray().filter((component: any) => component.id === identifier)[0].getFormatedContact(value.id); } else if (this.criteria.filter((field: any) => field.identifier === identifier)[0].identifier === 'folders') { return this.appFolderInput.getFolderLabel(value); } else if (this.criteria.filter((field: any) => field.identifier === identifier)[0].identifier === 'tags') { return this.appTagInput.getTagLabel(value); } else if (this.criteria.filter((field: any) => field.identifier === identifier)[0].type === 'banAutocomplete') { return `${value.addressNumber} ${value.addressStreet}, ${value.addressTown} (${value.addressPostcode})`; } else if (this.criteria.filter((field: any) => field.identifier === identifier)[0].type === 'selectAutocomplete') { return this.pluginSelectAutocompleteSearch.toArray().filter((component: any) => component.id === identifier)[0].getDataLabel(value); } else { return this.criteria.filter((field: any) => field.identifier === identifier)[0].values.filter((val: any) => val.id === value)[0].label; } } } getFormatLabel(identifier: string, value: any) { if (typeof value === 'object') { return `${this.datePipe.transform(value.start, 'dd/MM/y') } - ${this.datePipe.transform(value.end, 'dd/MM/y')}`; } else { if (identifier === 'registeredMail_issuingSite') { return this.appIssuingSiteInput.getSiteLabel(value); } else { return value; } } } getLabelValues(identifier: string, values: string[]) { if (values.length === 0) { return this.translate.instant('lang.undefined'); } else if (['doctype', 'destination'].indexOf(identifier) > -1) { return this.criteria.filter((field: any) => field.identifier === identifier)[0].values.filter((val: any) => values.indexOf(val.id) > -1).map((val: any) => val.title); } else { return this.criteria.filter((field: any) => field.identifier === identifier)[0].values.filter((val: any) => values.indexOf(val.id) > -1).map((val: any) => val.label); } } refreshCriteria(criteria: any) { this.currentCriteria.forEach((field: any, index: number) => { if (criteria[field.identifier] !== undefined) { if (this.currentCriteria[index].type === 'date' && this.functions.empty(criteria[field.identifier].values)) { field.control.setValue({ start: null, end: null }); } else { field.control.setValue(criteria[field.identifier].values); } } }); if (Object.keys(criteria)[0] === 'meta') { this.searchTermControl.setValue(criteria['meta'].values); } this.getCurrentCriteriaValues(); } searchInAttachments(identifier: string) { return ['subject', 'chrono', 'fulltext'].indexOf(identifier) > -1; } displayInfoSearch(infoSearchNumber: number) { if (infoSearchNumber === 1 && (this.isCurrentCriteria('subject') || this.isCurrentCriteria('chrono') || this.isCurrentCriteria('fulltext') )) { return true; } else if (infoSearchNumber === 2 && this.isCurrentCriteria('fulltext')) { return true; } return false; } set_meta_field(value: any) { this.searchTermControl.setValue(value); } set_doctype_field(elem: any) { return new Promise((resolve, reject) => { this.http.get(`../rest/doctypes`).pipe( tap((data: any) => { let arrValues: any[] = []; data.structure.forEach((doctype: any) => { if (doctype['doctypes_second_level_id'] === undefined) { arrValues.push({ id: doctype.doctypes_first_level_id, label: doctype.doctypes_first_level_label, title: doctype.doctypes_first_level_label, disabled: true, isTitle: true, color: doctype.css_style }); data.structure.filter((info: any) => info.doctypes_first_level_id === doctype.doctypes_first_level_id && info.doctypes_second_level_id !== undefined && info.description === undefined).forEach((secondDoctype: any) => { arrValues.push({ id: secondDoctype.doctypes_second_level_id, label: ' ' + secondDoctype.doctypes_second_level_label, title: secondDoctype.doctypes_second_level_label, disabled: true, isTitle: true, color: secondDoctype.css_style }); arrValues = arrValues.concat(data.structure.filter((infoDoctype: any) => infoDoctype.doctypes_second_level_id === secondDoctype.doctypes_second_level_id && infoDoctype.description !== undefined).map((infoType: any) => { return { id: infoType.type_id, label: ' ' + infoType.description, title: infoType.description, disabled: false, isTitle: false, }; })); }); } }); elem.values = arrValues; elem.event = 'calcLimitDate'; resolve(true); }) ).subscribe(); }); } set_priority_field(elem: any) { return new Promise((resolve, reject) => { this.http.get(`../rest/priorities`).pipe( tap((data: any) => { elem.values = data.priorities; resolve(true); }) ).subscribe(); }); } set_status_field(elem: any) { return new Promise((resolve, reject) => { this.http.get(`../rest/statuses`).pipe( tap((data: any) => { elem.values = data.statuses.map((val: any) => { return { id: val.identifier, label: val.label_status }; }); resolve(true); }) ).subscribe(); }); } set_category_field(elem: any) { return new Promise((resolve, reject) => { this.http.get(`../rest/categories`).pipe( tap((data: any) => { elem.values = data.categories.map((val: any) => { return { id: val.id, label: val.label }; }); resolve(true); }) ).subscribe(); }); } set_destination_field(elem: any) { return new Promise((resolve, reject) => { this.http.get(`../rest/indexingModels/entities`).pipe( tap((data: any) => { let title = ''; elem.values = elem.values.concat(data.entities.map((entity: any) => { title = entity.entity_label; for (let index = 0; index < entity.level; index++) { entity.entity_label = ' ' + entity.entity_label; } return { id: entity.id, title: title, label: entity.entity_label, disabled: false }; })); resolve(true); }) ).subscribe(); }); } set_initiator_field(elem: any) { return new Promise((resolve, reject) => { this.http.get(`../rest/indexingModels/entities`).pipe( tap((data: any) => { let title = ''; elem.values = elem.values.concat(data.entities.map((entity: any) => { title = entity.entity_label; for (let index = 0; index < entity.level; index++) { entity.entity_label = ' ' + entity.entity_label; } return { id: entity.id, title: title, label: entity.entity_label, disabled: false }; })); resolve(true); }) ).subscribe(); }); } set_role_field(elem: any) { elem.type = 'selectAutocomplete'; elem.routeDatas = elem.identifier === 'role_dest' ? ['/rest/autocomplete/users'] : ['/rest/autocomplete/users', '/rest/autocomplete/entities']; /*return new Promise((resolve, reject) => { this.http.get(`../rest/users`).pipe( tap((data: any) => { const arrValues: any[] = []; data.users.forEach((user: any) => { arrValues.push({ id: user.id, label: `${user.firstname} ${user.lastname}`, title: `${user.firstname} ${user.lastname}`, }); }); elem.values = arrValues; resolve(true); }) ).subscribe(); });*/ } getSearchTemplates() { this.http.get(`../rest/searchTemplates`).pipe( tap((data: any) => { this.searchTemplates = data.searchTemplates; }) ).subscribe(); } saveSearchTemplate() { let query: any = []; this.currentCriteria.forEach((field: any, index: number) => { query.push({'identifier': field.identifier, 'values': field.control.value}); }); query.push({'identifier': 'searchTerm', 'values': this.searchTermControl.value}); const dialogRef = this.dialog.open( AddSearchTemplateModalComponent, { panelClass: 'maarch-modal', autoFocus: true, disableClose: true, data: { searchTemplate: {query: query} } } ); dialogRef.afterClosed().pipe( filter((data: any) => data !== undefined), tap((data) => { this.searchTemplates.push(data.searchTemplate); }), catchError((err: any) => { this.notify.handleErrors(err); return of(false); }) ).subscribe(); } deleteSearchTemplate(id: number, index: number) { const dialogRef = this.dialog.open( ConfirmComponent, { panelClass: 'maarch-modal', autoFocus: false, disableClose: true, data: { title: this.translate.instant('lang.delete'), msg: this.translate.instant('lang.confirmAction') } } ); dialogRef.afterClosed().pipe( filter((data: string) => data === 'ok'), exhaustMap(() => this.http.delete(`../rest/searchTemplates/${id}`)), tap(() => { this.searchTemplates.splice(index, 1); this.notify.success(this.translate.instant('lang.searchTemplateDeleted')); }), catchError((err: any) => { this.notify.handleErrors(err); return of(false); }) ).subscribe(); } selectSearchTemplate(searchTemplate: any, openPanel: boolean = true) { this.currentCriteria = []; this.criteria.forEach((element: any) => { let index = searchTemplate.query.map((field: any) => field.identifier).indexOf(element.identifier); if (index > -1) { element.control = new FormControl({ value: searchTemplate.query[index].values, disabled: false }); element.control.value = searchTemplate.query[index].values; this.addCriteria(element, openPanel); } }); let index = searchTemplate.query.map((field: any) => field.identifier).indexOf('searchTerm'); if (index > -1) { this.searchTermControl.setValue(searchTemplate.query[index].values); } } }