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 (row 1) | Pick List | /ro/pick-full |
| Inventory Transactions (row 1) | Pick Item | /ro/pick-item-full |
| Inventory Transactions (row 1) | Pick Review & Posting | /ro/picks |
| Inventory Transactions (row 2) | Cycle Count (enter a count) | /count |
| Inventory Transactions (row 2) | Cycle Count Review & Post | /counts |
| Inventory Transactions (row 2) | Inventory ABC Analysis | /reports/abc |
| Inventory Transactions (row 3) | Handheld Menu | /handheld (public static) |
| Inventory Transactions (row 3) | Truck Tech Menu | /truck (public static) |
| Requirements | Requirements Orders & Material Status | /ro/inquiry |
| Requirements | RO Import Inbox | /ro/inbox |
| Requirements | RO Import Issues to Resolve | /ro/issues (summary) |
| Requirements | Create a Requirements Order | /ro/new |
| Purchasing | PO Workbench | /po/workbench |
| Purchasing | Buy List | /po/buylists |
| Purchasing | POs Created | /po/report |
| Purchasing | PO Alerts | /po/alerts (<!--ALERTBADGE--> filled server-side) |
| Support | Admin | /admin (sub-menu: Tables, System Settings, Users, Vendor Default GL /vendor-gl — moved from the removed Accounting group 2026-09-26) |
| Support | Poll/Sync Log | /ro/poll-log |
| Support | Change Log (items, settings, users) | /changes — reads audit_log (sku, field, old/new, who, source) |
| Support | Contacts & Definitions | /docs/help/contacts_definitions |
| Support | Operator & Technical Manuals | /docs |
| Support | Decision Log | /docs/ro-decision-log.html |
| Support | Not Finished Yet — Open Items | /docs/help/not_finished |
Layout 2026-09-26 (Dave): 4-column grid, .wrap max 950px (tile size unchanged from the 5-column layout); Shortcuts use .grid.half (8 columns) so the five external links are half-width on one row; the tag legend (.key) and the Rush Material Request row in Links to copy were removed (Rush is reached from /truck / /handheld); Support order puts Change Log first on row 2.
Re-grouped 2026-09-26 (Dave): Inventory Transactions is two .grid blocks so the cycle-count tiles + ABC always sit on their own row under the pick row; Requirements & Purchasing split into Requirements and Purchasing (PO Workbench first); Reports group removed (ABC moved to the count row, Change Log to Support).
Removed 2026-09-26 (Dave): Rush Material Request tile (lives on /truck and /handheld), Item Master Rollout Manual and IM2 Training Manual tiles (both static pages now listed under Overview on the manuals index at /docs, the single entry point), Testing Issue Log tile (Slack thread, never adopted).
The decision log, rollout manual and training manual are static files served by nginx from /var/www/im2docs/ (master copy of the decision log: /opt/im2/docs/pages/ro-decision-log.html — copy it over after editing), 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.
Ver 12 — 2026-10-02 (Dave)
Tile names shortened to one line: Item Master, New Item, Pick List, Pick Item, Pick Review, Cycle Count, Count Review, ABC Analysis, Req. Orders, RO Inbox, RO Issues, New RO, Buy Lists, POs Created, PO Alerts ⚠ (icon always shown; red count when alerts are open), Create PO, Contacts/Defs, Manuals, Change Log, Open Items. Tag Test only now reads Test. Tile names never wrap (.nm nowrap + ellipsis). Follow-up same day: Contacts/Definitions, Requirements Orders, Development To Do (was Open Items).
Poll/Sync Log error badge (Ver 13, 2026-10-23)
im2.logistics_menu replaces <!--POLLERRBADGE--> in menu.html with today/7d from ro.ro_poll_log where outcome='error': today = started_at Central date equals today's Central date; 7d = started_at >= now() - 7 days (rolling). Query failure leaves no badge.
Main Menu Ver 15 (2026-10-24)
Static file menu.html (copy in /var/www/im2docs/). Added section Accounting (first, under Shortcuts) with tile /vendor-gl labelled "Vendor"; Pick Item / Pick Review tags Test→Live; HH Menu + Truck Tech Menu tiles removed from Inventory Transactions.
- Ver 16 (2026-10-24): Handheld Menu tile (Inventory Transactions) and Truck Tech Menu tile (Support) now Live tiles; Accounting tile renamed Vendor Master.