Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ interface DropdownItemProps extends React.HTMLAttributes<HTMLElement> {
download?: string
children: ReactNode
as?: ElementType
to?: string // When passing <Link> as the `as` prop, this prop is used to pass the URL <DropdownButtonItem as={Link} to="/some-path">...</DropdownButtonItem>
}

export function DropdownButtonItem({
Expand Down
1 change: 1 addition & 0 deletions public/locales/en/shared.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"clearSearch": "Clear Search",
"submitSearch": "Submit Search",
"dragHandleLabel": "press space to select and keys to drag",
"unknown": "Unknown",
"pageNumberNotFound": {
"heading": "Page Number Not Found",
"message": "The page number you requested does not exist. Please try a different page number."
Expand Down
6 changes: 3 additions & 3 deletions src/files/infrastructure/FileJSDataverseRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ export class FileJSDataverseRepository implements FileRepository {
jsFile,
jsDataset,
getDatasetCitation.execute(jsDataset.id, datasetVersionNumber, includeDeaccessioned),
FileJSDataverseRepository.getCitationById(jsFile.id),
FileJSDataverseRepository.getCitationById(jsFile.id, datasetVersionNumber),
FileJSDataverseRepository.getDownloadCountById(jsFile.id, jsFile.publicationDate),
FileJSDataverseRepository.getPermissionsById(jsFile.id),
FileJSDataverseRepository.getThumbnailById(jsFile.id),
Expand Down Expand Up @@ -271,9 +271,9 @@ export class FileJSDataverseRepository implements FileRepository {
})
}

private static getCitationById(id: number): Promise<string> {
private static getCitationById(id: number, datasetVersionNumber?: string): Promise<string> {
return getFileCitation
.execute(id, undefined, includeDeaccessioned)
.execute(id, datasetVersionNumber, includeDeaccessioned)
.catch((error: ReadError) => {
throw new Error(error.message)
})
Expand Down
16 changes: 14 additions & 2 deletions src/sections/Route.enum.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { ReplaceFileReferrer } from './replace-file/ReplaceFile'

export enum Route {
HOME = '/',
SIGN_UP = '/dataverseuser.xhtml?editMode=CREATE&redirectPage=%2Fdataverse.xhtml',
Expand Down Expand Up @@ -27,13 +29,22 @@ export const RouteWithParams = {
EDIT_COLLECTION: (collectionId: string) => `/collections/${collectionId}/edit`,
EDIT_COLLECTION_FEATURED_ITEMS: (collectionId: string) =>
`/collections/${collectionId}/edit-featured-items`,
FILES_REPLACE: (datasetPersistentId: string, datasetVersion: string, fileId: number) => {
FILES_REPLACE: (
datasetPersistentId: string,
datasetVersion: string,
fileId: number,
referrer?: ReplaceFileReferrer
) => {
const searchParams = new URLSearchParams({
[QueryParamKey.FILE_ID]: fileId.toString(),
[QueryParamKey.PERSISTENT_ID]: datasetPersistentId,
[QueryParamKey.DATASET_VERSION]: datasetVersion
})

if (referrer) {
searchParams.append(QueryParamKey.REFERRER, referrer)
}

return `/files/replace?${searchParams.toString()}`
},
FEATURED_ITEM: (parentCollectionId: string, featuredItemId: string) =>
Expand All @@ -47,5 +58,6 @@ export enum QueryParamKey {
COLLECTION_ID = 'collectionId',
TAB = 'tab',
FILE_ID = 'fileId',
DATASET_VERSION = 'datasetVersion'
DATASET_VERSION = 'datasetVersion',
REFERRER = 'referrer'
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Link } from 'react-router-dom'
import { DropdownButtonItem } from '@iqss/dataverse-design-system'
import { FilePreview } from '../../../../../../files/domain/models/FilePreview'
import { useTranslation } from 'react-i18next'
Expand All @@ -8,6 +9,8 @@ import { useNotImplementedModal } from '../../../../../not-implemented/NotImplem
import { FileRepository } from '@/files/domain/repositories/FileRepository'
import { DatasetRestrictFileButton } from '@/sections/dataset/dataset-files/files-table/file-actions/edit-files-menu/DatasetRestrictFileButton'
import { DatasetDeleteFileButton } from '@/sections/dataset/dataset-files/files-table/file-actions/edit-files-menu/DatasetDeleteFileButton'
import { RouteWithParams } from '@/sections/Route.enum'
import { ReplaceFileReferrer } from '@/sections/replace-file/ReplaceFile'

type EditFilesOptionsProps =
| {
Expand All @@ -29,6 +32,7 @@ type EditFilesOptionsProps =

export interface EditFilesMenuDatasetInfo {
persistentId: string
versionNumber: string
releasedVersionExists: boolean
termsOfAccessForRestrictedFiles?: string
requestAccess: boolean
Expand All @@ -44,6 +48,7 @@ export function EditFilesOptions({
isHeader
}: EditFilesOptionsProps) {
const { t } = useTranslation('files')
const { t: tFile } = useTranslation('file')
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
Expand All @@ -59,6 +64,17 @@ export function EditFilesOptions({
datasetInfo={datasetInfo}
/>

<DropdownButtonItem
as={Link}
to={RouteWithParams.FILES_REPLACE(
datasetInfo.persistentId,
datasetInfo.versionNumber,
file.id,
ReplaceFileReferrer.DATASET
)}>
{tFile('actionButtons.editFileMenu.options.replace')}
</DropdownButtonItem>

<DatasetDeleteFileButton
fileId={file.id}
fileRepository={fileRepository}
Expand Down Expand Up @@ -92,9 +108,6 @@ export function EditFilesOptions({
{t('actions.editFilesMenu.options.restrict')}
</DropdownButtonItem>
)}
<DropdownButtonItem onClick={onClick}>
{t('actions.editFilesMenu.options.replace')}
</DropdownButtonItem>
{settingsEmbargoAllowed && (
<DropdownButtonItem onClick={onClick}>
{t('actions.editFilesMenu.options.embargo')}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export function FileOptionsMenu({ file, fileRepository }: FileOptionsMenuProps)
const datasetInfo: EditFilesMenuDatasetInfo = {
persistentId: dataset.persistentId,
releasedVersionExists: dataset.version.someDatasetVersionHasBeenReleased || false,
versionNumber: dataset.version.number.toSearchParam(),
requestAccess: dataset.termsOfUse?.termsOfAccess?.fileAccessRequest,
termsOfAccessForRestrictedFiles:
dataset.termsOfUse?.termsOfAccess?.termsOfAccessForRestrictedFiles || ''
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { useTranslation } from 'react-i18next'
import { useNavigate } from 'react-router-dom'
import { Link } from 'react-router-dom'
import { DropdownButton, DropdownButtonItem } from '@iqss/dataverse-design-system'
import { FileRepository } from '@/files/domain/repositories/FileRepository'
import { RouteWithParams } from '@/sections/Route.enum'
import { DeleteFileButton } from './delete-file-button/DeleteFileButton'
import { RestrictFileButton } from './restrict-file-button/RestrictFileButton'
import { ReplaceFileReferrer } from '@/sections/replace-file/ReplaceFile'

interface EditFileMenuProps {
fileId: number
Expand All @@ -28,12 +29,6 @@ export const EditFileMenu = ({
isRestricted
}: EditFileMenuProps) => {
const { t } = useTranslation('file')
const navigate = useNavigate()

const handleOnReplaceClick = () =>
navigate(
RouteWithParams.FILES_REPLACE(datasetInfo.persistentId, datasetInfo.versionNumber, fileId)
)

return (
<DropdownButton
Expand All @@ -47,7 +42,14 @@ export const EditFileMenu = ({
fileRepository={fileRepository}
datasetInfo={datasetInfo}
/>
<DropdownButtonItem onClick={handleOnReplaceClick}>
<DropdownButtonItem
as={Link}
to={RouteWithParams.FILES_REPLACE(
datasetInfo.persistentId,
datasetInfo.versionNumber,
fileId,
ReplaceFileReferrer.FILE
)}>
{t('actionButtons.editFileMenu.options.replace')}
</DropdownButtonItem>
<DeleteFileButton fileId={fileId} fileRepository={fileRepository} datasetInfo={datasetInfo} />
Expand Down
11 changes: 10 additions & 1 deletion src/sections/replace-file/ReplaceFile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,21 @@ interface ReplaceFileProps {
fileIdFromParams: number
datasetPidFromParams: string
datasetVersionFromParams: string
referrer?: ReplaceFileReferrer
}

// From where the user is coming from
export enum ReplaceFileReferrer {
DATASET = 'dataset',
FILE = 'file'
}

export const ReplaceFile = ({
fileRepository,
fileIdFromParams,
datasetPidFromParams,
datasetVersionFromParams
datasetVersionFromParams,
referrer
}: ReplaceFileProps) => {
const { t } = useTranslation('replaceFile')
const { t: tFiles } = useTranslation('files')
Expand Down Expand Up @@ -74,6 +82,7 @@ export const ReplaceFile = ({
storageType="S3"
operationType={OperationType.REPLACE_FILE}
originalFile={file}
referrer={referrer}
/>
</div>
</Tabs.Tab>
Expand Down
5 changes: 4 additions & 1 deletion src/sections/replace-file/ReplaceFileFactory.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ReactElement } from 'react'
import { useSearchParams } from 'react-router-dom'
import { FileJSDataverseRepository } from '@/files/infrastructure/FileJSDataverseRepository'
import { ReplaceFile } from './ReplaceFile'
import { ReplaceFile, ReplaceFileReferrer } from './ReplaceFile'
import { QueryParamKey } from '../Route.enum'
import { searchParamVersionToDomainVersion } from '@/router'

Expand Down Expand Up @@ -31,13 +31,16 @@ function ReplaceFileWithParams() {
const datasetVersionNumber = searchParamVersionToDomainVersion(
datasetVersionSearchParam
) as string
const referrer =
(searchParams.get(QueryParamKey.REFERRER) as ReplaceFileReferrer | null) ?? undefined

return (
<ReplaceFile
fileRepository={fileRepository}
fileIdFromParams={fileId}
datasetPidFromParams={datasetId}
datasetVersionFromParams={datasetVersionNumber}
referrer={referrer}
/>
)
}
7 changes: 6 additions & 1 deletion src/sections/shared/file-uploader/FileUploader.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { File as FileModel } from '@/files/domain/models/File'
import { FileRepository } from '@/files/domain/repositories/FileRepository'
import { ReplaceFileReferrer } from '@/sections/replace-file/ReplaceFile'
import { FileUploaderProvider } from './context/FileUploaderContext'
import { useGetFixityAlgorithm } from './useGetFixityAlgorithm'
import { FileUploaderGlobalConfig } from './context/fileUploaderReducer'
Expand All @@ -13,13 +14,15 @@ type FileUploaderProps =
storageType: StorageType
operationType: OperationType.REPLACE_FILE
originalFile: FileModel
referrer?: ReplaceFileReferrer
}
| {
fileRepository: FileRepository
datasetPersistentId: string
storageType: StorageType
operationType: OperationType.ADD_FILES_TO_DATASET
originalFile?: never
referrer?: never
}

export type StorageType = 'S3'
Expand All @@ -37,7 +40,8 @@ export const FileUploader = ({
datasetPersistentId,
storageType,
operationType,
originalFile
originalFile,
referrer
}: FileUploaderProps) => {
const { fixityAlgorithm, isLoadingFixityAlgorithm } = useGetFixityAlgorithm(fileRepository)

Expand All @@ -64,6 +68,7 @@ export const FileUploader = ({
<FileUploaderPanel
fileRepository={fileRepository}
datasetPersistentId={datasetPersistentId}
referrer={referrer}
/>
</FileUploaderProvider>
)
Expand Down
36 changes: 28 additions & 8 deletions src/sections/shared/file-uploader/FileUploaderPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Stack } from '@iqss/dataverse-design-system'
import { FileRepository } from '@/files/domain/repositories/FileRepository'
import { QueryParamKey, Route } from '@/sections/Route.enum'
import { DatasetNonNumericVersionSearchParam } from '@/dataset/domain/models/Dataset'
import { ReplaceFileReferrer } from '@/sections/replace-file/ReplaceFile'
import { useFileUploaderContext } from './context/FileUploaderContext'
import FileUploadInput from './file-upload-input/FileUploadInput'
import { UploadedFilesList } from './uploaded-files-list/UploadedFilesList'
Expand All @@ -15,9 +16,14 @@ import { ConfirmLeaveModal } from './confirm-leave-modal/ConfirmLeaveModal'
interface FileUploaderPanelProps {
fileRepository: FileRepository
datasetPersistentId: string
referrer?: ReplaceFileReferrer
}

const FileUploaderPanel = ({ fileRepository, datasetPersistentId }: FileUploaderPanelProps) => {
const FileUploaderPanel = ({
fileRepository,
datasetPersistentId,
referrer
}: FileUploaderPanelProps) => {
const { t } = useTranslation('shared')
const navigate = useNavigate()

Expand Down Expand Up @@ -62,22 +68,36 @@ const FileUploaderPanel = ({ fileRepository, datasetPersistentId }: FileUploader
}

useDeepCompareEffect(() => {
const datasetPageRedirectUrl = `${Route.DATASETS}?${QueryParamKey.PERSISTENT_ID}=${datasetPersistentId}&${QueryParamKey.VERSION}=${DatasetNonNumericVersionSearchParam.DRAFT}`

// Listens to the replace operation info result and navigates to the new file page if the operation was successful
if (replaceOperationInfo.success && replaceOperationInfo.newFileIdentifier) {
toast.success(t('fileUploader.fileReplacedSuccessfully'))
navigate(
`${Route.FILES}?id=${replaceOperationInfo.newFileIdentifier}&${QueryParamKey.DATASET_VERSION}=${DatasetNonNumericVersionSearchParam.DRAFT}`
)

if (referrer === ReplaceFileReferrer.DATASET) {
navigate(datasetPageRedirectUrl)
}

if (referrer === ReplaceFileReferrer.FILE) {
navigate(
`${Route.FILES}?id=${replaceOperationInfo.newFileIdentifier}&${QueryParamKey.DATASET_VERSION}=${DatasetNonNumericVersionSearchParam.DRAFT}`
)
}
}

// Listens to the add files to dataset operation info result and navigates to the dataset page if the operation was successful
if (addFilesToDatasetOperationInfo.success) {
toast.success(t('fileUploader.filesAddedToDatasetSuccessfully'))
navigate(
`${Route.DATASETS}?${QueryParamKey.PERSISTENT_ID}=${datasetPersistentId}&${QueryParamKey.VERSION}=${DatasetNonNumericVersionSearchParam.DRAFT}`
)
navigate(datasetPageRedirectUrl)
}
}, [replaceOperationInfo, addFilesToDatasetOperationInfo, datasetPersistentId, t, navigate])
}, [
replaceOperationInfo,
addFilesToDatasetOperationInfo,
datasetPersistentId,
t,
navigate,
referrer
])

return (
<Stack gap={4}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,8 +231,9 @@ const FileUploadInput = ({ fileRepository, datasetPersistentId }: FileUploadInpu
<ExclamationTriangle size={24} />
<span>
{t('fileUploader.fileTypeDifferentModal.message', {
originalFileType: MimeTypeDisplay[originalFileType],
replacementFileType: MimeTypeDisplay[replacementFileType]
originalFileType:
MimeTypeDisplay[originalFileType] ?? /* istanbul ignore next */ t('unknown'),
replacementFileType: MimeTypeDisplay[replacementFileType] ?? t('unknown')
})}
</span>
</div>
Expand Down
Loading