list and details cleanup
This commit is contained in:
parent
6829f2840c
commit
2e8297d426
2 changed files with 125 additions and 135 deletions
|
|
@ -51,32 +51,27 @@ export default function CO2GalvoList({
|
|||
const [rows, setRows] = useState<Row[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [localQuery, setLocalQuery] = useState(queryText ?? "");
|
||||
|
||||
// id -> username map (fix showing UUIDs)
|
||||
const [ownerMap, setOwnerMap] = useState<Record<string, string>>({});
|
||||
// current user id for "Edit" visibility
|
||||
const [meId, setMeId] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (queryText !== undefined) setLocalQuery(queryText);
|
||||
}, [queryText]);
|
||||
|
||||
// Load current user id
|
||||
// who am I?
|
||||
useEffect(() => {
|
||||
let alive = true;
|
||||
let live = true;
|
||||
(async () => {
|
||||
try {
|
||||
const r = await fetch(`${API}/users/me?fields=id`, { credentials: "include", cache: "no-store" });
|
||||
if (!r.ok) return;
|
||||
const j = await r.json().catch(() => null);
|
||||
const id = j?.data?.id ?? j?.id ?? null;
|
||||
if (alive) setMeId(id ? String(id) : null);
|
||||
const r = await fetch(`/api/dx/users/me?fields=id`, { cache: "no-store", credentials: "include" });
|
||||
const j = await readJson(r);
|
||||
const idVal = j?.data?.id ?? j?.id ?? null;
|
||||
if (live) setMeId(idVal ? String(idVal) : null);
|
||||
} catch {
|
||||
/* ignore */
|
||||
if (live) setMeId(null);
|
||||
}
|
||||
})();
|
||||
return () => {
|
||||
alive = false;
|
||||
live = false;
|
||||
};
|
||||
}, []);
|
||||
|
||||
|
|
@ -113,62 +108,9 @@ export default function CO2GalvoList({
|
|||
};
|
||||
}, []);
|
||||
|
||||
// Resolve owner usernames when only id/UUID is present
|
||||
useEffect(() => {
|
||||
const ids = new Set<string>();
|
||||
for (const r of rows) {
|
||||
const o = r.owner;
|
||||
if (!o) continue;
|
||||
if (typeof o === "string" || typeof o === "number") {
|
||||
const id = String(o);
|
||||
if (!ownerMap[id]) ids.add(id);
|
||||
} else {
|
||||
const id = o.id != null ? String(o.id) : "";
|
||||
const hasUsername = !!o.username;
|
||||
if (id && !hasUsername && !ownerMap[id]) ids.add(id);
|
||||
}
|
||||
}
|
||||
if (!ids.size) return;
|
||||
|
||||
let cancelled = false;
|
||||
(async () => {
|
||||
const all = Array.from(ids);
|
||||
const updates: Record<string, string> = {};
|
||||
const chunkSize = 100;
|
||||
for (let i = 0; i < all.length; i += chunkSize) {
|
||||
const slice = all.slice(i, i + chunkSize);
|
||||
const qs = new URLSearchParams();
|
||||
qs.set("fields", "id,username");
|
||||
qs.set("limit", String(slice.length));
|
||||
qs.set("filter[id][_in]", slice.join(","));
|
||||
const url = `${API}/users?${qs.toString()}`;
|
||||
try {
|
||||
const r = await fetch(url, { credentials: "include", cache: "no-store" });
|
||||
if (!r.ok) continue;
|
||||
const j = await r.json().catch(() => null);
|
||||
const arr: Array<{ id: string | number; username?: string | null }> = j?.data || [];
|
||||
for (const u of arr) {
|
||||
updates[String(u.id)] = u.username || String(u.id);
|
||||
}
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
if (!cancelled && Object.keys(updates).length) {
|
||||
setOwnerMap((prev) => ({ ...prev, ...updates }));
|
||||
}
|
||||
})();
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [rows, ownerMap]);
|
||||
|
||||
const ownerLabel = (o: Owner) => {
|
||||
if (!o) return "—";
|
||||
if (typeof o === "string" || typeof o === "number") {
|
||||
const id = String(o);
|
||||
return ownerMap[id] || id;
|
||||
}
|
||||
if (typeof o === "string" || typeof o === "number") return String(o);
|
||||
return (
|
||||
o.username ||
|
||||
[o.first_name, o.last_name].filter(Boolean).join(" ").trim() ||
|
||||
|
|
@ -177,15 +119,13 @@ export default function CO2GalvoList({
|
|||
);
|
||||
};
|
||||
|
||||
const isMine = (o: Owner) => {
|
||||
const isMine = (o: Owner): boolean => {
|
||||
if (!meId || !o) return false;
|
||||
if (typeof o === "string" || typeof o === "number") return String(o) === meId;
|
||||
if (o.id != null) return String(o.id) === meId;
|
||||
return false;
|
||||
};
|
||||
|
||||
const withEditParam = (href: string) => (href.includes("?") ? `${href}&edit=1` : `${href}?edit=1`);
|
||||
|
||||
const filtered = useMemo(() => {
|
||||
const q = (localQuery || "").toLowerCase();
|
||||
if (!q) return rows;
|
||||
|
|
@ -194,7 +134,9 @@ export default function CO2GalvoList({
|
|||
.filter(Boolean)
|
||||
.some((v) => String(v).toLowerCase().includes(q))
|
||||
);
|
||||
}, [rows, localQuery, ownerMap]);
|
||||
}, [rows, localQuery]);
|
||||
|
||||
const addEditParam = (href: string) => (href.includes("?") ? `${href}&edit=1` : `${href}?edit=1`);
|
||||
|
||||
return (
|
||||
<div className="space-y-3">
|
||||
|
|
@ -226,22 +168,25 @@ export default function CO2GalvoList({
|
|||
</thead>
|
||||
<tbody className="divide-y">
|
||||
{filtered.map((r) => {
|
||||
const href = linkFor(r.submission_id);
|
||||
const mine = isMine(r.owner);
|
||||
const ownerText = ownerLabel(r.owner) + (mine ? " (you)" : "");
|
||||
const viewHref = linkFor(r.submission_id);
|
||||
const editHref = addEditParam(viewHref);
|
||||
return (
|
||||
<tr key={r.submission_id} className="hover:bg-muted/40">
|
||||
<td className="px-2 py-2 truncate">
|
||||
<Link href={href} className="underline">
|
||||
<Link href={viewHref} className="underline">
|
||||
{r.setting_title || "Untitled"}
|
||||
</Link>
|
||||
</td>
|
||||
<td className="px-2 py-2 truncate">{ownerLabel(r.owner)}</td>
|
||||
<td className="px-2 py-2 truncate">{ownerText}</td>
|
||||
<td className="px-2 py-2 truncate">{r.mat?.name || "—"}</td>
|
||||
<td className="px-2 py-2 truncate">{r.mat_coat?.name || "—"}</td>
|
||||
<td className="px-2 py-2 truncate">{r.source?.model || "—"}</td>
|
||||
<td className="px-2 py-2 truncate">{r.lens?.field_size || "—"}</td>
|
||||
<td className="px-2 py-2">
|
||||
{isMine(r.owner) ? (
|
||||
<Link href={withEditParam(href)} className="underline">
|
||||
{mine ? (
|
||||
<Link href={editHref} className="underline">
|
||||
Edit
|
||||
</Link>
|
||||
) : (
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue