diff --git a/src/frontend/app/list/basket-list.component.html b/src/frontend/app/list/basket-list.component.html index 9d3755fb0d40cf18d244b6d570a8de6c9bbbbdd9..7042b97436bd5e092351ca6186368cb04b071f56 100644 --- a/src/frontend/app/list/basket-list.component.html +++ b/src/frontend/app/list/basket-list.component.html @@ -17,7 +17,7 @@ </div> <div class="row" style="margin:0px;"> <div class="col-md-9 col-xs-9"> - <app-filters-tool [listProperties]="this.listProperties" [snavR]="snav2" (refreshEvent)="refreshDao()"></app-filters-tool> + <app-filters-tool #filtersTool [currentBasketInfo]="currentBasketInfo" [listProperties]="this.listProperties" [snavR]="snav2" (refreshEvent)="refreshDao()"></app-filters-tool> </div> <div class="col-md-3 col-xs-3"> <mat-paginator [length]="resultsLength" [pageSize]="10"></mat-paginator> @@ -60,8 +60,8 @@ <div class="resultCol {{data.class}}" *ngFor="let data of displayedMainData"> <span *ngIf="data.id == 'alt_identifier'"> <mat-icon [ngStyle]="{'color': row.priority_color}" color="primary" class="{{row.status_icon.charAt(0)}}{{row.status_icon.charAt(1)}} {{row.status_icon}} {{row.status_icon.charAt(0)}}{{row.status_icon.charAt(1)}}-2x" - title="{{row.status_label}} ({{row.status_id}})"></mat-icon><br /> - <span style="color: rgba(0,0,0,0.4);font-size: 90%;">{{row[data.id]}}</span> + title="{{row.status_label}} ({{row.status_id}})" style="cursor: crosshair;" (click)="$event.stopPropagation();filterThis(row.status_label)"></mat-icon><br /> + <span style="color: rgba(0,0,0,0.4);font-size: 90%;cursor: crosshair;" (click)="$event.stopPropagation();filterThis(row[data.id])">{{row[data.id]}}</span> </span> <ng-container *ngIf="data.id == 'date'"> <i class="fa fa-calendar" title="{{lang.creationDate}}"></i> {{row.creation_date @@ -80,18 +80,15 @@ </ng-container> </div> <mat-button-toggle-group #group="matButtonToggleGroup" class="actions" multiple> - <button color="primary" mat-icon-button title="{{lang.notes}}" (click)="openBottomSheet(row)"> + <button color="primary" mat-icon-button title="{{lang.notes}}" (click)="$event.stopPropagation();openBottomSheet(row)"> <mat-icon matBadgeHidden="{{row.countNotes == 0}}" fontSet="fas" matBadge="{{row.countNotes}}" fontIcon="fa-comments fa-2x"></mat-icon> </button> - <button color="primary" mat-icon-button title="{{lang.attachments}}" (click)="openAttachSheet(row)"> + <button color="primary" mat-icon-button title="{{lang.attachments}}" (click)="$event.stopPropagation();openAttachSheet(row)"> <mat-icon matBadgeHidden="{{row.countAttachments == 0}}" fontSet="fas" matBadge="{{row.countAttachments}}" fontIcon="fa-paperclip fa-2x"></mat-icon> </button> - <button color="primary" mat-icon-button title="{{lang.diffusionList}}" (click)="openDiffusionSheet(row)"> + <button color="primary" mat-icon-button title="{{lang.diffusionList}}" (click)="$event.stopPropagation();openDiffusionSheet(row)"> <mat-icon fontSet="fas" fontIcon="fa-sitemap fa-2x"></mat-icon> </button> - <button color="primary" mat-icon-button title="{{lang.view}}" (click)="goTo(row)"> - <mat-icon fontSet="fas" fontIcon="fa-eye fa-2x"></mat-icon> - </button> <button color="primary" mat-icon-button title="{{lang.linkDetails}}" (click)="goToDetail(row);"> <mat-icon fontSet="fas" fontIcon="fa-info-circle fa-2x"></mat-icon> </button> @@ -99,7 +96,7 @@ </div> </td> </ng-container> - <tr mat-row *matRowDef="let row; columns: displayedColumnsBasket;"></tr> + <tr mat-row *matRowDef="let row; columns: displayedColumnsBasket;" (click)="goTo(row);" style="cursor: pointer;"></tr> </table> <div class="mat-paginator" style="min-height:48px;min-height: 48px;display: flex;justify-content: end;align-items: center;padding-right: 20px;">{{resultsLength}} {{lang.entries}}</div> @@ -107,9 +104,10 @@ </mat-sidenav-content> <mat-sidenav #snav2 mode="over" [fixedInViewport]="mobileQuery.matches" fixedTopGap="56" position='end' [opened]="mobileQuery.matches ? false : false" style="overflow-x:hidden;" [class.docView]="!filtersListService.filterMode" [ngStyle]="{'width': mobileMode ? '80%' : '40%'}" autoFocus="false"> - <div *ngIf="innerHtml && !filtersListService.filterMode" [innerHTML]="innerHtml" style="height: 100%;overflow: hidden;"></div> + <div *ngIf="innerHtml && !filtersListService.filterMode" [matTooltip]="currentChrono" [innerHTML]="innerHtml" style="height: 100%;overflow: hidden;"></div> <app-filters-list *ngIf="filtersListService.filterMode" [listProperties]="this.listProperties" (refreshEvent)="refreshDao()"></app-filters-list> + <mat-divider></mat-divider> </mat-sidenav> </mat-sidenav-container> diff --git a/src/frontend/app/list/basket-list.component.scss b/src/frontend/app/list/basket-list.component.scss index cae576406fda50a57f614c1dfeb17419806b8934..bb6c1288fd825b59936a0eb0224d8ad6e41b5351 100644 --- a/src/frontend/app/list/basket-list.component.scss +++ b/src/frontend/app/list/basket-list.component.scss @@ -2,6 +2,13 @@ overflow: hidden; } +mat-toolbar { + border: solid 1px #F9983066; + font-size: 10px; + height: 20px; + color: #666; +} + .resultContainer { // color : rgb(102, 102, 102); padding: 10px; diff --git a/src/frontend/app/list/basket-list.component.ts b/src/frontend/app/list/basket-list.component.ts index d53b74b796d6dafb0ffac2f5e1f92c9776b37a83..71f933e92e693fa39289092ff457c7ecbfa97d93 100755 --- a/src/frontend/app/list/basket-list.component.ts +++ b/src/frontend/app/list/basket-list.component.ts @@ -14,6 +14,7 @@ import { FiltersListService } from '../../service/filtersList.service'; import { NotesListComponent } from '../notes/notes.component'; import { AttachmentsListComponent } from '../attachments/attachments-list.component'; import { DiffusionsListComponent } from '../diffusions/diffusions-list.component'; +import { FiltersToolComponent } from './filters/filters-tool.component'; @@ -60,39 +61,39 @@ export class BasketListComponent implements OnInit { } ]; - displayedSecondaryData: any = []; - // displayedSecondaryData: any = [ - // { - // 'id' : 'priority_label', - // 'class' : '', - // 'icon' : '' - // }, - // { - // 'id' : 'category_id', - // 'class' : '', - // 'icon' : '' - // }, - // { - // 'id' : 'doctype_label', - // 'class' : '', - // 'icon' : 'fa fa-file' - // }, - // { - // 'id' : 'contact_society', - // 'class' : '', - // 'icon' : '' - // }, - // { - // 'id' : 'contact_society', - // 'class' : '', - // 'icon' : '' - // }, - // { - // 'id' : 'date', - // 'class' : 'rightData', - // 'icon' : '' - // }, - // ]; + //displayedSecondaryData: any = []; + displayedSecondaryData: any = [ + { + 'id' : 'priority_label', + 'class' : '', + 'icon' : '' + }, + { + 'id' : 'category_id', + 'class' : '', + 'icon' : '' + }, + { + 'id' : 'doctype_label', + 'class' : '', + 'icon' : 'fa fa-file' + }, + { + 'id' : 'contact_society', + 'class' : '', + 'icon' : '' + }, + { + 'id' : 'contact_society', + 'class' : '', + 'icon' : '' + }, + { + 'id' : 'date', + 'class' : 'rightData', + 'icon' : '' + }, + ]; resultListDatabase: ResultListHttpDao | null; data: any[] = []; @@ -100,6 +101,9 @@ export class BasketListComponent implements OnInit { isLoadingResults = true; listProperties: any = {}; currentBasketInfo: any = {}; + currentChrono: string = ''; + + @ViewChild('filtersTool') filtersTool: FiltersToolComponent; @ViewChild(MatPaginator) paginator: MatPaginator; @ViewChild('tableBasketListSort') sort: MatSort; @@ -186,6 +190,7 @@ export class BasketListComponent implements OnInit { this.sidenavRight.close(); } else { this.docUrl = this.coreUrl + 'rest/res/' + row.res_id + '/content'; + this.currentChrono = row.alt_identifier; this.innerHtml = this.sanitizer.bypassSecurityTrustHtml( "<iframe style='height:100%;width:100%;' src='" + this.docUrl + "' class='embed-responsive-item'>" + "</iframe>"); @@ -217,8 +222,13 @@ export class BasketListComponent implements OnInit { } refreshDao() { + this.paginator.pageIndex = this.listProperties.page; this.filtersChange.emit(); } + + filterThis(value: string) { + this.filtersTool.setInputSearch(value); + } } export interface BasketList { resources: any[]; diff --git a/src/frontend/app/list/filters/filters-list.component.html b/src/frontend/app/list/filters/filters-list.component.html index 3cb8eda04ad86bab069d00843533b14ab1653c4e..dd490bbe41946bd5069691f3a46db91da4a1e17a 100644 --- a/src/frontend/app/list/filters/filters-list.component.html +++ b/src/frontend/app/list/filters/filters-list.component.html @@ -1,5 +1,30 @@ <mat-nav-list disableRipple="true" class="filterList"> - <h3 mat-subheader>{{lang.filterBy}}</h3> + <h3 mat-subheader>{{lang.categories}}</h3> + <div class="row"> + <div class="col-md-4" *ngFor="let category of categories; let i=index"> + <mat-button-toggle class="filterListButton" [value]="category.id" [checked]="category.selected" (change)="setFilters($event, i, 'categories')">{{category.label}} + <span class="badge" style="min-width:auto;position: absolute;right: 1px;top: 1px;font-size: 9px;">??</span></mat-button-toggle> + </div> + </div> + <mat-divider></mat-divider> + <h3 mat-subheader>{{lang.prioritiesAlt}}</h3> + <div class="row"> + <div class="col-md-4" *ngFor="let priority of priorities; let i=index"> + <mat-button-toggle class="filterListButton" [value]="priority.id" [checked]="priority.selected" (change)="setFilters($event, i, 'priorities')">{{priority.label}} + <span class="badge" style="min-width:auto;position: absolute;right: 1px;top: 1px;font-size: 9px;">??</span></mat-button-toggle> + </div> + </div> + <mat-divider></mat-divider> + <h3 mat-subheader>{{lang.statuses}}</h3> + <div class="row"> + <div class="col-md-4" *ngFor="let status of statuses; let i=index"> + <mat-button-toggle title="{{status.label_status}}" class="filterListButton" [value]="status.id" [checked]="status.selected" (change)="setFilters($event, i, 'statuses')">{{status.label_status}} + <span class="badge" style="min-width:auto;position: absolute;right: 1px;top: 1px;font-size: 9px;">??</span></mat-button-toggle> + </div> + </div> + <h3 mat-subheader>{{lang.entities}}</h3> + <div>Coming soon...</div> + <!--<h3 mat-subheader>{{lang.filterBy}}</h3> <div *ngIf="loading" style="display:flex;height:100%;"> <mat-spinner style="margin:auto;"></mat-spinner> </div> @@ -102,5 +127,5 @@ </mat-list-option> </mat-selection-list> </mat-expansion-panel> - </ng-container> + </ng-container>--> </mat-nav-list> \ No newline at end of file diff --git a/src/frontend/app/list/filters/filters-list.component.scss b/src/frontend/app/list/filters/filters-list.component.scss index a399beeeed3b21ab60e9c26802aaf62de88dabe3..4b80f1ad97a034d9c0f11308eff0c46b314b2396 100644 --- a/src/frontend/app/list/filters/filters-list.component.scss +++ b/src/frontend/app/list/filters/filters-list.component.scss @@ -2,12 +2,21 @@ top : 10px !important; } -.mat-expansion-panel-header-title { +.filterList .mat-subheader { color: #F99830; font-size: 14px; font-weight: 500; } -.mat-pseudo-checkbox-checked { - background: #135f7f; +.filterList .mat-button-toggle-group { + max-width: 100%; + overflow: auto; +} +.mat-button-toggle-checked { + background-color: #F99830; + color: white; +} + +.filterListButton { + width: 100%; } \ No newline at end of file diff --git a/src/frontend/app/list/filters/filters-list.component.ts b/src/frontend/app/list/filters/filters-list.component.ts index 39b437aea83b088765871e00c06714fb7d2fedae..8bdf5b3608e791225152d8f7c4e915c0e32f2319 100644 --- a/src/frontend/app/list/filters/filters-list.component.ts +++ b/src/frontend/app/list/filters/filters-list.component.ts @@ -17,26 +17,15 @@ declare function $j(selector: any): any; export class FiltersListComponent implements OnInit { lang: any = LANG; - prioritiesList: any[] = []; - inPrioritiesProperty = false; - categoriesList: any[] = []; - inCategoriesProperty = false; + priorities: any[] = []; + categories: any[] = []; entitiesList: any[] = []; - inEntitiesProperty = false; - statusesList: any[] = []; - inStatusesProperty = false; + statuses: any[] = []; loading: boolean = false; @Input('listProperties') listProperties: any; - @ViewChild('categoriesPan') categoriesPan: MatExpansionPanel; - @ViewChild('prioritiesPan') prioritiesPan: MatExpansionPanel; - @ViewChild('entitiesPan') entitiesPan: MatExpansionPanel; - @ViewChild('subjectPan') subjectPan: MatExpansionPanel; - @ViewChild('referencePan') referencePan: MatExpansionPanel; - @ViewChild('statusesPan') statusesPan: MatExpansionPanel; - @Output('refreshEvent') refreshEvent = new EventEmitter<string>(); @@ -46,78 +35,73 @@ export class FiltersListComponent implements OnInit { this.loading = true; this.http.get("../../rest/priorities") .subscribe((data: any) => { - this.prioritiesList = data.priorities; - this.prioritiesList.forEach((element) => { + this.priorities = data.priorities; + this.priorities.forEach((element) => { element.selected = false; this.listProperties.priorities.forEach((listPropertyPrio: any) => { if (element.id === listPropertyPrio.id) { element.selected = true; - this.inPrioritiesProperty = true; } }); }); this.http.get("../../rest/categories") .subscribe((data: any) => { - this.categoriesList = data.categories; - this.categoriesList.forEach(element => { + this.categories = data.categories; + this.categories.forEach(element => { element.selected = false; this.listProperties.categories.forEach((listPropertyCat: any) => { if (element.id === listPropertyCat.id) { element.selected = true; - this.inCategoriesProperty = true; } }); }); this.http.get("../../rest/statuses") .subscribe((data: any) => { - this.statusesList = data.statuses; - this.statusesList.forEach(element => { + this.statuses = data.statuses; + this.statuses.forEach(element => { element.selected = false; this.listProperties.statuses.forEach((listPropertyStatus: any) => { if (element.id === listPropertyStatus.id) { element.selected = true; - this.inStatusesProperty = true; } }); }); this.loading = false; - - setTimeout(() => { - if (this.listProperties.reference.length > 0) { - this.referencePan.open(); - } - if (this.listProperties.subject.length > 0) { - this.subjectPan.open(); - } - if (this.inPrioritiesProperty) { - this.prioritiesPan.open(); - } - if (this.inCategoriesProperty) { - this.categoriesPan.open(); - } - if (this.inStatusesProperty) { - this.statusesPan.open(); - } - }, 200); }); }); }); } - setFilters(e: MatSelectionList, id: string) { + setFilters(e: any, i: number, id: string) { + this[id][i].selected = e.source.checked; this.listProperties[id] = []; - e.selectedOptions.selected.forEach(element => { + this[id].forEach((element: any) => { + if (element.selected === true) { + this.listProperties[id].push({ + 'id': element.id, + 'label': element.label + }); + } + + }); + this.updateFilters(); + } + + /*setFilters(e: any, elem: any, id: string) { + elem.selected = e.source.checked; + this.listProperties[id] = []; + elem.forEach(element => { this.listProperties[id].push({ 'id': element.value, 'label': element._text.nativeElement.innerText }); }); this.updateFilters(); - } + }*/ updateFilters() { this.listProperties.page = 0; diff --git a/src/frontend/app/list/filters/filters-tool.component.html b/src/frontend/app/list/filters/filters-tool.component.html index ca46c069d5530214c748142988d85d7886d0dc2e..2b35d0f25e956fd4040af9b2b2895000700fa0f0 100644 --- a/src/frontend/app/list/filters/filters-tool.component.html +++ b/src/frontend/app/list/filters/filters-tool.component.html @@ -1,7 +1,29 @@ -<mat-button-toggle-group #group="matButtonToggleGroup" class="envFilter" (change)="updateFiltersTool($event)" multiple> +<mat-button-toggle-group #group="matButtonToggleGroup" class="envFilter" multiple> <mat-checkbox color="primary" style="margin: 10px;" title="Sélectionner tous les courriers de la bannette"></mat-checkbox> - <button mat-stroked-button (click)="openFilter()">{{lang.filters}}</button> - <mat-button-toggle [checked]="this.listProperties.delayed" value="delayed" title="{{lang.displayProcessLimitRes}}"> + <form [formGroup]="stateForm"> + <mat-form-field appearance="outline" floatLabel="never" [style.fontSize.px]="10"> + <input class="metaSearch" type="text" matInput placeholder="Recherche un document" formControlName="stateGroup" + [matAutocomplete]="autoGroup" (focus)="initFilters()" (keyup.enter)="metaSearch($event);"> + <mat-autocomplete #autoGroup="matAutocomplete" (optionSelected)="selectFilter($event)" panelWidth="400"> + <mat-option *ngIf="isLoading" class="is-loading"> + <mat-spinner diameter="50"></mat-spinner> + </mat-option> + <ng-container *ngIf="!isLoading"> + <mat-optgroup *ngFor="let group of stateGroupOptions | async" [label]="group.letter"> + + <mat-option *ngFor="let name of group.names" [value]="name"> + <span [class.undefined]="name.label === '_UNDEFINED'" style="flex:1;overflow: hidden;text-overflow: ellipsis;">{{name.label}}</span> + <span> + <span bgcolor="warn" class="badge" style="min-width:auto;">{{name.count}}</span> + </span> + </mat-option> + </mat-optgroup> + </ng-container> + </mat-autocomplete> + </mat-form-field> + </form> + <mat-button-toggle [checked]="this.listProperties.delayed" value="delayed" title="{{lang.displayProcessLimitRes}}" + (change)="setFilters($event, 'delayed')"> <mat-icon fontSet="fas" fontIcon="fa-stopwatch fa-2x"></mat-icon> </mat-button-toggle> <mat-form-field appearance="outline" [style.fontSize.px]="10" style="width:200px !important;"> @@ -13,8 +35,8 @@ </mat-option> </mat-select> </mat-form-field> - <button [disabled]="this.listProperties.order == ''" mat-icon-button [title]="this.listProperties.orderDir == 'DESC' ? lang.descOrder : lang.ascOrder" style="color: rgba(0,0,0,0.38);" - (click)="changeOrderDir();"> + <button [disabled]="this.listProperties.order == ''" mat-icon-button [title]="this.listProperties.orderDir == 'DESC' ? lang.descOrder : lang.ascOrder" + style="color: rgba(0,0,0,0.38);" (click)="changeOrderDir();"> <mat-icon *ngIf="this.listProperties.orderDir == 'DESC'" fontSet="fas" fontIcon="fa-sort-amount-down fa-2x"></mat-icon> <mat-icon *ngIf="this.listProperties.orderDir == 'ASC'" fontSet="fas" fontIcon="fa-sort-amount-up fa-2x"></mat-icon> </button> @@ -37,14 +59,13 @@ </mat-menu> </mat-button-toggle-group> <div class="filterBadges"> - <span class="label label-info" title="{{lang.currentFilters}}" *ngFor="let category of this.listProperties.categories" - (click)="openFilter()">{{category.label}}</span> - <span class="label label-info" title="{{lang.currentFilters}}" *ngFor="let status of this.listProperties.statuses" - (click)="openFilter()">{{status.label}}</span> - <span class="label label-info" title="{{lang.currentFilters}}" (click)="openFilter()">{{this.listProperties.reference}}</span> - <span class="label label-info" title="{{lang.currentFilters}}" (click)="openFilter()">{{this.listProperties.subject}}</span> - <span class="label label-info" title="{{lang.currentFilters}}" *ngFor="let priority of this.listProperties.priorities" - (click)="openFilter()">{{priority.label}}</span> - <span class="label label-info" title="{{lang.currentFilters}}" *ngFor="let entity of this.listProperties.entities" - (click)="openFilter()">{{entity.label}}</span> + <span class="label badge-meta" *ngIf="this.listProperties.search !== ''" title="{{lang.currentFilters}}">{{this.listProperties.search}} + <i class="fa fa-times-circle" (click)="this.listProperties.search='';updateFilters();"></i></span> + <span class="label badge-cat" title="{{lang.currentFilters}}" *ngFor="let category of this.listProperties.categories; let i=index">{{category.label}} + <i class="fa fa-times-circle" (click)="removeFilter('categories', i)"></i></span> + <span class="label badge-prio" title="{{lang.currentFilters}}" *ngFor="let priority of this.listProperties.priorities; let i=index">{{priority.label}} + <i class="fa fa-times-circle" (click)="removeFilter('priorities', i)"></i></span> + <span class="label badge-stat" title="{{lang.currentFilters}}" *ngFor="let status of this.listProperties.statuses; let i=index">{{status.label}} + <i class="fa fa-times-circle" (click)="removeFilter('statuses', i)"></i></span> + <span class="label badge-ent" title="{{lang.currentFilters}}" *ngFor="let entity of this.listProperties.entities; let i=index">{{entity.label}} <i class="fa fa-times-circle" (click)="removeFilter('entities', i)"></i></span> </div> \ No newline at end of file diff --git a/src/frontend/app/list/filters/filters-tool.component.scss b/src/frontend/app/list/filters/filters-tool.component.scss index 09bfbd8e5c8b3ecf1da8c6d7f51ee86c35e7274d..e8a241a69f201e85c62321105da46298bb1cd57d 100644 --- a/src/frontend/app/list/filters/filters-tool.component.scss +++ b/src/frontend/app/list/filters/filters-tool.component.scss @@ -1,9 +1,3 @@ -mat-toolbar { - border: solid 1px #F9983066; - font-size: 10px; - height: 20px; - color: #666; -} .envFilter { height: 40px; @@ -16,8 +10,65 @@ mat-toolbar { color: white; } } -.filterBadges>.label { +.filterBadges>.badge-meta { margin: 5px; - background: #F99830; + background: #666; cursor: pointer; +} + +.filterBadges>.badge-cat { + margin: 5px; + background: #78AD32; + cursor: pointer; +} + +.filterBadges>.badge-stat { + margin: 5px; + background: #5bc0de; + cursor: pointer; +} + +.filterBadges>.badge-prio { + margin: 5px; + background: #F9D812; + cursor: pointer; +} + +.filterBadges>.badge-ent { + margin: 5px; + background: #7d5ba6; + cursor: pointer; +} + + +.filterContent { + height: auto; +} + +.filterContent:hover { + background: inherit !important; +} + +.mat-option .badge{ + background: #F99830; + font-size: 11px; +} + +.mat-option-text { + display: flex !important; + overflow: inherit !important; +} + +.mat-autocomplete-panel { + min-width: 400px !important; +} + +.mat-optgroup-label { + color: #F99830; + font-size: 14px; + font-weight: 500; +} +.undefined { + opacity: 0.5; + font-style: italic; } \ No newline at end of file diff --git a/src/frontend/app/list/filters/filters-tool.component.ts b/src/frontend/app/list/filters/filters-tool.component.ts index 60d0541878adbdcde36cdabcd589e0042ceea282..d020394c47d934f9ef5815814a64980b34c9e24d 100644 --- a/src/frontend/app/list/filters/filters-tool.component.ts +++ b/src/frontend/app/list/filters/filters-tool.component.ts @@ -1,11 +1,25 @@ -import { Component, OnInit, ViewEncapsulation, Input, EventEmitter, Output } from '@angular/core'; +import { Component, OnInit, ViewEncapsulation, Input, EventEmitter, Output, ViewChild } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { LANG } from '../../translate.component'; -import { MatSidenav } from '@angular/material'; +import { MatSidenav, MatMenu, MatMenuTrigger, MatAutocompleteSelectedEvent, MatInput, MatAutocompleteTrigger } from '@angular/material'; import { FiltersListService } from '../../../service/filtersList.service'; +import { Observable } from 'rxjs'; +import { FormBuilder, FormGroup } from '@angular/forms'; +import { startWith, map } from 'rxjs/operators'; declare function $j(selector: any): any; +export interface StateGroup { + letter: string; + names: any[]; +} + +export const _filter = (opt: string[], value: string): string[] => { + + const filterValue = value.toLowerCase(); + + return opt.filter(item => item['label'].toLowerCase().indexOf(filterValue) != -1); +}; @Component({ selector: 'app-filters-tool', templateUrl: 'filters-tool.component.html', @@ -16,6 +30,10 @@ export class FiltersToolComponent implements OnInit { lang: any = LANG; + stateForm: FormGroup = this.fb.group({ + stateGroup: '', + }); + displayColsOrder = [ { 'id': 'dest_user' }, { 'id': 'creation_date' }, @@ -26,19 +44,43 @@ export class FiltersToolComponent implements OnInit { { 'id': 'priority' }, { 'id': 'status' }, { 'id': 'type_id' } - ] + ]; + + @ViewChild(MatAutocompleteTrigger) autocomplete: MatAutocompleteTrigger; + + priorities: any[] = []; + categories: any[] = []; + entitiesList: any[] = []; + statuses: any[] = []; + + stateGroups: StateGroup[] = []; + stateGroupOptions: Observable<StateGroup[]>; + + isLoading: boolean = false; @Input('listProperties') listProperties: any; + @Input('currentBasketInfo') currentBasketInfo: any; + @Input('snavR') sidenavRight: MatSidenav; - + @Output('refreshEvent') refreshEvent = new EventEmitter<string>(); - constructor(public http: HttpClient, private filtersListService: FiltersListService) { } + constructor(public http: HttpClient, private filtersListService: FiltersListService, private fb: FormBuilder) { } ngOnInit(): void { } + private _filterGroup(value: string): StateGroup[] { + if (value) { + return this.stateGroups + .map(group => ({ letter: group.letter, names: _filter(group.names, value) })) + .filter(group => group.names.length > 0); + } + + return this.stateGroups; + } + changeOrderDir() { if (this.listProperties.orderDir == 'ASC') { this.listProperties.orderDir = 'DESC'; @@ -56,21 +98,126 @@ export class FiltersToolComponent implements OnInit { this.refreshEvent.emit(); } - updateFiltersTool(e: any) { - this.listProperties.delayed = false; - this.listProperties.page = 0; + setFilters(e: any, id: string) { + this.listProperties[id] = e.source.checked; + this.updateFilters(); + } + - e.value.forEach((element: any) => { - this.listProperties[element] = true; + selectFilter(e: MatAutocompleteSelectedEvent) { + this.listProperties[e.option.value.id].push({ + 'id': e.option.value.value, + 'label': e.option.value.label }); - this.filtersListService.updateListsProperties(this.listProperties); + $j('.metaSearch').blur(); + this.stateForm.controls['stateGroup'].reset(); + this.updateFilters(); + } - this.refreshEvent.emit(); + metaSearch(e: any) { + this.listProperties.search = e.target.value; + $j('.metaSearch').blur(); + this.stateForm.controls['stateGroup'].reset(); + this.autocomplete.closePanel(); + this.updateFilters(); + } + + removeFilter(id: string, i: number) { + this.listProperties[id].splice(i, 1); + this.updateFilters(); + } + + setInputSearch(value: string) { + $j('.metaSearch').focus(); + setTimeout(() => { + this.stateForm.controls['stateGroup'].setValue(value); + }, 200); } - openFilter() { - this.filtersListService.filterMode = true; - this.sidenavRight.open(); + initFilters() { + this.isLoading = true; + + this.stateForm.controls['stateGroup'].reset(); + this.stateGroups = [ + { + letter: this.lang.categories, + names: [] + }, + { + letter: this.lang.priorities, + names: [] + }, + { + letter: this.lang.statuses, + names: [] + }, + { + letter: this.lang.entities, + names: [] + }, + ]; + + this.http.get('../../rest/resourcesList/users/' + this.currentBasketInfo.ownerId + '/groups/' + this.currentBasketInfo.groupId + '/baskets/' + this.currentBasketInfo.basketId + '/filters') + .subscribe((data: any) => { + data.categories.forEach((element: any) => { + if (this.listProperties.categories.map((category: any) => (category.id)).indexOf(element.id) === -1) { + this.stateGroups[0].names.push( + { + id: 'categories', + value: element.id, + label: (element.label !== null ? element.label : '_UNDEFINED'), + count: element.count + } + ) + } + }); + data.priorities.forEach((element: any) => { + if (this.listProperties.priorities.map((priority: any) => (priority.id)).indexOf(element.id) === -1) { + this.stateGroups[1].names.push( + { + id: 'priorities', + value: element.id, + label: (element.label !== null ? element.label : '_UNDEFINED'), + count: element.count + } + ) + } + }); + data.statuses.forEach((element: any) => { + if (this.listProperties.statuses.map((status: any) => (status.id)).indexOf(element.id) === -1) { + this.stateGroups[2].names.push( + { + id: 'statuses', + value: element.id, + label: (element.label !== null ? element.label : '_UNDEFINED') , + count: element.count + } + ) + } + + }); + + data.entities.forEach((element: any) => { + if (this.listProperties.entities.map((entity: any) => (entity.id)).indexOf(element.id) === -1) { + this.stateGroups[3].names.push( + { + id: 'entities', + value: element.entityId, + label: (element.label !== null ? element.label : '_UNDEFINED') , + count: element.count + } + ) + } + + }); + this.isLoading = false; + }); + + this.stateGroupOptions = this.stateForm.get('stateGroup')!.valueChanges + .pipe( + startWith(''), + map(value => this._filterGroup(value)) + ); } } \ No newline at end of file diff --git a/src/frontend/plugins/timeLimit.pipe.ts b/src/frontend/plugins/timeLimit.pipe.ts index 85f68c985f60c4cf7bcbf2bbcf93c64c3d91a975..5d8d4f488721a95c1f59c383e18ad5168bbfa16d 100755 --- a/src/frontend/plugins/timeLimit.pipe.ts +++ b/src/frontend/plugins/timeLimit.pipe.ts @@ -46,12 +46,12 @@ export class TimeLimitPipe implements PipeTransform, OnDestroy { let months = Math.round(Math.abs(days/30.416)); let years = Math.round(Math.abs(days/365)); if(now > d) { - return '<span class="timeDanger" color="warn">' + this.lang.outdated + ' !</span>'; + return '<span class="timeDanger" color="warn"><b>' + this.lang.outdated + ' !</b></span>'; } else { if (Number.isNaN(seconds)){ return ''; } else if (days <= 3) { - return '<span color="warn">'+ days + ' ' + this.lang.dayS +'</span>'; + return '<span color="warn"><b>'+ days + ' ' + this.lang.dayS +'</b></span>'; } else if (days <= 7) { return '<span class="timeWarn">'+ days + ' ' + this.lang.dayS +'</span>'; } else if (days <= 345) { diff --git a/src/frontend/service/filtersList.service.ts b/src/frontend/service/filtersList.service.ts index 08ec3e65c924cbacb4b5e90d449df911fd4d7776..c53b4b1b9f1a80b4a9953beeb356e9d6e62027cb 100644 --- a/src/frontend/service/filtersList.service.ts +++ b/src/frontend/service/filtersList.service.ts @@ -7,8 +7,7 @@ interface listProperties { 'page' : string, 'order' : string, 'orderDir' : string, - 'reference' : string, - 'subject' : string, + 'search' : string, 'delayed': boolean, 'categories' : string[], 'priorities' : string[], @@ -51,8 +50,7 @@ export class FiltersListService { 'page' : '0', 'order' : '', 'orderDir' : 'DESC', - 'reference' : '', - 'subject' : '', + 'search' : '', 'delayed': false, 'categories' : [], 'priorities' : [], @@ -87,11 +85,8 @@ export class FiltersListService { if (this.listsProperties[this.listsPropertiesIndex].order.length > 0) { filters += '&order='+this.listsProperties[this.listsPropertiesIndex].order + ' ' + this.listsProperties[this.listsPropertiesIndex].orderDir; } - if (this.listsProperties[this.listsPropertiesIndex].reference.length > 0) { - filters += '&reference='+this.listsProperties[this.listsPropertiesIndex].reference; - } - if (this.listsProperties[this.listsPropertiesIndex].subject.length > 0) { - filters += '&subject='+this.listsProperties[this.listsPropertiesIndex].subject; + if (this.listsProperties[this.listsPropertiesIndex].search.length > 0) { + filters += '&search='+this.listsProperties[this.listsPropertiesIndex].search; } if (this.listsProperties[this.listsPropertiesIndex].categories.length > 0) { let cat: any[] = []; @@ -117,6 +112,15 @@ export class FiltersListService { filters += '&statuses='+status.join(','); } + + if (this.listsProperties[this.listsPropertiesIndex].entities.length > 0) { + let ent: any[] = []; + this.listsProperties[this.listsPropertiesIndex].entities.forEach((element: any) => { + ent.push(element.id); + }); + + filters += '&entities='+ent.join(','); + } return filters; }