diff --git a/app/api/dx/[...path]/route.ts b/app/api/dx/[...path]/route.ts new file mode 100644 index 00000000..ac842cbb --- /dev/null +++ b/app/api/dx/[...path]/route.ts @@ -0,0 +1,23 @@ +// app/api/dx/[...path]/route.ts +import { NextResponse } from "next/server"; +import { requireBearer } from "@/app/api/_lib/auth"; + +const BASE = (process.env.DIRECTUS_URL || "").replace(/\/$/, ""); + +export async function GET(req: Request, { params }: { params: { path: string[] } }) { + const bearer = requireBearer(req); + const search = new URL(req.url).search || ""; + const path = params.path.join("/"); + const url = `${BASE}/${path}${search}`; + + const res = await fetch(url, { + headers: { Accept: "application/json", Authorization: `Bearer ${bearer}` }, + cache: "no-store", + }); + + const body = await res.text(); + return new NextResponse(body, { + status: res.status, + headers: { "content-type": res.headers.get("content-type") || "application/json" }, + }); +} diff --git a/app/settings/co2-galvo/[id]/co2-galvo.tsx b/app/settings/co2-galvo/[id]/co2-galvo.tsx index 40933e12..f32a2169 100644 --- a/app/settings/co2-galvo/[id]/co2-galvo.tsx +++ b/app/settings/co2-galvo/[id]/co2-galvo.tsx @@ -1,3 +1,4 @@ +// app/settings/co2-galvo/[id]/co2-galvo.tsx "use client"; import { useEffect, useState } from "react"; @@ -20,8 +21,12 @@ export default function CO2GalvoSettingDetailPage() { "submission_id", "setting_title", "uploader", + + // 👇 include parent + requested subfields + "owner", "owner.id", "owner.username", + "setting_notes", "photo.filename_disk", "photo.title", @@ -40,17 +45,19 @@ export default function CO2GalvoSettingDetailPage() { "lens_apt.name", "lens_exp.name", "focus", + + // string-or-relation safe "laser_soft", "laser_soft.name", + "repeat_all", "fill_settings", "line_settings", "raster_settings", ].join(","); - const url = - `/api/dx/items/settings_co2gal/${encodeURIComponent(String(id))}` + - `?fields=${encodeURIComponent(fields)}`; + // use the authenticated proxy (sends ma_at automatically) + const url = `/api/dx/items/settings_co2gal/${encodeURIComponent(String(id))}?fields=${fields}`; setLoading(true); fetch(url, { cache: "no-store", credentials: "include" }) @@ -72,6 +79,7 @@ export default function CO2GalvoSettingDetailPage() { if (loading) return
Loading setting...
; if (!setting) returnSetting not found.
; + // ---- display helpers ---- const ownerDisplay: string = typeof setting?.owner === "object" ? (setting.owner?.username ?? setting.owner?.id ?? "—") diff --git a/app/settings/co2-galvo/page.tsx b/app/settings/co2-galvo/page.tsx index 5d7af485..59098a94 100644 --- a/app/settings/co2-galvo/page.tsx +++ b/app/settings/co2-galvo/page.tsx @@ -1,9 +1,9 @@ "use client"; import { useEffect, useState, useMemo } from "react"; -import { useSearchParams } from "next/navigation"; import Link from "next/link"; import Image from "next/image"; +import { useSearchParams } from "next/navigation"; type Owner = { id?: string | number; @@ -30,14 +30,13 @@ export default function CO2GalvoSettingsPage() { }, [query]); useEffect(() => { + // ✅ use the auth proxy + include cookie so expansions (owner.*) work const fields = [ "submission_id", "setting_title", "uploader", - // ensure relation expands "owner.id", "owner.username", - // assets / denorms "photo.id", "photo.title", "mat.name", @@ -46,8 +45,10 @@ export default function CO2GalvoSettingsPage() { "lens.field_size", ].join(","); - // IMPORTANT: go through our proxy so the user's ma_at cookie is used - const url = `/api/dx/items/settings_co2gal?fields=${encodeURIComponent(fields)}&limit=-1`; + const url = + `/api/dx/items/settings_co2gal` + + `?fields=${encodeURIComponent(fields)}` + + `&limit=-1`; fetch(url, { cache: "no-store", credentials: "include" }) .then(async (res) => { @@ -65,7 +66,9 @@ export default function CO2GalvoSettingsPage() { .finally(() => setLoading(false)); }, []); - const ownerLabel = (o?: Owner) => (o?.username ?? "—"); + // robust owner label + const ownerLabel = (o?: Owner) => + (o && (o.username || String(o.id || ""))) || "—"; const highlight = (text?: string) => { if (!debouncedQuery) return text || ""; @@ -92,7 +95,9 @@ export default function CO2GalvoSettingsPage() { }, [settings, debouncedQuery]); const total = settings.length; - const uniqueMaterials = new Set(settings.map((s) => s.mat?.name).filter(Boolean)).size; + const uniqueMaterials = new Set( + settings.map((s) => s.mat?.name).filter(Boolean) + ).size; const lensCounts = settings.reduce((acc: Record