undo a few changes#5
Open
Greensand321 wants to merge 238 commits into
Open
Conversation
Claude/review flowboard l qttz
Claude/review flowboard l qttz
Add Section 13 Roadway Plans checklist
Claude/review flowboard l qttz
…ually - Archive entire columns (with all their cards) via ⊡ button in column header - Archive individual cards via 📦 Archive button in card modal footer - Archive browser modal (📦 Archive in top nav) shows archived columns and cards with Restore and Delete actions per item - Restoring a column also clears archive flags on all cards within it - Archived items are fully filtered from the board, card counts, and stats - Archived columns are excluded from the card modal's column picker - All archive actions integrate with undo/redo stack https://claude.ai/code/session_01VxiEThbmeb8Y6ro3A68Mnd
…n-SVfAr Add archival feature to FlowBoard — archive columns and cards individ…
Replace flat lists with a horizontally scrollable row of column panels that use the same .col / .col-hdr / .col-body / .card CSS as the live board, making the archive immediately recognizable. - mkArchivePanel(): renders a column panel using the column's real PAL color and header style. Fully archived columns get an amber 🗄 Archived badge plus ↩ / × column-level actions. Context panels (active columns with individually archived cards) show the column name and count only. - mkArchiveCard(): renders a .card with the same border-left color, title, priority badge, tags, progress bar, and due-date badge as the live board. Appends ↩ Restore and 🗑 buttons. Restore is omitted for cards inside a fully archived column (whole-column restore is the right action there). - showArchiveModal(): builds the modal with DOM nodes directly (no HTML string), widens to min(92vw, 960px), and uses .group-cols for horizontal scroll. Panels sorted newest-archived first. Includes a legend row distinguishing the two panel types. Empty state preserved. https://claude.ai/code/session_01VxiEThbmeb8Y6ro3A68Mnd
…n-SVfAr Redesign archive modal to mirror the board's visual layout
Creates Section 60 Checklist.html from the section00-template, populated with all 60.001 required information items for Cover Drawing (30 items) and Right of Way Plan Drawings – General (42 items), with source bold formatting preserved via HTML strong tags. https://claude.ai/code/session_017f8GsiJFXxhAyvEViGmJxs
…klist-uF70W Add Section 60 Right Of Way Plans Checklist
Creates Section 50 Checklist.html from the section00-template, populated with all content from sections 50.001 General (1 item), 50.002 Required Information (26 items covering ESPCP cover drawing requirements), and 50.002 Additional Items (1 item noting optional delineation elements). https://claude.ai/code/session_017f8GsiJFXxhAyvEViGmJxs
…cklist-uF70W Add Section 50 Erosion, Sedimentation and Pollution Control Checklist
Replaces the one-line placeholder with a complete overview covering both tools: FlowBoard (features, sync, backups, themes) and the PPG compliance checklists (Sections 24, 50, 60). Includes a combined workflow showing how the two tools complement each other, a quick-start guide, and a clear statement of the target audience (GDOT civil engineers and consultants). https://claude.ai/code/session_017f8GsiJFXxhAyvEViGmJxs
…cklist-uF70W Rewrite README with full product marketing copy
Moves the uploaded demo images into assets/screenshots/ for clean repo organization and adds a two-column light/dark comparison table in the FlowBoard section of the README so visitors get an immediate visual of the tool. https://claude.ai/code/session_017f8GsiJFXxhAyvEViGmJxs
…cklist-uF70W Add FlowBoard screenshots and embed in README
Comprehensive engineer-facing spec covering all 9 pages/modals, data model, color palettes, animations, drag-and-drop mechanics, Firebase sync system, undo/redo, and implementation notes derived from the reference flowboard.html. https://claude.ai/code/session_01SXRYeiXpndK6y9y9Bo3Ls7
…mpt-Tw6gQ Add detailed FlowBoard website implementation prompt
…n00-template-to-section-50-checklist Add Section 50 ESPCP cover drawing checklist
The card modal stops propagation on its own clicks, so the old bubble-phase document listener never saw clicks inside the modal and the sort menu stayed open. Move dismissal to the capture phase (fires before the modal swallows the event), add scroll/resize/Escape dismissal, exclude the trigger button and the menu itself, and properly remove all listeners on close to stop the leak.
Claude/eloquent babbage n zjiw
… time - notify() default duration 2600ms -> 7800ms (triple), and now clears any pending hide-timeout on a new call so a fast second toast isn't cut short by the first one's timer. - localStorage save failures now distinguish quota-exceeded vs blocked storage (private/incognito) vs unknown error, and report actual board/ backup/auto-snap sizes so the message reflects what's really happening instead of a generic "storage may be full" guess. - Firebase per-edit write failures were previously silent to the user (only the sync badge changed color, error logged to console). They now surface a toast with the Firebase error code/message and a note that the local copy is safe, distinguishing offline vs permission-denied vs other errors.
Extracts Flowboard's local+cloud persistence architecture (autosave, undo/redo with crash recovery, manual + automatic snapshots, export/ import, diff viewer, whole-document cloud sync with a heuristic safety gate) into a config-driven module that doesn't assume any particular state shape or a global named S. A minimal demo task list proves the module end-to-end; the DSK_CONFIG block at the top is the only section meant to change when adopting this in another program. Also fixes a known inefficiency from the original Flowboard implementation: auto-snapshots are now stored as individually keyed Firebase children instead of one whole-array overwrite per snapshot. Includes a prominent integration warning listing 8 conditions (existing undo system, non-matching state shape, partial-update cloud writers, regulated data, multi-writer concurrency, existing soft-delete/ versioning, different storage-budget assumptions, non-function-based mutations) under which an integrator should flag the conflict to a human instead of silently implementing.
Claude/eloquent babbage n zjiw
…al backup interface Replaces the earlier minimal mockup with the real thing: the Backup & Restore modal, auto/manual snapshot lists, Compare/diff viewer, and their CSS (buttons, .bak-item/.auto-bak-item, .diff-* classes, .overlay/.modal) are cloned from Flowboard's showBackupModal()/ showDiffPicker()/showSnapshotDiff(), not reimagined. Theme is fixed to Flowboard's "pearl" light variables, no dark option, per request. The DSK module underneath is unchanged in behavior; only its UI-facing surface (setModal/closeModal, the modal HTML builders, triggerBadge, diffExpand) was added so the generic DSK_CONFIG adapters now drive the same interface instead of a scaled-down demo panel. Flowboard's USB-drive section is intentionally omitted (hardware file-access feature out of scope for this generic kit) and noted as such in a comment rather than silently dropped.
Rebuild Data Safety Kit UI as a light-theme clone of Flowboard's actu…
…dd drag edge auto-scroll Four fixes from the audited bug list, in order: 1. Card modals in light themes now tint with the card color (color-mix 8% toward white) instead of staying flat white — the tint was previously applied only when !isLight(), in both renderCM and setCMColor; extracted shared _cmModalBg() helper. 2. Checklist truncation preview is now robust: the hover handler moved from the text span to the whole row (the chevron/x/badge zone where the ellipsis visually sits previously had no handler at all), and the truncation test gained a sub-pixel Range measurement to catch text overflowing by less than 1px, which the integer scrollWidth comparison misses. 3. Description box gets a custom 34px grab handle (double the native ~17px resize corner), always visible, pointer-event based so it works with touch, persisting height through the existing EC.descH path. The native resize:vertical corner remains as a fallback. 4. Dragging a column or card near the edge of a scrollable container now auto-scrolls it (group row horizontally, limited column bodies and the board vertically) via a rAF loop that keeps scrolling while the pointer holds still in the 70px edge zone, refreshing the drop indicator as content moves under the pointer. Previously a drag could never reach an off-screen destination.
… scale setting Due dates: when a card's due is auto-synced from checklist items, the header now shows a ✕ button that clears every item's due date in one click (guarded by confirm + a pre-action auto-snapshot). Previously a synced due date could only be removed by opening each item's calendar individually. Card due is cleared explicitly since the sync leaves the stale derived date in place once no item has a due. UI scale: new "UI Scale" section in the settings panel with −/+ stepping (60–150%) and an Auto mode that seeds the scale from the screen width (0.85–1.1 across <1300 to ≥2400 px). Manual choice persists in localStorage — deliberately per-device, not in synced prefs, since the right scale differs between monitors (the reported home-vs-work problem). Applied via body zoom at boot.
…phan purge Option B storage/sync stopgap: - CRITICAL correctness fix: a failed local (localStorage) write no longer falls through to push to the cloud. Previously save() bumped lastModified and ran the Firebase set() even when the local write threw quota-exceeded — leaving the device's disk behind the cloud and silently desyncing it on the next reload/tab-discard. This is the mechanism behind "sync stopped being reliable after switching devices." Now: on unrecoverable local failure the timestamp is reverted, the sync badge shows error, and nothing is pushed, keeping the cloud consistent with what the device can actually persist. - Auto-cull safety valve: on a quota error, reclaim space (purge orphaned auto-snap stores, then trim every board's auto-snaps to the 3 newest) and retry the write once before surfacing a hard error. Manual snapshots are never touched. - Honest usage gauge: the "storage nearly full" warning now measures TRUE origin-wide localStorage usage across all keys, not just the current board's 3 keys — so it can no longer stay green while other boards' backups fill the shared ~5MB quota. - Orphan purge on load: auto-snapshot stores for boards no longer in the keys list are removed at startup (disposable auto-snaps only, keyed by share-key; user-created manual snapshots are never auto-deleted). Verified headlessly: failed write reverts timestamp + skips cloud push + shows error badge; successful auto-cull retry saves and notifies; gauge counts other boards; orphan purge removes dead stores and keeps live ones.
Claude/eloquent babbage n zjiw
…a real storage usage bar
Implements items 1-3 from the storage/sync report:
1. Persistent save-error banner: local-save failures now show a
body-level banner (survives full board re-renders, unlike a toast)
with real action buttons (Export Backup Now / Open Backups) instead
of prose telling the user where to go. Auto-hides the next time a
save succeeds; auto-dismissible manually. Quota failures also
invalidate the cached capacity probe, since a failure despite a
cached "plenty of room" reading means that reading was wrong.
2. Backups button now reflects real storage state: green/amber/red
(70%/90% of measured ceiling) plus a red dot badge when an
auto-cull has run and not yet been acknowledged. A small persisted
cull log (fb4_cull_log/fb4_cull_ack, capped at 10 entries) drives
both the badge and a banner inside the Backup modal itself
("Storage auto-cleanup ran on <date> — N old auto-snapshots
removed"). Opening the modal acknowledges it and clears the red
state.
3. Real storage usage bar in the Backup modal, backed by an empirical
capacity probe (_probeStorageCapacity): binary-search-writes a
throwaway key to find this browser/profile's actual localStorage
ceiling instead of guessing a per-browser constant that drifts out
of date across versions. Cached (fb4_cap_probe), runs lazily off
the initial render tick on first Backup-modal open so it can't
block the UI, with a manual "Recalculate" action. _storageStats()
is now the single source of truth for usage/ceiling/percentage,
replacing the old hardcoded 4MB threshold that was duplicated
across the save() warning, so the toast, button color, and bar can
no longer disagree with each other.
Verified headlessly: probe finds a plausible ceiling and cleans up its
own temp key; storage bar renders and Recalculate works; cull event
turns the button red with a badge and the modal shows the banner;
opening the modal acknowledges and clears both; the error banner
appears with working action buttons, survives a full render() wipe,
and hides itself on the next successful save.
Note: item 4 from the report (orphan auto-snapshot purge currently
runs silently and irreversibly on every boot) is NOT addressed here —
scoped out of this round per explicit instruction, but still an open
risk flagged for a follow-up.
Add persistent save-error banner, backups-button warning states, and …
… modal Item 4 from the storage/sync report. The previous _purgeOrphanAutoSnaps() ran on every boot and permanently deleted any local-only (or removed-key) board's auto-snapshots with zero confirmation — for boards that were never cloud-synced, those were the only copy, so this was quietly destroying unrecoverable data on every launch. - _findOrphanAutoSnaps() is now a pure detection function (never deletes), shared by both paths below. - New boot-time flow: _checkOrphanSnapshots() runs once per fresh page load (400ms after boot, so it doesn't compete with initial paint/sync/ USB-reconnect) and, if orphaned groups exist, shows a review modal listing each one (board key, snapshot count, size, date range) with per-group Export All / Delete This Group, and a per-snapshot expander with individual Restore-into-current-board / Export. Dismissing via "Keep All For Now" deletes nothing — the same groups are re-detected and re-shown on the NEXT startup, for as long as they still exist. - The emergency quota-reclaim path (_reclaimSpace, used mid-save when storage is full and there's no time for a prompt) keeps its original silent/automatic behavior via a refactored _purgeOrphanAutoSnaps() built on the same detection function — that cull is still surfaced afterward via the existing cull-log/banner (item 2), just not gated on a prompt, since blocking a save on user input would defeat its purpose. Verified headlessly: modal auto-shows on boot for a seeded orphan, data is untouched by showing/dismissing it, reappears on next reload after "Keep All For Now", Export All doesn't delete, per-snapshot rows render and both restore-into-current-board and explicit group deletion work, and the modal stops appearing once resolved. Also verified the emergency reclaim path is unaffected and still silent/automatic.
…fallback First of four commits for item 5. Pure addition — this IDB layer is NOT yet wired into getBaks/setBaks, so behavior is completely unchanged. - _openIdb / _idbGet / _idbPut / _idbDelete / _idbKeys: a ~90-line vanilla IndexedDB wrapper (no dependencies, single-file property preserved), two object stores (manual, auto) keyed by the same key strings used today (fb4_baks_<boardId> / fb4_auto_<key>), values are the snapshot arrays. - Every op degrades safely: unavailable IDB, blocked opens, and transaction errors all resolve to null/false/[] rather than throwing, so callers can fall back to the existing localStorage path. - _idbCheckUsable: one-time round-trip probe (write/read/delete) that detects IndexedDB that exists but silently fails to persist (private mode, opaque file:// origins) before we trust it. Verified headlessly in Chromium: full round-trip works AND data persists across a page reload on a file:// origin (the load-bearing feasibility risk for this whole migration). Full browser/device matrix still pending (Phase 4).
…rror The cutover. Backups (manual + auto snapshots) now live in IndexedDB; getBaks/getAutoBaks/setBaks/setAutoBaks keep their synchronous signatures by reading/writing an in-memory mirror of the current board's IDB record (Option B). All existing call sites are unchanged. - Mirror + hydration: _hydrateManualMirror/_hydrateAutoMirror load the current board's record from IDB; getters return the mirror (or [] while a stale/unhydrated key re-hydrates); setters update the mirror and persist immediately (puts are cheap — no debounce, so no lost-on-close window). setters refuse to persist when the mirror isn't hydrated for the current board, so they can never clobber unloaded data. - One-time migration (_migrateAllBackupsToIdb): moves every fb4_baks_* / fb4_auto_* from localStorage into IDB, sequentially, verifying each round-trip before deleting the localStorage original (reclaiming the space that was the whole problem). Corrupt/failed entries are left in place and retried next boot. Gated by fb4_idb_migrated. - Boot ordering: _initBackupStore() (probe usability -> migrate -> hydrate) runs before session-start snapshot, orphan review, and initSync, so nothing reads backups before the mirror is ready. - Cloud-listener race fix: the auto-snapshot Firebase listener now attaches only AFTER _hydrateAutoMirror() resolves, guarded by a captured-key check, so a merge can't run against an empty mirror and overwrite un-pushed local-only snapshots. - _applyRemote re-hydrates the manual mirror on board switch/join. - item 4 orphan review rewritten to enumerate the IDB 'auto' store (async detection cached in _orphanGroups; sync modal + handlers; async delete). item 2 emergency reclaim stays localStorage-only (correct: culling IDB can't relieve a localStorage-quota failure, and the tiny live board rarely triggers one). - Full localStorage fallback: if IDB is unusable (private mode, opaque file:// origin, absent), _backupsUseIdb stays false and every function uses the original localStorage path. Also hardened pre-existing USB _usbIDB() against a missing indexedDB (it called .open unguarded). Live board (fb4) intentionally still in localStorage — loads synchronously at boot; a total IDB failure costs backup history, never the working board. NOTE: the storage gauge (item 3) still reads _lsBytes and will now show near-empty since backups left localStorage — the IDB usage isn't reflected until commit 3 (navigator.storage.estimate). Cosmetic only. Verified headlessly in Chromium (file://): migration moves+verifies+ deletes originals; sync mirror reads; create/restore/delete for manual and auto; persistence across reload; orphan review reads IDB and deletes from it; and the localStorage-fallback path works with zero errors when IDB is forced unavailable.
…mate()
Now that backups live in IndexedDB, the localStorage-only gauge (_lsBytes)
would read near-empty and misreport. Switch _storageStats() to the origin
Storage API:
- _refreshStorageEstimate() caches navigator.storage.estimate() {usage,quota}
(async); _storageStats() reads the cache synchronously so the save()-path
warning and the Backups button color stay synchronous. Refreshed at boot,
on modal open, and via the bar's Recalculate button.
- Falls back to the previous localStorage probe before the first estimate
resolves, or where the Storage API is unavailable.
- Storage bar formats large ceilings as GB, labels the source
"(IndexedDB + localStorage)", and keeps a 1% sliver visible when usage is
tiny against a huge quota. Button thresholds (70/90%) now reflect true
disk-backed pressure, so red/amber effectively only appear under the
localStorage-fallback backend or a genuinely full disk — which is correct.
Verified headlessly on file:// (Chromium): estimate resolves, gauge reports
real quota (895MB in the sandbox) at ~0%, bar renders, no errors.
Final robustness pass for item 5.
- _requestPersistentStorage(): best-effort navigator.storage.persist() at
boot so the browser is less likely to evict our IndexedDB under disk
pressure. Non-blocking, checks persisted() first, tolerant of browsers
that ignore/prompt. (Does not defend against Safari/iOS's ~7-day
inactivity purge — cloud sync + export remain the backstop there.)
Verification (headless Chromium on file://, covering the Chromium family —
Chrome/Edge/Brave):
* cutover suite: migrate+verify+delete originals, sync mirror reads,
create/restore/delete (manual+auto), persist across reload, orphan
review reads+deletes IDB — all pass, zero errors.
* adversarial suite (all pass): migration idempotency; corrupt LS entry
survives migration; no cross-board mirror bleed on switch; stale-write
guard refuses to clobber an unloaded board; concurrent hydration
dedups to one promise; empty boot doesn't crash.
* gauge reads navigator.storage.estimate() on file:// (real quota, ~0%).
* localStorage fallback engages cleanly when IDB is forced unavailable.
NOT covered here (no engine available in CI): Firefox (Gecko) and iPad
Safari (WebKit). file:// storage behavior genuinely varies on those, which
is exactly why the localStorage fallback exists. These need manual
verification on real devices before this is trusted as done on them —
open the file, create a snapshot, fully close and reopen, confirm it
survived. If IDB doesn't persist there, the app silently stays on
localStorage with no data loss.
Claude/eloquent babbage n zjiw
Closes the Q1 gap from the drawbacks review: which backend is active
(IndexedDB vs the localStorage fallback) was previously invisible —
console-only, no UI signal — so a device silently stuck on the old ~5MB
cap looked identical to one on the large IndexedDB store.
- _backupModeInfo(): single source of truth for backend state/label,
used by both the button and the modal.
- Backups button now also goes amber when the fallback is active (not
just on storage-pressure %), and its tooltip states the backend and
usage on one line.
- Backup modal's storage section gains a mode line ("✅ Backup storage:
IndexedDB (large capacity)" / "⚠ Backup storage: Limited local
storage only (~5MB)...") plus, when on the fallback, an explanatory
note recommending regular exports on that device.
- One-time boot toast when the fallback engages, so it's seen even if
Backups is never opened — gated to once per browser session
(sessionStorage flag) so it doesn't repeat on every reload.
- The two previously-silent stale-write guards (setBaks/setAutoBaks
refusing to persist because the mirror wasn't hydrated yet) now also
notify() the user instead of only console.warn — rare, but a skipped
save should never be invisible.
Verified headlessly: normal (IDB) mode shows green button + "IndexedDB"
label + no boot toast; forced-fallback mode shows amber button + boot
toast (fires on first clean session, correctly suppressed on repeat
reloads within the same session) + modal warning block; both stale-write
paths produce a visible toast. Full cutover/adversarial/gauge regression
suites re-run clean with zero errors.
…fault
Previously checking a checklist item always live-moved it toward the done
block (_autoResortDone ran unconditionally whenever no static sort was
active), which meant items could disappear from view the moment you
checked them, whether you wanted that or not.
- New per-board preference S.prefs.chkAutoResort, OFF by default —
checking an item now just toggles its checkbox/strikethrough in place
and stays put.
- A toggle switch ("Auto-move checked items to bottom") now lives at the
top of the checklist Sort dropdown, above the existing sort-mode
options. Clicking it flips the pref, persists via save(), and refreshes
the dropdown IN PLACE rather than closing it, so it reads as a real
switch rather than a menu action.
- toggleCMItem's auto-resort call is now gated on the toggle in addition
to the existing !_chkSorted check, so it's fully inert unless
explicitly enabled.
- Static sort modes (By Due Date / By Priority / Done to Bottom) are
unaffected — they're a separate, explicit user action already.
Verified headlessly: default is off and item order is unchanged after
checking; the toggle appears in the menu; clicking it flips state without
closing the menu and persists the pref; with it on, checking an item
reproduces the exact prior live-reorder behavior; the sort menu's
capture-phase outside-click dismissal still works with the new content.
Claude/eloquent babbage n zjiw
PWA packaging is superseded by a future React app; FlowBoard sync docs now focus solely on the Firebase cross-device sync architecture.
…bluool Remove Android PWA section from deployment report
Replaces the FFD bin-packing agenda with a CSS multi-column newspaper flow in board order: each column (project) is a section, each card (deliverable) is one line with a dotted note-space for handwriting, and checklist items flow inline underneath. Priority is flagged only for High/Med (Low is the default and was noise); progress counts are dropped. Removes the now-obsolete machinery this layout no longer needs: - the per-card height estimation used to balance the two columns - the beforeprint "continued header" injection script and its ag-cont-* styles, plus the hardcoded Letter-size / 0.85 page-height math Pagination is now handled entirely by the browser via break-inside:avoid on cards and break-after:avoid on section headers, so the layout no longer depends on guessed heights and works regardless of page size.
…bluool Rewrite Meeting Agenda report as a two-up project flow
The "✓ Done" pill is driven by card.completed, which was a manual flag only ever cleared by the explicit Reopen / due-✕ buttons. Checking or unchecking checklist items updated done/completedAt but never reconciled completed, and saveCard only maintained completedAt. So after marking a card done (which fills all its items), unchecking an item left completed=true and the pill stuck on both the board and the card modal. toggleCMItem also only refreshed the modal header on a due-date change, so a corrected flag wouldn't repaint. Reconcile completion against the checklist on every item toggle: - new _allItemsDone(card) helper - toggleCMItem / toggleAllItems now set completed = all items checked, so checking the last item completes the card and unchecking any item reopens it; the header refreshes whenever the pill state changes, not only on a due change - saveCard clears a stale completed flag whenever a card has an open item (never auto-sets, so Reopen still holds even with all items checked); item-less cards remain governed by the manual flag Verified headlessly across manual-done→uncheck, check-all/uncheck-all, Reopen-holds, and item-less-card scenarios.
…bluool Fix sticky Done pill when unchecking items or clearing a deadline
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
undo some of the changes in the branch