Skip to content

Commit

Permalink
feat(DownloadFiles): add the No Selected Files modal
Browse files Browse the repository at this point in the history
  • Loading branch information
MellyGray committed Oct 26, 2023
1 parent ecae5f7 commit 2fe5ea9
Show file tree
Hide file tree
Showing 15 changed files with 269 additions and 59 deletions.
15 changes: 10 additions & 5 deletions public/locales/en/files.json
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,11 @@
"message": "This file has already been deleted (or replaced) in the current version. It may not be edited.",
"close": "Close"
},
"noSelectedFilesAlert": {
"title": "Select File(s)",
"message": "Please select one or more files.",
"close": "Close"
},
"accessFileMenu": {
"title": "Access File",
"headers": {
Expand All @@ -122,11 +127,11 @@
}
},
"downloadFiles": {
"title": "Download",
"options": {
"original": "Original Format",
"archival": "Archival Format (.tab)"
}
"title": "Download",
"options": {
"original": "Original Format",
"archival": "Archival Format (.tab)"
}
}
},
"requestAccess": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ import { FileInfoHeader } from './file-info/FileInfoHeader'
import { FileActionsHeader } from './file-actions/FileActionsHeader'
import { FileActionsCell } from './file-actions/file-actions-cell/FileActionsCell'
import { FilePaginationInfo } from '../../../../files/domain/models/FilePaginationInfo'
import { FileSelection } from './row-selection/useFileSelection'

export const createColumnsDefinition = (paginationInfo: FilePaginationInfo): ColumnDef<File>[] => [
export const createColumnsDefinition = (
paginationInfo: FilePaginationInfo,
fileSelection: FileSelection
): ColumnDef<File>[] => [
{
id: 'select',
header: ({ table }) => (
Expand Down Expand Up @@ -38,7 +42,10 @@ export const createColumnsDefinition = (paginationInfo: FilePaginationInfo): Col
},
{
header: ({ table }) => (
<FileActionsHeader files={table.getRowModel().rows.map((row) => row.original)} />
<FileActionsHeader
files={table.getRowModel().rows.map((row) => row.original)}
fileSelection={fileSelection}
/>
),
accessorKey: 'status',
cell: (props) => <FileActionsCell file={props.row.original} />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.container {
text-align: right;
display: flex;
justify-content: end;
text-align: right;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@ import { File } from '../../../../../files/domain/models/File'
import styles from './FileActionsHeader.module.scss'
import { useTranslation } from 'react-i18next'
import { DownloadFilesButton } from './download-files/DownloadFilesButton'
import { FileSelection } from '../row-selection/useFileSelection'
interface FileActionsHeaderProps {
files: File[]
fileSelection: FileSelection
}
export function FileActionsHeader({ files }: FileActionsHeaderProps) {
export function FileActionsHeader({ files, fileSelection }: FileActionsHeaderProps) {
const { t } = useTranslation('files')
return (
<div aria-label={t('actions.title')} className={styles.container}>
<EditFilesMenu files={files} />
<DownloadFilesButton files={files} />
<EditFilesMenu files={files} fileSelection={fileSelection} />
<DownloadFilesButton files={files} fileSelection={fileSelection} />
</div>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,21 @@ import { Button, DropdownButton, DropdownButtonItem } from '@iqss/dataverse-desi
import { Download } from 'react-bootstrap-icons'
import styles from './DownloadFilesButton.module.scss'
import { useTranslation } from 'react-i18next'
import { FileSelection } from '../../row-selection/useFileSelection'
import { NoSelectedFilesModal } from '../no-selected-files-modal/NoSelectedFilesModal'
import { useState } from 'react'

interface DownloadFilesButtonProps {
files: File[]
fileSelection: FileSelection
}

const MINIMUM_FILES_COUNT_TO_SHOW_DOWNLOAD_FILES_BUTTON = 1
export function DownloadFilesButton({ files }: DownloadFilesButtonProps) {
const SELECTED_FILES_EMPTY = 0
export function DownloadFilesButton({ files, fileSelection }: DownloadFilesButtonProps) {
const { t } = useTranslation('files')
const { dataset } = useDataset()
const [showNoFilesSelectedModal, setShowNoFilesSelectedModal] = useState(false)

if (
files.length < MINIMUM_FILES_COUNT_TO_SHOW_DOWNLOAD_FILES_BUTTON ||
Expand All @@ -21,23 +27,49 @@ export function DownloadFilesButton({ files }: DownloadFilesButtonProps) {
return <></>
}

const onClick = () => {
if (Object.keys(fileSelection).length === SELECTED_FILES_EMPTY) {
setShowNoFilesSelectedModal(true)
}
}

if (files.some((file) => file.isTabularData)) {
return (
<DropdownButton
id="download-files"
icon={<Download className={styles.icon} />}
title={t('actions.downloadFiles.title')}
variant="secondary"
withSpacing>
<DropdownButtonItem>{t('actions.downloadFiles.options.original')}</DropdownButtonItem>
<DropdownButtonItem>{t('actions.downloadFiles.options.archival')}</DropdownButtonItem>
</DropdownButton>
<>
<DropdownButton
id="download-files"
icon={<Download className={styles.icon} />}
title={t('actions.downloadFiles.title')}
variant="secondary"
withSpacing>
<DropdownButtonItem onClick={onClick}>
{t('actions.downloadFiles.options.original')}
</DropdownButtonItem>
<DropdownButtonItem onClick={onClick}>
{t('actions.downloadFiles.options.archival')}
</DropdownButtonItem>
</DropdownButton>
<NoSelectedFilesModal
show={showNoFilesSelectedModal}
handleClose={() => setShowNoFilesSelectedModal(false)}
/>
</>
)
}

return (
<Button variant="secondary" icon={<Download className={styles.icon} />} withSpacing>
{t('actions.downloadFiles.title')}
</Button>
<>
<Button
variant="secondary"
icon={<Download className={styles.icon} />}
withSpacing
onClick={onClick}>
{t('actions.downloadFiles.title')}
</Button>
<NoSelectedFilesModal
show={showNoFilesSelectedModal}
handleClose={() => setShowNoFilesSelectedModal(false)}
/>
</>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ import { EditFilesOptions } from './EditFilesOptions'
import { File } from '../../../../../../files/domain/models/File'
import { useTranslation } from 'react-i18next'
import { useDataset } from '../../../../DatasetContext'
import { FileSelection } from '../../row-selection/useFileSelection'

interface EditFilesMenuProps {
files: File[]
fileSelection: FileSelection
}
const MINIMUM_FILES_COUNT_TO_SHOW_EDIT_FILES_BUTTON = 1
export function EditFilesMenu({ files }: EditFilesMenuProps) {
export function EditFilesMenu({ files, fileSelection }: EditFilesMenuProps) {
const { t } = useTranslation('files')
const { user } = useSession()
const { dataset } = useDataset()
Expand All @@ -30,7 +32,7 @@ export function EditFilesMenu({ files }: EditFilesMenuProps) {
title={t('actions.editFilesMenu.title')}
disabled={dataset.isLockedFromEdits || !dataset.hasValidTermsOfAccess}
icon={<PencilFill className={styles.icon} />}>
<EditFilesOptions files={files} />
<EditFilesOptions files={files} fileSelection={fileSelection} />
</DropdownButton>
)
}
Original file line number Diff line number Diff line change
@@ -1,32 +1,62 @@
import { DropdownButtonItem } from '@iqss/dataverse-design-system'
import { File } from '../../../../../../files/domain/models/File'
import { useTranslation } from 'react-i18next'
import { useState } from 'react'
import { FileSelection } from '../../row-selection/useFileSelection'
import { NoSelectedFilesModal } from '../no-selected-files-modal/NoSelectedFilesModal'

interface EditFileOptionsProps {
files: File[]
fileSelection: FileSelection
}
export function EditFilesOptions({ files }: EditFileOptionsProps) {
const SELECTED_FILES_EMPTY = 0
export function EditFilesOptions({ files, fileSelection }: EditFileOptionsProps) {
const { t } = useTranslation('files')
const [showNoFilesSelectedModal, setShowNoFilesSelectedModal] = useState(false)
const settingsEmbargoAllowed = false // TODO - Ask Guillermo if this is included in the settings endpoint
const provenanceEnabledByConfig = false // TODO - Ask Guillermo if this is included in the MVP and from which endpoint is coming from

const onClick = () => {
if (Object.keys(fileSelection).length === SELECTED_FILES_EMPTY) {
setShowNoFilesSelectedModal(true)
}
}

return (
<>
<DropdownButtonItem>{t('actions.editFilesMenu.options.metadata')}</DropdownButtonItem>
<DropdownButtonItem onClick={onClick}>
{t('actions.editFilesMenu.options.metadata')}
</DropdownButtonItem>
{files.some((file) => file.access.restricted) && (
<DropdownButtonItem>{t('actions.editFilesMenu.options.unrestrict')}</DropdownButtonItem>
<DropdownButtonItem onClick={onClick}>
{t('actions.editFilesMenu.options.unrestrict')}
</DropdownButtonItem>
)}
{files.some((file) => !file.access.restricted) && (
<DropdownButtonItem>{t('actions.editFilesMenu.options.restrict')}</DropdownButtonItem>
<DropdownButtonItem onClick={onClick}>
{t('actions.editFilesMenu.options.restrict')}
</DropdownButtonItem>
)}
<DropdownButtonItem>{t('actions.editFilesMenu.options.replace')}</DropdownButtonItem>
<DropdownButtonItem onClick={onClick}>
{t('actions.editFilesMenu.options.replace')}
</DropdownButtonItem>
{settingsEmbargoAllowed && (
<DropdownButtonItem>{t('actions.editFilesMenu.options.embargo')}</DropdownButtonItem>
<DropdownButtonItem onClick={onClick}>
{t('actions.editFilesMenu.options.embargo')}
</DropdownButtonItem>
)}
{provenanceEnabledByConfig && (
<DropdownButtonItem>{t('actions.editFilesMenu.options.provenance')}</DropdownButtonItem>
<DropdownButtonItem onClick={onClick}>
{t('actions.editFilesMenu.options.provenance')}
</DropdownButtonItem>
)}
<DropdownButtonItem>{t('actions.editFilesMenu.options.delete')}</DropdownButtonItem>
<DropdownButtonItem onClick={onClick}>
{t('actions.editFilesMenu.options.delete')}
</DropdownButtonItem>
<NoSelectedFilesModal
show={showNoFilesSelectedModal}
handleClose={() => setShowNoFilesSelectedModal(false)}
/>
</>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { useTranslation } from 'react-i18next'
import { Button, Modal } from '@iqss/dataverse-design-system'
import styles from '../file-actions-cell/file-action-buttons/file-options-menu/FileAlreadyDeletedModal.module.scss'
import { ExclamationCircleFill } from 'react-bootstrap-icons'

interface NoSelectedFilesModalProps {
show: boolean
handleClose: () => void
}

export function NoSelectedFilesModal({ show, handleClose }: NoSelectedFilesModalProps) {
const { t } = useTranslation('files')
return (
<Modal show={show} onHide={handleClose} size="lg">
<Modal.Header>
<Modal.Title>{t('actions.noSelectedFilesAlert.title')}</Modal.Title>
</Modal.Header>
<Modal.Body>
<p className={styles.paragraph}>
<ExclamationCircleFill /> {t('actions.noSelectedFilesAlert.message')}
</p>
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>
{t('actions.noSelectedFilesAlert.close')}
</Button>
</Modal.Footer>
</Modal>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export function useFilesTable(files: File[], paginationInfo: FilePaginationInfo)
)
const table = useReactTable({
data: files,
columns: createColumnsDefinition(paginationInfo),
columns: createColumnsDefinition(paginationInfo, fileSelection),
state: {
rowSelection: currentPageRowSelection
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ export default meta
type Story = StoryObj<typeof EditFilesMenu>

export const NonTabularFiles: Story = {
render: () => <DownloadFilesButton files={FileMother.createMany(2, { tabularData: undefined })} />
render: () => (
<DownloadFilesButton
files={FileMother.createMany(2, { tabularData: undefined })}
fileSelection={{}}
/>
)
}

export const TabularFiles: Story = {
Expand All @@ -30,6 +35,7 @@ export const TabularFiles: Story = {
unf: 'some-unf'
}
})}
fileSelection={{}}
/>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ export default meta
type Story = StoryObj<typeof EditFilesMenu>

export const Default: Story = {
render: () => <EditFilesMenu files={FileMother.createMany(2)} />
render: () => <EditFilesMenu files={FileMother.createMany(2)} fileSelection={{}} />
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ describe('FileActionsHeader', () => {
<DatasetProvider
repository={datasetRepository}
searchParams={{ persistentId: 'some-persistent-id', version: 'some-version' }}>
<FileActionsHeader files={files} />
<FileActionsHeader files={files} fileSelection={{}} />
</DatasetProvider>
)

Expand Down
Loading

0 comments on commit 2fe5ea9

Please sign in to comment.