Add original name support for shows: implement API endpoint to set original name, update Show and ShowDto models to include original name field, and enhance UI components for managing original names in show metadata. Update validation and database schema accordingly.
This commit is contained in:
@@ -15,6 +15,7 @@ import {
|
||||
getMetadataProviders,
|
||||
refreshEpisodesMetadata,
|
||||
searchMetadata,
|
||||
setShowOriginalName,
|
||||
showPosterUrl,
|
||||
updateMetadata,
|
||||
uploadPoster,
|
||||
@@ -25,7 +26,8 @@ export function ShowMetadataCard({ show, onChanged }: { show: ShowDto; onChanged
|
||||
const posterInput = useRef<HTMLInputElement>(null)
|
||||
const [bust, setBust] = useState(0)
|
||||
const [provider, setProvider] = useState('')
|
||||
const [query, setQuery] = useState(show.name)
|
||||
const [originalName, setOriginalName] = useState(show.originalName ?? '')
|
||||
const [query, setQuery] = useState(show.originalName || show.name)
|
||||
const [results, setResults] = useState<MetadataCandidate[]>([])
|
||||
const [searched, setSearched] = useState(false)
|
||||
const [description, setDescription] = useState(show.description ?? '')
|
||||
@@ -53,6 +55,15 @@ export function ShowMetadataCard({ show, onChanged }: { show: ShowDto; onChanged
|
||||
},
|
||||
onError,
|
||||
})
|
||||
const saveOriginal = useMutation({
|
||||
mutationFn: () => setShowOriginalName(show.id, originalName.trim() || null),
|
||||
onSuccess: () => {
|
||||
toast.success(t('settings.saved'))
|
||||
setQuery(originalName.trim() || show.name)
|
||||
onChanged()
|
||||
},
|
||||
onError,
|
||||
})
|
||||
const apply = useMutation({
|
||||
mutationFn: (externalId: string) => applyMetadata(show.id, effectiveProvider, externalId),
|
||||
onSuccess: () => {
|
||||
@@ -143,6 +154,28 @@ export function ShowMetadataCard({ show, onChanged }: { show: ShowDto; onChanged
|
||||
|
||||
{/* Поиск + ручная правка */}
|
||||
<div className="flex min-w-0 flex-1 flex-col gap-4">
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<Label>{t('admin.metadata.originalName')}</Label>
|
||||
<div className="flex items-end gap-2">
|
||||
<Input
|
||||
className="min-w-40 flex-1"
|
||||
value={originalName}
|
||||
maxLength={256}
|
||||
placeholder={t('admin.metadata.originalNamePlaceholder')}
|
||||
onChange={(e) => setOriginalName(e.target.value)}
|
||||
/>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
disabled={saveOriginal.isPending || originalName === (show.originalName ?? '')}
|
||||
onClick={() => saveOriginal.mutate()}
|
||||
>
|
||||
{t('common.save')}
|
||||
</Button>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">{t('admin.metadata.originalNameHint')}</p>
|
||||
</div>
|
||||
|
||||
{providers && providers.length > 0 && (
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className="flex flex-wrap items-end gap-2">
|
||||
|
||||
@@ -15,6 +15,7 @@ export function ShowsPanel() {
|
||||
const { t } = useTranslation()
|
||||
const queryClient = useQueryClient()
|
||||
const [name, setName] = useState('')
|
||||
const [originalName, setOriginalName] = useState('')
|
||||
const [kind, setKind] = useState<ShowKind>('Series')
|
||||
|
||||
const { data, isLoading } = useQuery({ queryKey: ['admin', 'shows'], queryFn: listShows })
|
||||
@@ -23,9 +24,11 @@ export function ShowsPanel() {
|
||||
toast.error(error instanceof HttpError ? error.detail : t('common.error'))
|
||||
|
||||
const createMutation = useMutation({
|
||||
mutationFn: () => createShow({ name: name.trim(), kind }),
|
||||
mutationFn: () =>
|
||||
createShow({ name: name.trim(), kind, originalName: originalName.trim() || undefined }),
|
||||
onSuccess: () => {
|
||||
setName('')
|
||||
setOriginalName('')
|
||||
invalidate()
|
||||
},
|
||||
onError,
|
||||
@@ -43,6 +46,12 @@ export function ShowsPanel() {
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
/>
|
||||
<Input
|
||||
className="max-w-xs"
|
||||
placeholder={t('admin.shows.originalName')}
|
||||
value={originalName}
|
||||
onChange={(e) => setOriginalName(e.target.value)}
|
||||
/>
|
||||
<Select value={kind} onValueChange={(v) => setKind(v as ShowKind)}>
|
||||
<SelectTrigger className="w-40">
|
||||
<SelectValue />
|
||||
|
||||
@@ -15,10 +15,22 @@ export function getShow(id: string) {
|
||||
return apiRequest<ShowDto>(`/admin/shows/${id}`)
|
||||
}
|
||||
|
||||
export function createShow(body: { name: string; kind: ShowKind; description?: string }) {
|
||||
export function createShow(body: {
|
||||
name: string
|
||||
kind: ShowKind
|
||||
description?: string
|
||||
originalName?: string
|
||||
}) {
|
||||
return apiRequest<CreatedIdResponse>('/admin/shows', { method: 'POST', body })
|
||||
}
|
||||
|
||||
export function setShowOriginalName(id: string, originalName: string | null) {
|
||||
return apiRequest<void>(`/admin/shows/${id}/original-name`, {
|
||||
method: 'PUT',
|
||||
body: { originalName },
|
||||
})
|
||||
}
|
||||
|
||||
export function deleteShow(id: string) {
|
||||
return apiRequest<void>(`/admin/shows/${id}`, { method: 'DELETE' })
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user