diff --git a/package-lock.json b/package-lock.json index ae9b44949..07dff0099 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "0.1.0", "dependencies": { "@faker-js/faker": "7.6.0", - "@iqss/dataverse-client-javascript": "2.0.0-pr97.418bf5e", + "@iqss/dataverse-client-javascript": "2.0.0-pr99.c36f1db", "@iqss/dataverse-design-system": "*", "@istanbuljs/nyc-config-typescript": "1.0.2", "@tanstack/react-table": "8.9.2", @@ -3589,9 +3589,9 @@ }, "node_modules/@iqss/dataverse-client-javascript": { "name": "@IQSS/dataverse-client-javascript", - "version": "2.0.0-pr97.418bf5e", - "resolved": "https://npm.pkg.github.com/download/@IQSS/dataverse-client-javascript/2.0.0-pr97.418bf5e/0d604232d6f567b41328143c2d5d27513d069380", - "integrity": "sha512-wKRR1ORFkFSoFoCrWsCQvcm1vExIIrVN3pJbIl9Nk8lopP7zkUEB1xcAU+UVShbGktIZIa20TQMFl0ONafDiZw==", + "version": "2.0.0-pr99.c36f1db", + "resolved": "https://npm.pkg.github.com/download/@IQSS/dataverse-client-javascript/2.0.0-pr99.c36f1db/3f49037b14e53295c39ce787cce53f20b2558ba6", + "integrity": "sha512-KzMVzB420eKKaOuwDEpvAB/k1RrW3Le/ZJcVtjxFk/Wvxov2Jl1npbwy4SXQWasEXaJWslohn2KRkBfBDoTHTQ==", "license": "MIT", "dependencies": { "@types/node": "^18.15.11", diff --git a/package.json b/package.json index 6c826d6b0..7de72ef50 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ }, "dependencies": { "@faker-js/faker": "7.6.0", - "@iqss/dataverse-client-javascript": "2.0.0-pr97.418bf5e", + "@iqss/dataverse-client-javascript": "2.0.0-pr99.c36f1db", "@iqss/dataverse-design-system": "*", "@istanbuljs/nyc-config-typescript": "1.0.2", "@tanstack/react-table": "8.9.2", diff --git a/src/dataset/domain/models/Dataset.ts b/src/dataset/domain/models/Dataset.ts index 409a7ab5e..0c34de6b7 100644 --- a/src/dataset/domain/models/Dataset.ts +++ b/src/dataset/domain/models/Dataset.ts @@ -259,20 +259,19 @@ export interface DatasetPermissions { } export interface DatasetLock { - id: number + userPersistentId: string reason: DatasetLockReason } export enum DatasetLockReason { - INGEST = 'ingest', - WORKFLOW = 'workflow', - IN_REVIEW = 'inReview', - DCM_UPLOAD = 'dcmUpload', - GLOBUS_UPLOAD = 'globusUpload', + INGEST = 'Ingest', + WORKFLOW = 'Workflow', + IN_REVIEW = 'InReview', + DCM_UPLOAD = 'DcmUpload', + GLOBUS_UPLOAD = 'GlobusUpload', FINALIZE_PUBLICATION = 'finalizePublication', - - EDIT_IN_PROGRESS = 'editInProgress', - FILE_VALIDATION_FAILED = 'fileValidationFailed' + EDIT_IN_PROGRESS = 'EditInProgress', + FILE_VALIDATION_FAILED = 'FileValidationFailed' } export interface PrivateUrl { @@ -303,8 +302,8 @@ export class Dataset { return this.metadataBlocks[0].fields.title } - public get isLockedFromPublishing(): boolean { - return this.isLockedFromEdits + public checkIsLockedFromPublishing(userPersistentId: string): boolean { + return this.checkIsLockedFromEdits(userPersistentId) } public get isLocked(): boolean { @@ -315,12 +314,19 @@ export class Dataset { return this.locks.some((lock) => lock.reason === DatasetLockReason.WORKFLOW) } - public get isLockedFromEdits(): boolean { + public checkIsLockedFromEdits(userPersistentId: string): boolean { const lockedReasonIsInReview = this.locks.some( (lock) => lock.reason === DatasetLockReason.IN_REVIEW ) - // If the lock reason is workflow and the workflow userId is the same as the current user, then the user can edit - // TODO - Ask how we want to manage pending workflows + + if ( + this.locks.some( + (lock) => + lock.reason === DatasetLockReason.WORKFLOW && lock.userPersistentId === userPersistentId + ) + ) { + return false + } return this.isLocked && !(lockedReasonIsInReview && this.permissions.canPublishDataset) } diff --git a/src/dataset/infrastructure/mappers/JSDatasetMapper.ts b/src/dataset/infrastructure/mappers/JSDatasetMapper.ts index 77a8c3031..d4475c287 100644 --- a/src/dataset/infrastructure/mappers/JSDatasetMapper.ts +++ b/src/dataset/infrastructure/mappers/JSDatasetMapper.ts @@ -3,7 +3,8 @@ import { DatasetMetadataBlock as JSDatasetMetadataBlock, DatasetMetadataBlocks as JSDatasetMetadataBlocks, DatasetMetadataFields as JSDatasetMetadataFields, - DatasetVersionInfo as JSDatasetVersionInfo + DatasetVersionInfo as JSDatasetVersionInfo, + DatasetLock as JSDatasetLock } from '@iqss/dataverse-client-javascript' import { DatasetVersionState as JSDatasetVersionState } from '@iqss/dataverse-client-javascript/dist/datasets/domain/models/Dataset' import { @@ -14,7 +15,9 @@ import { DatasetMetadataFields, DatasetVersion, MetadataBlockName, - PrivateUrl + PrivateUrl, + DatasetLock, + DatasetLockReason } from '../../domain/models/Dataset' export class JSDatasetMapper { @@ -22,6 +25,7 @@ export class JSDatasetMapper { jsDataset: JSDataset, citation: string, summaryFieldsNames: string[], + jsDatasetLocks: JSDatasetLock[], requestedVersion?: string, privateUrl?: PrivateUrl ): Dataset { @@ -45,7 +49,7 @@ export class JSDatasetMapper { canManageFilesPermissions: true, canDeleteDataset: true }, // TODO Connect with dataset permissions - [], // TODO Connect with dataset locks + JSDatasetMapper.toLocks(jsDatasetLocks), true, // TODO Connect with dataset hasValidTermsOfAccess true, // TODO Connect with dataset isValid jsDataset.versionInfo.releaseTime !== undefined && @@ -185,4 +189,13 @@ export class JSDatasetMapper { return extraFields } + + static toLocks(jsDatasetLocks: JSDatasetLock[]): DatasetLock[] { + return jsDatasetLocks.map((jsDatasetLock) => { + return { + userPersistentId: jsDatasetLock.userId, + reason: jsDatasetLock.lockType as unknown as DatasetLockReason + } + }) + } } diff --git a/src/dataset/infrastructure/repositories/DatasetJSDataverseRepository.ts b/src/dataset/infrastructure/repositories/DatasetJSDataverseRepository.ts index c3fc7fbf0..239724296 100644 --- a/src/dataset/infrastructure/repositories/DatasetJSDataverseRepository.ts +++ b/src/dataset/infrastructure/repositories/DatasetJSDataverseRepository.ts @@ -7,7 +7,9 @@ import { Dataset as JSDataset, getPrivateUrlDataset, getPrivateUrlDatasetCitation, - ReadError + ReadError, + getDatasetLocks, + DatasetLock as JSDatasetLock } from '@iqss/dataverse-client-javascript' import { JSDatasetMapper } from '../mappers/JSDatasetMapper' @@ -23,11 +25,24 @@ export class DatasetJSDataverseRepository implements DatasetRepository { Promise.all([ jsDataset, getDatasetSummaryFieldNames.execute(), - getDatasetCitation.execute(jsDataset.id, this.versionToVersionId(version)) + getDatasetCitation.execute(jsDataset.id, this.versionToVersionId(version)), + getDatasetLocks.execute(jsDataset.id) ]) ) - .then(([jsDataset, summaryFieldsNames, citation]: [JSDataset, string[], string]) => - JSDatasetMapper.toDataset(jsDataset, citation, summaryFieldsNames, requestedVersion) + .then( + ([jsDataset, summaryFieldsNames, citation, jsDatasetLocks]: [ + JSDataset, + string[], + string, + JSDatasetLock[] + ]) => + JSDatasetMapper.toDataset( + jsDataset, + citation, + summaryFieldsNames, + jsDatasetLocks, + requestedVersion + ) ) .catch((error: ReadError) => { if (!version) { @@ -42,9 +57,9 @@ export class DatasetJSDataverseRepository implements DatasetRepository { getPrivateUrlDataset.execute(privateUrlToken), getDatasetSummaryFieldNames.execute(), getPrivateUrlDatasetCitation.execute(privateUrlToken) - ]) + ]) // TODO - Add getDatasetLocks.execute(privateUrlToken) when it is available in js-dataverse .then(([jsDataset, summaryFieldsNames, citation]: [JSDataset, string[], string]) => - JSDatasetMapper.toDataset(jsDataset, citation, summaryFieldsNames, undefined) + JSDatasetMapper.toDataset(jsDataset, citation, summaryFieldsNames, []) ) .catch((error: ReadError) => { throw new Error(error.message) diff --git a/src/sections/dataset/dataset-action-buttons/edit-dataset-menu/EditDatasetMenu.tsx b/src/sections/dataset/dataset-action-buttons/edit-dataset-menu/EditDatasetMenu.tsx index 326518a5e..798e2d451 100644 --- a/src/sections/dataset/dataset-action-buttons/edit-dataset-menu/EditDatasetMenu.tsx +++ b/src/sections/dataset/dataset-action-buttons/edit-dataset-menu/EditDatasetMenu.tsx @@ -4,13 +4,16 @@ import { EditDatasetPermissionsMenu } from './EditDatasetPermissionsMenu' import { DeleteDatasetButton } from './DeleteDatasetButton' import { DeaccessionDatasetButton } from './DeaccessionDatasetButton' import { useTranslation } from 'react-i18next' +import { useSession } from '../../../session/SessionContext' interface EditDatasetMenuProps { dataset: Dataset } export function EditDatasetMenu({ dataset }: EditDatasetMenuProps) { - if (!dataset.permissions.canUpdateDataset) { + const { user } = useSession() + + if (!user || !dataset.permissions.canUpdateDataset) { return <> } @@ -21,7 +24,7 @@ export function EditDatasetMenu({ dataset }: EditDatasetMenuProps) { title={t('datasetActionButtons.editDataset.title')} asButtonGroup variant="secondary" - disabled={dataset.isLockedFromEdits}> + disabled={dataset.checkIsLockedFromEdits(user.persistentId)}> {t('datasetActionButtons.editDataset.filesUpload')} diff --git a/src/sections/dataset/dataset-action-buttons/publish-dataset-menu/PublishDatasetMenu.tsx b/src/sections/dataset/dataset-action-buttons/publish-dataset-menu/PublishDatasetMenu.tsx index 58ec23cd8..ac7f9cc0d 100644 --- a/src/sections/dataset/dataset-action-buttons/publish-dataset-menu/PublishDatasetMenu.tsx +++ b/src/sections/dataset/dataset-action-buttons/publish-dataset-menu/PublishDatasetMenu.tsx @@ -2,15 +2,18 @@ import { Dataset, DatasetPublishingStatus } from '../../../../dataset/domain/mod import { DropdownButton, DropdownButtonItem } from '@iqss/dataverse-design-system' import { ChangeCurationStatusMenu } from './ChangeCurationStatusMenu' import { useTranslation } from 'react-i18next' +import { useSession } from '../../../session/SessionContext' interface PublishDatasetMenuProps { dataset: Dataset } export function PublishDatasetMenu({ dataset }: PublishDatasetMenuProps) { + const { user } = useSession() if ( !dataset.version.isLatest || dataset.version.publishingStatus !== DatasetPublishingStatus.DRAFT || + !user || !dataset.permissions.canPublishDataset ) { return <> @@ -24,7 +27,9 @@ export function PublishDatasetMenu({ dataset }: PublishDatasetMenuProps) { asButtonGroup variant="secondary" disabled={ - dataset.isLockedFromPublishing || !dataset.hasValidTermsOfAccess || !dataset.isValid + dataset.checkIsLockedFromPublishing(user.persistentId) || + !dataset.hasValidTermsOfAccess || + !dataset.isValid }> {t('datasetActionButtons.publish.publish')} {dataset.version.isInReview && ( diff --git a/src/sections/dataset/dataset-action-buttons/submit-for-review-button/SubmitForReviewButton.tsx b/src/sections/dataset/dataset-action-buttons/submit-for-review-button/SubmitForReviewButton.tsx index 1f9c18a3a..b352b4065 100644 --- a/src/sections/dataset/dataset-action-buttons/submit-for-review-button/SubmitForReviewButton.tsx +++ b/src/sections/dataset/dataset-action-buttons/submit-for-review-button/SubmitForReviewButton.tsx @@ -1,17 +1,20 @@ import { Dataset, DatasetPublishingStatus } from '../../../../dataset/domain/models/Dataset' import { Button } from '@iqss/dataverse-design-system' import { useTranslation } from 'react-i18next' +import { useSession } from '../../../session/SessionContext' interface SubmitForReviewButtonProps { dataset: Dataset } export function SubmitForReviewButton({ dataset }: SubmitForReviewButtonProps) { + const { user } = useSession() if ( !dataset.version.isLatest || dataset.version.publishingStatus !== DatasetPublishingStatus.DRAFT || dataset.isLockedInWorkflow || dataset.permissions.canPublishDataset || + !user || !dataset.permissions.canUpdateDataset ) { return <> @@ -22,7 +25,9 @@ export function SubmitForReviewButton({ dataset }: SubmitForReviewButtonProps) { ) diff --git a/src/sections/dataset/dataset-files/file-criteria-form/FileCriteriaForm.tsx b/src/sections/dataset/dataset-files/file-criteria-form/FileCriteriaForm.tsx index 5096d4001..26194bc35 100644 --- a/src/sections/dataset/dataset-files/file-criteria-form/FileCriteriaForm.tsx +++ b/src/sections/dataset/dataset-files/file-criteria-form/FileCriteriaForm.tsx @@ -18,31 +18,36 @@ export function FileCriteriaForm({ onCriteriaChange, filesCountInfo }: FileCriteriaInputsProps) { - if (!filesCountInfo || filesCountInfo.total < MINIMUM_FILES_TO_SHOW_CRITERIA_INPUTS) { - return <> - } + const showFileCriteriaInputs = + filesCountInfo && filesCountInfo.total >= MINIMUM_FILES_TO_SHOW_CRITERIA_INPUTS return ( -
- - - - - - - - - - - - - - - - -
+
+
+ + {showFileCriteriaInputs && ( + + + + )} + + + + + {showFileCriteriaInputs && ( + + + + + + + + + )} +
+
) } diff --git a/src/sections/dataset/dataset-files/files-table/file-actions/edit-files-menu/EditFilesMenu.tsx b/src/sections/dataset/dataset-files/files-table/file-actions/edit-files-menu/EditFilesMenu.tsx index 052d5957e..23f34bd02 100644 --- a/src/sections/dataset/dataset-files/files-table/file-actions/edit-files-menu/EditFilesMenu.tsx +++ b/src/sections/dataset/dataset-files/files-table/file-actions/edit-files-menu/EditFilesMenu.tsx @@ -30,7 +30,7 @@ export function EditFilesMenu({ files, fileSelection }: EditFilesMenuProps) { variant="secondary" id="edit-files-menu" title={t('actions.editFilesMenu.title')} - disabled={dataset.isLockedFromEdits || !dataset.hasValidTermsOfAccess} + disabled={dataset.checkIsLockedFromEdits(user.persistentId) || !dataset.hasValidTermsOfAccess} icon={}> diff --git a/src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/file-options-menu/FileOptionsMenu.tsx b/src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/file-options-menu/FileOptionsMenu.tsx index c81d34c77..f336fe594 100644 --- a/src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/file-options-menu/FileOptionsMenu.tsx +++ b/src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/file-options-menu/FileOptionsMenu.tsx @@ -24,7 +24,7 @@ export function FileOptionsMenu({ file }: { file: File }) { {t('actions.optionsMenu.title')}}>