[angular-16-irish-monitor | DONE | ADDED]: New type of filter (triplet) added - use of <mat-button-toggle-group> | Grouping of filters added | Fixed checks for dependent filters and added new checks for dependent to filter values.

1. newSearchPage.component.html: Added display of grouped filters | Added checks for triplet typed filters.
2. newSearchPage.component.ts: Fixed checks for dependent filters and added new checks for dependent to filter values.
3. searchFilter.component.html: New "triplet" type of filter | Grouping of filters - smaller titles.
4. searchFilter.component.ts: Added field "@Input() grouped: boolean = false" | Added check for triplet filter | Added method "tripletFilterChange()".
5. searchFilter.module.ts: Import MatButtonToggleModule.
6. searchResearchResults.component.ts: Fixed how groupedFilters are initialized - TODO: Add this fix in other search pages too.
This commit is contained in:
Konstantina Galouni 2023-12-21 10:57:14 +02:00
parent 0870766720
commit 59bd3918e8
6 changed files with 255 additions and 32 deletions

View File

@ -318,7 +318,14 @@ export class SearchResearchResultsComponent {
}
if (refine) {
this.filters = this.searchPage.prepareFiltersToShow(filters, totalResults);
let refineFilters = this.searchPage.prepareFiltersToShow(filters, totalResults);
// for(let filter of refineFilters) {
// let index = this.filters.findIndex(oldFilter => oldFilter.filterId == filter.filterId);
// if(index != -1 && this.filters[index].isOpen) {
// filter.isOpen = true;
// }
// }
this.filters = refineFilters;
this.rangeFilters = this.searchPage.prepareRangeFiltersToShow();
this.staticFilters = this.searchPage.prepareStaticFiltersToShow();
@ -328,9 +335,14 @@ export class SearchResearchResultsComponent {
if (group.type == "refine") {
let groupedFilters = {title: group.title, values: []};
for (let field of group.values) {
let index = this.filters.findIndex(filter => filter.filterId == field);
let index = this.staticFilters.findIndex(filter => filter.filterId == field);
if (index > -1) {
groupedFilters.values.push(this.filters[index]);
groupedFilters.values.push(this.staticFilters[index]);
} else {
index = this.filters.findIndex(filter => filter.filterId == field);
if (index > -1) {
groupedFilters.values.push(this.filters[index]);
}
}
}
if (groupedFilters.values.length > 0) {

View File

@ -49,9 +49,13 @@
<span class="uk-label uk-label-primary uk-flex uk-flex-middle">
<span
class="uk-margin-small-right uk-width-expand uk-text-truncate">
<span *ngIf="filter.type && filter.type == 'boolean' else noboolean">{{filter.title}}:
{{value.name=='true'?'Yes':'No'}}
</span>
<ng-container *ngIf="filter.type && (filter.type == 'boolean' || filter.type == 'triplet') else noboolean">
<!-- *ngIf="filter.type == 'boolean'"-->
<span>{{filter.title}}:
{{(value.name=='true'||value.name=='Yes')?'Yes':'No'}}
</span>
<!-- <span *ngIf="filter.type == 'triplet'">{{value.name=='true'?'':'Not '}}{{filter.title}}</span>-->
</ng-container>
<ng-template #noboolean>
{{value.name}}
</ng-template></span>
@ -70,10 +74,12 @@
class="">
<span class="uk-label uk-label-primary uk-flex uk-flex-middle">
<span
class="uk-margin-small-right uk-width-expand uk-text-truncate">
<span *ngIf="filter.type && filter.type == 'boolean' else noboolean">{{filter.title}}:
{{value.name=='true'?'Yes':'No'}}
</span>
class="uk-margin-small-right uk-width-expand uk-text-truncate">
<ng-container *ngIf="filter.type && (filter.type == 'boolean' || filter.type == 'triplet') else noboolean">
<span>{{filter.title}}:
{{(value.name=='true'||value.name=='Yes')?'Yes':'No'}}
</span>
</ng-container>
<ng-template #noboolean>
{{value.name}}
</ng-template></span>
@ -94,13 +100,13 @@
</h1>
</ng-template>
<ng-template #search_filter let-filter="filter" let-showResultCount="showResultCount">
<ng-template #search_filter let-filter="filter" let-showResultCount="showResultCount" let-grouped="grouped">
<search-filter [filterValuesNum]="filterValuesNum" [showMoreInline]="showMoreFilterValuesInline"
[isDisabled]="disabled"
[filter]="filter" [showResultCount]=showResultCount
(onFilterChange)="filterChanged($event)"
(onFilterToggle)="filterToggled($event)"
[actionRoute]="true"></search-filter>
[actionRoute]="true" [grouped]="grouped"></search-filter>
</ng-template>
<ng-template #filters_column>
@ -125,15 +131,15 @@
<ul *ngIf="!showUnknownFilters" class="uk-list uk-list-xlarge">
<ng-container *ngIf="orderedFilters && orderedFilters.length > 0">
<ng-container *ngFor="let group of orderedFilters">
<h5 *ngIf="group.title" class="uk-h5">{{group.title}}</h5>
<ng-container *ngFor="let filter of group.values">
<h6 *ngIf="group.title" class="uk-h6">{{group.title}}</h6>
<ng-container *ngFor="let filter of group.values; let i=index">
<li *ngIf="filter.originalFilterIdFrom && filter.originalFilterIdTo; else refineBlock">
<range-filter [isDisabled]="disabled" [filter]="filter"
(onFilterChange)="filterChanged($event)" [actionRoute]="true"></range-filter>
</li>
<ng-template #refineBlock>
<li *ngIf="filter.values && filter.values.length > 0">
<ng-container *ngTemplateOutlet="search_filter; context: {filter: filter, showResultCount: filter.type!='static'}"></ng-container>
<li *ngIf="filter.values && filter.values.length > 0" [ngClass]="group.title && i==0 ? 'uk-margin-small-top' : ''">
<ng-container *ngTemplateOutlet="search_filter; context: {filter: filter, showResultCount: filter.type!='static', grouped: !!group.title}"></ng-container>
</li>
</ng-template>
</ng-container>

View File

@ -425,13 +425,19 @@ export class NewSearchPageComponent implements OnInit, OnDestroy, OnChanges {
/*
* Get A sub-array of this.refineFields array, which contains the ids of the selected filters
*/
public getSelectedFilters(): string[] {
var selected: string[] = [];
public getSelectedFilters(): Map<string, string[]> {
var selected: Map<string, string[]> = new Map<string, string[]>();
var filters = this.URLCreatedFilters;
for (var i = 0; i < filters.length; i++) {
var filter: Filter = filters[i];
if (filter.countSelectedValues > 0) {
selected.push(filter.filterId);
let selectedValues: string[] = [];
for(let value of filter.values) {
if(value.selected) {
selectedValues.push(value.id);
}
}
selected.set(filter.filterId, selectedValues);
}
}
return selected;
@ -440,31 +446,96 @@ export class NewSearchPageComponent implements OnInit, OnDestroy, OnChanges {
/*
* Get A sub-array of this.refineFields array, which contains the ids of the selected parameters
*/
private getSelectedParameters(): string[] {
var selected: string[] = [];
private getSelectedParameters(): Map<string, string[]> {
var selected: Map<string, string[]> = new Map<string, string[]>();
for (var i = 0; i < this.refineFields.length; i++) {
if (this.parameterNames.indexOf(this.refineFields[i]) != -1) {
selected.push(this.refineFields[i]);
let selectedValues: string[] = [];
let index = this.parameterNames.indexOf(this.refineFields[i]);
if (index != -1) {
for(let values of this.parameterValues[index]) {
let split = values.split('"');
for(let value of split) {
if(value != "" && value != ",") {
selectedValues.push(value);
}
}
}
selected.set(this.refineFields[i], selectedValues);
}
}
return selected;
}
/*
* Get A sub-array of this.staticFields array, which contains the ids of the selected filters
*/
public getSelectedStaticFilters(): Map<string, string[]> {
var selected: Map<string, string[]> = new Map<string, string[]>();
var filters = this.URLCreatedStaticFilters;
for (var i = 0; i < filters.length; i++) {
var filter: Filter = filters[i];
if (filter.countSelectedValues > 0) {
let selectedValues: string[] = [];
for(let value of filter.values) {
if(value.selected) {
selectedValues.push(value.id);
}
}
selected.set(filter.filterId, selectedValues);
}
}
return selected;
}
/*
* Get A sub-array of this.staticFields array, which contains the ids of the selected parameters
*/
private getSelectedStaticParameters(): Map<string, string[]> {
var selected: Map<string, string[]> = new Map<string, string[]>();
for (var i = 0; i < this.staticFields.length; i++) {
let selectedValues: string[] = [];
let index = this.parameterNames.indexOf(this.staticFields[i]);
if (index != -1) {
let split = this.parameterValues[index].split('"');
for(let value of split) {
if(value != "" && value != ",") {
selectedValues.push(value);
}
}
selected.set(this.staticFields[i], selectedValues);
}
}
return selected;
}
/*
* Get A sub-array of this.refineFields array, which hides hidden fields (e.g Funding level 0,1,2,..), and contains those that depend on another fields (e.g Funding level 0 if Funder is selected )
*/
public getFields(): string[] {
var selected_filters: string[] = this.getSelectedFilters();
if (selected_filters.length == 0) {
var selected_filters: Map<string, string[]> = this.getSelectedFilters();
if (selected_filters.size == 0) {
selected_filters = this.getSelectedParameters();
}
var selected_static_filters: Map<string, string[]> = this.getSelectedStaticFilters();
if (selected_static_filters.size == 0) {
selected_static_filters = this.getSelectedStaticParameters();
}
let all_selected_filters = new Map([...selected_filters, ...selected_static_filters]);
// let all_selected_filters = selected_filters.concat(selected_static_filters);
var fields: string[] = [];
for (var i = 0; i < this.refineFields.length; i++) {
var dependentTo = this.searchFieldsHelper.DEPENDENT_FIELDS[this.refineFields[i]];
var dependentToValues = this.searchFieldsHelper.DEPENDENT_FIELDS_AND_VALUES[this.refineFields[i]];
// TODO check again the checks
//if filter is not marked as hidden OR it is hidden but it is dependent to a field that it IS selected
if (this.searchFieldsHelper.HIDDEN_FIELDS.indexOf(this.refineFields[i]) == -1
|| (selected_filters.indexOf(dependentTo) != -1) || (selected_filters.indexOf(this.refineFields[i]) != -1)
|| (all_selected_filters.has(this.refineFields[i]))
|| (!dependentTo && !dependentToValues)
|| (all_selected_filters.has(dependentTo))
|| (dependentToValues && (all_selected_filters.has(dependentToValues.field) && dependentToValues.values.some(dependentValue=> all_selected_filters.get(dependentToValues.field).includes(dependentValue))))
|| (this.resultTypes && this.resultTypes.filterId == dependentTo && this.resultTypes.countSelectedValues > 0)
// || (this.resultAccesses && this.resultAccesses.filterId == dependentTo && this.resultAccesses.countSelectedValues > 0)
) {
@ -1762,7 +1833,38 @@ export class NewSearchPageComponent implements OnInit, OnDestroy, OnChanges {
}
public prepareStaticFiltersToShow() {
this.staticFilters = RefineResultsUtils.parse(this.staticFieldValues, this.staticFields, this.entityType, "search", true);
var selected_filters: Map<string, string[]> = this.getSelectedFilters();
if (selected_filters.size == 0) {
selected_filters = this.getSelectedParameters();
}
var selected_static_filters: Map<string, string[]> = this.getSelectedStaticFilters();
if (selected_static_filters.size == 0) {
selected_static_filters = this.getSelectedStaticParameters();
}
let all_selected_filters = new Map([...selected_filters, ...selected_static_filters]);
// let all_selected_filters = selected_filters.concat(selected_static_filters);
let staticFields: string[] = [];
for (var i = 0; i < this.staticFields.length; i++) {
var dependentTo = this.searchFieldsHelper.DEPENDENT_FIELDS[this.staticFields[i]];
var dependentToValues = this.searchFieldsHelper.DEPENDENT_FIELDS_AND_VALUES[this.staticFields[i]];
// TODO check again the checks
//if filter is not marked as hidden OR it is hidden but it is dependent to a field that it IS selected
if (this.searchFieldsHelper.HIDDEN_FIELDS.indexOf(this.staticFields[i]) == -1
|| (all_selected_filters.has(this.staticFields[i]))
|| (!dependentTo && !dependentToValues)
|| (all_selected_filters.has(dependentTo))
|| (dependentToValues && (all_selected_filters.has(dependentToValues.field) && dependentToValues.values.some(dependentValue=> all_selected_filters.get(dependentToValues.field).includes(dependentValue))))
) {
staticFields.push(this.staticFields[i]);
}
}
this.staticFilters = RefineResultsUtils.parse(this.staticFieldValues, staticFields, this.entityType, "search", true);
this.checkSelectedStaticFilters(this.staticFilters);
this.countSelectedStaticFilters(this.staticFilters);
this.cdr.detectChanges();

View File

@ -1,9 +1,35 @@
<div *ngIf="filter.values.length >0">
<div class="uk-flex uk-flex-middle uk-margin-bottom">
<div *ngIf="!grouped else groupedTitle" class="uk-flex uk-flex-middle uk-margin-bottom">
<h6 [title]="filter.title" class="uk-margin-remove-bottom">{{_formatTitle(filter.title, filter.values.length)}}</h6>
<a *ngIf="filter.countSelectedValues>0" class="uk-text-small uk-margin-left" (click)="clearFilter()" [class.uk-disabled]="isDisabled">Clear</a>
</div>
<div>
<ng-template #groupedTitle>
<div class="uk-flex uk-flex-middle uk-margin-small-bottom">
<div [title]="filter.title" class="uk-margin-remove-bottom uk-text-meta">{{_formatTitle(filter.title, filter.values.length)}}</div>
<a *ngIf="filter.countSelectedValues>0" class="uk-text-small uk-margin-left" (click)="clearFilter()" [class.uk-disabled]="isDisabled">Clear</a>
</div>
</ng-template>
<div *ngIf="filter.type && filter.type == 'triplet'">
<span>
<mat-button-toggle-group [name]="filter.title" [aria-label]="filter.title" class="uk-text-xsmall"
[(ngModel)]="filter.radioValue" (ngModelChange)="tripletFilterChange()" [disabled]="isDisabled">
<mat-button-toggle *ngFor="let value of filter.values" [value]="value.id" class="filter-button-toggle">
<div style="width: 50px">{{value.name}}</div>
</mat-button-toggle>
<!-- <ng-container *ngFor="let value of filter.values">-->
<!-- <mat-button-toggle value="true">-->
<!-- {{filter.title}}-->
<!-- </mat-button-toggle>-->
<!-- <mat-button-toggle value="false">-->
<!-- Not {{filter.title}}-->
<!-- </mat-button-toggle>-->
<!-- </ng-container>-->
</mat-button-toggle-group>
</span>
</div>
<div *ngIf="!filter.type || filter.type != 'triplet'">
<div *ngFor="let value of getSelectedAndTopValues(filter, filterValuesNum)"
class="uk-animation-fade uk-text-small uk-margin-small-bottom">
<div [title]="value.name">
@ -49,6 +75,67 @@
</div>
</div>
</div>
<!--<ul *ngIf="filter.values.length >0" class="uk-accordion">-->
<!-- <li (click)="filter.isOpen = !filter.isOpen" [class]="filter.isOpen ? 'uk-open' : ''">-->
<!-- <a class="uk-accordion-title">-->
<!-- {{filter.isOpen}}-->
<!-- <span>{{_formatTitle(filter.title, filter.values.length)}}</span>-->
<!-- <span *ngIf="filter.countSelectedValues>0" class="uk-margin-left">{{filter.countSelectedValues}}</span>-->
<!-- </a>-->
<!-- <div *ngIf="filter.isOpen" class="uk-accordion-content">-->
<!-- <div *ngFor="let value of getSelectedAndTopValues(filter, filterValuesNum)"-->
<!-- class="uk-animation-fade uk-text-small uk-margin-small-bottom">-->
<!-- <div [title]="value.name">-->
<!-- <ng-container *ngTemplateOutlet="input_label_wrapper; context: {filter: filter, value: value}"></ng-container>-->
<!-- </div>-->
<!-- </div>-->
<!-- <div *ngIf="addShowMore && hasMoreValues">-->
<!-- <a *ngIf="filterValuesNum > 0 " class="uk-text-small view-more-less-link uk-margin-small-top" [ngClass]="((isDisabled)?'uk-disabled uk-link-muted ':'')" (click)="toggle($event)">-->
<!-- <span *ngIf="!filter.isViewAllOpen">View all</span>-->
<!-- <span *ngIf="filter.isViewAllOpen">View less </span>-->
<!-- </a>-->
<!-- <div *ngIf="filter.isViewAllOpen" class="uk-text-small uk-margin-small-top uk-margin-small-bottom">-->
<!-- <div *ngIf="filter.countAllValues == -1">-->
<!-- <loading class="uk-height-small uk-display-block" size="medium"></loading>-->
<!-- </div>-->
<!-- <div *ngIf="filter.countAllValues == 0">-->
<!-- <span class="uk-text-warning">An error occured. </span><span><a class="uk-button-link" (click)="toggleWithoutUpdate()">Please try again</a>.</span>-->
<!-- </div>-->
<!-- <ng-container *ngIf="(!filter.countAllValues && filter.countAllValues != 0) || filter.countAllValues > 0">-->
<!-- <div class="uk-margin-small-left">-->
<!-- <div class="uk-text-meta">Top 100 values are shown in the filters</div>-->
<!-- <div class="uk-flex uk-flex-bottom uk-margin-top">-->
<!-- <div input class="uk-width-1-2@m uk-margin-right" [placeholder]="{label: 'Search', static: true}" inputClass="inner small" [(value)]="keyword" (valueChange)="initMatching()"></div>-->
<!-- <div *ngIf="showResultCount === true" input type="select" class="uk-width-expand" placeholder="Sort by"-->
<!-- inputClass="border-bottom" [(value)]="sortBy" [options]="sortByOptions" (valueChange)="sort()"></div>-->
<!-- </div>-->
<!-- </div>-->
<!-- <div class="uk-overflow-auto uk-height-max-small uk-margin-small-left uk-margin-small-right uk-margin-top">-->
<!-- <ng-container *ngFor="let value of this.sortedValues">-->
<!-- <div *ngIf="filterKeywords(value.name)" title="{{value.name}}"-->
<!-- class="uk-animation-fade uk-text-small">-->
<!-- <ng-container *ngTemplateOutlet="input_label_wrapper; context: {filter: filter, value: value}"></ng-container>-->
<!-- </div>-->
<!-- </ng-container>-->
<!-- <ng-container *ngIf="!hasMatch">-->
<!-- <div class="uk-padding-small uk-text-meta">-->
<!-- No filters available with that term-->
<!-- </div>-->
<!-- </ng-container>-->
<!-- </div>-->
<!-- </ng-container>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<!-- </li>-->
<!--</ul>-->
<ng-template #input_label let-filter="filter" let-value="value">
<span *ngIf="filter.filterType == 'checkbox' || filter.filterType == 'radio'" class="uk-flex uk-flex-middle"
[class.uk-disabled]="isDisabled || (showResultCount && value.number === 0)">

View File

@ -46,6 +46,7 @@ export class SearchFilterComponent implements OnInit, OnChanges {
// @Input() isViewAllOpen: boolean = false;
sortedValues;
hasMatch: boolean = false;
@Input() grouped: boolean = false;
constructor(private _router: Router,
private route: ActivatedRoute,
@ -88,7 +89,7 @@ export class SearchFilterComponent implements OnInit, OnChanges {
// this.filter.values = this.filter.values.filter(value => !value.name.toLowerCase().includes('unknown') && !value.name.toLowerCase().includes('not available'));
this.filter.values = this.filter.values.filter(value => value && value.name != "unidentified" && value.name != "Undetermined" && !value.name.toLowerCase().includes('unknown') && !value.name.toLowerCase().includes('not available'));
if (this.filter.filterType == "radio") {
if (this.filter.filterType == "radio" || this.filter.filterType == "triplet") {
this.filter.radioValue = "";
this.filter.values.forEach(value => {
if (value.selected) {
@ -162,6 +163,20 @@ export class SearchFilterComponent implements OnInit, OnChanges {
value: this.filter
});
}
tripletFilterChange() {
if(this.filter.radioValue == "") {
this.clearFilter();
} else {
this.filter.countSelectedValues = 1;
this.filter.values.forEach(value => {
value.selected = (value.id == this.filter.radioValue);
});
this.onFilterChange.emit({
value: this.filter
});
}
}
clearFilter() {
for (var i = 0; i < this.filter.values.length; i++) {

View File

@ -9,11 +9,12 @@ import {RouterModule} from "@angular/router";
import {InputModule} from '../../sharedComponents/input/input.module';
import {IconsModule} from "../../utils/icons/icons.module";
import {LoadingModule} from "../../utils/loading/loading.module";
import {MatButtonToggleModule} from "@angular/material/button-toggle";
@NgModule({
imports: [
CommonModule, FormsModule, ModalModule, RouterModule,
InputModule, IconsModule, LoadingModule
InputModule, IconsModule, LoadingModule, MatButtonToggleModule
],
declarations: [
SearchFilterComponent, SearchFilterModalComponent