[MNT-24388] fix location search facet (#11171)

* [MNT-24388] fetch sites for locations facet

* [MNT-24388] fix sonar issues

* [MNT-24388] apply cr comments
This commit is contained in:
Grzegorz Jaśkowski
2025-09-17 12:18:23 +02:00
committed by GitHub
parent 1c8181fca8
commit d49575ba03
3 changed files with 71 additions and 8 deletions

View File

@@ -22,11 +22,14 @@ import { SearchFilterAutocompleteChipsComponent } from './search-filter-autocomp
import { EMPTY, of, ReplaySubject } from 'rxjs'; import { EMPTY, of, ReplaySubject } from 'rxjs';
import { AutocompleteField } from '../../models/autocomplete-option.interface'; import { AutocompleteField } from '../../models/autocomplete-option.interface';
import { TagService } from '../../../tag/services/tag.service'; import { TagService } from '../../../tag/services/tag.service';
import { SitesService } from '../../../common/services/sites.service';
import { SitePaging } from '@alfresco/js-api';
describe('SearchFilterAutocompleteChipsComponent', () => { describe('SearchFilterAutocompleteChipsComponent', () => {
let component: SearchFilterAutocompleteChipsComponent; let component: SearchFilterAutocompleteChipsComponent;
let fixture: ComponentFixture<SearchFilterAutocompleteChipsComponent>; let fixture: ComponentFixture<SearchFilterAutocompleteChipsComponent>;
let tagService: TagService; let tagService: TagService;
let sitesService: SitesService;
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
@@ -42,6 +45,7 @@ describe('SearchFilterAutocompleteChipsComponent', () => {
fixture = TestBed.createComponent(SearchFilterAutocompleteChipsComponent); fixture = TestBed.createComponent(SearchFilterAutocompleteChipsComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
tagService = TestBed.inject(TagService); tagService = TestBed.inject(TagService);
sitesService = TestBed.inject(SitesService);
component.id = 'test-id'; component.id = 'test-id';
component.context = { component.context = {
queryFragments: { queryFragments: {
@@ -160,4 +164,28 @@ describe('SearchFilterAutocompleteChipsComponent', () => {
expect(component.selectedOptions).toEqual([{ value: 'option2' }, { value: 'option1' }]); expect(component.selectedOptions).toEqual([{ value: 'option2' }, { value: 'option1' }]);
expect(component.context.filterLoaded.next).toHaveBeenCalled(); expect(component.context.filterLoaded.next).toHaveBeenCalled();
}); });
it('should populate LOCATION field options with sites and predefined values from config', (done) => {
const sitesMock: SitePaging = {
list: {
pagination: {},
entries: [
{ entry: { guid: 'site1', id: 'site1', title: 'Marketing', visibility: 'public' } },
{ entry: { guid: 'site2', id: 'site2', title: 'Finance', visibility: 'private' } }
]
}
};
component.settings.field = AutocompleteField.LOCATION;
component.settings.autocompleteOptions = [{ value: 'Repository', query: `PATH:'somePath'` }];
spyOn(sitesService, 'getSites').and.returnValue(of(sitesMock));
component.onInputChange('mark');
component.autocompleteOptions$.subscribe((result) => {
expect(result).toEqual([
{ id: 'site1', value: 'Marketing' },
{ id: 'site2', value: 'Finance' },
{ value: 'Repository', query: `PATH:'somePath'` }
]);
done();
});
});
}); });

View File

@@ -30,6 +30,7 @@ import { SearchChipAutocompleteInputComponent } from '../search-chip-autocomplet
import { TranslatePipe } from '@ngx-translate/core'; import { TranslatePipe } from '@ngx-translate/core';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { SitesService } from '../../../common/services/sites.service';
@Component({ @Component({
selector: 'adf-search-filter-autocomplete-chips', selector: 'adf-search-filter-autocomplete-chips',
@@ -54,7 +55,11 @@ export class SearchFilterAutocompleteChipsComponent implements SearchWidget, OnI
private readonly destroyRef = inject(DestroyRef); private readonly destroyRef = inject(DestroyRef);
constructor(private tagService: TagService, private categoryService: CategoryService) { constructor(
private readonly tagService: TagService,
private readonly categoryService: CategoryService,
private readonly sitesService: SitesService
) {
this.options = new SearchFilterList<AutocompleteOption[]>(); this.options = new SearchFilterList<AutocompleteOption[]>();
} }
@@ -117,8 +122,12 @@ export class SearchFilterAutocompleteChipsComponent implements SearchWidget, OnI
} }
onInputChange(value: string) { onInputChange(value: string) {
if (this.settings.field === AutocompleteField.CATEGORIES && value) { if (value) {
if (this.settings.field === AutocompleteField.CATEGORIES) {
this.searchForExistingCategories(value); this.searchForExistingCategories(value);
} else if (this.settings.field === AutocompleteField.LOCATION) {
this.populateSitesOptions();
}
} }
} }
@@ -131,10 +140,16 @@ export class SearchFilterAutocompleteChipsComponent implements SearchWidget, OnI
this.displayValue$.next(this.selectedOptions.map((option) => option.value).join(', ')); this.displayValue$.next(this.selectedOptions.map((option) => option.value).join(', '));
if (this.context && this.settings && this.settings.field) { if (this.context && this.settings && this.settings.field) {
let queryFragments; let queryFragments;
if (this.settings.field === AutocompleteField.CATEGORIES) { switch (this.settings.field) {
case AutocompleteField.CATEGORIES:
queryFragments = this.selectedOptions.map((val) => `${this.settings.field}:"workspace://SpacesStore/${val.id}"`); queryFragments = this.selectedOptions.map((val) => `${this.settings.field}:"workspace://SpacesStore/${val.id}"`);
} else { break;
case AutocompleteField.LOCATION:
queryFragments = this.selectedOptions.map((val) => val.query ?? `${this.settings.field}:"${val.id}"`);
break;
default:
queryFragments = this.selectedOptions.map((val) => val.query ?? `${this.settings.field}:"${val.value}"`); queryFragments = this.selectedOptions.map((val) => val.query ?? `${this.settings.field}:"${val.value}"`);
break;
} }
this.context.queryFragments[this.id] = queryFragments.join(' OR '); this.context.queryFragments[this.id] = queryFragments.join(' OR ');
if (updateContext) { if (updateContext) {
@@ -157,6 +172,9 @@ export class SearchFilterAutocompleteChipsComponent implements SearchWidget, OnI
case AutocompleteField.CATEGORIES: case AutocompleteField.CATEGORIES:
this.autocompleteOptionsSubject$.next([]); this.autocompleteOptionsSubject$.next([]);
break; break;
case AutocompleteField.LOCATION:
this.autocompleteOptionsSubject$.next([]);
break;
default: default:
this.autocompleteOptionsSubject$.next(this.settings.autocompleteOptions); this.autocompleteOptionsSubject$.next(this.settings.autocompleteOptions);
} }
@@ -173,4 +191,20 @@ export class SearchFilterAutocompleteChipsComponent implements SearchWidget, OnI
); );
}); });
} }
private populateSitesOptions(): void {
this.sitesService
.getSites()
.pipe(
map((sites) => {
const predefinedOptions = this.settings?.autocompleteOptions || [];
const sitesOptions = sites.list.entries.map<AutocompleteOption>((siteEntry) => ({
id: siteEntry.entry.id,
value: siteEntry.entry.title
}));
return [...sitesOptions, ...predefinedOptions];
})
)
.subscribe((options) => this.autocompleteOptionsSubject$.next(options));
}
} }

View File

@@ -24,5 +24,6 @@ export interface AutocompleteOption {
export enum AutocompleteField { export enum AutocompleteField {
TAG = 'TAG', TAG = 'TAG',
CATEGORIES = 'cm:categories' CATEGORIES = 'cm:categories',
LOCATION = 'SITE'
} }