From 065fa86328ce048341eb835e9e8c4ebe213bd4db Mon Sep 17 00:00:00 2001 From: Juan Pablo Tosca Villanueva Date: Fri, 10 Apr 2026 14:33:35 -0400 Subject: [PATCH 1/6] Import from v1 --- public/locales/en/createDataset.json | 7 ++ public/locales/en/editDatasetMetadata.json | 5 +- .../hooks/useGetAvailableDatasetTypes.ts | 56 +++++++++ src/dataset/domain/models/Dataset.ts | 10 +- src/dataset/domain/models/DatasetType.ts | 7 ++ .../useCases/getAvailableDatasetTypes.ts | 8 ++ .../DatasetTypeSelect.module.scss | 110 ++++++++++++++++++ .../dataset-type-select/DatasetTypeSelect.tsx | 92 +++++++++++++++ .../domain/models/DatasetTypeMother.ts | 19 +++ 9 files changed, 310 insertions(+), 4 deletions(-) create mode 100644 src/dataset/domain/hooks/useGetAvailableDatasetTypes.ts create mode 100644 src/dataset/domain/models/DatasetType.ts create mode 100644 src/dataset/domain/useCases/getAvailableDatasetTypes.ts create mode 100644 src/sections/create-dataset/dataset-type-select/DatasetTypeSelect.module.scss create mode 100644 src/sections/create-dataset/dataset-type-select/DatasetTypeSelect.tsx create mode 100644 tests/component/dataset/domain/models/DatasetTypeMother.ts diff --git a/public/locales/en/createDataset.json b/public/locales/en/createDataset.json index d9900dd7c..a7ee61f29 100644 --- a/public/locales/en/createDataset.json +++ b/public/locales/en/createDataset.json @@ -11,5 +11,12 @@ "label": "Dataset Template", "description": "The dataset template which prepopulates info into the form automatically.", "helpText": "Changing the template will clear any fields you may have entered data into." + }, + "datasetType": { + "label": "Dataset Type", + "description": "The type of dataset you are creating.", + "helpText": "Changing the dataset type will clear any fields you may have entered data into.", + "placeholder": "Select a dataset type", + "toggleMenu": "Toggle dataset types options menu" } } diff --git a/public/locales/en/editDatasetMetadata.json b/public/locales/en/editDatasetMetadata.json index ee406b0da..473dacf61 100644 --- a/public/locales/en/editDatasetMetadata.json +++ b/public/locales/en/editDatasetMetadata.json @@ -8,5 +8,8 @@ "label": "Host Collection", "description": "The collection which contains this data." }, - "metadata": "Metadata" + "metadata": "Metadata", + "datasetType": { + "label": "Dataset Type" + } } diff --git a/src/dataset/domain/hooks/useGetAvailableDatasetTypes.ts b/src/dataset/domain/hooks/useGetAvailableDatasetTypes.ts new file mode 100644 index 000000000..16f6e34bd --- /dev/null +++ b/src/dataset/domain/hooks/useGetAvailableDatasetTypes.ts @@ -0,0 +1,56 @@ +import { useCallback, useEffect, useState } from 'react' +import { ReadError } from '@iqss/dataverse-client-javascript' +import { JSDataverseReadErrorHandler } from '@/shared/helpers/JSDataverseReadErrorHandler' +import { DatasetRepository } from '../repositories/DatasetRepository' +import { getAvailableDatasetTypes } from '../useCases/getAvailableDatasetTypes' +import { DatasetType } from '../models/DatasetType' + +interface useGetAvailableDatasetTypesProps { + datasetRepository: DatasetRepository + autoFetch?: boolean +} + +export const useGetAvailableDatasetTypes = ({ + datasetRepository, + autoFetch = true +}: useGetAvailableDatasetTypesProps) => { + const [datasetTypes, setDatasetTypes] = useState([]) + const [isLoadingDatasetTypes, setIsLoadingDatasetTypes] = useState(autoFetch) + const [errorGetDatasetTypes, setErrorGetDatasetTypes] = useState(null) + + const fetchDatasetTypes = useCallback(async () => { + setIsLoadingDatasetTypes(true) + setErrorGetDatasetTypes(null) + + try { + const response: DatasetType[] = await getAvailableDatasetTypes(datasetRepository) + + setDatasetTypes(response) + } catch (err) { + if (err instanceof ReadError) { + const error = new JSDataverseReadErrorHandler(err) + const formattedError = + error.getReasonWithoutStatusCode() ?? /* istanbul ignore next */ error.getErrorMessage() + + setErrorGetDatasetTypes(formattedError) + } else { + setErrorGetDatasetTypes('Something went wrong getting the dataset types. Try again later.') + } + } finally { + setIsLoadingDatasetTypes(false) + } + }, [datasetRepository]) + + useEffect(() => { + if (autoFetch) { + void fetchDatasetTypes() + } + }, [autoFetch, fetchDatasetTypes]) + + return { + datasetTypes, + isLoadingDatasetTypes, + errorGetDatasetTypes, + fetchDatasetTypes + } +} diff --git a/src/dataset/domain/models/Dataset.ts b/src/dataset/domain/models/Dataset.ts index 19c9935a2..e0b0af7f7 100644 --- a/src/dataset/domain/models/Dataset.ts +++ b/src/dataset/domain/models/Dataset.ts @@ -438,7 +438,8 @@ export class Dataset { public readonly nextMajorVersion?: string, public readonly nextMinorVersion?: string, public readonly requiresMajorVersionUpdate?: boolean, - public readonly fileStore?: string + public readonly fileStore?: string, + public readonly datasetType?: string ) {} public checkIsLockedFromPublishing(userPersistentId: string): boolean { @@ -533,7 +534,9 @@ export class Dataset { public readonly nextMajorVersionNumber?: string, public readonly nextMinorVersionNumber?: string, public readonly requiresMajorVersionUpdate?: boolean, - public readonly fileStore?: string + public readonly fileStore?: string, + public readonly datasetType?: string + ) { this.withAlerts() } @@ -605,7 +608,8 @@ export class Dataset { this.nextMajorVersionNumber, this.nextMinorVersionNumber, this.requiresMajorVersionUpdate, - this.fileStore + this.fileStore, + this.datasetType ) } } diff --git a/src/dataset/domain/models/DatasetType.ts b/src/dataset/domain/models/DatasetType.ts new file mode 100644 index 000000000..d8e02e180 --- /dev/null +++ b/src/dataset/domain/models/DatasetType.ts @@ -0,0 +1,7 @@ +export interface DatasetType { + id: number + name: string + description: string + linkedMetadataBlocks?: string[] + availableLicenses?: string[] +} diff --git a/src/dataset/domain/useCases/getAvailableDatasetTypes.ts b/src/dataset/domain/useCases/getAvailableDatasetTypes.ts new file mode 100644 index 000000000..926a42f58 --- /dev/null +++ b/src/dataset/domain/useCases/getAvailableDatasetTypes.ts @@ -0,0 +1,8 @@ +import { DatasetRepository } from '../repositories/DatasetRepository' +import { DatasetType } from '@iqss/dataverse-client-javascript' + +export function getAvailableDatasetTypes( + datasetRepository: DatasetRepository +): Promise { + return datasetRepository.getAvailableDatasetTypes() +} diff --git a/src/sections/create-dataset/dataset-type-select/DatasetTypeSelect.module.scss b/src/sections/create-dataset/dataset-type-select/DatasetTypeSelect.module.scss new file mode 100644 index 000000000..160336305 --- /dev/null +++ b/src/sections/create-dataset/dataset-type-select/DatasetTypeSelect.module.scss @@ -0,0 +1,110 @@ +@use 'sass:color'; +@import 'node_modules/@iqss/dataverse-design-system/src/lib/assets/styles/design-tokens/colors.module'; + +.dataset-type-select { + position: relative; + + .toggle { + position: relative; + display: grid; + background-color: #fff; + + // Chevron icon + &::after { + position: absolute; + top: 50%; + right: 1rem; + display: inline-block; + width: 0.45em; + height: 0.45em; + border-color: rgb(0 0 0 / 75%); + border-style: solid; + border-width: 2px 2px 0 0; + transform: translateY(-60%) rotate(-225deg); + content: ''; + } + + > input[type='button'] { + position: relative; + z-index: 1; + display: flex; + grid-area: 1 / 1; + align-items: center; + justify-content: space-between; + width: 100%; + padding: var(--toggle-padding); + background-color: transparent; + border: solid 1px $dv-secondary-color; + border-radius: 6px; + cursor: pointer; + transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + + &::after { + display: none; + } + + &:focus-within, + &:focus { + border-color: color.adjust($dv-primary-color, $alpha: -0.4); + outline: 0; + box-shadow: 0 0 0 0.25rem color.adjust($dv-primary-color, $alpha: -0.7); + } + } + + > span { + position: relative; + z-index: 2; + grid-area: 1 / 1; + padding: var(--toggle-padding); + pointer-events: none; + + .single-selected-option { + margin: 0; + } + } + } + + .menu { + position: absolute; + top: calc(100% + 5px); + left: 0; + z-index: 120; + display: flex; + flex-direction: column; + gap: 0.5rem; + width: 100%; + background: #fff; + max-width: 100%; + max-height: 300px; + padding: 0.5rem; + overflow-x: hidden; + overflow-y: auto; + border: 1px solid #ddd; + border-radius: 6px; + box-shadow: 0 5px 10px rgb(0 0 0 / 15%); + opacity: 0; + transform: translateY(-6px) scale(0.98); + pointer-events: none; + + &.open { + opacity: 1; + transform: translateY(0) scale(1); + pointer-events: auto; + } + + .type-option { + cursor: pointer; + transition: all 0.3s ease; + + &:hover, + &.selected { + background: color.adjust($dv-primary-color, $alpha: -0.9); + border: solid 1px $dv-primary-color; + } + + &:active { + background: color.adjust($dv-primary-color, $alpha: -0.6); + } + } + } +} diff --git a/src/sections/create-dataset/dataset-type-select/DatasetTypeSelect.tsx b/src/sections/create-dataset/dataset-type-select/DatasetTypeSelect.tsx new file mode 100644 index 000000000..7989bd643 --- /dev/null +++ b/src/sections/create-dataset/dataset-type-select/DatasetTypeSelect.tsx @@ -0,0 +1,92 @@ +import { useState, useRef, useEffect } from 'react' +import { useTranslation } from 'react-i18next' +import cn from 'classnames' +import { Card, Col, Form } from '@iqss/dataverse-design-system' +import { DatasetType } from '@/dataset/domain/models/DatasetType' +import styles from './DatasetTypeSelect.module.scss' + +interface DatasetTypeSelectProps { + datasetTypes: DatasetType[] + onChange: (selectedTypeId: string) => void + selectedType: DatasetType +} + +export const DatasetTypeSelect = ({ + datasetTypes, + onChange, + selectedType +}: DatasetTypeSelectProps) => { + const { t } = useTranslation('createDataset') + const [isOpen, setIsOpen] = useState(false) + const dropdownRef = useRef(null) + + const handleSelectType = (typeId: number) => { + onChange(typeId.toString()) + setIsOpen(false) + } + + // Close menu when clicking outside, focusing outside, or pressing Escape + useEffect(() => { + const handleClose = (event: MouseEvent | FocusEvent) => { + if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) { + setIsOpen(false) + } + } + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key === 'Escape') setIsOpen(false) + } + + document.addEventListener('mousedown', handleClose) + document.addEventListener('focusin', handleClose) + document.addEventListener('keydown', handleKeyDown) + return () => { + document.removeEventListener('mousedown', handleClose) + document.removeEventListener('focusin', handleClose) + document.removeEventListener('keydown', handleKeyDown) + } + }, []) + + return ( + + + {t('datasetType.label')} + + + {t('datasetType.helpText')} + +
+
+ setIsOpen((prev) => !prev)} + aria-label={t('datasetType.toggleMenu')} + /> + + {selectedType.name} + +
+ +
+ {datasetTypes.map((dt) => ( + handleSelectType(dt.id)} + tabIndex={0} + key={dt.id}> + + + {dt.name} +
+ {dt.description} +
+
+
+ ))} +
+
+ +
+ ) +} diff --git a/tests/component/dataset/domain/models/DatasetTypeMother.ts b/tests/component/dataset/domain/models/DatasetTypeMother.ts new file mode 100644 index 000000000..10c093572 --- /dev/null +++ b/tests/component/dataset/domain/models/DatasetTypeMother.ts @@ -0,0 +1,19 @@ +import { faker } from '@faker-js/faker' +import { DatasetType } from '@/dataset/domain/models/DatasetType' + +export class DatasetTypeMother { + static createMany(count: number, props?: Partial): DatasetType[] { + return Array.from({ length: count }, () => this.create(props)) + } + static create(props?: Partial): DatasetType { + return { + id: faker.datatype.number({ min: 1 }), + name: faker.lorem.words(3), + ...props + } + } + + static creatDefaultDatasetType(): DatasetType { + return this.create({ id: 1, name: 'dataset', linkedMetadataBlocks: [], availableLicenses: [] }) + } +} From 74a8a1fa61f6405d3709ba10a7e315840a6c12e2 Mon Sep 17 00:00:00 2001 From: Juan Pablo Tosca Villanueva Date: Fri, 10 Apr 2026 14:34:21 -0400 Subject: [PATCH 2/6] Update from js dataverse type --- src/dataset/domain/models/DatasetType.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/dataset/domain/models/DatasetType.ts b/src/dataset/domain/models/DatasetType.ts index d8e02e180..028686a4a 100644 --- a/src/dataset/domain/models/DatasetType.ts +++ b/src/dataset/domain/models/DatasetType.ts @@ -1,7 +1,8 @@ export interface DatasetType { id: number name: string - description: string + displayName: string linkedMetadataBlocks?: string[] availableLicenses?: string[] -} + description?: string +} \ No newline at end of file From df5e2844237187d8b436be75e68494c351fba7c7 Mon Sep 17 00:00:00 2001 From: Juan Pablo Tosca Villanueva Date: Fri, 10 Apr 2026 16:09:34 -0400 Subject: [PATCH 3/6] Update from js dataverse type --- .../domain/repositories/DatasetRepository.ts | 8 +++- src/dataset/domain/useCases/createDataset.ts | 5 ++- .../infrastructure/mappers/JSDatasetMapper.ts | 6 ++- .../DatasetJSDataverseRepository.ts | 20 +++++++-- .../MetadataBlockInfoRepository.ts | 8 +++- ...OnCreateMetadataBlockInfoByCollectionId.ts | 5 ++- .../getMetadataBlockInfoByCollectionId.ts | 14 +++--- .../MetadataBlockInfoJSDataverseRepository.ts | 25 ++++++++--- src/sections/create-dataset/CreateDataset.tsx | 45 ++++++++++++++++++- 9 files changed, 111 insertions(+), 25 deletions(-) diff --git a/src/dataset/domain/repositories/DatasetRepository.ts b/src/dataset/domain/repositories/DatasetRepository.ts index 1bd783499..0fcc42243 100644 --- a/src/dataset/domain/repositories/DatasetRepository.ts +++ b/src/dataset/domain/repositories/DatasetRepository.ts @@ -12,6 +12,7 @@ import { DatasetLicenseUpdateRequest } from '../models/DatasetLicenseUpdateReque import { CollectionSummary } from '@/collection/domain/models/CollectionSummary' import { DatasetVersionPaginationInfo } from '../models/DatasetVersionPaginationInfo' import { DatasetUploadLimits } from '../models/DatasetUploadLimits' +import { DatasetType } from '../models/DatasetType' export interface DatasetRepository { getByPersistentId: ( @@ -29,7 +30,11 @@ export interface DatasetRepository { includeDeaccessioned: boolean ) => Promise - create: (dataset: DatasetDTO, collectionId: string) => Promise<{ persistentId: string }> + create: ( + dataset: DatasetDTO, + collectionId: string, + datasetType?: DatasetType + ) => Promise<{ persistentId: string }> updateMetadata: ( datasetId: string | number, datasetDTO: DatasetDTO, @@ -70,4 +75,5 @@ export interface DatasetRepository { unlink(datasetId: string | number, collectionIdOrAlias: string | number): Promise getDatasetLinkedCollections: (datasetId: string | number) => Promise getDatasetUploadLimits: (datasetId: string | number) => Promise + getAvailableDatasetTypes: () => Promise } diff --git a/src/dataset/domain/useCases/createDataset.ts b/src/dataset/domain/useCases/createDataset.ts index abe0a943f..bc231855c 100644 --- a/src/dataset/domain/useCases/createDataset.ts +++ b/src/dataset/domain/useCases/createDataset.ts @@ -4,9 +4,10 @@ import { DatasetDTO } from './DTOs/DatasetDTO' export function createDataset( datasetRepository: DatasetRepository, dataset: DatasetDTO, - collectionId: string + collectionId: string, + datasetType?: string ): Promise<{ persistentId: string }> { - return datasetRepository.create(dataset, collectionId).catch((error: Error) => { + return datasetRepository.create(dataset, collectionId, datasetType).catch((error: Error) => { throw new Error(error.message) }) } diff --git a/src/dataset/infrastructure/mappers/JSDatasetMapper.ts b/src/dataset/infrastructure/mappers/JSDatasetMapper.ts index a147285e5..99e615d13 100644 --- a/src/dataset/infrastructure/mappers/JSDatasetMapper.ts +++ b/src/dataset/infrastructure/mappers/JSDatasetMapper.ts @@ -49,7 +49,8 @@ export class JSDatasetMapper { latestPublishedVersionMajorNumber?: number, latestPublishedVersionMinorNumber?: number, datasetVersionDiff?: JSDatasetVersionDiff, - fileStore?: string + fileStore?: string, + datasetType?: string ): Dataset { const version = JSDatasetVersionMapper.toVersion( jsDataset.versionId, @@ -100,7 +101,8 @@ export class JSDatasetMapper { latestPublishedVersionMinorNumber ), JSDatasetMapper.toRequiresMajorVersionUpdate(datasetVersionDiff), - fileStore + fileStore, + datasetType ).build() } diff --git a/src/dataset/infrastructure/repositories/DatasetJSDataverseRepository.ts b/src/dataset/infrastructure/repositories/DatasetJSDataverseRepository.ts index a26660169..f4044a70e 100644 --- a/src/dataset/infrastructure/repositories/DatasetJSDataverseRepository.ts +++ b/src/dataset/infrastructure/repositories/DatasetJSDataverseRepository.ts @@ -44,7 +44,9 @@ import { getDatasetLinkedCollections, updateTermsOfAccess, updateDatasetLicense, - getDatasetUploadLimits + getDatasetUploadLimits, + DatasetType, + getDatasetAvailableDatasetTypes } from '@iqss/dataverse-client-javascript' import { JSDatasetMapper } from '../mappers/JSDatasetMapper' import { DatasetPaginationInfo } from '../../domain/models/DatasetPaginationInfo' @@ -64,6 +66,7 @@ import { AxiosResponse } from 'axios' import { JSDataverseReadErrorHandler } from '@/shared/helpers/JSDataverseReadErrorHandler' import { CollectionSummary } from '@/collection/domain/models/CollectionSummary' import { DatasetUploadLimits } from '@/dataset/domain/models/DatasetUploadLimits' +import { DatasetType } from '@/dataset/domain/models/DatasetType' const includeDeaccessioned = true @@ -269,7 +272,8 @@ export class DatasetJSDataverseRepository implements DatasetRepository { datasetDetails.latestPublishedVersionMajorNumber, datasetDetails.latestPublishedVersionMinorNumber, datasetDetails.datasetVersionDiff, - datasetDetails.fileStore + datasetDetails.fileStore, + datasetDetails.datasetType ) }) .catch((error: ReadError) => { @@ -327,9 +331,13 @@ export class DatasetJSDataverseRepository implements DatasetRepository { }) } - create(dataset: DatasetDTO, collectionId: string): Promise<{ persistentId: string }> { + create( + dataset: DatasetDTO, + collectionId: string, + datasetType?: string + ): Promise<{ persistentId: string }> { return createDataset - .execute(DatasetDTOMapper.toJSDatasetDTO(dataset), collectionId) + .execute(DatasetDTOMapper.toJSDatasetDTO(dataset), collectionId, datasetType) .then((jsDatasetIdentifiers: JSDatasetIdentifiers) => ({ persistentId: jsDatasetIdentifiers.persistentId })) @@ -431,6 +439,10 @@ export class DatasetJSDataverseRepository implements DatasetRepository { return getDatasetLinkedCollections.execute(datasetId) } + getAvailableDatasetTypes: () => Promise = () => { + return getDatasetAvailableDatasetTypes.execute() + } + /* TODO: This is a temporary solution as this use case doesn't exist in js-dataverse yet and the API should also return the file store type rather than name only. After https://github.com/IQSS/dataverse/issues/11695 is implemented, create a js-dataverse use case. diff --git a/src/metadata-block-info/domain/repositories/MetadataBlockInfoRepository.ts b/src/metadata-block-info/domain/repositories/MetadataBlockInfoRepository.ts index 4b5044051..e4d827288 100644 --- a/src/metadata-block-info/domain/repositories/MetadataBlockInfoRepository.ts +++ b/src/metadata-block-info/domain/repositories/MetadataBlockInfoRepository.ts @@ -8,8 +8,12 @@ export interface MetadataBlockInfoRepository { getByName: (name: string) => Promise getAll: () => Promise getDisplayedOnCreateByCollectionId: ( - collectionId: number | string + collectionId: number | string, + datasetType?: string + ) => Promise + getByCollectionId: ( + collectionId: number | string, + datasetType?: string ) => Promise - getByCollectionId: (collectionId: number | string) => Promise getAllFacetableMetadataFields: () => Promise } diff --git a/src/metadata-block-info/domain/useCases/getDisplayedOnCreateMetadataBlockInfoByCollectionId.ts b/src/metadata-block-info/domain/useCases/getDisplayedOnCreateMetadataBlockInfoByCollectionId.ts index 3fede920f..da9c676c8 100644 --- a/src/metadata-block-info/domain/useCases/getDisplayedOnCreateMetadataBlockInfoByCollectionId.ts +++ b/src/metadata-block-info/domain/useCases/getDisplayedOnCreateMetadataBlockInfoByCollectionId.ts @@ -3,10 +3,11 @@ import { MetadataBlockInfoRepository } from '../repositories/MetadataBlockInfoRe export async function getDisplayedOnCreateMetadataBlockInfoByCollectionId( metadataBlockInfoRepository: MetadataBlockInfoRepository, - collectionId: number | string + collectionId: number | string, + datasetType?: string ): Promise { return metadataBlockInfoRepository - .getDisplayedOnCreateByCollectionId(collectionId) + .getDisplayedOnCreateByCollectionId(collectionId, datasetType) .catch((error: Error) => { throw new Error(error.message) }) diff --git a/src/metadata-block-info/domain/useCases/getMetadataBlockInfoByCollectionId.ts b/src/metadata-block-info/domain/useCases/getMetadataBlockInfoByCollectionId.ts index ab3fba345..cb6501949 100644 --- a/src/metadata-block-info/domain/useCases/getMetadataBlockInfoByCollectionId.ts +++ b/src/metadata-block-info/domain/useCases/getMetadataBlockInfoByCollectionId.ts @@ -3,9 +3,13 @@ import { MetadataBlockInfoRepository } from '../repositories/MetadataBlockInfoRe export async function getMetadataBlockInfoByCollectionId( metadataBlockInfoRepository: MetadataBlockInfoRepository, - collectionId: number | string + collectionId: number | string, + onlyDisplayedOnCreate?: boolean, + datasetType?: string ): Promise { - return metadataBlockInfoRepository.getByCollectionId(collectionId).catch((error: Error) => { - throw new Error(error.message) - }) -} + return metadataBlockInfoRepository + .getByCollectionId(collectionId, onlyDisplayedOnCreate, datasetType) + .catch((error: Error) => { + throw new Error(error.message) + }) +} \ No newline at end of file diff --git a/src/metadata-block-info/infrastructure/repositories/MetadataBlockInfoJSDataverseRepository.ts b/src/metadata-block-info/infrastructure/repositories/MetadataBlockInfoJSDataverseRepository.ts index baa46e3d3..fb49676da 100644 --- a/src/metadata-block-info/infrastructure/repositories/MetadataBlockInfoJSDataverseRepository.ts +++ b/src/metadata-block-info/infrastructure/repositories/MetadataBlockInfoJSDataverseRepository.ts @@ -37,9 +37,13 @@ export class MetadataBlockInfoJSDataverseRepository implements MetadataBlockInfo }) } - getByCollectionId(collectionIdOrAlias: number | string): Promise { + getByCollectionId( + collectionIdOrAlias: number | string, + onlyDisplayedOnCreate?: boolean, + datasetType?: string + ): Promise { return getCollectionMetadataBlocks - .execute(collectionIdOrAlias) + .execute(collectionIdOrAlias, onlyDisplayedOnCreate, datasetType) .then((metadataBlocks: MetadataBlockInfo[]) => { return metadataBlocks }) @@ -49,12 +53,23 @@ export class MetadataBlockInfoJSDataverseRepository implements MetadataBlockInfo } getDisplayedOnCreateByCollectionId( - collectionIdOrAlias: number | string + collectionIdOrAlias: number | string, + datasetType?: string ): Promise { return getCollectionMetadataBlocks - .execute(collectionIdOrAlias, true) + .execute(collectionIdOrAlias, true, datasetType) .then((metadataBlocks: MetadataBlockInfo[]) => { - return metadataBlocks + const metadataBlocksWithFields: MetadataBlockInfo[] = [] + metadataBlocks.forEach((block) => { + const numFields = Object.keys(block.metadataFields).length + // numFields can be zero if you pass a datasetType that's linked to + // a metadata block that doesn't have any fields set to displayOnCreate. + // See https://github.com/IQSS/dataverse/blob/v6.7.1/src/test/java/edu/harvard/iq/dataverse/api/DatasetTypesIT.java#L512 + if (numFields > 0) { + metadataBlocksWithFields.push(block) + } + }) + return metadataBlocksWithFields }) .catch((error: ReadError) => { throw new Error(error.message) diff --git a/src/sections/create-dataset/CreateDataset.tsx b/src/sections/create-dataset/CreateDataset.tsx index ab41d17e8..da2b33d1f 100644 --- a/src/sections/create-dataset/CreateDataset.tsx +++ b/src/sections/create-dataset/CreateDataset.tsx @@ -19,6 +19,9 @@ import { type Template } from '@/templates/domain/models/Template' import { DatasetTemplateSelect } from './dataset-template-select/DatasetTemplateSelect' import { TemplateRepository } from '@/templates/domain/repositories/TemplateRepository' import { useCollectionRepositories } from '@/shared/contexts/repositories/RepositoriesProvider' +import { useGetAvailableDatasetTypes } from '@/dataset/domain/hooks/useGetAvailableDatasetTypes' +import { DatasetType } from '@/dataset/domain/models/DatasetType' +import { DatasetTypeSelect } from './dataset-type-select/DatasetTypeSelect' interface CreateDatasetProps { datasetRepository: DatasetRepository @@ -38,12 +41,15 @@ export function CreateDataset({ const { isModalOpen, hideModal } = useNotImplementedModal() const { setIsLoading } = useLoading() const [selectedTemplate, setSelectedTemplate] = useState