From e326a1392b594571f10314e477ff94e15d5df7db Mon Sep 17 00:00:00 2001 From: Vera Clemens Date: Tue, 29 Sep 2026 13:24:34 +0200 Subject: [PATCH 1/4] feat: add support for including dataset collections to `GetMyDataCollectionItems` --- docs/useCases.md | 1 + .../domain/repositories/ICollectionsRepository.ts | 3 ++- .../domain/useCases/GetMyDataCollectionItems.ts | 7 +++++-- .../infra/repositories/CollectionsRepository.ts | 10 ++++++++-- .../transformers/MyDataDatasetPreviewPayload.ts | 7 +++++++ .../transformers/datasetPreviewsTransformers.ts | 15 +++++++++++++-- 6 files changed, 36 insertions(+), 7 deletions(-) diff --git a/docs/useCases.md b/docs/useCases.md index 1b1f25ed..83bad7b1 100644 --- a/docs/useCases.md +++ b/docs/useCases.md @@ -423,6 +423,7 @@ This use case supports the following optional parameters depending on the search - **selectedPage**: (number) the page of results to be returned. (default is 1) - **searchText** is an optional string to filter the results by. - **otherUserName** is an optional string to return the collection items of another user. If not set, the calling user will be used. _Only superusers can use this parameter_. +- **showCollections**: If true, dataset results will include a `collections` array containing [CollectionSummary](../src/collections/domain/models/CollectionSummary.ts) objects for their collections (Optional). The `CollectionItemSubset`returned instance contains a property called `totalItemCount` which is necessary for pagination. diff --git a/src/collections/domain/repositories/ICollectionsRepository.ts b/src/collections/domain/repositories/ICollectionsRepository.ts index cf1fad5b..c62ddb55 100644 --- a/src/collections/domain/repositories/ICollectionsRepository.ts +++ b/src/collections/domain/repositories/ICollectionsRepository.ts @@ -59,7 +59,8 @@ export interface ICollectionsRepository { limit?: number, selectedPage?: number, searchText?: string, - otherUserName?: string + otherUserName?: string, + showCollections?: boolean ): Promise updateCollection( collectionIdOrAlias: number | string, diff --git a/src/collections/domain/useCases/GetMyDataCollectionItems.ts b/src/collections/domain/useCases/GetMyDataCollectionItems.ts index 96522783..0b556c88 100644 --- a/src/collections/domain/useCases/GetMyDataCollectionItems.ts +++ b/src/collections/domain/useCases/GetMyDataCollectionItems.ts @@ -21,6 +21,7 @@ export class GetMyDataCollectionItems implements UseCase} */ async execute( @@ -30,7 +31,8 @@ export class GetMyDataCollectionItems implements UseCase { return this.collectionsRepository.getMyDataCollectionItems( roleIds, @@ -39,7 +41,8 @@ export class GetMyDataCollectionItems implements UseCase { const queryParams = new URLSearchParams() @@ -329,6 +331,10 @@ export class CollectionsRepository extends ApiRepository implements ICollections queryParams.set(GetMyDataCollectionItemsQueryParams.USER_IDENTIFIER, userIdentifier) } + if (showCollections) { + queryParams.set(GetMyDataCollectionItemsQueryParams.SHOW_COLLECTIONS, 'true') + } + collectionItemTypes.forEach((itemType) => { let mappedItemType: string diff --git a/src/datasets/infra/repositories/transformers/MyDataDatasetPreviewPayload.ts b/src/datasets/infra/repositories/transformers/MyDataDatasetPreviewPayload.ts index 6b11529d..94b6f281 100644 --- a/src/datasets/infra/repositories/transformers/MyDataDatasetPreviewPayload.ts +++ b/src/datasets/infra/repositories/transformers/MyDataDatasetPreviewPayload.ts @@ -18,4 +18,11 @@ export interface MyDataDatasetPreviewPayload { user_roles: string[] image_url?: string published_at?: string + collections?: MyDataDatasetCollectionPayload[] +} + +export interface MyDataDatasetCollectionPayload { + 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..7482897f 100644 --- a/src/datasets/infra/repositories/transformers/datasetPreviewsTransformers.ts +++ b/src/datasets/infra/repositories/transformers/datasetPreviewsTransformers.ts @@ -5,7 +5,10 @@ import { DatasetPreviewSubset } from '../../../domain/models/DatasetPreviewSubse import { DatasetPreviewPayload } from './DatasetPreviewPayload' import { PublicationStatus } from '../../../../core/domain/models/PublicationStatus' import { CollectionItemType } from '../../../../collections/domain/models/CollectionItemType' -import { MyDataDatasetPreviewPayload } from './MyDataDatasetPreviewPayload' +import { + MyDataDatasetCollectionPayload, + MyDataDatasetPreviewPayload +} from './MyDataDatasetPreviewPayload' export const transformDatasetPreviewsResponseToDatasetPreviewSubset = ( response: AxiosResponse @@ -62,6 +65,13 @@ export const transformMyDataDatasetPreviewPayloadToDatasetPreview = ( datasetPreviewPayload.publicationStatuses.forEach((element) => { publicationStatuses.push(element as unknown as PublicationStatus) }) + const collections: CollectionSummary[] | undefined = datasetPreviewPayload.collections?.map( + (collection: MyDataDatasetCollectionPayload) => ({ + id: collection.id, + alias: collection.alias, + displayName: collection.name + }) + ) return { type: CollectionItemType.DATASET, persistentId: datasetPreviewPayload.global_id, @@ -85,6 +95,7 @@ export const transformMyDataDatasetPreviewPayloadToDatasetPreview = ( ...(datasetPreviewPayload.image_url && { imageUrl: datasetPreviewPayload.image_url }), - userRoles: datasetPreviewPayload.user_roles + userRoles: datasetPreviewPayload.user_roles, + ...(collections && { collections }) } } From e8f56cc8cacf8cbe7e2f2f8948adb1ffa963eac6 Mon Sep 17 00:00:00 2001 From: Vera Clemens Date: Tue, 29 Sep 2026 13:27:55 +0200 Subject: [PATCH 2/4] feat: add support for metadata fields to `GetMyDataCollectionItems` --- docs/useCases.md | 2 ++ .../domain/repositories/ICollectionsRepository.ts | 4 +++- .../domain/useCases/GetMyDataCollectionItems.ts | 10 ++++++++-- .../infra/repositories/CollectionsRepository.ts | 13 ++++++++++--- .../transformers/collectionTransformers.ts | 6 ++++-- .../transformers/MyDataDatasetPreviewPayload.ts | 3 +++ .../transformers/datasetPreviewsTransformers.ts | 9 +++++++-- 7 files changed, 37 insertions(+), 10 deletions(-) diff --git a/docs/useCases.md b/docs/useCases.md index 83bad7b1..3d70247e 100644 --- a/docs/useCases.md +++ b/docs/useCases.md @@ -424,6 +424,8 @@ This use case supports the following optional parameters depending on the search - **searchText** is an optional string to filter the results by. - **otherUserName** is an optional string to return the collection items of another user. If not set, the calling user will be used. _Only superusers can use this parameter_. - **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). The `CollectionItemSubset`returned instance contains a property called `totalItemCount` which is necessary for pagination. diff --git a/src/collections/domain/repositories/ICollectionsRepository.ts b/src/collections/domain/repositories/ICollectionsRepository.ts index c62ddb55..19a0275b 100644 --- a/src/collections/domain/repositories/ICollectionsRepository.ts +++ b/src/collections/domain/repositories/ICollectionsRepository.ts @@ -60,7 +60,9 @@ export interface ICollectionsRepository { selectedPage?: number, searchText?: string, otherUserName?: string, - showCollections?: boolean + showCollections?: boolean, + metadataFields?: `${string}:${string}`[], + keepRawFields?: boolean ): Promise updateCollection( collectionIdOrAlias: number | string, diff --git a/src/collections/domain/useCases/GetMyDataCollectionItems.ts b/src/collections/domain/useCases/GetMyDataCollectionItems.ts index 0b556c88..a2c28eee 100644 --- a/src/collections/domain/useCases/GetMyDataCollectionItems.ts +++ b/src/collections/domain/useCases/GetMyDataCollectionItems.ts @@ -22,6 +22,8 @@ export class GetMyDataCollectionItems implements UseCase} */ async execute( @@ -32,7 +34,9 @@ export class GetMyDataCollectionItems implements UseCase { return this.collectionsRepository.getMyDataCollectionItems( roleIds, @@ -42,7 +46,9 @@ export class GetMyDataCollectionItems implements UseCase { const queryParams = new URLSearchParams() @@ -335,6 +338,10 @@ export class CollectionsRepository extends ApiRepository implements ICollections queryParams.set(GetMyDataCollectionItemsQueryParams.SHOW_COLLECTIONS, 'true') } + metadataFields?.forEach((metadataField) => { + queryParams.append(GetMyDataCollectionItemsQueryParams.METADATA_FIELDS, metadataField) + }) + collectionItemTypes.forEach((itemType) => { let mappedItemType: string @@ -363,7 +370,7 @@ export class CollectionsRepository extends ApiRepository implements ICollections if (response.data.success !== true) { throw new ReadError(response.data.error_message) } - return transformMyDataResponseToCollectionItemSubset(response) + return transformMyDataResponseToCollectionItemSubset(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..7607c898 100644 --- a/src/collections/infra/repositories/transformers/collectionTransformers.ts +++ b/src/collections/infra/repositories/transformers/collectionTransformers.ts @@ -182,7 +182,8 @@ export const transformCollectionLinksResponseToCollectionLinks = ( } } export const transformMyDataResponseToCollectionItemSubset = ( - response: AxiosResponse + response: AxiosResponse, + keepRawFields = false ): MyDataCollectionItemSubset => { const responseDataPayload = response.data.data const itemsPayload = responseDataPayload.items @@ -205,7 +206,8 @@ export const transformMyDataResponseToCollectionItemSubset = ( } else if (itemPayload.type === 'dataset') { items.push( transformMyDataDatasetPreviewPayloadToDatasetPreview( - itemPayload as MyDataDatasetPreviewPayload + itemPayload as MyDataDatasetPreviewPayload, + keepRawFields ) ) } else if (itemPayload.type === 'dataverse') { diff --git a/src/datasets/infra/repositories/transformers/MyDataDatasetPreviewPayload.ts b/src/datasets/infra/repositories/transformers/MyDataDatasetPreviewPayload.ts index 94b6f281..c19c3b51 100644 --- a/src/datasets/infra/repositories/transformers/MyDataDatasetPreviewPayload.ts +++ b/src/datasets/infra/repositories/transformers/MyDataDatasetPreviewPayload.ts @@ -1,3 +1,5 @@ +import { MetadataBlocksPayload } from './DatasetPayload' + export interface MyDataDatasetPreviewPayload { name: string type: string @@ -19,6 +21,7 @@ export interface MyDataDatasetPreviewPayload { image_url?: string published_at?: string collections?: MyDataDatasetCollectionPayload[] + metadataBlocks?: MetadataBlocksPayload } export interface MyDataDatasetCollectionPayload { diff --git a/src/datasets/infra/repositories/transformers/datasetPreviewsTransformers.ts b/src/datasets/infra/repositories/transformers/datasetPreviewsTransformers.ts index 7482897f..cd5e0717 100644 --- a/src/datasets/infra/repositories/transformers/datasetPreviewsTransformers.ts +++ b/src/datasets/infra/repositories/transformers/datasetPreviewsTransformers.ts @@ -59,7 +59,8 @@ export const transformDatasetPreviewPayloadToDatasetPreview = ( } export const transformMyDataDatasetPreviewPayloadToDatasetPreview = ( - datasetPreviewPayload: MyDataDatasetPreviewPayload + datasetPreviewPayload: MyDataDatasetPreviewPayload, + keepRawFields = false ): DatasetPreview => { const publicationStatuses: PublicationStatus[] = [] datasetPreviewPayload.publicationStatuses.forEach((element) => { @@ -72,6 +73,9 @@ export const transformMyDataDatasetPreviewPayloadToDatasetPreview = ( displayName: collection.name }) ) + const metadataBlocks: DatasetMetadataBlock[] | undefined = datasetPreviewPayload.metadataBlocks + ? transformPayloadToDatasetMetadataBlocks(datasetPreviewPayload.metadataBlocks, keepRawFields) + : undefined return { type: CollectionItemType.DATASET, persistentId: datasetPreviewPayload.global_id, @@ -96,6 +100,7 @@ export const transformMyDataDatasetPreviewPayloadToDatasetPreview = ( imageUrl: datasetPreviewPayload.image_url }), userRoles: datasetPreviewPayload.user_roles, - ...(collections && { collections }) + ...(collections && { collections }), + ...(metadataBlocks && { metadataBlocks }) } } From d01790c0d52bd4f0495115ac0f8730758568d188 Mon Sep 17 00:00:00 2001 From: Vera Clemens Date: Tue, 29 Sep 2026 13:44:08 +0200 Subject: [PATCH 3/4] feat: add support for filter queries to `GetMyDataCollectionItems` --- docs/useCases.md | 1 + .../repositories/ICollectionsRepository.ts | 3 ++- .../useCases/GetMyDataCollectionItems.ts | 7 ++++-- .../repositories/CollectionsRepository.ts | 23 ++++++++++++++++--- 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/docs/useCases.md b/docs/useCases.md index 3d70247e..90dbafa3 100644 --- a/docs/useCases.md +++ b/docs/useCases.md @@ -426,6 +426,7 @@ This use case supports the following optional parameters depending on the search - **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). +- **filterQueries**: A list of simple `key:value` filters or a single complete filter expression. A single string is sent unchanged and may contain parentheses, `AND`/`OR`, wildcards, ranges, and other search syntax (Optional). The `CollectionItemSubset`returned instance contains a property called `totalItemCount` which is necessary for pagination. diff --git a/src/collections/domain/repositories/ICollectionsRepository.ts b/src/collections/domain/repositories/ICollectionsRepository.ts index 19a0275b..7d29f2fa 100644 --- a/src/collections/domain/repositories/ICollectionsRepository.ts +++ b/src/collections/domain/repositories/ICollectionsRepository.ts @@ -62,7 +62,8 @@ export interface ICollectionsRepository { otherUserName?: string, showCollections?: boolean, metadataFields?: `${string}:${string}`[], - keepRawFields?: boolean + keepRawFields?: boolean, + filterQueries?: string | string[] ): Promise updateCollection( collectionIdOrAlias: number | string, diff --git a/src/collections/domain/useCases/GetMyDataCollectionItems.ts b/src/collections/domain/useCases/GetMyDataCollectionItems.ts index a2c28eee..d6f685b8 100644 --- a/src/collections/domain/useCases/GetMyDataCollectionItems.ts +++ b/src/collections/domain/useCases/GetMyDataCollectionItems.ts @@ -24,6 +24,7 @@ export class GetMyDataCollectionItems implements UseCase} */ async execute( @@ -36,7 +37,8 @@ export class GetMyDataCollectionItems implements UseCase { return this.collectionsRepository.getMyDataCollectionItems( roleIds, @@ -48,7 +50,8 @@ export class GetMyDataCollectionItems implements UseCase { const queryParams = new URLSearchParams() @@ -342,6 +344,10 @@ export class CollectionsRepository extends ApiRepository implements ICollections queryParams.append(GetMyDataCollectionItemsQueryParams.METADATA_FIELDS, metadataField) }) + if (filterQueries) { + this.applyFilterQueriesToQueryParams(queryParams, filterQueries) + } + collectionItemTypes.forEach((itemType) => { let mappedItemType: string @@ -523,7 +529,18 @@ export class CollectionsRepository extends ApiRepository implements ICollections } if (collectionSearchCriteria?.filterQueries) { - collectionSearchCriteria.filterQueries.forEach((filterQuery) => { + this.applyFilterQueriesToQueryParams(queryParams, collectionSearchCriteria.filterQueries) + } + } + + private applyFilterQueriesToQueryParams( + queryParams: URLSearchParams, + filterQueries: string | string[] + ) { + if (typeof filterQueries === 'string') { + queryParams.append(GetCollectionItemsQueryParams.FILTERQUERY, filterQueries) + } else { + filterQueries.forEach((filterQuery) => { const idx = filterQuery.indexOf(':') if (idx === -1) return // Invalid filter query, skip it From 679d83e8ed1c6d59bef0d8a9c6c2ff0ee47f5ee5 Mon Sep 17 00:00:00 2001 From: Vera Clemens Date: Tue, 29 Sep 2026 13:46:49 +0200 Subject: [PATCH 4/4] feat: add support for sorting to `GetMyDataCollectionItems` --- docs/useCases.md | 2 ++ .../repositories/ICollectionsRepository.ts | 6 ++++-- .../domain/useCases/GetMyDataCollectionItems.ts | 11 +++++++++-- .../infra/repositories/CollectionsRepository.ts | 16 ++++++++++++++-- 4 files changed, 29 insertions(+), 6 deletions(-) diff --git a/docs/useCases.md b/docs/useCases.md index 90dbafa3..8d6659f9 100644 --- a/docs/useCases.md +++ b/docs/useCases.md @@ -427,6 +427,8 @@ This use case supports the following optional parameters depending on the search - **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). - **filterQueries**: A list of simple `key:value` filters or a single complete filter expression. A single string is sent unchanged and may contain parentheses, `AND`/`OR`, wildcards, ranges, and other search syntax (Optional). +- **sort**: The field by which to sort the results (Optional). +- **order**: The sort order, either ascending or descending (Optional). The `CollectionItemSubset`returned instance contains a property called `totalItemCount` which is necessary for pagination. diff --git a/src/collections/domain/repositories/ICollectionsRepository.ts b/src/collections/domain/repositories/ICollectionsRepository.ts index 7d29f2fa..7a054144 100644 --- a/src/collections/domain/repositories/ICollectionsRepository.ts +++ b/src/collections/domain/repositories/ICollectionsRepository.ts @@ -5,7 +5,7 @@ import { CollectionFacet } from '../models/CollectionFacet' import { FeaturedItem } from '../models/FeaturedItem' import { CollectionItemSubset } from '../models/CollectionItemSubset' import { MyDataCollectionItemSubset } from '../models/MyDataCollectionItemSubset' -import { CollectionSearchCriteria } from '../models/CollectionSearchCriteria' +import { CollectionSearchCriteria, OrderType, SortType } from '../models/CollectionSearchCriteria' import { CollectionUserPermissions } from '../models/CollectionUserPermissions' import { PublicationStatus } from '../../../core/domain/models/PublicationStatus' import { CollectionItemType } from '../../../collections/domain/models/CollectionItemType' @@ -63,7 +63,9 @@ export interface ICollectionsRepository { showCollections?: boolean, metadataFields?: `${string}:${string}`[], keepRawFields?: boolean, - filterQueries?: string | string[] + filterQueries?: string | string[], + sort?: SortType, + order?: OrderType ): Promise updateCollection( collectionIdOrAlias: number | string, diff --git a/src/collections/domain/useCases/GetMyDataCollectionItems.ts b/src/collections/domain/useCases/GetMyDataCollectionItems.ts index d6f685b8..bccfcc43 100644 --- a/src/collections/domain/useCases/GetMyDataCollectionItems.ts +++ b/src/collections/domain/useCases/GetMyDataCollectionItems.ts @@ -3,6 +3,7 @@ import { MyDataCollectionItemSubset } from '../models/MyDataCollectionItemSubset import { ICollectionsRepository } from '../repositories/ICollectionsRepository' import { CollectionItemType } from '../../../collections/domain/models/CollectionItemType' import { PublicationStatus } from '../../../core/domain/models/PublicationStatus' +import { OrderType, SortType } from '../models/CollectionSearchCriteria' export class GetMyDataCollectionItems implements UseCase { private collectionsRepository: ICollectionsRepository @@ -25,6 +26,8 @@ export class GetMyDataCollectionItems implements UseCase} */ async execute( @@ -38,7 +41,9 @@ export class GetMyDataCollectionItems implements UseCase { return this.collectionsRepository.getMyDataCollectionItems( roleIds, @@ -51,7 +56,9 @@ export class GetMyDataCollectionItems implements UseCase { const queryParams = new URLSearchParams() @@ -348,6 +352,14 @@ export class CollectionsRepository extends ApiRepository implements ICollections this.applyFilterQueriesToQueryParams(queryParams, filterQueries) } + if (sort) { + queryParams.set(GetMyDataCollectionItemsQueryParams.SORT, sort) + } + + if (order) { + queryParams.set(GetMyDataCollectionItemsQueryParams.ORDER, order) + } + collectionItemTypes.forEach((itemType) => { let mappedItemType: string