diff --git a/docs/useCases.md b/docs/useCases.md index f77a40e1..21ba1424 100644 --- a/docs/useCases.md +++ b/docs/useCases.md @@ -17,6 +17,7 @@ The different use cases currently available in the package are classified below, - [List My Data Collection Items](#list-my-data-collection-items) - [Get Collection Featured Items](#get-collection-featured-items) - [Get Collections for Linking](#get-collections-for-linking) + - [Get Collections for Creating](#get-collections-for-creating) - [Collections write use cases](#collections-write-use-cases) - [Create a Collection](#create-a-collection) - [Update a Collection](#update-a-collection) @@ -409,6 +410,46 @@ Notes: - When the first argument is `'collection'`, the second argument can be a numeric collection id or a collection alias. - When the first argument is `'dataset'`, the second argument must be the dataset persistent identifier string (e.g., `doi:...`). +#### Get Collections for Creating + +Returns an array of [CollectionSummary](../src/collections/domain/models/CollectionSummary.ts) (id, alias, displayName) representing the Dataverse collections which an authenticated user may create a new dataset in. + +##### Example calls: + +```typescript +import { getCollectionsForCreating } from '@iqss/dataverse-client-javascript' + +/* ... */ + +// Case 1: For the user who is currently authenticated +getCollectionsForCreating + .execute() + .then((collections) => { + // collections: CollectionSummary[] + /* ... */ + }) + .catch((error: Error) => { + /* ... */ + }) + +/* ... */ + +// Case 2: For a given user (by username) +const username = 'anotherUser' + +getCollectionsForCreating + .execute(username) + .then((collections) => { + // collections: CollectionSummary[] + /* ... */ + }) + .catch((error: Error) => { + /* ... */ + }) +``` + +_See [use case](../src/collections/domain/useCases/GetCollectionsForCreating.ts) implementation_. + ### Collections Write Use Cases #### Create a Collection diff --git a/src/collections/domain/repositories/ICollectionsRepository.ts b/src/collections/domain/repositories/ICollectionsRepository.ts index bc8960c8..a7076293 100644 --- a/src/collections/domain/repositories/ICollectionsRepository.ts +++ b/src/collections/domain/repositories/ICollectionsRepository.ts @@ -68,4 +68,5 @@ export interface ICollectionsRepository { searchTerm: string, alreadyLinked: boolean ): Promise + getCollectionsForCreating(userIdentifier?: string): Promise } diff --git a/src/collections/domain/useCases/GetCollectionsForCreating.ts b/src/collections/domain/useCases/GetCollectionsForCreating.ts new file mode 100644 index 00000000..d0310320 --- /dev/null +++ b/src/collections/domain/useCases/GetCollectionsForCreating.ts @@ -0,0 +1,21 @@ +import { UseCase } from '../../../core/domain/useCases/UseCase' +import { ICollectionsRepository } from '../repositories/ICollectionsRepository' +import { CollectionSummary } from '../models/CollectionSummary' + +export class GetCollectionsForCreating implements UseCase { + private collectionsRepository: ICollectionsRepository + + constructor(collectionsRepository: ICollectionsRepository) { + this.collectionsRepository = collectionsRepository + } + + /** + * Returns an array of CollectionSummary (id, alias, displayName) of the collections an authenticated user can create a Dataset in. + * @param userIdentifier - May be used by a superuser to get the collections for a specific user. + */ + async execute( + userIdentifier?: string + ): Promise { + return await this.collectionsRepository.getCollectionsForCreating(userIdentifier) + } +} diff --git a/src/collections/index.ts b/src/collections/index.ts index 59e2e50b..54519357 100644 --- a/src/collections/index.ts +++ b/src/collections/index.ts @@ -16,6 +16,7 @@ import { LinkCollection } from './domain/useCases/LinkCollection' import { UnlinkCollection } from './domain/useCases/UnlinkCollection' import { GetCollectionLinks } from './domain/useCases/GetCollectionLinks' import { GetCollectionsForLinking } from './domain/useCases/GetCollectionsForLinking' +import { GetCollectionsForCreating } from './domain/useCases/GetCollectionsForCreating' const collectionsRepository = new CollectionsRepository() @@ -36,6 +37,7 @@ const linkCollection = new LinkCollection(collectionsRepository) const unlinkCollection = new UnlinkCollection(collectionsRepository) const getCollectionLinks = new GetCollectionLinks(collectionsRepository) const getCollectionsForLinking = new GetCollectionsForLinking(collectionsRepository) +const getCollectionsForCreating = new GetCollectionsForCreating(collectionsRepository) export { getCollection, @@ -54,7 +56,8 @@ export { linkCollection, unlinkCollection, getCollectionLinks, - getCollectionsForLinking + getCollectionsForLinking, + getCollectionsForCreating } export { Collection, CollectionInputLevel } from './domain/models/Collection' export { CollectionFacet } from './domain/models/CollectionFacet' diff --git a/src/collections/infra/repositories/CollectionsRepository.ts b/src/collections/infra/repositories/CollectionsRepository.ts index e0e459b0..ec5383cd 100644 --- a/src/collections/infra/repositories/CollectionsRepository.ts +++ b/src/collections/infra/repositories/CollectionsRepository.ts @@ -528,4 +528,30 @@ export class CollectionsRepository extends ApiRepository implements ICollections throw error }) } + + public async getCollectionsForCreating(userIdentifier?: string): Promise { + const queryParams = new URLSearchParams() + + if (userIdentifier) { + queryParams.set(GetMyDataCollectionItemsQueryParams.USER_IDENTIFIER, userIdentifier) + } + + return this.doGet("/mydata/retrieve/collectionList", true, queryParams) + .then((response) => { + const payload = response.data.data.items as { + id: number + alias: string + name: string + }[] + + return payload.map((item) => ({ + id: item.id, + alias: item.alias, + displayName: item.name + })) + }) + .catch((error) => { + throw error + }) + } } diff --git a/test/unit/collections/GetCollectionsForCreating.test.ts b/test/unit/collections/GetCollectionsForCreating.test.ts new file mode 100644 index 00000000..d4042b3b --- /dev/null +++ b/test/unit/collections/GetCollectionsForCreating.test.ts @@ -0,0 +1,28 @@ +import { ICollectionsRepository } from '../../../src/collections/domain/repositories/ICollectionsRepository' +import { GetCollectionsForCreating } from '../../../src/collections/domain/useCases/GetCollectionsForCreating' +import { CollectionSummary, ReadError } from '../../../src' + +const sample: CollectionSummary[] = [ + { id: 1, alias: 'col1', displayName: 'Collection 1' }, + { id: 2, alias: 'col2', displayName: 'Collection 2' } +] + +describe('GetCollectionsForCreating', () => { + test('should return collections for creating on success', async () => { + const repo: ICollectionsRepository = {} as ICollectionsRepository + repo.getCollectionsForCreating = jest.fn().mockResolvedValue(sample) + + const uc = new GetCollectionsForCreating(repo) + await expect(uc.execute('testUser')).resolves.toEqual(sample) + expect(repo.getCollectionsForCreating).toHaveBeenCalledWith('@testUser') + }) + + test('should return error result on repository error', async () => { + const repo: ICollectionsRepository = {} as ICollectionsRepository + repo.getCollectionsForCreating = jest.fn().mockRejectedValue(new ReadError('x')) + + const uc = new GetCollectionsForCreating(repo) + await expect(uc.execute('testUser')).rejects.toThrow(ReadError) + expect(repo.getCollectionsForCreating).toHaveBeenCalledWith('@testUser') + }) +})