diff --git a/.playwright-mcp/page-2026-08-09T20-21-23-880Z.yml b/.playwright-mcp/page-2026-08-09T20-21-23-880Z.yml new file mode 100644 index 0000000..c7f63dd --- /dev/null +++ b/.playwright-mcp/page-2026-08-09T20-21-23-880Z.yml @@ -0,0 +1,399 @@ +- generic [active] [ref=e1]: + - link "Skip to content" [ref=e2] [cursor=pointer]: + - /url: "#main" + - generic [ref=e3]: + - link "bggpipe shelf → BGG pipeline" [ref=e4] [cursor=pointer]: + - /url: / + - generic [ref=e5]: + - text: bggpipe + - generic [ref=e6]: shelf → BGG pipeline + - navigation "Primary" [ref=e7]: + - link "Pipeline" [ref=e8] [cursor=pointer]: + - /url: / + - link "Photos 4" [ref=e9] [cursor=pointer]: + - /url: /photos + - text: Photos + - generic [ref=e10]: "4" + - link "Titles" [ref=e11] [cursor=pointer]: + - /url: /titles + - link "Review" [ref=e12] [cursor=pointer]: + - /url: /review + - link "Queue" [ref=e13] [cursor=pointer]: + - /url: /queue + - link "Library" [ref=e14] [cursor=pointer]: + - /url: /library + - link "Shelves" [ref=e15] [cursor=pointer]: + - /url: /shelves + - link "Help" [ref=e16] [cursor=pointer]: + - /url: /help + - figure "art by Juniper" [ref=e17]: + - img "the bggpipe piper — a bagpiper whose bag is a board game box" [ref=e18] + - generic [ref=e20]: BoardGameGeek and BGG are trademarks of BoardGameGeek, LLC. bggpipe is an independent project, not affiliated with or endorsed by BoardGameGeek. + - generic [ref=e21]: + - status + - main [ref=e22]: + - heading "Shelves" [level=1] [ref=e23] + - generic [ref=e24]: 3 unit(s), 27 opening(s), 7 game(s) unshelved + - heading "Add a unit" [level=2] [ref=e26] + - generic [ref=e27]: + - generic [ref=e28]: + - text: Unit name + - textbox "Unit name" [ref=e29]: + - /placeholder: Living room Kallax + - generic [ref=e30]: + - text: Preset + - combobox "Preset" [ref=e31]: + - option "IKEA Kallax cube (13.25 × 13.25 × 15.4)" [selected] + - option "IKEA Billy shelf (30.75 × 13 × 11)" + - option "custom size" + - option "no size — travel case, lent out…" + - generic [ref=e32]: + - text: Rows + - textbox "Rows" [ref=e33]: "1" + - generic [ref=e34]: + - text: Columns + - textbox "Columns" [ref=e35]: "1" + - generic [ref=e36]: + - text: Zone + - textbox "Zone" [ref=e37]: + - /placeholder: party games + - generic [ref=e38]: + - text: Description + - textbox "Description" [ref=e39]: + - /placeholder: the wall behind the couch — main game storage + - button "create" [ref=e41] [cursor=pointer] + - generic [ref=e42]: grid mode labels openings A1, A2… by row; you can edit, add, or remove openings afterward — repeat with another grid to stack sections (double-wides above cubes, say) in the same unit + - generic [ref=e43]: + - generic [ref=e44]: + - generic [ref=e45]: + - heading "Library Kallax" [level=2] [ref=e46] + - generic [ref=e47]: + - button "duplicate" [ref=e48] [cursor=pointer] + - button "rename" [ref=e49] [cursor=pointer] + - button "remove unit" [ref=e50] [cursor=pointer] + - paragraph [ref=e51]: + - generic [ref=e52]: Centerpiece of the game wall in the library + - button "edit description" [ref=e53] [cursor=pointer] + - generic [ref=e54]: + - button "Top — flat stack 0% of height, standing lane 0% of width" [ref=e56] [cursor=pointer]: + - generic [ref=e57]: Top + - generic [ref=e58]: — + - img "flat stack 0% of height, standing lane 0% of width" [ref=e59]: + - 'generic "flat stack: 0% of interior height"' + - generic [ref=e61]: + - button "A1 oversize 7 · 1 unmeasured flat stack 99% of height, standing lane 30% of width, 1 unmeasured boxes not counted" [ref=e62] [cursor=pointer]: + - generic [ref=e63]: A1 + - generic [ref=e64]: oversize + - generic [ref=e65]: 7 · 1 unmeasured + - img "flat stack 99% of height, standing lane 30% of width, 1 unmeasured boxes not counted" [ref=e66]: + - 'generic "flat stack: 99% of interior height" [ref=e67]' + - button "A2 oversize 6 · 1 unmeasured flat stack 89% of height, standing lane 67% of width, 1 unmeasured boxes not counted" [ref=e70] [cursor=pointer]: + - generic [ref=e71]: A2 + - generic [ref=e72]: oversize + - generic [ref=e73]: 6 · 1 unmeasured + - img "flat stack 89% of height, standing lane 67% of width, 1 unmeasured boxes not counted" [ref=e74]: + - 'generic "flat stack: 89% of interior height" [ref=e75]' + - generic [ref=e78]: + - button "B1 party 7 flat stack 98% of height, standing lane 0% of width" [ref=e79] [cursor=pointer]: + - generic [ref=e80]: B1 + - generic [ref=e81]: party + - generic [ref=e82]: "7" + - img "flat stack 98% of height, standing lane 0% of width" [ref=e83]: + - 'generic "flat stack: 98% of interior height" [ref=e84]' + - 'button "B2 no way to pack: The Red Dragon Inn Smorgasbox party 5 flat stack 89% of height, standing lane 0% of width, overfull" [ref=e86] [cursor=pointer]': + - generic [ref=e87]: + - text: B2 + - 'img "no way to pack: The Red Dragon Inn Smorgasbox" [ref=e88]': ⚠ + - generic [ref=e89]: party + - generic [ref=e90]: "5" + - img "flat stack 89% of height, standing lane 0% of width, overfull" [ref=e91]: + - 'generic "flat stack: 89% of interior height" [ref=e92]' + - button "B3 party 16 · 8 unmeasured flat stack 36% of height, standing lane 100% of width, 8 unmeasured boxes not counted" [ref=e94] [cursor=pointer]: + - generic [ref=e95]: B3 + - generic [ref=e96]: party + - generic [ref=e97]: 16 · 8 unmeasured + - img "flat stack 36% of height, standing lane 100% of width, 8 unmeasured boxes not counted" [ref=e98]: + - 'generic "flat stack: 36% of interior height" [ref=e99]' + - button "B4 two-player 6 · 1 unmeasured flat stack 39% of height, standing lane 94% of width, 1 unmeasured boxes not counted" [ref=e102] [cursor=pointer]: + - generic [ref=e103]: B4 + - generic [ref=e104]: two-player + - generic [ref=e105]: 6 · 1 unmeasured + - img "flat stack 39% of height, standing lane 94% of width, 1 unmeasured boxes not counted" [ref=e106]: + - 'generic "flat stack: 39% of interior height" [ref=e107]' + - generic [ref=e110]: + - 'button "C1 no way to pack: Calico, A Gentle Rain, Castle Panic: The Dark Titan general 11 · 2 unmeasured flat stack 100% of height, standing lane 60% of width, overfull, 2 unmeasured boxes not counted" [ref=e111] [cursor=pointer]': + - generic [ref=e112]: + - text: C1 + - 'img "no way to pack: Calico, A Gentle Rain, Castle Panic: The Dark Titan" [ref=e113]': ⚠ + - generic [ref=e114]: general + - generic [ref=e115]: 11 · 2 unmeasured + - img "flat stack 100% of height, standing lane 60% of width, overfull, 2 unmeasured boxes not counted" [ref=e116]: + - 'generic "flat stack: 100% of interior height" [ref=e117]' + - 'button "C2 no way to pack: Evolution: The Beginning, Doctor Who: The Card Game, Dastardly Dirigibles, Exploding Kittens general 14 · 3 unmeasured flat stack 95% of height, standing lane 91% of width, overfull, 3 unmeasured boxes not counted" [ref=e120] [cursor=pointer]': + - generic [ref=e121]: + - text: C2 + - 'img "no way to pack: Evolution: The Beginning, Doctor Who: The Card Game, Dastardly Dirigibles, Exploding Kittens" [ref=e122]': ⚠ + - generic [ref=e123]: general + - generic [ref=e124]: 14 · 3 unmeasured + - img "flat stack 95% of height, standing lane 91% of width, overfull, 3 unmeasured boxes not counted" [ref=e125]: + - 'generic "flat stack: 95% of interior height" [ref=e126]' + - 'button "C3 no way to pack: Forbidden Island, Mantis Falls, Murder at the Manor, Hold Your Breath!, Guillotine general 14 · 3 unmeasured flat stack 97% of height, standing lane 100% of width, overfull, 3 unmeasured boxes not counted" [ref=e129] [cursor=pointer]': + - generic [ref=e130]: + - text: C3 + - 'img "no way to pack: Forbidden Island, Mantis Falls, Murder at the Manor, Hold Your Breath!, Guillotine" [ref=e131]': ⚠ + - generic [ref=e132]: general + - generic [ref=e133]: 14 · 3 unmeasured + - img "flat stack 97% of height, standing lane 100% of width, overfull, 3 unmeasured boxes not counted" [ref=e134]: + - 'generic "flat stack: 97% of interior height" [ref=e135]' + - 'button "C4 no way to pack: Skylanders Portal Master, Robot Turtles, Sorcerer: The Game of Magical Conflict, SPANC: Space Pirate Amazon Ninja Catgirls general 13 · 4 unmeasured flat stack 90% of height, standing lane 56% of width, overfull, 4 unmeasured boxes not counted" [ref=e138] [cursor=pointer]': + - generic [ref=e139]: + - text: C4 + - 'img "no way to pack: Skylanders Portal Master, Robot Turtles, Sorcerer: The Game of Magical Conflict, SPANC: Space Pirate Amazon Ninja Catgirls" [ref=e140]': ⚠ + - generic [ref=e141]: general + - generic [ref=e142]: 13 · 4 unmeasured + - img "flat stack 90% of height, standing lane 56% of width, overfull, 4 unmeasured boxes not counted" [ref=e143]: + - 'generic "flat stack: 90% of interior height" [ref=e144]' + - generic [ref=e147]: + - 'button "D1 no way to pack: The Simpsons Trivia Game, Völuspá, The Office Trivia Game, Walk the Plank! general 11 · 2 unmeasured flat stack 94% of height, standing lane 67% of width, overfull, 2 unmeasured boxes not counted" [ref=e148] [cursor=pointer]': + - generic [ref=e149]: + - text: D1 + - 'img "no way to pack: The Simpsons Trivia Game, Völuspá, The Office Trivia Game, Walk the Plank!" [ref=e150]': ⚠ + - generic [ref=e151]: general + - generic [ref=e152]: 11 · 2 unmeasured + - img "flat stack 94% of height, standing lane 67% of width, overfull, 2 unmeasured boxes not counted" [ref=e153]: + - 'generic "flat stack: 94% of interior height" [ref=e154]' + - button "D2 vintage wargames 7 flat stack 75% of height, standing lane 100% of width" [ref=e157] [cursor=pointer]: + - generic [ref=e158]: D2 + - generic [ref=e159]: vintage wargames + - generic [ref=e160]: "7" + - img "flat stack 75% of height, standing lane 100% of width" [ref=e161]: + - 'generic "flat stack: 75% of interior height" [ref=e162]' + - button "D3 heavy 3 flat stack 42% of height, standing lane 94% of width" [ref=e165] [cursor=pointer]: + - generic [ref=e166]: D3 + - generic [ref=e167]: heavy + - generic [ref=e168]: "3" + - img "flat stack 42% of height, standing lane 94% of width" [ref=e169]: + - 'generic "flat stack: 42% of interior height" [ref=e170]' + - button "D4 campaign 4 flat stack 83% of height, standing lane 92% of width" [ref=e173] [cursor=pointer]: + - generic [ref=e174]: D4 + - generic [ref=e175]: campaign + - generic [ref=e176]: "4" + - img "flat stack 83% of height, standing lane 92% of width" [ref=e177]: + - 'generic "flat stack: 83% of interior height" [ref=e178]' + - paragraph [ref=e181]: Add an opening + - generic [ref=e182]: + - generic [ref=e183]: + - text: Rows + - textbox "Rows" [ref=e184]: "1" + - generic [ref=e185]: + - text: Columns + - textbox "Columns" [ref=e186]: "1" + - generic [ref=e187]: + - text: Label + - textbox "Label" [ref=e188]: + - /placeholder: wide top — for a single opening + - generic [ref=e189]: + - text: Zone + - textbox "Zone" [ref=e190] + - generic [ref=e191]: + - checkbox "at the top" [ref=e192] + - text: at the top + - generic [ref=e193]: + - text: W + - textbox "W" [ref=e194]: + - /placeholder: "13.25" + - generic [ref=e195]: + - text: H + - textbox "H" [ref=e196]: + - /placeholder: "13.25" + - generic [ref=e197]: + - text: D + - textbox "D" [ref=e198]: + - /placeholder: "15.4" + - button "add" [ref=e200] [cursor=pointer] + - generic [ref=e201]: a grid (rows × columns) continues the row letters — 3 × 4 under an existing A row becomes B1…D4; or set 1 × 1 and a label for a single opening. All three sizes, or none for a no-limit spot. + - generic [ref=e202]: + - generic [ref=e203]: + - heading "Library Right Shelving" [level=2] [ref=e204] + - generic [ref=e205]: + - button "duplicate" [ref=e206] [cursor=pointer] + - button "rename" [ref=e207] [cursor=pointer] + - button "remove unit" [ref=e208] [cursor=pointer] + - paragraph [ref=e209]: + - generic [ref=e210]: To the right of the Kallax + - button "edit description" [ref=e211] [cursor=pointer] + - generic [ref=e212]: + - button "Top — flat stack 0% of height, standing lane 0% of width" [ref=e214] [cursor=pointer]: + - generic [ref=e215]: Top + - generic [ref=e216]: — + - img "flat stack 0% of height, standing lane 0% of width" [ref=e217]: + - 'generic "flat stack: 0% of interior height"' + - button "A1 — flat stack 0% of height, standing lane 0% of width" [ref=e220] [cursor=pointer]: + - generic [ref=e221]: A1 + - generic [ref=e222]: — + - img "flat stack 0% of height, standing lane 0% of width" [ref=e223]: + - 'generic "flat stack: 0% of interior height"' + - button "B1 — flat stack 0% of height, standing lane 0% of width" [ref=e226] [cursor=pointer]: + - generic [ref=e227]: B1 + - generic [ref=e228]: — + - img "flat stack 0% of height, standing lane 0% of width" [ref=e229]: + - 'generic "flat stack: 0% of interior height"' + - button "C1 — flat stack 0% of height, standing lane 0% of width" [ref=e232] [cursor=pointer]: + - generic [ref=e233]: C1 + - generic [ref=e234]: — + - img "flat stack 0% of height, standing lane 0% of width" [ref=e235]: + - 'generic "flat stack: 0% of interior height"' + - button "D1 — flat stack 0% of height, standing lane 0% of width" [ref=e238] [cursor=pointer]: + - generic [ref=e239]: D1 + - generic [ref=e240]: — + - img "flat stack 0% of height, standing lane 0% of width" [ref=e241]: + - 'generic "flat stack: 0% of interior height"' + - button "E1 6 · 3 unmeasured flat stack 0% of height, standing lane 39% of width, 3 unmeasured boxes not counted" [ref=e244] [cursor=pointer]: + - generic [ref=e245]: E1 + - generic [ref=e246]: 6 · 3 unmeasured + - img "flat stack 0% of height, standing lane 39% of width, 3 unmeasured boxes not counted" [ref=e247]: + - 'generic "flat stack: 0% of interior height"' + - paragraph [ref=e250]: Add an opening + - generic [ref=e251]: + - generic [ref=e252]: + - text: Rows + - textbox "Rows" [ref=e253]: "1" + - generic [ref=e254]: + - text: Columns + - textbox "Columns" [ref=e255]: "1" + - generic [ref=e256]: + - text: Label + - textbox "Label" [ref=e257]: + - /placeholder: wide top — for a single opening + - generic [ref=e258]: + - text: Zone + - textbox "Zone" [ref=e259] + - generic [ref=e260]: + - checkbox "at the top" [ref=e261] + - text: at the top + - generic [ref=e262]: + - text: W + - textbox "W" [ref=e263]: + - /placeholder: "13.25" + - generic [ref=e264]: + - text: H + - textbox "H" [ref=e265]: + - /placeholder: "13.25" + - generic [ref=e266]: + - text: D + - textbox "D" [ref=e267]: + - /placeholder: "15.4" + - button "add" [ref=e269] [cursor=pointer] + - generic [ref=e270]: a grid (rows × columns) continues the row letters — 3 × 4 under an existing A row becomes B1…D4; or set 1 × 1 and a label for a single opening. All three sizes, or none for a no-limit spot. + - generic [ref=e271]: + - generic [ref=e272]: + - heading "Library Left Shelving" [level=2] [ref=e273] + - generic [ref=e274]: + - button "duplicate" [ref=e275] [cursor=pointer] + - button "rename" [ref=e276] [cursor=pointer] + - button "remove unit" [ref=e277] [cursor=pointer] + - paragraph [ref=e278]: + - generic [ref=e279]: To the left of the Kallax + - button "edit description" [ref=e280] [cursor=pointer] + - generic [ref=e281]: + - button "Top — flat stack 0% of height, standing lane 0% of width" [ref=e283] [cursor=pointer]: + - generic [ref=e284]: Top + - generic [ref=e285]: — + - img "flat stack 0% of height, standing lane 0% of width" [ref=e286]: + - 'generic "flat stack: 0% of interior height"' + - button "A1 — flat stack 0% of height, standing lane 0% of width" [ref=e289] [cursor=pointer]: + - generic [ref=e290]: A1 + - generic [ref=e291]: — + - img "flat stack 0% of height, standing lane 0% of width" [ref=e292]: + - 'generic "flat stack: 0% of interior height"' + - button "B1 — flat stack 0% of height, standing lane 0% of width" [ref=e295] [cursor=pointer]: + - generic [ref=e296]: B1 + - generic [ref=e297]: — + - img "flat stack 0% of height, standing lane 0% of width" [ref=e298]: + - 'generic "flat stack: 0% of interior height"' + - button "C1 — flat stack 0% of height, standing lane 0% of width" [ref=e301] [cursor=pointer]: + - generic [ref=e302]: C1 + - generic [ref=e303]: — + - img "flat stack 0% of height, standing lane 0% of width" [ref=e304]: + - 'generic "flat stack: 0% of interior height"' + - button "D1 4 · 4 unmeasured flat stack 0% of height, standing lane 0% of width, 4 unmeasured boxes not counted" [ref=e307] [cursor=pointer]: + - generic [ref=e308]: D1 + - generic [ref=e309]: 4 · 4 unmeasured + - img "flat stack 0% of height, standing lane 0% of width, 4 unmeasured boxes not counted" [ref=e310]: + - 'generic "flat stack: 0% of interior height"' + - button "E1 1 flat stack 0% of height, standing lane 42% of width" [ref=e313] [cursor=pointer]: + - generic [ref=e314]: E1 + - generic [ref=e315]: "1" + - img "flat stack 0% of height, standing lane 42% of width" [ref=e316]: + - 'generic "flat stack: 0% of interior height"' + - paragraph [ref=e319]: Add an opening + - generic [ref=e320]: + - generic [ref=e321]: + - text: Rows + - textbox "Rows" [ref=e322]: "1" + - generic [ref=e323]: + - text: Columns + - textbox "Columns" [ref=e324]: "1" + - generic [ref=e325]: + - text: Label + - textbox "Label" [ref=e326]: + - /placeholder: wide top — for a single opening + - generic [ref=e327]: + - text: Zone + - textbox "Zone" [ref=e328] + - generic [ref=e329]: + - checkbox "at the top" [ref=e330] + - text: at the top + - generic [ref=e331]: + - text: W + - textbox "W" [ref=e332]: + - /placeholder: "13.25" + - generic [ref=e333]: + - text: H + - textbox "H" [ref=e334]: + - /placeholder: "13.25" + - generic [ref=e335]: + - text: D + - textbox "D" [ref=e336]: + - /placeholder: "15.4" + - button "add" [ref=e338] [cursor=pointer] + - generic [ref=e339]: a grid (rows × columns) continues the row letters — 3 × 4 under an existing A row becomes B1…D4; or set 1 × 1 and a label for a single opening. All three sizes, or none for a no-limit spot. + - generic [ref=e340]: + - heading "Unshelved" [level=2] [ref=e341] + - generic [ref=e342]: + - link "DUNGEONS & DRAGONS" [ref=e343] [cursor=pointer]: + - /url: /library/game/local%3Adungeons%20and%20dragons%3AIMG_4519.jpeg + - generic "no trusted size — fit can't be verified" [ref=e344]: unmeasured + - generic [ref=e345]: + - link "DUNGEONS & DRAGONS FANTASY GAME RULES" [ref=e346] [cursor=pointer]: + - /url: /library/game/local%3Adungeons%20and%20dragons%20fantasy%20game%20rules%3AIMG_4519.jpeg + - generic "no trusted size — fit can't be verified" [ref=e347]: unmeasured + - generic [ref=e348]: + - 'link "Etherfields: Awakened Items & Actions" [ref=e349] [cursor=pointer]': + - /url: /library/game/355873%3A597861 + - generic [ref=e350]: + - button "♥ Library Right Shelving · E1" [ref=e351] [cursor=pointer] + - button "→ Library Right Shelving · A1" [ref=e352] [cursor=pointer] + - button "→ Library Left Shelving · A1" [ref=e353] [cursor=pointer] + - generic [ref=e354]: + - 'link "Etherfields: Search Mini Deck" [ref=e355] [cursor=pointer]': + - /url: /library/game/309202%3A507805 + - generic [ref=e356]: + - button "♥ Library Right Shelving · E1" [ref=e357] [cursor=pointer] + - button "→ Library Right Shelving · A1" [ref=e358] [cursor=pointer] + - button "→ Library Left Shelving · A1" [ref=e359] [cursor=pointer] + - generic [ref=e360]: + - 'link "Etherfields: Shifting Story Promo Deck" [ref=e361] [cursor=pointer]': + - /url: /library/game/381209%3A651213 + - generic [ref=e362]: + - button "♥ Library Right Shelving · E1" [ref=e363] [cursor=pointer] + - button "→ Library Right Shelving · A1" [ref=e364] [cursor=pointer] + - button "→ Library Left Shelving · A1" [ref=e365] [cursor=pointer] + - generic [ref=e366]: + - 'link "Etherfields: Story Dice Expansion" [ref=e367] [cursor=pointer]': + - /url: /library/game/386805%3A658656 + - generic "no trusted size — fit can't be verified" [ref=e368]: unmeasured + - generic [ref=e369]: + - 'link "Etherfields: Thorn Knight" [ref=e370] [cursor=pointer]': + - /url: /library/game/291126%3A475383 + - generic "no trusted size — fit can't be verified" [ref=e371]: unmeasured \ No newline at end of file diff --git a/docs/guide.md b/docs/guide.md index 2451cf2..843a1ed 100644 --- a/docs/guide.md +++ b/docs/guide.md @@ -144,7 +144,10 @@ because can't-verify is not the same as fits. You can also assign by searching inside an opening, or from a game's detail page (openings grouped by unit, each labeled fits / doesn't fit / can't verify). Games stored inside another box inherit their container's spot — through whole -chains (minis in an insert in a big box live where the big box does). On a +chains (minis in an insert in a big box live where the big box does) — +and the space view lists only the physical boxes: contents collapse into +a "holds N inside" hint on their container's row (hover for names; the +full list lives on the container's game page). On a phone over `--lan`, the opening view docks as a bottom sheet — the moving-day loop is search, tap, done. diff --git a/src/bggpipe/export.py b/src/bggpipe/export.py index 346512d..2279c85 100644 --- a/src/bggpipe/export.py +++ b/src/bggpipe/export.py @@ -411,10 +411,17 @@ def _shelves_body( each opening listing its residents as links.""" openings = opening_index(units) residents: dict[str, list[tuple[str, dict]]] = {} + holds: dict[str, int] = {} # physical box key -> games riding inside for key, entry in games.items(): - oid, _, _via = effective_location(key, entry, games, locations) + oid, _, via = effective_location(key, entry, games, locations) if oid and oid in openings: - residents.setdefault(oid, []).append((key, entry)) + if via is not None: + # contents ride inside a box that IS listed — the box on + # the shelf is the physical object; its contents live on + # its game page, not as wall clutter + holds[via] = holds.get(via, 0) + 1 + else: + residents.setdefault(oid, []).append((key, entry)) parts = [] for unit in units: cells_rows = [] @@ -427,6 +434,7 @@ def _shelves_body( ) links = " · ".join( f'{html.escape(e.get("name") or "?")}' + + (f" (+{holds[k]} inside)" if holds.get(k) else "") for k, e in here ) zone = ( diff --git a/src/bggpipe/templates/pages/help.html b/src/bggpipe/templates/pages/help.html index c7b8586..6b85fea 100644 --- a/src/bggpipe/templates/pages/help.html +++ b/src/bggpipe/templates/pages/help.html @@ -30,7 +30,7 @@
Titles — every read off your shelves, alphabetized, with its status and photos. This is the proofread checkpoint: edit, split, remove. Its badge counts shaky read lines — the model wasn't sure and nothing has verified them; filter to them, then press ✓ looks right or edit each one.
Review — the decisions only you can make: which game a title is, which edition a copy is, whether two same-game reads are really one box (merges show a veto), and whether an unmatched title is a real game BGG simply doesn't have (keep locally: it joins the Library, never uploads). Keyboard-first; see shortcuts.
Queue — exactly what upload will do (new entries and version upgrades) and the log of everything it has done. Nothing reaches BGG that isn't visible here first. A job that fails is skipped by later runs (so one broken game can't loop forever); when any exist, the Pipeline's upload card offers a retry N failed checkbox. Each queued row shows what upload did with it — pending, done, failed, or retired (a review decision since the last diff withdrew it). Finished rows stay listed until the next diff rebuilds the queue; the log below them is the permanent record.
-Shelves — where everything physically lives, drawn as it really stands: openings group into rows by label letter with widths proportional to their interiors, so the page is a diagram of your wall. Describe furniture once (presets for Kallax cubes and Billy shelves, grids of rows × columns — a later grid continues the row letters — custom sizes, and no-size spots like a travel case); units and openings both take a free-text description beside the zone keyword. Suggestions rank an opening holding a series-mate or base game first (marked ♥ — every placement you confirm teaches the suggester your organization), always against the remaining room, then tightest verified fit; a measured game with nowhere suitable says "no matching openings yet", and unmeasured games get no suggestions because can't-verify ≠ fits. Assign by tapping suggestions, searching inside an opening, or from any game's detail page. Capacity is a two-lane model — a flat stack against interior height plus a standing lane against the remaining width; the largest boxes lie flat, smaller ones stand, and each box's lane is flippable in the opening's view. ⚠ means no packing fits, not merely "tall stack" — and the packer is deliberately conservative (one flat pile, one standing row) while real shelves are 3-D. When it refuses a placement you can see with your own eyes, the it's here anyway button overrules it: the box takes a lane where one works (spine-out overhangs land "standing, proud") and otherwise is marked wedged in — really there, outside the capacity bars, never warned about. Unmeasured boxes get an unmeasured — measure it button: enter your own tape-measure numbers and they outrank BGG's everywhere sizes are used. And where a game lives vs where it is can differ: the Right now field on any game's detail page marks a box out (travel case, loaned to a friend) without touching its home — the spot stays reserved, contents ride along, and blanking the field brings it back. Games stored inside another box ride along with their container, through whole chains. Your layout is local data only — never sent anywhere. Bulk-load a plan with bggpipe shelve --import plan.csv (name,opening, plus an optional acknowledge column for deliberate overhangs) — re-imports are upserts that keep notes, lanes, and acknowledgments — and check capacity anytime with bggpipe dims.
Shelves — where everything physically lives, drawn as it really stands: openings group into rows by label letter with widths proportional to their interiors, so the page is a diagram of your wall. Describe furniture once (presets for Kallax cubes and Billy shelves, grids of rows × columns — a later grid continues the row letters — custom sizes, and no-size spots like a travel case); units and openings both take a free-text description beside the zone keyword. Suggestions rank an opening holding a series-mate or base game first (marked ♥ — every placement you confirm teaches the suggester your organization), always against the remaining room, then tightest verified fit; a measured game with nowhere suitable says "no matching openings yet", and unmeasured games get no suggestions because can't-verify ≠ fits. Assign by tapping suggestions, searching inside an opening, or from any game's detail page. Capacity is a two-lane model — a flat stack against interior height plus a standing lane against the remaining width; the largest boxes lie flat, smaller ones stand, and each box's lane is flippable in the opening's view. ⚠ means no packing fits, not merely "tall stack" — and the packer is deliberately conservative (one flat pile, one standing row) while real shelves are 3-D. When it refuses a placement you can see with your own eyes, the it's here anyway button overrules it: the box takes a lane where one works (spine-out overhangs land "standing, proud") and otherwise is marked wedged in — really there, outside the capacity bars, never warned about. Unmeasured boxes get an unmeasured — measure it button: enter your own tape-measure numbers and they outrank BGG's everywhere sizes are used. And where a game lives vs where it is can differ: the Right now field on any game's detail page marks a box out (travel case, loaned to a friend) without touching its home — the spot stays reserved, contents ride along, and blanking the field brings it back. Games stored inside another box ride along with their container, through whole chains — and the space view lists only the physical boxes, collapsing contents into a "holds N inside" hint on the container's row (the full list lives on its game page). Your layout is local data only — never sent anywhere. Bulk-load a plan with bggpipe shelve --import plan.csv (name,opening, plus an optional acknowledge column for deliberate overhangs) — re-imports are upserts that keep notes, lanes, and acknowledgments — and check capacity anytime with bggpipe dims.
Library — your enriched collection. Search titles, designers, mechanics and categories at once; filter by kind (board games, RPGs, off-BGG) or by how many people are playing tonight; sort by name, year, BGG rank, weight, or playing time. Click any game for its full detail: art, the usual stats, designers and mechanics, your edition, the shelf photos it was read from, and a link to its BGG page. RPG and off-BGG games live here too — identified and enriched, never uploaded. RPGs pull their designers, publishers and genres from RPGGeek; an off-BGG game's detail page lets you write its facts yourself and add a cover photo, since nothing else will ever have them (both are saved under data/ and folded in by the next enrich).