Add CreateTemplate endpoint and related functionality for channels without grids
Implement a new API endpoint to create a template for channels lacking a grid, enhancing the template management capabilities. Update frontend components to support the creation of templates directly from the channel detail view, including user feedback and translations for improved clarity. Add integration tests to ensure the new functionality works as expected.
This commit is contained in:
@@ -15,6 +15,7 @@ import { toast } from '@/shared/ui/toast-store'
|
||||
import {
|
||||
applyChannelTemplate,
|
||||
copyTemplateTo,
|
||||
createChannelTemplate,
|
||||
createLayer,
|
||||
createSlot,
|
||||
deleteLayer,
|
||||
@@ -41,8 +42,8 @@ import { ViewerCard } from './components/ViewerCard'
|
||||
import { SlotInspector, type SlotDraft } from './components/SlotInspector'
|
||||
import { toTime } from './lib/format'
|
||||
|
||||
/** Вкладки экрана канала — в порядке частоты правки. */
|
||||
const TABS = ['grid', 'rules', 'junctions', 'bumpers', 'viewer', 'settings', 'air'] as const
|
||||
/** Вкладки экрана канала: настройки первыми — с них канал и начинается. */
|
||||
const TABS = ['settings', 'grid', 'rules', 'junctions', 'bumpers', 'viewer', 'air'] as const
|
||||
type ChannelTab = (typeof TABS)[number]
|
||||
|
||||
export function ChannelDetail({ channelId }: { channelId: string }) {
|
||||
@@ -58,7 +59,7 @@ export function ChannelDetail({ channelId }: { channelId: string }) {
|
||||
const [applyOpen, setApplyOpen] = useState(false)
|
||||
const [traceEntryId, setTraceEntryId] = useState<string | null>(null)
|
||||
const [copyToChannel, setCopyToChannel] = useState('')
|
||||
const [tab, setTab] = useState<ChannelTab>('grid')
|
||||
const [tab, setTab] = useState<ChannelTab>('settings')
|
||||
|
||||
const { data: channel, isLoading } = useQuery({
|
||||
queryKey: ['admin', 'channels', channelId],
|
||||
@@ -154,6 +155,13 @@ export function ChannelDetail({ channelId }: { channelId: string }) {
|
||||
onError,
|
||||
})
|
||||
|
||||
// Канал без сетки — наследство старой ротации: заводим шаблон на месте, а не пересоздаём канал.
|
||||
const createTemplateMutation = useMutation({
|
||||
mutationFn: () => createChannelTemplate(channelId),
|
||||
onSuccess: invalidate,
|
||||
onError,
|
||||
})
|
||||
|
||||
const copyTemplateMutation = useMutation({
|
||||
mutationFn: (targetChannelId: string) => copyTemplateTo(channelId, targetChannelId),
|
||||
onSuccess: (result) => {
|
||||
@@ -283,11 +291,21 @@ export function ChannelDetail({ channelId }: { channelId: string }) {
|
||||
|
||||
{/* Шаблон мог не загрузиться — раньше вкладка сетки просто оказывалась пустой. */}
|
||||
{tab === 'grid' && !template && (
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{templateError instanceof HttpError
|
||||
? templateError.detail
|
||||
: t('admin.channels.noTemplate')}
|
||||
</p>
|
||||
<div className="flex flex-col items-start gap-3">
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{templateError instanceof HttpError
|
||||
? templateError.detail
|
||||
: t('admin.channels.noTemplate')}
|
||||
</p>
|
||||
<Button
|
||||
size="sm"
|
||||
disabled={createTemplateMutation.isPending}
|
||||
onClick={() => createTemplateMutation.mutate()}
|
||||
>
|
||||
<Plus className="h-4 w-4" /> {t('admin.channels.createTemplate')}
|
||||
</Button>
|
||||
<p className="text-xs text-muted-foreground">{t('admin.channels.createTemplateHint')}</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{tab === 'grid' && template && (
|
||||
|
||||
@@ -67,6 +67,11 @@ export function getChannelTemplate(channelId: string) {
|
||||
return apiRequest<ScheduleTemplateDto>(`/admin/channels/${channelId}/template`)
|
||||
}
|
||||
|
||||
/** Заводит каналу сетку, если её нет: у каналов из старой ротации шаблона может не быть. */
|
||||
export function createChannelTemplate(channelId: string) {
|
||||
return apiRequest<CreatedIdResponse>(`/admin/channels/${channelId}/template`, { method: 'POST' })
|
||||
}
|
||||
|
||||
/** Применяет правила к эфиру: пересобирает будущий хвост. Правка слотов эфир не двигает. */
|
||||
export function applyChannelTemplate(channelId: string) {
|
||||
return apiRequest<ApplyResultDto>(`/admin/channels/${channelId}/template/apply`, {
|
||||
|
||||
Reference in New Issue
Block a user