mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[ACS-4788] Add support for the Categories facet (#8470)
* [ACS-4525] load category paths * [ACS-4525] fix for buckets to update properly * [ACS-4525] getCategory docs * [ACS-4525] unit tests * [ACS-4525] small fixes * [ACS-4525] bug fix * [ACS-4525] code improvements * [ACS-4525] alignment * [ACS-4525] linting
This commit is contained in:
committed by
GitHub
parent
10e6cf1d6f
commit
4fd1e3093f
@@ -61,6 +61,13 @@ describe('CategoryService', () => {
|
||||
});
|
||||
}));
|
||||
|
||||
it('should fetch the category with the provided categoryId', fakeAsync(() => {
|
||||
const getSpy = spyOn(categoryService.categoriesApi, 'getCategory').and.returnValue(Promise.resolve(fakeCategoryEntry));
|
||||
categoryService.getCategory(fakeParentCategoryId).subscribe(() => {
|
||||
expect(getSpy).toHaveBeenCalledOnceWith(fakeParentCategoryId);
|
||||
});
|
||||
}));
|
||||
|
||||
it('should create subcategory', fakeAsync(() => {
|
||||
const createSpy = spyOn(categoryService.categoriesApi, 'createSubcategories').and.returnValue(Promise.resolve(fakeCategoryEntry));
|
||||
categoryService.createSubcategories(fakeParentCategoryId, [fakeCategoryEntry.entry]).subscribe(() => {
|
||||
|
@@ -57,6 +57,16 @@ export class CategoryService {
|
||||
return from(this.categoriesApi.getSubcategories(parentCategoryId ?? '-root-', {skipCount, maxItems}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a category by ID
|
||||
*
|
||||
* @param categoryId The identifier of a category.
|
||||
* @return Observable<CategoryEntry>
|
||||
*/
|
||||
getCategory(categoryId: string): Observable<CategoryEntry> {
|
||||
return from(this.categoriesApi.getCategory(categoryId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates subcategories under category with provided categoryId
|
||||
*
|
||||
|
@@ -20,16 +20,27 @@ import { TestBed } from '@angular/core/testing';
|
||||
import { SearchFacetFiltersService } from './search-facet-filters.service';
|
||||
import { ContentTestingModule } from '../../testing/content.testing.module';
|
||||
import { SearchQueryBuilderService } from './search-query-builder.service';
|
||||
import { FacetBucketSortBy, FacetBucketSortDirection } from '@alfresco/adf-content-services';
|
||||
import { CategoryService, FacetBucketSortBy, FacetBucketSortDirection } from '@alfresco/adf-content-services';
|
||||
import { EMPTY, of } from 'rxjs';
|
||||
|
||||
describe('SearchFacetFiltersService', () => {
|
||||
let searchFacetFiltersService: SearchFacetFiltersService;
|
||||
let queryBuilder: SearchQueryBuilderService;
|
||||
let categoryService: CategoryService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [ContentTestingModule]
|
||||
imports: [ContentTestingModule],
|
||||
providers: [{
|
||||
provide: CategoryService,
|
||||
useValue: {
|
||||
getCategory: () => EMPTY,
|
||||
searchCategories: () => EMPTY
|
||||
}
|
||||
}]
|
||||
});
|
||||
|
||||
categoryService = TestBed.inject(CategoryService);
|
||||
searchFacetFiltersService = TestBed.inject(SearchFacetFiltersService);
|
||||
queryBuilder = TestBed.inject(SearchQueryBuilderService);
|
||||
});
|
||||
@@ -460,6 +471,63 @@ describe('SearchFacetFiltersService', () => {
|
||||
expect(searchFacetFiltersService.responseFacets.map(f => f.field)).toEqual(['field4', 'field1', 'Query 1', 'field2', 'field3']);
|
||||
});
|
||||
|
||||
it('should load category names for cm:categories facet', () => {
|
||||
const entry = {id: 'test-id-test', name: 'name'};
|
||||
searchFacetFiltersService.responseFacets = null;
|
||||
spyOn(categoryService, 'getCategory').and.returnValue(of({entry}));
|
||||
spyOn(categoryService, 'searchCategories').and.returnValue(of({
|
||||
list: {
|
||||
entries: [{
|
||||
entry: {
|
||||
...entry,
|
||||
nodeType: 'node-type',
|
||||
path: { name: '/categories/General/Test Category/Subcategory'},
|
||||
isFolder: false,
|
||||
isFile: false
|
||||
}
|
||||
}]
|
||||
}
|
||||
}));
|
||||
|
||||
queryBuilder.config = {
|
||||
categories: [],
|
||||
facetFields: {
|
||||
fields: [
|
||||
{label: 'f1', field: 'f1', mincount: 0},
|
||||
{label: 'categories', field: 'cm:categories', mincount: 0}
|
||||
]
|
||||
},
|
||||
facetQueries: {
|
||||
queries: []
|
||||
}
|
||||
};
|
||||
|
||||
const fields: any = [
|
||||
{type: 'field', label: 'f1', buckets: [{label: 'a1'}, {label: 'a2'}]},
|
||||
{
|
||||
type: 'field', label: 'categories', buckets: [{
|
||||
label: `workspace://SpacesStore/${entry.id}`,
|
||||
filterQuery: `cm:categories:"workspace://SpacesStore/${entry.id}"`
|
||||
}]
|
||||
}
|
||||
];
|
||||
let data = {
|
||||
list: {
|
||||
context: {
|
||||
facets: fields
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
searchFacetFiltersService.onDataLoaded(data);
|
||||
|
||||
expect(categoryService.getCategory).toHaveBeenCalledWith(entry.id);
|
||||
expect(categoryService.searchCategories).toHaveBeenCalledWith(entry.name);
|
||||
expect(searchFacetFiltersService.responseFacets[1].buckets.items[0].display).toBe(`Test Category/Subcategory/${entry.name}`);
|
||||
expect(searchFacetFiltersService.responseFacets[1].buckets.length).toEqual(1);
|
||||
expect(searchFacetFiltersService.responseFacets.length).toEqual(2);
|
||||
});
|
||||
|
||||
describe('Bucket sorting', () => {
|
||||
let data;
|
||||
|
||||
|
@@ -17,15 +17,16 @@
|
||||
|
||||
import { Inject, Injectable, OnDestroy } from '@angular/core';
|
||||
import { FacetBucketSortBy, FacetBucketSortDirection, FacetField } from '../models/facet-field.interface';
|
||||
import { Subject } from 'rxjs';
|
||||
import { Subject, throwError } from 'rxjs';
|
||||
import { SEARCH_QUERY_SERVICE_TOKEN } from '../search-query-service.token';
|
||||
import { SearchQueryBuilderService } from './search-query-builder.service';
|
||||
import { TranslationService } from '@alfresco/adf-core';
|
||||
import { SearchService } from '../services/search.service';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { SearchService } from './search.service';
|
||||
import { catchError, concatMap, takeUntil } from 'rxjs/operators';
|
||||
import { GenericBucket, GenericFacetResponse, ResultSetContext, ResultSetPaging } from '@alfresco/js-api';
|
||||
import { SearchFilterList } from '../models/search-filter-list.model';
|
||||
import { FacetFieldBucket } from '../models/facet-field-bucket.interface';
|
||||
import { CategoryService } from '../../category';
|
||||
|
||||
export interface SelectedBucket {
|
||||
field: FacetField;
|
||||
@@ -53,7 +54,9 @@ export class SearchFacetFiltersService implements OnDestroy {
|
||||
|
||||
constructor(@Inject(SEARCH_QUERY_SERVICE_TOKEN) public queryBuilder: SearchQueryBuilderService,
|
||||
private searchService: SearchService,
|
||||
private translationService: TranslationService) {
|
||||
private translationService: TranslationService,
|
||||
private categoryService: CategoryService
|
||||
) {
|
||||
if (queryBuilder.config && queryBuilder.config.facetQueries) {
|
||||
this.facetQueriesPageSize = queryBuilder.config.facetQueries.pageSize || DEFAULT_PAGE_SIZE;
|
||||
}
|
||||
@@ -102,6 +105,10 @@ export class SearchFacetFiltersService implements OnDestroy {
|
||||
this.sortFacetBuckets(responseBuckets, field.settings?.bucketSortBy, field.settings?.bucketSortDirection ?? FacetBucketSortDirection.ASCENDING);
|
||||
const alreadyExistingField = this.findResponseFacet(itemType, field.label);
|
||||
|
||||
if (field.field === 'cm:categories'){
|
||||
this.loadCategoryNames(responseBuckets);
|
||||
}
|
||||
|
||||
if (alreadyExistingField) {
|
||||
const alreadyExistingBuckets = alreadyExistingField.buckets && alreadyExistingField.buckets.items || [];
|
||||
|
||||
@@ -335,6 +342,27 @@ export class SearchFacetFiltersService implements OnDestroy {
|
||||
};
|
||||
}
|
||||
|
||||
private loadCategoryNames(bucketList: FacetFieldBucket[]) {
|
||||
bucketList.forEach((item) => {
|
||||
const categoryId = item.label.split('/').pop();
|
||||
this.categoryService.getCategory(categoryId)
|
||||
.pipe(
|
||||
concatMap((categoryEntry) => this.categoryService.searchCategories(categoryEntry.entry.name)),
|
||||
catchError(error => throwError(error))
|
||||
)
|
||||
.subscribe(
|
||||
result => {
|
||||
const nextAfterGeneralPathPartIndex = 3;
|
||||
const pathSeparator = '/';
|
||||
const currentCat = result.list.entries.filter(entry => entry.entry.id === categoryId)[0];
|
||||
const path = currentCat.entry.path.name.split(pathSeparator).slice(nextAfterGeneralPathPartIndex).join('/');
|
||||
|
||||
item.display = path ? `${path}/${currentCat.entry.name}` : currentCat.entry.name;
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
unselectFacetBucket(field: FacetField, bucket: FacetFieldBucket) {
|
||||
if (bucket) {
|
||||
bucket.checked = false;
|
||||
|
Reference in New Issue
Block a user