From 255f10f3a8743f610f8afc56305e37ed4c3507ab Mon Sep 17 00:00:00 2001 From: AlexSanchez-bit Date: Wed, 3 Jun 2026 12:35:14 -0400 Subject: [PATCH] fix[frontend](alerts-view): add a duplication avoid on alert filter fields count --- .../alert-generic-filter.component.ts | 74 ++++++++++--------- .../elasticsearch-index.service.ts | 15 +++- 2 files changed, 54 insertions(+), 35 deletions(-) diff --git a/frontend/src/app/data-management/alert-management/shared/components/filters/alert-generic-filter/alert-generic-filter.component.ts b/frontend/src/app/data-management/alert-management/shared/components/filters/alert-generic-filter/alert-generic-filter.component.ts index 2d8d027e3..19dfeb5ec 100644 --- a/frontend/src/app/data-management/alert-management/shared/components/filters/alert-generic-filter/alert-generic-filter.component.ts +++ b/frontend/src/app/data-management/alert-management/shared/components/filters/alert-generic-filter/alert-generic-filter.component.ts @@ -1,6 +1,6 @@ import {Component, EventEmitter, Input, OnDestroy, OnInit, Output} from '@angular/core'; import {Subject} from 'rxjs'; -import {takeUntil} from 'rxjs/operators'; +import {debounceTime, distinctUntilChanged, switchMap, takeUntil} from 'rxjs/operators'; import {ALERT_TAGS_FIELD} from '../../../../../../shared/constants/alert/alert-field.constant'; import {ALERT_INDEX_PATTERN} from '../../../../../../shared/constants/main-index-pattern.constant'; import {ElasticDataTypesEnum} from '../../../../../../shared/enums/elastic-data-types.enum'; @@ -30,6 +30,7 @@ export class AlertGenericFilterComponent implements OnInit, OnDestroy { filter: ElasticFilterType; sort: { orderByCount: boolean, sortAsc: boolean } = {orderByCount: true, sortAsc: false}; destroy$: Subject = new Subject(); + private fetchRequest$ = new Subject(); constructor(private elasticSearchIndexService: ElasticSearchIndexService, private alertFiltersBehavior: AlertFiltersBehavior, @@ -37,10 +38,39 @@ export class AlertGenericFilterComponent implements OnInit, OnDestroy { } ngOnInit() { - // this.getFieldValues(); - /** - * If filter is tags subscribe to changes to reload data on add new tag on alert - */ + this.fetchRequest$ + .pipe( + debounceTime(300), + switchMap(() => { + const field = this.setFieldKeyword(); + const filters = this.activeFilters + .filter(value => !value.field.includes(field)); + if (this.search !== undefined && this.search !== '') { + filters.push({ + field: this.fieldFilter.field, + operator: ElasticOperatorsEnum.CONTAIN, + value: this.search + }); + } + const req = { + field, + filters, + index: ALERT_INDEX_PATTERN, + orderByCount: this.sort.orderByCount, + sortAsc: this.sort.sortAsc, + top: this.top + }; + return this.elasticSearchIndexService.getValuesWithCount(req); + }), + takeUntil(this.destroy$) + ) + .subscribe(response => { + this.fieldValues = response.body; + this.loading = false; + this.searching = false; + this.loadingMore = false; + }); + if (this.fieldFilter.field === ALERT_TAGS_FIELD) { this.alertUpdateTagBehavior.$tagRefresh .pipe(takeUntil(this.destroy$)) @@ -50,9 +80,6 @@ export class AlertGenericFilterComponent implements OnInit, OnDestroy { } }); } - /** - * Reset all values of selected filter - */ this.alertFiltersBehavior.$resetFilter .pipe(takeUntil(this.destroy$)) .subscribe(reset => { @@ -74,7 +101,11 @@ export class AlertGenericFilterComponent implements OnInit, OnDestroy { } }); this.alertFiltersBehavior.$filters - .pipe(takeUntil(this.destroy$)) + .pipe( + debounceTime(150), + distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)), + takeUntil(this.destroy$) + ) .subscribe((filters: ElasticFilterType[]) => { if (filters) { this.activeFilters = filters; @@ -101,30 +132,7 @@ export class AlertGenericFilterComponent implements OnInit, OnDestroy { } getFieldValues() { - const field = this.setFieldKeyword(); - const filters = this.activeFilters - .filter(value => !value.field.includes(field)); - if (this.search !== undefined && this.search !== '') { - filters.push({ - field: this.fieldFilter.field, - operator: ElasticOperatorsEnum.CONTAIN, - value: this.search - }); - } - const req = { - field, - filters, - index: ALERT_INDEX_PATTERN, - orderByCount: this.sort.orderByCount, - sortAsc: this.sort.sortAsc, - top: this.top - }; - this.elasticSearchIndexService.getValuesWithCount(req).subscribe(response => { - this.fieldValues = response.body; - this.loading = false; - this.searching = false; - this.loadingMore = false; - }); + this.fetchRequest$.next(); } setFieldKeyword(): string { diff --git a/frontend/src/app/shared/services/elasticsearch/elasticsearch-index.service.ts b/frontend/src/app/shared/services/elasticsearch/elasticsearch-index.service.ts index 0f7f38755..ea1ccbf67 100644 --- a/frontend/src/app/shared/services/elasticsearch/elasticsearch-index.service.ts +++ b/frontend/src/app/shared/services/elasticsearch/elasticsearch-index.service.ts @@ -1,16 +1,18 @@ import {HttpClient, HttpResponse} from '@angular/common/http'; import {Injectable} from '@angular/core'; -import {Observable} from 'rxjs'; +import {Observable, Subscription, Subject} from 'rxjs'; import {SERVER_API_URL} from '../../../app.constants'; import {ElasticSearchFieldInfoType} from '../../types/elasticsearch/elastic-search-field-info.type'; import {ElasticsearchIndexType} from '../../types/elasticsearch/elasticsearch-index.type'; import {createRequestOption} from '../../util/request-util'; +import { finalize, shareReplay } from 'rxjs/operators'; @Injectable({ providedIn: 'root' }) export class ElasticSearchIndexService { public resourceUrl = SERVER_API_URL + 'api/elasticsearch/'; + private inFlightRequests = new Map>(); constructor(private http: HttpClient) { } @@ -40,7 +42,16 @@ export class ElasticSearchIndexService { } getValuesWithCount(rq) { - return this.http.post(this.resourceUrl + 'property/values-with-count', rq, {observe: 'response'}); + const key = JSON.stringify(rq); + let req = this.inFlightRequests.get(key); + if (!req) { + req = this.http.post(this.resourceUrl + 'property/values-with-count', rq, {observe: 'response'}).pipe( + finalize(() => this.inFlightRequests.delete(key)), + shareReplay(1) + ); + this.inFlightRequests.set(key, req); + } + return req; } deleteIndexes(indexes: string[]) {