Editable templates (#225)

* editable templates

* removed unused import
This commit is contained in:
Marco Piovanello
2024-11-15 14:24:44 +01:00
committed by GitHub
parent 6c9118f67e
commit ab7932ae92
6 changed files with 167 additions and 62 deletions

View File

@@ -0,0 +1,67 @@
import { FC, useState } from 'react'
import DeleteIcon from '@mui/icons-material/Delete'
import EditIcon from '@mui/icons-material/Edit'
import {
Button,
Grid,
TextField
} from '@mui/material'
import { useI18n } from '../hooks/useI18n'
import { CustomTemplate } from '../types'
interface Props {
template: CustomTemplate
onChange: (template: CustomTemplate) => void
onDelete: (id: string) => void
}
const TemplateTextField: FC<Props> = ({ template, onChange, onDelete }) => {
const { i18n } = useI18n()
const [editedTemplate, setEditedTemplate] = useState(template)
return (
<Grid
container
spacing={2}
justifyContent="center"
alignItems="center"
key={template.id}
sx={{ mt: 1 }}
>
<Grid item xs={3}>
<TextField
fullWidth
label={i18n.t('templatesEditorNameLabel')}
defaultValue={template.name}
onChange={(e) => setEditedTemplate({ ...editedTemplate, name: e.target.value })}
/>
</Grid>
<Grid item xs={9}>
<TextField
fullWidth
label={i18n.t('templatesEditorContentLabel')}
defaultValue={template.content}
onChange={(e) => setEditedTemplate({ ...editedTemplate, content: e.target.value })}
InputProps={{
endAdornment: <div style={{ display: 'flex', gap: 2 }}>
<Button
variant='contained'
onClick={() => onChange(editedTemplate)}>
<EditIcon />
</Button>
<Button
variant='contained'
onClick={() => onDelete(editedTemplate.id)}>
<DeleteIcon />
</Button>
</div>
}}
/>
</Grid>
</Grid>
)
}
export default TemplateTextField

View File

@@ -1,6 +1,7 @@
import AddIcon from '@mui/icons-material/Add'
import CloseIcon from '@mui/icons-material/Close'
import DeleteIcon from '@mui/icons-material/Delete'
import EditIcon from '@mui/icons-material/Edit'
import {
Alert,
AppBar,
@@ -26,6 +27,7 @@ import { useI18n } from '../hooks/useI18n'
import { ffetch } from '../lib/httpClient'
import { CustomTemplate } from '../types'
import { useAtomValue } from 'jotai'
import TemplateTextField from './TemplateTextField'
const Transition = forwardRef(function Transition(
props: TransitionProps & {
@@ -55,11 +57,11 @@ const TemplatesEditor: React.FC<Props> = ({ open, onClose }) => {
useEffect(() => {
if (open) {
getTemplates()
fetchTemplates()
}
}, [open])
const getTemplates = async () => {
const fetchTemplates = async () => {
const task = ffetch<CustomTemplate[]>(`${serverAddr}/api/v1/template/all`)
const either = await task()
@@ -89,7 +91,7 @@ const TemplatesEditor: React.FC<Props> = ({ open, onClose }) => {
(l) => pushMessage(l, 'warning'),
() => {
pushMessage('Added template')
getTemplates()
fetchTemplates()
setTemplateName('')
setTemplateContent('')
}
@@ -97,6 +99,26 @@ const TemplatesEditor: React.FC<Props> = ({ open, onClose }) => {
)
}
const updateTemplate = async (template: CustomTemplate) => {
const task = ffetch<CustomTemplate>(`${serverAddr}/api/v1/template`, {
method: 'PATCH',
body: JSON.stringify(template)
})
const either = await task()
pipe(
either,
matchW(
(l) => pushMessage(l, 'warning'),
(r) => {
pushMessage(`Updated template ${r.name}`)
fetchTemplates()
}
)
)
}
const deleteTemplate = async (id: string) => {
const task = ffetch<unknown>(`${serverAddr}/api/v1/template/${id}`, {
method: 'DELETE',
@@ -110,7 +132,7 @@ const TemplatesEditor: React.FC<Props> = ({ open, onClose }) => {
(l) => pushMessage(l, 'warning'),
() => {
pushMessage('Deleted template')
getTemplates()
fetchTemplates()
}
)
)
@@ -188,38 +210,12 @@ const TemplatesEditor: React.FC<Props> = ({ open, onClose }) => {
</Grid>
</Grid>
{templates.map(template => (
<Grid
container
spacing={2}
justifyContent="center"
alignItems="center"
<TemplateTextField
key={template.id}
sx={{ mt: 1 }}
>
<Grid item xs={3}>
<TextField
fullWidth
label={i18n.t('templatesEditorNameLabel')}
value={template.name}
/>
</Grid>
<Grid item xs={9}>
<TextField
fullWidth
label={i18n.t('templatesEditorContentLabel')}
value={template.content}
InputProps={{
endAdornment: <Button
variant='contained'
onClick={() => {
startTransition(() => { deleteTemplate(template.id) })
}}>
<DeleteIcon />
</Button>
}}
/>
</Grid>
</Grid>
template={template}
onChange={updateTemplate}
onDelete={deleteTemplate}
/>
))}
</Paper>
</Grid>

View File

@@ -5,6 +5,7 @@ export const useI18n = () => {
const instance = useAtomValue(i18nBuilderState)
return {
i18n: instance
i18n: instance,
t: instance.t
}
}