diff --git a/docs/DEPLOY-WINDOWS-IIS.md b/docs/DEPLOY-WINDOWS-IIS.md index 6d7394a..eac85d7 100644 --- a/docs/DEPLOY-WINDOWS-IIS.md +++ b/docs/DEPLOY-WINDOWS-IIS.md @@ -106,25 +106,38 @@ $env:FLASK_APP="shopdb" venv\Scripts\flask db upgrade venv\Scripts\flask seed reference-data -# Enable the plugins this site tracks (registry lives in the gitignored -# instance/plugins.json, so a fresh box starts with none enabled): +# Install the plugins this site tracks (registry lives in the gitignored +# instance/plugins.json, so a fresh box starts with none installed). Run +# `flask plugin list` to see the current bundled set; the 13 bundled plugins are +# computers, employees, geenforce, knowledgebase, machines, measuringtools, +# network, notifications, printedparts, printers, slides, usb, warranty. Install +# only the ones this site wants: venv\Scripts\flask plugin list +venv\Scripts\flask plugin install machines +venv\Scripts\flask plugin install printers venv\Scripts\flask plugin install computers -venv\Scripts\flask plugin install equipment venv\Scripts\flask plugin install network venv\Scripts\flask plugin install notifications -venv\Scripts\flask plugin install printers venv\Scripts\flask plugin install usb venv\Scripts\flask plugin install knowledgebase venv\Scripts\flask plugin install slides venv\Scripts\flask plugin install employees +venv\Scripts\flask plugin upgrade-all # First admin (password is generated and printed once): venv\Scripts\flask seed admin --username admin --email admin@yourfacility.example.com ``` +Cleaner than a hand list: declare the set once in a site profile and apply it: + +```powershell +venv\Scripts\flask plugin apply-profile deploy\site-profile.json # install + enable the chosen set, in dependency order +venv\Scripts\flask plugin upgrade-all +venv\Scripts\flask plugin prune-schema --yes --force # lean DB: drop tables of plugins this site did NOT install (ADR-014) +``` + (Alternatively copy the dev box's `instance/plugins.json` to `APP_ROOT\instance\` -to reproduce the exact enabled set, then just run `flask plugin upgrade-all`.) +to reproduce the exact set, then just run `flask plugin upgrade-all`.) ## 6. Create the IIS site + web.config diff --git a/docs/PLUGIN-HOOKS.md b/docs/PLUGIN-HOOKS.md index ad3dc13..23fefe5 100644 --- a/docs/PLUGIN-HOOKS.md +++ b/docs/PLUGIN-HOOKS.md @@ -174,7 +174,9 @@ isolated in prod, re-raised in dev/test). ### `get_navigation_items() -> List[Dict]` -Returns navigation menu items. +Returns navigation menu items. A plugin owns its own sidebar entry here, so it +appears when the plugin is installed and disappears when it is not (including in +a lean per-site build that omits the plugin). ```python class ComputersPlugin(BasePlugin): @@ -187,6 +189,26 @@ class ComputersPlugin(BasePlugin): }] ``` +**Placement.** `position` (int) sets both the sort order and which section the +item lands in - the core sidebar (`AppLayout.vue:buildNavItems`) assigns section +headers by position range: + +| `position` | section | +|-----------|---------| +| `< 10` | top, above any header (Dashboard is 0, Map is 4) | +| `10-29` | **Assets** | +| `30-49` | **Information** | +| `>= 50` | trailing, below Information | + +Lower number sorts higher within a section. An explicit `'section': +'information'` forces the Information group regardless of position. Only these +two named sections exist; a new section needs a core edit to `buildNavItems`. +The **Displays** group (kiosk/TV links) is hardcoded in `AppLayout.vue`, not +plugin-driven. + +`icon` is a string key mapped to a Lucide component core-side (same idea as +`get_settings_cards`); an unknown key renders with no icon. + > Removed in contract 0.4.0: `get_searchable_fields`. Global search > (`/api/search`) is a core concern that queries the asset model directly and > already covers every bundled asset type; no plugin ever implemented the hook. diff --git a/docs/PLUGINS.md b/docs/PLUGINS.md index 8853e6a..5baba73 100644 --- a/docs/PLUGINS.md +++ b/docs/PLUGINS.md @@ -67,6 +67,37 @@ For sister-site plugins (per [ADR-003](adr/ADR-003-plugin-distribution.md)): - Plugin manifest declares `core_version` range matching the framework version they target - Plugin readme explains: what it tracks, who maintains it, where to file issues +## Lean per-site builds + +A site ships only the plugins it chose; a site that never wants printedparts / +usb / network never carries that code (see +[ADR-013](adr/ADR-013-plugin-catalog-and-lean-builds.md) and +[ADR-014](adr/ADR-014-schema-lean-per-site.md)). Three layers make a build lean: + +- **Backend code** - `scripts/build-site.sh ` stages `shopdb/core` plus + only the chosen plugins' directories (and their hard-dependency closure). A + plugin a site did not choose is absent from the backend tree. +- **Frontend code** - `SITE_PLUGINS=machines,printers npm run build` (via + `scripts/stage-frontend.mjs`) stages only those plugins' `frontend/` dirs and + codegens the route table. **Exception:** a `plugins//frontend/` dir with + **no `manifest.json`** is a CORE feature (e.g. `applications`), not a per-site + plugin, and is ALWAYS staged regardless of `SITE_PLUGINS` - otherwise a lean + build would lose a core page. +- **Database** - the shared core Alembic baseline creates every plugin's tables, + so a lean site provisions them and then drops the ones it does not use with + `flask plugin prune-schema` (ADR-014). Run it once at provisioning, after + `flask db upgrade` and `flask plugin upgrade-all`; see + [DEPLOY.md](DEPLOY.md). + +**Menus follow the build, not a plugin flag.** The sidebar nav, the settings +rail, and the Displays links all gate on whether the target route was actually +staged into this build (the router's own route table), not on a registry +"enabled" flag. So a lean site never shows a menu entry that dead-ends on a +blank page - an omitted plugin's nav item, settings cards, and kiosk links all +disappear together. Shopfloor Dashboard is a core view but is gated on the +notifications plugin (its only data source), so it drops when notifications is +not in the build. + ## Naming policy Plugin names follow the framework's naming convention (lowercase concatenated, no underscores or dashes; full words preferred over acronyms). See [CONTRIBUTING.md](../CONTRIBUTING.md). Plugin name collisions across sites are not enforced; the convention recommends prefixing site-specific plugins with the site code (e.g., `wjsf-shippingstation`) when there is risk of overlap.