diff --git a/src/dataset/domain/models/Dataset.ts b/src/dataset/domain/models/Dataset.ts index afce970e2..4a40e35d9 100644 --- a/src/dataset/domain/models/Dataset.ts +++ b/src/dataset/domain/models/Dataset.ts @@ -210,7 +210,8 @@ export class DatasetVersion { public readonly minorNumber: number, public readonly status: DatasetStatus, public readonly isLatest: boolean, - public readonly isInReview: boolean + public readonly isInReview: boolean, + public readonly latestVersionStatus: DatasetStatus ) {} toString(): string { @@ -222,6 +223,9 @@ export interface DatasetPermissions { canDownloadFiles: boolean canUpdateDataset: boolean canPublishDataset: boolean + canManageDatasetPermissions: boolean + canManageFilesPermissions: boolean + canDeleteDataset: boolean } export interface DatasetLock { @@ -251,7 +255,8 @@ export class Dataset { public readonly license: DatasetLicense, public readonly metadataBlocks: DatasetMetadataBlocks, public readonly permissions: DatasetPermissions, - public readonly locks: DatasetLock[] + public readonly locks: DatasetLock[], + public readonly hasValidTermsOfAccess: boolean ) {} public getTitle(): string { @@ -259,11 +264,7 @@ export class Dataset { } public get isLockedFromPublishing(): boolean { - const lockedReasonIsInReview = this.locks.some( - (lock) => lock.reason === DatasetLockReason.IN_REVIEW - ) - - return this.isLocked && !(lockedReasonIsInReview && this.permissions.canPublishDataset) + return this.isLockedFromEdits } public get isLocked(): boolean { @@ -274,6 +275,16 @@ export class Dataset { return this.locks.some((lock) => lock.reason === DatasetLockReason.WORKFLOW) } + public get isLockedFromEdits(): 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 + + return this.isLocked && !(lockedReasonIsInReview && this.permissions.canPublishDataset) + } + static Builder = class { public readonly labels: DatasetLabel[] = [] @@ -285,7 +296,8 @@ export class Dataset { public readonly license: DatasetLicense = defaultLicense, public readonly metadataBlocks: DatasetMetadataBlocks, public readonly permissions: DatasetPermissions, - public readonly locks: DatasetLock[] + public readonly locks: DatasetLock[], + public readonly hasValidTermsOfAccess: boolean ) { this.withLabels() } @@ -345,7 +357,8 @@ export class Dataset { this.license, this.metadataBlocks, this.permissions, - this.locks + this.locks, + this.hasValidTermsOfAccess ) } } diff --git a/src/dataset/infrastructure/mappers/JSDatasetMapper.ts b/src/dataset/infrastructure/mappers/JSDatasetMapper.ts index 868f5cf69..e9b4dff35 100644 --- a/src/dataset/infrastructure/mappers/JSDatasetMapper.ts +++ b/src/dataset/infrastructure/mappers/JSDatasetMapper.ts @@ -35,6 +35,7 @@ export class JSDatasetMapper { jsDatasetVersionInfo.minorNumber, JSDatasetMapper.toStatus(jsDatasetVersionInfo.state), false, + false, false ) } diff --git a/src/sections/dataset/dataset-action-buttons/DatasetActionButtons.tsx b/src/sections/dataset/dataset-action-buttons/DatasetActionButtons.tsx index c8ac4be0e..f5d535cb9 100644 --- a/src/sections/dataset/dataset-action-buttons/DatasetActionButtons.tsx +++ b/src/sections/dataset/dataset-action-buttons/DatasetActionButtons.tsx @@ -4,6 +4,7 @@ import { AccessDatasetMenu } from './access-dataset-menu/AccessDatasetMenu' import { PublishDatasetMenu } from './publish-dataset-menu/PublishDatasetMenu' import styles from './DatasetActionButtons.module.scss' import { SubmitForReviewButton } from './submit-for-review-button/SubmitForReviewButton' +import { EditDatasetMenu } from './edit-dataset-menu/EditDatasetMenu' interface DatasetActionButtonsProps { dataset: Dataset @@ -15,6 +16,7 @@ export function DatasetActionButtons({ dataset }: DatasetActionButtonsProps) { + ) } diff --git a/src/sections/dataset/dataset-action-buttons/edit-dataset-menu/DeaccessionDatasetButton.tsx b/src/sections/dataset/dataset-action-buttons/edit-dataset-menu/DeaccessionDatasetButton.tsx new file mode 100644 index 000000000..c28831947 --- /dev/null +++ b/src/sections/dataset/dataset-action-buttons/edit-dataset-menu/DeaccessionDatasetButton.tsx @@ -0,0 +1,18 @@ +import { Dataset, DatasetStatus } from '../../../../dataset/domain/models/Dataset' +import { DropdownButtonItem, DropdownSeparator } from '@iqss/dataverse-design-system' + +interface DeaccessionDatasetButtonProps { + dataset: Dataset +} +export function DeaccessionDatasetButton({ dataset }: DeaccessionDatasetButtonProps) { + if (dataset.version.status !== DatasetStatus.RELEASED || !dataset.permissions.canPublishDataset) { + return <> + } + + return ( + <> + + Deaccession Dataset + + ) +} diff --git a/src/sections/dataset/dataset-action-buttons/edit-dataset-menu/DeleteDatasetButton.tsx b/src/sections/dataset/dataset-action-buttons/edit-dataset-menu/DeleteDatasetButton.tsx new file mode 100644 index 000000000..bbaba2852 --- /dev/null +++ b/src/sections/dataset/dataset-action-buttons/edit-dataset-menu/DeleteDatasetButton.tsx @@ -0,0 +1,25 @@ +import { Dataset, DatasetStatus } from '../../../../dataset/domain/models/Dataset' +import { DropdownButtonItem, DropdownSeparator } from '@iqss/dataverse-design-system' + +interface DeleteDatasetButtonProps { + dataset: Dataset +} +export function DeleteDatasetButton({ dataset }: DeleteDatasetButtonProps) { + if ( + !dataset.permissions.canDeleteDataset || + dataset.version.latestVersionStatus !== DatasetStatus.DRAFT + ) { + return <> + } + + return ( + <> + + + {dataset.version.status === DatasetStatus.RELEASED + ? 'Delete Draft Version' + : 'Delete Dataset'} + + + ) +} 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 new file mode 100644 index 000000000..e36a8c8c9 --- /dev/null +++ b/src/sections/dataset/dataset-action-buttons/edit-dataset-menu/EditDatasetMenu.tsx @@ -0,0 +1,38 @@ +import { Dataset } from '../../../../dataset/domain/models/Dataset' +import { DropdownButton, DropdownButtonItem } from '@iqss/dataverse-design-system' +import { EditDatasetPermissionsMenu } from './EditDatasetPermissionsMenu' +import { DeleteDatasetButton } from './DeleteDatasetButton' +import { DeaccessionDatasetButton } from './DeaccessionDatasetButton' + +interface EditDatasetMenuProps { + dataset: Dataset +} + +export function EditDatasetMenu({ dataset }: EditDatasetMenuProps) { + if (!dataset.permissions.canUpdateDataset) { + return <> + } + + return ( + + + Files (Upload) + + Metadata + Terms + + {(dataset.permissions.canManageDatasetPermissions || + dataset.permissions.canManageFilesPermissions) && ( + Private URL + )} + Thumbnails + Widgets + + + + ) +} diff --git a/src/sections/dataset/dataset-action-buttons/edit-dataset-menu/EditDatasetPermissionsMenu.tsx b/src/sections/dataset/dataset-action-buttons/edit-dataset-menu/EditDatasetPermissionsMenu.tsx new file mode 100644 index 000000000..dda952544 --- /dev/null +++ b/src/sections/dataset/dataset-action-buttons/edit-dataset-menu/EditDatasetPermissionsMenu.tsx @@ -0,0 +1,46 @@ +import { Dataset } from '../../../../dataset/domain/models/Dataset' +import { DropdownButton, DropdownButtonItem } from '@iqss/dataverse-design-system' +import { useSettings } from '../../../settings/SettingsContext' +import { useEffect, useState } from 'react' +import { SettingName } from '../../../../settings/domain/models/Setting' +import { HasPublicStore } from '../../../../settings/domain/models/HasPublicStore' + +interface EditDatasetPermissionsMenuProps { + dataset: Dataset +} +export function EditDatasetPermissionsMenu({ dataset }: EditDatasetPermissionsMenuProps) { + if ( + !dataset.permissions.canManageDatasetPermissions && + !dataset.permissions.canManageFilesPermissions + ) { + return <> + } + + const { getSettingByName } = useSettings() + const [hasPublicStore, setHasPublicStore] = useState(false) + + useEffect(() => { + getSettingByName(SettingName.HAS_PUBLIC_STORE) + .then((hasPublicStoreSetting) => { + setHasPublicStore(hasPublicStoreSetting.value) + }) + .catch((error) => { + console.error(error) + }) + }, [getSettingByName]) + + if (hasPublicStore) { + return Permissions + } + + return ( + + {dataset.permissions.canManageDatasetPermissions && ( + Dataset + )} + {dataset.permissions.canManageFilesPermissions && ( + File + )} + + ) +} diff --git a/src/settings/domain/models/HasPublicStore.ts b/src/settings/domain/models/HasPublicStore.ts new file mode 100644 index 000000000..9f37def8a --- /dev/null +++ b/src/settings/domain/models/HasPublicStore.ts @@ -0,0 +1 @@ +export type HasPublicStore = boolean diff --git a/src/settings/domain/models/Setting.ts b/src/settings/domain/models/Setting.ts index 52c2bc238..48fcfc1ca 100644 --- a/src/settings/domain/models/Setting.ts +++ b/src/settings/domain/models/Setting.ts @@ -1,6 +1,8 @@ export enum SettingName { ZIP_DOWNLOAD_LIMIT = 'ZIP_DOWNLOAD_LIMIT', - ALLOWED_EXTERNAL_STATUSES = 'ALLOWED_EXTERNAL_STATUSES' + ALLOWED_EXTERNAL_STATUSES = 'ALLOWED_EXTERNAL_STATUSES', + + HAS_PUBLIC_STORE = 'HAS_PUBLIC_STORE' } export interface Setting { diff --git a/src/stories/dataset/DatasetMockData.ts b/src/stories/dataset/DatasetMockData.ts index 4d99e1587..fff377601 100644 --- a/src/stories/dataset/DatasetMockData.ts +++ b/src/stories/dataset/DatasetMockData.ts @@ -15,7 +15,7 @@ export const DatasetMockData = (props?: Partial, anonymized = false): D citation: `${ anonymized ? 'Author name(s) withheld' : 'Bennet, Elizabeth; Darcy, Fitzwilliam' }, 2023, "Dataset Title", https://doi.org/10.5072/FK2/BUDNRV, Root, V1`, - version: new DatasetVersion(1, 0, DatasetStatus.RELEASED, false, false), + version: new DatasetVersion(1, 0, DatasetStatus.RELEASED, false, false, false), labels: [ { value: 'Version 1.0', semanticMeaning: DatasetLabelSemanticMeaning.FILE }, { value: DatasetLabelValue.DRAFT, semanticMeaning: DatasetLabelSemanticMeaning.DATASET } diff --git a/src/stories/dataset/dataset-action-buttons/DatasetActionButtons.stories.tsx b/src/stories/dataset/dataset-action-buttons/DatasetActionButtons.stories.tsx index 000209a43..d7dbcfd7a 100644 --- a/src/stories/dataset/dataset-action-buttons/DatasetActionButtons.stories.tsx +++ b/src/stories/dataset/dataset-action-buttons/DatasetActionButtons.stories.tsx @@ -1,7 +1,6 @@ import { Meta, StoryObj } from '@storybook/react' import { WithI18next } from '../../WithI18next' import { WithSettings } from '../../WithSettings' -import { WithLayout } from '../../WithLayout' import { DatasetActionButtons } from '../../../sections/dataset/dataset-action-buttons/DatasetActionButtons' import { DatasetMother, diff --git a/src/stories/dataset/dataset-citation/DatasetCitation.stories.tsx b/src/stories/dataset/dataset-citation/DatasetCitation.stories.tsx index 5220b1005..3f99a7cf9 100644 --- a/src/stories/dataset/dataset-citation/DatasetCitation.stories.tsx +++ b/src/stories/dataset/dataset-citation/DatasetCitation.stories.tsx @@ -31,7 +31,7 @@ export const DraftVersion: Story = { const dataset = DatasetMockData({ citation: 'Admin, Dataverse, 2023, "Dataset Title", https://doi.org/10.5072/FK2/BUDNRV, Root, DRAFT VERSION', - version: new DatasetVersion(1, 0, DatasetStatus.DRAFT, false, false) + version: new DatasetVersion(1, 0, DatasetStatus.DRAFT, false, false, false) }) /* @@ -52,7 +52,7 @@ export const Deaccessioned: Story = { const dataset = DatasetMockData({ citation: 'Admin, Dataverse, 2023, "Dataset Title", https://doi.org/10.5072/FK2/BUDNRV, Root, V1 DEACCESSIONED VERSION', - version: new DatasetVersion(1, 0, DatasetStatus.DEACCESSIONED, false, false) + version: new DatasetVersion(1, 0, DatasetStatus.DEACCESSIONED, false, false, false) }) /* diff --git a/tests/component/dataset/domain/models/DatasetMother.ts b/tests/component/dataset/domain/models/DatasetMother.ts index 8b8956540..c49a3379d 100644 --- a/tests/component/dataset/domain/models/DatasetMother.ts +++ b/tests/component/dataset/domain/models/DatasetMother.ts @@ -20,28 +20,48 @@ export class DatasetVersionMother { props?.minorNumber ?? 0, props?.status ?? DatasetStatus.RELEASED, props?.isLatest ?? false, - props?.isInReview ?? false + props?.isInReview ?? false, + props?.latestVersionStatus ?? DatasetStatus.RELEASED ) } static createReleased(): DatasetVersion { - return new DatasetVersion(1, 0, DatasetStatus.RELEASED, false, false) + return new DatasetVersion(1, 0, DatasetStatus.RELEASED, false, false, DatasetStatus.RELEASED) } static createDeaccessioned(): DatasetVersion { - return new DatasetVersion(1, 0, DatasetStatus.DEACCESSIONED, false, false) + return new DatasetVersion( + 1, + 0, + DatasetStatus.DEACCESSIONED, + false, + false, + DatasetStatus.RELEASED + ) } static createDraftAsLatestVersion(): DatasetVersion { - return new DatasetVersion(1, 0, DatasetStatus.DRAFT, true, false) + return new DatasetVersion(1, 0, DatasetStatus.DRAFT, true, false, DatasetStatus.RELEASED) } static createDraft(): DatasetVersion { - return new DatasetVersion(1, 0, DatasetStatus.DRAFT, false, false) + return new DatasetVersion(1, 0, DatasetStatus.DRAFT, false, false, DatasetStatus.RELEASED) } static createDraftAsLatestVersionInReview(): DatasetVersion { - return new DatasetVersion(1, 0, DatasetStatus.DRAFT, true, true) + return new DatasetVersion(1, 0, DatasetStatus.DRAFT, true, true, DatasetStatus.RELEASED) + } + + static createReleasedWithLatestVersionIsADraft(): DatasetVersion { + return new DatasetVersion(1, 0, DatasetStatus.RELEASED, false, false, DatasetStatus.DRAFT) + } + + static createDraftWithLatestVersionIsADraft(): DatasetVersion { + return new DatasetVersion(1, 0, DatasetStatus.DRAFT, false, false, DatasetStatus.DRAFT) + } + + static createWithLatestVersionIsNotADraft(): DatasetVersion { + return new DatasetVersion(1, 0, DatasetStatus.DRAFT, false, false, DatasetStatus.RELEASED) } } @@ -51,6 +71,9 @@ export class DatasetPermissionsMother { canDownloadFiles: faker.datatype.boolean(), canUpdateDataset: faker.datatype.boolean(), canPublishDataset: faker.datatype.boolean(), + canManageDatasetPermissions: faker.datatype.boolean(), + canManageFilesPermissions: faker.datatype.boolean(), + canDeleteDataset: faker.datatype.boolean(), ...props } } @@ -75,7 +98,10 @@ export class DatasetPermissionsMother { return this.create({ canDownloadFiles: true, canUpdateDataset: true, - canPublishDataset: true + canPublishDataset: true, + canManageDatasetPermissions: true, + canManageFilesPermissions: true, + canDeleteDataset: true }) } @@ -94,6 +120,30 @@ export class DatasetPermissionsMother { canPublishDataset: false }) } + + static createWithManageDatasetPermissionsAllowed(): DatasetPermissions { + return this.create({ canManageDatasetPermissions: true }) + } + + static createWithManageFilesPermissionsAllowed(): DatasetPermissions { + return this.create({ canManageFilesPermissions: true }) + } + + static createWithManagePermissionsNotAllowed(): DatasetPermissions { + return this.create({ canManageDatasetPermissions: false, canManageFilesPermissions: false }) + } + + static createWithManagePermissionsAllowed(): DatasetPermissions { + return this.create({ canManageDatasetPermissions: true, canManageFilesPermissions: true }) + } + + static createWithDeleteDatasetAllowed(): DatasetPermissions { + return this.create({ canDeleteDataset: true }) + } + + static createWithDeleteDatasetNotAllowed(): DatasetPermissions { + return this.create({ canDeleteDataset: false }) + } } export class DatasetLockMother { @@ -112,6 +162,10 @@ export class DatasetLockMother { static createLockedInReview(): DatasetLock { return this.create({ reason: DatasetLockReason.IN_REVIEW }) } + + static createLockedInEditInProgress(): DatasetLock { + return this.create({ reason: DatasetLockReason.EDIT_IN_PROGRESS }) + } } export class DatasetMother { @@ -206,6 +260,7 @@ export class DatasetMother { ] as DatasetMetadataBlocks, permissions: DatasetPermissionsMother.create(), locks: [], + hasValidTermsOfAccess: faker.datatype.boolean(), ...props } @@ -217,7 +272,8 @@ export class DatasetMother { dataset.license, dataset.metadataBlocks, dataset.permissions, - dataset.locks + dataset.locks, + dataset.hasValidTermsOfAccess ).build() } diff --git a/tests/component/sections/dataset/dataset-action-buttons/DatasetActionButtons.spec.tsx b/tests/component/sections/dataset/dataset-action-buttons/DatasetActionButtons.spec.tsx index 1e9d3e97b..f23bd04cf 100644 --- a/tests/component/sections/dataset/dataset-action-buttons/DatasetActionButtons.spec.tsx +++ b/tests/component/sections/dataset/dataset-action-buttons/DatasetActionButtons.spec.tsx @@ -7,7 +7,7 @@ import { const dataset = DatasetMother.create() describe('DatasetActionButtons', () => { - it('renders the DatasetActionButtons', () => { + it('renders the DatasetActionButtons with the Publish button', () => { const dataset = DatasetMother.create({ version: DatasetVersionMother.createDraftAsLatestVersion(), permissions: DatasetPermissionsMother.createWithAllAllowed() @@ -18,5 +18,24 @@ describe('DatasetActionButtons', () => { cy.findByRole('group', { name: 'Dataset Action Buttons' }).should('exist') cy.findByRole('button', { name: 'Access Dataset' }).should('exist') cy.findByRole('button', { name: 'Publish Dataset' }).should('exist') + cy.findByRole('button', { name: 'Edit Dataset' }).should('exist') + }) + + it('renders the DatasetActionButtons with the Submit for Review button', () => { + const dataset = DatasetMother.create({ + version: DatasetVersionMother.createDraftAsLatestVersion(), + permissions: DatasetPermissionsMother.create({ + canDownloadFiles: true, + canUpdateDataset: true, + canPublishDataset: false + }) + }) + + cy.customMount() + + cy.findByRole('group', { name: 'Dataset Action Buttons' }).should('exist') + cy.findByRole('button', { name: 'Access Dataset' }).should('exist') + cy.findByRole('button', { name: 'Submit for Review' }).should('exist') + cy.findByRole('button', { name: 'Edit Dataset' }).should('exist') }) }) diff --git a/tests/component/sections/dataset/dataset-action-buttons/edit-dataset-menu/DeaccessionDatasetButton.spec.tsx b/tests/component/sections/dataset/dataset-action-buttons/edit-dataset-menu/DeaccessionDatasetButton.spec.tsx new file mode 100644 index 000000000..50d64a5ed --- /dev/null +++ b/tests/component/sections/dataset/dataset-action-buttons/edit-dataset-menu/DeaccessionDatasetButton.spec.tsx @@ -0,0 +1,42 @@ +import { + DatasetMother, + DatasetPermissionsMother, + DatasetVersionMother +} from '../../../../dataset/domain/models/DatasetMother' +import { DeaccessionDatasetButton } from '../../../../../../src/sections/dataset/dataset-action-buttons/edit-dataset-menu/DeaccessionDatasetButton' + +describe('DeaccessionDatasetButton', () => { + it('renders the DeaccessionDatasetButton if the user has publish dataset permissions and the dataset is released', () => { + const dataset = DatasetMother.create({ + permissions: DatasetPermissionsMother.createWithPublishingDatasetAllowed(), + version: DatasetVersionMother.createReleased() + }) + + cy.customMount() + + cy.findByRole('separator').should('exist') + cy.findByRole('button', { name: 'Deaccession Dataset' }).should('exist') + }) + + it('does not render the DeaccessionDatasetButton if the user does not have publish dataset permissions', () => { + const dataset = DatasetMother.create({ + permissions: DatasetPermissionsMother.createWithPublishingDatasetNotAllowed(), + version: DatasetVersionMother.createReleased() + }) + + cy.customMount() + + cy.findByRole('button', { name: 'Deaccession Dataset' }).should('not.exist') + }) + + it('does not render the DeaccessionDatasetButton if the dataset is not released', () => { + const dataset = DatasetMother.create({ + permissions: DatasetPermissionsMother.createWithPublishingDatasetAllowed(), + version: DatasetVersionMother.createDraft() + }) + + cy.customMount() + + cy.findByRole('button', { name: 'Deaccession Dataset' }).should('not.exist') + }) +}) diff --git a/tests/component/sections/dataset/dataset-action-buttons/edit-dataset-menu/DeleteDatasetButton.spec.tsx b/tests/component/sections/dataset/dataset-action-buttons/edit-dataset-menu/DeleteDatasetButton.spec.tsx new file mode 100644 index 000000000..80c8720fb --- /dev/null +++ b/tests/component/sections/dataset/dataset-action-buttons/edit-dataset-menu/DeleteDatasetButton.spec.tsx @@ -0,0 +1,69 @@ +import { DeleteDatasetButton } from '../../../../../../src/sections/dataset/dataset-action-buttons/edit-dataset-menu/DeleteDatasetButton' +import { + DatasetMother, + DatasetPermissionsMother, + DatasetVersionMother +} from '../../../../dataset/domain/models/DatasetMother' + +describe('DeleteDatasetButton', () => { + it('renders the DeleteDatasetButton if the user has delete dataset permissions and the latest version is a draft', () => { + const dataset = DatasetMother.create({ + permissions: DatasetPermissionsMother.createWithDeleteDatasetAllowed(), + locks: [], + version: DatasetVersionMother.createReleasedWithLatestVersionIsADraft() + }) + + cy.customMount() + + cy.findByRole('separator').should('exist') + cy.findByRole('button', { name: /Delete/ }).should('exist') + }) + + it('renders the Delete Dataset button if the dataset is not released', () => { + const dataset = DatasetMother.create({ + permissions: DatasetPermissionsMother.createWithDeleteDatasetAllowed(), + locks: [], + version: DatasetVersionMother.createDraftWithLatestVersionIsADraft() + }) + + cy.customMount() + + cy.findByRole('button', { name: 'Delete Dataset' }).should('exist') + }) + + it('renders the Delete Draft Version if the dataset is released', () => { + const dataset = DatasetMother.create({ + permissions: DatasetPermissionsMother.createWithDeleteDatasetAllowed(), + locks: [], + version: DatasetVersionMother.createReleasedWithLatestVersionIsADraft() + }) + + cy.customMount() + + cy.findByRole('button', { name: 'Delete Draft Version' }).should('exist') + }) + + it('does not render the DeleteDatasetButton if the user does not have delete dataset permissions', () => { + const dataset = DatasetMother.create({ + permissions: DatasetPermissionsMother.createWithDeleteDatasetNotAllowed(), + locks: [], + version: DatasetVersionMother.createReleasedWithLatestVersionIsADraft() + }) + + cy.customMount() + + cy.findByRole('button', { name: /Delete/ }).should('not.exist') + }) + + it('does not render the DeleteDatasetButton if the latest version is not a draft', () => { + const dataset = DatasetMother.create({ + permissions: DatasetPermissionsMother.createWithDeleteDatasetAllowed(), + locks: [], + version: DatasetVersionMother.createWithLatestVersionIsNotADraft() + }) + + cy.customMount() + + cy.findByRole('button', { name: /Delete/ }).should('not.exist') + }) +}) diff --git a/tests/component/sections/dataset/dataset-action-buttons/edit-dataset-menu/EditDatasetMenu.spec.tsx b/tests/component/sections/dataset/dataset-action-buttons/edit-dataset-menu/EditDatasetMenu.spec.tsx new file mode 100644 index 000000000..4083056ee --- /dev/null +++ b/tests/component/sections/dataset/dataset-action-buttons/edit-dataset-menu/EditDatasetMenu.spec.tsx @@ -0,0 +1,87 @@ +import { + DatasetLockMother, + DatasetMother, + DatasetPermissionsMother, + DatasetVersionMother +} from '../../../../dataset/domain/models/DatasetMother' +import { EditDatasetMenu } from '../../../../../../src/sections/dataset/dataset-action-buttons/edit-dataset-menu/EditDatasetMenu' + +describe('EditDatasetMenu', () => { + it('renders the EditDatasetMenu if the user has update dataset permissions', () => { + const dataset = DatasetMother.create({ + permissions: DatasetPermissionsMother.createWithAllAllowed(), + locks: [], + hasValidTermsOfAccess: true, + version: DatasetVersionMother.createReleasedWithLatestVersionIsADraft() + }) + + cy.customMount() + + cy.findByRole('button', { name: 'Edit Dataset' }).should('exist').should('be.enabled').click() + + cy.findByRole('button', { name: 'Files (Upload)' }).should('exist') + cy.findByRole('button', { name: 'Metadata' }).should('exist') + cy.findByRole('button', { name: 'Terms' }).should('exist') + cy.findByRole('button', { name: 'Thumbnails + Widgets' }).should('exist') + cy.findByRole('button', { name: /Delete/ }).should('exist') + cy.findByRole('button', { name: 'Permissions' }).should('exist') + cy.findByRole('button', { name: 'Private URL' }).should('exist') + cy.findByRole('button', { name: 'Deaccession Dataset' }).should('exist') + }) + + it('does not render the EditDatasetMenu if the user does not have update dataset permissions', () => { + const dataset = DatasetMother.create({ + permissions: DatasetPermissionsMother.createWithUpdateDatasetNotAllowed(), + locks: [] + }) + + cy.customMount() + + cy.findByRole('button', { name: 'Edit Dataset' }).should('not.exist') + }) + + it('renders the button disabled if the dataset is locked from edits', () => { + const dataset = DatasetMother.create({ + permissions: DatasetPermissionsMother.createWithUpdateDatasetAllowed(), + locks: [DatasetLockMother.createLockedInEditInProgress()] + }) + + cy.customMount() + + cy.findByRole('button', { name: 'Edit Dataset' }).should('exist').should('be.disabled') + }) + + it('renders some options enabled if the dataset has valid terms of access', () => { + const dataset = DatasetMother.create({ + permissions: DatasetPermissionsMother.createWithUpdateDatasetAllowed(), + locks: [], + hasValidTermsOfAccess: true + }) + + cy.customMount() + + cy.findByRole('button', { name: 'Edit Dataset' }).click() + cy.findByRole('button', { name: 'Files (Upload)' }) + .should('exist') + .should('not.have.class', 'disabled') + cy.findByRole('button', { name: 'Metadata' }) + .should('exist') + .should('not.have.class', 'disabled') + }) + + it('renders some options disabled if the dataset does not have valid terms of access', () => { + const dataset = DatasetMother.create({ + permissions: DatasetPermissionsMother.createWithUpdateDatasetAllowed(), + locks: [], + hasValidTermsOfAccess: false + }) + + cy.customMount() + + cy.findByRole('button', { name: 'Edit Dataset' }).click() + cy.findByRole('button', { name: 'Files (Upload)' }) + .should('exist') + .should('have.class', 'disabled') + cy.findByRole('button', { name: 'Metadata' }).should('exist').should('have.class', 'disabled') + }) +}) diff --git a/tests/component/sections/dataset/dataset-action-buttons/edit-dataset-menu/EditDatasetPermissionsMenu.spec.tsx b/tests/component/sections/dataset/dataset-action-buttons/edit-dataset-menu/EditDatasetPermissionsMenu.spec.tsx new file mode 100644 index 000000000..b43d3d3ac --- /dev/null +++ b/tests/component/sections/dataset/dataset-action-buttons/edit-dataset-menu/EditDatasetPermissionsMenu.spec.tsx @@ -0,0 +1,67 @@ +import { EditDatasetPermissionsMenu } from '../../../../../../src/sections/dataset/dataset-action-buttons/edit-dataset-menu/EditDatasetPermissionsMenu' +import { + DatasetMother, + DatasetPermissionsMother +} from '../../../../dataset/domain/models/DatasetMother' +import { SettingRepository } from '../../../../../../src/settings/domain/repositories/SettingRepository' +import { SettingMother } from '../../../../settings/domain/models/SettingMother' +import { SettingsProvider } from '../../../../../../src/sections/settings/SettingsProvider' + +describe('EditDatasetPermissionsMenu', () => { + it('renders the EditDatasetPermissionsMenu if the user has manage dataset permissions', () => { + const dataset = DatasetMother.create({ + permissions: DatasetPermissionsMother.createWithManageDatasetPermissionsAllowed(), + locks: [] + }) + + cy.customMount() + + cy.findByRole('button', { name: 'Permissions' }).should('exist').click() + cy.findByRole('button', { name: 'Dataset' }).should('exist') + }) + + it('renders the EditDatasetPermissionsMenu if the user has manage files permissions', () => { + const dataset = DatasetMother.create({ + permissions: DatasetPermissionsMother.createWithManageFilesPermissionsAllowed(), + locks: [] + }) + + cy.customMount() + + cy.findByRole('button', { name: 'Permissions' }).should('exist').click() + cy.findByRole('button', { name: 'File' }).should('exist') + }) + + it('renders the Permissions button with no options if there is public store', () => { + const dataset = DatasetMother.create({ + permissions: DatasetPermissionsMother.createWithManageFilesPermissionsAllowed(), + locks: [] + }) + + const settingRepository = {} as SettingRepository + settingRepository.getByName = cy.stub().resolves(SettingMother.createHasPublicStore(true)) + + cy.customMount( + + + + ) + + cy.wait(1000) // Wait for the settings to be loaded + + cy.findByRole('button', { name: 'Permissions' }).should('exist').click() + cy.findByRole('button', { name: 'File' }).should('not.exist') + cy.findByRole('button', { name: 'Dataset' }).should('not.exist') + }) + + it('does not render the EditDatasetPermissionsMenu if the user does not have manage dataset permissions or manage files permissions', () => { + const dataset = DatasetMother.create({ + permissions: DatasetPermissionsMother.createWithManagePermissionsNotAllowed(), + locks: [] + }) + + cy.customMount() + + cy.findByRole('button', { name: 'Permissions' }).should('not.exist') + }) +}) diff --git a/tests/component/sections/dataset/dataset-action-buttons/submit-for-review-button/SubmitForReviewButton.spec.tsx b/tests/component/sections/dataset/dataset-action-buttons/submit-for-review-button/SubmitForReviewButton.spec.tsx index e28feb45a..9e5678d14 100644 --- a/tests/component/sections/dataset/dataset-action-buttons/submit-for-review-button/SubmitForReviewButton.spec.tsx +++ b/tests/component/sections/dataset/dataset-action-buttons/submit-for-review-button/SubmitForReviewButton.spec.tsx @@ -5,7 +5,6 @@ import { DatasetPermissionsMother, DatasetVersionMother } from '../../../../dataset/domain/models/DatasetMother' -import { PublishDatasetMenu } from '../../../../../../src/sections/dataset/dataset-action-buttons/publish-dataset-menu/PublishDatasetMenu' import { DatasetLockReason } from '../../../../../../src/dataset/domain/models/Dataset' describe('SubmitForReviewButton', () => { diff --git a/tests/component/sections/dataset/dataset-citation/DatasetCitation.spec.tsx b/tests/component/sections/dataset/dataset-citation/DatasetCitation.spec.tsx index 043161cc0..fab3d3c2b 100644 --- a/tests/component/sections/dataset/dataset-citation/DatasetCitation.spec.tsx +++ b/tests/component/sections/dataset/dataset-citation/DatasetCitation.spec.tsx @@ -21,7 +21,7 @@ describe('DatasetCitation', () => { it('shows the draft tooltip when version is draft', () => { const dataset = DatasetMother.create({ - version: new DatasetVersion(1, 0, DatasetStatus.DRAFT, false, false) + version: new DatasetVersion(1, 0, DatasetStatus.DRAFT, false, false, false) }) cy.customMount() @@ -33,7 +33,7 @@ describe('DatasetCitation', () => { it('shows the deaccessioned tooltip when version is deaccessioned', () => { const dataset = DatasetMother.create({ - version: new DatasetVersion(1, 0, DatasetStatus.DEACCESSIONED, false, false) + version: new DatasetVersion(1, 0, DatasetStatus.DEACCESSIONED, false, false, false) }) cy.customMount() diff --git a/tests/component/settings/domain/models/SettingMother.ts b/tests/component/settings/domain/models/SettingMother.ts index 3451a12a8..59574ba60 100644 --- a/tests/component/settings/domain/models/SettingMother.ts +++ b/tests/component/settings/domain/models/SettingMother.ts @@ -22,4 +22,11 @@ export class SettingMother { value: value ? value : [faker.datatype.string(), faker.datatype.string()] } } + + static createHasPublicStore(value?: boolean): Setting { + return { + name: SettingName.HAS_PUBLIC_STORE, + value: value ? value : faker.datatype.boolean() + } + } } diff --git a/tests/e2e-integration/integration/datasets/DatasetJSDataverseRepository.spec.ts b/tests/e2e-integration/integration/datasets/DatasetJSDataverseRepository.spec.ts index 13ebb1423..cf6c4bfeb 100644 --- a/tests/e2e-integration/integration/datasets/DatasetJSDataverseRepository.spec.ts +++ b/tests/e2e-integration/integration/datasets/DatasetJSDataverseRepository.spec.ts @@ -102,7 +102,7 @@ describe('Dataset JSDataverse Repository', () => { throw new Error('Dataset not found') } const datasetExpected = datasetData(dataset.persistentId) - const newVersion = new DatasetVersion(1, 0, DatasetStatus.RELEASED, false, false) + const newVersion = new DatasetVersion(1, 0, DatasetStatus.RELEASED, false, false, false) expect(dataset.getTitle()).to.deep.equal(datasetExpected.title) expect(dataset.version).to.deep.equal(newVersion)