Skip to content

Commit

Permalink
Merge pull request #464 from IQSS/feature/417-upload-integration
Browse files Browse the repository at this point in the history
Feature/417 File upload integration
  • Loading branch information
g-saracca authored Sep 4, 2024
2 parents c71e287 + f1ff52d commit 08511d7
Show file tree
Hide file tree
Showing 15 changed files with 384 additions and 188 deletions.
3 changes: 2 additions & 1 deletion cypress.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ export default defineConfig({
supportFile: 'tests/support/e2e.ts',
setupNodeEvents(on) {
on('file:preprocessor', vitePreprocessor(path.resolve(__dirname, './vite.config.ts')))
}
},
defaultCommandTimeout: 10_000 // https://docs.cypress.io/guides/references/configuration#Timeouts
},
component: {
indexHtmlFile: 'tests/support/component-index.html',
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.

6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
},
"dependencies": {
"@faker-js/faker": "7.6.0",
"@iqss/dataverse-client-javascript": "2.0.0-pr169.aa49f06",
"@iqss/dataverse-client-javascript": "2.0.0-pr187.f29c0e6",
"@iqss/dataverse-design-system": "*",
"@istanbuljs/nyc-config-typescript": "1.0.2",
"@tanstack/react-table": "8.9.2",
Expand Down Expand Up @@ -44,7 +44,9 @@
"typescript": "4.9.5",
"use-deep-compare": "1.2.1",
"vite-plugin-istanbul": "4.0.1",
"web-vitals": "2.1.4"
"web-vitals": "2.1.4",
"js-md5": "0.8.3",
"async-mutex": "0.5.0"
},
"scripts": {
"start": "vite --base=/spa",
Expand Down
30 changes: 30 additions & 0 deletions src/files/domain/models/FileUploadState.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { UploadedFileDTO } from '@iqss/dataverse-client-javascript'
import { FileSize, FileSizeUnit } from './FileMetadata'
import { UploadedFileDTOMapper } from '../../infrastructure/mappers/UploadedFileDTOMapper'

export interface FileUploadState {
progress: number
Expand All @@ -17,6 +19,7 @@ export interface FileUploadState {
description?: string
tags: string[]
restricted: boolean
checksumValue?: string
}

export interface FileUploaderState {
Expand Down Expand Up @@ -94,6 +97,18 @@ export class FileUploadTools {
return { state: oldState.state, uploaded: this.toUploaded(oldState.state) }
}

static checksum(
file: File,
checksumValue: string,
oldState: FileUploaderState
): FileUploaderState {
const fileUploadState = oldState.state.get(this.key(file))
if (fileUploadState) {
fileUploadState.checksumValue = checksumValue
}
return { state: oldState.state, uploaded: this.toUploaded(oldState.state) }
}

static failed(file: File, oldState: FileUploaderState): FileUploaderState {
const fileUploadState = oldState.state.get(this.key(file))
if (fileUploadState) {
Expand Down Expand Up @@ -127,6 +142,21 @@ export class FileUploadTools {
return { state: oldState.state, uploaded: this.toUploaded(oldState.state) }
}

static mapToUploadedFilesDTOs(state: FileUploadState[]): UploadedFileDTO[] {
return state.map((uploadedFile) =>
UploadedFileDTOMapper.toUploadedFileDTO(
uploadedFile.fileName,
uploadedFile.description,
uploadedFile.fileDir,
uploadedFile.tags,
uploadedFile.restricted,
uploadedFile.storageId as string,
uploadedFile.checksumValue as string,
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
)
)
}

private static toNewState(
file: File,
oldState: FileUploaderState
Expand Down
9 changes: 2 additions & 7 deletions src/files/domain/repositories/FileRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { FilePaginationInfo } from '../models/FilePaginationInfo'
import { FilePreview } from '../models/FilePreview'
import { FilesWithCount } from '../models/FilesWithCount'
import { FileHolder } from '../models/FileHolder'
import { FileUploadState } from '../models/FileUploadState'
import { UploadedFileDTO } from '@iqss/dataverse-client-javascript'

export interface FileRepository {
getAllByDatasetPersistentId: (
Expand Down Expand Up @@ -42,10 +42,5 @@ export interface FileRepository {
abortController: AbortController,
storageIdSetter: (storageId: string) => void
) => Promise<void>
addUploadedFiles: (datasetId: number | string, files: FileUploadState[]) => Promise<void>
addUploadedFile: (
datasetId: number | string,
file: FileHolder,
storageId: string
) => Promise<void>
addUploadedFiles: (datasetId: number | string, files: UploadedFileDTO[]) => Promise<void>
}
21 changes: 3 additions & 18 deletions src/files/domain/useCases/addUploadedFiles.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,16 @@
import { FileUploadState } from '../models/FileUploadState'
import { UploadedFileDTO } from '@iqss/dataverse-client-javascript'
import { FileRepository } from '../repositories/FileRepository'

export function addUploadedFiles(
fileRepository: FileRepository,
datasetId: number | string,
files: FileUploadState[],
files: UploadedFileDTO[],
done: () => void
): void {
fileRepository
.addUploadedFiles(datasetId, files)
.then(done)
.catch((error: Error) => {
throw new Error(error.message)
})
.finally(done)
}

export function addUploadedFile(
fileRepository: FileRepository,
datasetId: number | string,
file: File,
storageId: string,
done: () => void
): void {
fileRepository
.addUploadedFile(datasetId, { file: file }, storageId)
.catch((error: Error) => {
throw new Error(error.message)
})
.finally(done)
}
13 changes: 4 additions & 9 deletions src/files/infrastructure/FileJSDataverseRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import {
getFileDownloadCount,
getFileUserPermissions,
uploadFile as jsUploadFile,
addUploadedFilesToDataset,
UploadedFileDTO,
ReadError
} from '@iqss/dataverse-client-javascript'
import { FileCriteria } from '../domain/models/FileCriteria'
Expand All @@ -31,7 +33,6 @@ import { FilePermissions } from '../domain/models/FilePermissions'
import { JSFilePermissionsMapper } from './mappers/JSFilePermissionsMapper'
import { FilesWithCount } from '../domain/models/FilesWithCount'
import { FileHolder } from '../domain/models/FileHolder'
import { FileUploadState } from '../domain/models/FileUploadState'

const includeDeaccessioned = true

Expand Down Expand Up @@ -300,13 +301,7 @@ export class FileJSDataverseRepository implements FileRepository {
})
}

addUploadedFiles(_datasetId: number | string, _files: FileUploadState[]): Promise<void> {
// TODO: not yet implemented
return new Promise<void>(() => {})
}

addUploadedFile(datasetId: number | string, file: FileHolder, storageId: string): Promise<void> {
return new Promise<void>(() => {})
// return addUploadedFilesToDataset.execute(datasetId, file.file)
addUploadedFiles(datasetId: number | string, uploadedFiles: UploadedFileDTO[]): Promise<void> {
return addUploadedFilesToDataset.execute(datasetId, uploadedFiles)
}
}
26 changes: 26 additions & 0 deletions src/files/infrastructure/mappers/UploadedFileDTOMapper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { UploadedFileDTO } from '@iqss/dataverse-client-javascript'

export class UploadedFileDTOMapper {
static toUploadedFileDTO(
fileName: string,
description: string | undefined,
fileDir: string,
tags: string[],
restricted: boolean,
storageId: string,
checksumValue: string,
fileType: string
): UploadedFileDTO {
return {
fileName: fileName,
description: description,
directoryLabel: fileDir,
categories: tags,
restrict: restricted,
storageId: storageId,
checksumValue: checksumValue,
checksumType: 'md5',
mimeType: fileType
}
}
}
25 changes: 7 additions & 18 deletions src/sections/upload-dataset-files/FileUploader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { FileUploadTools, FileUploaderState } from '../../files/domain/models/Fi
import styles from './FileUploader.module.scss'

export interface FileUploaderProps {
upload: (files: File[]) => void
upload: (file: File) => void
cancelTitle: string
info: string
selectText: string
Expand All @@ -30,21 +30,14 @@ export function FileUploader({

const addFiles = (selectedFiles: FileList | null) => {
if (selectedFiles && selectedFiles.length > 0) {
setFiles((alreadyAdded) => {
const selectedFilesArray = Array.from(selectedFiles)
const selectedFilesSet = new Set(selectedFilesArray.map((x) => FileUploadTools.key(x)))
const alreadyAddedFiltered = alreadyAdded.filter(
/* istanbul ignore next */
(x) => !selectedFilesSet.has(FileUploadTools.key(x))
)
return [...alreadyAddedFiltered, ...selectedFilesArray]
})
Array.from(selectedFiles).forEach((file) => addFile(file))
}
}

const addFile = (file: File) => {
if (!files.some((x) => FileUploadTools.key(x) === FileUploadTools.key(file))) {
setFiles((oldFiles) => [...oldFiles, file])
upload(file)
}
}

Expand Down Expand Up @@ -106,15 +99,11 @@ export function FileUploader({
}

useEffect(() => {
upload(files)
}, [files, upload])

useEffect(() => {
setFiles((newFiles) =>
newFiles.filter((x) => {
const res = !FileUploadTools.get(x, fileUploaderState).removed
setFiles((currentFiles) =>
currentFiles.filter((file) => {
const res = !FileUploadTools.get(file, fileUploaderState).removed
if (!res) {
cleanFileState(x)
cleanFileState(file)
}
return res
})
Expand Down
Loading

0 comments on commit 08511d7

Please sign in to comment.