Simplify radio CRUD code

This commit is contained in:
Deluan 2023-01-24 20:58:20 -05:00 committed by Deluan Quintão
parent 39161fdf47
commit 5eefb265e5
6 changed files with 59 additions and 241 deletions

View File

@ -174,11 +174,6 @@
"updatedAt": "Updated at",
"createdAt": "Created at"
},
"notifications": {
"created": "Radio created",
"updated": "Radio updated",
"deleted": "Radio deleted"
},
"actions": {
"playNow": "Play Now"
}
@ -356,8 +351,6 @@
"noPlaylistsAvailable": "None available",
"delete_user_title": "Delete user '%{name}'",
"delete_user_content": "Are you sure you want to delete this user and all their data (including playlists and preferences)?",
"delete_radio_title": "Delete radio '%{name}'",
"delete_radio_content": "Are you sure you want to remove this radio?",
"notifications_blocked": "You have blocked Notifications for this site in your browser's settings",
"notifications_not_available": "This browser does not support desktop notifications or you are not accessing Navidrome over https",
"lastfmLinkSuccess": "Last.fm successfully linked and scrobbling enabled",

View File

@ -1,76 +0,0 @@
import { fade, makeStyles } from '@material-ui/core'
import DeleteIcon from '@material-ui/icons/Delete'
import clsx from 'clsx'
import React from 'react'
import {
Button,
Confirm,
useDeleteWithConfirmController,
useNotify,
useRedirect,
} from 'react-admin'
const useStyles = makeStyles(
(theme) => ({
deleteButton: {
color: theme.palette.error.main,
'&:hover': {
backgroundColor: fade(theme.palette.error.main, 0.12),
// Reset on mouse devices
'@media (hover: none)': {
backgroundColor: 'transparent',
},
},
},
}),
{ name: 'RaDeleteWithConfirmButton' }
)
const DeleteRadioButton = (props) => {
const { resource, record, basePath, className, onClick, ...rest } = props
const notify = useNotify()
const redirect = useRedirect()
const onSuccess = () => {
notify('resources.radio.notifications.deleted')
redirect('/radio')
}
const { open, loading, handleDialogOpen, handleDialogClose, handleDelete } =
useDeleteWithConfirmController({
resource,
record,
basePath,
onClick,
onSuccess,
})
const classes = useStyles(props)
return (
<>
<Button
onClick={handleDialogOpen}
label="ra.action.delete"
key="button"
className={clsx('ra-delete-button', classes.deleteButton, className)}
{...rest}
>
<DeleteIcon />
</Button>
<Confirm
isOpen={open}
loading={loading}
title="message.delete_radio_title"
content="message.delete_radio_content"
translateOptions={{
name: record.name,
}}
onConfirm={handleDelete}
onClose={handleDialogClose}
/>
</>
)
}
export default DeleteRadioButton

View File

@ -1,62 +1,41 @@
import React, { useCallback } from 'react'
import {
Create,
required,
SimpleForm,
TextInput,
useMutation,
useNotify,
useRedirect,
useTranslate,
} from 'react-admin'
import { Title } from '../common'
import { urlValidate } from '../utils/validations'
const RadioCreate = (props) => {
const RadioTitle = () => {
const translate = useTranslate()
const [mutate] = useMutation()
const notify = useNotify()
const redirect = useRedirect()
const resourceName = translate('resources.radio.name', { smart_count: 1 })
const resourceName = translate('resources.radio.name', {
smart_count: 1,
})
const title = translate('ra.page.create', {
name: `${resourceName}`,
})
return <Title subTitle={title} />
}
const save = useCallback(
async (values) => {
try {
await mutate(
{
type: 'create',
resource: 'radio',
payload: { data: values },
},
{ returnPromise: true }
)
notify('resources.radio.notifications.created', 'info', {
smart_count: 1,
})
redirect('/radio')
} catch (error) {
if (error.body.errors) {
return error.body.errors
}
}
},
[mutate, notify, redirect]
)
const RadioCreate = (props) => {
return (
<Create title={<Title subTitle={title} />} {...props}>
<SimpleForm save={save} variant={'outlined'}>
<Create title={<RadioTitle />} {...props}>
<SimpleForm redirect="list" variant={'outlined'}>
<TextInput source="name" validate={[required()]} />
<TextInput
type="url"
source="streamUrl"
fullWidth
validate={[required()]}
validate={[required(), urlValidate]}
/>
<TextInput
type="url"
source="homepageUrl"
fullWidth
validate={[urlValidate]}
/>
<TextInput type="url" source="homepageUrl" fullWidth />
</SimpleForm>
</Create>
)

View File

@ -1,133 +1,43 @@
import { Card, makeStyles } from '@material-ui/core'
import React, { useCallback } from 'react'
import {
DateField,
EditContextProvider,
Edit,
required,
SaveButton,
SimpleForm,
TextInput,
Toolbar,
useEditController,
useMutation,
useNotify,
useRedirect,
useTranslate,
} from 'react-admin'
import DeleteRadioButton from './DeleteRadioButton'
import { urlValidate } from '../utils/validations'
import { Title } from '../common'
const useStyles = makeStyles({
toolbar: {
display: 'flex',
justifyContent: 'space-between',
},
})
function urlValidate(value) {
if (!value) {
return undefined
}
try {
new URL(value)
return undefined
} catch (_) {
return 'ra.validation.url'
}
}
const RadioToolbar = (props) => (
<Toolbar {...props} classes={useStyles()}>
<SaveButton disabled={props.pristine} />
<DeleteRadioButton />
</Toolbar>
)
const RadioEditLayout = ({
hasCreate,
hasShow,
hasEdit,
hasList,
...props
}) => {
const [mutate] = useMutation()
const notify = useNotify()
const redirect = useRedirect()
const { record } = props
const save = useCallback(
async (values) => {
try {
await mutate(
{
type: 'update',
resource: 'radio',
payload: {
id: values.id,
data: {
name: values.name,
streamUrl: values.streamUrl,
homePageUrl: values.homePageUrl,
},
},
},
{ returnPromise: true }
)
notify('resources.radio.notifications.updated', 'info', {
smart_count: 1,
})
redirect('/radio')
} catch (error) {
if (error.body.errors) {
return error.body.errors
}
}
},
[mutate, notify, redirect]
)
if (!record) {
return null
}
return (
<>
{record && (
<Card>
<SimpleForm
variant="outlined"
save={save}
toolbar={<RadioToolbar />}
{...props}
>
<TextInput source="name" validate={[required()]} />
<TextInput
type="url"
source="streamUrl"
fullWidth
validate={[required(), urlValidate]}
/>
<TextInput
type="url"
source="homePageUrl"
fullWidth
validate={[urlValidate]}
/>
<DateField variant="body1" source="updatedAt" showTime />
<DateField variant="body1" source="createdAt" showTime />
</SimpleForm>
</Card>
)}
</>
)
const RadioTitle = ({ record }) => {
const translate = useTranslate()
const resourceName = translate('resources.radio.name', {
smart_count: 1,
})
return <Title subTitle={`${resourceName} ${record ? record.name : ''}`} />
}
const RadioEdit = (props) => {
const controllerProps = useEditController(props)
return (
<EditContextProvider value={controllerProps}>
<RadioEditLayout {...props} record={controllerProps.record} />
</EditContextProvider>
<Edit title={<RadioTitle />} {...props}>
<SimpleForm variant="outlined" {...props}>
<TextInput source="name" validate={[required()]} />
<TextInput
type="url"
source="streamUrl"
fullWidth
validate={[required(), urlValidate]}
/>
<TextInput
type="url"
source="homePageUrl"
fullWidth
validate={[urlValidate]}
/>
<DateField variant="body1" source="updatedAt" showTime />
<DateField variant="body1" source="createdAt" showTime />
</SimpleForm>
</Edit>
)
}

View File

@ -23,7 +23,7 @@ const TranscodingTitle = () => {
const TranscodingCreate = (props) => (
<Create title={<TranscodingTitle />} {...props}>
<SimpleForm variant={'outlined'}>
<SimpleForm redirect="list" variant={'outlined'}>
<TextInput source="name" validate={[required()]} />
<TextInput source="targetFormat" validate={[required()]} />
<SelectInput

View File

@ -0,0 +1,12 @@
export const urlValidate = (value) => {
if (!value) {
return undefined
}
try {
new URL(value)
return undefined
} catch (_) {
return 'ra.validation.url'
}
}