From 4e155d6744198ce55519c610f4190d97b9d09cbd Mon Sep 17 00:00:00 2001 From: Alex ORLUC <alex.orluc@maarch.org> Date: Fri, 18 Sep 2020 09:18:16 +0200 Subject: [PATCH] FEAT #13271 TIME 4 add badges for current search --- .../app/adv-search/adv-search.component.html | 25 ++++++ .../app/adv-search/adv-search.component.scss | 23 +++++ .../app/adv-search/adv-search.component.ts | 56 ++++++++---- .../criteria-tool.component.html | 6 +- .../criteria-tool/criteria-tool.component.ts | 90 ++++++++++++++++--- .../app/header/header-right.component.html | 2 +- .../app/header/header-right.component.ts | 1 - .../select-search/select-search.component.ts | 19 ++-- .../service/indexing-fields.service.ts | 16 ++++ 9 files changed, 194 insertions(+), 44 deletions(-) diff --git a/src/frontend/app/adv-search/adv-search.component.html b/src/frontend/app/adv-search/adv-search.component.html index 8c8f78c53ef..8fd39af0eb3 100644 --- a/src/frontend/app/adv-search/adv-search.component.html +++ b/src/frontend/app/adv-search/adv-search.component.html @@ -24,6 +24,31 @@ (toggleAllRes)="toggleAllRes($event)" (refreshEventAfterAction)="refreshDaoAfterAction()" (refreshEvent)="refreshDao()" [title]="this.translate.instant('lang.searchMailInFolder')"> </app-filters-tool>--> + <div class="filterBadges"> + <span *ngIf="!emptyCriteria()" class="label badge-eraser" + title="{{'lang.eraseAllFilters' | translate}}"><i class="fas fa-eraser"></i></span> + <ng-container *ngFor="let critKey of criteria | keyvalue"> + <ng-container + *ngIf="isArrayType(critKey.value.values) && critKey.value.values.length <= 3"> + <span class="label badge-search" *ngFor="let val of critKey.value.values" + [title]="appCriteriaTool.getLabelValue(critKey.key,val)" + (click)="removeCriteria(critKey.key, val)"><i + class="fa {{indexingFieldService.getField(critKey.key).icon}}" + [title]="indexingFieldService.getField(critKey.key).label"></i> {{appCriteriaTool.getLabelValue(critKey.key,val)}} <i class="fa fa-times-circle"></i></span> + </ng-container> + <ng-container *ngIf="isArrayType(critKey.value.values) && critKey.value.values.length > 3"> + <span class="label badge-search" + [title]="appCriteriaTool.getLabelValues(critKey.key,critKey.value.values)" + (click)="removeCriteria(critKey.key)"><i + class="fa {{indexingFieldService.getField(critKey.key).icon}}" [title]="indexingFieldService.getField(critKey.key).label"></i> {{critKey.value.values.length}} valeurs <i class="fa fa-times-circle"></i></span> + </ng-container> + <ng-container *ngIf="!isArrayType(critKey.value.values)"> + <span class="label badge-search" [title]="critKey.value.values" (click)="removeCriteria(critKey.key, val)"><i + class="fa {{indexingFieldService.getField(critKey.key).icon}}" + [title]="indexingFieldService.getField(critKey.key).label"></i> {{critKey.value.values}} <i class="fa fa-times-circle"></i></span> + </ng-container> + </ng-container> + </div> </div> </div> <div class="container" [class.fullContainer]="appService.getViewMode()"> diff --git a/src/frontend/app/adv-search/adv-search.component.scss b/src/frontend/app/adv-search/adv-search.component.scss index 4bff5a75049..a9ce2b7cdc2 100644 --- a/src/frontend/app/adv-search/adv-search.component.scss +++ b/src/frontend/app/adv-search/adv-search.component.scss @@ -2,6 +2,7 @@ .bg-head-content { flex-direction: column; + padding-bottom: 70px; } .dragPreview { @@ -115,3 +116,25 @@ overflow: hidden; text-overflow: ellipsis; } + +.filterBadges { + width: 100%; +} +.filterBadges>.badge-eraser { + margin: 5px; + background: none; + cursor: pointer; + color: white; + font-size: 20px; +} + +.filterBadges>.label { + white-space: inherit; +} + +.filterBadges>.badge-search { + margin: 5px; + background: white; + color: $primary; + cursor: pointer; +} \ No newline at end of file diff --git a/src/frontend/app/adv-search/adv-search.component.ts b/src/frontend/app/adv-search/adv-search.component.ts index 18fcedcfeeb..ada54c4b904 100644 --- a/src/frontend/app/adv-search/adv-search.component.ts +++ b/src/frontend/app/adv-search/adv-search.component.ts @@ -25,6 +25,8 @@ import { of } from 'rxjs/internal/observable/of'; import { Observable } from 'rxjs/internal/Observable'; import { CriteriaToolComponent } from './criteria-tool/criteria-tool.component'; import { FormControl } from '@angular/forms'; +import { IndexingFieldsService } from '../../service/indexing-fields.service'; +import { ValueConverter } from '@angular/compiler/src/render3/view/template'; declare var $: any; @@ -39,6 +41,7 @@ export class AdvSearchComponent implements OnInit, OnDestroy { public innerHtml: SafeHtml; searchUrl: string = '../rest/search'; searchTerm: string = ''; + criteria: any = {}; homeData: any; injectDatasParam = { @@ -120,13 +123,14 @@ export class AdvSearchComponent implements OnInit, OnDestroy { public viewContainerRef: ViewContainerRef, public appService: AppService, public foldersService: FoldersService, - public functions: FunctionsService) { - _activatedRoute.queryParams.subscribe( - params => { - this.searchTerm = params.value; - } - ); - } + public functions: FunctionsService, + public indexingFieldService: IndexingFieldsService) { + _activatedRoute.queryParams.subscribe( + params => { + this.searchTerm = params.value; + } + ); + } ngOnInit(): void { this.headerService.sideBarAdmin = true; @@ -191,8 +195,8 @@ export class AdvSearchComponent implements OnInit, OnDestroy { this.destroy$.next(true); } - launchSearch(value: any) { - // this.searchUrl = value; + launchSearch(criteria: any) { + this.criteria = criteria; this.refreshDao(); } @@ -211,20 +215,20 @@ export class AdvSearchComponent implements OnInit, OnDestroy { switchMap(() => { this.isLoadingResults = true; return this.resultListDatabase!.getRepoIssues( - this.sort.active, this.sort.direction, this.paginator.pageIndex, this.searchUrl, null, this.paginator.pageSize); + this.sort.active, this.sort.direction, this.paginator.pageIndex, this.searchUrl, null, this.paginator.pageSize, this.criteria); }), map((data: any) => { // Flip flag to show that loading has finished. this.isLoadingResults = false; data = this.processPostData(data); - this.resultsLength = data.countResources; + this.resultsLength = data.count; this.allResInBasket = data.allResources; // this.headerService.setHeader('Dossier : ' + this.folderInfo.label); return data.resources; }), catchError((err: any) => { this.notify.handleErrors(err); - this.router.navigate(['/home']); + // this.router.navigate(['/home']); this.isLoadingResults = false; return of(false); }) @@ -438,6 +442,26 @@ export class AdvSearchComponent implements OnInit, OnDestroy { }) ).subscribe(); } + + emptyCriteria() { + return Object.keys(this.criteria).length === 0; + } + + isArrayType(value: any) { + return (Array.isArray(value)); + } + + removeCriteria(identifier: string, value: any = null) { + const tmpArrCrit = []; + if (value === null || this.criteria[identifier].values.length === 1) { + this.criteria[identifier].values = []; + } else { + const indexArr = this.criteria[identifier].values.indexOf(value); + this.criteria[identifier].values.splice(indexArr, 1); + } + + this.appCriteriaTool.refreshCriteria(this.criteria); + } } export interface BasketList { folder: any; @@ -450,12 +474,12 @@ export class ResultListHttpDao { constructor(private http: HttpClient, private filtersListService: FiltersListService) { } - getRepoIssues(sort: string, order: string, page: number, href: string, filters: string, pageSize: number): Observable<BasketList> { + getRepoIssues(sort: string, order: string, page: number, href: string, filters: string, pageSize: number, criteria: any): Observable<BasketList> { // this.filtersListService.updateListsPropertiesPage(page); // this.filtersListService.updateListsPropertiesPageSize(pageSize); const offset = page * pageSize; - const requestUrl = `${href}?limit=${pageSize}&offset=${offset}${filters}`; - - return this.http.get<BasketList>(requestUrl); + const requestUrl = `${href}?limit=${pageSize}&offset=${offset}`; + // console.log(criteria); + return this.http.post<BasketList>(requestUrl, criteria); } } diff --git a/src/frontend/app/adv-search/criteria-tool/criteria-tool.component.html b/src/frontend/app/adv-search/criteria-tool/criteria-tool.component.html index b697d764812..761f8529bbe 100755 --- a/src/frontend/app/adv-search/criteria-tool/criteria-tool.component.html +++ b/src/frontend/app/adv-search/criteria-tool/criteria-tool.component.html @@ -2,7 +2,7 @@ <mat-form-field floatLabel="never" class="basket-search"> <input class="metaSearch" type="text" matInput [matAutocomplete]="autoCriteria" [placeholder]="'lang.quickSearch' |Â translate" [formControl]="searchTermControl"> - <button mat-icon-button matPrefix (click)="focusFilter()" [title]="'lang.displayCriteria' | translate"> + <button mat-icon-button matPrefix type="button" (click)="focusFilter()" [title]="'lang.displayCriteria' | translate"> <mat-icon class="fas fa-clipboard-list"></mat-icon> </button> <mat-autocomplete [class]="hideCriteriaList ? 'hide' : ''" #autoCriteria="matAutocomplete" @@ -57,10 +57,10 @@ <span class="criteria-label"> <i class="fa {{field.icon}}"></i> {{field.label}} : </span> - <mat-form-field class="input-form"> + <mat-form-field class="input-form" floatLabel="never"> <input [id]="field.identifier" type="number" matInput [formControl]="field.control" [placeholder]="'lang.typeValue' | translate" - min="0" step="0.1"> + min="0" step="1"> </mat-form-field> </ng-container> <ng-container *ngIf="['select', 'radio', 'checkbox'].indexOf(field.type) > -1"> diff --git a/src/frontend/app/adv-search/criteria-tool/criteria-tool.component.ts b/src/frontend/app/adv-search/criteria-tool/criteria-tool.component.ts index 84bd52099a6..976daeb6a5a 100644 --- a/src/frontend/app/adv-search/criteria-tool/criteria-tool.component.ts +++ b/src/frontend/app/adv-search/criteria-tool/criteria-tool.component.ts @@ -127,17 +127,6 @@ export class CriteriaToolComponent implements OnInit { } } - getSearchUrl() { - let arrUrl: any[] = []; - this.currentCriteria.forEach((crit: any) => { - if (!this.functions.empty(crit.control.value)) { - arrUrl.push(`${crit.id}=${crit.control.value}`); - } - }); - this.criteriaTool.close(); - this.searchUrlGenerated.emit('&' + arrUrl.join('&')); - } - getFilterControl() { return this.searchCriteria; } @@ -165,11 +154,46 @@ export class CriteriaToolComponent implements OnInit { }; } this.currentCriteria.forEach((field: any) => { - objCriteria[field.identifier] = { - values: field.control.value - }; + if (!this.functions.empty(field.control.value)) { + objCriteria[field.identifier] = { + values: field.control.value + }; + } }); this.searchUrlGenerated.emit(objCriteria); + this.criteriaTool.close(); + } + + + getLabelValue(identifier: string, value: string) { + 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 { + return this.criteria.filter((field: any) => field.identifier === identifier)[0].values.filter((val: any) => val.id === value)[0].label; + + } + } + + 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) { + field.control.setValue(criteria[field.identifier].values); + } + }); + + this.getCurrentCriteriaValues(); } set_doctype_field(elem: any) { @@ -215,4 +239,42 @@ export class CriteriaToolComponent implements OnInit { ).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_destination_field(elem: any) { + let route = `../rest/indexingModels/entities`; + + return new Promise((resolve, reject) => { + this.http.get(route).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(); + }); + + } } diff --git a/src/frontend/app/header/header-right.component.html b/src/frontend/app/header/header-right.component.html index 88fc4961d5e..21df50a6ebe 100644 --- a/src/frontend/app/header/header-right.component.html +++ b/src/frontend/app/header/header-right.component.html @@ -21,7 +21,7 @@ <mat-form-field floatLabel="never" class="basket-search"> <input class="metaSearch" type="text" matInput [placeholder]="'lang.searchMails' |Â translate" name="searchTarget" [(ngModel)]="searchTarget"> - <button mat-icon-button type="submit" matPrefix [title]="'lang.displayCriteria' | translate"> + <button mat-icon-button type="submit" matPrefix [title]="'lang.quickSearchTarget' | translate"> <mat-icon class="fas fa-search"></mat-icon> </button> </mat-form-field> diff --git a/src/frontend/app/header/header-right.component.ts b/src/frontend/app/header/header-right.component.ts index 7633ceb8af0..2fd2fa2f9f9 100644 --- a/src/frontend/app/header/header-right.component.ts +++ b/src/frontend/app/header/header-right.component.ts @@ -40,7 +40,6 @@ export class HeaderRightComponent implements OnInit { ngOnInit(): void { this.menus = this.privilegeService.getCurrentUserMenus(); - console.log(this.router); } gotToMenu(shortcut: any) { diff --git a/src/frontend/plugins/select-search/select-search.component.ts b/src/frontend/plugins/select-search/select-search.component.ts index 90b5c10d9d8..75d0d371ddb 100755 --- a/src/frontend/plugins/select-search/select-search.component.ts +++ b/src/frontend/plugins/select-search/select-search.component.ts @@ -164,12 +164,13 @@ export class PluginSelectSearchComponent implements OnInit, OnDestroy, AfterView } }); }); - - this.filteredDatas = this.formControlSearch.valueChanges - .pipe( - startWith(''), - map(value => this._filter(value)) - ); + setTimeout(() => { + this.filteredDatas = this.formControlSearch.valueChanges + .pipe( + startWith(''), + map(value => this._filter(value)) + ); + }, 0); // this.initMultipleHandling(); @@ -177,18 +178,18 @@ export class PluginSelectSearchComponent implements OnInit, OnDestroy, AfterView } initOptGroups() { - this.datas.unshift({ id : 0, label : 'toto', disabled : true}); + this.datas.unshift({ id: 0, label: 'toto', disabled: true }); let tmpArr = []; this.optGroupList = this.sortPipe.transform(this.optGroupList, 'label'); this.optGroupList.forEach(group => { - tmpArr.push({ id : group.id, label : group.label, disabled : true}); + tmpArr.push({ id: group.id, label: group.label, disabled: true }); tmpArr = tmpArr.concat(this.datas.filter(data => data[this.optGroupTarget] === group.id).map(data => { return { ...data, title: data.label, - label : '  ' + data.label + label: '  ' + data.label }; })); }); diff --git a/src/frontend/service/indexing-fields.service.ts b/src/frontend/service/indexing-fields.service.ts index aabd7e410d6..ca08bba60bc 100644 --- a/src/frontend/service/indexing-fields.service.ts +++ b/src/frontend/service/indexing-fields.service.ts @@ -41,6 +41,15 @@ export class IndexingFieldsService { ]; fields: any[] = [ + { + identifier: 'resId', + label: this.translate.instant('lang.getResId'), + icon: 'fa-envelope', + type: 'integer', + default_value: [], + values: [], + enabled: true, + }, { identifier: 'recipients', label: this.translate.instant('lang.getRecipients'), @@ -269,6 +278,13 @@ export class IndexingFieldsService { }); } + getField(identifier: string) { + let mergedFields = this.getCoreFields().concat(this.getFields()); + mergedFields = mergedFields.concat(this.customFields); + + return mergedFields.filter(field => field.identifier === identifier)[0]; + } + async getAllFields() { const customFields = await this.getCustomFields(); -- GitLab