Skip to content

Commit

Permalink
feat: add updateCollectionFeaturedItems use case
Browse files Browse the repository at this point in the history
  • Loading branch information
g-saracca committed Jan 7, 2025
1 parent 559c89c commit 3f12018
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 3 deletions.
27 changes: 27 additions & 0 deletions docs/useCases.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ The different use cases currently available in the package are classified below,
- [Create a Collection](#create-a-collection)
- [Update a Collection](#update-a-collection)
- [Publish a Collection](#publish-a-collection)
- [Update Collection Featured Items](#update-collection-featured-items)
- [Datasets](#Datasets)
- [Datasets read use cases](#datasets-read-use-cases)
- [Get a Dataset](#get-a-dataset)
Expand Down Expand Up @@ -313,6 +314,32 @@ The `collectionIdOrAlias` is a generic collection identifier, which can be eithe

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

#### Update Collection Featured Items

Updates all featured items, given a collection identifier and a CollectionFeaturedItemsDTO.

##### Example call:

```typescript
import { updateCollectionFeaturedItems } from '@iqss/dataverse-client-javascript'

/* ... */

const collectionIdOrAlias = 12345

updateCollectionFeaturedItems
.execute(collectionIdOrAlias)
.then((collectionFeaturedItems: CollectionFeaturedItem[]) => {
/* ... */
})

/* ... */
```

The `collectionIdOrAlias` is a generic collection identifier, which can be either a string (for queries by CollectionAlias), or a number (for queries by CollectionId).

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

## Datasets

### Datasets Read Use Cases
Expand Down
9 changes: 9 additions & 0 deletions src/collections/domain/dtos/CollectionFeaturedItemsDTO.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export type CollectionFeaturedItemsDTO = CollectionFeaturedItemDTO[]

export interface CollectionFeaturedItemDTO {
id?: number
content: string
displayOrder: number
file?: File
keepFile: boolean
}
5 changes: 5 additions & 0 deletions src/collections/domain/repositories/ICollectionsRepository.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { CollectionDTO } from '../dtos/CollectionDTO'
import { CollectionFeaturedItemsDTO } from '../dtos/CollectionFeaturedItemsDTO'
import { Collection } from '../models/Collection'
import { CollectionFacet } from '../models/CollectionFacet'
import { CollectionFeaturedItem } from '../models/CollectionFeaturedItem'
Expand Down Expand Up @@ -30,4 +31,8 @@ export interface ICollectionsRepository {
getCollectionFeaturedItems(
collectionIdOrAlias: number | string
): Promise<CollectionFeaturedItem[]>
updateCollectionFeaturedItems(
collectionIdOrAlias: number | string,
featuredItemDTOs: CollectionFeaturedItemsDTO
): Promise<CollectionFeaturedItem[]>
}
32 changes: 32 additions & 0 deletions src/collections/domain/useCases/UpdateCollectionFeaturedItems.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { UseCase } from '../../../core/domain/useCases/UseCase'
import { CollectionFeaturedItemsDTO } from '../dtos/CollectionFeaturedItemsDTO'
import { ROOT_COLLECTION_ID } from '../models/Collection'
import { CollectionFeaturedItem } from '../models/CollectionFeaturedItem'
import { ICollectionsRepository } from '../repositories/ICollectionsRepository'

export class UpdateCollectionFeaturedItems implements UseCase<CollectionFeaturedItem[]> {
private collectionsRepository: ICollectionsRepository

constructor(collectionsRepository: ICollectionsRepository) {
this.collectionsRepository = collectionsRepository
}

/**
* Updates all featured items, given a collection identifier and a CollectionFeaturedItemsDTO.
*
* @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)
* If this parameter is not set, the default value is: ':root'
* @param {CollectionFeaturedItemsDTO} [newCollectionFeaturedItems] - CollectionFeaturedItemsDTO object including the updated collection featured items data.
* @returns {Promise<CollectionFeaturedItem[]>} -This method returns the updated collection featured items upon successful completion.
* @throws {WriteError} - If there are errors while writing data.
*/
async execute(
collectionIdOrAlias: number | string = ROOT_COLLECTION_ID,
featuredItemsDTO: CollectionFeaturedItemsDTO
): Promise<CollectionFeaturedItem[]> {
return await this.collectionsRepository.updateCollectionFeaturedItems(
collectionIdOrAlias,
featuredItemsDTO
)
}
}
6 changes: 5 additions & 1 deletion src/collections/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { PublishCollection } from './domain/useCases/PublishCollection'
import { UpdateCollection } from './domain/useCases/UpdateCollection'
import { GetCollectionFeaturedItems } from './domain/useCases/GetCollectionFeaturedItems'
import { CollectionsRepository } from './infra/repositories/CollectionsRepository'
import { UpdateCollectionFeaturedItems } from './domain/useCases/UpdateCollectionFeaturedItems'

const collectionsRepository = new CollectionsRepository()

Expand All @@ -18,6 +19,7 @@ const getCollectionItems = new GetCollectionItems(collectionsRepository)
const publishCollection = new PublishCollection(collectionsRepository)
const updateCollection = new UpdateCollection(collectionsRepository)
const getCollectionFeaturedItems = new GetCollectionFeaturedItems(collectionsRepository)
const updateCollectionFeaturedItems = new UpdateCollectionFeaturedItems(collectionsRepository)

export {
getCollection,
Expand All @@ -27,7 +29,8 @@ export {
getCollectionItems,
publishCollection,
updateCollection,
getCollectionFeaturedItems
getCollectionFeaturedItems,
updateCollectionFeaturedItems
}
export { Collection, CollectionInputLevel } from './domain/models/Collection'
export { CollectionFacet } from './domain/models/CollectionFacet'
Expand All @@ -37,3 +40,4 @@ export { CollectionPreview } from './domain/models/CollectionPreview'
export { CollectionItemType } from './domain/models/CollectionItemType'
export { CollectionSearchCriteria } from './domain/models/CollectionSearchCriteria'
export { CollectionFeaturedItem } from './domain/models/CollectionFeaturedItem'
export { CollectionFeaturedItemsDTO } from './domain/dtos/CollectionFeaturedItemsDTO'
45 changes: 45 additions & 0 deletions src/collections/infra/repositories/CollectionsRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import {
import { CollectionItemType } from '../../domain/models/CollectionItemType'
import { CollectionFeaturedItem } from '../../domain/models/CollectionFeaturedItem'
import { transformCollectionFeaturedItemsPayloadToCollectionFeaturedItems } from './transformers/collectionFeaturedItemsTransformer'
import { CollectionFeaturedItemsDTO } from '../../domain/dtos/CollectionFeaturedItemsDTO'
import { ApiConstants } from '../../../core/infra/repositories/ApiConstants'

export interface NewCollectionRequestPayload {
alias: string
Expand Down Expand Up @@ -254,4 +256,47 @@ export class CollectionsRepository extends ApiRepository implements ICollections
throw error
})
}

public async updateCollectionFeaturedItems(
collectionIdOrAlias: number | string,
featuredItemsDTO: CollectionFeaturedItemsDTO
): Promise<CollectionFeaturedItem[]> {
const featuredItemsFormData =
this.defineUpdateCollectionFeaturedItemsRequestBody(featuredItemsDTO)

return this.doPut(
`/${this.collectionsResourceName}/${collectionIdOrAlias}/featuredItems`,
featuredItemsFormData,
undefined,
ApiConstants.CONTENT_TYPE_MULTIPART_FORM_DATA
)
.then((response) =>
transformCollectionFeaturedItemsPayloadToCollectionFeaturedItems(response.data.data)
)
.catch((error) => {
throw error
})
}

private defineUpdateCollectionFeaturedItemsRequestBody(
featuredItemsDTO: CollectionFeaturedItemsDTO
): FormData {
const formData = new FormData()

featuredItemsDTO.forEach((item) => {
const { id, content, displayOrder, file, keepFile } = item

// TODO: We need to configure this project to use strict typescript rules or at least strictNullChecks: true
// id is inferred here as number but it should be a number | undefined, same for file
// This config change should be done in a separate issue because it will require changes in some other ts files

formData.append(`items[${item.displayOrder}][id]`, id ? id.toString() : '0')
formData.append(`items[${item.displayOrder}][displayOrder]`, displayOrder.toString())
formData.append(`items[${item.displayOrder}][content]`, content)
formData.append(`items[${item.displayOrder}][file]`, file ? file : 'false')
formData.append(`items[${item.displayOrder}][keepFile]`, keepFile.toString())
})

return formData
}
}
5 changes: 3 additions & 2 deletions src/core/infra/repositories/ApiRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@ export abstract class ApiRepository {
public async doPut(
apiEndpoint: string,
data: string | object,
queryParams: object = {}
queryParams: object = {},
contentType: string = ApiConstants.CONTENT_TYPE_APPLICATION_JSON
): Promise<AxiosResponse> {
return await this.doRequest('put', apiEndpoint, data, queryParams)
return await this.doRequest('put', apiEndpoint, data, queryParams, contentType)
}

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

0 comments on commit 3f12018

Please sign in to comment.