Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
99d76cc
feature: edit template and table
ChengShi-1 Jan 9, 2026
4e9cfbf
feature: delete and view a template
ChengShi-1 Jan 9, 2026
8019647
Merge branch 'RestructureGetTemplates' into TemplateUI
ChengShi-1 Jan 13, 2026
9e503bb
feature: create Template (only metadata/no terms page here)
ChengShi-1 Jan 13, 2026
daaa730
feature: view Template button, add request access
ChengShi-1 Jan 14, 2026
39ba7b8
feature: create template navigate to edit terms
ChengShi-1 Jan 14, 2026
ce50d9a
feature: create template skeleton
ChengShi-1 Jan 14, 2026
3745c59
chore: renaming
ChengShi-1 Jan 14, 2026
05980e1
feature: storybooks
ChengShi-1 Jan 14, 2026
4ef4093
chore: lint error
ChengShi-1 Jan 14, 2026
45c899a
chore: changelog
ChengShi-1 Jan 14, 2026
50d925d
feature: add some unit tests
ChengShi-1 Jan 14, 2026
3e92339
Merge branch 'RestructureGetTemplates' into TemplateUI
ChengShi-1 Jan 15, 2026
cbe7535
chore: some fixes on path
ChengShi-1 Jan 15, 2026
62a8ac6
fix: edit permission and tests
ChengShi-1 Jan 15, 2026
7b404d6
chore: lint error
ChengShi-1 Jan 15, 2026
c435180
test: add more tests
ChengShi-1 Jan 20, 2026
749a9ab
chore: do some clean on code
ChengShi-1 Jan 20, 2026
28a0215
fix: github reviews
ChengShi-1 Jan 20, 2026
f02ac61
chore: lint error
ChengShi-1 Jan 20, 2026
992303d
chore: test error
ChengShi-1 Jan 20, 2026
233360b
chore: e2e test error
ChengShi-1 Jan 21, 2026
b7f8497
FIX: breadcrumb
ChengShi-1 Jan 21, 2026
beb8968
Feat: copy a template func, and its tests
ChengShi-1 Jan 22, 2026
f47cd29
feat: custom instruction fields
ChengShi-1 Jan 27, 2026
15ac1ec
feat: required fields change
ChengShi-1 Jan 27, 2026
bbb5547
fix: unit test error
ChengShi-1 Jan 28, 2026
f274281
fix: requiredFields error in primitive type
ChengShi-1 Jan 29, 2026
d22429b
fix: delete button
ChengShi-1 Jan 29, 2026
9d4d3c7
fix: changes on TemplateInfo based on copilot review
ChengShi-1 Jan 30, 2026
dbe26db
feat: show custom instruction in preview
ChengShi-1 Feb 3, 2026
b524abc
fix: custom instruction layout
ChengShi-1 Feb 4, 2026
a1fd12e
fix: remove only
ChengShi-1 Feb 4, 2026
eee4713
Merge branch 'develop' into TemplateUI
ChengShi-1 Feb 4, 2026
2c3d4f1
fix: test coverage
ChengShi-1 Feb 5, 2026
2e0d904
Merge branch 'develop' into TemplateUI
ChengShi-1 Feb 5, 2026
7c1e54f
fix: increase test coverage
ChengShi-1 Feb 5, 2026
7e79eaf
fix: test error
ChengShi-1 Feb 6, 2026
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 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ This changelog follows the principles of [Keep a Changelog](https://keepachangel
### Added

- Added the value entered by the user in the error messages for metadata field validation errors in EMAIL and URL type fields. For example, instead of showing “Point of Contact E-mail is not a valid email address.“, we now show “Point of Contact E-mail foo is not a valid email address.”
- Dataset Templates UI integration, including create/edit flows, previews, and skeleton states.
- Contact Owner button in File Page.
- Share button in File Page.
- Link Collection and Link Dataset features.
Expand Down
2 changes: 1 addition & 1 deletion cypress.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export default defineConfig({
],
defaultLanguage: 'en',
codeCoverage: {
exclude: ['tests/**/*.*', '**/ErrorPage.tsx']
exclude: ['tests/**/*.*', '**/ErrorPage.tsx', '**/EditGuestBook.tsx']
}
}
})
1 change: 1 addition & 0 deletions public/locales/en/collection.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"editCollection": {
"edit": "Edit",
"generalInfo": "General Information",
"datasetTemplates": "Dataset Templates",
"deleteCollection": "Delete Collection"
},
"featuredItems": {
Expand Down
96 changes: 96 additions & 0 deletions public/locales/en/datasetTemplates.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
{
"pageTitle": "Dataset Templates",
"infoAlert": {
"title": "Manage Dataset Templates",
"text": "Create a template prefilled with metadata fields standard values, such as Author Affiliation, or add instructions in the metadata fields to give depositors more information on what metadata is expected."
},
"actions": {
"create": "Create Dataset Template",
"makeDefault": "Make Default",
"default": "Default",
"view": "View",
"copy": "Copy",
"edit": "Edit Template",
"delete": "Delete",
"deleteDisabledTip": "This template is already used by datasets and cannot be deleted."
},
"filters": {
"includeTemplatesFromRoot": "Include Templates from {{root}}"
},
"table": {
"name": "Template Name",
"created": "Date Created",
"usage": "Usage",
"action": "Action",
"templateCreatedAt": "Template created at {{alias}}"
},
"emptyState": {
"whyTitle": "Why Use Templates?",
"whyBullets": [
"Templates are useful when you have several datasets that have the same information in multiple metadata fields that you would prefer not to have to keep manually typing in.",
"Templates can be used to input instructions for those uploading datasets into your dataverse if you have a specific way you want a metadata field to be filled out."
],
"howTitle": "How To Use Templates?",
"howBullets": [
"Templates are created at the dataverse level, can be deleted (so it does not show for future datasets), set to default (not required), and can be copied so you do not have to start over when creating a new template with similar metadata from another template. When a template is deleted, it does not impact the datasets that have used the template already."
],
"howNote": "Please note that the ability to choose which metadata fields are hidden, required, or optional is done on the <anchor>General Information</anchor> page for this dataverse.",
"footer": "To get started, click on the Create Dataset Template button above. To learn more about templates, visit the <anchor>Dataset Templates</anchor> section of the User Guide."
},
"deleteModal": {
"title": "Delete Template",
"message": "Are you sure you want to delete this template? A new dataset will not be able to use this template."
},
"alerts": {
"deleteSuccess": "Template deleted.",
"deleteError": "Something went wrong deleting the template. Try again later.",
"copySuccess": "Template copied.",
"copyError": "Something went wrong copying the template. Try again later."
},
"copyNamePrefix": "copy {{name}}",
"preview": {
"title": "Dataset Template Preview",
"templateLabel": "Dataset Template",
"sections": {
"metadata": "Citation Metadata",
"terms": "Dataset Terms",
"access": "Restricted Files + Terms of Access"
},
"noMetadata": "No citation metadata is available for this template.",
"error": "Something went wrong loading the template preview. Please try again."
},
"createTemplate": {
"pageTitle": "Create Dataset Template",
"breadcrumb": "Create",
"templateName": "Template Name",
"requiredInfo": "Asterisks indicate metadata fields that users will be required to fill out while adding a dataset to this dataverse.",
"citationMissing": "Citation metadata is not available for this template.",
"saveAddTerms": "Save + Add Terms",
"cancel": "Cancel",
"alerts": {
"success": "Success! Template has been created."
},
"errors": {
"nameRequired": "Please add in a name for the dataset template.",
"saveFailed": "Something went wrong creating the template. Try again later."
},
"customInstructions": {
"label": "Custom Instructions:",
"none": "(None - click to add)",
"addAria": "Add custom instructions",
"editAria": "Edit custom instructions",
"inputAriaLabel": "Custom instructions",
"save": "Save",
"cancel": "Cancel"
},
"terms": {
"datasetTermsTitle": "Dataset Terms",
"licenseLabel": "License/Data Use Agreement",
"restrictedTitle": "Restricted Files + Terms of Access",
"requestAccessLabel": "Request Access",
"requestAccessHelp": "Enable access request",
"termsOfAccessLabel": "Terms of Access for Restricted Files",
"dataAccessPlaceLabel": "Data Access Place"
}
}
}
1 change: 1 addition & 0 deletions public/locales/en/shared.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"files": "Files",
"page": "Page",
"asterisksIndicateRequiredFields": "Asterisks indicate required fields",
"asterisksRequiredDatasetFields": "Asterisks indicate metadata fields that users will be required to fill out while adding a dataset to this dataverse.",
"remove": "Remove",
"add": "Add",
"yes": "Yes",
Expand Down
1 change: 1 addition & 0 deletions public/locales/es/collection.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"editCollection": {
"edit": "Editar",
"generalInfo": "Información general",
"datasetTemplates": "Plantillas de conjuntos de datos",
"deleteCollection": "Eliminar colección"
},
"featuredItems": {
Expand Down
95 changes: 95 additions & 0 deletions public/locales/es/datasetTemplates.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
{
"pageTitle": "Plantillas de conjuntos de datos",
"infoAlert": {
"title": "Gestionar plantillas de conjuntos de datos",
"text": "Cree una plantilla precargada con valores estándar de campos de metadatos, como Afiliación del autor, o agregue instrucciones en los campos de metadatos para dar a los depositantes más información sobre qué metadatos se esperan."
},
"actions": {
"create": "Crear plantilla de conjunto de datos",
"makeDefault": "Hacer predeterminada",
"default": "Predeterminada",
"view": "Ver",
"copy": "Copiar",
"edit": "Editar plantilla",
"delete": "Eliminar"
},
"filters": {
"includeTemplatesFromRoot": "Incluir plantillas de {{root}}"
},
"table": {
"name": "Nombre de la plantilla",
"created": "Fecha de creación",
"usage": "Uso",
"action": "Acción",
"templateCreatedAt": "Plantilla creada en {{alias}}"
},
"emptyState": {
"whyTitle": "¿Por qué usar plantillas?",
"whyBullets": [
"Las plantillas son útiles cuando tienes varios conjuntos de datos que tienen la misma información en múltiples campos de metadatos y preferirías no tener que seguir escribiéndola manualmente.",
"Las plantillas se pueden usar para incluir instrucciones para quienes cargan conjuntos de datos en tu dataverse si tienes una forma específica en la que quieres que se complete un campo de metadatos."
],
"howTitle": "Cómo usar plantillas",
"howBullets": [
"Las plantillas se crean a nivel de dataverse, se pueden eliminar (para que no aparezcan en futuros conjuntos de datos), establecer como predeterminadas (no obligatorias) y copiar para que no tengas que empezar de cero al crear una nueva plantilla con metadatos similares a otra. Cuando se elimina una plantilla, no afecta a los conjuntos de datos que ya la hayan usado."
],
"howNote": "Ten en cuenta que la capacidad de elegir qué campos de metadatos están ocultos, son obligatorios u opcionales se configura en la página de <anchor>Información General</anchor> de este dataverse.",
"footer": "Para comenzar, haz clic en el botón Crear plantilla de conjunto de datos de arriba. Para obtener más información sobre las plantillas, visita la sección <anchor>Plantillas de conjuntos de datos</anchor> de la Guía del usuario."
},
"deleteModal": {
"title": "Eliminar plantilla",
"message": "¿Está seguro de que desea eliminar esta plantilla? Un nuevo conjunto de datos no podrá usar esta plantilla."
},
"alerts": {
"deleteSuccess": "Plantilla eliminada.",
"deleteError": "Algo salió mal al eliminar la plantilla. Inténtelo de nuevo más tarde.",
"copySuccess": "Plantilla copiada.",
"copyError": "Algo salió mal al copiar la plantilla. Inténtelo de nuevo más tarde."
},
"copyNamePrefix": "copia {{name}}",
"preview": {
"title": "Vista previa de plantilla de conjunto de datos",
"templateLabel": "Plantilla de conjunto de datos",
"sections": {
"metadata": "Metadatos de citación",
"terms": "Términos del conjunto de datos",
"access": "Archivos restringidos + términos de acceso"
},
"noMetadata": "No hay metadatos de citación disponibles para esta plantilla.",
"error": "No se pudo cargar la vista previa de la plantilla. Inténtelo de nuevo más tarde."
},
"createTemplate": {
"pageTitle": "Crear plantilla de conjunto de datos",
"breadcrumb": "Crear",
"templateName": "Nombre de la plantilla",
"requiredInfo": "Los asteriscos indican los campos de metadatos que los usuarios deberán completar al agregar un conjunto de datos a este dataverse.",
"citationMissing": "Los metadatos de citación no están disponibles para esta plantilla.",
"saveAddTerms": "Guardar + agregar términos",
"cancel": "Cancelar",
"alerts": {
"success": "¡Éxito! La plantilla ha sido creada."
},
"errors": {
"nameRequired": "Por favor, añade un nombre para la plantilla del conjunto de datos.",
"saveFailed": "Algo salió mal al crear la plantilla. Inténtelo de nuevo más tarde."
},
"customInstructions": {
"label": "Instrucciones personalizadas:",
"none": "(Ninguna: haz clic para añadir)",
"addAria": "Agregar instrucciones personalizadas",
"editAria": "Editar instrucciones personalizadas",
"inputAriaLabel": "Instrucciones personalizadas",
"save": "Guardar",
"cancel": "Cancelar"
},
"terms": {
"datasetTermsTitle": "Términos del conjunto de datos",
"licenseLabel": "Licencia/Acuerdo de uso de datos",
"restrictedTitle": "Archivos restringidos + términos de acceso",
"requestAccessLabel": "Solicitar acceso",
"requestAccessHelp": "Habilitar solicitud de acceso",
"termsOfAccessLabel": "Términos de acceso para archivos restringidos",
"dataAccessPlaceLabel": "Lugar de acceso a los datos"
}
}
}
1 change: 1 addition & 0 deletions public/locales/es/shared.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"files": "Ficheros",
"page": "Página",
"asterisksIndicateRequiredFields": "Los asteriscos indican los campos obligatorios",
"asterisksRequiredDatasetFields": "Los asteriscos indican los campos de metadatos que los usuarios deberán completar al agregar un conjunto de datos a este dataverse.",
"remove": "Eliminar",
"add": "Agregar",
"yes": "Sí",
Expand Down
4 changes: 2 additions & 2 deletions src/dataset/domain/useCases/DTOs/DatasetDTO.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ export interface DatasetMetadataBlockValuesDTO {
fields: DatasetMetadataFieldsDTO
}

type DatasetMetadataFieldsDTO = Record<string, DatasetMetadataFieldValueDTO>
export type DatasetMetadataFieldsDTO = Record<string, DatasetMetadataFieldValueDTO>

type DatasetMetadataFieldValueDTO =
export type DatasetMetadataFieldValueDTO =
| string
| string[]
| DatasetMetadataChildFieldValueDTO
Expand Down
6 changes: 1 addition & 5 deletions src/dataset/domain/useCases/updateDatasetLicense.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,5 @@ export function updateDatasetLicense(
datasetId: string | number,
licenseUpdateRequest: DatasetLicenseUpdateRequest
): Promise<void> {
return datasetRepository
.updateDatasetLicense(datasetId, licenseUpdateRequest)
.catch((error: Error) => {
throw new Error(error.message)
})
return datasetRepository.updateDatasetLicense(datasetId, licenseUpdateRequest)
}
4 changes: 1 addition & 3 deletions src/dataset/domain/useCases/updateTermsOfAccess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,5 @@ export function updateTermsOfAccess(
datasetId: string | number,
termsOfAccess: TermsOfAccess
): Promise<void> {
return datasetRepository.updateTermsOfAccess(datasetId, termsOfAccess).catch((error: Error) => {
throw new Error(error.message)
})
return datasetRepository.updateTermsOfAccess(datasetId, termsOfAccess)
}
49 changes: 49 additions & 0 deletions src/router/routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,28 @@ const EditFeaturedItems = lazy(() =>
)
)

const DatasetTemplatesPage = lazy(() =>
import('../sections/templates/DatasetTemplatesFactory').then(({ DatasetTemplatesFactory }) => ({
default: () => DatasetTemplatesFactory.create()
}))
)

const CreateTemplatePage = lazy(() =>
import('../sections/templates/create-template/CreateTemplateFactory').then(
({ CreateTemplateFactory }) => ({
default: () => CreateTemplateFactory.create()
})
)
)

const EditDatasetTemplateTermsPage = lazy(() =>
import('../sections/templates/edit-template-terms/EditTemplateTermsFactory').then(
({ EditTemplateTermsFactory }) => ({
default: () => EditTemplateTermsFactory.create()
})
)
)

const ReplaceFile = lazy(() =>
import('../sections/replace-file/ReplaceFileFactory').then(({ ReplaceFileFactory }) => ({
default: () => ReplaceFileFactory.create()
Expand Down Expand Up @@ -292,6 +314,33 @@ export const routes: RouteObject[] = [
),
errorElement: <ErrorPage />
},
{
path: Route.COLLECTION_TEMPLATES,
element: (
<Suspense fallback={<AppLoader />}>
<DatasetTemplatesPage />
</Suspense>
),
errorElement: <ErrorPage />
},
{
path: Route.TEMPLATES_CREATE,
element: (
<Suspense fallback={<AppLoader />}>
<CreateTemplatePage />
</Suspense>
),
errorElement: <ErrorPage />
},
{
path: Route.TEMPLATES_EDIT_TERMS,
element: (
<Suspense fallback={<AppLoader />}>
<EditDatasetTemplateTermsPage />
</Suspense>
),
errorElement: <ErrorPage />
},
{
path: Route.EDIT_FILE_METADATA,
element: (
Expand Down
10 changes: 10 additions & 0 deletions src/sections/Route.enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ export enum Route {
ACCOUNT = '/account',
EDIT_COLLECTION = '/collections/:collectionId/edit',
EDIT_FEATURED_ITEMS = '/collections/:collectionId/edit-featured-items',
COLLECTION_TEMPLATES = '/:collectionId/templates',
TEMPLATES_CREATE = '/:collectionId/templates/create',
TEMPLATES_EDIT_METADATA = '/:collectionId/templates/:templateId/edit/metadata',
TEMPLATES_EDIT_TERMS = '/:collectionId/templates/:templateId/edit/terms',
FEATURED_ITEM = '/featured-item/:parentCollectionId/:featuredItemId',
NOT_FOUND_PAGE = '/404',
AUTH_CALLBACK = '/auth-callback',
Expand All @@ -34,6 +38,12 @@ export const RouteWithParams = {
CREATE_DATASET: (collectionId: string) => `/datasets/${collectionId}/create`,
EDIT_COLLECTION: (collectionId: string) => `/collections/${collectionId}/edit`,
EDIT_FEATURED_ITEMS: (collectionId: string) => `/collections/${collectionId}/edit-featured-items`,
COLLECTION_TEMPLATES: (collectionId: string) => `/${collectionId}/templates`,
TEMPLATES_CREATE: (collectionId: string) => `/${collectionId}/templates/create`,
TEMPLATES_EDIT_METADATA: (collectionId: string, templateId: number | string) =>
`/${collectionId}/templates/${templateId}/edit/metadata`,
TEMPLATES_EDIT_TERMS: (collectionId: string, templateId: number | string) =>
`/${collectionId}/templates/${templateId}/edit/terms`,
EDIT_FILE_METADATA: (
datasetPersistentId: string,
datasetVersion: string,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ export const EditCollectionDropdown = ({
<DropdownButtonItem as={Link} to={RouteWithParams.EDIT_FEATURED_ITEMS(collection.id)}>
{t('featuredItems.title')}
</DropdownButtonItem>
<DropdownButtonItem as={Link} to={RouteWithParams.COLLECTION_TEMPLATES(collection.id)}>
{t('editCollection.datasetTemplates')}
</DropdownButtonItem>

{canCollectionBeDeleted && (
<>
Expand Down
2 changes: 1 addition & 1 deletion src/sections/create-dataset/CreateDataset.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { BreadcrumbsGenerator } from '../shared/hierarchy/BreadcrumbsGenerator'
import { useCollection } from '../collection/useCollection'
import { NotFoundPage } from '../not-found-page/NotFoundPage'
import { CreateDatasetSkeleton } from './CreateDatasetSkeleton'
import { useGetTemplatesByCollectionId } from '@/dataset/domain/hooks/useGetTemplatesByCollectionId'
import { useGetTemplatesByCollectionId } from '@/templates/domain/hooks/useGetTemplatesByCollectionId'
import { type Template } from '@/templates/domain/models/Template'
import { DatasetTemplateSelect } from './dataset-template-select/DatasetTemplateSelect'
import { TemplateRepository } from '@/templates/domain/repositories/TemplateRepository'
Expand Down
Loading
Loading