Skip to content

Users: move flock-assignment into the shared dialog; keep capture forms inline (#133) - #154

Merged
mforce merged 2 commits into
mainfrom
feat/users-flock-dialog
Jul 23, 2026
Merged

mforce merged 2 commits into
mainfrom
feat/users-flock-dialog

Conversation

@mforce

@mforce mforce commented Jul 23, 2026

Copy link
Copy Markdown
Owner

Closes #133.

Decision

#133 asked whether the remaining inline capture forms should become dialogs. The call, matching the issue's own analysis:

  • Users flock-assignment — moved to a dialog. Not a judgement call: it's a per-row action, so it should match the neighbours Inline add/edit forms → modal dialogs (less-intrusive capture) #131 migrated. It was simply missed.
  • Water / Daily entry / expense-add / Sales draft-line — stay inline. The form is the screen (Water, Daily entry — a dialog is an extra step on every daily visit), or a dialog-per-line would grate (Sales). The Help "Adding & correcting" section already documents why, so no change there.

What changed

The worker row's flocks button now opens a "Flock access — <email>" dialog (the shared Dialog, same contract as #131) holding the assignment list, per-row remove, and the assign control. Assign/remove refresh in place and keep it open; errors show inside it. Closes via Done / the X / Escape / backdrop — the old hide flocks toggle is gone.

Tests

382 pass. UsersPage suite updated to open-the-dialog-first (assert on the dialog by its accessible name, close via Done); UsersPage.tsx 98.5%. Coverage above floor (90.68 / 84.53 / 71.45). tsc + vite build clean.

Docs

Help "Adding & correcting" drill-down list gains "a worker's flocks to manage their access." No new user-facing term (flock assignment is already glossed), and the inline-capture list there already records the keep-inline decision — so no GLOSSARY / glossary-table change.

Part of epic #14 (Phase 1.1) — this closes the last open item in the phase.

mforce added 2 commits July 22, 2026 17:29
#131 migrated the per-row CRUD surfaces to modal dialogs but missed one: the
flock-scoping control in an expanded worker row was still an inline panel that
pushed the page around on open. It is a per-row action, so it belongs in the
same dialog as its neighbours.

The row's 'flocks' button now opens a 'Flock access — <email>' dialog holding
the assignment list, per-row remove, and the assign control; the dialog's Done
/ Close / Escape / backdrop close it (no more 'hide flocks' toggle). Assign and
remove refresh in place and keep the dialog open; errors show inside it.

The remaining inline capture forms stay inline by decision, not oversight:
Water and Daily entry are the screen (a dialog would be an extra step every
day), and a dialog per draft-order line would grate. The Help 'Adding &
correcting' section already documents why; this adds flock access to its
drill-down list.

UsersPage tests updated to open-the-dialog-first; 382 pass, UsersPage 98.5%.
…review)

Two findings from the codex + 2-agent + pi review of the flock-assignment
dialog:

- Stale-closure race (feature-dev): onAssign/onUnassign captured openUser in a
  closure and, after awaiting the write + a refresh, wrote the result back
  unconditionally. Close ('Done'/Escape/backdrop aren't gated on busy) and
  reopen for a different worker while that refresh is in flight, and it spliced
  the first worker's assignment list — or a misattributed error — into the
  second worker's open dialog. Track the live dialog target in an activeUser
  ref and commit each post-await write only while it still matches the request's
  target; openAssignments and the load-failure path are guarded the same way.

- Stale dropdown (cavecrew): the assign select kept the previous worker's pick
  across opens. Reset it to the first active flock on each open.

Tests: a switch-workers-mid-refresh test proving the stale list is discarded,
and a reset test. 384 pass, UsersPage 97.65%.
@mforce

mforce commented Jul 23, 2026

Copy link
Copy Markdown
Owner Author

Review round complete — codex + 2 Claude agents + pi

All four ran. The dialog wiring itself was confirmed sound (error guard, closed-state title, close behavior, tests, Help doc all correct). Two real issues, both fixed:

Async race on switching workers (feature-dev, confidence 85; pi independently, Medium; codex pointed at the same area + the InventoryPage re-validate idiom)

  • onAssign/onUnassign captured openUser in a closure and wrote the post-await refresh back unconditionally. Since Done/Escape/backdrop aren't gated on busy, you could remove for worker A → close → open worker B while A's refresh was in flight, and A's assignment list (or a misattributed error) would splice into B's open dialog. pi flagged the mirror case in openAssignments (rapid A→B, out-of-order responses).
  • Fix: an activeUser ref tracks the live dialog target; every post-await commit in openAssignments, onAssign, and onUnassign applies only while it still matches the request's target. New test: switch-workers-mid-refresh proves the stale list is discarded.

Stale assign dropdown (cavecrew; pi Low)

  • The assign select kept the previous worker's pick across opens. Fix: reset to the first active flock on each open. New test guards it.

feature-dev downgraded the dropdown to a nit and pi called the race pre-existing — kept both fixes anyway; they're cheap and correct. 384 tests pass, UsersPage.tsx 97.65%, coverage above floor, tsc + vite build clean, tree clean before/after each external run. CI re-running on the push.

@mforce
mforce merged commit bbb3fee into main Jul 23, 2026
3 checks passed
@mforce
mforce deleted the feat/users-flock-dialog branch July 23, 2026 00:41
@mforce mforce mentioned this pull request Jul 23, 2026
90 tasks done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Capture screens: move Water / expense-add / Sales add-line forms into dialogs?

1 participant