feat(admin): category SEO fields, Templates admin, safe project PATCH
Build backend images / build content-svc (push) Failing after 21s
Build backend images / build file-svc (push) Failing after 3m49s
Build backend images / build gateway (push) Failing after 1m2s
Build backend images / build identity-svc (push) Failing after 1m1s
Build backend images / build notification-svc (push) Failing after 1m2s
Build backend images / build render-svc (push) Failing after 1m0s
Build backend images / build studio-svc (push) Failing after 58s
Build backend images / build content-svc (push) Failing after 21s
Build backend images / build file-svc (push) Failing after 3m49s
Build backend images / build gateway (push) Failing after 1m2s
Build backend images / build identity-svc (push) Failing after 1m1s
Build backend images / build notification-svc (push) Failing after 1m2s
Build backend images / build render-svc (push) Failing after 1m0s
Build backend images / build studio-svc (push) Failing after 58s
- categories/tags admin forms: add meta title/description/keywords, bot-follow,
sort, is_active (backend already supported these)
- new Templates admin (/admin/templates): container CRUD with description,
keywords, publishing, premium, primary mode, category/tag assignment, plus
editable per-variant aspect & resolution
- content-svc: PATCH /v1/projects/{id} partial update so aspect/resolution edits
never wipe render/colour data (SharedColorsSvg, RenderAepComp, Folder)
- admin resource proxy: add PATCH passthrough
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -17,6 +17,7 @@ export default async function AdminLayout({
|
||||
const t = await getTranslations("auto.appAdminLayout");
|
||||
const links: { href: string; label: string }[] = [
|
||||
{ href: "/admin/categories", label: t("categories") },
|
||||
{ href: "/admin/templates", label: t("templates") },
|
||||
{ href: "/admin/tags", label: t("tags") },
|
||||
{ href: "/admin/fonts", label: t("fonts") },
|
||||
{ href: "/admin/blogs", label: t("blogs") },
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { TemplatesAdmin } from "@/components/admin/TemplatesAdmin";
|
||||
|
||||
export default function Page() {
|
||||
return <TemplatesAdmin />;
|
||||
}
|
||||
@@ -19,7 +19,7 @@ export const dynamic = "force-dynamic";
|
||||
async function forward(
|
||||
req: NextRequest,
|
||||
path: string[],
|
||||
method: "GET" | "POST" | "PUT" | "DELETE"
|
||||
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE"
|
||||
): Promise<NextResponse> {
|
||||
const token = await getAccessToken();
|
||||
if (!token) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||||
@@ -37,7 +37,7 @@ async function forward(
|
||||
const gwPath = `/v1/${joined}${path.length === 1 && method === "GET" ? "/" : ""}${search}`;
|
||||
|
||||
let body: string | undefined;
|
||||
if (method === "POST" || method === "PUT") {
|
||||
if (method === "POST" || method === "PUT" || method === "PATCH") {
|
||||
const json = await req.json().catch(() => ({}));
|
||||
body = JSON.stringify(json);
|
||||
}
|
||||
@@ -91,6 +91,9 @@ export async function POST(req: NextRequest, ctx: { params: { path: string[] } }
|
||||
export async function PUT(req: NextRequest, ctx: { params: { path: string[] } }) {
|
||||
return forward(req, ctx.params.path, "PUT");
|
||||
}
|
||||
export async function PATCH(req: NextRequest, ctx: { params: { path: string[] } }) {
|
||||
return forward(req, ctx.params.path, "PATCH");
|
||||
}
|
||||
export async function DELETE(req: NextRequest, ctx: { params: { path: string[] } }) {
|
||||
return forward(req, ctx.params.path, "DELETE");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user