feat(schedule): add loop and recycle policy options to programming blocks
This commit is contained in:
@@ -58,6 +58,8 @@ const blockSchema = z.object({
|
||||
items: z.array(z.string()),
|
||||
}),
|
||||
]),
|
||||
loop_on_finish: z.boolean().optional(),
|
||||
ignore_recycle_policy: z.boolean().optional(),
|
||||
});
|
||||
|
||||
const channelFormSchema = z.object({
|
||||
@@ -211,6 +213,8 @@ function defaultBlock(startMins = 20 * 60, durationMins = 60): ProgrammingBlock
|
||||
start_time: minsToTime(startMins),
|
||||
duration_mins: durationMins,
|
||||
content: { type: "algorithmic", filter: defaultFilter(), strategy: "random" },
|
||||
loop_on_finish: true,
|
||||
ignore_recycle_policy: false,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -534,13 +538,47 @@ function BlockEditor({ block, index, isSelected, color, errors, onChange, onRemo
|
||||
</div>
|
||||
|
||||
{content.type === "algorithmic" && (
|
||||
<AlgorithmicFilterEditor
|
||||
content={content}
|
||||
pfx={pfx}
|
||||
errors={errors}
|
||||
setFilter={setFilter}
|
||||
setStrategy={setStrategy}
|
||||
/>
|
||||
<>
|
||||
<AlgorithmicFilterEditor
|
||||
content={content}
|
||||
pfx={pfx}
|
||||
errors={errors}
|
||||
setFilter={setFilter}
|
||||
setStrategy={setStrategy}
|
||||
/>
|
||||
|
||||
{content.strategy === "sequential" && (
|
||||
<div className="space-y-2 rounded-md border border-zinc-700/50 bg-zinc-800 p-3">
|
||||
<p className="text-[11px] font-medium uppercase tracking-wider text-zinc-500">
|
||||
Sequential options
|
||||
</p>
|
||||
<label className="flex items-center gap-2 cursor-pointer">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={block.loop_on_finish ?? true}
|
||||
onChange={(e) => onChange({ ...block, loop_on_finish: e.target.checked })}
|
||||
className="accent-zinc-400"
|
||||
/>
|
||||
<span className="text-sm text-zinc-300">Loop series</span>
|
||||
<span className="text-[11px] text-zinc-600">
|
||||
Restart from episode 1 after the final episode
|
||||
</span>
|
||||
</label>
|
||||
<label className="flex items-center gap-2 cursor-pointer">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={block.ignore_recycle_policy ?? false}
|
||||
onChange={(e) => onChange({ ...block, ignore_recycle_policy: e.target.checked })}
|
||||
className="accent-zinc-400"
|
||||
/>
|
||||
<span className="text-sm text-zinc-300">Independent scheduling</span>
|
||||
<span className="text-[11px] text-zinc-600">
|
||||
Play episodes in order even if they aired in another block today
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
{content.type === "manual" && (
|
||||
|
||||
@@ -63,6 +63,10 @@ export interface ProgrammingBlock {
|
||||
start_time: string;
|
||||
duration_mins: number;
|
||||
content: BlockContent;
|
||||
/** Sequential only: loop back to episode 1 after the last episode. Default true on backend. */
|
||||
loop_on_finish?: boolean;
|
||||
/** When true, skip the channel-level recycle policy for this block. Default false on backend. */
|
||||
ignore_recycle_policy?: boolean;
|
||||
}
|
||||
|
||||
export interface ScheduleConfig {
|
||||
|
||||
Reference in New Issue
Block a user