diff --git a/CHANGELOG.md b/CHANGELOG.md index 863ad93a3..57dd57551 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ This changelog follows the principles of [Keep a Changelog](https://keepachangel ### Added +- Edit Dataset Template Integration: "Edit Template" dropdown on the Dataset Templates listing now opens the Metadata or Terms editor and shows a "Template updated" toast on return. +- External Tools: Added guestbook and terms modal for Dataverse external tools. - Manage Guestbooks page integration, including: - a guestbooks table with sorting, enable/disable actions, preview, and per-guestbook response download - Create Guestbook and Download All Responses actions @@ -25,8 +27,13 @@ This changelog follows the principles of [Keep a Changelog](https://keepachangel ### Fixed +- After saving on either Edit Template tab (Metadata or Terms), the user is redirected to the templates listing with a success toast instead of staying on the edit page. +- Edit Template breadcrumb on the Terms page no longer renders the dataset's "Terms and Guestbook" label (templates have no guestbook). + ### Removed +- Standalone `EditTemplateMetadataFactory` and `EditTemplateTermsFactory` route factories — replaced by a single `EditTemplateFactory` dispatcher that selects the right page based on `editMode`. + --- ## [v0.3.1] -- 2026-04-30 @@ -49,6 +56,7 @@ This changelog follows the principles of [Keep a Changelog](https://keepachangel - Added Notifications tab in Account Page - Added runtime configuration options for homepage branding and support link. - Added an environment variable to docker-compose-dev.yml to hide the OIDC client used in the SPA from the JSF frontend: DATAVERSE_AUTH_OIDC_HIDDEN_JSF: 1 +- Dataset Templates UI integration, including create/edit flows, previews, and skeleton states. - Added a message note to the login page - Download with terms of use and guestbook. - Show terms modal before download when dataset has custom terms, a non-default license (not CC0 1.0), or a guestbook. Draft datasets and dataset editors bypass the modal. diff --git a/public/locales/en/datasetTemplates.json b/public/locales/en/datasetTemplates.json index 7f70cc561..52d7a62eb 100644 --- a/public/locales/en/datasetTemplates.json +++ b/public/locales/en/datasetTemplates.json @@ -45,7 +45,12 @@ "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." + "copyError": "Something went wrong copying the template. Try again later.", + "setDefaultSuccess": "The template has been selected as the default template for this dataverse.", + "setDefaultError": "Something went wrong setting the template as default. Try again later.", + "unsetDefaultSuccess": "The template has been removed as the default template for this dataverse.", + "unsetDefaultError": "Something went wrong removing the default template. Try again later.", + "editSuccess": "Template updated." }, "copyNamePrefix": "copy {{name}}", "preview": { @@ -92,5 +97,24 @@ "termsOfAccessLabel": "Terms of Access for Restricted Files", "dataAccessPlaceLabel": "Data Access Place" } + }, + "editTemplate": { + "metadataPageTitle": "Edit Template Metadata", + "termsPageTitle": "Edit Template Terms", + "actions": { + "metadata": "Metadata", + "terms": "Terms" + }, + "alerts": { + "metadataUpdated": "Template metadata updated.", + "licenseUpdated": "Template license/terms updated.", + "termsOfAccessUpdated": "Template terms of access updated." + }, + "errors": { + "saveMetadataFailed": "Something went wrong updating the template metadata. Try again later.", + "saveLicenseFailed": "Something went wrong updating the template license/terms. Try again later.", + "saveTermsOfAccessFailed": "Something went wrong updating the template terms of access. Try again later.", + "loadingTemplate": "Something went wrong loading the template. Try again later." + } } } diff --git a/public/locales/es/datasetTemplates.json b/public/locales/es/datasetTemplates.json index 13bb0c65d..68ca79305 100644 --- a/public/locales/es/datasetTemplates.json +++ b/public/locales/es/datasetTemplates.json @@ -44,7 +44,12 @@ "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." + "copyError": "Algo salió mal al copiar la plantilla. Inténtelo de nuevo más tarde.", + "setDefaultSuccess": "La plantilla ha sido seleccionada como la plantilla predeterminada para este dataverse.", + "setDefaultError": "Algo salió mal al establecer la plantilla como predeterminada. Inténtelo de nuevo más tarde.", + "unsetDefaultSuccess": "La plantilla ha sido eliminada como la plantilla predeterminada para este dataverse.", + "unsetDefaultError": "Algo salió mal al eliminar la plantilla predeterminada. Inténtelo de nuevo más tarde.", + "editSuccess": "Plantilla actualizada." }, "copyNamePrefix": "copia {{name}}", "preview": { @@ -91,5 +96,24 @@ "termsOfAccessLabel": "Términos de acceso para archivos restringidos", "dataAccessPlaceLabel": "Lugar de acceso a los datos" } + }, + "editTemplate": { + "metadataPageTitle": "Editar metadatos de plantilla", + "termsPageTitle": "Editar términos de plantilla", + "actions": { + "metadata": "Metadatos", + "terms": "Términos" + }, + "alerts": { + "metadataUpdated": "Metadatos de plantilla actualizados.", + "licenseUpdated": "Licencia/términos de plantilla actualizados.", + "termsOfAccessUpdated": "Términos de acceso de plantilla actualizados." + }, + "errors": { + "saveMetadataFailed": "Algo salió mal al actualizar los metadatos de la plantilla. Inténtelo de nuevo más tarde.", + "saveLicenseFailed": "Algo salió mal al actualizar la licencia/términos de la plantilla. Inténtelo de nuevo más tarde.", + "saveTermsOfAccessFailed": "Algo salió mal al actualizar los términos de acceso de la plantilla. Inténtelo de nuevo más tarde.", + "loadingTemplate": "Algo salió mal al cargar la plantilla. Inténtelo de nuevo más tarde." + } } } diff --git a/src/router/routes.tsx b/src/router/routes.tsx index 5d9cbd3bb..c6c17d20a 100644 --- a/src/router/routes.tsx +++ b/src/router/routes.tsx @@ -105,10 +105,10 @@ const CreateTemplatePage = lazy(() => ) ) -const EditDatasetTemplateTermsPage = lazy(() => - import('../sections/templates/edit-template-terms/EditTemplateTermsFactory').then( - ({ EditTemplateTermsFactory }) => ({ - default: () => EditTemplateTermsFactory.create() +const EditDatasetTemplatePage = lazy(() => + import('../sections/templates/edit-template/EditTemplateFactory').then( + ({ EditTemplateFactory }) => ({ + default: () => EditTemplateFactory.create() }) ) ) @@ -363,10 +363,10 @@ export const routes: RouteObject[] = [ errorElement: }, { - path: Route.TEMPLATES_EDIT_TERMS, + path: Route.TEMPLATES_EDIT, element: ( }> - + ), errorElement: diff --git a/src/sections/Route.enum.ts b/src/sections/Route.enum.ts index 642498b6c..9838f6cc9 100644 --- a/src/sections/Route.enum.ts +++ b/src/sections/Route.enum.ts @@ -24,8 +24,7 @@ export enum Route { GUESTBOOKS = '/:collectionId/guestbooks', GUESTBOOKS_CREATE = '/:collectionId/guestbooks/create', TEMPLATES_CREATE = '/:collectionId/templates/create', - TEMPLATES_EDIT_METADATA = '/:collectionId/templates/:templateId/edit/metadata', - TEMPLATES_EDIT_TERMS = '/:collectionId/templates/:templateId/edit/terms', + TEMPLATES_EDIT = '/templates/edit', FEATURED_ITEM = '/featured-item/:parentCollectionId/:featuredItemId', NOT_FOUND_PAGE = '/404', AUTH_CALLBACK = '/auth-callback', @@ -44,10 +43,18 @@ export const RouteWithParams = { GUESTBOOKS: (collectionId: string) => `/${collectionId}/guestbooks`, GUESTBOOKS_CREATE: (collectionId: string) => `/${collectionId}/guestbooks/create`, 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`, + TEMPLATES_EDIT: ( + collectionId: string, + templateId: number | string, + editMode: TemplateEditMode + ) => { + const searchParams = new URLSearchParams({ + [QueryParamKey.ID]: templateId.toString(), + [QueryParamKey.OWNER_ID]: collectionId, + [QueryParamKey.EDIT_MODE]: editMode + }) + return `${Route.TEMPLATES_EDIT}?${searchParams.toString()}` + }, EDIT_FILE_METADATA: ( datasetPersistentId: string, datasetVersion: string, @@ -93,9 +100,17 @@ export enum QueryParamKey { COLLECTION_ID = 'collectionId', TAB = 'tab', FILE_ID = 'id', + ID = 'id', + OWNER_ID = 'ownerId', + EDIT_MODE = 'editMode', DATASET_VERSION = 'datasetVersion', REFERRER = 'referrer', AUTH_STATE = 'state', VALID_TOKEN_BUT_NOT_LINKED_ACCOUNT = 'validTokenButNotLinkedAccount', TOOL_TYPE = 'toolType' } + +export enum TemplateEditMode { + METADATA = 'METADATA', + LICENSE = 'LICENSE' +} diff --git a/src/sections/edit-dataset-terms/edit-terms-of-access/EditTermsOfAccess.tsx b/src/sections/edit-dataset-terms/edit-terms-of-access/EditTermsOfAccess.tsx index bd96bdf24..2d88f98f8 100644 --- a/src/sections/edit-dataset-terms/edit-terms-of-access/EditTermsOfAccess.tsx +++ b/src/sections/edit-dataset-terms/edit-terms-of-access/EditTermsOfAccess.tsx @@ -227,7 +227,7 @@ export function EditTermsOfAccess({ onFormStateChange }: EditTermsOfAccessProps) disabled={isLoading || (!isRequestAccessEnabled && !isTermsOfAccessProvided)}> {isLoading ? tShared('saving') : tShared('saveChanges')} - diff --git a/src/sections/shared/form/TemplateMetadataForm/TemplateForm/index.module.scss b/src/sections/shared/form/TemplateMetadataForm/TemplateForm/index.module.scss index 8c4b6631a..8f5f4dc54 100644 --- a/src/sections/shared/form/TemplateMetadataForm/TemplateForm/index.module.scss +++ b/src/sections/shared/form/TemplateMetadataForm/TemplateForm/index.module.scss @@ -5,10 +5,17 @@ margin-bottom: $spacer; } +.required-field-text { + display: flex; + flex-direction: column; +} + .accordion { margin-top: $spacer; } .form-actions { + display: flex; + gap: 1rem; margin-top: $spacer; } diff --git a/src/sections/shared/form/TemplateMetadataForm/TemplateForm/index.tsx b/src/sections/shared/form/TemplateMetadataForm/TemplateForm/index.tsx index 337072c8d..966b59b13 100644 --- a/src/sections/shared/form/TemplateMetadataForm/TemplateForm/index.tsx +++ b/src/sections/shared/form/TemplateMetadataForm/TemplateForm/index.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from 'react' +import { useEffect, useMemo, useState } from 'react' import { useNavigate } from 'react-router-dom' import { useTranslation } from 'react-i18next' import { FormProvider, useForm } from 'react-hook-form' @@ -20,14 +20,16 @@ import { } from '../../DatasetMetadataForm/MetadataFieldsHelper' import { MetadataBlockFormFields } from '../../DatasetMetadataForm/MetadataForm/MetadataBlockFormFields' import { RequiredFieldText } from '../../RequiredFieldText/RequiredFieldText' -import { RouteWithParams } from '@/sections/Route.enum' +import { RouteWithParams, TemplateEditMode } from '@/sections/Route.enum' import { TemplateRepository } from '@/templates/domain/repositories/TemplateRepository' +import { Template } from '@/templates/domain/models/Template' import { useGetTemplatesByCollectionId } from '@/templates/domain/hooks/useGetTemplatesByCollectionId' import { SubmissionStatus, useSubmitTemplate } from '../useSubmitTemplate' import { TemplateInfo, TemplateInstructionInfo } from '@/templates/domain/models/TemplateInfo' +import { UpdateTemplateMetadataInfo } from '@/templates/domain/models/UpdateTemplateMetadataInfo' import styles from './index.module.scss' -interface TemplateFormProps { +type CommonTemplateFormProps = { collectionId: string templateRepository: TemplateRepository metadataBlocksInfo: MetadataBlockInfo[] @@ -35,21 +37,52 @@ interface TemplateFormProps { metadataFieldsForMapping: Record> } -export const TemplateForm = ({ - collectionId, - templateRepository, - metadataBlocksInfo, - formDefaultValues, - metadataFieldsForMapping -}: TemplateFormProps) => { +type TemplateFormProps = + | (CommonTemplateFormProps & { + mode: 'create' + template?: never + }) + | (CommonTemplateFormProps & { + mode: 'edit' + template: Template + }) + +export const TemplateForm = (props: TemplateFormProps) => { + const { + mode, + collectionId, + templateRepository, + metadataBlocksInfo, + formDefaultValues, + metadataFieldsForMapping + } = props + const template = mode === 'edit' ? props.template : undefined + const { t } = useTranslation('datasetTemplates') + const { t: tShared } = useTranslation('shared') const navigate = useNavigate() const [validationError, setValidationError] = useState(null) - const [templateName, setTemplateName] = useState('') - const [templateInstructions, setTemplateInstructions] = useState< - Record - >({}) - const { submissionStatus, submitError, submitTemplate } = useSubmitTemplate(collectionId) + const [templateName, setTemplateName] = useState(template?.name ?? '') + + const initialInstructionsMap = useMemo>(() => { + if (!template?.instructions) return {} + return template.instructions.reduce>( + (acc, instruction) => { + acc[instruction.instructionField] = instruction + return acc + }, + {} + ) + }, [template]) + + const [templateInstructions, setTemplateInstructions] = + useState>(initialInstructionsMap) + + const submitOptions = + mode === 'edit' && template + ? ({ mode: 'edit', templateRepository, templateId: template.id } as const) + : ({ mode: 'create', templateRepository, collectionId } as const) + const { submissionStatus, submitError, submitTemplate } = useSubmitTemplate(submitOptions) const { fetchDatasetTemplates } = useGetTemplatesByCollectionId({ templateRepository, @@ -75,7 +108,7 @@ export const TemplateForm = ({ }) } - const handleSaveAndAddTerms = () => { + const handleSubmit = () => { if (!templateName.trim()) { setValidationError(t('createTemplate.errors.nameRequired')) return @@ -87,7 +120,7 @@ export const TemplateForm = ({ const formValuesBackToDots = MetadataFieldsHelper.replaceSlashKeysWithDot(formValues) const datasetDto = MetadataFieldsHelper.formatFormValuesToDatasetDTO( formValuesBackToDots, - 'create' + mode === 'edit' ? 'edit' : 'create' ) const templateFields = datasetDto.metadataBlocks.flatMap((metadataBlock) => MetadataFieldsHelper.buildTemplateFieldsFromMetadataValues( @@ -98,6 +131,21 @@ export const TemplateForm = ({ const instructions = Object.values(templateInstructions) + if (mode === 'edit') { + const updatePayload: UpdateTemplateMetadataInfo = { + name: templateName.trim(), + fields: templateFields, + instructions + } + const didSubmit = await submitTemplate(updatePayload) + if (!didSubmit) return + + navigate(RouteWithParams.COLLECTION_TEMPLATES(collectionId), { + state: { fromEditTemplate: true } + }) + return + } + const templatePayload: TemplateInfo = { name: templateName.trim(), fields: templateFields, @@ -110,21 +158,27 @@ export const TemplateForm = ({ const updatedTemplates = await fetchDatasetTemplates() const normalizedName = templateName.trim().toLowerCase() const createdTemplate = updatedTemplates.find( - (template) => template.name.trim().toLowerCase() === normalizedName + (currentTemplate) => currentTemplate.name.trim().toLowerCase() === normalizedName ) if (!createdTemplate) return - navigate(RouteWithParams.TEMPLATES_EDIT_TERMS(collectionId, createdTemplate.id), { - state: { fromCreateTemplate: true } - }) + navigate( + RouteWithParams.TEMPLATES_EDIT(collectionId, createdTemplate.id, TemplateEditMode.LICENSE), + { + state: { fromCreateTemplate: true } + } + ) })() } + const submitButtonLabel = + mode === 'edit' ? tShared('saveChanges') : t('createTemplate.saveAddTerms') + return (
- {submissionStatus === SubmissionStatus.SubmitComplete && ( + {submissionStatus === SubmissionStatus.SubmitComplete && mode === 'create' && ( {t('createTemplate.alerts.success')} @@ -158,8 +212,10 @@ export const TemplateForm = ({ )} - - +
+ + +
{metadataBlocksInfo.map((metadataBlock, index) => ( diff --git a/src/sections/shared/form/TemplateMetadataForm/TemplateMetadataForm.tsx b/src/sections/shared/form/TemplateMetadataForm/TemplateMetadataForm.tsx index 641a3ffbe..cbd8fd4c1 100644 --- a/src/sections/shared/form/TemplateMetadataForm/TemplateMetadataForm.tsx +++ b/src/sections/shared/form/TemplateMetadataForm/TemplateMetadataForm.tsx @@ -1,24 +1,39 @@ -import { useMemo } from 'react' +import { useEffect, useMemo } from 'react' import { Alert } from '@iqss/dataverse-design-system' import { MetadataBlockInfoRepository } from '@/metadata-block-info/domain/repositories/MetadataBlockInfoRepository' import { type MetadataField } from '@/metadata-block-info/domain/models/MetadataBlockInfo' import { TemplateRepository } from '@/templates/domain/repositories/TemplateRepository' +import { Template } from '@/templates/domain/models/Template' import { useGetMetadataBlocksInfo } from '../DatasetMetadataForm/useGetMetadataBlocksInfo' import { MetadataFieldsHelper } from '../DatasetMetadataForm/MetadataFieldsHelper' import { MetadataFormSkeleton } from '../DatasetMetadataForm/MetadataForm/MetadataFormSkeleton' import { TemplateForm } from './TemplateForm' +import { useLoading } from '@/shared/contexts/loading/LoadingContext' -interface TemplateMetadataFormProps { - collectionId: string - metadataBlockInfoRepository: MetadataBlockInfoRepository - templateRepository: TemplateRepository -} +type TemplateMetadataFormProps = + | { + mode: 'create' + collectionId: string + metadataBlockInfoRepository: MetadataBlockInfoRepository + templateRepository: TemplateRepository + template?: never + } + | { + mode: 'edit' + collectionId: string + metadataBlockInfoRepository: MetadataBlockInfoRepository + templateRepository: TemplateRepository + template: Template + } export const TemplateMetadataForm = ({ + mode, collectionId, metadataBlockInfoRepository, - templateRepository + templateRepository, + template }: TemplateMetadataFormProps) => { + const { setIsLoading } = useLoading() const { metadataBlocksInfo: metadataBlocksInfoForDisplay, isLoading, @@ -29,13 +44,28 @@ export const TemplateMetadataForm = ({ metadataBlockInfoRepository }) - const metadataBlocksInfo = useMemo( - () => - MetadataFieldsHelper.replaceMetadataBlocksInfoDotNamesKeysWithSlash( - metadataBlocksInfoForDisplay - ), - [metadataBlocksInfoForDisplay] - ) + useEffect(() => { + setIsLoading(isLoading) + }, [isLoading, setIsLoading]) + + const metadataBlocksInfo = useMemo(() => { + const normalized = MetadataFieldsHelper.replaceMetadataBlocksInfoDotNamesKeysWithSlash( + metadataBlocksInfoForDisplay + ) + + if (mode === 'edit' && template?.datasetMetadataBlocks) { + const normalizedTemplateBlocks = + MetadataFieldsHelper.replaceDatasetMetadataBlocksDotKeysWithSlash( + template.datasetMetadataBlocks + ) + return MetadataFieldsHelper.addFieldValuesToMetadataBlocksInfo( + normalized, + normalizedTemplateBlocks + ) + } + + return normalized + }, [metadataBlocksInfoForDisplay, mode, template]) const metadataFieldsForMapping = useMemo( () => @@ -55,7 +85,7 @@ export const TemplateMetadataForm = ({ ) if (isLoading) { - return + return } if (error) { @@ -66,8 +96,23 @@ export const TemplateMetadataForm = ({ ) } + if (mode === 'edit') { + return ( + + ) + } + return ( Promise - submitError: null - } - | { - submissionStatus: SubmissionStatus.Errored - submitTemplate: (payload: TemplateInfo) => Promise - submitError: string - } +type CreateOptions = { + mode: 'create' + templateRepository: TemplateRepository + collectionId: string +} + +type EditOptions = { + mode: 'edit' + templateRepository: TemplateRepository + templateId: number +} + +type UseSubmitTemplateOptions = CreateOptions | EditOptions -export function useSubmitTemplate(collectionId: string): UseSubmitTemplateReturnType { - const { t } = useTranslation('datasetTemplates', { keyPrefix: 'createTemplate' }) +interface UseSubmitTemplateReturn { + submissionStatus: SubmissionStatus + submitTemplate: (payload: TemplateInfo | UpdateTemplateMetadataInfo) => Promise + submitError: string | null +} + +export function useSubmitTemplate(options: UseSubmitTemplateOptions): UseSubmitTemplateReturn { + const { t } = useTranslation('datasetTemplates') const [submissionStatus, setSubmissionStatus] = useState( SubmissionStatus.NotSubmitted ) const [submitError, setSubmitError] = useState(null) - const submitTemplate = async (template: TemplateInfo): Promise => { + const submitTemplate = async ( + payload: TemplateInfo | UpdateTemplateMetadataInfo + ): Promise => { setSubmissionStatus(SubmissionStatus.IsSubmitting) setSubmitError(null) try { - await createTemplate.execute( - template as Parameters[0], - collectionId - ) + if (options.mode === 'create') { + await createTemplateUseCase( + options.templateRepository, + payload as TemplateInfo, + options.collectionId + ) + } else { + await updateTemplateMetadataUseCase( + options.templateRepository, + options.templateId, + payload as UpdateTemplateMetadataInfo + ) + } setSubmissionStatus(SubmissionStatus.SubmitComplete) return true } catch (error) { + console.error('useSubmitTemplate error:', error) if (error instanceof WriteError) { const handler = new JSDataverseWriteErrorHandler(error) const formattedError = handler.getReasonWithoutStatusCode() ?? /* istanbul ignore next */ handler.getErrorMessage() setSubmitError(formattedError) + } else if (error instanceof Error && error.message) { + setSubmitError(error.message) } else { - setSubmitError(t('errors.saveFailed')) + setSubmitError( + options.mode === 'create' + ? t('createTemplate.errors.saveFailed') + : t('editTemplate.errors.saveMetadataFailed') + ) } setSubmissionStatus(SubmissionStatus.Errored) return false @@ -63,5 +90,5 @@ export function useSubmitTemplate(collectionId: string): UseSubmitTemplateReturn submissionStatus, submitTemplate, submitError - } as UseSubmitTemplateReturnType + } } diff --git a/src/sections/templates/DatasetTemplates.tsx b/src/sections/templates/DatasetTemplates.tsx index b2b232ced..94d94262a 100644 --- a/src/sections/templates/DatasetTemplates.tsx +++ b/src/sections/templates/DatasetTemplates.tsx @@ -1,5 +1,5 @@ -import { useMemo, useState } from 'react' -import { useNavigate } from 'react-router-dom' +import { startTransition, useEffect, useMemo, useState } from 'react' +import { useLocation, useNavigate } from 'react-router-dom' import { useTranslation } from 'react-i18next' import { Alert, @@ -23,7 +23,7 @@ import { Trash } from 'react-bootstrap-icons' import { toast } from 'react-toastify' -import { RouteWithParams } from '@/sections/Route.enum' +import { RouteWithParams, TemplateEditMode } from '@/sections/Route.enum' import { BreadcrumbsGenerator } from '../shared/hierarchy/BreadcrumbsGenerator' import { DatasetTemplatesSkeleton } from './DatasetTemplatesSkeleton' import { useGetCollectionUserPermissions } from '@/shared/hooks/useGetCollectionUserPermissions' @@ -34,15 +34,17 @@ import { TemplateRepository } from '@/templates/domain/repositories/TemplateRepo import { useCollection } from '../collection/useCollection' import { useGetTemplatesByCollectionId } from '@/templates/domain/hooks/useGetTemplatesByCollectionId' import { NotFoundPage } from '../not-found-page/NotFoundPage' -import { NotImplementedModal } from '../not-implemented/NotImplementedModal' -import { useNotImplementedModal } from '../not-implemented/NotImplementedModalContext' import { Template } from '@/templates/domain/models/Template' import { ConfirmDeleteTemplateModal } from './confirm-delete-template-modal/ConfirmDeleteTemplateModal' import { TemplatePreviewModal } from './template-preview-modal/TemplatePreviewModal' import { useCopyTemplate } from './useCopyTemplate' +import { useSetTemplateAsDefault } from './useSetTemplateAsDefault' +import { useLoading } from '@/shared/contexts/loading/LoadingContext' import styles from './DatasetTemplates.module.scss' +const EDIT_TEMPLATE_SUCCESS_TOAST_ID = 'edit-template-success' + interface DatasetTemplatesProps { collectionRepository: CollectionRepository templateRepository: TemplateRepository @@ -57,9 +59,17 @@ export const DatasetTemplates = ({ collectionId }: DatasetTemplatesProps) => { const { t } = useTranslation('datasetTemplates') - const { t: tDataset } = useTranslation('dataset') const navigate = useNavigate() - const { isModalOpen, hideModal, showModal } = useNotImplementedModal() + const location = useLocation() + const { setIsLoading } = useLoading() + + useEffect(() => { + const state = location.state as { fromEditTemplate?: boolean } | null + if (state?.fromEditTemplate) { + toast.success(t('alerts.editSuccess'), { toastId: EDIT_TEMPLATE_SUCCESS_TOAST_ID }) + navigate(location.pathname, { replace: true, state: null }) + } + }, [location, navigate, t]) const [sortBy, setSortBy] = useState<'name' | 'created' | 'usage' | null>(null) const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>('asc') const [templateToDelete, setTemplateToDelete] = useState