Skip to content

Commit

Permalink
Merge pull request #193 from IQSS/feature/160-display-actual-file-thu…
Browse files Browse the repository at this point in the history
…mbnails

160 - Display actual file thumbnails
  • Loading branch information
GPortas authored Nov 2, 2023
2 parents 52db0cd + f4bb101 commit c5d6cd8
Show file tree
Hide file tree
Showing 13 changed files with 646 additions and 209 deletions.
485 changes: 320 additions & 165 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -164,5 +164,8 @@
"workerDirectory": "public"
},
"readme": "ERROR: No README data found!",
"_id": "dataverse-frontend@0.1.0"
"_id": "dataverse-frontend@0.1.0",
"overrides": {
"@parcel/watcher": "2.1.0"
}
}
18 changes: 9 additions & 9 deletions packages/design-system/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,25 +32,25 @@
},
"dependencies": {
"@types/react": "18.0.27",
"typescript": "4.9.5",
"vite-plugin-istanbul": "4.0.1",
"bootstrap": "5.2.3",
"react-bootstrap": "2.7.2",
"react-bootstrap-icons": "1.10.3",
"sass": "1.58.1",
"vite-plugin-istanbul": "4.0.1"
"sass": "1.58.1"
},
"devDependencies": {
"@vitejs/plugin-react": "3.1.0",
"@testing-library/cypress": "9.0.0",
"@storybook/react": "7.0.2",
"@storybook/test-runner": "0.10.0",
"@testing-library/cypress": "9.0.0",
"@vitejs/plugin-react": "3.1.0",
"axe-playwright": "1.2.3",
"chromatic": "6.17.4",
"cypress": "12.5.1",
"react": "18.2.0",
"typescript": "^5.2.2",
"vite": "4.1.5",
"vite-plugin-dts": "2.3.0",
"vite-plugin-libcss": "1.0.6"
"vite-plugin-libcss": "1.0.6",
"react": "18.2.0",
"axe-playwright": "1.2.3",
"chromatic": "6.17.4"
},
"files": [
"dist",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export function Tooltip({ placement, overlay, children, maxWidth = 200 }: Overla
<OverlayTriggerBS
key={placement}
placement={placement}
overlay={<TooltipBS style={{ maxWidth: maxWidth }}>{overlay}</TooltipBS>}>
overlay={<TooltipBS style={{ maxWidth: maxWidth, position: 'fixed' }}>{overlay}</TooltipBS>}>
<div style={{ display: 'inline-block' }}>{children}</div>
</OverlayTriggerBS>
)
Expand Down
2 changes: 1 addition & 1 deletion src/files/domain/models/File.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ export class File {
public readonly isDeleted: boolean,
public readonly ingest: FileIngest,
readonly checksum?: FileChecksum,
readonly thumbnail?: string,
public thumbnail?: string,
readonly directory?: string,
readonly embargo?: FileEmbargo,
readonly tabularData?: FileTabularData,
Expand Down
31 changes: 31 additions & 0 deletions src/files/infrastructure/FileJSDataverseRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ import { DatasetVersion } from '../../dataset/domain/models/Dataset'
const includeDeaccessioned = true

export class FileJSDataverseRepository implements FileRepository {
static readonly DATAVERSE_BACKEND_URL =
(import.meta.env.VITE_DATAVERSE_BACKEND_URL as string) ?? ''

getAllByDatasetPersistentId(
datasetPersistentId: string,
datasetVersion: DatasetVersion,
Expand All @@ -39,6 +42,7 @@ export class FileJSDataverseRepository implements FileRepository {
)
.then((jsFiles) => jsFiles.map((jsFile) => JSFileMapper.toFile(jsFile, datasetVersion)))
.then((files) => FileJSDataverseRepository.getAllWithDownloadCount(files))
.then((files) => FileJSDataverseRepository.getAllWithThumbnail(files))
.catch((error: ReadError) => {
throw new Error(error.message)
})
Expand Down Expand Up @@ -67,6 +71,33 @@ export class FileJSDataverseRepository implements FileRepository {
return Promise.resolve(0)
}

private static getAllWithThumbnail(files: File[]): Promise<File[]> {
return Promise.all(
files.map((file) =>
FileJSDataverseRepository.getThumbnailById(file.id).then((thumbnail) => {
file.thumbnail = thumbnail
return file
})
)
)
}

private static getThumbnailById(id: number): Promise<string | undefined> {
return fetch(`${this.DATAVERSE_BACKEND_URL}/api/access/datafile/${id}?imageThumb=400`)
.then((response) => {
if (!response.ok) {
throw new Error('Network response was not ok')
}
return response.blob()
})
.then((blob) => {
return URL.createObjectURL(blob)
})
.catch(() => {
return undefined
})
}

getFilesCountInfoByDatasetPersistentId(
datasetPersistentId: string,
datasetVersion: DatasetVersion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ interface FileThumbnailProps {

export function FileThumbnail({ file }: FileThumbnailProps) {
const { sessionUserHasFileDownloadPermission } = useFileDownloadPermission(file)
const showPreviewImage = file.thumbnail && sessionUserHasFileDownloadPermission

return (
<div
className={`${
showPreviewImage ? styles['container-preview-image'] : styles['container-icon']
file.thumbnail && sessionUserHasFileDownloadPermission
? styles['container-preview-image']
: styles['container-icon']
}`}>
{showPreviewImage ? (
{file.thumbnail && sessionUserHasFileDownloadPermission ? (
<FileThumbnailPreviewImage thumbnail={file.thumbnail} name={file.name} />
) : (
<FileThumbnailIcon type={file.type} />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,10 @@
import styles from './FileThumbnail.module.scss'
import { IconName } from '@iqss/dataverse-design-system'
import { FileType } from '../../../../../../../../files/domain/models/File'

const TYPE_TO_ICON: Record<string, IconName> = {
archive: IconName.PACKAGE,
video: IconName.VIDEO,
audio: IconName.AUDIO,
code: IconName.CODE,
data: IconName.TABULAR,
network: IconName.NETWORK,
astro: IconName.ASTRO,
image: IconName.IMAGE,
document: IconName.DOCUMENT,
geospatial: IconName.GEODATA,
tabular: IconName.TABULAR,
text: IconName.DOCUMENT,
unknown: IconName.FILE,
default: IconName.FILE,
other: IconName.OTHER
}
import { FileTypeToFileIconMap } from './FileTypeToFileIconMap'
import { IconName } from '@iqss/dataverse-design-system'

export function FileThumbnailIcon({ type }: { type: FileType }) {
const icon = TYPE_TO_ICON[type.value] || TYPE_TO_ICON.default
const icon = FileTypeToFileIconMap[type.value] || IconName.OTHER

return (
<span className={`${styles.icon} ${icon} ${styles.container}`} role="img" aria-label={icon}>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
import { IconName } from '@iqss/dataverse-design-system'

export const FileTypeToFileIconMap: Record<string, IconName> = {
'application/pdf': IconName.DOCUMENT,
'image/pdf': IconName.DOCUMENT,
'text/pdf': IconName.DOCUMENT,
'application/x-pdf': IconName.DOCUMENT,
'application/cnt': IconName.DOCUMENT,
'application/msword': IconName.DOCUMENT,
'application/vnd.ms-excel': IconName.DOCUMENT,
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': IconName.DOCUMENT,
'application/vnd.ms-powerpoint': IconName.DOCUMENT,
'application/vnd.openxmlformats-officedocument.presentationml.presentation': IconName.DOCUMENT,
'application/vnd.openxmlformats-officedocument.wordprocessingml.document': IconName.DOCUMENT,
'application/vnd.oasis.opendocument.spreadsheet': IconName.DOCUMENT,
'application/vnd.ms-excel.sheet.macroenabled.12': IconName.DOCUMENT,
'text/plain': IconName.DOCUMENT,
'text/x-log': IconName.DOCUMENT,
'text/html': IconName.DOCUMENT,
'application/x-tex': IconName.DOCUMENT,
'text/x-tex': IconName.DOCUMENT,
'text/markdown': IconName.DOCUMENT,
'text/x-markdown': IconName.DOCUMENT,
'text/x-r-markdown': IconName.DOCUMENT,
'text/x-rst': IconName.DOCUMENT,
'application/rtf': IconName.DOCUMENT,
'text/rtf': IconName.DOCUMENT,
'text/richtext': IconName.DOCUMENT,
'text/turtle': IconName.DOCUMENT,
'application/xml': IconName.DOCUMENT,
'text/xml': IconName.DOCUMENT,
'text/x-c': IconName.CODE,
'text/x-c++src': IconName.CODE,
'text/css': IconName.CODE,
'text/x-objcsrc': IconName.CODE,
'application/java-vm': IconName.CODE,
'text/x-java-source': IconName.CODE,
'text/javascript': IconName.CODE,
'application/javascript': IconName.CODE,
'application/x-javascript': IconName.CODE,
'text/x-perl-script': IconName.CODE,
'text/x-matlab': IconName.CODE,
'text/x-mathematica': IconName.CODE,
'text/php': IconName.CODE,
'text/x-fortran': IconName.CODE,
'text/x-pascal': IconName.CODE,
'text/x-python': IconName.CODE,
'text/x-python-script': IconName.CODE,
'text/x-r-source': IconName.CODE,
'text/x-sh': IconName.CODE,
'application/x-sh': IconName.CODE,
'application/x-shellscript': IconName.CODE,
'application/x-sql': IconName.CODE,
'text/x-sql': IconName.CODE,
'application/x-swc': IconName.CODE,
'application/x-msdownload': IconName.CODE,
'application/x-ipynb+json': IconName.CODE,
'application/x-stata-do': IconName.CODE,
'text/x-stata-syntax': IconName.CODE,
'application/x-stata-syntax': IconName.CODE,
'text/x-spss-syntax': IconName.CODE,
'application/x-spss-syntax': IconName.CODE,
'text/x-sas-syntax': IconName.CODE,
'application/x-sas-syntax': IconName.CODE,
'type/x-r-syntax': IconName.CODE,
'application/postscript': IconName.CODE,
'application/vnd.wolfram.mathematica.package': IconName.CODE,
'application/vnd.wolfram.mathematica': IconName.CODE,
'text/x-workflow-description-language': IconName.CODE,
'text/x-computational-workflow-language': IconName.CODE,
'text/x-nextflow': IconName.CODE,
'text/x-r-notebook': IconName.CODE,
'text/x-ruby-script': IconName.CODE,
'text/x-dagman': IconName.CODE,
'text/x-makefile': IconName.CODE,
'text/x-snakemake': IconName.CODE,
'application/x-docker-file': IconName.CODE,
'application/x-vagrant-file': IconName.CODE,
'text/tab-separated-values': IconName.TABULAR,
'text/tsv': IconName.TABULAR,
'text/comma-separated-values': IconName.TABULAR,
'text/x-comma-separated-values': IconName.TABULAR,
'text/csv': IconName.TABULAR,
'text/x-vcard': IconName.TABULAR,
'text/x-fixed-field': IconName.TABULAR,
'application/x-rlang-transport': IconName.TABULAR,
'application/x-R-2': IconName.TABULAR,
'application/x-stata': IconName.TABULAR,
'application/x-stata-6': IconName.TABULAR,
'application/x-stata-13': IconName.TABULAR,
'application/x-stata-14': IconName.TABULAR,
'application/x-stata-15': IconName.TABULAR,
'application/x-stata-ado': IconName.TABULAR,
'application/x-stata-dta': IconName.TABULAR,
'application/x-stata-smcl': IconName.TABULAR,
'application/x-spss-por': IconName.TABULAR,
'application/x-spss-portable': IconName.TABULAR,
'application/x-spss-sav': IconName.TABULAR,
'application/x-spss-sps': IconName.TABULAR,
'application/x-sas': IconName.TABULAR,
'application/x-sas-transport': IconName.TABULAR,
'application/x-sas-system': IconName.TABULAR,
'application/x-sas-data': IconName.TABULAR,
'application/x-sas-catalog': IconName.TABULAR,
'application/x-sas-log': IconName.TABULAR,
'application/x-sas-output': IconName.TABULAR,
'application/x-r-data': IconName.TABULAR,
'application/softgrid-do': IconName.TABULAR,
'application/x-dvn-csvspss-zip': IconName.TABULAR,
'application/x-dvn-tabddi-zip': IconName.TABULAR,
'application/x-emf': IconName.TABULAR,
'application/x-h5': IconName.TABULAR,
'application/x-hdf': IconName.TABULAR,
'application/x-hdf5': IconName.TABULAR,
'application/geo+json': IconName.TABULAR,
'application/json': IconName.TABULAR,
'application/mathematica': IconName.TABULAR,
'application/matlab-mat': IconName.TABULAR,
'application/x-matlab-data': IconName.TABULAR,
'application/x-matlab-figure': IconName.TABULAR,
'application/x-matlab-workspace': IconName.TABULAR,
'application/x-xfig': IconName.TABULAR,
'application/x-msaccess': IconName.TABULAR,
'application/netcdf': IconName.TABULAR,
'application/x-netcdf': IconName.TABULAR,
'application/vnd.lotus-notes': IconName.TABULAR,
'application/x-nsdstat': IconName.TABULAR,
'application/vnd.flographit': IconName.TABULAR,
'application/vnd.realvnc.bed': IconName.TABULAR,
'application/vnd.ms-pki.stl': IconName.TABULAR,
'application/vnd.isac.fcs': IconName.TABULAR,
'application/java-serialized-object': IconName.TABULAR,
'chemical/x-xyz': IconName.TABULAR,
'image/fits': IconName.FILE,
'application/fits': IconName.FILE,
'application/dbf': IconName.FILE,
'application/dbase': IconName.FILE,
'application/prj': IconName.FILE,
'application/sbn': IconName.FILE,
'application/sbx': IconName.FILE,
'application/shp': IconName.FILE,
'application/shx': IconName.FILE,
'application/x-esri-shape': IconName.FILE,
'application/vnd.google-earth.kml+xml': IconName.FILE,
'application/zipped-shapefile': IconName.FILE,
'application/zip': IconName.PACKAGE,
'application/x-zip-compressed': IconName.PACKAGE,
'application/vnd.antix.game-component': IconName.PACKAGE,
'application/x-bzip': IconName.PACKAGE,
'application/x-bzip2': IconName.PACKAGE,
'application/vnd.google-earth.kmz': IconName.PACKAGE,
'application/gzip': IconName.PACKAGE,
'application/x-gzip': IconName.PACKAGE,
'application/x-gzip-compressed': IconName.PACKAGE,
'application/rar': IconName.PACKAGE,
'application/x-rar': IconName.PACKAGE,
'application/x-rar-compressed': IconName.PACKAGE,
'application/tar': IconName.PACKAGE,
'application/x-tar': IconName.PACKAGE,
'application/x-compressed': IconName.PACKAGE,
'application/x-compressed-tar': IconName.PACKAGE,
'application/x-7z-compressed': IconName.PACKAGE,
'application/x-xz': IconName.PACKAGE,
'application/warc': IconName.PACKAGE,
'application/x-iso9660-image': IconName.PACKAGE,
'application/vnd.eln+zip': IconName.PACKAGE,
'image/gif': IconName.IMAGE,
'image/jpeg': IconName.IMAGE,
'image/jp2': IconName.IMAGE,
'image/x-portable-bitmap': IconName.IMAGE,
'image/x-portable-graymap': IconName.IMAGE,
'image/png': IconName.IMAGE,
'image/x-portable-anymap': IconName.IMAGE,
'image/x-portable-pixmap': IconName.IMAGE,
'application/x-msmetafile': IconName.IMAGE,
'application/dicom': IconName.IMAGE,
'image/dicom-rle': IconName.IMAGE,
'image/nii': IconName.IMAGE,
'image/cmu-raster': IconName.IMAGE,
'image/x-rgb': IconName.IMAGE,
'image/svg+xml': IconName.IMAGE,
'image/tiff': IconName.IMAGE,
'image/bmp': IconName.IMAGE,
'image/x-xbitmap': IconName.IMAGE,
'image/RAW': IconName.IMAGE,
'image/raw': IconName.IMAGE,
'application/x-tgif': IconName.IMAGE,
'image/x-xpixmap': IconName.IMAGE,
'image/x-xwindowdump': IconName.IMAGE,
'application/photoshop': IconName.IMAGE,
'image/vnd.adobe.photoshop': IconName.IMAGE,
'application/x-photoshop': IconName.IMAGE,
'audio/x-aiff': IconName.AUDIO,
'audio/mp3': IconName.AUDIO,
'audio/mpeg': IconName.AUDIO,
'audio/mp4': IconName.AUDIO,
'audio/x-m4a': IconName.AUDIO,
'audio/ogg': IconName.AUDIO,
'audio/wav': IconName.AUDIO,
'audio/x-wav': IconName.AUDIO,
'audio/x-wave': IconName.AUDIO,
'video/avi': IconName.VIDEO,
'video/x-msvideo': IconName.VIDEO,
'video/mpeg': IconName.VIDEO,
'video/mp4': IconName.VIDEO,
'video/x-m4v': IconName.VIDEO,
'video/ogg': IconName.VIDEO,
'video/quicktime': IconName.VIDEO,
'video/webm': IconName.VIDEO,
'text/xml-graphml': IconName.NETWORK,
'application/octet-stream': IconName.FILE,
'application/vnd.dataverse.file-package': IconName.TABULAR,
default: IconName.FILE
}
Loading

0 comments on commit c5d6cd8

Please sign in to comment.