Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ This changelog follows the principles of [Keep a Changelog](https://keepachangel
- Templates: Rename `CreateDatasetTemplateDTO` to `CreateTemplateDTO`.
- Templates: Rename `createDatasetTemplate` repository method to `createTemplate`.
- Templates: Rename `getDatasetTemplates` repository method to `getTemplatesByCollectionId`.
- Collections: `updateCollection` now supports partial updates by accepting `Partial<CollectionDTO>`. Only explicitly provided fields are sent in update requests, aligning with Dataverse API semantics. Metadata blocks handling was adjusted to respect inheritance flags and avoid invalid field combinations.

### Fixed

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export interface ICollectionsRepository {
): Promise<MyDataCollectionItemSubset>
updateCollection(
collectionIdOrAlias: number | string,
updatedCollection: CollectionDTO
updatedCollection: Partial<CollectionDTO>
): Promise<void>
getCollectionFeaturedItems(collectionIdOrAlias: number | string): Promise<FeaturedItem[]>
updateCollectionFeaturedItems(
Expand Down
2 changes: 1 addition & 1 deletion src/collections/domain/useCases/UpdateCollection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export class UpdateCollection implements UseCase<void> {
*/
async execute(
collectionIdOrAlias: number | string,
updatedCollection: CollectionDTO
updatedCollection: Partial<CollectionDTO>
): Promise<void> {
return await this.collectionsRepository.updateCollection(collectionIdOrAlias, updatedCollection)
}
Expand Down
84 changes: 82 additions & 2 deletions src/collections/infra/repositories/CollectionsRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,9 +215,9 @@ export class CollectionsRepository extends ApiRepository implements ICollections

public async updateCollection(
collectionIdOrAlias: string | number,
updatedCollection: CollectionDTO
updatedCollection: Partial<CollectionDTO>
): Promise<void> {
const requestBody = this.createCreateOrUpdateRequestBody(updatedCollection)
const requestBody = this.createUpdateRequestBody(updatedCollection)

return this.doPut(`/${this.collectionsResourceName}/${collectionIdOrAlias}`, requestBody)
.then(() => undefined)
Expand Down Expand Up @@ -332,6 +332,86 @@ export class CollectionsRepository extends ApiRepository implements ICollections
}
}

private createUpdateRequestBody(
collectionDTO: Partial<CollectionDTO>
): Partial<NewCollectionRequestPayload> {
const dataverseContacts: NewCollectionContactRequestPayload[] | undefined =
collectionDTO.contacts?.map((contact) => ({
contactEmail: contact
}))
const inputLevelsRequestBody: NewCollectionInputLevelRequestPayload[] | undefined =
collectionDTO.inputLevels?.map((inputLevel) => ({
datasetFieldTypeName: inputLevel.datasetFieldName,
include: inputLevel.include,
required: inputLevel.required
}))
let metadataBlocksRequestBody: Partial<NewCollectionMetadataBlocksRequestPayload> | undefined

const hasMetadataBlocksData =
collectionDTO.metadataBlockNames !== undefined ||
collectionDTO.facetIds !== undefined ||
collectionDTO.inputLevels !== undefined ||
collectionDTO.inheritMetadataBlocksFromParent !== undefined ||
collectionDTO.inheritFacetsFromParent !== undefined

if (hasMetadataBlocksData) {
metadataBlocksRequestBody = {}
if (collectionDTO.inheritMetadataBlocksFromParent !== true) {
if (collectionDTO.metadataBlockNames !== undefined) {
metadataBlocksRequestBody.metadataBlockNames = collectionDTO.metadataBlockNames
}
if (inputLevelsRequestBody !== undefined) {
metadataBlocksRequestBody.inputLevels = inputLevelsRequestBody
}
}
if (collectionDTO.inheritFacetsFromParent !== true) {
if (collectionDTO.facetIds !== undefined) {
metadataBlocksRequestBody.facetIds = collectionDTO.facetIds
}
}
if (collectionDTO.inheritMetadataBlocksFromParent !== undefined) {
metadataBlocksRequestBody.inheritMetadataBlocksFromParent =
collectionDTO.inheritMetadataBlocksFromParent
}
if (collectionDTO.inheritFacetsFromParent !== undefined) {
metadataBlocksRequestBody.inheritFacetsFromParent = collectionDTO.inheritFacetsFromParent
}
}

// Build the final request body, only including defined fields
const requestBody: Partial<NewCollectionRequestPayload> = {}

if (collectionDTO.alias !== undefined) {
requestBody.alias = collectionDTO.alias
}

if (collectionDTO.name !== undefined) {
requestBody.name = collectionDTO.name
}

if (dataverseContacts !== undefined) {
requestBody.dataverseContacts = dataverseContacts
}

if (collectionDTO.type !== undefined) {
requestBody.dataverseType = collectionDTO.type
}

if (collectionDTO.description !== undefined) {
requestBody.description = collectionDTO.description
}

if (collectionDTO.affiliation !== undefined) {
requestBody.affiliation = collectionDTO.affiliation
}

if (metadataBlocksRequestBody !== undefined) {
requestBody.metadataBlocks = metadataBlocksRequestBody
}

return requestBody
}

private applyCollectionSearchCriteriaToQueryParams(
queryParams: URLSearchParams,
collectionSearchCriteria: CollectionSearchCriteria
Expand Down
25 changes: 24 additions & 1 deletion test/functional/collections/UpdateCollection.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import {
WriteError,
createCollection,
getCollection,
updateCollection
updateCollection,
CollectionDTO
} from '../../../src'
import { TestConstants } from '../../testHelpers/TestConstants'
import { DataverseApiAuthMechanism } from '../../../src/core/infra/repositories/ApiConfig'
Expand Down Expand Up @@ -35,6 +36,28 @@ describe('execute', () => {
}
})

test('should successfully update a collection with partial data (name only)', async () => {
const testNewCollectionAlias = 'updateCollection-partial-test'
const testNewCollection = createCollectionDTO(testNewCollectionAlias)
await createCollection.execute(testNewCollection)

const partialUpdate: Partial<CollectionDTO> = {
name: 'Partially Updated Name'
}

expect.assertions(3)
try {
await updateCollection.execute(testNewCollectionAlias, partialUpdate)
} catch (error) {
throw new Error('Collection should be updated with partial data')
} finally {
const updatedCollection = await getCollection.execute(testNewCollectionAlias)
expect(updatedCollection.name).toBe('Partially Updated Name')
expect(updatedCollection.alias).toBe(testNewCollectionAlias)
expect(updatedCollection.type).toBe(testNewCollection.type)
}
})

test('should throw an error when the parent collection does not exist', async () => {
const testNewCollection = createCollectionDTO()
expect.assertions(2)
Expand Down
21 changes: 21 additions & 0 deletions test/integration/collections/CollectionsRepository.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1110,6 +1110,27 @@ describe('CollectionsRepository', () => {
expect(updatedInputLevel?.required).toBe(false)
})

test('should update collection with only partial fields (name and affiliation)', async () => {
const collectionDTO = createCollectionDTO('partial-update-test')
const testCollectionId = await sut.createCollection(collectionDTO)
const createdCollection = await sut.getCollection(testCollectionId)
const partialUpdate: Partial<CollectionDTO> = {
name: 'Partially Updated Name',
affiliation: 'New Affiliation'
}

await sut.updateCollection(testCollectionId, partialUpdate)
const updatedCollection = await sut.getCollection(testCollectionId)

expect(updatedCollection.name).toBe('Partially Updated Name')
expect(updatedCollection.affiliation).toBe('New Affiliation')
expect(updatedCollection.alias).toBe(createdCollection.alias)
expect(updatedCollection.type).toBe(createdCollection.type)
expect(updatedCollection.contacts).toEqual(createdCollection.contacts)

await deleteCollectionViaApi(collectionDTO.alias)
})

test('should update the collection to inherit metadata blocks from parent collection', async () => {
const parentCollectionAlias = 'inherit-metablocks-parent-update'
const parentCollectionDTO = createCollectionDTO(parentCollectionAlias)
Expand Down
Loading