Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/446 file card #450

Merged
merged 19 commits into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ $dv-warning-box-color: #fcf8e3;
$dv-info-box-color: #d9edf7;
$dv-info-border-color: #428BCA;

$dv-collection-border-color: #c55b28;
$dv-dataset-border-color: #428BCA;
$dv-file-border-color: #808080;

// Text colors
$dv-text-color: #333;
$dv-subtext-color: #767676;
Expand Down
4 changes: 4 additions & 0 deletions src/files/domain/models/FilePreview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,8 @@ export interface FilePreview {
ingest: FileIngest
metadata: FileMetadata
permissions: FilePermissions
releaseOrCreateDate?: Date
someDatasetVersionHasBeenReleased?: boolean
datasetPersistentId?: string
datasetName?: string
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
@use 'sass:color';
@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";

.container {
margin: 6px 0;
padding: 4px 10px;
border: 1px solid $dv-file-border-color;
}

.header {
display: flex;
justify-content: space-between;
}

.title {
display: flex;gap: 8px;
}

.icon {
margin-top: 2px;
font-size: 1.3em;
line-height: 1.1;

> div >span {
margin-right: 0;
}
}

.thumbnail {
width: 48px;
margin: 8px 12px 6px 0;
font-size: 2.8em;

img {
vertical-align: top;
}
}

.info {
display: flex;
color: $dv-subtext-color;
}

.description {
ekraffmiller marked this conversation as resolved.
Show resolved Hide resolved
ekraffmiller marked this conversation as resolved.
Show resolved Hide resolved
display: flex;
font-size: $dv-font-size-sm;
}

.descriptionText {
display: -webkit-box; -webkit-line-clamp: 3; line-clamp: 3; -webkit-box-orient: vertical;
flex-direction: column;
ekraffmiller marked this conversation as resolved.
Show resolved Hide resolved
width: 100%;
overflow: hidden;
color: black;
}

.date {
color: $dv-subtext-color;

}

.citation-box {
margin-top: 4px;
margin-bottom: .5em;
padding: 4px;
background-color: color.adjust($dv-primary-color, $lightness: 51%) ;
}

.citation-box-deaccessioned {
margin-top: 4px;
margin-bottom: .5em;
padding: 4px;
background-color: color.adjust($dv-danger-box-color, $lightness: 6%);
}
25 changes: 25 additions & 0 deletions src/sections/collection/datasets-list/file-card/FileCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import styles from './FileCard.module.scss'
import { FileCardHeader } from './FileCardHeader'
import { FileCardThumbnail } from './FileCardThumbnail'
import { FileCardInfo } from './FileCardInfo'
import { FilePreview } from '../../../../files/domain/models/FilePreview'
import { Stack } from '@iqss/dataverse-design-system'

interface FileCardProps {
filePreview: FilePreview
persistentId: string
}

export function FileCard({ filePreview, persistentId }: FileCardProps) {
return (
<article className={styles.container}>
<FileCardHeader filePreview={filePreview} />
<div className={styles.info}>
<Stack direction={'horizontal'} gap={3}>
<FileCardThumbnail filePreview={filePreview} persistentId={persistentId} />
<FileCardInfo filePreview={filePreview} persistentId={persistentId} />
</Stack>
</div>
</article>
)
}
39 changes: 39 additions & 0 deletions src/sections/collection/datasets-list/file-card/FileCardHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import styles from './FileCard.module.scss'
import { LinkToPage } from '../../../shared/link-to-page/LinkToPage'
import { Route } from '../../../Route.enum'
import { FilePreview } from '../../../../files/domain/models/FilePreview'
import { DatasetLabels } from '../../../dataset/dataset-labels/DatasetLabels'
import { FileCardIcon } from './FileCardIcon'
import { FileType } from '../../../../files/domain/models/FileMetadata'
import { FileCardHelper } from './FileCardHelper'

interface FileCardHeaderProps {
filePreview: FilePreview
}

export function FileCardHeader({ filePreview }: FileCardHeaderProps) {
const iconFileType = new FileType('text/tab-separated-values', 'Comma Separated Values')
return (
<div className={styles.header}>
<div className={styles.title}>
<LinkToPage
page={Route.FILES}
searchParams={FileCardHelper.getFileSearchParams(
filePreview.id,
filePreview.datasetPublishingStatus
)}>
{filePreview.name}
</LinkToPage>
<DatasetLabels
labels={FileCardHelper.getDatasetLabels(
filePreview.datasetPublishingStatus,
filePreview.someDatasetVersionHasBeenReleased
)}
/>
</div>
<div className={styles.icon}>
<FileCardIcon type={iconFileType} />
</div>
</div>
)
}
48 changes: 48 additions & 0 deletions src/sections/collection/datasets-list/file-card/FileCardHelper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import {
DatasetLabel,
DatasetLabelSemanticMeaning,
DatasetLabelValue,
DatasetNonNumericVersionSearchParam,
DatasetPublishingStatus
} from '../../../../dataset/domain/models/Dataset'
export class FileCardHelper {
static getDatasetSearchParams(
persistentId: string,
publishingStatus: DatasetPublishingStatus
): Record<string, string> {
const params: Record<string, string> = { persistentId: persistentId }
if (publishingStatus === DatasetPublishingStatus.DRAFT) {
params.version = DatasetNonNumericVersionSearchParam.DRAFT
}
return params
}
static getFileSearchParams(
id: number,
publishingStatus: DatasetPublishingStatus
): Record<string, string> {
const params: Record<string, string> = { id: id.toString() }
if (publishingStatus === DatasetPublishingStatus.DRAFT) {
params.datasetVersion = DatasetNonNumericVersionSearchParam.DRAFT
}
return params
}

static getDatasetLabels(
datasetPublishingStatus: DatasetPublishingStatus,
someDatasetVersionHasBeenReleased: boolean | undefined
) {
const labels: DatasetLabel[] = []
if (datasetPublishingStatus === DatasetPublishingStatus.DRAFT) {
labels.push(new DatasetLabel(DatasetLabelSemanticMeaning.DATASET, DatasetLabelValue.DRAFT))
}
if (
someDatasetVersionHasBeenReleased == undefined ||
someDatasetVersionHasBeenReleased == false
) {
labels.push(
new DatasetLabel(DatasetLabelSemanticMeaning.WARNING, DatasetLabelValue.UNPUBLISHED)
)
}
return labels
}
}
14 changes: 14 additions & 0 deletions src/sections/collection/datasets-list/file-card/FileCardIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import styles from './FileCard.module.scss'
import { IconName } from '@iqss/dataverse-design-system'
import { FileType } from '../../../../files/domain/models/FileMetadata'
import { FileTypeToFileIconMap } from '../../../file/file-preview/FileTypeToFileIconMap'

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

return (
<span className={`${styles.icon} ${icon} `} role="img" aria-label={icon}>
<title>{icon}</title>
</span>
)
}
42 changes: 42 additions & 0 deletions src/sections/collection/datasets-list/file-card/FileCardInfo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import styles from './FileCard.module.scss'
import { DateHelper } from '../../../../shared/helpers/DateHelper'
import { FilePreview } from '../../../../files/domain/models/FilePreview'
import { Stack } from '@iqss/dataverse-design-system'
import { LinkToPage } from '../../../shared/link-to-page/LinkToPage'
import { Route } from '../../../Route.enum'
import { FileChecksum } from '../../../dataset/dataset-files/files-table/file-info/file-info-cell/file-info-data/FileChecksum'
import { FileTabularData } from '../../../dataset/dataset-files/files-table/file-info/file-info-cell/file-info-data/FileTabularData'
import { FileCardHelper } from './FileCardHelper'

interface FileCardInfoProps {
filePreview: FilePreview
persistentId: string
}

export function FileCardInfo({ filePreview, persistentId }: FileCardInfoProps) {
return (
<div className={styles.description}>
<Stack gap={1}>
<span className={styles.date}>
{DateHelper.toDisplayFormat(filePreview.metadata.depositDate)} -{' '}
<LinkToPage
page={Route.DATASETS}
searchParams={FileCardHelper.getDatasetSearchParams(
persistentId,
filePreview.datasetPublishingStatus
)}>
{filePreview.datasetName}
</LinkToPage>
</span>
<span className={styles.info}>
<Stack gap={1} direction="horizontal">
{filePreview.metadata.type.toDisplayFormat()} - {filePreview.metadata.size.toString()}
<FileTabularData tabularData={filePreview.metadata.tabularData} />
<FileChecksum checksum={filePreview.metadata.checksum} />
</Stack>
</span>
<p className={styles.descriptionText}>{filePreview.metadata.description}</p>
</Stack>
</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import styles from './FileCard.module.scss'
import { LinkToPage } from '../../../shared/link-to-page/LinkToPage'
import { Route } from '../../../Route.enum'
import { FileThumbnail } from '../../../dataset/dataset-files/files-table/file-info/file-info-cell/file-info-data/file-thumbnail/FileThumbnail'
import { FilePreview } from '../../../../files/domain/models/FilePreview'
import { FileCardHelper } from './FileCardHelper'

interface FileCardThumbnailProps {
persistentId: string
filePreview: FilePreview
thumbnail?: string
}

export function FileCardThumbnail({ persistentId, filePreview }: FileCardThumbnailProps) {

Check warning on line 14 in src/sections/collection/datasets-list/file-card/FileCardThumbnail.tsx

View workflow job for this annotation

GitHub Actions / lint

'persistentId' is defined but never used. Allowed unused args must match /^_/u
return (
ekraffmiller marked this conversation as resolved.
Show resolved Hide resolved
<div className={styles.thumbnail}>
<LinkToPage
page={Route.FILES}
searchParams={FileCardHelper.getFileSearchParams(
filePreview.id,
filePreview.datasetPublishingStatus
)}>
<FileThumbnail file={filePreview} />
</LinkToPage>
</div>
)
}
48 changes: 48 additions & 0 deletions src/stories/collection/datasets-list/FileCard.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { Meta, StoryObj } from '@storybook/react'
import { WithI18next } from '../../WithI18next'
import { FileCard } from '../../../sections/collection/datasets-list/file-card/FileCard'
import { FilePreviewMother } from '../../../../tests/component/files/domain/models/FilePreviewMother'
import { FileMetadataMother } from '../../../../tests/component/files/domain/models/FileMetadataMother'
import { FakerHelper } from '../../../../tests/component/shared/FakerHelper'

const meta: Meta<typeof FileCard> = {
title: 'Sections/Collection Page/FileCard',
component: FileCard,
decorators: [WithI18next]
}

export default meta
type Story = StoryObj<typeof FileCard>

export const Default: Story = {
render: () => <FileCard persistentId={'testid'} filePreview={FilePreviewMother.createDefault()} />
}
export const TabDelimited: Story = {
render: () => <FileCard persistentId={'testid'} filePreview={FilePreviewMother.createTabular()} />
}
export const WithLongDescription: Story = {
render: () => {
const filePreview = FilePreviewMother.createDefault({
metadata: FileMetadataMother.createDefault({
description: FakerHelper.paragraph(20)
})
})
return <FileCard persistentId={'testid'} filePreview={filePreview} />
}
}
export const WithChecksum: Story = {
render: () => (
<FileCard persistentId={'testid'} filePreview={FilePreviewMother.createWithChecksum()} />
)
}
export const WithDraft: Story = {
render: () => (
<FileCard persistentId={'testid'} filePreview={FilePreviewMother.createWithDraft()} />
)
}

export const ReleasedWithDraft: Story = {
render: () => (
<FileCard persistentId={'testid'} filePreview={FilePreviewMother.createReleasedWithDraft()} />
)
}
8 changes: 6 additions & 2 deletions tests/component/files/domain/models/FileMetadataMother.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ export class FileMetadataMother {

static createTabular(props?: Partial<FileMetadata>): FileMetadata {
return this.createDefault({
description: FakerHelper.paragraph(),
type: FileTypeMother.createTabular(),
tabularData: FileTabularDataMother.create(),
...props
Expand All @@ -246,6 +247,7 @@ export class FileMetadataMother {

static createNonTabular(props?: Partial<FileMetadata>): FileMetadata {
return this.createDefault({
description: FakerHelper.paragraph(),
type: FileTypeMother.createText(),
tabularData: undefined,
...props
Expand Down Expand Up @@ -273,13 +275,15 @@ export class FileMetadataMother {

static createWithChecksum(): FileMetadata {
return this.createDefault({
checksum: FileChecksumMother.create()
checksum: FileChecksumMother.create(),
description: FakerHelper.paragraph()
})
}

static createWithNoChecksum(): FileMetadata {
return this.createDefault({
checksum: undefined
checksum: undefined,
description: FakerHelper.paragraph()
})
}

Expand Down
Loading
Loading