diff --git a/public/locales/en/file.json b/public/locales/en/file.json index 95a92ccb5..86231a113 100644 --- a/public/locales/en/file.json +++ b/public/locales/en/file.json @@ -45,5 +45,8 @@ "directory": "File Path", "description": "Description" } + }, + "actionButtons": { + "title": "File Action Buttons" } } diff --git a/src/files/domain/models/File.ts b/src/files/domain/models/File.ts index c39cb7154..08135ffed 100644 --- a/src/files/domain/models/File.ts +++ b/src/files/domain/models/File.ts @@ -3,8 +3,10 @@ import { FileMetadata } from './FileMetadata' import { FileVersion } from './FileVersion' import { FileAccess } from './FileAccess' import { FileUserPermissions } from './FileUserPermissions' +import { FileIngest } from './FileIngest' export interface File { + id: number version: FileVersion name: string access: FileAccess @@ -12,4 +14,5 @@ export interface File { citation: string permissions: FileUserPermissions metadata: FileMetadata + ingest: FileIngest } diff --git a/src/files/domain/models/FileIngest.ts b/src/files/domain/models/FileIngest.ts index 333e98093..802ae5ec8 100644 --- a/src/files/domain/models/FileIngest.ts +++ b/src/files/domain/models/FileIngest.ts @@ -5,7 +5,10 @@ export enum FileIngestStatus { ERROR = 'error' } -export interface FileIngest { - status: FileIngestStatus - reportMessage?: string +export class FileIngest { + constructor(readonly status: FileIngestStatus, readonly message?: string) {} + + get isInProgress(): boolean { + return this.status === FileIngestStatus.IN_PROGRESS + } } diff --git a/src/files/domain/models/FileMetadata.ts b/src/files/domain/models/FileMetadata.ts index e2650d562..dadf7856d 100644 --- a/src/files/domain/models/FileMetadata.ts +++ b/src/files/domain/models/FileMetadata.ts @@ -120,6 +120,14 @@ export class FileType { toDisplayFormat(): string { return FileTypeToFriendlyTypeMap[this.value] || FileTypeToFriendlyTypeMap.unknown } + + get displayFormatIsUnknown(): boolean { + return this.toDisplayFormat() === FileTypeToFriendlyTypeMap.unknown + } + + get originalFormatIsUnknown(): boolean { + return this.original === undefined || this.original === FileTypeToFriendlyTypeMap.unknown + } } export interface FileChecksum { @@ -159,4 +167,8 @@ export class FileMetadata { } return false } + + get isTabular(): boolean { + return this.tabularData !== undefined + } } diff --git a/src/files/infrastructure/mappers/JSFileIngestMapper.ts b/src/files/infrastructure/mappers/JSFileIngestMapper.ts index 0e4381e59..a18192b79 100644 --- a/src/files/infrastructure/mappers/JSFileIngestMapper.ts +++ b/src/files/infrastructure/mappers/JSFileIngestMapper.ts @@ -1,7 +1,7 @@ -import { FileIngestStatus } from '../../domain/models/FileIngest' +import { FileIngest, FileIngestStatus } from '../../domain/models/FileIngest' export class JSFileIngestMapper { static toFileIngest() { - return { status: FileIngestStatus.NONE } // TODO - Implement this when it is added to js-dataverse + return new FileIngest(FileIngestStatus.NONE) // TODO - Implement this when it is added to js-dataverse } } diff --git a/src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/FileActionButtons.tsx b/src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/FileActionButtons.tsx index 9703b36d0..1875ba1ae 100644 --- a/src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/FileActionButtons.tsx +++ b/src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/FileActionButtons.tsx @@ -1,17 +1,29 @@ -import { AccessFileMenu } from './access-file-menu/AccessFileMenu' +import { AccessFileMenu } from '../../../../../../file/file-action-buttons/access-file-menu/AccessFileMenu' import { FilePreview } from '../../../../../../../files/domain/models/FilePreview' import { FileOptionsMenu } from './file-options-menu/FileOptionsMenu' import { ButtonGroup } from '@iqss/dataverse-design-system' import { useTranslation } from 'react-i18next' +import { FilePublishingStatus } from '../../../../../../../files/domain/models/FileVersion' +import { useFileDownloadPermission } from '../../../../../../file/file-permissions/useFileDownloadPermission' interface FileActionButtonsProps { file: FilePreview } export function FileActionButtons({ file }: FileActionButtonsProps) { const { t } = useTranslation('files') + const { sessionUserHasFileDownloadPermission } = useFileDownloadPermission(file) + return ( - + ) diff --git a/src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/AccessFileMenu.tsx b/src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/AccessFileMenu.tsx deleted file mode 100644 index bc346227c..000000000 --- a/src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/AccessFileMenu.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { FilePreview } from '../../../../../../../../files/domain/models/FilePreview' -import { Download, FileEarmark } from 'react-bootstrap-icons' -import { AccessStatus } from './AccessStatus' -import { RequestAccessOption } from './RequestAccessOption' -import { DropdownButton, DropdownHeader, Tooltip } from '@iqss/dataverse-design-system' -import { useTranslation } from 'react-i18next' -import { FileDownloadOptions } from './FileDownloadOptions' - -interface FileActionButtonAccessFileProps { - file: FilePreview -} -export function AccessFileMenu({ file }: FileActionButtonAccessFileProps) { - const { t } = useTranslation('files') - return ( - - }> - - {t('actions.accessFileMenu.headers.fileAccess')} - - - - - - - ) -} diff --git a/src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/FileDownloadOptions.tsx b/src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/FileDownloadOptions.tsx deleted file mode 100644 index b00f47f7a..000000000 --- a/src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/FileDownloadOptions.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { DropdownHeader } from '@iqss/dataverse-design-system' -import { Download } from 'react-bootstrap-icons' -import { FilePreview } from '../../../../../../../../files/domain/models/FilePreview' -import { FileTabularDownloadOptions } from './FileTabularDownloadOptions' -import { FileNonTabularDownloadOptions } from './FileNonTabularDownloadOptions' -import { useTranslation } from 'react-i18next' -import { useFileDownloadPermission } from '../../../../../../../file/file-permissions/useFileDownloadPermission' - -interface FileDownloadOptionsProps { - file: FilePreview -} - -export function FileDownloadOptions({ file }: FileDownloadOptionsProps) { - const { t } = useTranslation('files') - const { sessionUserHasFileDownloadPermission } = useFileDownloadPermission(file) - - if (!sessionUserHasFileDownloadPermission) { - return <> - } - - return ( - <> - - {t('actions.accessFileMenu.downloadOptions.title')} - - - {file.metadata.tabularData ? ( - - ) : ( - - )} - - ) -} - -// TODO: Add guestbook support -// TODO: Add file package support diff --git a/src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/FileNonTabularDownloadOptions.tsx b/src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/FileNonTabularDownloadOptions.tsx deleted file mode 100644 index 989689505..000000000 --- a/src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/FileNonTabularDownloadOptions.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { FilePreview } from '../../../../../../../../files/domain/models/FilePreview' -import FileTypeToFriendlyTypeMap from '../../../../../../../../files/domain/models/FileTypeToFriendlyTypeMap' -import { DropdownButtonItem } from '@iqss/dataverse-design-system' -import { useDataset } from '../../../../../../DatasetContext' -import { useTranslation } from 'react-i18next' -import { FileIngestStatus } from '../../../../../../../../files/domain/models/FileIngest' - -interface FileNonTabularDownloadOptionsProps { - file: FilePreview -} - -export function FileNonTabularDownloadOptions({ file }: FileNonTabularDownloadOptionsProps) { - const { t } = useTranslation('files') - const { dataset } = useDataset() - const originalFileFormatIsKnown = - file.metadata.type.toDisplayFormat() !== FileTypeToFriendlyTypeMap.unknown - - if (file.metadata.tabularData) { - return <> - } - - return ( - - {originalFileFormatIsKnown - ? file.metadata.type.toDisplayFormat() - : t('actions.accessFileMenu.downloadOptions.options.original')} - - ) -} diff --git a/src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/FileTabularDownloadOptions.tsx b/src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/FileTabularDownloadOptions.tsx deleted file mode 100644 index 58b37cc83..000000000 --- a/src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/FileTabularDownloadOptions.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { FilePreview } from '../../../../../../../../files/domain/models/FilePreview' -import { DropdownButtonItem } from '@iqss/dataverse-design-system' -import { useDataset } from '../../../../../../DatasetContext' -import { useTranslation } from 'react-i18next' -import { FileIngestStatus } from '../../../../../../../../files/domain/models/FileIngest' - -interface FileTabularDownloadOptionsProps { - file: FilePreview -} - -export function FileTabularDownloadOptions({ file }: FileTabularDownloadOptionsProps) { - const { t } = useTranslation('files') - const { dataset } = useDataset() - const downloadDisabled = - file.ingest.status === FileIngestStatus.IN_PROGRESS || - (dataset && dataset.isLockedFromFileDownload) - - if (!file.metadata.tabularData) { - return <> - } - - return ( - <> - {file.metadata.type.original && file.metadata.type.original !== 'Unknown' && ( - {`${file.metadata.type.original} (${t( - 'actions.accessFileMenu.downloadOptions.options.original' - )})`} - )} - - {t('actions.accessFileMenu.downloadOptions.options.tabular')} - - {file.metadata.type.original !== 'R Data' && ( - - {t('actions.accessFileMenu.downloadOptions.options.RData')} - - )} - - ) -} diff --git a/src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-info-messages/IngestInfoMessage.tsx b/src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-info-messages/IngestInfoMessage.tsx index 7f7a632ca..a9ce3c387 100644 --- a/src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-info-messages/IngestInfoMessage.tsx +++ b/src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-info-messages/IngestInfoMessage.tsx @@ -31,9 +31,9 @@ export function IngestInfoMessage({ ingest }: IngestInfoMessageProps) { {t('ingest.error.tabularIngest')} {' '} - {ingest.reportMessage + {ingest.message ? t('ingest.error.reportMessage', { - reportMessage: ingest.reportMessage + reportMessage: ingest.message }) : t('ingest.error.reportMessageDefault')}

diff --git a/src/sections/file/File.module.scss b/src/sections/file/File.module.scss index 1d4c600db..69b04f28c 100644 --- a/src/sections/file/File.module.scss +++ b/src/sections/file/File.module.scss @@ -38,4 +38,10 @@ .restricted-icon { margin-right: 6px; +} + +.group { + display: flex; + width: 100%; + margin: 0.5rem 0; } \ No newline at end of file diff --git a/src/sections/file/File.tsx b/src/sections/file/File.tsx index 777e37baa..8ff124f28 100644 --- a/src/sections/file/File.tsx +++ b/src/sections/file/File.tsx @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next' import { PageNotFound } from '../page-not-found/PageNotFound' import styles from './File.module.scss' -import { Col, Row, Tabs } from '@iqss/dataverse-design-system' +import { ButtonGroup, Col, Row, Tabs } from '@iqss/dataverse-design-system' import { FileRepository } from '../../files/domain/repositories/FileRepository' import { useFile } from './useFile' import { useEffect } from 'react' @@ -12,6 +12,8 @@ import { FileCitation } from './file-citation/FileCitation' import { DatasetLabels } from '../dataset/dataset-labels/DatasetLabels' import { FileAccessRestrictedIcon } from './file-access/FileAccessRestrictedIcon' import { FileMetadata } from './file-metadata/FileMetadata' +import { AccessFileMenu } from './file-action-buttons/access-file-menu/AccessFileMenu' +import { FilePublishingStatus } from '../../files/domain/models/FileVersion' interface FileProps { repository: FileRepository @@ -61,6 +63,23 @@ export function File({ repository, id }: FileProps) { {t('datasetCitationTitle')} + + + + + diff --git a/src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/AccessFileMenu.module.scss b/src/sections/file/file-action-buttons/access-file-menu/AccessFileMenu.module.scss similarity index 100% rename from src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/AccessFileMenu.module.scss rename to src/sections/file/file-action-buttons/access-file-menu/AccessFileMenu.module.scss diff --git a/src/sections/file/file-action-buttons/access-file-menu/AccessFileMenu.tsx b/src/sections/file/file-action-buttons/access-file-menu/AccessFileMenu.tsx new file mode 100644 index 000000000..46871775b --- /dev/null +++ b/src/sections/file/file-action-buttons/access-file-menu/AccessFileMenu.tsx @@ -0,0 +1,75 @@ +import { Download, FileEarmark } from 'react-bootstrap-icons' +import { AccessStatus } from './AccessStatus' +import { RequestAccessOption } from './RequestAccessOption' +import { DropdownButton, DropdownHeader, Tooltip } from '@iqss/dataverse-design-system' +import { useTranslation } from 'react-i18next' +import { FileDownloadOptions } from './FileDownloadOptions' +import { FileAccess } from '../../../../files/domain/models/FileAccess' +import { FileMetadata } from '../../../../files/domain/models/FileMetadata' +import { ReactElement } from 'react' + +interface FileActionButtonAccessFileProps { + id: number + access: FileAccess + userHasDownloadPermission: boolean + metadata: FileMetadata + ingestInProgress: boolean + isDeaccessioned: boolean + asIcon?: boolean +} + +export function AccessFileMenu({ + id, + access, + userHasDownloadPermission, + metadata, + ingestInProgress, + isDeaccessioned, + asIcon = false +}: FileActionButtonAccessFileProps) { + const { t } = useTranslation('files') + function MenuWrapper({ children }: { children: ReactElement }) { + if (asIcon) { + return ( + + {children} + + ) + } + return children + } + + return ( + + : undefined}> + + {t('actions.accessFileMenu.headers.fileAccess')} + + + + + + + ) +} diff --git a/src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/AccessStatus.tsx b/src/sections/file/file-action-buttons/access-file-menu/AccessStatus.tsx similarity index 50% rename from src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/AccessStatus.tsx rename to src/sections/file/file-action-buttons/access-file-menu/AccessStatus.tsx index 8da22dc74..e5b2cfa01 100644 --- a/src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/AccessStatus.tsx +++ b/src/sections/file/file-action-buttons/access-file-menu/AccessStatus.tsx @@ -1,27 +1,30 @@ -import { FilePreview } from '../../../../../../../../files/domain/models/FilePreview' import { Globe, LockFill, UnlockFill } from 'react-bootstrap-icons' import { useTranslation } from 'react-i18next' import styles from './AccessFileMenu.module.scss' import { DropdownButtonItem } from '@iqss/dataverse-design-system' -import { useFileDownloadPermission } from '../../../../../../../file/file-permissions/useFileDownloadPermission' interface AccessStatusProps { - file: FilePreview + userHasDownloadPermission: boolean + isRestricted: boolean + isActivelyEmbargoed: boolean } -export function AccessStatus({ file }: AccessStatusProps) { - const { sessionUserHasFileDownloadPermission } = useFileDownloadPermission(file) - +export function AccessStatus({ + userHasDownloadPermission, + isRestricted, + isActivelyEmbargoed +}: AccessStatusProps) { return ( {' '} @@ -29,15 +32,15 @@ export function AccessStatus({ file }: AccessStatusProps) { } function AccessStatusIcon({ - sessionUserHasFileDownloadPermission, - restricted + userHasDownloadPermission, + isRestricted }: { - sessionUserHasFileDownloadPermission: boolean - restricted: boolean + userHasDownloadPermission: boolean + isRestricted: boolean }) { const { t } = useTranslation('file') - if (restricted) { - if (sessionUserHasFileDownloadPermission) { + if (isRestricted) { + if (userHasDownloadPermission) { return ( ) @@ -48,20 +51,22 @@ function AccessStatusIcon({ } function AccessStatusText({ - file, - sessionUserHasFileDownloadPermission + isActivelyEmbargoed, + isRestricted, + userHasDownloadPermission }: { - file: FilePreview - sessionUserHasFileDownloadPermission: boolean + isActivelyEmbargoed: boolean + isRestricted: boolean + userHasDownloadPermission: boolean }) { const { t } = useTranslation('file') const getAccessStatus = () => { - if (file.metadata.isActivelyEmbargoed) { + if (isActivelyEmbargoed) { return 'embargoed' } - if (file.access.restricted) { - if (!sessionUserHasFileDownloadPermission) { + if (isRestricted) { + if (!userHasDownloadPermission) { return 'restricted' } @@ -74,11 +79,7 @@ function AccessStatusText({ return ( {t(`fileAccess.${getAccessStatus()}.name`)} diff --git a/src/sections/file/file-action-buttons/access-file-menu/FileDownloadOptions.tsx b/src/sections/file/file-action-buttons/access-file-menu/FileDownloadOptions.tsx new file mode 100644 index 000000000..9b605de8e --- /dev/null +++ b/src/sections/file/file-action-buttons/access-file-menu/FileDownloadOptions.tsx @@ -0,0 +1,53 @@ +import { DropdownHeader } from '@iqss/dataverse-design-system' +import { Download } from 'react-bootstrap-icons' +import { FileTabularDownloadOptions } from './FileTabularDownloadOptions' +import { FileNonTabularDownloadOptions } from './FileNonTabularDownloadOptions' +import { useTranslation } from 'react-i18next' +import { FileDownloadUrls, FileType } from '../../../../files/domain/models/FileMetadata' + +interface FileDownloadOptionsProps { + type: FileType + isTabular: boolean + ingestInProgress: boolean + downloadUrls: FileDownloadUrls + userHasDownloadPermission: boolean +} + +export function FileDownloadOptions({ + type, + isTabular, + ingestInProgress, + downloadUrls, + userHasDownloadPermission +}: FileDownloadOptionsProps) { + const { t } = useTranslation('files') + + if (!userHasDownloadPermission) { + return <> + } + + return ( + <> + + {t('actions.accessFileMenu.downloadOptions.title')} + + + {isTabular ? ( + + ) : ( + + )} + + ) +} + +// TODO: Add guestbook support +// TODO: Add file package support diff --git a/src/sections/file/file-action-buttons/access-file-menu/FileNonTabularDownloadOptions.tsx b/src/sections/file/file-action-buttons/access-file-menu/FileNonTabularDownloadOptions.tsx new file mode 100644 index 000000000..ee0fce16e --- /dev/null +++ b/src/sections/file/file-action-buttons/access-file-menu/FileNonTabularDownloadOptions.tsx @@ -0,0 +1,29 @@ +import { DropdownButtonItem } from '@iqss/dataverse-design-system' +import { useDataset } from '../../../dataset/DatasetContext' +import { useTranslation } from 'react-i18next' +import { FileType } from '../../../../files/domain/models/FileMetadata' + +interface FileNonTabularDownloadOptionsProps { + type: FileType + downloadUrlOriginal: string + ingestIsInProgress: boolean +} + +export function FileNonTabularDownloadOptions({ + type, + downloadUrlOriginal, + ingestIsInProgress +}: FileNonTabularDownloadOptionsProps) { + const { t } = useTranslation('files') + const { dataset } = useDataset() + + return ( + + {type.displayFormatIsUnknown + ? t('actions.accessFileMenu.downloadOptions.options.original') + : type.toDisplayFormat()} + + ) +} diff --git a/src/sections/file/file-action-buttons/access-file-menu/FileTabularDownloadOptions.tsx b/src/sections/file/file-action-buttons/access-file-menu/FileTabularDownloadOptions.tsx new file mode 100644 index 000000000..cb458dde8 --- /dev/null +++ b/src/sections/file/file-action-buttons/access-file-menu/FileTabularDownloadOptions.tsx @@ -0,0 +1,39 @@ +import { DropdownButtonItem } from '@iqss/dataverse-design-system' +import { useDataset } from '../../../dataset/DatasetContext' +import { useTranslation } from 'react-i18next' +import { FileDownloadUrls, FileType } from '../../../../files/domain/models/FileMetadata' +import FileTypeToFriendlyTypeMap from '../../../../files/domain/models/FileTypeToFriendlyTypeMap' + +interface FileTabularDownloadOptionsProps { + type: FileType + ingestInProgress: boolean + downloadUrls: FileDownloadUrls +} + +export function FileTabularDownloadOptions({ + type, + ingestInProgress, + downloadUrls +}: FileTabularDownloadOptionsProps) { + const { t } = useTranslation('files') + const { dataset } = useDataset() + const downloadDisabled = ingestInProgress || (dataset && dataset.isLockedFromFileDownload) + + return ( + <> + {!type.originalFormatIsUnknown && ( + {`${ + type.original || '' + } (${t('actions.accessFileMenu.downloadOptions.options.original')})`} + )} + + {t('actions.accessFileMenu.downloadOptions.options.tabular')} + + {type.original !== FileTypeToFriendlyTypeMap['application/x-r-data'] && ( + + {t('actions.accessFileMenu.downloadOptions.options.RData')} + + )} + + ) +} diff --git a/src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/RequestAccessModal.tsx b/src/sections/file/file-action-buttons/access-file-menu/RequestAccessModal.tsx similarity index 95% rename from src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/RequestAccessModal.tsx rename to src/sections/file/file-action-buttons/access-file-menu/RequestAccessModal.tsx index eea369e4d..fbcfddbca 100644 --- a/src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/RequestAccessModal.tsx +++ b/src/sections/file/file-action-buttons/access-file-menu/RequestAccessModal.tsx @@ -1,9 +1,9 @@ import { Button, DropdownButtonItem, Modal } from '@iqss/dataverse-design-system' -import { useSession } from '../../../../../../../session/SessionContext' +import { useSession } from '../../../session/SessionContext' import { FormEvent, useState } from 'react' import { Form } from '@iqss/dataverse-design-system' import { ExclamationTriangle } from 'react-bootstrap-icons' -import { Route } from '../../../../../../../Route.enum' +import { Route } from '../../../Route.enum' import styles from './AccessFileMenu.module.scss' import { useTranslation } from 'react-i18next' diff --git a/src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/RequestAccessOption.tsx b/src/sections/file/file-action-buttons/access-file-menu/RequestAccessOption.tsx similarity index 51% rename from src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/RequestAccessOption.tsx rename to src/sections/file/file-action-buttons/access-file-menu/RequestAccessOption.tsx index d8abd6390..e530008a1 100644 --- a/src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/RequestAccessOption.tsx +++ b/src/sections/file/file-action-buttons/access-file-menu/RequestAccessOption.tsx @@ -1,26 +1,31 @@ import { DropdownButtonItem } from '@iqss/dataverse-design-system' import styles from './AccessFileMenu.module.scss' import { RequestAccessModal } from './RequestAccessModal' -import { FilePreview } from '../../../../../../../../files/domain/models/FilePreview' import { useTranslation } from 'react-i18next' -import { useFileDownloadPermission } from '../../../../../../../file/file-permissions/useFileDownloadPermission' -import { FilePublishingStatus } from '../../../../../../../../files/domain/models/FileVersion' +import { FileAccess } from '../../../../files/domain/models/FileAccess' interface RequestAccessButtonProps { - file: FilePreview + id: number + userHasDownloadPermission: boolean + access: FileAccess + isActivelyEmbargoed: boolean + isDeaccessioned: boolean } -export function RequestAccessOption({ file }: RequestAccessButtonProps) { + +export function RequestAccessOption({ + id, + access, + userHasDownloadPermission, + isActivelyEmbargoed, + isDeaccessioned +}: RequestAccessButtonProps) { const { t } = useTranslation('files') - const { sessionUserHasFileDownloadPermission } = useFileDownloadPermission(file) - if ( - file.version.publishingStatus === FilePublishingStatus.DEACCESSIONED || - sessionUserHasFileDownloadPermission - ) { + if (isDeaccessioned || userHasDownloadPermission) { return <> } - if (file.metadata.isActivelyEmbargoed) { - if (file.access.restricted) { + if (isActivelyEmbargoed) { + if (access.restricted) { return ( {t('requestAccess.embargoedThenRestricted')}. @@ -29,15 +34,15 @@ export function RequestAccessOption({ file }: RequestAccessButtonProps) { } return {t('requestAccess.embargoed')}. } - if (!file.access.canBeRequested) { + if (!access.canBeRequested) { return {t('requestAccess.requestNotAllowed')}. } - if (file.access.requested) { + if (access.requested) { return ( {t('requestAccess.accessRequested')} ) } - return + return } diff --git a/src/stories/dataset/dataset-files/files-table/file-actions/file-action-buttons/access-file-menu/AccessFileMenu.stories.tsx b/src/stories/dataset/dataset-files/files-table/file-actions/file-action-buttons/access-file-menu/AccessFileMenu.stories.tsx deleted file mode 100644 index 6cc207e53..000000000 --- a/src/stories/dataset/dataset-files/files-table/file-actions/file-action-buttons/access-file-menu/AccessFileMenu.stories.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { Meta, StoryObj } from '@storybook/react' -import { AccessFileMenu } from '../../../../../../../sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/AccessFileMenu' -import { WithI18next } from '../../../../../../WithI18next' -import { WithSettings } from '../../../../../../WithSettings' -import { WithFilePermissionsGranted } from '../../../../../../file/file-permission/WithFilePermissionsGranted' -import { FilePreviewMother } from '../../../../../../../../tests/component/files/domain/models/FilePreviewMother' - -const meta: Meta = { - title: - 'Sections/Dataset Page/DatasetFiles/FilesTable/FileActionsCell/FileActionButtons/AccessFileMenu', - component: AccessFileMenu, - decorators: [WithI18next, WithSettings] -} - -export default meta -type Story = StoryObj - -export const Default: Story = { - decorators: [WithFilePermissionsGranted], - render: () => -} - -export const NonTabularFiles: Story = { - render: () => -} - -export const TabularFiles: Story = { - render: () => -} - -export const Restricted: Story = { - render: () => -} - -export const RestrictedWithAccessRequestAllowed: Story = { - render: () => -} - -export const RestrictedWithAccessRequestPending: Story = { - render: () => -} - -export const RestrictedWithAccessGranted: Story = { - decorators: [WithFilePermissionsGranted], - render: () => -} - -export const WithEmbargo: Story = { - decorators: [WithFilePermissionsGranted], - render: () => -} - -export const WithEmbargoAndRestricted: Story = { - render: () => -} diff --git a/src/stories/dataset/dataset-files/files-table/file-actions/file-action-buttons/access-file-menu/RequestAccessModal.stories.tsx b/src/stories/dataset/dataset-files/files-table/file-actions/file-action-buttons/access-file-menu/RequestAccessModal.stories.tsx deleted file mode 100644 index ac21b4c43..000000000 --- a/src/stories/dataset/dataset-files/files-table/file-actions/file-action-buttons/access-file-menu/RequestAccessModal.stories.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { Meta, StoryObj } from '@storybook/react' -import { WithI18next } from '../../../../../../WithI18next' -import { WithSettings } from '../../../../../../WithSettings' -import { RequestAccessModal } from '../../../../../../../sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/RequestAccessModal' -import { WithLoggedInUser } from '../../../../../../WithLoggedInUser' - -const meta: Meta = { - title: - 'Sections/Dataset Page/DatasetFiles/FilesTable/FileActionsCell/FileActionButtons/RequestAccessModal', - component: RequestAccessModal, - decorators: [WithI18next, WithSettings] -} - -export default meta -type Story = StoryObj - -export const LoggedOut: Story = { - render: () => -} - -export const LoggedIn: Story = { - decorators: [WithLoggedInUser], - render: () => -} diff --git a/src/stories/dataset/dataset-files/files-table/file-info/file-info-cell/file-info-data/file-thumbnail/FileThumbnail.stories.tsx b/src/stories/dataset/dataset-files/files-table/file-info/file-info-cell/file-info-data/file-thumbnail/FileThumbnail.stories.tsx index 8b4701d4e..3737e69c6 100644 --- a/src/stories/dataset/dataset-files/files-table/file-info/file-info-cell/file-info-data/file-thumbnail/FileThumbnail.stories.tsx +++ b/src/stories/dataset/dataset-files/files-table/file-info/file-info-cell/file-info-data/file-thumbnail/FileThumbnail.stories.tsx @@ -39,7 +39,7 @@ export const WithThumbnailRestrictedLockedIcon: Story = { export const WithThumbnailRestrictedUnlockedIcon: Story = { decorators: [WithFilePermissionsGranted], render: () => { - const file = FilePreviewMother.createRestrictedWithAccessGranted() + const file = FilePreviewMother.createRestricted() return } } @@ -47,7 +47,7 @@ export const WithThumbnailRestrictedUnlockedIcon: Story = { export const WithThumbnailPreviewRestrictedUnlockedIcon: Story = { decorators: [WithFilePermissionsGranted], render: () => { - const file = FilePreviewMother.createWithThumbnailRestrictedWithAccessGranted() + const file = FilePreviewMother.createWithThumbnailRestricted() return } } diff --git a/src/stories/file/file-action-buttons/access-file-menu/AccessFileMenu.stories.tsx b/src/stories/file/file-action-buttons/access-file-menu/AccessFileMenu.stories.tsx new file mode 100644 index 000000000..00632dc73 --- /dev/null +++ b/src/stories/file/file-action-buttons/access-file-menu/AccessFileMenu.stories.tsx @@ -0,0 +1,162 @@ +import { Meta, StoryObj } from '@storybook/react' +import { AccessFileMenu } from '../../../../sections/file/file-action-buttons/access-file-menu/AccessFileMenu' +import { WithI18next } from '../../../WithI18next' +import { WithSettings } from '../../../WithSettings' +import { WithFilePermissionsGranted } from '../../file-permission/WithFilePermissionsGranted' +import { FileAccessMother } from '../../../../../tests/component/files/domain/models/FileAccessMother' +import { FileMetadataMother } from '../../../../../tests/component/files/domain/models/FileMetadataMother' + +const meta: Meta = { + title: 'Sections/File Page/Action Buttons/AccessFileMenu', + component: AccessFileMenu, + decorators: [WithI18next, WithSettings] +} + +export default meta +type Story = StoryObj + +export const Default: Story = { + render: () => ( + + ) +} + +export const AsIcon: Story = { + render: () => ( + + ) +} + +export const NonTabularFiles: Story = { + render: () => ( + + ) +} + +export const TabularFiles: Story = { + render: () => ( + + ) +} + +export const Restricted: Story = { + render: () => ( + + ) +} + +export const RestrictedWithAccessRequestAllowed: Story = { + render: () => ( + + ) +} + +export const RestrictedWithAccessRequestPending: Story = { + render: () => ( + + ) +} + +export const RestrictedWithAccessGranted: Story = { + decorators: [WithFilePermissionsGranted], + render: () => ( + + ) +} + +export const WithEmbargo: Story = { + decorators: [WithFilePermissionsGranted], + render: () => ( + + ) +} + +export const WithEmbargoAndRestricted: Story = { + render: () => ( + + ) +} + +export const WithEmbargoAndRestrictedWithAccessGranted: Story = { + render: () => ( + + ) +} diff --git a/src/stories/file/file-action-buttons/access-file-menu/RequestAccessModal.stories.tsx b/src/stories/file/file-action-buttons/access-file-menu/RequestAccessModal.stories.tsx new file mode 100644 index 000000000..f5ea38c63 --- /dev/null +++ b/src/stories/file/file-action-buttons/access-file-menu/RequestAccessModal.stories.tsx @@ -0,0 +1,23 @@ +import { Meta, StoryObj } from '@storybook/react' +import { WithI18next } from '../../../WithI18next' +import { WithSettings } from '../../../WithSettings' +import { WithLoggedInUser } from '../../../WithLoggedInUser' +import { RequestAccessModal } from '../../../../sections/file/file-action-buttons/access-file-menu/RequestAccessModal' + +const meta: Meta = { + title: 'Sections/File Page/Action Buttons/RequestAccessModal', + component: RequestAccessModal, + decorators: [WithI18next, WithSettings] +} + +export default meta +type Story = StoryObj + +export const LoggedOut: Story = { + render: () => +} + +export const LoggedIn: Story = { + decorators: [WithLoggedInUser], + render: () => +} diff --git a/tests/component/files/domain/models/FileAccessMother.ts b/tests/component/files/domain/models/FileAccessMother.ts index 79a7101a7..10e0315c3 100644 --- a/tests/component/files/domain/models/FileAccessMother.ts +++ b/tests/component/files/domain/models/FileAccessMother.ts @@ -12,7 +12,7 @@ export class FileAccessMother { } } - static createNotRestricted(): FileAccess { + static createPublic(): FileAccess { return this.create({ restricted: false, latestVersionRestricted: false, @@ -39,7 +39,7 @@ export class FileAccessMother { }) } - static createWithAccessGranted(): FileAccess { + static createWithAccessRequestAllowed(): FileAccess { return this.create({ restricted: true, latestVersionRestricted: true, @@ -48,11 +48,11 @@ export class FileAccessMother { }) } - static createWithAccessRequestAllowed(): FileAccess { + static createWithAccessRequestNotAllowed(): FileAccess { return this.create({ restricted: true, latestVersionRestricted: true, - canBeRequested: true, + canBeRequested: false, requested: false }) } diff --git a/tests/component/files/domain/models/FileIngestMother.ts b/tests/component/files/domain/models/FileIngestMother.ts index d92163da0..f971a82a0 100644 --- a/tests/component/files/domain/models/FileIngestMother.ts +++ b/tests/component/files/domain/models/FileIngestMother.ts @@ -3,21 +3,20 @@ import { FileIngest, FileIngestStatus } from '../../../../../src/files/domain/mo export class FileIngestMother { static create(props?: Partial): FileIngest { - return { - status: faker.helpers.arrayElement(Object.values(FileIngestStatus)), - reportMessage: faker.datatype.boolean() ? faker.lorem.sentence() : undefined, - ...props - } + return new FileIngest( + props?.status ?? faker.helpers.arrayElement(Object.values(FileIngestStatus)), + props?.message + ) } static createInProgress(): FileIngest { return this.create({ status: FileIngestStatus.IN_PROGRESS }) } - static createIngestProblem(reportMessage?: string): FileIngest { + static createIngestProblem(message?: string): FileIngest { return this.create({ status: FileIngestStatus.ERROR, - reportMessage: reportMessage + message: message }) } diff --git a/tests/component/files/domain/models/FileMetadataMother.ts b/tests/component/files/domain/models/FileMetadataMother.ts index a0501f0dd..978e46ed5 100644 --- a/tests/component/files/domain/models/FileMetadataMother.ts +++ b/tests/component/files/domain/models/FileMetadataMother.ts @@ -9,7 +9,8 @@ import { FileLabel, FileLabelType, FileTabularData, - FileMetadata + FileMetadata, + FileDownloadUrls } from '../../../../../src/files/domain/models/FileMetadata' import FileTypeToFriendlyTypeMap from '../../../../../src/files/domain/models/FileTypeToFriendlyTypeMap' @@ -30,6 +31,10 @@ export class FileTypeMother { return new FileType('text/tab-separated-values', 'Comma Separated Values') } + static createTabularUnknown(): FileType { + return new FileType('text/tab-separated-values', 'Unknown') + } + static createText(): FileType { return new FileType('text/plain') } @@ -45,6 +50,10 @@ export class FileTypeMother { static createUnknown(): FileType { return new FileType('unknown') } + + static createRData(): FileType { + return new FileType('text/tab-separated-values', 'R Data') + } } export class FileTabularDataMother { @@ -123,6 +132,17 @@ export class FileSizeMother { } } +export class FileDownloadUrlsMother { + static create(props?: Partial): FileDownloadUrls { + return { + original: faker.internet.url(), + tabular: faker.internet.url(), + rData: faker.internet.url(), + ...props + } + } +} + export class FileMetadataMother { static create(props?: Partial): FileMetadata { const thumbnail = valueOrUndefined(faker.image.imageUrl(400)) @@ -145,11 +165,7 @@ export class FileMetadataMother { tabularData: tabularFile && !checksum ? FileTabularDataMother.create() : undefined, description: valueOrUndefined(faker.lorem.paragraph()), isDeleted: faker.datatype.boolean(), - downloadUrls: { - original: this.createDownloadUrl(), - tabular: this.createDownloadUrl(), - rData: this.createDownloadUrl() - }, + downloadUrls: FileDownloadUrlsMother.create(), depositDate: faker.date.past(), publicationDate: faker.datatype.boolean() ? faker.date.past() : undefined, persistentId: faker.datatype.uuid(), diff --git a/tests/component/files/domain/models/FileMother.ts b/tests/component/files/domain/models/FileMother.ts index 74b0dd105..85bed0f08 100644 --- a/tests/component/files/domain/models/FileMother.ts +++ b/tests/component/files/domain/models/FileMother.ts @@ -5,10 +5,12 @@ import { FileVersionMother } from './FileVersionMother' import { FileAccessMother } from './FileAccessMother' import { FileUserPermissionsMother } from './FileUserPermissionsMother' import { faker } from '@faker-js/faker' +import { FileIngestMother } from './FileIngestMother' export class FileMother { static create(props?: Partial): File { return { + id: faker.datatype.number(), name: faker.system.fileName(), version: FileVersionMother.create(), datasetVersion: DatasetVersionMother.create(), @@ -16,6 +18,7 @@ export class FileMother { access: FileAccessMother.create(), metadata: FileMetadataMother.create(), permissions: FileUserPermissionsMother.create(), + ingest: FileIngestMother.create(), ...props } } @@ -25,7 +28,7 @@ export class FileMother { name: 'File Title', datasetVersion: DatasetVersionMother.createRealistic(), citation: FileCitationMother.create('File Title'), - access: FileAccessMother.createNotRestricted(), + access: FileAccessMother.createPublic(), permissions: FileUserPermissionsMother.createWithAllPermissionsGranted(), metadata: FileMetadataMother.createDefault(), ...props diff --git a/tests/component/files/domain/models/FilePreviewMother.ts b/tests/component/files/domain/models/FilePreviewMother.ts index 2e4828bae..07cf0a898 100644 --- a/tests/component/files/domain/models/FilePreviewMother.ts +++ b/tests/component/files/domain/models/FilePreviewMother.ts @@ -26,7 +26,7 @@ export class FilePreviewMother { return this.create({ name: 'File Title', version: FileVersionMother.createReleased(), - access: FileAccessMother.createNotRestricted(), + access: FileAccessMother.createPublic(), ingest: FileIngestMother.createIngestNone(), metadata: FileMetadataMother.createDefault(), ...props @@ -48,7 +48,7 @@ export class FilePreviewMother { static createWithPublicAccess(): FilePreview { return this.createDefault({ - access: FileAccessMother.createNotRestricted(), + access: FileAccessMother.createPublic(), metadata: FileMetadataMother.createNotEmbargoed() }) } @@ -67,13 +67,6 @@ export class FilePreviewMother { }) } - static createRestrictedWithAccessGranted(): FilePreview { - return this.createDefault({ - access: FileAccessMother.createWithAccessGranted(), - metadata: FileMetadataMother.createNotEmbargoed() - }) - } - static createWithAccessRequestAllowed(): FilePreview { return this.createDefault({ access: FileAccessMother.createWithAccessRequestAllowed(), @@ -94,13 +87,6 @@ export class FilePreviewMother { }) } - static createWithThumbnailRestrictedWithAccessGranted(): FilePreview { - return this.createDefault({ - access: FileAccessMother.createWithAccessGranted(), - metadata: FileMetadataMother.createWithThumbnail() - }) - } - static createWithThumbnailRestricted(): FilePreview { return this.createDefault({ access: FileAccessMother.createRestricted(), diff --git a/tests/component/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/AccessFileMenu.spec.tsx b/tests/component/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/AccessFileMenu.spec.tsx deleted file mode 100644 index 3c60bef4c..000000000 --- a/tests/component/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/AccessFileMenu.spec.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import { AccessFileMenu } from '../../../../../../../../../../src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/AccessFileMenu' -import { Suspense } from 'react' -import { FilePermissionsProvider } from '../../../../../../../../../../src/sections/file/file-permissions/FilePermissionsProvider' -import { FileRepository } from '../../../../../../../../../../src/files/domain/repositories/FileRepository' -import { FileUserPermissionsMother } from '../../../../../../../../files/domain/models/FileUserPermissionsMother' -import { FilePreviewMother } from '../../../../../../../../files/domain/models/FilePreviewMother' - -const file = FilePreviewMother.create() - -const fileRepository = {} as FileRepository -describe('AccessFileMenu', () => { - beforeEach(() => { - fileRepository.getUserPermissionsById = cy.stub().resolves( - FileUserPermissionsMother.create({ - canDownloadFile: true - }) - ) - }) - it('renders the access file menu', () => { - cy.customMount() - - cy.findByRole('button', { name: 'Access File' }).should('exist') - }) - - it('renders the access file menu with tooltip', () => { - cy.customMount() - - cy.findByRole('button', { name: 'Access File' }).trigger('mouseover') - cy.findByRole('tooltip', { name: 'Access File' }).should('exist') - }) - - it('renders the menu headers', () => { - cy.customMount( - - - - ) - - cy.findByRole('button', { name: 'Access File' }).should('exist').click() - cy.findByRole('heading', { name: 'File Access' }).should('exist') - }) - - it('renders the access status of the file', () => { - const filePublic = FilePreviewMother.createWithPublicAccess() - cy.customMount( - - - - ) - - cy.findByRole('button', { name: 'Access File' }).click() - cy.findByText('Public').should('exist') - }) - - it('renders the request access button', () => { - const fileRestrictedWithAccessRequestAllowed = - FilePreviewMother.createWithAccessRequestAllowed() - cy.customMount( - - - - ) - - cy.findByRole('button', { name: 'Access File' }).click() - cy.findByRole('button', { name: 'Request Access' }).should('exist') - }) - - it('renders the download options header', () => { - const filePublic = FilePreviewMother.createWithPublicAccess() - cy.customMount( - - - - ) - - cy.findByRole('button', { name: 'Access File' }).click() - cy.findByRole('heading', { name: 'Download Options' }).should('exist') - }) -}) diff --git a/tests/component/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/AccessStatus.spec.tsx b/tests/component/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/AccessStatus.spec.tsx deleted file mode 100644 index 3ef3f76ac..000000000 --- a/tests/component/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/AccessStatus.spec.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import { AccessStatus } from '../../../../../../../../../../src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/AccessStatus' -import styles from '../../../../../../../../../../src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/AccessFileMenu.module.scss' -import { FileRepository } from '../../../../../../../../../../src/files/domain/repositories/FileRepository' -import { FileUserPermissionsMother } from '../../../../../../../../files/domain/models/FileUserPermissionsMother' -import { FilePermissionsProvider } from '../../../../../../../../../../src/sections/file/file-permissions/FilePermissionsProvider' -import { FilePreviewMother } from '../../../../../../../../files/domain/models/FilePreviewMother' - -describe('AccessStatus', () => { - it('renders the access status public', () => { - const filePublic = FilePreviewMother.createWithPublicAccess() - cy.customMount() - - cy.findByText('Public').should('exist').should('have.class', styles.success) - cy.findByText('Public File Icon').should('exist') - }) - - it('renders the access status restricted', () => { - const fileRestricted = FilePreviewMother.createRestricted() - cy.customMount() - - cy.findByText('Restricted').should('exist').should('have.class', styles.danger) - cy.findByText('Restricted File Icon').should('exist') - }) - - it('renders the access status restricted with access', () => { - const fileRestrictedWithAccess = FilePreviewMother.createRestrictedWithAccessGranted() - const fileRepository: FileRepository = {} as FileRepository - fileRepository.getUserPermissionsById = cy.stub().resolves( - FileUserPermissionsMother.create({ - fileId: fileRestrictedWithAccess.id, - canDownloadFile: true - }) - ) - - cy.customMount( - - - - ) - - cy.findByText('Restricted with Access Granted') - .should('exist') - .should('have.class', styles.success) - cy.findByText('Restricted with access Icon').should('exist') - }) - - it('renders the access status embargoed', () => { - const fileRestrictedWithAccess = FilePreviewMother.createRestrictedWithAccessGranted() - const fileRepository: FileRepository = {} as FileRepository - fileRepository.getUserPermissionsById = cy.stub().resolves( - FileUserPermissionsMother.create({ - fileId: fileRestrictedWithAccess.id, - canDownloadFile: true - }) - ) - const fileEmbargoed = FilePreviewMother.createWithEmbargo() - cy.customMount( - - {' '} - - ) - - cy.findByText('Embargoed').should('exist').should('have.class', styles.success) - cy.findByText('Public File Icon').should('exist') - }) - - it('renders the access status embargoed restricted', () => { - const fileEmbargoedRestricted = FilePreviewMother.createWithEmbargoRestricted() - cy.customMount() - - cy.findByText('Embargoed').should('exist').should('have.class', styles.danger) - cy.findByText('Restricted File Icon').should('exist') - }) - - it('renders the access status embargoed restricted with access', () => { - const fileRestrictedWithAccess = FilePreviewMother.createRestrictedWithAccessGranted() - const fileRepository: FileRepository = {} as FileRepository - fileRepository.getUserPermissionsById = cy.stub().resolves( - FileUserPermissionsMother.create({ - fileId: fileRestrictedWithAccess.id, - canDownloadFile: true - }) - ) - const fileEmbargoedRestricted = FilePreviewMother.createWithEmbargoRestricted() - cy.customMount( - - {' '} - - ) - - cy.findByText('Embargoed').should('exist').should('have.class', styles.success) - cy.findByText('Restricted with access Icon').should('exist') - }) -}) diff --git a/tests/component/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/FileDownloadOptions.spec.tsx b/tests/component/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/FileDownloadOptions.spec.tsx deleted file mode 100644 index 46458bbca..000000000 --- a/tests/component/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/FileDownloadOptions.spec.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import { FileDownloadOptions } from '../../../../../../../../../../src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/FileDownloadOptions' -import { FileUserPermissionsMother } from '../../../../../../../../files/domain/models/FileUserPermissionsMother' -import { FilePermissionsProvider } from '../../../../../../../../../../src/sections/file/file-permissions/FilePermissionsProvider' -import { FileRepository } from '../../../../../../../../../../src/files/domain/repositories/FileRepository' -import { FilePreviewMother } from '../../../../../../../../files/domain/models/FilePreviewMother' - -const fileNonTabular = FilePreviewMother.createNonTabular() -const fileTabular = FilePreviewMother.createTabular() -const fileRepository = {} as FileRepository -describe('FileDownloadOptions', () => { - beforeEach(() => { - fileRepository.getUserPermissionsById = cy.stub().resolves( - FileUserPermissionsMother.create({ - canDownloadFile: true - }) - ) - }) - - it('renders the download options header', () => { - cy.customMount( - - - - ) - - cy.findByRole('heading', { name: 'Download Options' }).should('exist') - }) - - it('does not render the download options if the user does not have permissions', () => { - fileRepository.getUserPermissionsById = cy.stub().resolves( - FileUserPermissionsMother.create({ - canDownloadFile: false - }) - ) - - cy.customMount( - - - - ) - - cy.findByRole('heading', { name: 'Download Options' }).should('not.exist') - }) - - it('renders the download options for a non-tabular file', () => { - cy.customMount( - - {' '} - - ) - - cy.findByRole('link', { name: 'Plain Text' }).should('exist') - }) - - it('renders the download options for a tabular file', () => { - cy.customMount( - - - - ) - - cy.findByRole('link', { name: 'Comma Separated Values (Original File Format)' }).should('exist') - }) -}) diff --git a/tests/component/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/FileNonTabularDownloadOptions.spec.tsx b/tests/component/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/FileNonTabularDownloadOptions.spec.tsx deleted file mode 100644 index 1b478b012..000000000 --- a/tests/component/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/FileNonTabularDownloadOptions.spec.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import { FileMetadataMother } from '../../../../../../../../files/domain/models/FileMetadataMother' - -import { FileNonTabularDownloadOptions } from '../../../../../../../../../../src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/FileNonTabularDownloadOptions' -import { DatasetProvider } from '../../../../../../../../../../src/sections/dataset/DatasetProvider' -import { DatasetRepository } from '../../../../../../../../../../src/dataset/domain/repositories/DatasetRepository' -import { - DatasetLockMother, - DatasetMother -} from '../../../../../../../../dataset/domain/models/DatasetMother' -import { FilePreviewMother } from '../../../../../../../../files/domain/models/FilePreviewMother' -import { FileIngestMother } from '../../../../../../../../files/domain/models/FileIngestMother' - -const fileNonTabular = FilePreviewMother.create({ - metadata: FileMetadataMother.createNonTabular(), - ingest: FileIngestMother.createIngestNone() -}) -describe('FileNonTabularDownloadOptions', () => { - it('renders the download options for a non-tabular file of unknown type', () => { - const fileNonTabularUnknown = FilePreviewMother.create({ - metadata: FileMetadataMother.createNonTabularUnknown(), - ingest: FileIngestMother.createIngestNone() - }) - cy.customMount() - - cy.findByRole('link', { name: 'Original File Format' }) - .should('exist') - .should('not.have.class', 'disabled') - .should('have.attr', 'href', fileNonTabularUnknown.metadata.downloadUrls.original) - }) - - it('renders the download options for a non-tabular file', () => { - cy.customMount() - - cy.findByRole('link', { name: 'Plain Text' }) - .should('exist') - .should('not.have.class', 'disabled') - .should('have.attr', 'href', fileNonTabular.metadata.downloadUrls.original) - }) - - it('does not render the download options for a tabular file', () => { - const fileTabular = FilePreviewMother.createTabular() - cy.customMount() - - cy.findByRole('link', { name: 'Original File Format' }).should('not.exist') - cy.findByRole('link', { name: 'Tab-Delimited' }).should('not.exist') - }) - - it('renders the options as disabled when the file ingest is in progress', () => { - const fileNonTabularInProgress = FilePreviewMother.create({ - metadata: FileMetadataMother.createNonTabular(), - ingest: FileIngestMother.createInProgress() - }) - cy.customMount() - - cy.findByRole('link', { name: 'Plain Text' }).should('have.class', 'disabled') - }) - - it('renders the options as disabled when the dataset is locked from file download', () => { - const datasetRepository: DatasetRepository = {} as DatasetRepository - const datasetLockedFromFileDownload = DatasetMother.create({ - locks: [DatasetLockMother.createLockedFromFileDownload()] - }) - datasetRepository.getByPersistentId = cy.stub().resolves(datasetLockedFromFileDownload) - - cy.customMount( - - - - ) - - cy.findByRole('link', { name: 'Plain Text' }).should('have.class', 'disabled') - }) -}) diff --git a/tests/component/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/FileTabularDownloadOptions.spec.tsx b/tests/component/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/FileTabularDownloadOptions.spec.tsx deleted file mode 100644 index 500bb9be5..000000000 --- a/tests/component/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/FileTabularDownloadOptions.spec.tsx +++ /dev/null @@ -1,118 +0,0 @@ -import { FileMetadataMother } from '../../../../../../../../files/domain/models/FileMetadataMother' -import { FileType } from '../../../../../../../../../../src/files/domain/models/FileMetadata' -import { FileTabularDownloadOptions } from '../../../../../../../../../../src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/FileTabularDownloadOptions' -import { DatasetRepository } from '../../../../../../../../../../src/dataset/domain/repositories/DatasetRepository' -import { - DatasetLockMother, - DatasetMother -} from '../../../../../../../../dataset/domain/models/DatasetMother' -import { DatasetProvider } from '../../../../../../../../../../src/sections/dataset/DatasetProvider' -import { FilePreviewMother } from '../../../../../../../../files/domain/models/FilePreviewMother' -import { FileIngestMother } from '../../../../../../../../files/domain/models/FileIngestMother' - -const fileNonTabular = FilePreviewMother.create({ - metadata: FileMetadataMother.createNonTabular(), - ingest: FileIngestMother.createIngestNone() -}) -const fileTabular = FilePreviewMother.create({ - metadata: FileMetadataMother.createTabular(), - ingest: FileIngestMother.createIngestNone() -}) -const fileTabularUnknown = FilePreviewMother.create({ - metadata: FileMetadataMother.createTabular({ - type: new FileType('text/tab-separated-values', 'Unknown') - }), - ingest: FileIngestMother.createIngestNone() -}) -describe('FileTabularDownloadOptions', () => { - it('renders the download options for a tabular file', () => { - cy.customMount() - - cy.findByRole('link', { name: 'Comma Separated Values (Original File Format)' }) - .should('exist') - .should('have.attr', 'href', fileTabular.metadata.downloadUrls.original) - cy.findByRole('link', { name: 'Tab-Delimited' }) - .should('exist') - .should('have.attr', 'href', fileTabular.metadata.downloadUrls.tabular) - .should('not.have.class', 'disabled') - cy.findByRole('link', { name: 'R Data' }) - .should('exist') - .should('not.have.class', 'disabled') - .should('have.attr', 'href', fileTabular.metadata.downloadUrls.rData) - }) - - it('renders the download options for a tabular file of unknown original type', () => { - cy.customMount() - - cy.findByRole('link', { name: /(Original File Format)/ }).should('not.exist') - cy.findByRole('link', { name: 'Tab-Delimited' }) - .should('exist') - .should('not.have.class', 'disabled') - cy.findByRole('link', { name: 'R Data' }).should('exist').should('not.have.class', 'disabled') - }) - - it('does not render the download options for a non-tabular file', () => { - cy.customMount() - - cy.findByRole('link', { name: /(Original File Format)/ }).should('not.exist') - cy.findByRole('link', { name: 'Tab-Delimited' }).should('not.exist') - cy.findByRole('link', { name: 'R Data' }).should('not.exist') - }) - - it('renders the options as disabled when the file ingest is in progress', () => { - const fileTabularInProgress = FilePreviewMother.createTabular({ - ingest: FileIngestMother.createInProgress() - }) - cy.customMount() - - cy.findByRole('link', { name: 'Comma Separated Values (Original File Format)' }) - .should('exist') - .should('have.class', 'disabled') - cy.findByRole('link', { name: 'Tab-Delimited' }) - .should('exist') - .should('have.class', 'disabled') - cy.findByRole('link', { name: 'R Data' }).should('exist').should('have.class', 'disabled') - }) - - it('renders the options as disabled when the dataset is locked from file download', () => { - const datasetRepository: DatasetRepository = {} as DatasetRepository - const datasetLockedFromFileDownload = DatasetMother.create({ - locks: [DatasetLockMother.createLockedFromFileDownload()] - }) - datasetRepository.getByPersistentId = cy.stub().resolves(datasetLockedFromFileDownload) - - cy.customMount( - - - - ) - - cy.findByRole('link', { name: 'Comma Separated Values (Original File Format)' }) - .should('exist') - .should('have.class', 'disabled') - cy.findByRole('link', { name: 'Tab-Delimited' }) - .should('exist') - .should('have.class', 'disabled') - cy.findByRole('link', { name: 'R Data' }).should('exist').should('have.class', 'disabled') - }) - - it('does not render the RData option if the file type is already R Data', () => { - const fileTabularRData = FilePreviewMother.create({ - metadata: FileMetadataMother.createTabular({ - type: new FileType('application/octet-stream', 'R Data') - }), - ingest: FileIngestMother.createIngestNone() - }) - cy.customMount() - - cy.findByRole('link', { name: 'R Data (Original File Format)' }) - .should('exist') - .should('not.have.class', 'disabled') - cy.findByRole('link', { name: 'Tab-Delimited' }) - .should('exist') - .should('not.have.class', 'disabled') - cy.findByRole('link', { name: 'R Data' }).should('not.exist') - }) -}) diff --git a/tests/component/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/RequestAccessOption.spec.tsx b/tests/component/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/RequestAccessOption.spec.tsx deleted file mode 100644 index 9f3537947..000000000 --- a/tests/component/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/RequestAccessOption.spec.tsx +++ /dev/null @@ -1,122 +0,0 @@ -import { RequestAccessOption } from '../../../../../../../../../../src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/RequestAccessOption' -import { FileRepository } from '../../../../../../../../../../src/files/domain/repositories/FileRepository' -import { FileUserPermissionsMother } from '../../../../../../../../files/domain/models/FileUserPermissionsMother' -import { FilePermissionsProvider } from '../../../../../../../../../../src/sections/file/file-permissions/FilePermissionsProvider' -import { FilePreviewMother } from '../../../../../../../../files/domain/models/FilePreviewMother' - -describe('RequestAccessOption', () => { - it('renders the embargoed message when the file is embargoed', () => { - const fileEmbargoed = FilePreviewMother.createWithEmbargo() - cy.customMount() - - cy.findByRole('button', { name: 'Files are unavailable during the specified embargo.' }) - .should('exist') - .should('have.class', 'disabled') - }) - - it('renders the embargo then restricted message when the file is embargoed and restricted', () => { - const fileEmbargoedRestricted = FilePreviewMother.createWithEmbargoRestricted() - cy.customMount() - - cy.findByRole('button', { - name: 'Files are unavailable during the specified embargo and restricted after that.' - }) - .should('exist') - .should('have.class', 'disabled') - }) - - it('renders the Users may not request access to files. message when the file is restricted and access request is not allowed', () => { - const fileRestricted = FilePreviewMother.createRestricted() - cy.customMount() - - cy.findByRole('button', { name: 'Users may not request access to files.' }) - .should('exist') - .should('have.class', 'disabled') - }) - - it('renders the request access button when the file is restricted and can be requested', () => { - const fileRestrictedCanBeRequested = FilePreviewMother.createWithAccessRequestAllowed() - cy.customMount() - - cy.findByRole('button', { name: 'Request Access' }).should('exist') - }) - - it('renders the access requested message when hen the file is restricted and the access has already been requested', () => { - const fileAlreadyRequested = FilePreviewMother.createWithAccessRequestPending() - - cy.customMount() - - cy.findByRole('button', { name: 'Access Requested' }) - .should('exist') - .should('have.class', 'disabled') - }) - - it('does not render the request access button when the file is deaccessioned', () => { - const fileDeaccessioned = FilePreviewMother.createDeaccessioned() - cy.customMount() - - cy.findByRole('button', { name: 'Users may not request access to files.' }).should('not.exist') - cy.findByRole('button', { name: 'Request Access' }).should('not.exist') - cy.findByRole('button', { name: 'Access Requested' }).should('not.exist') - cy.findByRole('button', { name: 'Files are unavailable during the specified embargo.' }).should( - 'not.exist' - ) - cy.findByRole('button', { - name: 'Files are unavailable during the specified embargo and restricted after that.' - }).should('not.exist') - }) - - it('does not render the request access button when the file status is public', () => { - const filePublic = FilePreviewMother.createWithPublicAccess() - const fileRepository: FileRepository = {} as FileRepository - fileRepository.getUserPermissionsById = cy.stub().resolves( - FileUserPermissionsMother.create({ - fileId: filePublic.id, - canDownloadFile: true - }) - ) - - cy.customMount( - - - - ) - - cy.findByRole('button', { name: 'Users may not request access to files.' }).should('not.exist') - cy.findByRole('button', { name: 'Request Access' }).should('not.exist') - cy.findByRole('button', { name: 'Access Requested' }).should('not.exist') - cy.findByRole('button', { name: 'Files are unavailable during the specified embargo.' }).should( - 'not.exist' - ) - cy.findByRole('button', { - name: 'Files are unavailable during the specified embargo and restricted after that.' - }).should('not.exist') - }) - - it('does not render the request access button when the file status is restricted with access granted', () => { - const fileRestrictedWithAccess = FilePreviewMother.createRestrictedWithAccessGranted() - const fileRepository: FileRepository = {} as FileRepository - fileRepository.getUserPermissionsById = cy.stub().resolves( - FileUserPermissionsMother.create({ - fileId: fileRestrictedWithAccess.id, - canDownloadFile: true - }) - ) - - cy.customMount( - - - - ) - - cy.findByRole('button', { name: 'Users may not request access to files.' }).should('not.exist') - cy.findByRole('button', { name: 'Request Access' }).should('not.exist') - cy.findByRole('button', { name: 'Access Requested' }).should('not.exist') - cy.findByRole('button', { name: 'Files are unavailable during the specified embargo.' }).should( - 'not.exist' - ) - cy.findByRole('button', { - name: 'Files are unavailable during the specified embargo and restricted after that.' - }).should('not.exist') - }) -}) diff --git a/tests/component/sections/dataset/dataset-files/files-table/files-info/file-info-cell/file-info-data/file-thumbnail/FileThumbnail.spec.tsx b/tests/component/sections/dataset/dataset-files/files-table/files-info/file-info-cell/file-info-data/file-thumbnail/FileThumbnail.spec.tsx index 85474e633..2428861fa 100644 --- a/tests/component/sections/dataset/dataset-files/files-table/files-info/file-info-cell/file-info-data/file-thumbnail/FileThumbnail.spec.tsx +++ b/tests/component/sections/dataset/dataset-files/files-table/files-info/file-info-cell/file-info-data/file-thumbnail/FileThumbnail.spec.tsx @@ -41,7 +41,7 @@ describe('FileThumbnail', () => { }) it('renders FilePreviewImage when thumbnail is provided with unlocked icon if restricted with access', () => { - const file = FilePreviewMother.createWithThumbnailRestrictedWithAccessGranted() + const file = FilePreviewMother.createWithThumbnailRestricted() fileRepository.getUserPermissionsById = cy.stub().resolves( FileUserPermissionsMother.create({ fileId: file.id, @@ -104,7 +104,7 @@ describe('FileThumbnail', () => { }) it('renders FileIcon when thumbnail is not provided with unlock icon when restricted with access', () => { - const file = FilePreviewMother.createRestrictedWithAccessGranted() + const file = FilePreviewMother.createRestricted() fileRepository.getUserPermissionsById = cy.stub().resolves( FileUserPermissionsMother.create({ fileId: file.id, diff --git a/tests/component/sections/file/File.spec.tsx b/tests/component/sections/file/File.spec.tsx index f006dbf1a..ad3eab491 100644 --- a/tests/component/sections/file/File.spec.tsx +++ b/tests/component/sections/file/File.spec.tsx @@ -24,6 +24,7 @@ describe('File', () => { cy.findByText('Version 1.0').should('exist') cy.findByRole('tab', { name: 'Metadata' }).should('exist') cy.findByRole('button', { name: 'File Metadata' }).should('exist') + cy.findByRole('group', { name: 'File Action Buttons' }).should('exist') }) it('renders skeleton while loading', () => { diff --git a/tests/component/sections/file/file-action-buttons/access-file-menu/AccessFileMenu.spec.tsx b/tests/component/sections/file/file-action-buttons/access-file-menu/AccessFileMenu.spec.tsx new file mode 100644 index 000000000..e3821e522 --- /dev/null +++ b/tests/component/sections/file/file-action-buttons/access-file-menu/AccessFileMenu.spec.tsx @@ -0,0 +1,138 @@ +import { AccessFileMenu } from '../../../../../../src/sections/file/file-action-buttons/access-file-menu/AccessFileMenu' +import { FileAccessMother } from '../../../../files/domain/models/FileAccessMother' +import { FileMetadataMother } from '../../../../files/domain/models/FileMetadataMother' +import { Suspense } from 'react' + +describe('AccessFileMenu', () => { + it('renders the access file menu', () => { + cy.customMount( + + ) + + cy.findByRole('button', { name: 'Access File' }).should('exist') + }) + + it('renders the access file menu with tooltip when asIcon is true', () => { + cy.customMount( + + ) + + cy.findByRole('button', { name: 'Access File' }).trigger('mouseover') + cy.findByRole('tooltip', { name: 'Access File' }).should('exist') + }) + + it('does not render the access file menu with tooltip when asIcon is false', () => { + cy.customMount( + + ) + + cy.findByRole('button', { name: 'Access File' }).trigger('mouseover') + cy.findByRole('tooltip', { name: 'Access File' }).should('not.exist') + }) + + it('renders the menu headers', () => { + cy.customMount( + + + + ) + + cy.findByRole('button', { name: 'Access File' }).should('exist').click() + cy.findByRole('heading', { name: 'File Access' }).should('exist') + }) + + it('renders the access status of the file', () => { + cy.customMount( + + ) + + cy.findByRole('button', { name: 'Access File' }).click() + cy.findByText('Public').should('exist') + }) + + it('renders the request access button', () => { + cy.customMount( + + ) + + cy.findByRole('button', { name: 'Access File' }).click() + cy.findByRole('button', { name: 'Request Access' }).should('exist') + }) + + it('renders the download options header', () => { + cy.customMount( + + ) + + cy.findByRole('button', { name: 'Access File' }).click() + cy.findByRole('heading', { name: 'Download Options' }).should('exist') + }) + + it('renders the button as an icon when asIcon is true', () => { + cy.customMount( + + ) + + cy.findByRole('button', { name: 'Access File' }).should('exist') + cy.get('svg').should('exist') + }) +}) diff --git a/tests/component/sections/file/file-action-buttons/access-file-menu/AccessStatus.spec.tsx b/tests/component/sections/file/file-action-buttons/access-file-menu/AccessStatus.spec.tsx new file mode 100644 index 000000000..93d86bf4f --- /dev/null +++ b/tests/component/sections/file/file-action-buttons/access-file-menu/AccessStatus.spec.tsx @@ -0,0 +1,80 @@ +import { AccessStatus } from '../../../../../../src/sections/file/file-action-buttons/access-file-menu/AccessStatus' +import styles from '../../../../../../src/sections/file/file-action-buttons/access-file-menu/AccessFileMenu.module.scss' + +describe('AccessStatus', () => { + it('renders the access status public when is not restricted and the user does not have permissions', () => { + cy.customMount( + + ) + + cy.findByText('Public').should('exist').should('have.class', styles.success) + cy.findByText('Public File Icon').should('exist') + }) + + it('renders the the public embargoed status then the file is not restricted but its embargoed', () => { + cy.customMount( + + ) + + cy.findByText('Embargoed').should('exist').should('have.class', styles.danger) + cy.findByText('Public File Icon').should('exist') + }) + + it('renders the access status public', () => { + cy.customMount( + + ) + + cy.findByText('Public').should('exist').should('have.class', styles.success) + cy.findByText('Public File Icon').should('exist') + }) + + it('renders the access status restricted', () => { + cy.customMount( + + ) + + cy.findByText('Restricted').should('exist').should('have.class', styles.danger) + cy.findByText('Restricted File Icon').should('exist') + }) + + it('renders the access status restricted with access', () => { + cy.customMount( + + ) + + cy.findByText('Restricted with Access Granted') + .should('exist') + .should('have.class', styles.success) + cy.findByText('Restricted with access Icon').should('exist') + }) + + it('renders the access status embargoed', () => { + cy.customMount( + + ) + + cy.findByText('Embargoed').should('exist').should('have.class', styles.success) + cy.findByText('Public File Icon').should('exist') + }) + + it('renders the access status embargoed restricted', () => { + cy.customMount( + + ) + + cy.findByText('Embargoed').should('exist').should('have.class', styles.danger) + cy.findByText('Restricted File Icon').should('exist') + }) + + it('renders the access status embargoed restricted with access', () => { + cy.customMount() + + cy.findByText('Embargoed').should('exist').should('have.class', styles.success) + cy.findByText('Restricted with access Icon').should('exist') + }) +}) diff --git a/tests/component/sections/file/file-action-buttons/access-file-menu/FileDownloadOptions.spec.tsx b/tests/component/sections/file/file-action-buttons/access-file-menu/FileDownloadOptions.spec.tsx new file mode 100644 index 000000000..64f80369b --- /dev/null +++ b/tests/component/sections/file/file-action-buttons/access-file-menu/FileDownloadOptions.spec.tsx @@ -0,0 +1,66 @@ +import { FileDownloadOptions } from '../../../../../../src/sections/file/file-action-buttons/access-file-menu/FileDownloadOptions' +import { + FileDownloadUrlsMother, + FileTypeMother +} from '../../../../files/domain/models/FileMetadataMother' + +const nonTabularType = FileTypeMother.createText() +const downloadUrls = FileDownloadUrlsMother.create() +describe('FileDownloadOptions', () => { + it('renders the download options header', () => { + cy.customMount( + + ) + + cy.findByRole('heading', { name: 'Download Options' }).should('exist') + }) + + it('does not render the download options if the user does not have permissions', () => { + cy.customMount( + + ) + + cy.findByRole('heading', { name: 'Download Options' }).should('not.exist') + }) + + it('renders the download options for a non-tabular file', () => { + cy.customMount( + + ) + + cy.findByRole('link', { name: 'Plain Text' }).should('exist') + }) + + it('renders the download options for a tabular file', () => { + const tabularType = FileTypeMother.createTabular() + cy.customMount( + + ) + + cy.findByRole('link', { name: 'Comma Separated Values (Original File Format)' }).should('exist') + }) +}) diff --git a/tests/component/sections/file/file-action-buttons/access-file-menu/FileNonTabularDownloadOptions.spec.tsx b/tests/component/sections/file/file-action-buttons/access-file-menu/FileNonTabularDownloadOptions.spec.tsx new file mode 100644 index 000000000..dc03dda69 --- /dev/null +++ b/tests/component/sections/file/file-action-buttons/access-file-menu/FileNonTabularDownloadOptions.spec.tsx @@ -0,0 +1,78 @@ +import { + FileDownloadUrlsMother, + FileTypeMother +} from '../../../../files/domain/models/FileMetadataMother' + +import { FileNonTabularDownloadOptions } from '../../../../../../src/sections/file/file-action-buttons/access-file-menu/FileNonTabularDownloadOptions' +import { DatasetProvider } from '../../../../../../src/sections/dataset/DatasetProvider' +import { DatasetRepository } from '../../../../../../src/dataset/domain/repositories/DatasetRepository' +import { DatasetLockMother, DatasetMother } from '../../../../dataset/domain/models/DatasetMother' + +const unknownType = FileTypeMother.createUnknown() +const downloadUrls = FileDownloadUrlsMother.create() +const textType = FileTypeMother.createText() +describe('FileNonTabularDownloadOptions', () => { + it('renders the download options for a file of unknown type', () => { + cy.customMount( + + ) + + cy.findByRole('link', { name: 'Original File Format' }) + .should('exist') + .should('not.have.class', 'disabled') + .should('have.attr', 'href', downloadUrls.original) + }) + + it('renders the download options for a file of known type', () => { + cy.customMount( + + ) + + cy.findByRole('link', { name: 'Plain Text' }) + .should('exist') + .should('not.have.class', 'disabled') + .should('have.attr', 'href', downloadUrls.original) + }) + + it('renders the options as disabled when the file ingest is in progress', () => { + cy.customMount( + + ) + + cy.findByRole('link', { name: 'Plain Text' }).should('have.class', 'disabled') + }) + + it('renders the options as disabled when the dataset is locked from file download', () => { + const datasetRepository: DatasetRepository = {} as DatasetRepository + const datasetLockedFromFileDownload = DatasetMother.create({ + locks: [DatasetLockMother.createLockedFromFileDownload()] + }) + datasetRepository.getByPersistentId = cy.stub().resolves(datasetLockedFromFileDownload) + + cy.customMount( + + + + ) + + cy.findByRole('link', { name: 'Plain Text' }).should('have.class', 'disabled') + }) +}) diff --git a/tests/component/sections/file/file-action-buttons/access-file-menu/FileTabularDownloadOptions.spec.tsx b/tests/component/sections/file/file-action-buttons/access-file-menu/FileTabularDownloadOptions.spec.tsx new file mode 100644 index 000000000..5316b691b --- /dev/null +++ b/tests/component/sections/file/file-action-buttons/access-file-menu/FileTabularDownloadOptions.spec.tsx @@ -0,0 +1,112 @@ +import { + FileDownloadUrlsMother, + FileTypeMother +} from '../../../../files/domain/models/FileMetadataMother' +import { FileTabularDownloadOptions } from '../../../../../../src/sections/file/file-action-buttons/access-file-menu/FileTabularDownloadOptions' +import { DatasetRepository } from '../../../../../../src/dataset/domain/repositories/DatasetRepository' +import { DatasetLockMother, DatasetMother } from '../../../../dataset/domain/models/DatasetMother' +import { DatasetProvider } from '../../../../../../src/sections/dataset/DatasetProvider' + +const tabularType = FileTypeMother.createTabular() +const downloadUrls = FileDownloadUrlsMother.create() +describe('FileTabularDownloadOptions', () => { + it('renders the download options for a tabular file', () => { + cy.customMount( + + ) + + cy.findByRole('link', { name: 'Comma Separated Values (Original File Format)' }) + .should('exist') + .should('have.attr', 'href', downloadUrls.original) + cy.findByRole('link', { name: 'Tab-Delimited' }) + .should('exist') + .should('have.attr', 'href', downloadUrls.tabular) + .should('not.have.class', 'disabled') + cy.findByRole('link', { name: 'R Data' }) + .should('exist') + .should('not.have.class', 'disabled') + .should('have.attr', 'href', downloadUrls.rData) + }) + + it('renders the download options for a tabular file of unknown original type', () => { + const unknownType = FileTypeMother.createTabularUnknown() + cy.customMount( + + ) + + cy.findByRole('link', { name: /(Original File Format)/ }).should('not.exist') + cy.findByRole('link', { name: 'Tab-Delimited' }) + .should('exist') + .should('not.have.class', 'disabled') + cy.findByRole('link', { name: 'R Data' }).should('exist').should('not.have.class', 'disabled') + }) + + it('renders the options as disabled when the file ingest is in progress', () => { + cy.customMount( + + ) + + cy.findByRole('link', { name: 'Comma Separated Values (Original File Format)' }) + .should('exist') + .should('have.class', 'disabled') + cy.findByRole('link', { name: 'Tab-Delimited' }) + .should('exist') + .should('have.class', 'disabled') + cy.findByRole('link', { name: 'R Data' }).should('exist').should('have.class', 'disabled') + }) + + it('renders the options as disabled when the dataset is locked from file download', () => { + const datasetRepository: DatasetRepository = {} as DatasetRepository + const datasetLockedFromFileDownload = DatasetMother.create({ + locks: [DatasetLockMother.createLockedFromFileDownload()] + }) + datasetRepository.getByPersistentId = cy.stub().resolves(datasetLockedFromFileDownload) + + cy.customMount( + + + + ) + + cy.findByRole('link', { name: 'Comma Separated Values (Original File Format)' }) + .should('exist') + .should('have.class', 'disabled') + cy.findByRole('link', { name: 'Tab-Delimited' }) + .should('exist') + .should('have.class', 'disabled') + cy.findByRole('link', { name: 'R Data' }).should('exist').should('have.class', 'disabled') + }) + + it('does not render the RData option if the file type is already R Data', () => { + const rDataType = FileTypeMother.createRData() + cy.customMount( + + ) + + cy.findByRole('link', { name: 'R Data (Original File Format)' }) + .should('exist') + .should('not.have.class', 'disabled') + cy.findByRole('link', { name: 'Tab-Delimited' }) + .should('exist') + .should('not.have.class', 'disabled') + cy.findByRole('link', { name: 'R Data' }).should('not.exist') + }) +}) diff --git a/tests/component/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/RequestAccessModal.spec.tsx b/tests/component/sections/file/file-action-buttons/access-file-menu/RequestAccessModal.spec.tsx similarity index 76% rename from tests/component/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/RequestAccessModal.spec.tsx rename to tests/component/sections/file/file-action-buttons/access-file-menu/RequestAccessModal.spec.tsx index f261a7500..b0faad15f 100644 --- a/tests/component/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/RequestAccessModal.spec.tsx +++ b/tests/component/sections/file/file-action-buttons/access-file-menu/RequestAccessModal.spec.tsx @@ -1,9 +1,9 @@ -import { RequestAccessModal } from '../../../../../../../../../../src/sections/dataset/dataset-files/files-table/file-actions/file-actions-cell/file-action-buttons/access-file-menu/RequestAccessModal' -import { UserMother } from '../../../../../../../../users/domain/models/UserMother' -import { UserRepository } from '../../../../../../../../../../src/users/domain/repositories/UserRepository' -import { SessionProvider } from '../../../../../../../../../../src/sections/session/SessionProvider' -import { Route } from '../../../../../../../../../../src/sections/Route.enum' -import { FilePreviewMother } from '../../../../../../../../files/domain/models/FilePreviewMother' +import { RequestAccessModal } from '../../../../../../src/sections/file/file-action-buttons/access-file-menu/RequestAccessModal' +import { UserMother } from '../../../../users/domain/models/UserMother' +import { UserRepository } from '../../../../../../src/users/domain/repositories/UserRepository' +import { SessionProvider } from '../../../../../../src/sections/session/SessionProvider' +import { Route } from '../../../../../../src/sections/Route.enum' +import { FilePreviewMother } from '../../../../files/domain/models/FilePreviewMother' describe('RequestAccessModal', () => { it('renders the RequestAccessModal', () => { diff --git a/tests/component/sections/file/file-action-buttons/access-file-menu/RequestAccessOption.spec.tsx b/tests/component/sections/file/file-action-buttons/access-file-menu/RequestAccessOption.spec.tsx new file mode 100644 index 000000000..18c39fa31 --- /dev/null +++ b/tests/component/sections/file/file-action-buttons/access-file-menu/RequestAccessOption.spec.tsx @@ -0,0 +1,135 @@ +import { RequestAccessOption } from '../../../../../../src/sections/file/file-action-buttons/access-file-menu/RequestAccessOption' +import { FileAccessMother } from '../../../../files/domain/models/FileAccessMother' + +const access = FileAccessMother.create() +describe('RequestAccessOption', () => { + it('renders the embargoed message when the file is embargoed', () => { + const accessPublic = FileAccessMother.createPublic() + cy.customMount( + + ) + + cy.findByRole('button', { name: 'Files are unavailable during the specified embargo.' }) + .should('exist') + .should('have.class', 'disabled') + }) + + it('renders the embargo then restricted message when the file is embargoed and restricted', () => { + const accessRestricted = FileAccessMother.createRestricted() + cy.customMount( + + ) + + cy.findByRole('button', { + name: 'Files are unavailable during the specified embargo and restricted after that.' + }) + .should('exist') + .should('have.class', 'disabled') + }) + + it('renders the Users may not request access to files. message when the file is restricted and access request is not allowed', () => { + const accessRequestNotAllowed = FileAccessMother.createWithAccessRequestNotAllowed() + cy.customMount( + + ) + + cy.findByRole('button', { name: 'Users may not request access to files.' }) + .should('exist') + .should('have.class', 'disabled') + }) + + it('renders the request access button when the file is restricted and can be requested', () => { + const accessRequestAllowed = FileAccessMother.createWithAccessRequestAllowed() + cy.customMount( + + ) + + cy.findByRole('button', { name: 'Request Access' }).should('exist') + }) + + it('renders the access requested message when hen the file is restricted and the access has already been requested', () => { + const accessRequestPending = FileAccessMother.createWithAccessRequestPending() + + cy.customMount( + + ) + + cy.findByRole('button', { name: 'Access Requested' }) + .should('exist') + .should('have.class', 'disabled') + }) + + it('does not render the request access button when the file is deaccessioned', () => { + cy.customMount( + + ) + + cy.findByRole('button', { name: 'Users may not request access to files.' }).should('not.exist') + cy.findByRole('button', { name: 'Request Access' }).should('not.exist') + cy.findByRole('button', { name: 'Access Requested' }).should('not.exist') + cy.findByRole('button', { name: 'Files are unavailable during the specified embargo.' }).should( + 'not.exist' + ) + cy.findByRole('button', { + name: 'Files are unavailable during the specified embargo and restricted after that.' + }).should('not.exist') + }) + + it('does not render the request access button when the user has download permission', () => { + cy.customMount( + + ) + + cy.findByRole('button', { name: 'Users may not request access to files.' }).should('not.exist') + cy.findByRole('button', { name: 'Request Access' }).should('not.exist') + cy.findByRole('button', { name: 'Access Requested' }).should('not.exist') + cy.findByRole('button', { name: 'Files are unavailable during the specified embargo.' }).should( + 'not.exist' + ) + cy.findByRole('button', { + name: 'Files are unavailable during the specified embargo and restricted after that.' + }).should('not.exist') + }) +})