Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
1,094 changes: 1,015 additions & 79 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"react-bootstrap": "^2.7.2",
"react-bootstrap-icons": "^1.10.3",
"react-i18next": "^12.1.5",
"react-markdown": "^8.0.7",
"react-router-dom": "^6.8.1",
"react-topbar-progress-indicator": "^4.1.1",
"sass": "^1.58.1",
Expand Down
13 changes: 13 additions & 0 deletions src/dataset/domain/models/Dataset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,21 @@ export interface DatasetLabel {
value: string
}

export interface DatasetField {
title: string
description: string
value: string
}
export interface License {
name: string
shortDescription: string
uri: string
iconUrl?: string
}
export interface Dataset {
id: string
title: string
labels: DatasetLabel[]
summaryFields: DatasetField[]
license: License
}
7 changes: 6 additions & 1 deletion src/sections/dataset/Dataset.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { useLoading } from '../loading/LoadingContext'
import { DatasetSkeleton } from './DatasetSkeleton'
import { PageNotFound } from '../page-not-found/PageNotFound'
import { useTranslation } from 'react-i18next'
import { DatasetSummary } from './dataset-summary/DatasetSummary'

interface DatasetProps {
datasetRepository: DatasetRepository
Expand Down Expand Up @@ -37,7 +38,11 @@ export function Dataset({ datasetRepository, id }: DatasetProps) {
<Col sm={9}>Citation Block</Col>
</Row>
<Row>
<Col sm={9}>Summary Block</Col>
<Col sm={9}>
<DatasetSummary
summaryFields={dataset.summaryFields}
license={dataset.license}></DatasetSummary>
</Col>
</Row>
<Tabs defaultActiveKey="files">
<Tabs.Tab eventKey="files" title={t('filesTabTitle')}>
Expand Down
17 changes: 17 additions & 0 deletions src/sections/dataset/dataset-summary/DatasetSummary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { DatasetField } from '../../../../src/dataset/domain/models/Dataset'
import { SummaryFields } from './SummaryFields'
import { License as LicenseModel } from './../../../../src/dataset/domain/models/Dataset'
import { License } from './License'
interface DatasetSummaryProps {
summaryFields: DatasetField[]
license: LicenseModel
}

export function DatasetSummary({ summaryFields, license }: DatasetSummaryProps) {
return (
<article>
<SummaryFields summaryFields={summaryFields}></SummaryFields>
<License license={license}></License>
</article>
)
}
25 changes: 25 additions & 0 deletions src/sections/dataset/dataset-summary/License.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Row, Col } from 'dataverse-design-system'
import { License as LicenseModel } from '../../../dataset/domain/models/Dataset'
interface LicenseProps {
license: LicenseModel
}

export function License({ license }: LicenseProps) {
return (
<article>
<Row>
<Col sm={3}>
<b>License/Data Use Agreement</b>
</Col>
<Col>
{' '}
<img
alt={license.name + ' license icon'}
src={license.iconUrl}
title={license.shortDescription}></img>{' '}
<a href={license.uri}>{license.name}</a>
</Col>
</Row>
</article>
)
}
24 changes: 24 additions & 0 deletions src/sections/dataset/dataset-summary/SummaryFields.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Row, Col, Tooltip } from 'dataverse-design-system'
import { MarkdownComponent } from '../markdown/MarkdownComponent'
import { DatasetField } from '../../../dataset/domain/models/Dataset'
interface SummaryFieldsProps {
summaryFields: DatasetField[]
}

export function SummaryFields({ summaryFields }: SummaryFieldsProps) {
return (
<article>
{summaryFields.map((field, index) => (
<Row key={index}>
<Col sm={3}>
<b>{field.title}</b> <Tooltip placement="right" message={field.description}></Tooltip>
</Col>
<Col>
{' '}
<MarkdownComponent markdown={field.value} />
</Col>
</Row>
))}
</article>
)
}
13 changes: 13 additions & 0 deletions src/sections/dataset/markdown/MarkdownComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import ReactMarkdown from 'react-markdown'
import { useRef } from 'react'
interface Props {
markdown: string
}
export function MarkdownComponent({ markdown }: Props) {
const containerRef = useRef<HTMLDivElement>(null)
return (
<div ref={containerRef}>
<ReactMarkdown>{markdown}</ReactMarkdown>
</div>
)
}
36 changes: 36 additions & 0 deletions src/stories/dataset/Dataset.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Dataset as DatasetModel } from '../../dataset/domain/models/Dataset'
import { DatasetRepository } from '../../dataset/domain/repositories/DatasetRepository'
import { LabelSemanticMeaning } from '../../dataset/domain/models/LabelSemanticMeaning.enum'
import { WithLayoutLoading } from '../WithLayoutLoading'
import { faker } from '@faker-js/faker'

const meta: Meta<typeof Dataset> = {
title: 'Pages/Dataset',
Expand All @@ -26,6 +27,41 @@ class DatasetMockRepository implements DatasetRepository {
labels: [
{ value: 'Version 1.0', semanticMeaning: LabelSemanticMeaning.FILE },
{ value: 'Draft', semanticMeaning: LabelSemanticMeaning.DATASET }
],
version: '1.0',
license: {
name: 'CC0 1.0',
shortDescription: 'CC0 1.0 Universal Public Domain Dedication',
uri: 'https://creativecommons.org/publicdomain/zero/1.0/',
iconUrl: 'https://licensebuttons.net/p/zero/1.0/88x31.png'
},
summaryFields: [
{
title: 'Description',
description: 'this is the description field',
value: faker.lorem.paragraph(3)
},
{
title: 'Keyword',
description: 'this is the keyword field',
value: 'Malaria, Tuberculosis, Drug Resistant'
},
{
title: 'Subject',
description: 'this is the subject field',
value: 'Medicine, Health and Life Sciences, Social Sciences'
},

{
title: 'Related Publication',
description: 'this is the keyword field',
value: faker.lorem.words(3)
},
{
title: 'Notes',
description: 'this is the notes field',
value: faker.lorem.paragraph(3)
}
]
})
}, 1000)
Expand Down
55 changes: 55 additions & 0 deletions src/stories/dataset/DatasetSummary.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import type { Meta, StoryObj } from '@storybook/react'
import { WithI18next } from '../WithI18next'

import { DatasetSummary } from '../../sections/dataset/dataset-summary/DatasetSummary'
import { faker } from '@faker-js/faker'
import { DatasetField, License } from '../../dataset/domain/models/Dataset'

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

const licenseMock: License = {
name: 'CC0 1.0',
shortDescription: 'CC0 1.0 Universal Public Domain Dedication',
uri: 'https://creativecommons.org/publicdomain/zero/1.0/',
iconUrl: 'https://licensebuttons.net/p/zero/1.0/88x31.png'
}
const summaryFieldsMock: DatasetField[] = [
{
title: 'Description',
description: 'this is the description field',
value:
'This is the description field. Here is [a link](https://dataverse.org). ' +
'This text is *italic* and this is **bold**. Here is an image ![Alt text](https://picsum.photos/id/10/20/20) '
},
{
title: 'Keyword',
description: 'this is the keyword field',
value: 'Malaria, Tuberculosis, Drug Resistant'
},
{
title: 'Subject',
description: 'this is the subject field',
value: 'Medicine, Health and Life Sciences, Social Sciences'
},
{
title: 'Related Publication',
description: 'this is the keyword field',
value: 'CNN Journal [CNN.com](https://cnn.com)'
},
{
title: 'Notes',
description: 'this is the notes field',
value: faker.lorem.paragraph(3)
}
]

export default meta
type Story = StoryObj<typeof DatasetSummary>

export const Default: Story = {
render: () => <DatasetSummary summaryFields={summaryFieldsMock} license={licenseMock} />
}
33 changes: 33 additions & 0 deletions tests/component/dataset/domain/models/DatasetMother.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,39 @@ export class DatasetMother {
semanticMeaning: faker.helpers.arrayElement(Object.values(LabelSemanticMeaning))
}
],
summaryFields: [
{
title: faker.lorem.word(),
description: faker.lorem.sentence(),
value: faker.lorem.sentence()
},
{
title: faker.lorem.word(),
description: faker.lorem.sentence(),
value: faker.lorem.sentence()
},
{
title: faker.lorem.word(),
description: faker.lorem.sentence(),
value: faker.lorem.sentence()
},
{
title: faker.lorem.word(),
description: faker.lorem.sentence(),
value: faker.lorem.sentence()
},
{
title: faker.lorem.word(),
description: faker.lorem.sentence(),
value: faker.lorem.sentence()
}
],
license: {
name: faker.lorem.sentence(),
shortDescription: faker.lorem.sentence(),
uri: faker.internet.url(),
iconUrl: faker.image.imageUrl()
},
...props
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { DatasetSummary } from '../../../../../src/sections/dataset/dataset-summary/DatasetSummary'
import { DatasetField, License } from '../../../../../src/dataset/domain/models/Dataset'
import { faker } from '@faker-js/faker'

describe('DatasetSummary', () => {
const licenseMock: License = {
name: 'CC0 1.0',
shortDescription: 'CC0 1.0 Universal Public Domain Dedication',
uri: 'https://creativecommons.org/publicdomain/zero/1.0/',
iconUrl: 'https://licensebuttons.net/p/zero/1.0/88x31.png'
}
const summaryFieldsMock: DatasetField[] = [
{
title: 'Description',
description: 'this is the description field',
value: 'This is the description field. This is where we describe the dataset'
},
{
title: 'Keyword',
description: 'this is the keyword field',
value: 'Malaria, Tuberculosis, Drug Resistant'
},
{
title: 'Subject',
description: 'this is the subject field',
value: 'Medicine, Health and Life Sciences, Social Sciences'
},
{
title: 'Related Publication',
description: 'this is the keyword field',
value: 'keyword1, keyword2'
},
{
title: 'Notes',
description: 'this is the notes field',
value: faker.lorem.paragraph(3)
}
]

it('renders the DatasetSummary fields', () => {
cy.mount(<DatasetSummary summaryFields={summaryFieldsMock} license={licenseMock} />)
summaryFieldsMock.map((field) => {
cy.findByText(field.title).should('exist')
cy.findByText(field.value).should('exist')
})

cy.get('img').should('exist')
cy.findByText(licenseMock.name).should('exist')
})
})
32 changes: 32 additions & 0 deletions tests/component/sections/dataset/dataset-summary/License.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { License } from '../../../../../src/sections/dataset/dataset-summary/License'

describe('DatasetSummary', () => {
it('renders the license information correctly', () => {
// Mock license data
const license = {
name: 'Test License',
iconUrl: 'https://example.com/icon.png',
shortDescription: 'Test description',
uri: 'https://example.com/license'
}

cy.customMount(<License license={license} />)

// Check if the License component is rendered
cy.get('article').should('exist')

// Check if the license name is displayed
cy.get('article').contains('Test License').should('exist')
cy.findByText('License/Data Use Agreement').should('exist')
// Check if the license icon is displayed
cy.get('img')
.should('have.attr', 'alt', 'Test License license icon')
.and('have.attr', 'src', 'https://example.com/icon.png')
.and('have.attr', 'title', 'Test description')

// Check if the license link is correct
cy.get('a')
.should('have.attr', 'href', 'https://example.com/license')
.and('have.text', 'Test License')
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { MarkdownComponent } from '../../../../../src/sections/dataset/markdown/MarkdownComponent'

describe('MarkdownComponent', () => {
it('renders Markdown correctly', () => {
const markdown =
'# Heading\n\nThis is some **bold** text ' +
'This is the description field. Here is [a link](https://dataverse.org). ' +
' Here is an image ![Alt text](https://picsum.photos/id/10/20/20) '

cy.customMount(<MarkdownComponent markdown={markdown} />)
cy.get('h1').should('have.text', 'Heading')
cy.get('strong').should('have.text', 'bold')
cy.get('p').should('exist')
cy.get('a').should('have.attr', 'href').and('eq', 'https://dataverse.org')
})
})

it('updates Markdown correctly', () => {
const initialMarkdown = '# Heading\n\nThis is some **bold** text'
const updatedMarkdown = '# New heading\n\nThis is some _italic_ text'
cy.customMount(<MarkdownComponent markdown={initialMarkdown} />)

cy.get('h1').should('have.text', 'Heading')
cy.get('strong').should('have.text', 'bold')
cy.get('p').should('exist')
cy.customMount(<MarkdownComponent markdown={updatedMarkdown} />)
cy.get('h1').should('have.text', 'New heading')
cy.get('em').should('have.text', 'italic')
})
Loading