diff --git a/app/settings/co2-galvo/[id]/co2-galvo.tsx b/app/settings/co2-galvo/[id]/co2-galvo.tsx index 9bbeaa7e..492ad601 100644 --- a/app/settings/co2-galvo/[id]/co2-galvo.tsx +++ b/app/settings/co2-galvo/[id]/co2-galvo.tsx @@ -25,15 +25,16 @@ export default function CO2GalvoSettingDetailPage() { "submission_id", "setting_title", "uploader", + // ✅ Owner (M2O) — request username explicitly "owner.id", - "owner.first_name", - "owner.last_name", - "owner.email", + "owner.username", + // Content & assets "setting_notes", "photo.filename_disk", "photo.title", "screen.filename_disk", "screen.title", + // Denormalized relations / fields "mat.name", "mat_coat.name", "mat_color.name", @@ -41,13 +42,14 @@ export default function CO2GalvoSettingDetailPage() { "mat_thickness", "source.make", "source.model", + // ✅ laser_soft is a STRING, not a relation + "laser_soft", "lens.field_size", "lens.focal_length", "lens_conf.name", "lens_apt.name", "lens_exp.name", "focus", - "laser_soft.name", "repeat_all", "fill_settings", "line_settings", @@ -67,11 +69,11 @@ export default function CO2GalvoSettingDetailPage() { if (loading) return
Loading setting...
; if (!setting) returnSetting not found.
; + // ✅ Prefer the owner's username (string). Return null if absent so claim UI shows. const ownerName = (row: any) => { const o = row?.owner; if (!o) return null; - const name = [o.first_name, o.last_name].filter(Boolean).join(" ").trim(); - return name || o.email || null; + return o.username || null; }; const formatBoolean = (val: any) => @@ -107,9 +109,10 @@ export default function CO2GalvoSettingDetailPage() { ); }; + // ✅ Point searches back to the list route under /settings const openSearchInNewTab = (value: string) => { if (!value || typeof window === "undefined") return; - const url = new URL("/co2-galvo-settings", window.location.origin); + const url = new URL("/settings/co2-galvo", window.location.origin); url.searchParams.set("query", value); const a = document.createElement("a"); a.href = url.toString(); @@ -185,8 +188,9 @@ export default function CO2GalvoSettingDetailPage() { )} + {/* ✅ Back link to list route */} ← Back to CO₂ Galvo Settings @@ -249,8 +253,9 @@ export default function CO2GalvoSettingDetailPage() { {/* Setup */}- Software: {setting.laser_soft?.name || "—"} + Software: {setting.laser_soft || "—"}
Repeat All (global): {setting.repeat_all ?? "—"}
@@ -385,16 +390,8 @@ export default function CO2GalvoSettingDetailPage() {
{ key: "pulse", label: "Pulse Width (ns)" },
{ key: "type", label: "Type" },
{ key: "dither", label: "Dither" },
- {
- key: "halftone_cell",
- label: "Cell Size (mm)",
- condition: (e: any) => e.dither === "halftone",
- },
- {
- key: "halftone_angle",
- label: "Halftone Angle",
- condition: (e: any) => e.dither === "halftone",
- },
+ { key: "halftone_cell", label: "Cell Size (mm)", condition: (e: any) => e.dither === "halftone" },
+ { key: "halftone_angle", label: "Halftone Angle", condition: (e: any) => e.dither === "halftone" },
{ key: "inversion", label: "Image Inverted" },
{ key: "interval", label: "Interval (mm)" },
{ key: "dot", label: "Dot-width Adjustment (mm)" },
diff --git a/app/settings/co2-galvo/page.tsx b/app/settings/co2-galvo/page.tsx
index 7630ed49..adb3cd9f 100644
--- a/app/settings/co2-galvo/page.tsx
+++ b/app/settings/co2-galvo/page.tsx
@@ -6,8 +6,9 @@ import Link from "next/link";
import Image from "next/image";
type Owner = {
- username?: string | null;
id?: string | number;
+ username?: string | null;
+ // keep extras harmlessly if API returns them
first_name?: string | null;
last_name?: string | null;
email?: string | null;
@@ -37,10 +38,10 @@ export default function CO2GalvoSettingsPage() {
"submission_id",
"setting_title",
"uploader",
- "owner.id", "owner.username",
- "owner.first_name",
- "owner.last_name",
- "owner.email",
+ // owner (M2O) – ensure username is requested
+ "owner.id",
+ "owner.username",
+ // assets / denorms
"photo.id",
"photo.title",
"mat.name",
@@ -63,10 +64,7 @@ export default function CO2GalvoSettingsPage() {
.finally(() => setLoading(false));
}, []);
- const ownerLabel = (o?: Owner) => {
- if (!o) return "—";
- return o.username || "—";
- };
+ const ownerLabel = (o?: Owner) => (o?.username ?? "—");
const highlight = (text?: string) => {
if (!debouncedQuery) return text || "";
@@ -93,7 +91,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
- View and explore detailed CO₂ galvo settings with context.
-
+ View and explore detailed CO₂ galvo settings with context.
+
- Browse community CO₂ galvo settings. Use search to narrow results. Click a row to view full configuration,
- notes, and photos.
-
+ Browse community CO₂ galvo settings. Use search to narrow results.
+ Click a row to view full configuration, notes, and photos.
+ Loading settings... No CO₂ galvo settings found. Loading settings... No CO₂ galvo settings found.
- View and explore detailed CO₂ galvo settings with context.
-
- Browse real-world CO₂ galvo settings from the community. Use the search to narrow results. Click any setting to view its full configuration, notes, and photos. Click any linked term to find related settings.
-
- Have a reliable galvo setting to share? Contribute to the community database.
- Loading settings... No CO₂ galvo settings found.CO₂ Galvo Settings
- setQuery(e.target.value)}
- placeholder="Search by material, owner, uploader, model, lens…"
- className="w-full mb-4 dark:bg-background border border-border rounded-md p-2"
- />
- CO₂ Galvo Settings
+ setQuery(e.target.value)}
+ placeholder="Search by material, owner, uploader, model, lens…"
+ className="w-full mb-4 dark:bg-background border border-border rounded-md p-2"
+ />
+ How to Use
- How to Use
+ Stats Summary
-
-
- Stats Summary
+
+
+ Recently Added
-
- {recent.map((s) => (
-
-
-
-
+
-
-
-
- {filtered.map((s) => (
- Photo
- Title
- Owner
- Uploader
- Material
- Coating
- Source
- Lens
-
-
+ className="underline text-accent"
+ >
+ {s.setting_title || "Untitled"}
+ {" "}
+
+ by {ownerLabel(s.owner)}
+ {s.uploader ? ` (uploader: ${s.uploader})` : ""}
+
+
))}
-
-
- {s.photo?.id ? (
-
-
+ {/* Recently Added */}
+
- Recently Added
+
+ {recent.map((s) => (
+
-
-
-
-
-
-
+
+
+
+
+
+
+ {filtered.map((s) => (
+ Photo
+ Title
+ Owner
+ Uploader
+ Material
+ Coating
+ Source
+ Lens
+
+
+ ))}
+
+
+ {s.photo?.id ? (
+
+
+
+
+
+
+
+
+
+
+ CO₂ Galvo Settings
- setQuery(e.target.value)}
- placeholder="Search settings by material, uploader, etc..."
- className="w-full mb-4 dark:bg-background border border-border rounded-md p-2"
- />
- How to Use
- Stats Summary
-
-
- Recently Added
-
- {recentSettings.map((s) => (
-
- Resources
-
-
- Submit a Setting
-
-
-
-
-
-
-
- {filtered.map((setting) => (
- Photo
- Title
- Uploader
- Material
- Coating
- Source
- Lens
-
-
- ))}
-
-
- {setting.photo?.filename_disk ? (
-
-
-
-
-
-
-
-
-
-
Software: {setting.laser_soft?.name || "—"}
+ {/* laser_soft is a string field */} +Software: {setting.laser_soft || "—"}
Repeat All (global): {setting.repeat_all ?? "—"}
Focus: {setting.focus ?? "—"} mm
-Values Focus Closer | +Values Focus Further diff --git a/app/settings/co2-gantry/page.tsx b/app/settings/co2-gantry/page.tsx index 367f42ae..c6381196 100644 --- a/app/settings/co2-gantry/page.tsx +++ b/app/settings/co2-gantry/page.tsx @@ -8,6 +8,7 @@ import Image from "next/image"; type Owner = { username?: string | null; id?: string | number; + // keep extras harmlessly in case API returns them first_name?: string | null; last_name?: string | null; email?: string | null; @@ -37,10 +38,10 @@ export default function CO2GantrySettingsPage() { "submission_id", "setting_title", "uploader", - "owner.id", "owner.username", - "owner.first_name", - "owner.last_name", - "owner.email", + // owner (M2O) – ensure username is requested + "owner.id", + "owner.username", + // assets / denorms "photo.id", "photo.title", "mat.name", @@ -64,10 +65,7 @@ export default function CO2GantrySettingsPage() { .finally(() => setLoading(false)); }, []); - const ownerLabel = (o?: Owner) => { - if (!o) return "—"; - return o.username || "—"; - }; + const ownerLabel = (o?: Owner) => (o?.username ?? "—"); const highlight = (text?: string) => { if (!debouncedQuery) return text || ""; @@ -94,7 +92,9 @@ export default function CO2GantrySettingsPage() { }, [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- Explore curated CO₂ gantry settings. Click any row to see full details. -
-+ Explore curated CO₂ gantry settings. Click any row to see full + details. +
+Loading settings...
- ) : filtered.length === 0 ? ( -No gantry settings found.
- ) : ( -| Photo | -Title | -Owner | -Uploader | -Material | -Coating | -Source | -Lens | -
|---|---|---|---|---|---|---|---|
|
- {s.photo?.id ? (
- |
-
+ {/* Recently Added */}
+
+ Recently Added+
|
- - | - | - | - | - | - |
Loading settings...
+ ) : filtered.length === 0 ? ( +No gantry settings found.
+ ) : ( +| Photo | +Title | +Owner | +Uploader | +Material | +Coating | +Source | +Lens | +
|---|---|---|---|---|---|---|---|
|
+ {s.photo?.id ? (
+ |
+ + + | ++ | + | + | + | + | + |
Loading setting...
; if (!setting) returnSetting not found.
; + // Prefer owner's username per schema const ownerName = (row: any) => { const o = row?.owner; if (!o) return null; - const name = [o.first_name, o.last_name].filter(Boolean).join(" ").trim(); - return name || o.email || null; + return o.username || null; }; const formatBoolean = (val: any) => @@ -103,7 +107,8 @@ export default function FiberSettingDetailPage() { }; const openSearchInNewTab = (value: string) => { - const url = new URL("/fiber-settings", window.location.origin); + if (!value || typeof window === "undefined") return; + const url = new URL("/settings/fiber", window.location.origin); url.searchParams.set("query", value); const a = document.createElement("a"); a.href = url.toString(); @@ -180,7 +185,7 @@ export default function FiberSettingDetailPage() {- Software: {setting.laser_soft?.name || "—"} + Software: {setting.laser_soft || "—"}
Repeat All (global): {setting.repeat_all ?? "—"} diff --git a/app/settings/uv/[id]/uv.tsx b/app/settings/uv/[id]/uv.tsx index f540cea7..6fc89d56 100644 --- a/app/settings/uv/[id]/uv.tsx +++ b/app/settings/uv/[id]/uv.tsx @@ -25,15 +25,16 @@ export default function UVSettingDetailPage() { "submission_id", "setting_title", "uploader", + // ✅ Owner (M2O) — use username (string) "owner.id", - "owner.first_name", - "owner.last_name", - "owner.email", + "owner.username", + // content & assets "setting_notes", "photo.filename_disk", "photo.title", "screen.filename_disk", "screen.title", + // relations / denorms "mat.name", "mat_coat.name", "mat_color.name", @@ -42,6 +43,7 @@ export default function UVSettingDetailPage() { "source.model", "lens.field_size", "lens.focal_length", + // misc "focus", "fill_settings", "line_settings", @@ -61,12 +63,8 @@ export default function UVSettingDetailPage() { if (loading) return
Loading setting...
; if (!setting) returnSetting not found.
; - const ownerName = (row: any) => { - const o = row?.owner; - if (!o) return null; - const name = [o.first_name, o.last_name].filter(Boolean).join(" ").trim(); - return name || o.email || null; - }; + // ✅ Prefer owner's username per schema + const ownerName = (row: any) => row?.owner?.username ?? null; const formatBoolean = (val: any) => val ? "Enabled" : val === false ? "Disabled" : "—"; @@ -88,10 +86,8 @@ export default function UVSettingDetailPage() { return ({label}:{" "} - {typeof value === "boolean" - ? formatBoolean(value) - : value ?? "—"} -
+ {typeof value === "boolean" ? formatBoolean(value) : value ?? "—"} + ); })}