Skip to content

fix(web): note save was re-rendering the editor, causing content to duplicate#11

Merged
SwathiMystery merged 1 commit intomainfrom
fix/note-save-duplication
Apr 21, 2026
Merged

fix(web): note save was re-rendering the editor, causing content to duplicate#11
SwathiMystery merged 1 commit intomainfrom
fix/note-save-duplication

Conversation

@SwathiMystery
Copy link
Copy Markdown
Contributor

Bug

Every save of a daily or trade note appeared to duplicate the textarea content. Hitting save a second time duplicated again.

Root cause

  • `POST /notes/{trade|day}/...` returned the full `note_block` partial, and `hx-swap="outerHTML"` replaced `#note-block` wholesale.
  • EasyMDE's CodeMirror sat inside `#note-block`. When the block swapped, the old CodeMirror stayed attached to the detached textarea while a new one mounted on the fresh textarea.
  • The `htmx:afterSwap` re-mount listener was registered inside `wire()` — so every mount added another listener. Every save then fired N listeners, each attempting to re-mount. Multiple stacked CodeMirror instances all flushed into the same hidden textarea → content visually duplicated.

Fix

  • New partial `partials/note_meta.html`: a single `<span id="note-meta-stamp">` with the saved-at timestamp.
  • Save endpoint now returns just that span (78 bytes per save vs ~1.5 KB of editor HTML).
  • Form's `hx-target` narrowed to `#note-meta-stamp`; editor DOM untouched.
  • `editor.js`: CodeMirror `blur` now calls `htmx.trigger(form, 'khata-save')` — autosave without re-rendering.
  • Removed the `htmx:afterSwap` re-mount listener (nothing swaps the editor anymore).
  • Tests updated to assert the stamp-only response, then verify persistence via follow-up GET.

Verification

POST /notes/day/2026-04-15  (body=\"Hello from a save test\")
→ 200  78B  <span id=\"note-meta-stamp\" class=\"subtle\">saved 2026-04-21 04:29:42 UTC</span>
POST /notes/day/2026-04-15  (body=\"Second save\")
→ 200  78B  <span id=\"note-meta-stamp\" class=\"subtle\">saved 2026-04-21 04:29:42 UTC</span>
GET  /day/2026-04-15
→ editor textarea contains \"Second save\" exactly once.

Checklist

  • 46/46 tests green
  • `uv run ruff check khata tests` clean
  • `uv run ruff format khata tests` applied
  • No schema change

…uplicate

Root cause
- POST /notes/{trade|day}/... returned the entire note_block partial,
  and the form's hx-swap="outerHTML" replaced #note-block wholesale.
- EasyMDE's CodeMirror DOM sat *inside* #note-block. When the block
  was swapped, the old CodeMirror stayed attached to the detached
  textarea while a new one mounted on the fresh textarea. The
  htmx:afterSwap listener that re-wired the editor was registered
  inside wire() — one listener per mount — so every save added
  another listener and every listener re-mounted. Content visually
  duplicated because multiple CodeMirrors stacked on top of each
  other all flushed into the same hidden textarea.

Fix
- Save endpoint now returns just partials/note_meta.html — a single
  <span id="note-meta-stamp"> with the saved-at timestamp. 78 bytes
  per save versus ~1.5 KB of editor HTML.
- Form's hx-target narrowed to #note-meta-stamp, hx-swap="outerHTML"
  replaces only that span. Editor DOM untouched.
- editor.js: CodeMirror 'blur' now fires htmx.trigger(form,
  'khata-save') — autosave without touching the editor DOM.
- Removed the htmx:afterSwap re-mount listener (no longer needed;
  nothing swaps the editor).
- Tests updated to assert the stamp-only response, then verify
  persistence via a follow-up GET.

No schema change. 46/46 tests green.
@SwathiMystery SwathiMystery merged commit d7f5f37 into main Apr 21, 2026
7 checks passed
@SwathiMystery SwathiMystery deleted the fix/note-save-duplication branch April 21, 2026 04:36
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.

1 participant