volume storage should be working. fixed another intitative ordering bug (and added quick entry fields and add participant time fields....)
From @keen
> volume storage should be working. fixed another intitative ordering bug (and added quick entry fields and add participant time fields....)
Add form: optional initiative field (monster + character). Empty = roll
d20+mod (current behavior). Filled = use value, skip roll. 'blank=roll'
hint + 'auto' placeholder for clarity.
Inline edit: ALL participants. Number input in participant row. Blur or
Enter commits. Capped 2 digits (max 99). Auto-select on focus for quick
overwrite. Styled to match other fields (border-stone-700, rounded-md,
shadow-sm, w-10).
handleAddParticipant: manualInit detects set value. lastRollDetails
adapts display (manual flag shows 'Set initiative' vs 'Rolled d20').
Campaign card date: Clock icon + 'Created:' prefix, own row, muted
stone-300 opacity-70. Was crammed inline with character/encounter counts.
Tests: InitiativeField.test.js (2 tests - set value + empty=roll).
RED first (field missing), then green after impl. App + Participant
characterization still green (18 total).
Note: inline init edit does NOT re-sort. Known followup — displays + list
order must reflect changed initiative. Tracked separately.
Reslot: handleInlineInitiative now sorts participants[] by init desc
(stable, tie-break original index) via sortParticipantsByInitiative.
Display + AdminView reflect new order after init edit. Not a blind
re-sort — only moved element changes position.
Gate: inline init field disabled when combat active + not paused.
Matches drag gating. DM must pause to edit initiative mid-combat.
Tests: InitiativeReslot.test.js (2). RED first (no reslot, Goblin stayed
at idx 1), green after impl (reslots to idx 0). Field gate test.
Reslot (stable sort by init desc, tie-break = original array index) now
fires on all 4 paths that can change order:
1. Add participant — sortParticipantsByInitiative([...parts, new], parts)
2. Edit modal save (handleUpdateParticipant) — reslot + syncTurnOrder
3. Drag reorder — splice move (already correct, untouched)
4. Inline init field — reslot (already committed 08c27c1)
Before: add appended (ignored init), edit modal overwrote value without
moving slot. Both caused list order to drift from init order until
startEncounter (sorts once). Now any init change immediately reslots
into correct position. Display + AdminView reflect order.
Stable sort preserves drag order within ties (tie-break = original index
= reflects prior drag). Move-one semantics: only changed element moves.
EditParticipantModal: added htmlFor/id link on Initiative label (was
missing — a11y + testable).
Tests: ReslotAllPaths.test.js (2). RED first (add appended, edit modal
no reslot), green after impl.
All 5 storage.setDoc(activeDisplay, {...}, {merge:true}) →
storage.updateDoc(activeDisplay, {...}).
setDoc merge:true worked in prod (firebase honors merge) but ws adapter
+ mock ignore opts arg entirely → clobbers doc. updateDoc uses PATCH
across all adapters (firebase real updateDoc, ws PATCH endpoint, mock
merge). Consistent, no clobber.
Sites fixed:
- hidePlayerHp toggle
- startEncounter (set active ids)
- endEncounter (null active ids)
- deactivate active display
- activate new display
TDD: HideHpToggle.test RED first (assert updateDoc patch, impl still
setDoc → 0 calls found). GREEN after switch.
Char tests updated: Encounter.characterization (2) + Combat.characterization
(2) assert updateDoc on activeDisplay, not setDoc.
BUG-4: prod was already fixed (merge:true), test was RED due to mock
ignoring opts. Now all 3 adapters consistent via updateDoc.
Mirrors hidePlayerHp. New hideNpcHp flag on activeDisplay doc.
- AdminView: 'Hide NPC/monster HP' switch in Player Display settings.
- DisplayView: HP bar gated by !(hideNpcHp && p.type !== 'character').
Covers monsters + NPCs (all non-player).
- Default false (show NPC HP) — opposite of player HP default true.
updateDoc patch (BUG-4 pattern). No clobber.
Test: HideHpToggle selector scoped to 'hide player hp' (now 2 switches).
robert
merged commit 8cf3dad5b6 into main2026-07-03 08:35:32 -04:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
From @keen
All 5 storage.setDoc(activeDisplay, {...}, {merge:true}) → storage.updateDoc(activeDisplay, {...}). setDoc merge:true worked in prod (firebase honors merge) but ws adapter + mock ignore opts arg entirely → clobbers doc. updateDoc uses PATCH across all adapters (firebase real updateDoc, ws PATCH endpoint, mock merge). Consistent, no clobber. Sites fixed: - hidePlayerHp toggle - startEncounter (set active ids) - endEncounter (null active ids) - deactivate active display - activate new display TDD: HideHpToggle.test RED first (assert updateDoc patch, impl still setDoc → 0 calls found). GREEN after switch. Char tests updated: Encounter.characterization (2) + Combat.characterization (2) assert updateDoc on activeDisplay, not setDoc. BUG-4: prod was already fixed (merge:true), test was RED due to mock ignoring opts. Now all 3 adapters consistent via updateDoc.