docs: Obsidian-style vault under docs/
Add a navigable Obsidian vault as the project's first-class technical documentation. Notes cross-reference with [[wikilinks]]; docs/index.md is the Map of Content. New notes: index.md MOC, entry point architecture.md what the extension owns vs what lives outside data-model.md entity-by-entity schema reference menu-tree.md the arbitrary-depth tree concept order-flow.md state machine + invoice listener + print nostr-layer.md kinds 0/30402/5/1059, signing, t-tags api-reference.md endpoint catalog by audience cms.md Vue 3 + Quasar 2 UMD conventions, q-tree webapp-integration.md multi-restaurant cart pattern + atomicity glossary.md domain terms Existing notes (kept as-is): adr-0001-menu-tree.md the storage choice rationale design-conversation.md trimmed transcript README.md adds a Documentation section pointing at docs/index.md with the headline note list. Each note links to ~3-5 others; the vault forms a connected graph. A project-level memory rule (saved outside the repo) commits us to keeping these docs in sync as the code evolves: any commit that materially changes schema, API, order flow, Nostr surface, CMS conventions, or webapp integration must update the relevant note(s) in the same commit.
This commit is contained in:
parent
7f7915a041
commit
42a8b08a5b
11 changed files with 1015 additions and 0 deletions
88
docs/cms.md
Normal file
88
docs/cms.md
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
# CMS
|
||||
|
||||
The operator-facing console — what the restaurant owner sees when
|
||||
they enable the extension. Lives under `/restaurant/...` and uses
|
||||
LNbits' built-in **Vue 3.5 + Quasar 2.18 UMD** runtime: no build
|
||||
step, no bundler, just Jinja templates including a per-page JS file.
|
||||
|
||||
## Pages
|
||||
|
||||
All pages extend `base.html` (provided by LNbits core) and require a
|
||||
logged-in user (`check_user_exists`).
|
||||
|
||||
| Path | Template | Script | Purpose |
|
||||
|---|---|---|---|
|
||||
| `/restaurant/` | `restaurant/index.html` | `static/js/index.js` | Restaurant list / dashboard |
|
||||
| `/restaurant/{slug}` | `restaurant/menu.html` | `static/js/menu.js` | [[menu-tree\|menu]] builder (q-tree) |
|
||||
| `/restaurant/{slug}/orders` | `restaurant/orders.html` | `static/js/orders.js` | Order monitor |
|
||||
| `/restaurant/{slug}/kds` | `restaurant/kds.html` | `static/js/kds.js` | Kitchen Display |
|
||||
| `/restaurant/{slug}/settings` | `restaurant/settings.html` | `static/js/settings.js` | Restaurant + extension settings |
|
||||
|
||||
## Conventions
|
||||
|
||||
- `{% extends "base.html" %}` and `{% from "macros.jinja" import window_vars with context %}`.
|
||||
- Page content goes in `{% block page %}`. Scripts in `{% block scripts %}`, after `{{ window_vars(user) }}`.
|
||||
- The page JS sets `window.app = Vue.createApp({mixins: [windowMixin], data, methods, created})`. LNbits' `init-app.js` runs after the extension scripts and finishes the mount with `app.use(Quasar)` + `app.mount('#vue')` — **don't call `.mount()` yourself**.
|
||||
- Bootstrap data is injected via `<script>window.X = {{ thing | tojson | safe }}</script>` between the macro and the per-page script.
|
||||
- The shared REST client is `static/js/api.js`, exposing `window.RestaurantAPI` (one method per resource).
|
||||
|
||||
## Menu builder (q-tree)
|
||||
|
||||
The menu page uses Quasar's `q-tree` directly off the hydrated tree
|
||||
returned by `GET /api/v1/restaurants/{id}/menu`. Three-pane layout:
|
||||
|
||||
```
|
||||
+--------------------+----------------+----------------------------+
|
||||
| sidebar nav | q-tree | Items panel |
|
||||
| (orders / KDS / | with inline | (filtered by selected |
|
||||
| settings links) | edit buttons | tree node) |
|
||||
+--------------------+----------------+----------------------------+
|
||||
```
|
||||
|
||||
Custom `default-header` slot renders:
|
||||
|
||||
- node name + item-count badge + child-count hint
|
||||
- inline buttons: `add` (disabled at depth 3), `edit`,
|
||||
`drive_file_move`, `delete` (with cascade prompt)
|
||||
|
||||
Add-root button sits above the tree (`+ New top-level`).
|
||||
|
||||
The Move dialog uses a flat-indented `q-select` of all nodes,
|
||||
filtered to exclude the moved node + its descendants and any
|
||||
depth-3 candidate. (The server enforces both checks too — see
|
||||
[[menu-tree]].)
|
||||
|
||||
Drag-drop reorder is **v2**; v1 uses the explicit Move dialog.
|
||||
|
||||
## Item dialog
|
||||
|
||||
The item dialog includes a flat-indented `q-select` for `node_id`,
|
||||
populated by walking the tree with em-space indentation per depth
|
||||
level. An item can land on any node, not just leaves.
|
||||
|
||||
Modifier groups + modifiers live in a separate dialog (a child of
|
||||
the item dialog) with the `chooseOne / chooseMany / required /
|
||||
optional` semantics from [[data-model|the data model]].
|
||||
|
||||
## Order monitor + KDS
|
||||
|
||||
Both use the same data source (`GET /restaurants/{id}/orders`)
|
||||
filtered by status. The KDS view escalates color by age (`>5min`
|
||||
orange, `>15min` red) and offers one-tap state transitions.
|
||||
|
||||
Today the monitor + KDS poll every 5–8 s. SSE / Nostr push is on
|
||||
the roadmap.
|
||||
|
||||
## Settings
|
||||
|
||||
`settings.html` saves restaurant fields via
|
||||
`PUT /restaurants/{id}` and (for LNbits admins) extension-wide
|
||||
toggles via `PUT /settings`. NIP-17 orders toggle is currently
|
||||
disabled because the unwrap step is stubbed — see [[nostr-layer]].
|
||||
|
||||
## See also
|
||||
|
||||
- [[architecture]]
|
||||
- [[menu-tree]]
|
||||
- [[order-flow]]
|
||||
- [[api-reference]]
|
||||
Loading…
Add table
Add a link
Reference in a new issue