frontend: kanal silme özelliği
Kanal detay sayfasına "Kanalı Sil" eklendi — kanal + tüm session/ segment/candidate geçmişini (dosyalar dahil) siler, ana sayfaya yönlendirir. Yanlışlıkla/test amaçlı eklenen kanalları temizlemek için. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
import { unlink } from "node:fs/promises";
|
import { unlink } from "node:fs/promises";
|
||||||
import { prisma } from "@streamclipper/db";
|
import { prisma } from "@streamclipper/db";
|
||||||
import { revalidatePath } from "next/cache";
|
import { revalidatePath } from "next/cache";
|
||||||
|
import { redirect } from "next/navigation";
|
||||||
|
|
||||||
export async function addChannel(formData: FormData) {
|
export async function addChannel(formData: FormData) {
|
||||||
const name = String(formData.get("name") ?? "").trim();
|
const name = String(formData.get("name") ?? "").trim();
|
||||||
@@ -39,6 +40,25 @@ export async function deleteCandidateSegment(candidateId: string) {
|
|||||||
revalidatePath("/", "layout");
|
revalidatePath("/", "layout");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function deleteChannel(channelId: string) {
|
||||||
|
const sessions = await prisma.streamSession.findMany({
|
||||||
|
where: { channelId },
|
||||||
|
include: { segments: true },
|
||||||
|
});
|
||||||
|
const rawSegmentIds = sessions.flatMap((s) => s.segments.map((seg) => seg.id));
|
||||||
|
const filePaths = sessions.flatMap((s) => s.segments.map((seg) => seg.filePath));
|
||||||
|
|
||||||
|
await prisma.candidateSegment.deleteMany({ where: { rawSegmentId: { in: rawSegmentIds } } });
|
||||||
|
await prisma.rawSegment.deleteMany({ where: { sessionId: { in: sessions.map((s) => s.id) } } });
|
||||||
|
await prisma.streamSession.deleteMany({ where: { channelId } });
|
||||||
|
await prisma.channel.delete({ where: { id: channelId } });
|
||||||
|
|
||||||
|
await Promise.all(filePaths.map((p) => unlink(p).catch(() => {})));
|
||||||
|
|
||||||
|
revalidatePath("/", "layout");
|
||||||
|
redirect("/");
|
||||||
|
}
|
||||||
|
|
||||||
export async function updateYtdlpCookies(formData: FormData) {
|
export async function updateYtdlpCookies(formData: FormData) {
|
||||||
const value = String(formData.get("cookies") ?? "").trim();
|
const value = String(formData.get("cookies") ?? "").trim();
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { notFound } from "next/navigation";
|
|||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { prisma } from "@streamclipper/db";
|
import { prisma } from "@streamclipper/db";
|
||||||
import { fetchChannelStatuses } from "../../../lib/apiDaemon";
|
import { fetchChannelStatuses } from "../../../lib/apiDaemon";
|
||||||
import { deleteRawSegment, deleteCandidateSegment } from "../../actions";
|
import { deleteRawSegment, deleteCandidateSegment, deleteChannel } from "../../actions";
|
||||||
import { DeleteButton } from "../../components/DeleteButton";
|
import { DeleteButton } from "../../components/DeleteButton";
|
||||||
|
|
||||||
export const dynamic = "force-dynamic";
|
export const dynamic = "force-dynamic";
|
||||||
@@ -51,7 +51,12 @@ export default async function ChannelDetailPage({ params }: { params: Promise<{
|
|||||||
<>
|
<>
|
||||||
<p><Link href="/">← Kanal Durumu</Link></p>
|
<p><Link href="/">← Kanal Durumu</Link></p>
|
||||||
|
|
||||||
<h1>{channel.name}</h1>
|
<div className="card-head">
|
||||||
|
<h1>{channel.name}</h1>
|
||||||
|
<form action={deleteChannel.bind(null, channel.id)}>
|
||||||
|
<DeleteButton confirmText="Bu kanalı ve tüm kayıt geçmişini silmek istediğine emin misin? Geri alınamaz." label="Kanalı Sil" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
<p className="mono">{channel.youtubeHandle} · {channel.channelId}</p>
|
<p className="mono">{channel.youtubeHandle} · {channel.channelId}</p>
|
||||||
|
|
||||||
<div className="card">
|
<div className="card">
|
||||||
|
|||||||
Reference in New Issue
Block a user