add post
option for media
to /article/show
page
This commit is contained in:
parent
96585fe618
commit
311bf2189b
@ -1,42 +1,95 @@
|
|||||||
import {Stack, Typography, Box, Grid2 as Grid, Button} from '@mui/material'
|
import {Stack, Typography, Box, Grid2 as Grid, Button, MenuItem, Select, FormControl, InputLabel, TextField} from '@mui/material'
|
||||||
import {useShow} from '@refinedev/core'
|
import {useShow} from '@refinedev/core'
|
||||||
import {Show, TextFieldComponent as TextField} from '@refinedev/mui'
|
import {Show, TextFieldComponent} from '@refinedev/mui'
|
||||||
|
|
||||||
import {useEffect, useState} from 'react'
|
import {useEffect, useState} from 'react'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
|
||||||
import {BACKEND_URL} from '../../lib/constants'
|
import {BACKEND_URL} from '../../lib/constants'
|
||||||
|
|
||||||
|
type MediaItem = {
|
||||||
|
id: string
|
||||||
|
filename: string
|
||||||
|
media_type: string
|
||||||
|
}
|
||||||
|
|
||||||
export const ArticleShow = () => {
|
export const ArticleShow = () => {
|
||||||
const {query} = useShow({})
|
const {query} = useShow({})
|
||||||
const {data, isLoading} = query
|
const {data, isLoading} = query
|
||||||
const record = data?.data
|
const record = data?.data
|
||||||
|
|
||||||
const [media, setMedia] = useState<any[]>([])
|
const [media, setMedia] = useState<MediaItem[]>([])
|
||||||
const [mediaLoading, setMediaLoading] = useState(true)
|
const [linkedMedia, setLinkedMedia] = useState<MediaItem[]>([])
|
||||||
|
const [selectedMediaId, setSelectedMediaId] = useState<string>('')
|
||||||
|
const [mediaOrder, setMediaOrder] = useState<number>(1)
|
||||||
|
const [mediaLoading, setMediaLoading] = useState<boolean>(true)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (record?.id) {
|
if (record?.id) {
|
||||||
axios
|
axios
|
||||||
.get(`${BACKEND_URL}/article/${record.id}/media`)
|
.get(`${BACKEND_URL}/article/${record.id}/media`)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
setMedia(response?.data || [])
|
setLinkedMedia(response?.data || [])
|
||||||
setMediaLoading(false)
|
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
setMedia([])
|
setLinkedMedia([])
|
||||||
setMediaLoading(false)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}, [record?.id])
|
}, [record?.id])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
axios
|
||||||
|
.get(`${BACKEND_URL}/media`)
|
||||||
|
.then((response) => {
|
||||||
|
setMedia(response?.data || [])
|
||||||
|
setMediaLoading(false)
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
setMedia([])
|
||||||
|
setMediaLoading(false)
|
||||||
|
})
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const availableMedia = media.filter((mediaItem) => !linkedMedia.some((linkedItem) => linkedItem.id === mediaItem.id))
|
||||||
|
|
||||||
|
const linkMedia = () => {
|
||||||
|
if (selectedMediaId) {
|
||||||
|
const requestData = {
|
||||||
|
media_id: selectedMediaId,
|
||||||
|
media_order: mediaOrder,
|
||||||
|
}
|
||||||
|
|
||||||
|
axios
|
||||||
|
.post(`${BACKEND_URL}/article/${record?.id}/media`, requestData, {
|
||||||
|
headers: {
|
||||||
|
accept: 'application/json',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
axios
|
||||||
|
.get(`${BACKEND_URL}/article/${record?.id}/media`)
|
||||||
|
.then((response) => {
|
||||||
|
setLinkedMedia(response?.data || [])
|
||||||
|
setMediaOrder(mediaOrder + 1)
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
setLinkedMedia([])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error('Error linking media:', error)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const deleteMedia = (mediaId: string) => {
|
const deleteMedia = (mediaId: string) => {
|
||||||
axios
|
axios
|
||||||
.delete(`${BACKEND_URL}/article/${record?.id}/media`, {
|
.delete(`${BACKEND_URL}/article/${record?.id}/media`, {
|
||||||
data: {media_id: mediaId},
|
data: {media_id: mediaId},
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
setMedia((prevMedia) => prevMedia.filter((item) => item.id !== mediaId))
|
setLinkedMedia((prevMedia) => prevMedia.filter((item) => item.id !== mediaId))
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error('Error deleting media:', error)
|
console.error('Error deleting media:', error)
|
||||||
@ -50,9 +103,9 @@ export const ArticleShow = () => {
|
|||||||
]
|
]
|
||||||
|
|
||||||
const mediaFields = [
|
const mediaFields = [
|
||||||
{label: 'ID', data: 'id'},
|
{label: 'ID', data: 'id' as keyof MediaItem},
|
||||||
{label: 'Filename', data: 'filename'},
|
{label: 'Filename', data: 'filename' as keyof MediaItem},
|
||||||
{label: 'Media Type', data: 'media_type'},
|
{label: 'Media Type', data: 'media_type' as keyof MediaItem},
|
||||||
]
|
]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -63,7 +116,7 @@ export const ArticleShow = () => {
|
|||||||
<Typography variant="body1" fontWeight="bold">
|
<Typography variant="body1" fontWeight="bold">
|
||||||
{label}
|
{label}
|
||||||
</Typography>
|
</Typography>
|
||||||
<TextField value={record?.[data]} />
|
<TextFieldComponent value={record?.[data] || ''} />
|
||||||
</Stack>
|
</Stack>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
@ -75,28 +128,12 @@ export const ArticleShow = () => {
|
|||||||
<Grid container gap={2}>
|
<Grid container gap={2}>
|
||||||
{mediaLoading ? (
|
{mediaLoading ? (
|
||||||
<Typography>Loading media...</Typography>
|
<Typography>Loading media...</Typography>
|
||||||
) : media.length > 0 ? (
|
) : linkedMedia.length > 0 ? (
|
||||||
media.map((mediaItem, index) => (
|
linkedMedia.map((mediaItem, index) => (
|
||||||
<Box key={index} sx={{border: '2px solid #dddddd25', padding: '20px', marginBottom: '8px'}}>
|
<Box key={index} sx={{border: '2px solid #dddddd25', padding: '20px', marginBottom: '8px'}}>
|
||||||
{record && (
|
{record && (
|
||||||
<Box
|
<Box sx={{display: 'flex', justifyContent: 'center', alignItems: 'center', marginBottom: '20px'}}>
|
||||||
sx={{
|
<img src={`${BACKEND_URL}/media/${mediaItem?.id}/download`} alt={mediaItem?.filename} style={{maxWidth: '100%', height: '20vh', objectFit: 'contain', borderRadius: 8}} />
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'center',
|
|
||||||
alignItems: 'center',
|
|
||||||
marginBottom: '20px',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
src={`${BACKEND_URL}/media/${mediaItem?.id}/download`}
|
|
||||||
alt={mediaItem?.filename}
|
|
||||||
style={{
|
|
||||||
maxWidth: '100%',
|
|
||||||
height: '20vh',
|
|
||||||
objectFit: 'contain',
|
|
||||||
borderRadius: 8,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@ -117,6 +154,33 @@ export const ArticleShow = () => {
|
|||||||
<Typography>No media found</Typography>
|
<Typography>No media found</Typography>
|
||||||
)}
|
)}
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
|
<Stack gap={2}>
|
||||||
|
<Typography variant="body1" fontWeight="bold">
|
||||||
|
Link Media
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<Stack gap={2.5}>
|
||||||
|
<FormControl fullWidth>
|
||||||
|
<InputLabel>Media</InputLabel>
|
||||||
|
<Select value={selectedMediaId} onChange={(e) => setSelectedMediaId(e.target.value)} label="Media" fullWidth>
|
||||||
|
{availableMedia.map((mediaItem) => (
|
||||||
|
<MenuItem key={mediaItem.id} value={mediaItem.id}>
|
||||||
|
{mediaItem.filename}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<FormControl fullWidth>
|
||||||
|
<TextField type="number" label="Media Order" name="heading" value={mediaOrder} onChange={(e) => setMediaOrder(Number(e.target.value))} fullWidth InputLabelProps={{shrink: true}} />
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<Button variant="contained" onClick={linkMedia} disabled={!selectedMediaId}>
|
||||||
|
Link Media
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Show>
|
</Show>
|
||||||
|
Loading…
Reference in New Issue
Block a user