Initial commit of Descrybe v2 without local scratch artifacts.

Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
This commit is contained in:
2026-08-09 22:47:43 +02:00
commit 8580c996c3
1285 changed files with 325780 additions and 0 deletions
+83
View File
@@ -0,0 +1,83 @@
/**
* Products list selection + export id helpers (node:test friendly).
*/
export function idsEqual(a: string | number, b: string | number): boolean {
return String(a) === String(b);
}
export function selectionHas(
selected: ReadonlyArray<string | number>,
id: string | number
): boolean {
return selected.some((x) => idsEqual(x, id));
}
/** Immutable add/remove for the products table checkbox selection. */
export function setProductSelected(
selected: ReadonlyArray<string | number>,
id: string | number,
selectedOn: boolean
): Array<string | number> {
if (selectedOn) {
if (selectionHas(selected, id)) return [...selected];
return [...selected, id];
}
return selected.filter((x) => !idsEqual(x, id));
}
/** Toggle all visible (selectable) ids into / out of the selection. */
export function toggleSelectAllIds(
selected: ReadonlyArray<string | number>,
visibleIds: ReadonlyArray<string | number>
): Array<string | number> {
const allOn =
visibleIds.length > 0 && visibleIds.every((id) => selectionHas(selected, id));
if (allOn) {
return selected.filter((id) => !visibleIds.some((v) => idsEqual(v, id)));
}
const merged = [...selected];
for (const id of visibleIds) {
if (!selectionHas(merged, id)) merged.push(id);
}
return merged;
}
export function selectableProductIds(
products: ReadonlyArray<{ id: string | number; processing_status?: string | null }>
): Array<string | number> {
return products
.filter((p) => p.processing_status !== "processing")
.map((p) => p.id);
}
/** Raw product ids for processing jobs (raw tab uses row id; processed uses raw_product_id). */
export function selectedRawProductIds(
products: ReadonlyArray<{
id: string | number;
raw_product_id?: string | number | null;
}>,
selected: ReadonlyArray<string | number>,
kind: "processed" | "raw"
): string[] {
const ids: string[] = [];
for (const p of products) {
if (!selectionHas(selected, p.id)) continue;
if (kind === "raw") ids.push(String(p.id));
else if (p.raw_product_id) ids.push(String(p.raw_product_id));
}
return ids;
}
export function toExportProductIds(selected: ReadonlyArray<string | number>): string[] {
return selected.map(String);
}
export function canOpenExportDialog(selectedCount: number): boolean {
return selectedCount > 0;
}
/** Map processing_status to ProductStatusBadge branch key. */
export function normalizeStatusBadgeLabel(status?: string | null): string {
return String(status ?? "").trim() || "unknown";
}