Main Menu & Handheld Menu
Main Menu & Handheld Menu — Technical Spec
Two static HTML documents. Neither extends base.html; both are self-contained (inline CSS, absolute https://logistics.solalt.com/... hrefs, target="_top" so they work inside an iframe/embed).
Serving
| Path | Served by | Source file |
|---|---|---|
GET /menu | im2.py logistics_menu() — Depends(current_user), reads the file off disk on every request and returns HTMLResponse | app/menu.html (deployed /opt/im2/app/menu.html) |
GET /handheld | nginx location = /handheld alias to /var/www/im2docs/handheld.html — no app route, no login check | repo copy app/static/handheld.html |
Reading menu.html per request is deliberate: the menu can never be a stale cached copy. An nginx location = /menu alias used to shadow the app route with a stale static file; it was removed 2026-09-05. Menu edits go in app/menu.html only. Because /handheld is still a static alias, the handheld menu must be edited in both places (app/static/handheld.html in the repo and /var/www/im2docs/handheld.html on the box).
IM2_LMM_URL (env, default /menu) is what other screens use to link back to the menu.
Access
/menu requires a session (current_user → 303 to the login screen when the im2 cookie is missing). /handheld is served straight by nginx, so it renders for anyone who can reach the host; every tile behind it still requires login, so nothing sensitive is exposed — but the menu itself is not authenticated.
Neither page filters tiles by role. All role behaviour is enforced per screen via role_field_perms (field edits) and role_action_perms / ACTION_DEFAULTS (actions: item_create, item_qb_sync, item_upload, count_record, count_post, abc_run, abc_write, ro_view, ro_write, pick_do, pick_post, rush_priority_set).
Tile status tags
Class names in the markup, not data: t-ok = Live, t-sl = In review, t-test = Test only, t-tb = Being designed (rendered as a div.card.p, not an anchor, so it cannot be clicked). Changing a tile's status is a manual edit of the HTML.
Main Menu tiles → targets
| Group | Tile | Target |
|---|---|---|
| Shortcuts | QuickBooks Online / FieldPulse / Kickserv / Salesforce / BuilderTrend | external vendor login URLs |
| Item Master | Item Master Display & Maintenance | / |
| Item Master | Create New Inventory Item | /new |
| Inventory Transactions | Pick List | /ro/pick-full |
| Inventory Transactions | Pick Item | /ro/pick-item-full |
| Inventory Transactions | Pick Review & Posting | /ro/picks |
| Inventory Transactions | Handheld Menu | /handheld |
| Requirements & Purchasing | Requirements Orders & Material Status | /ro/inquiry |
| Requirements & Purchasing | RO Import Issues to Resolve | /ro/issues (summary) |
| Requirements & Purchasing | RO Import Inbox | /ro/inbox |
| Requirements & Purchasing | Create a Requirements Order | /ro/new |
| Requirements & Purchasing | PO Workbench | /po/workbench |
| Requirements & Purchasing | Rush Material Request | /ro/rush |
| Requirements & Purchasing | Stock Replenishment on a Handheld | none (placeholder) |
| Reports | Inventory ABC Analysis | /reports/abc |
| Reports | Change Log | /changes |
| Support | Contacts & Definitions | /docs/help/contacts_definitions |
| Support | Operator & Technical Manuals | /docs |
| Support | Item Master Rollout Manual | /docs/rollout-manual.html |
| Support | IM2 Training Manual (PDF) | /docs/training-manual.html |
| Support | RO Decision Log | /docs/ro-decision-log.html |
The four /docs/*.html targets are static files under /var/www/im2docs/, separate from the markdown docs served by docs.py at /docs/help/{slug} and /docs/tech/{slug}.
Handheld Menu tiles → targets
/count (Cycle Count), /scan (Item Display & Bin Lookup), /ro/pick (Pick List), /ro/pick-item (Pick Item), /ro/rush (Rush Material Request), a dead Stock Replenishment card, and a footer link to /menu.
"Links to copy" block
Bottom of the Main Menu: two readonly <input>s (u_hh = /handheld, u_rush = /ro/rush) with a cp(id, btn) helper that uses navigator.clipboard.writeText and falls back to document.execCommand('copy'), flashing "Copied" for 1.4s. Copy targets are hard-coded absolute URLs — they must be updated by hand if the host changes.
Known limits / gaps
- The two menus drift. The Handheld Menu tags Rush as
t-sl("In review") but only defines.t-ok,.t-tband.t-testin its CSS, so that tag renders unstyled (no pill background). [found 2026-09-06] - Handheld menu exists in two places (repo
app/static/handheld.htmland the nginx-served/var/www/im2docs/handheld.html) with no automated sync — easy to fix one and not the other. - Every href is a hard-coded
logistics.solalt.comabsolute URL; a hostname change means editing both files. - Footer dates ("updated 4 September 2026" / "5 September 2026") are hand-maintained.
- No role-based tile hiding — by design, but it means level3 users see tiles whose buttons will be missing when they arrive.
The handheld Menu control (2026-09-06)
Dave, 2026-09-06: "I like the small Menu option on the HH pick screen, add that to all the HH screens including the ones that open with one prompt like pick item and in the next screen that opens."
Present on all five handheld screens — /scan, /count (both render scan.html), /ro/rush, /ro/pick and /ro/pick-item — on the first prompt screen as well as the screen that opens after it, as a .hhmenu form top-right.
Two different targets, deliberately:
POST /hh/leave(im2.py, defined aftercurrent_user) is used by the prompt screens, Item Display, Cycle Count and Rush. It only deletes thero_pick_item_order/ro_pick_item_pickcookies and redirects to/handheld, and requires no pick permission, so it works for every role including level 3.POST /ro/pick/leavewithredirect_to=/handheldstays on the in-pick header, because that path also needsrequire_writeand has to decide whether an empty pick session is deleted or kept for Pick Review.
Placement gotcha for future edits: the Menu form on ro_pick_item.html sits immediately after {% if not order %}. An earlier edit replaced that line and the app failed to render /ro/pick-item with unknown tag else until it was restored — always re-check the {% if %}/{% endif %} balance after patching a template by string replacement.
Tile status (2026-09-06)
PO Workbench shows In review, not Live: Dave, 2026-09-06 — "PO WB tile isn't live until ROs are." It buys against RO demand, so it cannot be live ahead of Requirements Orders. The RO screens, Rush Request and the three pick screens are the same story (In review / Test only). Live today: Item Master Display, Create New Inventory Item, Handheld Menu, ABC Analysis, Change Log and the manuals.
Tags, current (Dave, 2026-09-06)
Everything that was In review now reads Test only — built, demo data, do not use it for real work. The one exception is PO Workbench, which stays In review until Requirements Orders go live. Every tile that is genuinely live carries the green Live tag, including the two manuals that were mistagged.