Skip to content

Commit 3f12018

Browse files
committed
feat: add updateCollectionFeaturedItems use case
1 parent 559c89c commit 3f12018

File tree

7 files changed

+126
-3
lines changed

7 files changed

+126
-3
lines changed

docs/useCases.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ The different use cases currently available in the package are classified below,
1919
- [Create a Collection](#create-a-collection)
2020
- [Update a Collection](#update-a-collection)
2121
- [Publish a Collection](#publish-a-collection)
22+
- [Update Collection Featured Items](#update-collection-featured-items)
2223
- [Datasets](#Datasets)
2324
- [Datasets read use cases](#datasets-read-use-cases)
2425
- [Get a Dataset](#get-a-dataset)
@@ -313,6 +314,32 @@ The `collectionIdOrAlias` is a generic collection identifier, which can be eithe
313314

314315
_See [use case](../src/collections/domain/useCases/PublishCollection.ts)_ definition.
315316

317+
#### Update Collection Featured Items
318+
319+
Updates all featured items, given a collection identifier and a CollectionFeaturedItemsDTO.
320+
321+
##### Example call:
322+
323+
```typescript
324+
import { updateCollectionFeaturedItems } from '@iqss/dataverse-client-javascript'
325+
326+
/* ... */
327+
328+
const collectionIdOrAlias = 12345
329+
330+
updateCollectionFeaturedItems
331+
.execute(collectionIdOrAlias)
332+
.then((collectionFeaturedItems: CollectionFeaturedItem[]) => {
333+
/* ... */
334+
})
335+
336+
/* ... */
337+
```
338+
339+
The `collectionIdOrAlias` is a generic collection identifier, which can be either a string (for queries by CollectionAlias), or a number (for queries by CollectionId).
340+
341+
_See [use case](../src/collections/domain/useCases/UpdateCollectionFeaturedItems.ts)_ definition.
342+
316343
## Datasets
317344

318345
### Datasets Read Use Cases
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export type CollectionFeaturedItemsDTO = CollectionFeaturedItemDTO[]
2+
3+
export interface CollectionFeaturedItemDTO {
4+
id?: number
5+
content: string
6+
displayOrder: number
7+
file?: File
8+
keepFile: boolean
9+
}

src/collections/domain/repositories/ICollectionsRepository.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { CollectionDTO } from '../dtos/CollectionDTO'
2+
import { CollectionFeaturedItemsDTO } from '../dtos/CollectionFeaturedItemsDTO'
23
import { Collection } from '../models/Collection'
34
import { CollectionFacet } from '../models/CollectionFacet'
45
import { CollectionFeaturedItem } from '../models/CollectionFeaturedItem'
@@ -30,4 +31,8 @@ export interface ICollectionsRepository {
3031
getCollectionFeaturedItems(
3132
collectionIdOrAlias: number | string
3233
): Promise<CollectionFeaturedItem[]>
34+
updateCollectionFeaturedItems(
35+
collectionIdOrAlias: number | string,
36+
featuredItemDTOs: CollectionFeaturedItemsDTO
37+
): Promise<CollectionFeaturedItem[]>
3338
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { UseCase } from '../../../core/domain/useCases/UseCase'
2+
import { CollectionFeaturedItemsDTO } from '../dtos/CollectionFeaturedItemsDTO'
3+
import { ROOT_COLLECTION_ID } from '../models/Collection'
4+
import { CollectionFeaturedItem } from '../models/CollectionFeaturedItem'
5+
import { ICollectionsRepository } from '../repositories/ICollectionsRepository'
6+
7+
export class UpdateCollectionFeaturedItems implements UseCase<CollectionFeaturedItem[]> {
8+
private collectionsRepository: ICollectionsRepository
9+
10+
constructor(collectionsRepository: ICollectionsRepository) {
11+
this.collectionsRepository = collectionsRepository
12+
}
13+
14+
/**
15+
* Updates all featured items, given a collection identifier and a CollectionFeaturedItemsDTO.
16+
*
17+
* @param {number | string} [collectionIdOrAlias = ':root'] - A generic collection identifier, which can be either a string (for queries by CollectionAlias), or a number (for queries by CollectionId)
18+
* If this parameter is not set, the default value is: ':root'
19+
* @param {CollectionFeaturedItemsDTO} [newCollectionFeaturedItems] - CollectionFeaturedItemsDTO object including the updated collection featured items data.
20+
* @returns {Promise<CollectionFeaturedItem[]>} -This method returns the updated collection featured items upon successful completion.
21+
* @throws {WriteError} - If there are errors while writing data.
22+
*/
23+
async execute(
24+
collectionIdOrAlias: number | string = ROOT_COLLECTION_ID,
25+
featuredItemsDTO: CollectionFeaturedItemsDTO
26+
): Promise<CollectionFeaturedItem[]> {
27+
return await this.collectionsRepository.updateCollectionFeaturedItems(
28+
collectionIdOrAlias,
29+
featuredItemsDTO
30+
)
31+
}
32+
}

src/collections/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { PublishCollection } from './domain/useCases/PublishCollection'
77
import { UpdateCollection } from './domain/useCases/UpdateCollection'
88
import { GetCollectionFeaturedItems } from './domain/useCases/GetCollectionFeaturedItems'
99
import { CollectionsRepository } from './infra/repositories/CollectionsRepository'
10+
import { UpdateCollectionFeaturedItems } from './domain/useCases/UpdateCollectionFeaturedItems'
1011

1112
const collectionsRepository = new CollectionsRepository()
1213

@@ -18,6 +19,7 @@ const getCollectionItems = new GetCollectionItems(collectionsRepository)
1819
const publishCollection = new PublishCollection(collectionsRepository)
1920
const updateCollection = new UpdateCollection(collectionsRepository)
2021
const getCollectionFeaturedItems = new GetCollectionFeaturedItems(collectionsRepository)
22+
const updateCollectionFeaturedItems = new UpdateCollectionFeaturedItems(collectionsRepository)
2123

2224
export {
2325
getCollection,
@@ -27,7 +29,8 @@ export {
2729
getCollectionItems,
2830
publishCollection,
2931
updateCollection,
30-
getCollectionFeaturedItems
32+
getCollectionFeaturedItems,
33+
updateCollectionFeaturedItems
3134
}
3235
export { Collection, CollectionInputLevel } from './domain/models/Collection'
3336
export { CollectionFacet } from './domain/models/CollectionFacet'
@@ -37,3 +40,4 @@ export { CollectionPreview } from './domain/models/CollectionPreview'
3740
export { CollectionItemType } from './domain/models/CollectionItemType'
3841
export { CollectionSearchCriteria } from './domain/models/CollectionSearchCriteria'
3942
export { CollectionFeaturedItem } from './domain/models/CollectionFeaturedItem'
43+
export { CollectionFeaturedItemsDTO } from './domain/dtos/CollectionFeaturedItemsDTO'

src/collections/infra/repositories/CollectionsRepository.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import {
1919
import { CollectionItemType } from '../../domain/models/CollectionItemType'
2020
import { CollectionFeaturedItem } from '../../domain/models/CollectionFeaturedItem'
2121
import { transformCollectionFeaturedItemsPayloadToCollectionFeaturedItems } from './transformers/collectionFeaturedItemsTransformer'
22+
import { CollectionFeaturedItemsDTO } from '../../domain/dtos/CollectionFeaturedItemsDTO'
23+
import { ApiConstants } from '../../../core/infra/repositories/ApiConstants'
2224

2325
export interface NewCollectionRequestPayload {
2426
alias: string
@@ -254,4 +256,47 @@ export class CollectionsRepository extends ApiRepository implements ICollections
254256
throw error
255257
})
256258
}
259+
260+
public async updateCollectionFeaturedItems(
261+
collectionIdOrAlias: number | string,
262+
featuredItemsDTO: CollectionFeaturedItemsDTO
263+
): Promise<CollectionFeaturedItem[]> {
264+
const featuredItemsFormData =
265+
this.defineUpdateCollectionFeaturedItemsRequestBody(featuredItemsDTO)
266+
267+
return this.doPut(
268+
`/${this.collectionsResourceName}/${collectionIdOrAlias}/featuredItems`,
269+
featuredItemsFormData,
270+
undefined,
271+
ApiConstants.CONTENT_TYPE_MULTIPART_FORM_DATA
272+
)
273+
.then((response) =>
274+
transformCollectionFeaturedItemsPayloadToCollectionFeaturedItems(response.data.data)
275+
)
276+
.catch((error) => {
277+
throw error
278+
})
279+
}
280+
281+
private defineUpdateCollectionFeaturedItemsRequestBody(
282+
featuredItemsDTO: CollectionFeaturedItemsDTO
283+
): FormData {
284+
const formData = new FormData()
285+
286+
featuredItemsDTO.forEach((item) => {
287+
const { id, content, displayOrder, file, keepFile } = item
288+
289+
// TODO: We need to configure this project to use strict typescript rules or at least strictNullChecks: true
290+
// id is inferred here as number but it should be a number | undefined, same for file
291+
// This config change should be done in a separate issue because it will require changes in some other ts files
292+
293+
formData.append(`items[${item.displayOrder}][id]`, id ? id.toString() : '0')
294+
formData.append(`items[${item.displayOrder}][displayOrder]`, displayOrder.toString())
295+
formData.append(`items[${item.displayOrder}][content]`, content)
296+
formData.append(`items[${item.displayOrder}][file]`, file ? file : 'false')
297+
formData.append(`items[${item.displayOrder}][keepFile]`, keepFile.toString())
298+
})
299+
300+
return formData
301+
}
257302
}

src/core/infra/repositories/ApiRepository.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,10 @@ export abstract class ApiRepository {
3030
public async doPut(
3131
apiEndpoint: string,
3232
data: string | object,
33-
queryParams: object = {}
33+
queryParams: object = {},
34+
contentType: string = ApiConstants.CONTENT_TYPE_APPLICATION_JSON
3435
): Promise<AxiosResponse> {
35-
return await this.doRequest('put', apiEndpoint, data, queryParams)
36+
return await this.doRequest('put', apiEndpoint, data, queryParams, contentType)
3637
}
3738

3839
public async doDelete(apiEndpoint: string, queryParams: object = {}): Promise<AxiosResponse> {

0 commit comments

Comments
 (0)