Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ This changelog follows the principles of [Keep a Changelog](https://keepachangel

### Changed

- Use of the new `sourceLastUpdateTime` query parameter from update dataset and file metadata endpoints to support optimistic concurrency control during editing operations. See [Edit Dataset Metadata](https://guides.dataverse.org/en/6.8/api/native-api.html#edit-dataset-metadata) and [Updating File Metadata](https://guides.dataverse.org/en/6.8/api/native-api.html#updating-file-metadata) guides for more details.

### Fixed

### Removed
Expand Down
10 changes: 5 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"@dnd-kit/sortable": "8.0.0",
"@dnd-kit/utilities": "3.2.2",
"@faker-js/faker": "7.6.0",
"@iqss/dataverse-client-javascript": "2.0.0-alpha.67",
"@iqss/dataverse-client-javascript": "2.0.0-alpha.76",
"@iqss/dataverse-design-system": "*",
"@istanbuljs/nyc-config-typescript": "1.0.2",
"@tanstack/react-table": "8.9.2",
Expand Down
8 changes: 8 additions & 0 deletions src/dataset/domain/models/Dataset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,12 @@ export class DatasetVersion {
public readonly isInReview: boolean,
public readonly latestVersionPublishingStatus: DatasetPublishingStatus,
public readonly someDatasetVersionHasBeenReleased: boolean,
/**
* The timestamp of the last update to this dataset version.
* Format: ISO 8601 string (e.g., "2023-06-01T12:34:56Z").
* Used for optimistic concurrency control to detect concurrent updates.
*/
public readonly lastUpdateTime: string,
public readonly termsOfAccess?: TermsOfAccess,
public readonly deaccessionNote?: string
) {}
Expand All @@ -268,6 +274,7 @@ export class DatasetVersion {
public readonly isInReview: boolean,
public readonly latestVersionPublishingStatus: DatasetPublishingStatus,
public readonly someDatasetVersionHasBeenReleased: boolean,
public readonly lastUpdateTime: string,
public readonly termsOfAccess?: TermsOfAccess,
public readonly deaccessionNote?: string
) {
Expand Down Expand Up @@ -336,6 +343,7 @@ export class DatasetVersion {
this.isInReview,
this.latestVersionPublishingStatus,
this.someDatasetVersionHasBeenReleased,
this.lastUpdateTime,
this.termsOfAccess,
this.deaccessionNote
)
Expand Down
2 changes: 1 addition & 1 deletion src/dataset/domain/repositories/DatasetRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export interface DatasetRepository {
updateMetadata: (
datasetId: string | number,
datasetDTO: DatasetDTO,
internalVersionNumber: number
sourceLastUpdateTime?: string
) => Promise<void>
deaccession: (
datasetId: string | number,
Expand Down
4 changes: 2 additions & 2 deletions src/dataset/domain/useCases/updateDatasetMetadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ export function updateDatasetMetadata(
datasetRepository: DatasetRepository,
datasetId: string | number,
updatedDataset: DatasetDTO,
internalVersionNumber: number
sourceLastUpdateTime?: string
): Promise<void> {
return datasetRepository
.updateMetadata(datasetId, updatedDataset, internalVersionNumber)
.updateMetadata(datasetId, updatedDataset, sourceLastUpdateTime)
.catch((error: Error) => {
throw new Error(error.message)
})
Expand Down
1 change: 1 addition & 0 deletions src/dataset/infrastructure/mappers/JSDatasetMapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export class JSDatasetMapper {
jsDataset.versionInfo,
JSDatasetMapper.toDatasetTitle(jsDataset.metadataBlocks),
jsDatasetCitation,
jsDataset.versionInfo.lastUpdateTime,
jsDataset.publicationDate,
jsDataset.termsOfUse?.termsOfAccess,
jsDataset.versionInfo.deaccessionNote as string
Expand Down
3 changes: 2 additions & 1 deletion src/dataset/infrastructure/mappers/JSDatasetPreviewMapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ export class JSDatasetPreviewMapper {
jsDatasetPreview.versionId,
jsDatasetPreview.versionInfo,
jsDatasetPreview.title,
jsDatasetPreview.citation
jsDatasetPreview.citation,
jsDatasetPreview.versionInfo.lastUpdateTime
),
releaseOrCreateDate: JSDatasetPreviewMapper.toPreviewDate(jsDatasetPreview.versionInfo),
description: jsDatasetPreview.description,
Expand Down
2 changes: 2 additions & 0 deletions src/dataset/infrastructure/mappers/JSDatasetVersionMapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export class JSDatasetVersionMapper {
jsDatasetVersionInfo: JSDatasetVersionInfo,
jsDatasetTitle: string,
jsDatasetCitation: string,
jsDatasetLastUpdateTime: string,
jsDatasetPublicationDate?: string,
jsDatasettermsOfAccess?: TermsOfAccess,
jsDatasetDeaccessionedNote?: string
Expand All @@ -29,6 +30,7 @@ export class JSDatasetVersionMapper {
false, // TODO Connect with dataset version isInReview
this.toStatus(jsDatasetVersionInfo.state),
this.toSomeDatasetVersionHasBeenReleased(jsDatasetVersionInfo, jsDatasetPublicationDate),
jsDatasetLastUpdateTime,
jsDatasettermsOfAccess,
jsDatasetDeaccessionedNote
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -350,10 +350,10 @@ export class DatasetJSDataverseRepository implements DatasetRepository {
updateMetadata(
datasetId: string | number,
updatedDataset: DatasetDTO,
internalVersionNumber: number
sourceLastUpdateTime?: string
): Promise<void> {
return updateDataset
.execute(datasetId, DatasetDTOMapper.toJSDatasetDTO(updatedDataset), internalVersionNumber)
.execute(datasetId, DatasetDTOMapper.toJSDatasetDTO(updatedDataset), sourceLastUpdateTime)
.catch((error: WriteError) => {
throw new Error(error.message)
})
Expand Down
6 changes: 5 additions & 1 deletion src/files/domain/repositories/FileRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,11 @@ export interface FileRepository {
delete: (fileId: number | string) => Promise<void>
replace: (fileId: number | string, uploadedFileDTO: UploadedFileDTO) => Promise<number>
getFixityAlgorithm: () => Promise<FixityAlgorithm>
updateMetadata: (fileId: number | string, fileMetadata: FileMetadataDTO) => Promise<void>
updateMetadata: (
fileId: number | string,
fileMetadata: FileMetadataDTO,
sourceLastUpdateTime?: string
) => Promise<void>
restrict: (fileId: number | string, restrictFileDTO: RestrictFileDTO) => Promise<void>
updateTabularTags: (
fileId: number | string,
Expand Down
5 changes: 3 additions & 2 deletions src/files/domain/useCases/editFileMetadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { FileMetadataDTO } from '@/files/domain/useCases/DTOs/FileMetadataDTO'
export function editFileMetadata(
fileRepository: FileRepository,
fileId: number | string,
fileMetadata: FileMetadataDTO
fileMetadata: FileMetadataDTO,
sourceLastUpdateTime?: string
): Promise<void> {
return fileRepository.updateMetadata(fileId, fileMetadata)
return fileRepository.updateMetadata(fileId, fileMetadata, sourceLastUpdateTime)
}
8 changes: 6 additions & 2 deletions src/files/infrastructure/FileJSDataverseRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -356,8 +356,12 @@ export class FileJSDataverseRepository implements FileRepository {
.then((newFileIdentifier) => newFileIdentifier)
}

updateMetadata(fileId: number | string, fileMetadata: FileMetadataDTO): Promise<void> {
return updateFileMetadata.execute(fileId, fileMetadata)
updateMetadata(
fileId: number | string,
fileMetadata: FileMetadataDTO,
sourceLastUpdateTime?: string
): Promise<void> {
return updateFileMetadata.execute(fileId, fileMetadata, sourceLastUpdateTime)
}
// TODO - Not a priority but could be nice to implement this use case in js-dataverse when having time
getFixityAlgorithm(): Promise<FixityAlgorithm> {
Expand Down
1 change: 1 addition & 0 deletions src/files/infrastructure/mappers/JSFileMapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export class JSFileMapper {
jsDataset.versionInfo,
JSDatasetMapper.toDatasetTitle(jsDataset.metadataBlocks),
datasetCitation,
jsDataset.versionInfo.lastUpdateTime,
jsDataset.publicationDate,
jsDataset.termsOfUse?.termsOfAccess
)
Expand Down
2 changes: 1 addition & 1 deletion src/sections/edit-dataset-metadata/EditDatasetMetadata.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export const EditDatasetMetadata = ({
metadataBlockInfoRepository={metadataBlockInfoRepository}
datasetPersistentID={dataset.persistentId}
datasetMetadaBlocksCurrentValues={dataset.metadataBlocks}
datasetInternalVersionNumber={dataset.internalVersionNumber}
datasetLastUpdateTime={dataset.version.lastUpdateTime}
/>
</div>
</Tabs.Tab>
Expand Down
1 change: 1 addition & 0 deletions src/sections/edit-file-metadata/EditFileMetadata.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ export const EditFileMetadata = ({ fileId, fileRepository, referrer }: EditFileM
editFileMetadataFormData={createEditFileMetadataFormData(file)}
referrer={referrer}
datasetPersistentId={file.hierarchy.parent?.persistentId}
datasetLastUpdateTime={file.datasetVersion.lastUpdateTime}
/>
</div>
</Tabs.Tab>
Expand Down
7 changes: 5 additions & 2 deletions src/sections/edit-file-metadata/EditFilesList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,15 @@ type EditFilesListProps = {
editFileMetadataFormData: EditFileMetadataFormData
referrer: EditFileMetadataReferrer
datasetPersistentId?: string
datasetLastUpdateTime: string
}

export const EditFilesList = ({
fileRepository,
editFileMetadataFormData,
referrer,
datasetPersistentId
datasetPersistentId,
datasetLastUpdateTime
}: EditFilesListProps) => {
const { t } = useTranslation('shared')
const navigate = useNavigate()
Expand All @@ -56,7 +58,8 @@ export const EditFilesList = ({
}
const { submitForm, submissionStatus, submitError } = useSubmitFileMetadata(
fileRepository,
onSubmitSucceed
onSubmitSucceed,
datasetLastUpdateTime
)
const isSaving = submissionStatus === SubmissionStatus.IsSubmitting
const handleCancel = () => navigate(-1)
Expand Down
5 changes: 3 additions & 2 deletions src/sections/edit-file-metadata/useSubmitFileMetadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ type UseSubmitFileMetadataReturnType =

export const useSubmitFileMetadata = (
fileRepository: FileRepository,
onSubmitSucceed: () => void
onSubmitSucceed: () => void,
datasetLastUpdateTime: string
) => {
const [submissionStatus, setSubmissionStatus] = useState<SubmissionStatus>(
SubmissionStatus.NotSubmitted
Expand All @@ -45,7 +46,7 @@ export const useSubmitFileMetadata = (
directoryLabel: file.fileDir,
label: file.fileName
}
await editFileMetadata(fileRepository, file.id, fileMetadataDTO)
await editFileMetadata(fileRepository, file.id, fileMetadataDTO, datasetLastUpdateTime)
}

setSubmitError(null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ interface FormProps {
metadataBlocksInfo: MetadataBlockInfo[]
datasetRepository: DatasetRepository
datasetPersistentID?: string
datasetInternalVersionNumber?: number
datasetLastUpdateTime?: string
datasetTemplateInstructions?: DatasetTemplateInstruction[]
}

Expand All @@ -35,7 +35,7 @@ export const MetadataForm = ({
metadataBlocksInfo,
datasetRepository,
datasetPersistentID,
datasetInternalVersionNumber,
datasetLastUpdateTime,
datasetTemplateInstructions
}: FormProps) => {
const { user } = useSession()
Expand All @@ -57,7 +57,7 @@ export const MetadataForm = ({
datasetRepository,
onSubmitDatasetError,
datasetPersistentID,
datasetInternalVersionNumber
datasetLastUpdateTime
)

usePrefillFieldsWithUserData({ mode, user, formDefaultValues, setValue })
Expand Down
8 changes: 4 additions & 4 deletions src/sections/shared/form/DatasetMetadataForm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type DatasetMetadataFormProps =
datasetPersistentID?: never
metadataBlockInfoRepository: MetadataBlockInfoRepository
datasetMetadaBlocksCurrentValues?: never
datasetInternalVersionNumber?: never
datasetLastUpdateTime?: never
datasetTemplate?: DatasetTemplate
}
| {
Expand All @@ -28,7 +28,7 @@ type DatasetMetadataFormProps =
datasetPersistentID: string
metadataBlockInfoRepository: MetadataBlockInfoRepository
datasetMetadaBlocksCurrentValues: DatasetMetadataBlocks
datasetInternalVersionNumber: number
datasetLastUpdateTime?: string
datasetTemplate?: never
}

Expand All @@ -41,7 +41,7 @@ export const DatasetMetadataForm = ({
datasetPersistentID,
metadataBlockInfoRepository,
datasetMetadaBlocksCurrentValues,
datasetInternalVersionNumber,
datasetLastUpdateTime,
datasetTemplate
}: DatasetMetadataFormProps) => {
const { setIsLoading } = useLoading()
Expand Down Expand Up @@ -107,7 +107,7 @@ export const DatasetMetadataForm = ({
metadataBlocksInfo={metadataBlocksInfo}
datasetRepository={datasetRepository}
datasetPersistentID={datasetPersistentID}
datasetInternalVersionNumber={datasetInternalVersionNumber}
datasetLastUpdateTime={datasetLastUpdateTime}
datasetTemplateInstructions={datasetTemplate?.instructions}
/>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export function useSubmitDataset(
datasetRepository: DatasetRepository,
onSubmitErrorCallback: () => void,
datasetPersistentID?: string,
datasetInternalVersionNumber?: number
datasetLastUpdateTime?: string
): UseSubmitDatasetReturnType {
const navigate = useNavigate()
const { t } = useTranslation('shared', { keyPrefix: 'datasetMetadataForm' })
Expand Down Expand Up @@ -89,7 +89,7 @@ export function useSubmitDataset(
datasetRepository,
currentEditedDatasetPersistentID,
formattedFormValues,
datasetInternalVersionNumber as number
datasetLastUpdateTime as string
)
.then(() => {
setSubmitError(null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export const EditMode: Story = {
metadataBlockInfoRepository={new MetadataBlockInfoMockRepository()}
datasetPersistentID={datasetToEditMock.persistentId}
datasetMetadaBlocksCurrentValues={datasetToEditMock.metadataBlocks}
datasetInternalVersionNumber={1}
datasetLastUpdateTime="2023-06-01T12:34:56Z"
/>
)
}
3 changes: 2 additions & 1 deletion tests/component/dataset/domain/models/DatasetMother.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ export class DatasetVersionMother {
props?.isLatest ?? false,
props?.isInReview ?? false,
props?.latestVersionPublishingStatus ?? DatasetPublishingStatus.RELEASED,
props?.someDatasetVersionHasBeenReleased ?? faker.datatype.boolean()
props?.someDatasetVersionHasBeenReleased ?? faker.datatype.boolean(),
props?.lastUpdateTime ?? faker.date.recent().toISOString()
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const jsDataset = {
majorNumber: 0,
minorNumber: 0,
createTime: new Date('2023-09-07T13:40:04.000Z'),
lastUpdateTime: new Date('2023-09-07T13:40:04.000Z'),
lastUpdateTime: '2023-09-07T13:40:04.000Z',
releaseTime: undefined,
deaccessionNote: undefined
},
Expand Down Expand Up @@ -231,6 +231,7 @@ const expectedDataset = {
majorNumber: 0
},
someDatasetVersionHasBeenReleased: false,
lastUpdateTime: '2023-09-07T13:40:04.000Z',
termsOfAccess: termsOfAccess,
deaccessionNote: undefined,
citation:
Expand Down Expand Up @@ -349,6 +350,7 @@ const expectedDatasetWithPublicationDate = {
majorNumber: 0
},
someDatasetVersionHasBeenReleased: true,
lastUpdateTime: '2023-09-07T13:40:04.000Z',
citation:
'Finch, Fiona, 2023, "Darwin\'s Finches", <a href="https://doi.org/10.5072/FK2/B4B2MJ" target="_blank">https://doi.org/10.5072/FK2/B4B2MJ</a>, Root, DRAFT VERSION'
},
Expand Down Expand Up @@ -464,6 +466,7 @@ const expectedDatasetWithNextVersionNumbers = {
majorNumber: 0
},
someDatasetVersionHasBeenReleased: true,
lastUpdateTime: '2023-09-07T13:40:04.000Z',
termsOfAccess: termsOfAccess,
deaccessionNote: undefined,
citation:
Expand Down Expand Up @@ -585,6 +588,7 @@ const expectedDatasetAlternateVersion = {
majorNumber: 0
},
someDatasetVersionHasBeenReleased: false,
lastUpdateTime: '2023-09-07T13:40:04.000Z',
termsOfAccess: termsOfAccess,
deaccessionNote: undefined,
citation:
Expand Down
Loading
Loading