From 4059b0a620c5b2bf297d4260390ec3e572f5c385 Mon Sep 17 00:00:00 2001 From: Vera Clemens Date: Tue, 29 Sep 2026 10:44:38 +0200 Subject: [PATCH 1/4] feat: add support for including dataset collections to `GetCollectionItems` --- .../domain/repositories/ICollectionsRepository.ts | 2 ++ .../domain/useCases/GetCollectionItems.ts | 8 +++++++- .../infra/repositories/CollectionsRepository.ts | 10 +++++++++- src/datasets/domain/models/DatasetPreview.ts | 2 ++ .../transformers/DatasetPreviewPayload.ts | 7 +++++++ .../transformers/datasetPreviewsTransformers.ts | 13 ++++++++++++- 6 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/collections/domain/repositories/ICollectionsRepository.ts b/src/collections/domain/repositories/ICollectionsRepository.ts index cf1fad5b..93f1a945 100644 --- a/src/collections/domain/repositories/ICollectionsRepository.ts +++ b/src/collections/domain/repositories/ICollectionsRepository.ts @@ -51,6 +51,8 @@ export interface ICollectionsRepository { collectionSearchCriteria?: CollectionSearchCriteria, searchServiceName?: string, showTypeCounts?: boolean + showTypeCounts?: boolean, + showCollections?: boolean ): Promise getMyDataCollectionItems( roleIds: number[], diff --git a/src/collections/domain/useCases/GetCollectionItems.ts b/src/collections/domain/useCases/GetCollectionItems.ts index 2d8cd10b..4f89d79e 100644 --- a/src/collections/domain/useCases/GetCollectionItems.ts +++ b/src/collections/domain/useCases/GetCollectionItems.ts @@ -20,6 +20,7 @@ export class GetCollectionItems implements UseCase { * @param {CollectionSearchCriteria} [collectionSearchCriteria] - Supports filtering the collection items by different properties (optional). * @param {string} [searchServiceName] - The search service name on which to execute the search (optional). * @param {boolean} [showTypeCounts] - If true, the response will include the count per object type (optional). + * @param {boolean} [showCollections] - If true, dataset results will include the collections they belong to (optional). * @returns {Promise} */ async execute( @@ -28,7 +29,10 @@ export class GetCollectionItems implements UseCase { offset?: number, collectionSearchCriteria?: CollectionSearchCriteria, searchServiceName?: string, - showTypeCounts = false + showTypeCounts = false, + showCollections = false + // metadataFields?: `${string}:${string}`[], + // keepRawFields = false ): Promise { return await this.collectionsRepository.getCollectionItems( collectionId, @@ -37,6 +41,8 @@ export class GetCollectionItems implements UseCase { collectionSearchCriteria, searchServiceName, showTypeCounts + showTypeCounts, + showCollections ) } } diff --git a/src/collections/infra/repositories/CollectionsRepository.ts b/src/collections/infra/repositories/CollectionsRepository.ts index 99dddaf3..c64ce282 100644 --- a/src/collections/infra/repositories/CollectionsRepository.ts +++ b/src/collections/infra/repositories/CollectionsRepository.ts @@ -83,6 +83,7 @@ export enum GetCollectionItemsQueryParams { TYPE = 'type', FILTERQUERY = 'fq', SHOW_TYPE_COUNTS = 'show_type_counts', + SHOW_COLLECTIONS = 'show_collections', SEARCH_SERVICE_NAME = 'search_service' } @@ -246,7 +247,10 @@ export class CollectionsRepository extends ApiRepository implements ICollections offset?: number, collectionSearchCriteria?: CollectionSearchCriteria, searchServiceName?: string, - showTypeCounts?: boolean + showTypeCounts?: boolean, + showCollections?: boolean + // metadataFields?: `${string}:${string}`[], + // keepRawFields?: boolean ): Promise { const queryParams = new URLSearchParams({ [GetCollectionItemsQueryParams.QUERY]: '*', @@ -271,6 +275,10 @@ export class CollectionsRepository extends ApiRepository implements ICollections queryParams.set(GetCollectionItemsQueryParams.SHOW_TYPE_COUNTS, 'true') } + if (showCollections) { + queryParams.set(GetCollectionItemsQueryParams.SHOW_COLLECTIONS, 'true') + } + if (searchServiceName) { queryParams.set(GetCollectionItemsQueryParams.SEARCH_SERVICE_NAME, searchServiceName) } diff --git a/src/datasets/domain/models/DatasetPreview.ts b/src/datasets/domain/models/DatasetPreview.ts index 5ac1da00..580b47ab 100644 --- a/src/datasets/domain/models/DatasetPreview.ts +++ b/src/datasets/domain/models/DatasetPreview.ts @@ -1,6 +1,7 @@ import { CollectionItemType } from '../../../collections' import { PublicationStatus } from '../../../core/domain/models/PublicationStatus' import { DatasetVersionInfo } from './Dataset' +import { CollectionSummary } from '../../../collections/domain/models/CollectionSummary' export interface DatasetPreview { type: CollectionItemType.DATASET @@ -15,4 +16,5 @@ export interface DatasetPreview { parentCollectionAlias: string imageUrl?: string userRoles?: string[] + collections?: CollectionSummary[] } diff --git a/src/datasets/infra/repositories/transformers/DatasetPreviewPayload.ts b/src/datasets/infra/repositories/transformers/DatasetPreviewPayload.ts index 99f764a5..3714082e 100644 --- a/src/datasets/infra/repositories/transformers/DatasetPreviewPayload.ts +++ b/src/datasets/infra/repositories/transformers/DatasetPreviewPayload.ts @@ -16,4 +16,11 @@ export interface DatasetPreviewPayload { identifier_of_dataverse: string name_of_dataverse: string image_url?: string + collections?: DatasetPreviewCollectionPayload[] +} + +export interface DatasetPreviewCollectionPayload { + id: number + name: string + alias: string } diff --git a/src/datasets/infra/repositories/transformers/datasetPreviewsTransformers.ts b/src/datasets/infra/repositories/transformers/datasetPreviewsTransformers.ts index 3ae56800..7d1afd43 100644 --- a/src/datasets/infra/repositories/transformers/datasetPreviewsTransformers.ts +++ b/src/datasets/infra/repositories/transformers/datasetPreviewsTransformers.ts @@ -2,7 +2,8 @@ import { AxiosResponse } from 'axios' import { DatasetPreview } from '../../../domain/models/DatasetPreview' import { DatasetVersionState } from '../../../domain/models/Dataset' import { DatasetPreviewSubset } from '../../../domain/models/DatasetPreviewSubset' -import { DatasetPreviewPayload } from './DatasetPreviewPayload' +import { DatasetPreviewCollectionPayload, DatasetPreviewPayload } from './DatasetPreviewPayload' +import { CollectionSummary } from '../../../../collections/domain/models/CollectionSummary' import { PublicationStatus } from '../../../../core/domain/models/PublicationStatus' import { CollectionItemType } from '../../../../collections/domain/models/CollectionItemType' import { MyDataDatasetPreviewPayload } from './MyDataDatasetPreviewPayload' @@ -29,6 +30,14 @@ export const transformDatasetPreviewPayloadToDatasetPreview = ( datasetPreviewPayload.publicationStatuses.forEach((element) => { publicationStatuses.push(element as unknown as PublicationStatus) }) + const collections: CollectionSummary[] | undefined = datasetPreviewPayload.collections?.map( + (collection: DatasetPreviewCollectionPayload) => ({ + id: collection.id, + alias: collection.alias, + displayName: collection.name + }) + ) + return { type: CollectionItemType.DATASET, persistentId: datasetPreviewPayload.global_id, @@ -52,6 +61,8 @@ export const transformDatasetPreviewPayloadToDatasetPreview = ( ...(datasetPreviewPayload.image_url && { imageUrl: datasetPreviewPayload.image_url }) + }), + ...(collections && { collections }) } } From 79e55b302ad0a79e1e25c5b509d85ed6774e9442 Mon Sep 17 00:00:00 2001 From: Vera Clemens Date: Tue, 29 Sep 2026 10:47:47 +0200 Subject: [PATCH 2/4] feat: add support for including metadata fields to `GetCollectionItems` --- docs/useCases.md | 3 +++ .../domain/repositories/ICollectionsRepository.ts | 5 +++-- .../domain/useCases/GetCollectionItems.ts | 13 ++++++++----- .../infra/repositories/CollectionsRepository.ts | 15 +++++++++++---- .../transformers/collectionTransformers.ts | 8 ++++++-- src/datasets/domain/models/DatasetPreview.ts | 2 ++ .../repositories/transformers/DatasetPayload.ts | 2 +- .../transformers/DatasetPreviewPayload.ts | 3 +++ .../transformers/datasetPreviewsTransformers.ts | 12 +++++++++--- .../transformers/datasetTransformers.ts | 2 +- 10 files changed, 47 insertions(+), 18 deletions(-) diff --git a/docs/useCases.md b/docs/useCases.md index 1b1f25ed..ad433a27 100644 --- a/docs/useCases.md +++ b/docs/useCases.md @@ -369,6 +369,9 @@ This use case supports the following optional parameters depending on the search - **collectionSearchCriteria**: ([CollectionSearchCriteria](../src/collections/domain/models/CollectionSearchCriteria.ts)) Supports filtering the collection items by different properties. - **searchServiceName**: The search service name on which to execute the search (Optional). - **showTypeCounts**: If true, the response will include the count per object type (Optional). +- **showCollections**: If true, dataset results will include a `collections` array containing [CollectionSummary](../src/collections/domain/models/CollectionSummary.ts) objects for their collections (Optional). +- **metadataFields**: A list of metadata fields to include in dataset results. Each value must use the `metadata_block_name:field_name` format (Optional). +- **keepRawFields**: If true, metadata field values are returned without Markdown transformation (Optional). #### List My Data Collection Items diff --git a/src/collections/domain/repositories/ICollectionsRepository.ts b/src/collections/domain/repositories/ICollectionsRepository.ts index 93f1a945..50d36571 100644 --- a/src/collections/domain/repositories/ICollectionsRepository.ts +++ b/src/collections/domain/repositories/ICollectionsRepository.ts @@ -50,9 +50,10 @@ export interface ICollectionsRepository { offset?: number, collectionSearchCriteria?: CollectionSearchCriteria, searchServiceName?: string, - showTypeCounts?: boolean showTypeCounts?: boolean, - showCollections?: boolean + showCollections?: boolean, + metadataFields?: `${string}:${string}`[], + keepRawFields?: boolean ): Promise getMyDataCollectionItems( roleIds: number[], diff --git a/src/collections/domain/useCases/GetCollectionItems.ts b/src/collections/domain/useCases/GetCollectionItems.ts index 4f89d79e..903a68c3 100644 --- a/src/collections/domain/useCases/GetCollectionItems.ts +++ b/src/collections/domain/useCases/GetCollectionItems.ts @@ -21,6 +21,8 @@ export class GetCollectionItems implements UseCase { * @param {string} [searchServiceName] - The search service name on which to execute the search (optional). * @param {boolean} [showTypeCounts] - If true, the response will include the count per object type (optional). * @param {boolean} [showCollections] - If true, dataset results will include the collections they belong to (optional). + * @param {`${string}:${string}`[]} [metadataFields] - Metadata fields to include in dataset results (optional). + * @param {boolean} [keepRawFields] - If true, metadata field values will not be transformed to Markdown (optional). * @returns {Promise} */ async execute( @@ -30,9 +32,9 @@ export class GetCollectionItems implements UseCase { collectionSearchCriteria?: CollectionSearchCriteria, searchServiceName?: string, showTypeCounts = false, - showCollections = false - // metadataFields?: `${string}:${string}`[], - // keepRawFields = false + showCollections = false, + metadataFields?: `${string}:${string}`[], + keepRawFields = false ): Promise { return await this.collectionsRepository.getCollectionItems( collectionId, @@ -40,9 +42,10 @@ export class GetCollectionItems implements UseCase { offset, collectionSearchCriteria, searchServiceName, - showTypeCounts showTypeCounts, - showCollections + showCollections, + metadataFields, + keepRawFields ) } } diff --git a/src/collections/infra/repositories/CollectionsRepository.ts b/src/collections/infra/repositories/CollectionsRepository.ts index c64ce282..75c64c10 100644 --- a/src/collections/infra/repositories/CollectionsRepository.ts +++ b/src/collections/infra/repositories/CollectionsRepository.ts @@ -84,6 +84,7 @@ export enum GetCollectionItemsQueryParams { FILTERQUERY = 'fq', SHOW_TYPE_COUNTS = 'show_type_counts', SHOW_COLLECTIONS = 'show_collections', + METADATA_FIELDS = 'metadata_fields', SEARCH_SERVICE_NAME = 'search_service' } @@ -248,9 +249,9 @@ export class CollectionsRepository extends ApiRepository implements ICollections collectionSearchCriteria?: CollectionSearchCriteria, searchServiceName?: string, showTypeCounts?: boolean, - showCollections?: boolean - // metadataFields?: `${string}:${string}`[], - // keepRawFields?: boolean + showCollections?: boolean, + metadataFields?: `${string}:${string}`[], + keepRawFields?: boolean ): Promise { const queryParams = new URLSearchParams({ [GetCollectionItemsQueryParams.QUERY]: '*', @@ -279,6 +280,10 @@ export class CollectionsRepository extends ApiRepository implements ICollections queryParams.set(GetCollectionItemsQueryParams.SHOW_COLLECTIONS, 'true') } + metadataFields?.forEach((metadataField) => { + queryParams.append(GetCollectionItemsQueryParams.METADATA_FIELDS, metadataField) + }) + if (searchServiceName) { queryParams.set(GetCollectionItemsQueryParams.SEARCH_SERVICE_NAME, searchServiceName) } @@ -288,7 +293,9 @@ export class CollectionsRepository extends ApiRepository implements ICollections } return this.doGet('/search', true, queryParams) - .then((response) => transformCollectionItemsResponseToCollectionItemSubset(response)) + .then((response) => + transformCollectionItemsResponseToCollectionItemSubset(response, keepRawFields) + ) .catch((error) => { throw error }) diff --git a/src/collections/infra/repositories/transformers/collectionTransformers.ts b/src/collections/infra/repositories/transformers/collectionTransformers.ts index 4aa71d0a..ffa586b2 100644 --- a/src/collections/infra/repositories/transformers/collectionTransformers.ts +++ b/src/collections/infra/repositories/transformers/collectionTransformers.ts @@ -107,7 +107,8 @@ const transformInputLevelsPayloadToInputLevels = ( } export const transformCollectionItemsResponseToCollectionItemSubset = ( - response: AxiosResponse + response: AxiosResponse, + keepRawFields = false ): CollectionItemSubset => { const responseDataPayload = response.data.data const itemsPayload = responseDataPayload.items @@ -125,7 +126,10 @@ export const transformCollectionItemsResponseToCollectionItemSubset = ( items.push(transformFilePreviewPayloadToFilePreview(itemPayload as FilePreviewPayload)) } else if (itemPayload.type === 'dataset') { items.push( - transformDatasetPreviewPayloadToDatasetPreview(itemPayload as DatasetPreviewPayload) + transformDatasetPreviewPayloadToDatasetPreview( + itemPayload as DatasetPreviewPayload, + keepRawFields + ) ) } else if (itemPayload.type === 'dataverse') { items.push( diff --git a/src/datasets/domain/models/DatasetPreview.ts b/src/datasets/domain/models/DatasetPreview.ts index 580b47ab..e51006ed 100644 --- a/src/datasets/domain/models/DatasetPreview.ts +++ b/src/datasets/domain/models/DatasetPreview.ts @@ -2,6 +2,7 @@ import { CollectionItemType } from '../../../collections' import { PublicationStatus } from '../../../core/domain/models/PublicationStatus' import { DatasetVersionInfo } from './Dataset' import { CollectionSummary } from '../../../collections/domain/models/CollectionSummary' +import { DatasetMetadataBlock } from './Dataset' export interface DatasetPreview { type: CollectionItemType.DATASET @@ -17,4 +18,5 @@ export interface DatasetPreview { imageUrl?: string userRoles?: string[] collections?: CollectionSummary[] + metadataBlocks?: DatasetMetadataBlock[] } diff --git a/src/datasets/infra/repositories/transformers/DatasetPayload.ts b/src/datasets/infra/repositories/transformers/DatasetPayload.ts index 347bc5d1..7432c4a5 100644 --- a/src/datasets/infra/repositories/transformers/DatasetPayload.ts +++ b/src/datasets/infra/repositories/transformers/DatasetPayload.ts @@ -51,7 +51,7 @@ export interface MetadataBlocksPayload { } export interface MetadataBlockPayload { - name: string + name?: string fields: MetadataFieldPayload[] } diff --git a/src/datasets/infra/repositories/transformers/DatasetPreviewPayload.ts b/src/datasets/infra/repositories/transformers/DatasetPreviewPayload.ts index 3714082e..3c1c1e89 100644 --- a/src/datasets/infra/repositories/transformers/DatasetPreviewPayload.ts +++ b/src/datasets/infra/repositories/transformers/DatasetPreviewPayload.ts @@ -1,3 +1,5 @@ +import { MetadataBlocksPayload } from './DatasetPayload' + export interface DatasetPreviewPayload { global_id: string name: string @@ -17,6 +19,7 @@ export interface DatasetPreviewPayload { name_of_dataverse: string image_url?: string collections?: DatasetPreviewCollectionPayload[] + metadataBlocks?: MetadataBlocksPayload } export interface DatasetPreviewCollectionPayload { diff --git a/src/datasets/infra/repositories/transformers/datasetPreviewsTransformers.ts b/src/datasets/infra/repositories/transformers/datasetPreviewsTransformers.ts index 7d1afd43..a89a5740 100644 --- a/src/datasets/infra/repositories/transformers/datasetPreviewsTransformers.ts +++ b/src/datasets/infra/repositories/transformers/datasetPreviewsTransformers.ts @@ -7,6 +7,8 @@ import { CollectionSummary } from '../../../../collections/domain/models/Collect import { PublicationStatus } from '../../../../core/domain/models/PublicationStatus' import { CollectionItemType } from '../../../../collections/domain/models/CollectionItemType' import { MyDataDatasetPreviewPayload } from './MyDataDatasetPreviewPayload' +import { DatasetMetadataBlock } from '../../../domain/models/Dataset' +import { transformPayloadToDatasetMetadataBlocks } from './datasetTransformers' export const transformDatasetPreviewsResponseToDatasetPreviewSubset = ( response: AxiosResponse @@ -24,7 +26,8 @@ export const transformDatasetPreviewsResponseToDatasetPreviewSubset = ( } export const transformDatasetPreviewPayloadToDatasetPreview = ( - datasetPreviewPayload: DatasetPreviewPayload + datasetPreviewPayload: DatasetPreviewPayload, + keepRawFields = false ): DatasetPreview => { const publicationStatuses: PublicationStatus[] = [] datasetPreviewPayload.publicationStatuses.forEach((element) => { @@ -37,6 +40,9 @@ export const transformDatasetPreviewPayloadToDatasetPreview = ( displayName: collection.name }) ) + const metadataBlocks: DatasetMetadataBlock[] | undefined = datasetPreviewPayload.metadataBlocks + ? transformPayloadToDatasetMetadataBlocks(datasetPreviewPayload.metadataBlocks, keepRawFields) + : undefined return { type: CollectionItemType.DATASET, @@ -60,9 +66,9 @@ export const transformDatasetPreviewPayloadToDatasetPreview = ( parentCollectionName: datasetPreviewPayload.name_of_dataverse, ...(datasetPreviewPayload.image_url && { imageUrl: datasetPreviewPayload.image_url - }) }), - ...(collections && { collections }) + ...(collections && { collections }), + ...(metadataBlocks && { metadataBlocks }) } } diff --git a/src/datasets/infra/repositories/transformers/datasetTransformers.ts b/src/datasets/infra/repositories/transformers/datasetTransformers.ts index 49ac6a42..0d25ecab 100644 --- a/src/datasets/infra/repositories/transformers/datasetTransformers.ts +++ b/src/datasets/infra/repositories/transformers/datasetTransformers.ts @@ -343,7 +343,7 @@ export const transformPayloadToDatasetMetadataBlocks = ( return Object.keys(metadataBlocksPayload).map((metadataBlockKey) => { const metadataBlock = metadataBlocksPayload[metadataBlockKey] return { - name: metadataBlock.name, + name: metadataBlock.name ?? metadataBlockKey, fields: transformPayloadToDatasetMetadataFields(metadataBlock.fields, keepRawFields) } }) as DatasetMetadataBlocks From 23985cf7c57ea54b2dc2cfbe6a5e4817caa4b848 Mon Sep 17 00:00:00 2001 From: Vera Clemens Date: Tue, 29 Sep 2026 10:50:21 +0200 Subject: [PATCH 3/4] feat: add support for complex filter queries to `GetCollectionItems --- docs/useCases.md | 2 +- .../domain/models/CollectionSearchCriteria.ts | 6 ++--- .../repositories/CollectionsRepository.ts | 25 ++++++++++++------- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/docs/useCases.md b/docs/useCases.md index ad433a27..4a876601 100644 --- a/docs/useCases.md +++ b/docs/useCases.md @@ -366,7 +366,7 @@ This use case supports the following optional parameters depending on the search - **limit**: (number) Limit for pagination. - **offset**: (number) Offset for pagination. -- **collectionSearchCriteria**: ([CollectionSearchCriteria](../src/collections/domain/models/CollectionSearchCriteria.ts)) Supports filtering the collection items by different properties. +- **collectionSearchCriteria**: ([CollectionSearchCriteria](../src/collections/domain/models/CollectionSearchCriteria.ts)) Supports filtering the collection items by different properties. `filterQueries` may be a list of simple `key:value` filters or a single complete filter expression, which is sent unchanged and may contain parentheses, `AND`/`OR`, wildcards, ranges, and other search syntax. - **searchServiceName**: The search service name on which to execute the search (Optional). - **showTypeCounts**: If true, the response will include the count per object type (Optional). - **showCollections**: If true, dataset results will include a `collections` array containing [CollectionSummary](../src/collections/domain/models/CollectionSummary.ts) objects for their collections (Optional). diff --git a/src/collections/domain/models/CollectionSearchCriteria.ts b/src/collections/domain/models/CollectionSearchCriteria.ts index 13454e43..be6a4b3a 100644 --- a/src/collections/domain/models/CollectionSearchCriteria.ts +++ b/src/collections/domain/models/CollectionSearchCriteria.ts @@ -11,15 +11,13 @@ export enum OrderType { DESC = 'desc' } -export type FilterQuery = `${string}:${string}` - export class CollectionSearchCriteria { constructor( public readonly searchText?: string, public readonly itemTypes?: CollectionItemType[], public readonly sort?: SortType, public readonly order?: OrderType, - public readonly filterQueries?: FilterQuery[] + public readonly filterQueries?: string | string[] ) {} withSearchText(searchText: string | undefined): CollectionSearchCriteria { @@ -62,7 +60,7 @@ export class CollectionSearchCriteria { ) } - withFilterQueries(filterQueries: FilterQuery[] | undefined): CollectionSearchCriteria { + withFilterQueries(filterQueries: string | string[] | undefined): CollectionSearchCriteria { return new CollectionSearchCriteria( this.searchText, this.itemTypes, diff --git a/src/collections/infra/repositories/CollectionsRepository.ts b/src/collections/infra/repositories/CollectionsRepository.ts index 75c64c10..501ca915 100644 --- a/src/collections/infra/repositories/CollectionsRepository.ts +++ b/src/collections/infra/repositories/CollectionsRepository.ts @@ -525,18 +525,25 @@ export class CollectionsRepository extends ApiRepository implements ICollections } if (collectionSearchCriteria?.filterQueries) { - collectionSearchCriteria.filterQueries.forEach((filterQuery) => { - const idx = filterQuery.indexOf(':') - if (idx === -1) return // Invalid filter query, skip it + if (typeof collectionSearchCriteria.filterQueries === 'string') { + queryParams.append( + GetCollectionItemsQueryParams.FILTERQUERY, + collectionSearchCriteria.filterQueries + ) + } else { + collectionSearchCriteria.filterQueries.forEach((filterQuery) => { + const idx = filterQuery.indexOf(':') + if (idx === -1) return // Invalid filter query, skip it - const filterQueryKey = filterQuery.substring(0, idx).trim() - const filterQueryValue = filterQuery.substring(idx + 1).trim() + const filterQueryKey = filterQuery.substring(0, idx).trim() + const filterQueryValue = filterQuery.substring(idx + 1).trim() - const filterQueryValueWithQuotes = `"${filterQueryValue}"` - const filterQueryToSet = `${filterQueryKey}:${filterQueryValueWithQuotes}` + const filterQueryValueWithQuotes = `"${filterQueryValue}"` + const filterQueryToSet = `${filterQueryKey}:${filterQueryValueWithQuotes}` - queryParams.append(GetCollectionItemsQueryParams.FILTERQUERY, filterQueryToSet) - }) + queryParams.append(GetCollectionItemsQueryParams.FILTERQUERY, filterQueryToSet) + }) + } } } From 7dc1ba3b2c37ee08d55ef0ab71b059d9a4b0e190 Mon Sep 17 00:00:00 2001 From: Vera Clemens Date: Tue, 29 Sep 2026 11:02:04 +0200 Subject: [PATCH 4/4] test: add support for complex filter queries to `GetCollectionItems --- .../collections/CollectionsRepository.test.ts | 41 ++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/test/unit/collections/CollectionsRepository.test.ts b/test/unit/collections/CollectionsRepository.test.ts index 075034cc..a2cdb31f 100644 --- a/test/unit/collections/CollectionsRepository.test.ts +++ b/test/unit/collections/CollectionsRepository.test.ts @@ -46,7 +46,8 @@ import { } from '../../testHelpers/collections/collectionItemsFacetsHelper' import { OrderType, - SortType + SortType, + CollectionSearchCriteria } from '../../../src/collections/domain/models/CollectionSearchCriteria' import { RoleAlias } from '../../../src/roles/domain/models/RoleAlias' @@ -654,6 +655,44 @@ describe('CollectionsRepository', () => { expect(actual).toStrictEqual(testItemSubset) }) + + + test('should preserve structured filter query syntax', async () => { + const getSpy = jest.spyOn(axios, 'get').mockResolvedValue(testItemPreviewsResponse) + + await sut.getCollectionItems( + testCollectionModel.alias, + undefined, + undefined, + new CollectionSearchCriteria().withFilterQueries([ + 'subject_ss:Medicine, Health and Life Sciences' + ]) + ) + + const arrayRequestConfig = getSpy.mock.calls[0]?.[1] as { params: URLSearchParams } + // fq filter value should be wrapped in quotes + expect(arrayRequestConfig.params.getAll(GetCollectionItemsQueryParams.FILTERQUERY)).toEqual([ + 'subject_ss:"Medicine, Health and Life Sciences"' + ]) + + const rawFilterQuery = + '(subject_ss:Medicine OR subject_ss:Health) AND subtreePath:*/42 AND abc:[0 TO 100]' + await sut.getCollectionItems( + testCollectionModel.alias, + undefined, + undefined, + new CollectionSearchCriteria().withFilterQueries(rawFilterQuery) + ) + + const rawRequestConfig = getSpy.mock.calls[1]?.[1] as { params: URLSearchParams } + // fq filter should be unchanged + expect(rawRequestConfig.params.getAll(GetCollectionItemsQueryParams.FILTERQUERY)).toEqual([ + rawFilterQuery + ]) + + getSpy.mockRestore() + }) + test('should return item previews when providing pagination params and response is successful', async () => { jest.spyOn(axios, 'get').mockResolvedValue(testItemPreviewsResponse)