Ebene-Add: Code = activeCode + nächste freie Nummer + Debug-Logs
Feature: neue Ebenen kriegen jetzt einen Code direkt nach dem aktuell angewaehlten (z.B. active="20" → "21" oder naechste freie darunter). Vorher war's Max+1 → sprang auf "100", neue Ebene landet am Listen-Ende und wirkte „unsichtbar" weil weit unten. Debug-Logs eingebaut um zu diagnostizieren warum Anlegen aus User- Sicht nicht funktioniert: - [EBENEN-UI] addNew → bei jedem Click + im Ebenen-Panel - [ZEICHNUNGSEBENEN-UI] addQuick → bei jedem Click + im Z-Panel - [EBENEN-UI/ZEICHNUNGSEBENEN-UI] structureKey diff → wenn der Auto-Apply-useEffect feuert - [EBENEN-UI/ZEICHNUNGSEBENEN-UI] applyAll firing now → wenn der Debounce-Timer am Ende den Backend-Call macht - [EBENEN-BE] APPLY from mode=X → Backend-Receiver - [EBENEN-BE] mode=X: y from doc.Strings n=N → was aus doc.Strings als Fallback geladen wurde So sehen wir wo's stockt — UI feuert nicht, Debounce klemmt, Backend kriegt's nicht, oder build_layers schmeisst still. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+6
-4
@@ -160,19 +160,21 @@ class EbenenBridge(panel_base.BaseBridge):
|
|||||||
if t == "READY":
|
if t == "READY":
|
||||||
self._on_ready()
|
self._on_ready()
|
||||||
elif t == "APPLY":
|
elif t == "APPLY":
|
||||||
# Jedes Panel ist autoritativ fuer SEINE Slice; die andere kommt
|
print("[EBENEN-BE] APPLY from mode={} payload-z={} payload-e={}".format(
|
||||||
# aus doc.Strings (Fallback) damit build_layers nicht mit leerer
|
self._mode,
|
||||||
# Liste arbeitet. So ueberschreiben wir nicht versehentlich die
|
len(p.get("zeichnungsebenen") or []),
|
||||||
# andere Panel-Slice mit "[]" bei Split-APPLYs.
|
len(p.get("ebenen") or [])))
|
||||||
if self._mode == "zeichnungsebenen":
|
if self._mode == "zeichnungsebenen":
|
||||||
z_payload = p.get("zeichnungsebenen") or []
|
z_payload = p.get("zeichnungsebenen") or []
|
||||||
e_raw = doc.Strings.GetValue("dossier_ebenen")
|
e_raw = doc.Strings.GetValue("dossier_ebenen")
|
||||||
e_payload = json.loads(e_raw) if e_raw else []
|
e_payload = json.loads(e_raw) if e_raw else []
|
||||||
|
print("[EBENEN-BE] mode=zeichnungsebenen: e from doc.Strings n={}".format(len(e_payload)))
|
||||||
self._apply(z_payload, e_payload, save_z=True, save_e=False)
|
self._apply(z_payload, e_payload, save_z=True, save_e=False)
|
||||||
else:
|
else:
|
||||||
e_payload = p.get("ebenen") or []
|
e_payload = p.get("ebenen") or []
|
||||||
z_raw = doc.Strings.GetValue("dossier_zeichnungsebenen")
|
z_raw = doc.Strings.GetValue("dossier_zeichnungsebenen")
|
||||||
z_payload = json.loads(z_raw) if z_raw else []
|
z_payload = json.loads(z_raw) if z_raw else []
|
||||||
|
print("[EBENEN-BE] mode=ebenen: z from doc.Strings n={}".format(len(z_payload)))
|
||||||
self._apply(z_payload, e_payload, save_z=False, save_e=True)
|
self._apply(z_payload, e_payload, save_z=False, save_e=True)
|
||||||
elif t == "LAYER_STYLE":
|
elif t == "LAYER_STYLE":
|
||||||
layer_builder.update_layer_style(doc, p["code"], p.get("color"), p.get("lw"))
|
layer_builder.update_layer_style(doc, p["code"], p.get("color"), p.get("lw"))
|
||||||
|
|||||||
@@ -110,7 +110,11 @@ export default function App() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (structureKey === appliedStructureKey) return
|
if (structureKey === appliedStructureKey) return
|
||||||
|
console.log('[EBENEN-UI] structureKey diff → schedule applyAll in 200ms', {
|
||||||
|
ebenenCount: ebenen.length, appliedCount: appliedE.length,
|
||||||
|
})
|
||||||
const t = setTimeout(() => {
|
const t = setTimeout(() => {
|
||||||
|
console.log('[EBENEN-UI] applyAll firing now', { ebenenCount: ebenen.length })
|
||||||
applyAll([], ebenen)
|
applyAll([], ebenen)
|
||||||
setAppliedE(ebenen)
|
setAppliedE(ebenen)
|
||||||
}, 200)
|
}, 200)
|
||||||
|
|||||||
@@ -88,7 +88,11 @@ export default function ZeichnungsebenenApp() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (structureKey === appliedStructureKey) return
|
if (structureKey === appliedStructureKey) return
|
||||||
|
console.log('[ZEICHNUNGSEBENEN-UI] structureKey diff → schedule applyAll in 200ms', {
|
||||||
|
zCount: zeichnungsebenen.length, appliedCount: appliedZ.length,
|
||||||
|
})
|
||||||
const t = setTimeout(() => {
|
const t = setTimeout(() => {
|
||||||
|
console.log('[ZEICHNUNGSEBENEN-UI] applyAll firing now', { zCount: zeichnungsebenen.length })
|
||||||
applyAll(zeichnungsebenen, [])
|
applyAll(zeichnungsebenen, [])
|
||||||
setAppliedZ(zeichnungsebenen)
|
setAppliedZ(zeichnungsebenen)
|
||||||
}, 200)
|
}, 200)
|
||||||
|
|||||||
@@ -352,25 +352,31 @@ export default function EbenenManager({
|
|||||||
setDeleteTarget(null)
|
setDeleteTarget(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
const nextFreeCode = () => {
|
const nextFreeAfter = (afterCode) => {
|
||||||
const codes = ebenen.map(e => parseInt(e.code, 10)).filter(n => !isNaN(n))
|
// Naechste freie Nummer NACH afterCode (= activeCode). Wenn afterCode
|
||||||
const next = codes.length ? Math.max(...codes) + 1 : 50
|
// = "20", probiert "21", dann "22", etc. Fallback: max+1.
|
||||||
return String(next).padStart(2, '0')
|
const existing = new Set(ebenen.map(e => e.code))
|
||||||
|
let n = parseInt(afterCode, 10)
|
||||||
|
if (isNaN(n)) n = 49
|
||||||
|
for (let i = 1; i < 100; i++) {
|
||||||
|
const c = String(n + i).padStart(2, '0')
|
||||||
|
if (!existing.has(c)) return c
|
||||||
|
}
|
||||||
|
const codes = ebenen.map(e => parseInt(e.code, 10)).filter(x => !isNaN(x))
|
||||||
|
return String((codes.length ? Math.max(...codes) : 49) + 1).padStart(2, '0')
|
||||||
}
|
}
|
||||||
|
|
||||||
const addNew = () => {
|
const addNew = () => {
|
||||||
// Modal-Dialog via window.prompt fuer expliziten Name-Input — selbe UX
|
|
||||||
// wie bei Ebenenkombinationen. Code wird automatisch generiert.
|
|
||||||
const name = (window.prompt('Name für neue Ebene:', 'NEU') || '').trim()
|
const name = (window.prompt('Name für neue Ebene:', 'NEU') || '').trim()
|
||||||
if (!name) return
|
if (!name) return
|
||||||
// Doppel-Namen erlauben (gibt's auch bisher), aber doppel-Codes vermeiden.
|
// Code-Vergabe: eine nach der aktuell angewaehlten Ebene.
|
||||||
const code = nextFreeCode()
|
const code = nextFreeAfter(activeCode)
|
||||||
onChange([...ebenen, {
|
const newEbene = {
|
||||||
code, name: name.toUpperCase(),
|
code, name: name.toUpperCase(),
|
||||||
color: '#888888', lw: 0.18, visible: true, locked: false,
|
color: '#888888', lw: 0.18, visible: true, locked: false,
|
||||||
}])
|
}
|
||||||
// Direkt in den Edit-Mode fuer Code-Feld — User kann Code anpassen
|
console.log('[EBENEN-UI] addNew →', { activeCode, code, name: newEbene.name, ebenenCountBefore: ebenen.length })
|
||||||
// falls die Auto-Vergabe nicht passt.
|
onChange([...ebenen, newEbene])
|
||||||
setAutoEdit({ code, field: 'code', token: Date.now() })
|
setAutoEdit({ code, field: 'code', token: Date.now() })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -94,8 +94,6 @@ export default function GeschossManager({
|
|||||||
.reduce((s, z) => s + (z.hoehe ?? 0), 0)
|
.reduce((s, z) => s + (z.hoehe ?? 0), 0)
|
||||||
|
|
||||||
const addQuick = () => {
|
const addQuick = () => {
|
||||||
// Modal-Dialog via window.prompt fuer expliziten Name-Input — selbe UX
|
|
||||||
// wie bei Ebenenkombinationen / neuer Ebene.
|
|
||||||
const defaultName = `${zeichnungsebenen.filter(z => z.isGeschoss).length + 1}OG`
|
const defaultName = `${zeichnungsebenen.filter(z => z.isGeschoss).length + 1}OG`
|
||||||
const name = (window.prompt(
|
const name = (window.prompt(
|
||||||
'Name für neue Zeichnungsebene (Geschoss):',
|
'Name für neue Zeichnungsebene (Geschoss):',
|
||||||
@@ -110,6 +108,7 @@ export default function GeschossManager({
|
|||||||
schnitthoehe: 1.0,
|
schnitthoehe: 1.0,
|
||||||
visible: true,
|
visible: true,
|
||||||
}
|
}
|
||||||
|
console.log('[ZEICHNUNGSEBENEN-UI] addQuick →', { newZ, countBefore: zeichnungsebenen.length })
|
||||||
onChange([...zeichnungsebenen, newZ])
|
onChange([...zeichnungsebenen, newZ])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user