The arrow that unbound half of wire(), and openings for the unit's top
Eric: styled buttons look great, but edit-description does nothing. One missing character — .forEach(b = instead of (b => — turned the callback into a strict-mode ReferenceError that killed wire() midway: everything bound before the typo (rename, duplicate) worked, everything after (edit description, its save, the add-opening submit) silently never bound, and the throw hid inside an async refresh where no pageerror fires. Fixed and verified live: description edits save, add-opening works again. And Eric's next question answered in code: things live ON the furniture too. The add-opening form gains an "at the top" checkbox — new openings (or whole grids) land above the existing rows instead of below, so "on top of the Kallax" is one labeled opening away. Give it real width/depth and the height to your ceiling, or no sizes for a no-limit display spot. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016jXZFSTZQKzAC8fqpWSz9g
This commit is contained in:
co-authored by
Claude Fable 5
parent
2f526335e8
commit
4ce7706521
@@ -166,6 +166,52 @@
|
||||
"depth_in": 9.5
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Library Left Shelving",
|
||||
"description": "To the right of the Kallax",
|
||||
"openings": [
|
||||
{
|
||||
"label": "A1",
|
||||
"zone": "",
|
||||
"width_in": 23.25,
|
||||
"height_in": 10.25,
|
||||
"depth_in": 9.5,
|
||||
"id": "library-right-shelving-2-a1"
|
||||
},
|
||||
{
|
||||
"label": "B1",
|
||||
"zone": "",
|
||||
"width_in": 23.25,
|
||||
"height_in": 10.25,
|
||||
"depth_in": 9.5,
|
||||
"id": "library-right-shelving-2-b1"
|
||||
},
|
||||
{
|
||||
"label": "C1",
|
||||
"zone": "",
|
||||
"width_in": 23.25,
|
||||
"height_in": 10.25,
|
||||
"depth_in": 9.5,
|
||||
"id": "library-right-shelving-2-c1"
|
||||
},
|
||||
{
|
||||
"label": "D1",
|
||||
"zone": "",
|
||||
"width_in": 23.25,
|
||||
"height_in": 10.25,
|
||||
"depth_in": 9.5,
|
||||
"id": "library-right-shelving-2-d1"
|
||||
},
|
||||
{
|
||||
"label": "E1",
|
||||
"zone": "",
|
||||
"width_in": 23.25,
|
||||
"height_in": 10.25,
|
||||
"depth_in": 9.5,
|
||||
"id": "library-right-shelving-2-e1"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -552,6 +552,9 @@ select {
|
||||
margin-bottom: .8rem; }
|
||||
.orow { display: flex; gap: .5rem; }
|
||||
.formlabel { margin: 1.2rem 0 .35rem; }
|
||||
.editform label.attop { flex-direction: row; align-items: center; gap: .35rem;
|
||||
text-transform: none; letter-spacing: normal; align-self: end;
|
||||
padding-bottom: .45rem; }
|
||||
.renamerow:not([hidden]) { display: flex; gap: .4rem; margin: .3rem 0 .6rem; }
|
||||
.renamerow input { font: inherit; font-size: .9rem;
|
||||
border: 2px solid var(--board-edge); border-radius: var(--radius);
|
||||
|
||||
@@ -148,6 +148,7 @@ function unitBlock(u) {
|
||||
<label>Columns <input name="cols" inputmode="numeric" size="3" value="1"></label>
|
||||
<label>Label <input name="label" placeholder="wide top — for a single opening"></label>
|
||||
<label>Zone <input name="zone"></label>
|
||||
<label class="attop"><input type="checkbox" name="at_top"> at the top</label>
|
||||
<label>W <input name="width_in" size="5" placeholder="13.25"></label>
|
||||
<label>H <input name="height_in" size="5" placeholder="13.25"></label>
|
||||
<label>D <input name="depth_in" size="5" placeholder="15.4"></label>
|
||||
@@ -325,7 +326,7 @@ function wire() {
|
||||
name: b.dataset.unit,
|
||||
new_name: b.closest(".renamerow").querySelector("input").value,
|
||||
}));
|
||||
document.querySelectorAll(".editunitdesc").forEach(b =
|
||||
document.querySelectorAll(".editunitdesc").forEach(b =>
|
||||
b.onclick = () => {
|
||||
const form = b.closest(".unitdesc").querySelector(".descform");
|
||||
form.hidden = !form.hidden;
|
||||
@@ -359,6 +360,7 @@ function wire() {
|
||||
try {
|
||||
await post("/api/furniture/add-openings", {
|
||||
unit: form.dataset.unit, zone: f.zone.value,
|
||||
at_top: f.at_top.checked,
|
||||
...(grid ? {rows, cols} : {label: f.label.value}),
|
||||
width_in: parseFloat(f.width_in.value) || null,
|
||||
height_in: parseFloat(f.height_in.value) || null,
|
||||
|
||||
@@ -237,6 +237,7 @@ class OpeningsBody(BaseModel):
|
||||
|
||||
unit: str
|
||||
zone: str = ""
|
||||
at_top: bool = False # new openings land ABOVE the existing rows
|
||||
label: str = "" # single mode
|
||||
rows: int = 0 # grid mode when rows*cols > 0
|
||||
cols: int = 0
|
||||
@@ -1307,6 +1308,14 @@ def create_app(
|
||||
# a half-sized opening would silently become limitless:
|
||||
# fit checks need all three axes, or none (virtual)
|
||||
raise HTTPException(400, "give all three interior dimensions, or none")
|
||||
added: list[dict] = []
|
||||
|
||||
def place(new_openings):
|
||||
if body.at_top:
|
||||
unit["openings"][:0] = new_openings
|
||||
else:
|
||||
unit["openings"].extend(new_openings)
|
||||
|
||||
if body.rows and body.cols:
|
||||
# a second grid on the same unit continues the row letters
|
||||
# (A1 already exists -> next section starts at C, say):
|
||||
@@ -1329,7 +1338,7 @@ def create_app(
|
||||
break
|
||||
for c in range(body.cols):
|
||||
label = f"{letters}{c + 1}"
|
||||
unit["openings"].append(
|
||||
added.append(
|
||||
{
|
||||
"id": new_opening_id(units, unit["name"], label),
|
||||
"label": label,
|
||||
@@ -1341,7 +1350,7 @@ def create_app(
|
||||
label = body.label.strip()
|
||||
if not label:
|
||||
raise HTTPException(400, "the opening needs a label")
|
||||
unit["openings"].append(
|
||||
added.append(
|
||||
{
|
||||
"id": new_opening_id(units, unit["name"], label),
|
||||
"label": label,
|
||||
@@ -1349,6 +1358,7 @@ def create_app(
|
||||
**dims,
|
||||
}
|
||||
)
|
||||
place(added)
|
||||
|
||||
return _mutate_furniture(add)
|
||||
|
||||
|
||||
@@ -978,3 +978,34 @@ def test_rename_unit_keeps_openings_locations_and_description(tmp_path):
|
||||
).status_code
|
||||
== 409
|
||||
)
|
||||
|
||||
|
||||
def test_add_openings_at_top(tmp_path):
|
||||
"""Things live ON the furniture too: an opening added at_top lands
|
||||
above the existing rows and renders first in the wall diagram."""
|
||||
web, cfg = _web(tmp_path, {})
|
||||
web.post("/api/furniture/add-unit", json={"name": "Kallax"})
|
||||
web.post(
|
||||
"/api/furniture/add-openings",
|
||||
json={
|
||||
"unit": "Kallax",
|
||||
"rows": 2,
|
||||
"cols": 2,
|
||||
"width_in": 13.25,
|
||||
"height_in": 13.25,
|
||||
"depth_in": 15.4,
|
||||
},
|
||||
)
|
||||
web.post(
|
||||
"/api/furniture/add-openings",
|
||||
json={
|
||||
"unit": "Kallax",
|
||||
"label": "on top",
|
||||
"zone": "display",
|
||||
"at_top": True,
|
||||
},
|
||||
)
|
||||
labels = [
|
||||
o["label"] for o in web.get("/api/shelves").json()["units"][0]["openings"]
|
||||
]
|
||||
assert labels == ["on top", "A1", "A2", "B1", "B2"]
|
||||
|
||||
Reference in New Issue
Block a user