@@ -58,7 +58,10 @@ export function Dataset({ repository, searchParams }: DatasetProps) {
-
+
diff --git a/src/sections/dataset/DatasetFactory.tsx b/src/sections/dataset/DatasetFactory.tsx
index cbc05a693..1471a0c23 100644
--- a/src/sections/dataset/DatasetFactory.tsx
+++ b/src/sections/dataset/DatasetFactory.tsx
@@ -4,15 +4,20 @@ import { Dataset } from './Dataset'
import { DatasetJSDataverseRepository } from '../../dataset/infrastructure/repositories/DatasetJSDataverseRepository'
import { useAnonymized } from './anonymized/AnonymizedContext'
import { AnonymizedProvider } from './anonymized/AnonymizedProvider'
+import { MetadataBlockInfoProvider } from './metadata-block-info/MetadataBlockProvider'
+import { MetadataBlockInfoJSDataverseRepository } from '../../metadata-block-info/infrastructure/MetadataBlockInfoJSDataverseRepository'
const datasetRepository = new DatasetJSDataverseRepository()
+const metadataBlockInfoRepository = new MetadataBlockInfoJSDataverseRepository()
export class DatasetFactory {
static create(): ReactElement {
return (
-
-
-
+
+
+
+
+
)
}
}
diff --git a/src/sections/dataset/anonymized/AnonymizedContext.ts b/src/sections/dataset/anonymized/AnonymizedContext.ts
index 6fc5d4103..5ecf9cb3e 100644
--- a/src/sections/dataset/anonymized/AnonymizedContext.ts
+++ b/src/sections/dataset/anonymized/AnonymizedContext.ts
@@ -5,6 +5,9 @@ interface AnonymizedContextProps {
setAnonymizedView: (anonymizedView: boolean) => void
}
-export const AnonymizedContext = createContext({} as AnonymizedContextProps)
+export const AnonymizedContext = createContext
({
+ anonymizedView: false,
+ setAnonymizedView: /* istanbul ignore next */ (): void => {}
+})
export const useAnonymized = () => useContext(AnonymizedContext)
diff --git a/src/sections/dataset/dataset-metadata/DatasetMetadata.tsx b/src/sections/dataset/dataset-metadata/DatasetMetadata.tsx
index ce293212c..14085aaed 100644
--- a/src/sections/dataset/dataset-metadata/DatasetMetadata.tsx
+++ b/src/sections/dataset/dataset-metadata/DatasetMetadata.tsx
@@ -1,19 +1,30 @@
import { Accordion } from 'dataverse-design-system'
-import { DatasetMetadataBlock as DatasetMetadataBlockModel } from '../../../dataset/domain/models/Dataset'
+import {
+ DatasetMetadataBlock as DatasetMetadataBlockModel,
+ MetadataBlockName
+} from '../../../dataset/domain/models/Dataset'
import { DatasetMetadataBlock } from './dataset-metadata-block/DatasetMetadataBlock'
interface DatasetMetadataProps {
+ persistentId: string
metadataBlocks: DatasetMetadataBlockModel[]
}
-export function DatasetMetadata({ metadataBlocks }: DatasetMetadataProps) {
+export function DatasetMetadata({ persistentId, metadataBlocks }: DatasetMetadataProps) {
return (
- {metadataBlocks.map((metadataBlock, index) => (
-
-
-
- ))}
+ {metadataBlocks.map((metadataBlock, index) => {
+ metadataBlock.fields =
+ metadataBlock.name === MetadataBlockName.CITATION
+ ? { persistentId: persistentId, ...metadataBlock.fields }
+ : metadataBlock.fields
+
+ return (
+
+
+
+ )
+ })}
)
}
diff --git a/src/sections/dataset/dataset-metadata/dataset-metadata-block/DatasetMetadataBlock.tsx b/src/sections/dataset/dataset-metadata/dataset-metadata-block/DatasetMetadataBlock.tsx
index 93ab3bc24..af871d515 100644
--- a/src/sections/dataset/dataset-metadata/dataset-metadata-block/DatasetMetadataBlock.tsx
+++ b/src/sections/dataset/dataset-metadata/dataset-metadata-block/DatasetMetadataBlock.tsx
@@ -9,7 +9,6 @@ interface DatasetMetadataBlockProps {
export function DatasetMetadataBlock({ metadataBlock }: DatasetMetadataBlockProps) {
const { t } = useTranslation(metadataBlock.name)
-
return (
<>
{t(`${metadataBlock.name}.name`)}
diff --git a/src/sections/dataset/dataset-metadata/dataset-metadata-fields/DatasetMetadataField.tsx b/src/sections/dataset/dataset-metadata/dataset-metadata-fields/DatasetMetadataField.tsx
index fcca3563d..4acb4abf3 100644
--- a/src/sections/dataset/dataset-metadata/dataset-metadata-fields/DatasetMetadataField.tsx
+++ b/src/sections/dataset/dataset-metadata/dataset-metadata-fields/DatasetMetadataField.tsx
@@ -3,6 +3,7 @@ import { Col, Row } from 'dataverse-design-system'
import { MetadataBlockName } from '../../../../dataset/domain/models/Dataset'
import { DatasetMetadataFieldValue } from './DatasetMetadataFieldValue'
import { DatasetMetadataFieldTitle } from './DatasetMetadataFieldTitle'
+import { DatasetMetadataFieldTip } from './DatasetMetadataFieldTip'
interface DatasetMetadataFieldProps {
metadataBlockName: MetadataBlockName
@@ -24,7 +25,14 @@ export function DatasetMetadataField({
/>
-
+
+
)
diff --git a/src/sections/dataset/dataset-metadata/dataset-metadata-fields/DatasetMetadataFieldTip.module.scss b/src/sections/dataset/dataset-metadata/dataset-metadata-fields/DatasetMetadataFieldTip.module.scss
new file mode 100644
index 000000000..405e1c4fb
--- /dev/null
+++ b/src/sections/dataset/dataset-metadata/dataset-metadata-fields/DatasetMetadataFieldTip.module.scss
@@ -0,0 +1,5 @@
+@import "node_modules/dataverse-design-system/src/lib/components/assets/styles/design-tokens/colors.module";
+
+.message {
+ color: $dv-subtext-color;
+}
\ No newline at end of file
diff --git a/src/sections/dataset/dataset-metadata/dataset-metadata-fields/DatasetMetadataFieldTip.tsx b/src/sections/dataset/dataset-metadata/dataset-metadata-fields/DatasetMetadataFieldTip.tsx
new file mode 100644
index 000000000..4effed183
--- /dev/null
+++ b/src/sections/dataset/dataset-metadata/dataset-metadata-fields/DatasetMetadataFieldTip.tsx
@@ -0,0 +1,20 @@
+import { MetadataBlockName } from '../../../../dataset/domain/models/Dataset'
+import { useTranslation } from 'react-i18next'
+import styles from './DatasetMetadataFieldTip.module.scss'
+
+interface DatasetMetadataFieldTipProps {
+ metadataBlockName: MetadataBlockName
+ metadataFieldName: string
+}
+
+export function DatasetMetadataFieldTip({
+ metadataBlockName,
+ metadataFieldName
+}: DatasetMetadataFieldTipProps) {
+ const { t } = useTranslation(`${metadataBlockName}`)
+ const tipMessageTranslationKey = `${metadataBlockName}.datasetField.${metadataFieldName}.tip`
+ const tipMessage =
+ t(tipMessageTranslationKey) === tipMessageTranslationKey ? null : t(tipMessageTranslationKey)
+
+ return tipMessage ? {tipMessage} : <>>
+}
diff --git a/src/sections/dataset/dataset-metadata/dataset-metadata-fields/DatasetMetadataFieldValue.tsx b/src/sections/dataset/dataset-metadata/dataset-metadata-fields/DatasetMetadataFieldValue.tsx
index d742832c1..1722b4159 100644
--- a/src/sections/dataset/dataset-metadata/dataset-metadata-fields/DatasetMetadataFieldValue.tsx
+++ b/src/sections/dataset/dataset-metadata/dataset-metadata-fields/DatasetMetadataFieldValue.tsx
@@ -1,24 +1,43 @@
import {
ANONYMIZED_FIELD_VALUE,
- DatasetMetadataFieldValue as DatasetMetadataFieldValueModel
+ DatasetMetadataFieldValue as DatasetMetadataFieldValueModel,
+ DatasetMetadataSubField
} from '../../../../dataset/domain/models/Dataset'
import { MarkdownComponent } from '../../markdown/MarkdownComponent'
import { useAnonymized } from '../../anonymized/AnonymizedContext'
import { useTranslation } from 'react-i18next'
+import { useMetadataBlockInfo } from '../../metadata-block-info/MetadataBlockInfoContext'
+import {
+ METADATA_FIELD_DISPLAY_FORMAT_PLACEHOLDER,
+ MetadataBlockInfo
+} from '../../../../metadata-block-info/domain/models/MetadataBlockInfo'
interface DatasetMetadataFieldValueProps {
+ metadataFieldName: string
metadataFieldValue: DatasetMetadataFieldValueModel
}
-export function DatasetMetadataFieldValue({ metadataFieldValue }: DatasetMetadataFieldValueProps) {
+export function DatasetMetadataFieldValue({
+ metadataFieldName,
+ metadataFieldValue
+}: DatasetMetadataFieldValueProps) {
const { anonymizedView } = useAnonymized()
-
const isAnonymizedField = anonymizedView && metadataFieldValue == ANONYMIZED_FIELD_VALUE
+ const { metadataBlockInfo } = useMetadataBlockInfo()
+
if (isAnonymizedField) {
return
}
- return
+ return (
+
+ )
}
const AnonymizedFieldValue = () => {
@@ -27,18 +46,24 @@ const AnonymizedFieldValue = () => {
}
export function metadataFieldValueToString(
- metadataFieldValue: DatasetMetadataFieldValueModel
+ metadataFieldName: string,
+ metadataFieldValue: DatasetMetadataFieldValueModel,
+ metadataBlockInfo?: MetadataBlockInfo
): string {
+ const separator = metadataBlockInfo?.fields[metadataFieldName]?.displayFormat ?? ''
+
if (isArrayOfObjects(metadataFieldValue)) {
- return metadataFieldValue.map((field) => Object.values(field).join(' ')).join(' \n \n')
+ return metadataFieldValue
+ .map((metadataSubField) => joinSubFields(metadataSubField, metadataBlockInfo))
+ .join(' \n \n')
}
if (Array.isArray(metadataFieldValue)) {
- return metadataFieldValue.join('; ')
+ return metadataFieldValue.join(`${separator} `)
}
if (isAnObject(metadataFieldValue)) {
- return Object.values(metadataFieldValue).join(' ')
+ return Object.values(metadataFieldValue).join(`${separator} `)
}
return metadataFieldValue
@@ -55,3 +80,29 @@ export function isArrayOfObjects(variable: unknown): variable is object[] {
function isAnObject(variable: unknown): variable is object {
return typeof variable === 'object' && variable !== null
}
+
+function joinSubFields(
+ metadataSubField: DatasetMetadataSubField,
+ metadataBlockInfo?: MetadataBlockInfo
+) {
+ return Object.entries(metadataSubField)
+ .map(([subFieldName, subFieldValue]) =>
+ formatSubFieldValue(subFieldValue, metadataBlockInfo?.fields[subFieldName]?.displayFormat)
+ )
+ .join(' ')
+}
+
+function formatSubFieldValue(
+ subFieldValue: string | undefined,
+ displayFormat: string | undefined
+): string {
+ if (subFieldValue === undefined) {
+ return ''
+ }
+
+ if (displayFormat === undefined) {
+ return subFieldValue
+ }
+
+ return displayFormat.replaceAll(METADATA_FIELD_DISPLAY_FORMAT_PLACEHOLDER, subFieldValue)
+}
diff --git a/src/sections/dataset/dataset-metadata/dataset-metadata-fields/DatasetMetadataFields.tsx b/src/sections/dataset/dataset-metadata/dataset-metadata-fields/DatasetMetadataFields.tsx
index 8f1869415..8a6b74751 100644
--- a/src/sections/dataset/dataset-metadata/dataset-metadata-fields/DatasetMetadataFields.tsx
+++ b/src/sections/dataset/dataset-metadata/dataset-metadata-fields/DatasetMetadataFields.tsx
@@ -1,6 +1,8 @@
import { DatasetMetadataField } from './DatasetMetadataField'
import { DatasetMetadataFields as DatasetMetadataFieldsModel } from '../../../../dataset/domain/models/Dataset'
import { MetadataBlockName } from '../../../../dataset/domain/models/Dataset'
+import { useMetadataBlockInfo } from '../../metadata-block-info/MetadataBlockInfoContext'
+import { useEffect } from 'react'
interface DatasetMetadataFieldsProps {
metadataBlockName: MetadataBlockName
@@ -11,6 +13,12 @@ export function DatasetMetadataFields({
metadataBlockName,
metadataFields
}: DatasetMetadataFieldsProps) {
+ const { setMetadataBlockName } = useMetadataBlockInfo()
+
+ useEffect(() => {
+ setMetadataBlockName(metadataBlockName)
+ }, [metadataBlockName])
+
return (
<>
{Object.entries(metadataFields).map(([metadataFieldName, metadataFieldValue], index) => (
diff --git a/src/sections/dataset/metadata-block-info/MetadataBlockInfoContext.ts b/src/sections/dataset/metadata-block-info/MetadataBlockInfoContext.ts
new file mode 100644
index 000000000..95ae7fcc8
--- /dev/null
+++ b/src/sections/dataset/metadata-block-info/MetadataBlockInfoContext.ts
@@ -0,0 +1,15 @@
+import { createContext, useContext } from 'react'
+import { MetadataBlockName } from '../../../dataset/domain/models/Dataset'
+import { MetadataBlockInfo } from '../../../metadata-block-info/domain/models/MetadataBlockInfo'
+
+interface MetadataBlockInfoContextProps {
+ metadataBlockInfo: MetadataBlockInfo | undefined
+ setMetadataBlockName: (metadataBlockName: MetadataBlockName) => void
+}
+
+export const MetadataBlockInfoContext = createContext({
+ metadataBlockInfo: undefined,
+ setMetadataBlockName: /* istanbul ignore next */ (): void => {}
+})
+
+export const useMetadataBlockInfo = () => useContext(MetadataBlockInfoContext)
diff --git a/src/sections/dataset/metadata-block-info/MetadataBlockProvider.tsx b/src/sections/dataset/metadata-block-info/MetadataBlockProvider.tsx
new file mode 100644
index 000000000..e4b35b2c6
--- /dev/null
+++ b/src/sections/dataset/metadata-block-info/MetadataBlockProvider.tsx
@@ -0,0 +1,28 @@
+import { PropsWithChildren, useEffect, useState } from 'react'
+import { MetadataBlockInfoContext } from './MetadataBlockInfoContext'
+import { MetadataBlockInfo } from '../../../metadata-block-info/domain/models/MetadataBlockInfo'
+import { MetadataBlockInfoRepository } from '../../../metadata-block-info/domain/repositories/MetadataBlockInfoRepository'
+import { getMetadataBlockInfoByName } from '../../../metadata-block-info/domain/useCases/getMetadataBlockInfoByName'
+import { MetadataBlockName } from '../../../dataset/domain/models/Dataset'
+
+export function MetadataBlockInfoProvider({
+ children,
+ repository
+}: PropsWithChildren<{ repository: MetadataBlockInfoRepository }>) {
+ const [metadataBlockName, setMetadataBlockName] = useState(MetadataBlockName.CITATION)
+ const [metadataBlockInfo, setMetadataBlockInfo] = useState()
+
+ useEffect(() => {
+ getMetadataBlockInfoByName(repository, metadataBlockName)
+ .then((metadataBlockInfo) => {
+ setMetadataBlockInfo(metadataBlockInfo)
+ })
+ .catch((error) => console.error('There was an error getting the metadata block info', error))
+ }, [repository, metadataBlockName])
+
+ return (
+
+ {children}
+
+ )
+}
diff --git a/src/stories/dataset/Dataset.stories.tsx b/src/stories/dataset/Dataset.stories.tsx
index c968966bd..409c0911e 100644
--- a/src/stories/dataset/Dataset.stories.tsx
+++ b/src/stories/dataset/Dataset.stories.tsx
@@ -6,11 +6,12 @@ import { WithLayoutLoading } from '../WithLayoutLoading'
import { WithAnonymizedView } from './WithAnonymizedView'
import { DatasetMockRepository } from './DatasetMockRepository'
import { DatasetMockNoDataRepository } from './DatasetMockNoDataRepository'
+import { WithCitationMetadataBlockInfo } from './WithCitationMetadataBlockInfo'
const meta: Meta = {
title: 'Pages/Dataset',
component: Dataset,
- decorators: [WithI18next],
+ decorators: [WithI18next, WithCitationMetadataBlockInfo],
parameters: {
// Sets the delay for all stories.
chromatic: { delay: 15000, pauseAnimationAtEnd: true }
@@ -23,21 +24,30 @@ type Story = StoryObj
export const Default: Story = {
decorators: [WithLayout],
render: () => (
-
+
)
}
export const Loading: Story = {
decorators: [WithLayoutLoading],
render: () => (
-
+
)
}
export const DatasetNotFound: Story = {
decorators: [WithLayout],
render: () => (
-
+
)
}
diff --git a/src/stories/dataset/DatasetMockData.ts b/src/stories/dataset/DatasetMockData.ts
index 3af778c35..f4d532261 100644
--- a/src/stories/dataset/DatasetMockData.ts
+++ b/src/stories/dataset/DatasetMockData.ts
@@ -3,80 +3,106 @@ import {
DatasetStatus,
DatasetVersion,
DatasetLabelSemanticMeaning,
- DatasetLabelValue
+ DatasetLabelValue,
+ DatasetMetadataBlocks
} from '../../dataset/domain/models/Dataset'
import { MetadataBlockName } from '../../dataset/domain/models/Dataset'
import { Dataset } from '../../dataset/domain/models/Dataset'
-export const DatasetMockData = (props?: Partial, anonymized = false): Dataset => ({
- persistentId: '123456789',
- title: 'Dataset title',
- citation: `${
- anonymized ? 'Author name(s) withheld' : 'Bennet, Elizabeth; Darcy, Fitzwilliam'
- }, 2023, "Dataset Title", https://doi.org/10.5072/FK2/BUDNRV, Root, V1`,
- version: new DatasetVersion(1, 0, DatasetStatus.RELEASED),
- labels: [
- { value: 'Version 1.0', semanticMeaning: DatasetLabelSemanticMeaning.FILE },
- { value: DatasetLabelValue.DRAFT, semanticMeaning: DatasetLabelSemanticMeaning.DATASET }
- ],
- license: {
- name: 'CC0 1.0',
- uri: 'https://creativecommons.org/publicdomain/zero/1.0/',
- iconUri: 'https://licensebuttons.net/p/zero/1.0/88x31.png'
- },
- summaryFields: [
- {
- name: MetadataBlockName.CITATION,
- fields: {
- dsDescription:
- 'This text is *italic* and this is **bold**. Here is an image ![Alt text](https://picsum.photos/id/10/20/20) ',
- keyword: 'Malaria, Tuberculosis, Drug Resistant',
- subject: 'Medicine, Health and Life Sciences, Social Sciences',
- publication: 'CNN Journal [CNN.com](https://cnn.com)',
- notesText: 'Here is an image ![Alt text](https://picsum.photos/id/10/40/40)'
- }
- }
- ],
- metadataBlocks: [
- {
- name: MetadataBlockName.CITATION,
- fields: {
- persistentId: 'doi:10.5072/FK2/ABC123',
- alternativePersistentId: 'doi:10.5072/FK2/ABC123',
- publicationDate: anonymized ? ANONYMIZED_FIELD_VALUE : '2021-01-01',
- citationDate: '2021-01-01',
- title: 'Dataset Title',
- subject: ['Subject1', 'Subject2'],
- author: anonymized
- ? ANONYMIZED_FIELD_VALUE
- : [
- {
- authorName: 'Admin, Dataverse',
- authorAffiliation: 'Dataverse.org',
- authorIdentifierScheme: 'ORCID',
- authorIdentifier: '123456789'
- },
- {
- authorName: 'Owner, Dataverse',
- authorAffiliation: 'Dataverse.org',
- authorIdentifierScheme: 'ORCID',
- authorIdentifier: '123456789'
- }
- ]
- }
+export const DatasetMockData = (props?: Partial, anonymized = false): Dataset => {
+ const dataset = {
+ persistentId: 'doi:10.5072/FK2/ABC123',
+ citation: `${
+ anonymized ? 'Author name(s) withheld' : 'Bennet, Elizabeth; Darcy, Fitzwilliam'
+ }, 2023, "Dataset Title", https://doi.org/10.5072/FK2/BUDNRV, Root, V1`,
+ version: new DatasetVersion(1, 0, DatasetStatus.RELEASED),
+ labels: [
+ { value: 'Version 1.0', semanticMeaning: DatasetLabelSemanticMeaning.FILE },
+ { value: DatasetLabelValue.DRAFT, semanticMeaning: DatasetLabelSemanticMeaning.DATASET }
+ ],
+ license: {
+ name: 'CC0 1.0',
+ uri: 'https://creativecommons.org/publicdomain/zero/1.0/',
+ iconUri: 'https://licensebuttons.net/p/zero/1.0/88x31.png'
},
- {
- name: MetadataBlockName.GEOSPATIAL,
- fields: {
- geographicUnit: 'km',
- geographicCoverage: anonymized
- ? ANONYMIZED_FIELD_VALUE
- : {
- geographicCoverageCountry: 'United States',
- geographicCoverageCity: 'Cambridge'
+ summaryFields: [
+ {
+ name: MetadataBlockName.CITATION,
+ fields: {
+ dsDescription: [
+ {
+ dsDescriptionValue:
+ 'This text is *italic* and this is **bold**. Here is an image ![Alt text](https://picsum.photos/id/10/20/20) '
}
+ ],
+ keyword: 'Malaria, Tuberculosis, Drug Resistant',
+ subject: 'Medicine, Health and Life Sciences, Social Sciences',
+ publication: 'CNN Journal [CNN.com](https://cnn.com)',
+ notesText: 'Here is an image ![Alt text](https://picsum.photos/id/10/40/40)'
+ }
+ }
+ ],
+ metadataBlocks: [
+ {
+ name: MetadataBlockName.CITATION,
+ fields: {
+ alternativePersistentId: 'doi:10.5072/FK2/ABC123',
+ publicationDate: anonymized ? ANONYMIZED_FIELD_VALUE : '2021-01-01',
+ citationDate: '2023-01-01',
+ title: 'Dataset Title',
+ subject: ['Subject1', 'Subject2'],
+ author: anonymized
+ ? ANONYMIZED_FIELD_VALUE
+ : [
+ {
+ authorName: 'Admin, Dataverse',
+ authorAffiliation: 'Dataverse.org',
+ authorIdentifierScheme: 'ORCID',
+ authorIdentifier: '0000-0002-1825-1097'
+ },
+ {
+ authorName: 'Owner, Dataverse',
+ authorAffiliation: 'Dataverse.org',
+ authorIdentifierScheme: 'ORCID',
+ authorIdentifier: '0000-0032-1825-0098'
+ }
+ ],
+ datasetContact: anonymized
+ ? ANONYMIZED_FIELD_VALUE
+ : [
+ {
+ datasetContactName: 'Admin, Dataverse'
+ }
+ ],
+ dsDescription: [
+ {
+ dsDescriptionValue:
+ 'This text is *italic* and this is **bold**. Here is an image ![Alt text](https://picsum.photos/id/10/20/20) '
+ }
+ ]
+ }
+ },
+ {
+ name: MetadataBlockName.GEOSPATIAL,
+ fields: {
+ geographicUnit: 'km',
+ geographicCoverage: anonymized
+ ? ANONYMIZED_FIELD_VALUE
+ : {
+ geographicCoverageCountry: 'United States',
+ geographicCoverageCity: 'Cambridge'
+ }
+ }
}
- }
- ],
- ...props
-})
+ ] as DatasetMetadataBlocks,
+ ...props
+ }
+ return new Dataset.Builder(
+ dataset.persistentId,
+ dataset.version,
+ dataset.citation,
+ dataset.summaryFields,
+ dataset.license,
+ dataset.metadataBlocks
+ ).build()
+}
diff --git a/src/stories/dataset/WithCitationMetadataBlockInfo.tsx b/src/stories/dataset/WithCitationMetadataBlockInfo.tsx
new file mode 100644
index 000000000..20636d3b4
--- /dev/null
+++ b/src/stories/dataset/WithCitationMetadataBlockInfo.tsx
@@ -0,0 +1,15 @@
+import { StoryFn } from '@storybook/react'
+import { MetadataBlockInfoContext } from '../../sections/dataset/metadata-block-info/MetadataBlockInfoContext'
+import { MetadataBlockInfoMother } from '../../../tests/component/metadata-block-info/domain/models/MetadataBlockInfoMother'
+
+export const WithCitationMetadataBlockInfo = (Story: StoryFn) => {
+ const setMetadataBlockName = () => {}
+ const metadataBlockInfoMock = MetadataBlockInfoMother.create()
+
+ return (
+
+
+
+ )
+}
diff --git a/src/stories/dataset/dataset-metadata/DatasetMetadata.stories.tsx b/src/stories/dataset/dataset-metadata/DatasetMetadata.stories.tsx
index e225d5886..3896a08cd 100644
--- a/src/stories/dataset/dataset-metadata/DatasetMetadata.stories.tsx
+++ b/src/stories/dataset/dataset-metadata/DatasetMetadata.stories.tsx
@@ -1,30 +1,37 @@
import type { Meta, StoryObj } from '@storybook/react'
import { WithI18next } from '../../WithI18next'
import { DatasetMetadata } from '../../../sections/dataset/dataset-metadata/DatasetMetadata'
-import { DatasetMetadataBlock } from '../../../dataset/domain/models/Dataset'
import { DatasetMockData } from '../DatasetMockData'
import { WithAnonymizedView } from '../WithAnonymizedView'
+import { WithCitationMetadataBlockInfo } from '../WithCitationMetadataBlockInfo'
const meta: Meta = {
title: 'Sections/Dataset Page/DatasetMetadata',
component: DatasetMetadata,
- decorators: [WithI18next]
+ decorators: [WithI18next, WithCitationMetadataBlockInfo]
}
export default meta
type Story = StoryObj
-const metadataBlocksMock: DatasetMetadataBlock[] = DatasetMockData().metadataBlocks
-const metadataBlocksAnonymizedMock: DatasetMetadataBlock[] = DatasetMockData(
- {},
- true
-).metadataBlocks
+const datasetMock = DatasetMockData()
+const datasetMockAnonymized = DatasetMockData({}, true)
export const Default: Story = {
- render: () =>
+ render: () => (
+
+ )
}
export const AnonymizedView: Story = {
decorators: [WithAnonymizedView],
- render: () =>
+ render: () => (
+
+ )
}
diff --git a/tests/component/dataset/domain/models/DatasetMother.ts b/tests/component/dataset/domain/models/DatasetMother.ts
index d056de378..0e84fa720 100644
--- a/tests/component/dataset/domain/models/DatasetMother.ts
+++ b/tests/component/dataset/domain/models/DatasetMother.ts
@@ -2,12 +2,13 @@ import { faker } from '@faker-js/faker'
import {
ANONYMIZED_FIELD_VALUE,
Dataset,
+ DatasetLabelSemanticMeaning,
+ DatasetLabelValue,
DatasetStatus,
DatasetVersion,
- DatasetLabelSemanticMeaning,
- DatasetLabelValue
+ MetadataBlockName,
+ DatasetMetadataBlocks
} from '../../../../../src/dataset/domain/models/Dataset'
-import { MetadataBlockName } from '../../../../../src/dataset/domain/models/Dataset'
export class DatasetMother {
static createEmpty(): undefined {
@@ -15,7 +16,7 @@ export class DatasetMother {
}
static create(props?: Partial): Dataset {
- return {
+ const dataset = {
persistentId: faker.datatype.uuid(),
title: faker.lorem.sentence(),
version: new DatasetVersion(1, 0, DatasetStatus.RELEASED),
@@ -44,6 +45,18 @@ export class DatasetMother {
semanticMeaning: faker.helpers.arrayElement(Object.values(DatasetLabelSemanticMeaning))
}
],
+ summaryFields: [
+ {
+ name: MetadataBlockName.CITATION,
+ fields: {
+ dsDescription: faker.lorem.sentence(),
+ keyword: faker.lorem.sentence(),
+ subject: faker.lorem.sentence(),
+ publication: faker.lorem.sentence(),
+ notesText: faker.lorem.sentence()
+ }
+ }
+ ],
metadataBlocks: [
{
name: MetadataBlockName.CITATION,
@@ -63,6 +76,17 @@ export class DatasetMother {
authorIdentifierScheme: faker.lorem.sentence(),
authorIdentifier: faker.lorem.sentence()
}
+ ],
+ datasetContact: [
+ {
+ datasetContactName: faker.lorem.sentence(),
+ datasetContactEmail: faker.internet.email()
+ }
+ ],
+ dsDescription: [
+ {
+ dsDescriptionValue: faker.lorem.sentence()
+ }
]
}
},
@@ -75,21 +99,18 @@ export class DatasetMother {
}
}
}
- ],
- summaryFields: [
- {
- name: MetadataBlockName.CITATION,
- fields: {
- dsDescription: faker.lorem.sentence(),
- keyword: faker.lorem.sentence(),
- subject: faker.lorem.sentence(),
- publication: faker.lorem.sentence(),
- notesText: faker.lorem.sentence()
- }
- }
- ],
+ ] as DatasetMetadataBlocks,
...props
}
+
+ return new Dataset.Builder(
+ dataset.persistentId,
+ dataset.version,
+ dataset.citation,
+ dataset.summaryFields,
+ dataset.license,
+ dataset.metadataBlocks
+ ).build()
}
static createAnonymized(): Dataset {
@@ -101,7 +122,15 @@ export class DatasetMother {
name: MetadataBlockName.CITATION,
fields: {
title: faker.lorem.sentence(),
- author: ANONYMIZED_FIELD_VALUE
+ subject: [faker.lorem.word(), faker.lorem.word()],
+ author: ANONYMIZED_FIELD_VALUE,
+ datasetContact: [
+ {
+ datasetContactName: faker.lorem.sentence(),
+ datasetContactEmail: faker.internet.email()
+ }
+ ],
+ dsDescription: ANONYMIZED_FIELD_VALUE
}
},
{
diff --git a/tests/component/fixtures/metadataTranslations.json b/tests/component/fixtures/metadataTranslations.json
index b5f620bc1..141aeb83e 100644
--- a/tests/component/fixtures/metadataTranslations.json
+++ b/tests/component/fixtures/metadataTranslations.json
@@ -2,6 +2,22 @@
"citation": {
"name": "Citation Metadata",
"datasetField": {
+ "persistentId": {
+ "name": "Persistent Identifier",
+ "description": "The Dataset's unique persistent identifier, either a DOI or Handle"
+ },
+ "alternativePersistentId": {
+ "name": "Previous Dataset Persistent ID",
+ "description": "A previously used persistent identifier for the Dataset, either a DOI or Handle"
+ },
+ "publicationDate": {
+ "name": "Publication Date",
+ "description": "The publication date of a Dataset."
+ },
+ "citationDate": {
+ "name": "Citation Date",
+ "description": "The citation date of a dataset, determined by the longest embargo on any file in version 1.0."
+ },
"title": { "name": "Title", "description": "The main title of the Dataset" },
"subtitle": {
"name": "Subtitle",
@@ -49,7 +65,8 @@
},
"datasetContact": {
"name": "Point of Contact",
- "description": "The entity, e.g. a person or organization, that users of the Dataset can contact with questions"
+ "description": "The entity, e.g. a person or organization, that users of the Dataset can contact with questions",
+ "tip": "Use email button above to contact."
},
"datasetContactName": {
"name": "Name",
diff --git a/tests/component/metadata-block-info/domain/models/MetadataBlockInfoMother.ts b/tests/component/metadata-block-info/domain/models/MetadataBlockInfoMother.ts
new file mode 100644
index 000000000..791b5b9a1
--- /dev/null
+++ b/tests/component/metadata-block-info/domain/models/MetadataBlockInfoMother.ts
@@ -0,0 +1,29 @@
+import { MetadataBlockInfo } from '../../../../../src/metadata-block-info/domain/models/MetadataBlockInfo'
+import { MetadataBlockName } from '../../../../../src/dataset/domain/models/Dataset'
+
+export class MetadataBlockInfoMother {
+ static create(props?: Partial): MetadataBlockInfo {
+ return {
+ name: MetadataBlockName.CITATION,
+ fields: {
+ alternativePersistentId: { displayFormat: '' },
+ publicationDate: { displayFormat: '' },
+ citationDate: { displayFormat: '' },
+ title: { displayFormat: '' },
+ subject: { displayFormat: ';' },
+ author: { displayFormat: '' },
+ authorName: { displayFormat: '#VALUE' },
+ authorAffiliation: { displayFormat: '(#VALUE)' },
+ authorIdentifierScheme: { displayFormat: '- #VALUE:' },
+ authorIdentifier: { displayFormat: '[#VALUE](https://orcid.org/#VALUE)' },
+ datasetContact: { displayFormat: '#VALUE' },
+ datasetContactName: { displayFormat: '#VALUE' },
+ datasetContactAffiliation: { displayFormat: '(#VALUE)' },
+ datasetContactEmail: { displayFormat: '#VALUE' },
+ dsDescription: { displayFormat: '' },
+ dsDescriptionValue: { displayFormat: '#VALUE' }
+ },
+ ...props
+ }
+ }
+}
diff --git a/tests/component/sections/dataset/Dataset.spec.tsx b/tests/component/sections/dataset/Dataset.spec.tsx
index beee775d0..e0248f283 100644
--- a/tests/component/sections/dataset/Dataset.spec.tsx
+++ b/tests/component/sections/dataset/Dataset.spec.tsx
@@ -5,7 +5,6 @@ import { LoadingProvider } from '../../../../src/sections/loading/LoadingProvide
import { useLoading } from '../../../../src/sections/loading/LoadingContext'
import { ANONYMIZED_FIELD_VALUE } from '../../../../src/dataset/domain/models/Dataset'
import { AnonymizedContext } from '../../../../src/sections/dataset/anonymized/AnonymizedContext'
-import { AnonymizedProvider } from '../../../../src/sections/dataset/anonymized/AnonymizedProvider'
describe('Dataset', () => {
const testDataset = DatasetMother.create()
@@ -38,7 +37,7 @@ describe('Dataset', () => {
cy.findByText(buttonText).click()
cy.findByTestId('dataset-skeleton').should('exist')
- cy.findByText(testDataset.title).should('not.exist')
+ cy.findByText(testDataset.getTitle()).should('not.exist')
})
it('renders page not found when dataset is null', () => {
@@ -83,7 +82,7 @@ describe('Dataset', () => {
cy.wrap(datasetRepository.getByPersistentId).should('be.calledWith', testDataset.persistentId)
- cy.findByText(testDataset.title).should('exist')
+ cy.findAllByText(testDataset.getTitle()).should('exist')
testDataset.labels.forEach((label) => {
cy.findAllByText(label.value).should('exist')
@@ -103,7 +102,7 @@ describe('Dataset', () => {
)
- cy.findByText(testDataset.title).should('exist')
+ cy.findAllByText(testDataset.getTitle()).should('exist')
const metadataTab = cy.findByRole('tab', { name: 'Metadata' })
metadataTab.should('exist')
@@ -114,6 +113,7 @@ describe('Dataset', () => {
})
it('renders the Dataset in anonymized view', () => {
+ const setAnonymizedView = () => {}
const testDatasetAnonymized = DatasetMother.createAnonymized()
const datasetRepository: DatasetRepository = {} as DatasetRepository
datasetRepository.getByPrivateUrlToken = cy.stub().resolves(testDatasetAnonymized)
@@ -121,19 +121,12 @@ describe('Dataset', () => {
cy.customMount(
-
-
- {({ setAnonymizedView }) => {
- setAnonymizedView(true)
- return (
-
- )
- }}
-
-
+
+
+
)
diff --git a/tests/component/sections/dataset/dataset-metadata/DatasetMetadata.spec.tsx b/tests/component/sections/dataset/dataset-metadata/DatasetMetadata.spec.tsx
index 1df4d6782..197e7e121 100644
--- a/tests/component/sections/dataset/dataset-metadata/DatasetMetadata.spec.tsx
+++ b/tests/component/sections/dataset/dataset-metadata/DatasetMetadata.spec.tsx
@@ -1,21 +1,32 @@
import { DatasetMother } from '../../../dataset/domain/models/DatasetMother'
import { DatasetMetadata } from '../../../../../src/sections/dataset/dataset-metadata/DatasetMetadata'
-import { ANONYMIZED_FIELD_VALUE } from '../../../../../src/dataset/domain/models/Dataset'
+import {
+ ANONYMIZED_FIELD_VALUE,
+ MetadataBlockName
+} from '../../../../../src/dataset/domain/models/Dataset'
import { AnonymizedContext } from '../../../../../src/sections/dataset/anonymized/AnonymizedContext'
-import { AnonymizedProvider } from '../../../../../src/sections/dataset/anonymized/AnonymizedProvider'
import {
isArrayOfObjects,
metadataFieldValueToString
} from '../../../../../src/sections/dataset/dataset-metadata/dataset-metadata-fields/DatasetMetadataFieldValue'
+import { MetadataBlockInfoProvider } from '../../../../../src/sections/dataset/metadata-block-info/MetadataBlockProvider'
+import { MetadataBlockInfoRepository } from '../../../../../src/metadata-block-info/domain/repositories/MetadataBlockInfoRepository'
+import { MetadataBlockInfoMother } from '../../../metadata-block-info/domain/models/MetadataBlockInfoMother'
describe('DatasetMetadata', () => {
it('renders the metadata blocks sections titles correctly', () => {
- const mockMetadataBlocks = DatasetMother.create().metadataBlocks
+ const mockDataset = DatasetMother.create()
+ const mockMetadataBlocks = mockDataset.metadataBlocks
cy.viewport(1280, 720)
cy.fixture('metadataTranslations').then((t) => {
- cy.customMount()
+ cy.customMount(
+
+ )
mockMetadataBlocks.forEach((metadataBlock) => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
@@ -26,12 +37,18 @@ describe('DatasetMetadata', () => {
})
it('renders the metadata blocks title correctly', () => {
- const mockMetadataBlocks = DatasetMother.create().metadataBlocks
+ const mockDataset = DatasetMother.create()
+ const mockMetadataBlocks = mockDataset.metadataBlocks
cy.viewport(1280, 720)
cy.fixture('metadataTranslations').then((t) => {
- cy.customMount()
+ cy.customMount(
+
+ )
mockMetadataBlocks.forEach((metadataBlock, index) => {
if (index !== 0) {
@@ -51,12 +68,18 @@ describe('DatasetMetadata', () => {
})
it('renders the metadata blocks description correctly', () => {
- const mockMetadataBlocks = DatasetMother.create().metadataBlocks
+ const mockDataset = DatasetMother.create()
+ const mockMetadataBlocks = mockDataset.metadataBlocks
cy.viewport(1280, 720)
cy.fixture('metadataTranslations').then((t) => {
- cy.customMount()
+ cy.customMount(
+
+ )
mockMetadataBlocks.forEach((metadataBlock, index) => {
if (index !== 0) {
@@ -81,12 +104,24 @@ describe('DatasetMetadata', () => {
})
it('renders the metadata blocks values correctly', () => {
- const mockMetadataBlocks = DatasetMother.create().metadataBlocks
+ const metadataBlockInfoMock = MetadataBlockInfoMother.create()
+ const metadataBlockInfoRepository: MetadataBlockInfoRepository =
+ {} as MetadataBlockInfoRepository
+ metadataBlockInfoRepository.getByName = cy.stub().resolves(metadataBlockInfoMock)
+ const mockDataset = DatasetMother.create()
+ const mockMetadataBlocks = mockDataset.metadataBlocks
cy.viewport(1280, 720)
cy.fixture('metadataTranslations').then((t) => {
- cy.customMount()
+ cy.customMount(
+
+
+
+ )
mockMetadataBlocks.forEach((metadataBlock, index) => {
if (index !== 0) {
@@ -94,8 +129,12 @@ describe('DatasetMetadata', () => {
cy.findByRole('button', { name: t[metadataBlock.name].name }).click()
}
- Object.entries(metadataBlock.fields).forEach(([, metadataFieldValue]) => {
- const metadataFieldValueString = metadataFieldValueToString(metadataFieldValue)
+ Object.entries(metadataBlock.fields).forEach(([metadataFieldName, metadataFieldValue]) => {
+ const metadataFieldValueString = metadataFieldValueToString(
+ metadataFieldName,
+ metadataFieldValue,
+ metadataBlockInfoMock
+ )
if (isArrayOfObjects(metadataFieldValue)) {
metadataFieldValueString.split(' \n \n').forEach((fieldValue) => {
@@ -114,19 +153,64 @@ describe('DatasetMetadata', () => {
})
it('renders the metadata blocks in anonymized view', () => {
- const mockAnonymizedMetadataBlocks = DatasetMother.createAnonymized().metadataBlocks
+ const setAnonymizedView = () => {}
+ const mockDataset = DatasetMother.createAnonymized()
+ const mockAnonymizedMetadataBlocks = mockDataset.metadataBlocks
cy.customMount(
-
-
- {({ setAnonymizedView }) => {
- setAnonymizedView(true)
- return
- }}
-
-
+
+
+
)
cy.findAllByText(ANONYMIZED_FIELD_VALUE).should('exist')
})
+
+ it('shows the Persistent Identifier as part of the Citation Metadata', () => {
+ const mockDataset = DatasetMother.create()
+ const mockMetadataBlocks = mockDataset.metadataBlocks
+
+ cy.viewport(1280, 720)
+
+ cy.fixture('metadataTranslations').then((t) => {
+ cy.customMount(
+
+ )
+
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
+ cy.findByRole('button', { name: t[MetadataBlockName.CITATION].name }).should('exist')
+
+ cy.findByText('Persistent Identifier').should('exist')
+ cy.findByText(mockDataset.persistentId).should('exist')
+ })
+ })
+
+ it('shows a tip if the translation exists', () => {
+ const mockDataset = DatasetMother.create()
+ const mockMetadataBlocks = mockDataset.metadataBlocks
+
+ cy.viewport(1280, 720)
+
+ cy.fixture('metadataTranslations').then((t) => {
+ cy.customMount(
+
+ )
+
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
+ cy.findByRole('button', { name: t[MetadataBlockName.CITATION].name }).should('exist')
+
+ cy.findByText(t[MetadataBlockName.CITATION].datasetField.datasetContact.tip as string).should(
+ 'exist'
+ )
+ })
+ })
})
diff --git a/tests/component/sections/dataset/dataset-summary/SummaryFields.spec.tsx b/tests/component/sections/dataset/dataset-summary/SummaryFields.spec.tsx
index 84e05c1a5..6041927b4 100644
--- a/tests/component/sections/dataset/dataset-summary/SummaryFields.spec.tsx
+++ b/tests/component/sections/dataset/dataset-summary/SummaryFields.spec.tsx
@@ -5,12 +5,23 @@ import {
isArrayOfObjects,
metadataFieldValueToString
} from '../../../../../src/sections/dataset/dataset-metadata/dataset-metadata-fields/DatasetMetadataFieldValue'
+import { MetadataBlockInfoMother } from '../../../metadata-block-info/domain/models/MetadataBlockInfoMother'
+import { MetadataBlockInfoRepository } from '../../../../../src/metadata-block-info/domain/repositories/MetadataBlockInfoRepository'
+import { MetadataBlockInfoProvider } from '../../../../../src/sections/dataset/metadata-block-info/MetadataBlockProvider'
describe('DatasetSummary', () => {
- const summaryFieldsMock: DatasetMetadataBlock[] = DatasetMother.create().summaryFields
-
it('renders the DatasetSummary fields', () => {
- cy.customMount()
+ const summaryFieldsMock: DatasetMetadataBlock[] = DatasetMother.create().summaryFields
+ const metadataBlockInfoMock = MetadataBlockInfoMother.create()
+ const metadataBlockInfoRepository: MetadataBlockInfoRepository =
+ {} as MetadataBlockInfoRepository
+ metadataBlockInfoRepository.getByName = cy.stub().resolves(metadataBlockInfoMock)
+
+ cy.customMount(
+
+
+
+ )
cy.fixture('metadataTranslations').then((t) => {
summaryFieldsMock.forEach((metadataBlock) => {
@@ -27,7 +38,11 @@ describe('DatasetSummary', () => {
)
summaryFieldDescription.should('exist')
- const summaryFieldValueString = metadataFieldValueToString(summaryFieldValue)
+ const summaryFieldValueString = metadataFieldValueToString(
+ summaryFieldName,
+ summaryFieldValue,
+ metadataBlockInfoMock
+ )
if (isArrayOfObjects(summaryFieldValue)) {
summaryFieldValueString.split(' \n \n').forEach((fieldValue) => {
diff --git a/tests/component/sections/layout/Layout.spec.tsx b/tests/component/sections/layout/Layout.spec.tsx
index 8acd58cff..23c103928 100644
--- a/tests/component/sections/layout/Layout.spec.tsx
+++ b/tests/component/sections/layout/Layout.spec.tsx
@@ -17,7 +17,7 @@ describe('Layout', () => {
it('renders the header', () => {
cy.customMount()
- cy.findByRole('img', { name: 'Brand Logo Image' }).should('exist')
+ cy.findByAltText('Brand Logo Image').should('exist')
cy.findByText('Dataverse').should('exist')
cy.findByRole('button', { name: 'Toggle navigation' }).click()
diff --git a/tests/e2e-integration/integration/datasets/DatasetJSDataverseRepository.spec.ts b/tests/e2e-integration/integration/datasets/DatasetJSDataverseRepository.spec.ts
index 7c049cf02..0d9dd37ba 100644
--- a/tests/e2e-integration/integration/datasets/DatasetJSDataverseRepository.spec.ts
+++ b/tests/e2e-integration/integration/datasets/DatasetJSDataverseRepository.spec.ts
@@ -79,7 +79,7 @@ describe('Dataset JSDataverse Repository', () => {
}
const datasetExpected = datasetData(dataset.persistentId)
- expect(dataset.title).to.deep.equal(datasetExpected.title)
+ expect(dataset.getTitle()).to.deep.equal(datasetExpected.title)
expect(dataset.citation).to.deep.equal(datasetExpected.citation)
expect(dataset.labels).to.deep.equal(datasetExpected.labels)
expect(dataset.license).to.deep.equal(datasetExpected.license)
@@ -104,7 +104,7 @@ describe('Dataset JSDataverse Repository', () => {
const datasetExpected = datasetData(dataset.persistentId)
const newVersion = new DatasetVersion(1, 0, DatasetStatus.RELEASED)
- expect(dataset.title).to.deep.equal(datasetExpected.title)
+ expect(dataset.getTitle()).to.deep.equal(datasetExpected.title)
expect(dataset.version).to.deep.equal(newVersion)
})
})
@@ -120,7 +120,7 @@ describe('Dataset JSDataverse Repository', () => {
}
const datasetExpected = datasetData(dataset.persistentId)
- expect(dataset.title).to.deep.equal(datasetExpected.title)
+ expect(dataset.getTitle()).to.deep.equal(datasetExpected.title)
expect(dataset.version).to.deep.equal(datasetExpected.version)
})
})
@@ -135,7 +135,7 @@ describe('Dataset JSDataverse Repository', () => {
}
const datasetExpected = datasetData(dataset.persistentId)
- expect(dataset.title).to.deep.equal(datasetExpected.title)
+ expect(dataset.getTitle()).to.deep.equal(datasetExpected.title)
expect(dataset.version).to.deep.equal(datasetExpected.version)
})
})