mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-23 17:19:37 +02:00
- Replace free-text license input with a select box - Improve visual presentation of modals and enhance keyboard interaction
140 lines
4.0 KiB
TypeScript
140 lines
4.0 KiB
TypeScript
import React, { useReducer, useState, useEffect, useRef, useCallback, useMemo } from 'react'
|
|
import { useTranslation } from 'react-i18next'
|
|
import OLForm from '@/features/ui/components/ol/ol-form'
|
|
import OLButton from '@/features/ui/components/ol/ol-button'
|
|
import withErrorBoundary from '@/infrastructure/error-boundary'
|
|
//import { useFocusTrap } from '../../hooks/use-focus-trap'
|
|
import TemplateActionModal from './template-action-modal'
|
|
import { useTemplateContext } from '../../context/template-context'
|
|
import TemplateFormFields from '../form/template-form-fields'
|
|
import type { Template } from '../../../../../../types/template'
|
|
|
|
type EditTemplateModalProps = {
|
|
showModal: boolean
|
|
handleCloseModal: () => void
|
|
actionHandler: (editedTemplate: Template) => void | Promise<void>
|
|
}
|
|
|
|
type ActionError = {
|
|
info?: {
|
|
statusCode?: number
|
|
}
|
|
}
|
|
|
|
type TemplateFormAction =
|
|
| { type: 'UPDATE'; payload: Partial<Template> }
|
|
| { type: 'RESET'; payload: Template }
|
|
| { type: 'CLEAR_FIELD'; field: keyof Template }
|
|
|
|
function templateFormReducer(state: Template, action: TemplateFormAction): Template {
|
|
switch (action.type) {
|
|
case 'UPDATE':
|
|
return { ...state, ...action.payload }
|
|
case 'RESET':
|
|
return { ...action.payload }
|
|
case 'CLEAR_FIELD':
|
|
return { ...state, [action.field]: '' }
|
|
default:
|
|
return state
|
|
}
|
|
}
|
|
|
|
function EditTemplateModal({
|
|
showModal,
|
|
handleCloseModal,
|
|
actionHandler,
|
|
}: EditTemplateModalProps) {
|
|
const { t } = useTranslation()
|
|
const { template } = useTemplateContext()
|
|
|
|
const [editedTemplate, dispatch] = useReducer(templateFormReducer, template)
|
|
const [actionError, setActionError] = useState<ActionError | null>(null)
|
|
const clearModalErrorRef = useRef<() => void>(() => {})
|
|
|
|
useEffect(() => {
|
|
if (showModal) {
|
|
dispatch({ type: 'RESET', payload: template })
|
|
setActionError(null)
|
|
}
|
|
}, [showModal, template])
|
|
|
|
const isConflictError = useMemo(
|
|
() => actionError?.info?.statusCode === 409,
|
|
[actionError]
|
|
)
|
|
|
|
const valid = useMemo(
|
|
() => editedTemplate.name.trim().length > 0,
|
|
[editedTemplate.name]
|
|
)
|
|
|
|
const handleChange = useCallback(
|
|
(changes: Partial<Template>) => {
|
|
dispatch({ type: 'UPDATE', payload: changes })
|
|
if ('name' in changes && isConflictError) {
|
|
setActionError(null)
|
|
clearModalErrorRef.current?.()
|
|
}
|
|
},
|
|
[isConflictError]
|
|
)
|
|
|
|
const handleEnterKey = useCallback(() => {
|
|
document.getElementById('submit-edit-template')?.click()
|
|
}, [])
|
|
|
|
const handleAction = useCallback(() => {
|
|
return Promise.resolve(actionHandler(editedTemplate)).catch(err => {
|
|
setActionError(err)
|
|
throw err
|
|
})
|
|
}, [actionHandler, editedTemplate])
|
|
|
|
const submitButtonDisabled = !valid || isConflictError
|
|
|
|
return (
|
|
<TemplateActionModal
|
|
action="edit"
|
|
title={t('edit_template')}
|
|
template={editedTemplate}
|
|
showModal={showModal}
|
|
handleCloseModal={handleCloseModal}
|
|
size="lg"
|
|
actionHandler={handleAction}
|
|
renderFooterButtons={({ onConfirm, onCancel, isProcessing }) => (
|
|
<>
|
|
<OLButton variant="secondary" onClick={onCancel}>
|
|
{t('cancel')}
|
|
</OLButton>
|
|
<OLButton
|
|
id="submit-edit-template"
|
|
onClick={onConfirm}
|
|
variant="primary"
|
|
disabled={submitButtonDisabled || isProcessing}
|
|
>
|
|
{t('save')}
|
|
</OLButton>
|
|
</>
|
|
)}
|
|
onClearError={fn => {
|
|
clearModalErrorRef.current = fn
|
|
}}
|
|
>
|
|
<div className="modal-body-publish">
|
|
<div className="content-as-table">
|
|
<OLForm onSubmit={e => e.preventDefault()}>
|
|
<TemplateFormFields
|
|
template={editedTemplate}
|
|
includeLanguage
|
|
onChange={handleChange}
|
|
onEnterKey={handleEnterKey}
|
|
/>
|
|
</OLForm>
|
|
</div>
|
|
</div>
|
|
</TemplateActionModal>
|
|
)
|
|
}
|
|
|
|
export default withErrorBoundary(React.memo(EditTemplateModal))
|