Web: Etiketten-Export signalisiert mitexportierte Unterkategorien
Waehlt man beim P-touch-Export eine Kategorie, schliesst der Server ihre Unterkategorien mit ein – das war im UI nicht sichtbar. Jetzt erscheinen die Unterkategorien einer gewaehlten Kategorie als „enthalten" (angehakt, deaktiviert, gedimmt); gewaehlte Oberkategorien mit Unterkategorien tragen „inkl. Unterkategorien", nicht gewaehlte einen „+ Unterkategorien"-Hinweis. Der Einleitungstext erklaert es zusaetzlich. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -129,6 +129,23 @@ export default function Transfer() {
|
||||
}
|
||||
}
|
||||
|
||||
// Gegenstands-Kategorien als Baum; für die Anzeige, welche Unterkategorien
|
||||
// durch eine gewählte Oberkategorie automatisch mitkommen.
|
||||
const objTree = asTree(categories).filter((c) => c.tracking === "object");
|
||||
const parentOf = Object.fromEntries(categories.map((c) => [c.id, c.parent_id]));
|
||||
const nameById = Object.fromEntries(categories.map((c) => [c.id, c.name]));
|
||||
const hatKinder = (id) => objTree.some((o) => o.parent_id === id);
|
||||
// Name der nächsten ausgewählten Oberkategorie (oder null) – dann ist diese
|
||||
// Kategorie „über die Oberkategorie enthalten".
|
||||
function abgedecktVon(id) {
|
||||
let p = parentOf[id];
|
||||
while (p != null) {
|
||||
if (selCats.has(p)) return nameById[p];
|
||||
p = parentOf[p];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="page-head">
|
||||
@@ -217,8 +234,9 @@ export default function Transfer() {
|
||||
<p className="muted small mt-0">
|
||||
Je Einzelstück eine Zeile: <strong>QR-Inhalt</strong>, UID, Produkt, Marke, Kategorie,
|
||||
Lagerort. In der Etiketten-Software (z.B. P-touch) als <strong>Datenbank</strong>{" "}
|
||||
verknüpfen – sie erzeugt QR-Code und Text automatisch. Kategorien wählen
|
||||
(Unterkategorien sind enthalten); ohne Auswahl kommen alle Einzelstücke.
|
||||
verknüpfen – sie erzeugt QR-Code und Text automatisch. Ohne Auswahl kommen alle
|
||||
Einzelstücke. Wählst du eine Kategorie, kommen ihre <strong>Unterkategorien
|
||||
automatisch mit</strong> – sie erscheinen unten als „enthalten".
|
||||
</p>
|
||||
<label style={{ maxWidth: 340 }}>
|
||||
Trennzeichen (für die Etiketten-Software)
|
||||
@@ -229,14 +247,31 @@ export default function Transfer() {
|
||||
</select>
|
||||
</label>
|
||||
<div className="kat-check-liste">
|
||||
{asTree(categories).filter((c) => c.tracking === "object").map((c) => (
|
||||
<label key={c.id} className="check-inline" style={{ paddingLeft: c.depth * 18 }}>
|
||||
<input type="checkbox" checked={selCats.has(c.id)}
|
||||
onChange={(e) => toggleCat(c.id, e.target.checked)} />
|
||||
<span>{c.name}</span>
|
||||
</label>
|
||||
))}
|
||||
{asTree(categories).filter((c) => c.tracking === "object").length === 0 && (
|
||||
{objTree.map((c) => {
|
||||
const enthalten = abgedecktVon(c.id);
|
||||
const direkt = selCats.has(c.id);
|
||||
return (
|
||||
<label key={c.id}
|
||||
className={`check-inline ${enthalten ? "kat-enthalten" : ""}`}
|
||||
style={{ paddingLeft: c.depth * 18 }}
|
||||
title={enthalten ? `über „${enthalten}" enthalten` : undefined}>
|
||||
<input type="checkbox" checked={direkt || enthalten != null}
|
||||
disabled={enthalten != null}
|
||||
onChange={(e) => toggleCat(c.id, e.target.checked)} />
|
||||
<span>{c.name}</span>
|
||||
{enthalten != null && (
|
||||
<span className="badge nowrap">enthalten</span>
|
||||
)}
|
||||
{enthalten == null && direkt && hatKinder(c.id) && (
|
||||
<span className="badge nowrap">inkl. Unterkategorien</span>
|
||||
)}
|
||||
{enthalten == null && !direkt && hatKinder(c.id) && (
|
||||
<span className="muted small nowrap">+ Unterkategorien</span>
|
||||
)}
|
||||
</label>
|
||||
);
|
||||
})}
|
||||
{objTree.length === 0 && (
|
||||
<span className="muted small">Noch keine Gegenstands-Kategorien.</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -891,6 +891,8 @@ select.zeitraum:hover { color: var(--text); }
|
||||
.clean-list li { display: flex; align-items: center; gap: var(--sp-2); padding: 6px 8px; background: var(--surface-2); border-radius: 8px; }
|
||||
.check-inline { display: flex; align-items: center; gap: var(--sp-2); }
|
||||
.check-inline input { width: auto; margin: 0; }
|
||||
/* Über eine gewählte Oberkategorie automatisch enthaltene Unterkategorie. */
|
||||
.kat-enthalten { opacity: 0.6; }
|
||||
.feldkopf { display: inline-flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
|
||||
tr.row-active { background: var(--surface-2); }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user