Merge pull request #4121 from arvoConsultores/DS-4097

Store the state of the computed filters
This commit is contained in:
Tim Donohue
2025-04-11 11:28:51 -05:00
committed by GitHub
2 changed files with 138 additions and 19 deletions

View File

@@ -1,13 +1,13 @@
<h3>{{"search.filters.head" | translate}}</h3>
<div *ngIf="(filters | async)?.hasSucceeded">
<div [class.visually-hidden]="filtersWithComputedVisibility !== (filters | async)?.payload?.length"
*ngFor="let filter of (filters | async)?.payload; trackBy: trackUpdate">
<div [class.visually-hidden]="getFinalFiltersComputed(this.currentConfiguration) !== (filters | async)?.payload?.length"
*ngFor="let filter of (filters | async)?.payload">
<ds-search-filter (isVisibilityComputed)="countFiltersWithComputedVisibility($event)" [scope]="currentScope" [filter]="filter" [inPlaceSearch]="inPlaceSearch" [refreshFilters]="refreshFilters"></ds-search-filter>
</div>
</div>
<ng-container *ngIf="filtersWithComputedVisibility !== (filters | async)?.payload?.length">
<ng-container *ngIf="getFinalFiltersComputed(this.currentConfiguration) !== (filters | async)?.payload?.length">
<ngx-skeleton-loader [count]="defaultFilterCount"/>
</ng-container>
<a class="btn btn-primary" [routerLink]="[searchLink]" [queryParams]="clearParams | async" queryParamsHandling="merge" role="button"><i class="fas fa-undo"></i> {{"search.filters.reset" | translate}}</a>

View File

@@ -2,7 +2,7 @@ import { Component, Inject, Input, OnDestroy, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { BehaviorSubject, Observable } from 'rxjs';
import { map, tap } from 'rxjs/operators';
import { map, filter, take } from 'rxjs/operators';
import { SearchService } from '../../../core/shared/search/search.service';
import { RemoteData } from '../../../core/data/remote-data';
@@ -62,9 +62,16 @@ export class SearchFiltersComponent implements OnInit, OnDestroy {
searchLink: string;
/**
* Filters for which visibility has been computed
* Keeps track of the filters computed for each configuration during the current rendering cycle
* This array stores objects with configuration identifier and number of computed filters
*/
filtersWithComputedVisibility = 0;
private currentFiltersComputed = [];
/**
* Stores the final count of computed filters for each configuration
* Used to determine when all filters for a configuration have been processed
*/
private finalFiltersComputed = [];
subs = [];
defaultFilterCount: number;
@@ -88,16 +95,13 @@ export class SearchFiltersComponent implements OnInit, OnDestroy {
}
ngOnInit(): void {
this.router.events.subscribe(() => {
this.clearParams = this.searchConfigService.getCurrentFrontendFilters().pipe(
tap(() => this.filtersWithComputedVisibility = 0),
map((filters) => {
Object.keys(filters).forEach((f) => filters[f] = null);
return filters;
})
);
this.searchLink = this.getSearchLink();
});
}
/**
@@ -127,7 +131,122 @@ export class SearchFiltersComponent implements OnInit, OnDestroy {
countFiltersWithComputedVisibility(computed: boolean) {
if (computed) {
this.filtersWithComputedVisibility += 1;
this.filters.pipe(
// Get filter data and check if we need to increment the counter
map(filtersData => {
if (filtersData && filtersData.hasSucceeded && filtersData.payload) {
const totalFilters = filtersData.payload.length;
const currentComputed = this.getCurrentFiltersComputed(this.currentConfiguration);
// If we've already computed all filters for this configuration
if (currentComputed >= totalFilters) {
// Register in finalFiltersComputed if not already registered
if (!this.findConfigInFinalFilters(this.currentConfiguration)) {
this.updateFinalFiltersComputed(this.currentConfiguration, totalFilters);
}
return { shouldIncrement: false };
}
// We haven't reached the total yet, proceed with increment
return {
shouldIncrement: true,
totalFilters
};
}
return { shouldIncrement: false };
}),
// Only continue if we need to increment the counter
filter(result => result.shouldIncrement),
// Increment the counter for the current configuration
map(result => {
const filterConfig = this.findConfigInCurrentFilters(this.currentConfiguration);
if (filterConfig) {
// Update existing counter
filterConfig.filtersComputed += 1;
} else {
// Create new counter entry
this.currentFiltersComputed.push({
configuration: this.currentConfiguration,
filtersComputed: 1
});
}
// Pass along the total and updated count
return {
totalFilters: result.totalFilters,
currentComputed: this.getCurrentFiltersComputed(this.currentConfiguration)
};
}),
// Check if we've reached the total after incrementing
map(result => {
if (result.currentComputed === result.totalFilters) {
// If we've reached the total, update final filters count
this.updateFinalFiltersComputed(this.currentConfiguration, result.currentComputed);
}
return result;
})
).pipe(take(1)).subscribe(); // Execute the pipeline and immediately unsubscribe
}
}
/**
* Finds a configuration entry in the currentFiltersComputed array
* @param configuration The configuration identifier to search for
* @returns The filter configuration object if found, otherwise undefined
*/
private findConfigInCurrentFilters(configuration: string) {
return this.currentFiltersComputed.find(
(configFilter) => configFilter.configuration === configuration
);
}
/**
* Finds a configuration entry in the finalFiltersComputed array
* @param configuration The configuration identifier to search for
* @returns The filter configuration object if found, otherwise undefined
*/
private findConfigInFinalFilters(configuration: string) {
return this.finalFiltersComputed.find(
(configFilter) => configFilter.configuration === configuration
);
}
/**
* Updates or adds a new entry in the finalFiltersComputed array
* @param configuration The configuration identifier to update
* @param count The number of computed filters to set for this configuration
*/
private updateFinalFiltersComputed(configuration: string, count: number) {
const filterConfig = this.findConfigInFinalFilters(configuration);
if (filterConfig) {
filterConfig.filtersComputed = count;
} else {
this.finalFiltersComputed.push({
configuration,
filtersComputed: count
});
}
}
/**
* Gets the current number of computed filters for a specific configuration
* @param configuration The configuration identifier to get the count for
* @returns The number of computed filters, or 0 if none found
*/
private getCurrentFiltersComputed(configuration: string) {
const configFilter = this.findConfigInCurrentFilters(configuration);
return configFilter?.filtersComputed || 0;
}
/**
* Gets the final number of computed filters for a specific configuration
* @param configuration The configuration identifier to get the count for
* @returns The number of computed filters in the final state, or 0 if none found
*/
getFinalFiltersComputed(configuration: string): number {
const configFilter = this.findConfigInFinalFilters(configuration);
return configFilter?.filtersComputed || 0;
}
}