Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
d29349d
chore: upgrade solr version
g-saracca Feb 27, 2025
c5e9002
chore: upgrade js-dv pkg version
g-saracca Feb 27, 2025
206c4fa
feat: repositort method + routing
g-saracca Feb 28, 2025
3ae4dd3
fix: object contain to img
g-saracca Feb 28, 2025
1b70718
feat: get dataset from file replace page
g-saracca Feb 28, 2025
783430a
feat: initial work
g-saracca Mar 5, 2025
75d72c5
feat: styling
g-saracca Mar 5, 2025
e2c4d23
feat: add accordion, tab and texts
g-saracca Mar 6, 2025
1569ba3
feat: add prop to place tooltip
g-saracca Mar 6, 2025
d882f4e
feat: update FileDirectory component to use data-testid for testing
g-saracca Mar 6, 2025
0da5ab5
feat: add original file information display in ReplaceFile component
g-saracca Mar 6, 2025
70829c6
feat: add file type difference modal functionality
g-saracca Mar 6, 2025
12167ed
feat: file type different changes
g-saracca Mar 7, 2025
ebe7b0b
chore: install swall deps
g-saracca Mar 7, 2025
7762fd2
feat: different types functionality done
g-saracca Mar 7, 2025
135f6ae
feat: add upload failure message and improve file uploader styles
g-saracca Mar 7, 2025
41b0d8a
refactor: remove todos, referrer param and helper fn
g-saracca Mar 7, 2025
c10bd18
feat: avoid uploading duplicate files and get fullpath
g-saracca Mar 7, 2025
bd52a5e
chore: clearing TODOS
g-saracca Mar 7, 2025
96b8a17
feat: implement file removal functionality in ReplaceFile component
g-saracca Mar 7, 2025
d7205ec
refactor: remove unused ADD_FILES action from file uploader reducer
g-saracca Mar 7, 2025
08c4a33
refactor: move RowSelectionCheckbox to shared folder
g-saracca Mar 10, 2025
bfda897
feat: add UploadedFilesList component to display uploaded files with …
g-saracca Mar 10, 2025
6d2337a
refactor: update FileThumbnail import to named export and remove defa…
g-saracca Mar 10, 2025
d093e01
feat(ds): NEW rows prop
g-saracca Mar 10, 2025
35904e8
feat: enhance file handling with sanitization and improved notifications
g-saracca Mar 10, 2025
dee635a
feat: implement UploadedFilesListHelper for mapping and validation of…
g-saracca Mar 10, 2025
b8c279e
feat: add fixity algorithm handling and loading spinner in file uploader
g-saracca Mar 11, 2025
1c1b1d5
feat: enhance file type confirmation modal with dynamic type display
g-saracca Mar 11, 2025
c1706ed
feat: add checksum algorithm data to file uploader state
g-saracca Mar 11, 2025
3f1dab2
feat: improve UploadedFileRow layout and enhance file info display
g-saracca Mar 11, 2025
456811d
feat: add confirmation modal for unsaved file uploads before leaving …
g-saracca Mar 11, 2025
a986b97
fix: unused async
g-saracca Mar 11, 2025
16aa600
feat: validation for uniqueness
g-saracca Mar 11, 2025
d30f7e1
refactor: update file removal logic
g-saracca Mar 11, 2025
87802c9
refactor: file uploader panel wraps everything
g-saracca Mar 12, 2025
d5561a7
refactor: update replace file method to return new file identifier
g-saracca Mar 12, 2025
71945aa
feat: file replacement working
g-saracca Mar 12, 2025
249efdf
feat: navigate to replaced file
g-saracca Mar 12, 2025
6005c25
feat: add isSaving prop
g-saracca Mar 12, 2025
e221f38
feat: add draft alert component for files from unpublished datasets
g-saracca Mar 12, 2025
9f837e1
feat: update file uploader to use originalFile object instead of orig…
g-saracca Mar 12, 2025
d277584
feat: support original file description during replacement
g-saracca Mar 12, 2025
e480349
feat: dont allow dropping multiple files or dropping another file whe…
g-saracca Mar 12, 2025
5efe147
feat: update file selection handling and add edit dropdown for upload…
g-saracca Mar 12, 2025
a86bce2
chore: add TODOs
g-saracca Mar 13, 2025
b998a7d
refactor: using a context to share state
g-saracca Mar 13, 2025
7e66e6a
chore: update @iqss/dataverse-client-javascript version
g-saracca Mar 13, 2025
8f7a24f
feat: replace file working
g-saracca Mar 13, 2025
32e7453
feat: upload files to dataset working
g-saracca Mar 13, 2025
5c6b8c2
feat: add locales
g-saracca Mar 13, 2025
37c098f
refactor: remove FileUploader repeated
g-saracca Mar 13, 2025
179060b
feat: improve styling and selection
g-saracca Mar 14, 2025
4a952be
feat: calculate checksum with dynamic fixity algorithm
g-saracca Mar 14, 2025
e0c856d
refactor: remove unused isRemovingFiles state and related code
g-saracca Mar 14, 2025
951c92d
feat: cancel if accept leaving, footer fixed, etc
g-saracca Mar 14, 2025
354c9ce
Merge branch 'develop' into feat/614-replace-file
g-saracca Mar 16, 2025
41f0254
feat: consolidate file validation logic into FileUploaderHelper and r…
g-saracca Mar 16, 2025
664beef
feat: adding stories
g-saracca Mar 17, 2025
7206ccf
feat: confirm leave modal story
g-saracca Mar 17, 2025
b1f3b17
feat: add ReplaceFile story to Storybook
g-saracca Mar 17, 2025
d48a4f1
refactor: reuse dto mapper and dont hardcode checksum type
g-saracca Mar 17, 2025
6d0287e
test: use data router instead of memory for component tests
g-saracca Mar 17, 2025
92eef54
test: Upload dataset files cases
g-saracca Mar 17, 2025
c58cc84
test: add replace file and add files cases
g-saracca Mar 17, 2025
7febd55
test: more tests
g-saracca Mar 17, 2025
10a7797
test: more test cases
g-saracca Mar 17, 2025
14580fb
test: add unit tests for FileUploaderHelper functions
g-saracca Mar 17, 2025
e57ed41
feat: meet min color contrast ratio
g-saracca Mar 17, 2025
d195114
clean some things
g-saracca Mar 18, 2025
3b275df
chore: update @iqss/dataverse-client-javascript to version 2.0.0-alph…
g-saracca Mar 21, 2025
6144770
merge with develop
g-saracca Mar 21, 2025
46abfe9
code review tweaks
g-saracca Mar 26, 2025
e637737
merge branch into 614
g-saracca Mar 26, 2025
5494e56
fix: test using removed mother method
g-saracca Mar 26, 2025
f25a4ed
Merge branch 'develop' into feat/614-replace-file
g-saracca Mar 26, 2025
645acc0
fix: use correct interface
g-saracca Mar 26, 2025
c76c097
add line to see if merge conflicts go away
g-saracca Mar 26, 2025
fb41001
Merge branch 'develop' into feat/614-replace-file
g-saracca Mar 26, 2025
8b08f8d
removel log
g-saracca Mar 26, 2025
14282ac
Merge branch 'develop' into feat/614-replace-file
g-saracca Mar 27, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .storybook/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { ThemeProvider } from '@iqss/dataverse-design-system'
import { createBrowserRouter, RouteObject, RouterProvider } from 'react-router-dom'
import { FakerHelper } from '../tests/component/shared/FakerHelper'
import 'react-loading-skeleton/dist/skeleton.css'
import '../src/assets/swal-custom.scss'
import '../src/assets/react-toastify-custom.scss'

const preview: Preview = {
parameters: {
Expand Down
30 changes: 26 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"@dnd-kit/sortable": "8.0.0",
"@dnd-kit/utilities": "3.2.2",
"@faker-js/faker": "7.6.0",
"@iqss/dataverse-client-javascript": "2.0.0-alpha.29",
"@iqss/dataverse-client-javascript": "2.0.0-alpha.31",
"@iqss/dataverse-design-system": "*",
"@istanbuljs/nyc-config-typescript": "1.0.2",
"@tanstack/react-table": "8.9.2",
Expand Down Expand Up @@ -50,6 +50,9 @@
"react-toastify": "11.0.2",
"react-topbar-progress-indicator": "4.1.1",
"sass": "1.58.1",
"sweetalert2": "11.17.2",
"sweetalert2-react-content": "5.1.0",
"turndown": "7.2.0",
"typescript": "5.7.2",
"use-deep-compare": "1.2.1",
"vite-plugin-istanbul": "4.0.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,17 @@ export interface FormTextAreaProps extends Omit<React.HTMLAttributes<FormInputEl
isInvalid?: boolean
value?: string
autoFocus?: boolean
rows?: number
}

export const FormTextArea = React.forwardRef(function FormTextArea(
{ name, disabled, isValid, isInvalid, value, autoFocus, ...props }: FormTextAreaProps,
{ name, disabled, isValid, isInvalid, value, autoFocus, rows = 5, ...props }: FormTextAreaProps,
ref
) {
return (
<FormBS.Control
as="textarea"
rows={5}
rows={rows}
disabled={disabled}
name={name}
isValid={isValid}
Expand Down
6 changes: 6 additions & 0 deletions public/locales/en/file.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@
},
"fileDeletedSuccess": "The file has been deleted.",
"defaultFileDeleteError": "Something went wrong deleting the file. Try again later.",
"alerts": {
"draftVersion": {
"heading": "This draft version needs to be published",
"alertText": "When ready for sharing, please <a>go to the dataset page</a> to publish it so that others can see these changes."
}
},
"restriction": {
"fileRestrictdSuccess": "The file has been restricted.",
"fileUnrestrictedSuccess": "The file has been unrestricted.",
Expand Down
1 change: 1 addition & 0 deletions public/locales/en/files.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"files": "Files",
"filesLoading": "Files loading spinner symbol",
"errorUnkownGetFilesFromDataset": "There was an error getting the files total download size",
"errorUnkownGetFilesCountInfo": "There was an error getting the files count info",
Expand Down
5 changes: 5 additions & 0 deletions public/locales/en/replaceFile.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"pageTitle": "Replace File",
"notAllowedToReplaceFile": "You do not have permissions to replace this file.",
"originalFile": "Original File"
}
66 changes: 66 additions & 0 deletions public/locales/en/shared.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,72 @@
},
"createCollection": "Create Collection"
},
"fileUploader": {
"supportedFiles": "All file types are supported for upload and download in their original format. If you are uploading Excel, CSV, TSV, RData, Stata, or SPSS files, <anchor>see the guides</anchor> for tabular support and limitations.",
"accordionTitle": "Upload with HTTP via your browser",
"selectFileSingle": "Select file to add",
"selectFileMultiple": "Select files to add",
"dragDropSingle": "Drag and drop file here.",
"dragDropMultiple": "Drag and drop files and/or directories here.",
"cancelUpload": "Cancel upload",
"uploadFailed": "There was an error uploading this file.",
"loadingConfiguration": "Loading configuration",
"replaceFileMultipleError": "You can only drop one file to replace.",
"replaceFileAlreadyOneFileError": "You already have a file to replace. Please remove it first.",
"fileReplacedSuccessfully": "The file has been replaced successfully.",
"defaultFileReplaceError": "Something went wrong replacing the file. Try again later.",
"defaultAddUploadedFilesToDatasetError": "Something went wrong adding the uploaded files to the dataset. Try again later.",
"filesAddedToDatasetSuccessfully": "Files added to dataset successfully.",
"fileUploadSkipped": {
"dsStore": "File upload skipped: .DS_Store files are not allowed.",
"alreadyUploaded": "File {{fileName}} was skipped because it has already been uploaded."
},
"fileTypeDifferentModal": {
"title": "File Type Different",
"message": "The original file ({{originalFileType}}) and replacement file ({{replacementFileType}}) are different file types. Would you like to continue?"
},
"confirmLeaveModal": {
"title": "Discard Uploaded Files?",
"message": "Uploaded files haven’t been saved. If you leave now, they’ll be lost.",
"stay": "Stay on this page",
"leave": "Leave without saving"
},
"uploadedFilesList": {
"fields": {
"fileName": {
"label": "File Name",
"required": "File Name is required",
"invalid": {
"maxLength": "File Name must be at most {{maxLength}} characters.",
"characters": "The file name contains invalid characters. The following characters are not allowed: : < > ; # / \" * | ? \\",
"duplicateCombination": "File Name, File Path or combination of File path + File name should be unique. There is already a combination with the same value."
}
},
"filePath": {
"label": "File Path",
"description": "Hierarchical directory structure path used to display file organization and support reproducibility.",
"invalid": {
"maxLength": "File Path must be at most {{maxLength}} characters.",
"characters": "The file path contains invalid characters. Only letters, numbers, spaces, dashes, periods, backslashes, and forward slashes are allowed.",
"duplicateCombination": "File Name, File Path or combination of File path + File name should be unique. There is already a combination with the same value."
}
},
"description": {
"label": "Description",
"invalid": {
"maxLength": "Description must be at most {{maxLength}} characters."
}
}
},
"removeFile": "Remove File",
"editSelectedFiles": "Edit Selected Files",
"removeSelectedFiles": "Remove Selected Files",
"uploadedFile": "File uploaded",
"uploadedFiles": "Files uploaded",
"selectAllFiles": "Select all files",
"deselectAllFiles": "Deselect all files"
}
},
"contact": {
"message": "Message",
"subject": "Subject",
Expand Down
1 change: 1 addition & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { BASE_URL } from './config'
import { ToastContainer } from 'react-toastify'
import 'react-loading-skeleton/dist/skeleton.css'
import './assets/react-toastify-custom.scss'
import './assets/swal-custom.scss'

if (BASE_URL === '') {
throw Error('VITE_DATAVERSE_BACKEND_URL environment variable should be specified.')
Expand Down
52 changes: 52 additions & 0 deletions src/assets/swal-custom.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
@import 'node_modules/@iqss/dataverse-design-system/src/lib/assets/styles/design-tokens/colors.module';
@import 'node_modules/@iqss/dataverse-design-system/src/lib/assets/styles/design-tokens/typography.module';

/*
Here are declared the classes that will overwrite certain SweetAlert2 modal styles.
The classes declared here are defined in the SwalModal component that takes the Swal component from the library and adds some defaults to it.
So we have a SweetAlert2 component with the styles that we want in the whole app.
*/

.swal-popup-custom {
width: clamp(300px, 80%, 700px);
padding-bottom: 0;
}

.swal-title-custom {
padding: 1rem;
color: $dv-text-color;
font-weight: 500;
font-size: 1.5rem;
text-align: left;
border-bottom: solid 1px $dv-border-color;
}

.swal-html-container-custom {
padding: 1rem;
color: $dv-text-color;
font-size: $dv-font-size;
text-align: left;
}

.swal-actions-custom {
display: flex;
gap: 0.5rem;
justify-content: flex-end;
margin: 0;
padding: 12px;
border-top: solid 1px $dv-border-color;
}

.swal-button-custom {
&.confirm {
order: 3;
}

&.cancel {
order: 2;
}

&.deny {
order: 1;
}
}
2 changes: 2 additions & 0 deletions src/files/domain/models/FileUploadState.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { UploadedFileDTO } from '@iqss/dataverse-client-javascript'
import { FileSize, FileSizeUnit } from './FileMetadata'
import { UploadedFileDTOMapper } from '../../infrastructure/mappers/UploadedFileDTOMapper'
import { FixityAlgorithm } from './FixityAlgorithm'

export interface FileUploadState {
progress: number
Expand Down Expand Up @@ -152,6 +153,7 @@ export class FileUploadTools {
uploadedFile.restricted,
uploadedFile.storageId as string,
uploadedFile.checksumValue as string,
FixityAlgorithm.MD5,
uploadedFile.fileType === '' ? 'application/octet-stream' : uploadedFile.fileType // some browsers (e.g., chromium for .java files) fail to detect the mime type for some files and leave the fileType as an empty string, we use the default value 'application/octet-stream' in that case
)
)
Expand Down
6 changes: 6 additions & 0 deletions src/files/domain/models/FixityAlgorithm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export enum FixityAlgorithm {
MD5 = 'MD5',
SHA1 = 'SHA-1',
SHA256 = 'SHA-256',
SHA512 = 'SHA-512'
}
3 changes: 3 additions & 0 deletions src/files/domain/repositories/FileRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { FilePreview } from '../models/FilePreview'
import { FilesWithCount } from '../models/FilesWithCount'
import { FileHolder } from '../models/FileHolder'
import { UploadedFileDTO } from '@iqss/dataverse-client-javascript'
import { FixityAlgorithm } from '../models/FixityAlgorithm'

export interface FileRepository {
getAllByDatasetPersistentId: (
Expand Down Expand Up @@ -44,5 +45,7 @@ export interface FileRepository {
) => Promise<void>
addUploadedFiles: (datasetId: number | string, files: UploadedFileDTO[]) => Promise<void>
delete: (fileId: number | string) => Promise<void>
replace: (fileId: number | string, uploadedFileDTO: UploadedFileDTO) => Promise<number>
getFixityAlgorithm: () => Promise<FixityAlgorithm>
restrict: (fileId: number | string, restrict: boolean) => Promise<void>
}
12 changes: 3 additions & 9 deletions src/files/domain/useCases/addUploadedFiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,7 @@ import { FileRepository } from '../repositories/FileRepository'
export function addUploadedFiles(
fileRepository: FileRepository,
datasetId: number | string,
files: UploadedFileDTO[],
done: () => void
): void {
fileRepository
.addUploadedFiles(datasetId, files)
.then(done)
.catch((error: Error) => {
throw new Error(error.message)
})
files: UploadedFileDTO[]
): Promise<void> {
return fileRepository.addUploadedFiles(datasetId, files)
}
8 changes: 8 additions & 0 deletions src/files/domain/useCases/getFixityAlgorithm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { FileRepository } from '../repositories/FileRepository'
import { FixityAlgorithm } from '../models/FixityAlgorithm'

export async function getFixityAlgorithm(repository: FileRepository): Promise<FixityAlgorithm> {
return repository.getFixityAlgorithm().catch((error: Error) => {
throw error
})
}
10 changes: 10 additions & 0 deletions src/files/domain/useCases/replaceFile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { UploadedFileDTO } from '@iqss/dataverse-client-javascript'
import { FileRepository } from '../repositories/FileRepository'

export function replaceFile(
fileRepository: FileRepository,
fileId: number | string,
newFile: UploadedFileDTO
): Promise<number> {
return fileRepository.replace(fileId, newFile)
}
2 changes: 2 additions & 0 deletions src/files/domain/useCases/uploadFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ export function uploadFile(
storageIdSetter: (storageId: string) => void
): () => void {
const controller = new AbortController()

fileRepository
.uploadFile(datasetId, { file: file }, progress, controller, storageIdSetter)
.then(done)
.catch(failed)

return () => controller.abort()
}
Loading
Loading