Skip to content

Commit aa68c68

Browse files
committed
Merge Conflict
2 parents cad29c2 + 406416c commit aa68c68

File tree

19 files changed

+422
-22
lines changed

19 files changed

+422
-22
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ This changelog follows the principles of [Keep a Changelog](https://keepachangel
88

99
### Added
1010

11+
- New Use Case: [Get Collections For Linking Use Case](./docs/useCases.md#get-collections-for-linking).
12+
1113
### Changed
1214

1315
### Fixed

docs/useCases.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ The different use cases currently available in the package are classified below,
1616
- [List All Collection Items](#list-all-collection-items)
1717
- [List My Data Collection Items](#list-my-data-collection-items)
1818
- [Get Collection Featured Items](#get-collection-featured-items)
19+
- [Get Collections for Linking](#get-collections-for-linking)
1920
- [Collections write use cases](#collections-write-use-cases)
2021
- [Create a Collection](#create-a-collection)
2122
- [Update a Collection](#update-a-collection)
@@ -336,6 +337,69 @@ The `collectionIdOrAlias` is a generic collection identifier, which can be eithe
336337

337338
If no collection identifier is specified, the default collection identifier; `:root` will be used. If you want to search for a different collection, you must add the collection identifier as a parameter in the use case call.
338339

340+
#### Get Collections for Linking
341+
342+
Returns an array of [CollectionSummary](../src/collections/domain/models/CollectionSummary.ts) (id, alias, displayName) representing the Dataverse collections to which a given Dataverse collection or Dataset may be linked.
343+
344+
This use case supports an optional `searchTerm` to filter by collection name.
345+
346+
##### Example calls:
347+
348+
```typescript
349+
import { getCollectionsForLinking } from '@iqss/dataverse-client-javascript'
350+
351+
/* ... */
352+
353+
// Case 1: For a given Dataverse collection (by numeric id or alias)
354+
const collectionIdOrAlias: number | string = 'collectionAlias' // or 123
355+
const searchTerm = 'searchOn'
356+
357+
getCollectionsForLinking
358+
.execute('collection', collectionIdOrAlias, searchTerm)
359+
.then((collections) => {
360+
// collections: CollectionSummary[]
361+
/* ... */
362+
})
363+
.catch((error: Error) => {
364+
/* ... */
365+
})
366+
367+
/* ... */
368+
369+
// Case 2: For a given Dataset (by persistent identifier)
370+
const persistentId = 'doi:10.5072/FK2/J8SJZB'
371+
372+
getCollectionsForLinking
373+
.execute('dataset', persistentId, searchTerm)
374+
.then((collections) => {
375+
// collections: CollectionSummary[]
376+
/* ... */
377+
})
378+
.catch((error: Error) => {
379+
/* ... */
380+
})
381+
382+
// Case 3: [alreadyLinked] Optional flag. When true, returns collections currently linked (candidates to unlink). Defaults to false.
383+
const alreadyLinked = true
384+
385+
getCollectionsForLinking
386+
.execute('dataset', persistentId, searchTerm, alreadyLinked)
387+
.then((collections) => {
388+
// collections: CollectionSummary[]
389+
/* ... */
390+
})
391+
.catch((error: Error) => {
392+
/* ... */
393+
})
394+
```
395+
396+
_See [use case](../src/collections/domain/useCases/GetCollectionsForLinking.ts) implementation_.
397+
398+
Notes:
399+
400+
- When the first argument is `'collection'`, the second argument can be a numeric collection id or a collection alias.
401+
- When the first argument is `'dataset'`, the second argument must be the dataset persistent identifier string (e.g., `doi:...`).
402+
339403
### Collections Write Use Cases
340404

341405
#### Create a Collection

src/collections/domain/repositories/ICollectionsRepository.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import { CollectionUserPermissions } from '../models/CollectionUserPermissions'
1010
import { PublicationStatus } from '../../../core/domain/models/PublicationStatus'
1111
import { CollectionItemType } from '../../../collections/domain/models/CollectionItemType'
1212
import { CollectionLinks } from '../models/CollectionLinks'
13+
import { CollectionSummary } from '../models/CollectionSummary'
14+
import { LinkingObjectType } from '../useCases/GetCollectionsForLinking'
1315

1416
export interface ICollectionsRepository {
1517
getCollection(collectionIdOrAlias: number | string): Promise<Collection>
@@ -60,4 +62,10 @@ export interface ICollectionsRepository {
6062
linkingCollectionIdOrAlias: number | string
6163
): Promise<void>
6264
getCollectionLinks(collectionIdOrAlias: number | string): Promise<CollectionLinks>
65+
getCollectionsForLinking(
66+
objectType: LinkingObjectType,
67+
id: number | string,
68+
searchTerm: string,
69+
alreadyLinked: boolean
70+
): Promise<CollectionSummary[]>
6371
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { UseCase } from '../../../core/domain/useCases/UseCase'
2+
import { ICollectionsRepository } from '../repositories/ICollectionsRepository'
3+
import { CollectionSummary } from '../models/CollectionSummary'
4+
5+
export type LinkingObjectType = 'collection' | 'dataset'
6+
7+
export class GetCollectionsForLinking implements UseCase<CollectionSummary[]> {
8+
private collectionsRepository: ICollectionsRepository
9+
10+
constructor(collectionsRepository: ICollectionsRepository) {
11+
this.collectionsRepository = collectionsRepository
12+
}
13+
14+
/**
15+
* Returns an array of CollectionSummary (id, alias, displayName) to which the given Dataverse collection or Dataset may be linked.
16+
* @param objectType - 'collection' when providing a collection identifier/alias; 'dataset' when providing a dataset persistentId.
17+
* @param id - For objectType 'collection', a numeric id or alias string. For 'dataset', the persistentId string (e.g., doi:...)
18+
* @param searchTerm - Optional search term to filter by collection name. Defaults to empty string (no filtering).
19+
* @param alreadyLinked - Optional flag. When true, returns collections currently linked (candidates to unlink). Defaults to false.
20+
*/
21+
async execute(
22+
objectType: LinkingObjectType,
23+
id: number | string,
24+
searchTerm = '',
25+
alreadyLinked = false
26+
): Promise<CollectionSummary[]> {
27+
return await this.collectionsRepository.getCollectionsForLinking(
28+
objectType,
29+
id,
30+
searchTerm,
31+
alreadyLinked
32+
)
33+
}
34+
}

src/collections/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { DeleteCollectionFeaturedItem } from './domain/useCases/DeleteCollection
1515
import { LinkCollection } from './domain/useCases/LinkCollection'
1616
import { UnlinkCollection } from './domain/useCases/UnlinkCollection'
1717
import { GetCollectionLinks } from './domain/useCases/GetCollectionLinks'
18+
import { GetCollectionsForLinking } from './domain/useCases/GetCollectionsForLinking'
1819

1920
const collectionsRepository = new CollectionsRepository()
2021

@@ -34,6 +35,7 @@ const deleteCollectionFeaturedItem = new DeleteCollectionFeaturedItem(collection
3435
const linkCollection = new LinkCollection(collectionsRepository)
3536
const unlinkCollection = new UnlinkCollection(collectionsRepository)
3637
const getCollectionLinks = new GetCollectionLinks(collectionsRepository)
38+
const getCollectionsForLinking = new GetCollectionsForLinking(collectionsRepository)
3739

3840
export {
3941
getCollection,
@@ -51,7 +53,8 @@ export {
5153
deleteCollectionFeaturedItem,
5254
linkCollection,
5355
unlinkCollection,
54-
getCollectionLinks
56+
getCollectionLinks,
57+
getCollectionsForLinking
5558
}
5659
export { Collection, CollectionInputLevel } from './domain/models/Collection'
5760
export { CollectionFacet } from './domain/models/CollectionFacet'
@@ -62,3 +65,4 @@ export { CollectionItemType } from './domain/models/CollectionItemType'
6265
export { CollectionSearchCriteria } from './domain/models/CollectionSearchCriteria'
6366
export { FeaturedItem } from './domain/models/FeaturedItem'
6467
export { FeaturedItemsDTO } from './domain/dtos/FeaturedItemsDTO'
68+
export { CollectionSummary } from './domain/models/CollectionSummary'

src/collections/infra/repositories/CollectionsRepository.ts

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ import { ApiConstants } from '../../../core/infra/repositories/ApiConstants'
3838
import { PublicationStatus } from '../../../core/domain/models/PublicationStatus'
3939
import { ReadError } from '../../../core/domain/repositories/ReadError'
4040
import { CollectionLinks } from '../../domain/models/CollectionLinks'
41+
import { CollectionSummary } from '../../domain/models/CollectionSummary'
42+
import { LinkingObjectType } from '../../domain/useCases/GetCollectionsForLinking'
4143

4244
export interface NewCollectionRequestPayload {
4345
alias: string
@@ -93,7 +95,6 @@ export enum GetMyDataCollectionItemsQueryParams {
9395

9496
export class CollectionsRepository extends ApiRepository implements ICollectionsRepository {
9597
private readonly collectionsResourceName: string = 'dataverses'
96-
9798
public async getCollection(
9899
collectionIdOrAlias: number | string = ROOT_COLLECTION_ID
99100
): Promise<Collection> {
@@ -485,4 +486,46 @@ export class CollectionsRepository extends ApiRepository implements ICollections
485486
throw error
486487
})
487488
}
489+
490+
public async getCollectionsForLinking(
491+
objectType: LinkingObjectType,
492+
id: number | string,
493+
searchTerm: string,
494+
alreadyLinked: boolean
495+
): Promise<CollectionSummary[]> {
496+
let path: string
497+
const queryParams = new URLSearchParams()
498+
if (objectType === 'collection') {
499+
path = `/${this.collectionsResourceName}/${id}/dataverse/linkingDataverses`
500+
} else {
501+
path = `/${this.collectionsResourceName}/:persistentId/dataset/linkingDataverses`
502+
queryParams.set('persistentId', String(id))
503+
}
504+
505+
if (searchTerm) {
506+
queryParams.set('searchTerm', searchTerm)
507+
}
508+
509+
if (alreadyLinked) {
510+
queryParams.set('alreadyLinking', 'true')
511+
}
512+
513+
return this.doGet(path, true, queryParams)
514+
.then((response) => {
515+
const payload = response.data.data as {
516+
id: number
517+
alias: string
518+
name: string
519+
}[]
520+
521+
return payload.map((item) => ({
522+
id: item.id,
523+
alias: item.alias,
524+
displayName: item.name
525+
}))
526+
})
527+
.catch((error) => {
528+
throw error
529+
})
530+
}
488531
}

src/collections/infra/repositories/transformers/collectionTransformers.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,13 @@ export const transformCollectionLinksResponseToCollectionLinks = (
159159
const responseDataPayload = response.data.data
160160
const linkedCollections = responseDataPayload.linkedDataverses
161161
const collectionsLinkingToThis = responseDataPayload.dataversesLinkingToThis
162-
const linkedDatasets = responseDataPayload.linkedDatasets
162+
const linkedDatasets = responseDataPayload.linkedDatasets.map(
163+
(ld: { identifier: string; title: string }) => ({
164+
persistentId: ld.identifier,
165+
title: ld.title
166+
})
167+
)
168+
163169
return {
164170
linkedCollections,
165171
collectionsLinkingToThis,
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { DatasetType } from '../models/DatasetType'
2+
3+
export type DatasetTypeDTO = Omit<DatasetType, 'id'>

src/datasets/domain/models/DatasetType.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
export interface DatasetType {
2-
id?: number
2+
id: number
33
name: string
44
linkedMetadataBlocks?: string[]
55
availableLicenses?: string[]

src/datasets/domain/repositories/IDatasetsRepository.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { FormattedCitation } from '../models/FormattedCitation'
1515
import { DatasetTemplate } from '../models/DatasetTemplate'
1616
import { DatasetType } from '../models/DatasetType'
1717
import { TermsOfAccess } from '../models/Dataset'
18+
import { DatasetTypeDTO } from '../dtos/DatasetTypeDTO'
1819

1920
export interface IDatasetsRepository {
2021
getDataset(
@@ -68,8 +69,8 @@ export interface IDatasetsRepository {
6869
): Promise<DatasetDownloadCount>
6970
getDatasetVersionsSummaries(datasetId: number | string): Promise<DatasetVersionSummaryInfo[]>
7071
deleteDatasetDraft(datasetId: number | string): Promise<void>
71-
linkDataset(datasetId: number, collectionAlias: string): Promise<void>
72-
unlinkDataset(datasetId: number, collectionAlias: string): Promise<void>
72+
linkDataset(datasetId: number | string, collectionIdOrAlias: number | string): Promise<void>
73+
unlinkDataset(datasetId: number | string, collectionIdOrAlias: number | string): Promise<void>
7374
getDatasetLinkedCollections(datasetId: number | string): Promise<DatasetLinkedCollection[]>
7475
getDatasetAvailableCategories(datasetId: number | string): Promise<string[]>
7576
getDatasetCitationInOtherFormats(
@@ -81,7 +82,7 @@ export interface IDatasetsRepository {
8182
getDatasetTemplates(collectionIdOrAlias: number | string): Promise<DatasetTemplate[]>
8283
getDatasetAvailableDatasetTypes(): Promise<DatasetType[]>
8384
getDatasetAvailableDatasetType(datasetTypeId: number | string): Promise<DatasetType>
84-
addDatasetType(datasetType: DatasetType): Promise<DatasetType>
85+
addDatasetType(datasetType: DatasetTypeDTO): Promise<DatasetType>
8586
linkDatasetTypeWithMetadataBlocks(
8687
datasetTypeId: number | string,
8788
metadataBlocks: string[]

0 commit comments

Comments
 (0)