feat(presets): admin preset stories (premade example videos) end-to-end
Build backend images / build content-svc (push) Failing after 31s
Build backend images / build file-svc (push) Failing after 31s
Build backend images / build gateway (push) Failing after 31s
Build backend images / build identity-svc (push) Failing after 30s
Build backend images / build notification-svc (push) Failing after 30s
Build backend images / build render-svc (push) Failing after 31s
Build backend images / build studio-svc (push) Failing after 31s
Build backend images / build content-svc (push) Failing after 31s
Build backend images / build file-svc (push) Failing after 31s
Build backend images / build gateway (push) Failing after 31s
Build backend images / build identity-svc (push) Failing after 30s
Build backend images / build notification-svc (push) Failing after 30s
Build backend images / build render-svc (push) Failing after 31s
Build backend images / build studio-svc (push) Failing after 31s
Epic A — admins author premade example videos per template; users pick one on the template detail page to start a pre-filled project. Backend (content-svc): - PresetStory DTOs + PresetStoryService (admin CRUD + public published-only filter via role check + soft-delete) + PresetStoriesController (/v1/preset-stories) - DI registration; gateway route /v1/preset-stories (optionalAuth, public read) Frontend: - ProjectPresetStories admin authoring UI (name/description/demo upload/published/ sort + scene picker with order+duration + advanced scenes_spa); «ویدیوهای نمونه» button + modal in ProjectsAdmin - TemplateDetailExamples renders real published stories (image/video preview, hover → "use this example" → creates a pre-bound project), falls back to placeholders when none; selected aspect's variant id keys the fetch - public /api/preset-stories route; preset_story_id plumbed through createProjectFromTemplate + projects POST route; usePreset i18n (fa+en) Verified: full CRUD via gateway (public hides unpublished); creating a project with presetStoryId persists selected_preset_story_id on the saved project. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
import { gatewayFetch } from "@/lib/api/gateway";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
||||
|
||||
/**
|
||||
* Public list of PUBLISHED preset stories (premade example videos) for a content
|
||||
* project. No auth → the gateway/content-svc returns published stories only, which
|
||||
* is exactly what the template-detail "example videos" section needs.
|
||||
*/
|
||||
export async function GET(request: Request) {
|
||||
const projectId = new URL(request.url).searchParams.get("project_id") ?? "";
|
||||
if (!UUID_RE.test(projectId)) {
|
||||
return NextResponse.json({ stories: [] });
|
||||
}
|
||||
try {
|
||||
const res = await gatewayFetch(`/v1/preset-stories/?project_id=${projectId}`);
|
||||
if (!res.ok) return NextResponse.json({ stories: [] });
|
||||
const data = await res.json().catch(() => null);
|
||||
const stories = Array.isArray(data) ? data : (data?.data ?? []);
|
||||
return NextResponse.json({ stories });
|
||||
} catch {
|
||||
return NextResponse.json({ stories: [] });
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,8 @@ const createProjectSchema = z.object({
|
||||
// The original/template project id may be passed explicitly or carried inside
|
||||
// scene_data.templateId by the legacy create helpers.
|
||||
original_project_id: z.string().uuid().optional(),
|
||||
// Start the project pre-bound to an admin-authored preset story (premade video).
|
||||
preset_story_id: z.string().uuid().optional(),
|
||||
});
|
||||
|
||||
export async function GET() {
|
||||
@@ -109,6 +111,7 @@ export async function POST(request: Request) {
|
||||
const result = await createSavedProject({
|
||||
original_project_id: contentProjectId,
|
||||
name: parsed.data.name,
|
||||
preset_story_id: parsed.data.preset_story_id,
|
||||
copy_default_values: true,
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user