Add restore functionality for template management and enhance related components
Implemented a new endpoint for restoring templates to their last applied state, allowing users to revert changes made since the last application. Updated the ScheduleTemplate class to include a snapshot of the last applied state, enabling rollback capabilities. Enhanced the frontend with a restore button in the ChannelDetail component, providing users with a confirmation prompt before executing the restore action. Localization updates were made to support new UI strings in both English and Russian, improving the overall user experience in template management.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
||||
import { Link } from '@tanstack/react-router'
|
||||
import { ChevronLeft, Send } from 'lucide-react'
|
||||
import { ChevronLeft, Send, Undo2 } from 'lucide-react'
|
||||
import { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { listAllMedia } from '@/features/admin/media/api'
|
||||
@@ -11,7 +11,13 @@ import { Badge } from '@/shared/ui/badge'
|
||||
import { Button } from '@/shared/ui/button'
|
||||
import { Card, CardContent } from '@/shared/ui/card'
|
||||
import { toast } from '@/shared/ui/toast-store'
|
||||
import { applyChannelTemplate, getChannel, getChannelTemplate, getSchedule } from './api'
|
||||
import {
|
||||
applyChannelTemplate,
|
||||
getChannel,
|
||||
getChannelTemplate,
|
||||
getSchedule,
|
||||
restoreChannelTemplate,
|
||||
} from './api'
|
||||
import { ApplyDialog } from './components/ApplyDialog'
|
||||
import { BumperCard } from './components/BumperCard'
|
||||
import { EntryTraceDialog } from './components/EntryTraceDialog'
|
||||
@@ -70,6 +76,18 @@ export function ChannelDetail({ channelId }: Readonly<{ channelId: string }>) {
|
||||
onError,
|
||||
})
|
||||
|
||||
const restoreMutation = useMutation({
|
||||
mutationFn: () => restoreChannelTemplate(channelId),
|
||||
onSuccess: (result) => {
|
||||
toast.success(t('admin.channels.restored', { count: result.slots }))
|
||||
// Ссылка на удалённую группу или стык вернуться не может — говорим об этом прямо.
|
||||
if (result.droppedRefs > 0)
|
||||
toast.error(t('admin.channels.restoreDropped', { count: result.droppedRefs }))
|
||||
invalidate()
|
||||
},
|
||||
onError,
|
||||
})
|
||||
|
||||
if (isLoading || !channel) return <p className="text-muted-foreground">{t('common.loading')}</p>
|
||||
|
||||
return (
|
||||
@@ -89,13 +107,31 @@ export function ChannelDetail({ channelId }: Readonly<{ channelId: string }>) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Правка правил эфира не двигает — применение отдельной кнопкой. */}
|
||||
{/* Правка правил эфира не двигает — применение отдельной кнопкой. Рядом откат: правки
|
||||
сетки правятся на месте, и без этой кнопки вернуть «как в эфире» было бы нечем. */}
|
||||
{template?.hasPendingChanges && (
|
||||
<div className="flex flex-wrap items-center justify-between gap-3 rounded-md border border-amber-500/50 bg-amber-500/10 px-4 py-2 text-sm">
|
||||
<span>{t('admin.channels.pendingChanges')}</span>
|
||||
<Button size="sm" disabled={applyMutation.isPending} onClick={() => setApplyOpen(true)}>
|
||||
<Send className="h-4 w-4" /> {t('admin.channels.apply')}
|
||||
</Button>
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
{/* Кнопки отката нет, пока сетку ни разу не применяли: возвращаться некуда. */}
|
||||
{template.canRestore && (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
disabled={restoreMutation.isPending}
|
||||
onClick={() => {
|
||||
// Откат необратим — он стирает всё, сделанное с последнего применения.
|
||||
if (!window.confirm(t('admin.channels.restoreConfirm'))) return
|
||||
restoreMutation.mutate()
|
||||
}}
|
||||
>
|
||||
<Undo2 className="h-4 w-4" /> {t('admin.channels.restore')}
|
||||
</Button>
|
||||
)}
|
||||
<Button size="sm" disabled={applyMutation.isPending} onClick={() => setApplyOpen(true)}>
|
||||
<Send className="h-4 w-4" /> {t('admin.channels.apply')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user