diff --git a/docs/useCases.md b/docs/useCases.md index 1b1f25ed..8d6659f9 100644 --- a/docs/useCases.md +++ b/docs/useCases.md @@ -423,6 +423,12 @@ 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). +- **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 cf1fad5b..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' @@ -59,7 +59,13 @@ export interface ICollectionsRepository { limit?: number, selectedPage?: number, searchText?: string, - otherUserName?: string + otherUserName?: string, + showCollections?: boolean, + metadataFields?: `${string}:${string}`[], + keepRawFields?: boolean, + 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 96522783..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 @@ -21,6 +22,12 @@ export class GetMyDataCollectionItems implements UseCase} */ async execute( @@ -30,7 +37,13 @@ export class GetMyDataCollectionItems implements UseCase { return this.collectionsRepository.getMyDataCollectionItems( roleIds, @@ -39,7 +52,13 @@ export class GetMyDataCollectionItems implements UseCase { const queryParams = new URLSearchParams() @@ -329,6 +340,26 @@ export class CollectionsRepository extends ApiRepository implements ICollections queryParams.set(GetMyDataCollectionItemsQueryParams.USER_IDENTIFIER, userIdentifier) } + if (showCollections) { + queryParams.set(GetMyDataCollectionItemsQueryParams.SHOW_COLLECTIONS, 'true') + } + + metadataFields?.forEach((metadataField) => { + queryParams.append(GetMyDataCollectionItemsQueryParams.METADATA_FIELDS, metadataField) + }) + + if (filterQueries) { + this.applyFilterQueriesToQueryParams(queryParams, filterQueries) + } + + if (sort) { + queryParams.set(GetMyDataCollectionItemsQueryParams.SORT, sort) + } + + if (order) { + queryParams.set(GetMyDataCollectionItemsQueryParams.ORDER, order) + } + collectionItemTypes.forEach((itemType) => { let mappedItemType: string @@ -357,7 +388,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 @@ -510,7 +541,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 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 6b11529d..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 @@ -18,4 +20,12 @@ export interface MyDataDatasetPreviewPayload { user_roles: string[] image_url?: string published_at?: string + collections?: MyDataDatasetCollectionPayload[] + metadataBlocks?: MetadataBlocksPayload +} + +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..cd5e0717 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 @@ -56,12 +59,23 @@ export const transformDatasetPreviewPayloadToDatasetPreview = ( } export const transformMyDataDatasetPreviewPayloadToDatasetPreview = ( - datasetPreviewPayload: MyDataDatasetPreviewPayload + datasetPreviewPayload: MyDataDatasetPreviewPayload, + keepRawFields = false ): DatasetPreview => { const publicationStatuses: PublicationStatus[] = [] 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 + }) + ) + const metadataBlocks: DatasetMetadataBlock[] | undefined = datasetPreviewPayload.metadataBlocks + ? transformPayloadToDatasetMetadataBlocks(datasetPreviewPayload.metadataBlocks, keepRawFields) + : undefined return { type: CollectionItemType.DATASET, persistentId: datasetPreviewPayload.global_id, @@ -85,6 +99,8 @@ export const transformMyDataDatasetPreviewPayloadToDatasetPreview = ( ...(datasetPreviewPayload.image_url && { imageUrl: datasetPreviewPayload.image_url }), - userRoles: datasetPreviewPayload.user_roles + userRoles: datasetPreviewPayload.user_roles, + ...(collections && { collections }), + ...(metadataBlocks && { metadataBlocks }) } }