Skip to content

fix(schedule): derive the item editor's selection from the document - #92

Merged
atman-33 merged 1 commit into
mainfrom
fix/schedule-editor-stale-selection
Jul 27, 2026
Merged

fix(schedule): derive the item editor's selection from the document#92
atman-33 merged 1 commit into
mainfrom
fix/schedule-editor-stale-selection

Conversation

@atman-33

Copy link
Copy Markdown
Owner

Problem

In the Schedule tab, an edit made in the side panel could undo a change made on
the grid.

Reported case: create a bar for 7/5–7/6, shorten it to 7/5, then change its
kind to arrow — the period jumps back to 7/5–7/6.

Root cause

The selected element was held as a copy in two places while doc was the real
source of truth:

  • schedule-view.tsxconst [selected, setSelected] = useState<ScheduleItem | null>(null)
  • item-editor.tsxconst [draft, setDraft] = useState(item), re-seeded from
    the prop by a useEffect

Every edit path that does not run through the side panel updates doc alone and
leaves both copies stale: a drag or resize on the grid (ScheduleGrid suppresses
onSelectItem when the pointer moved, so the selection is never refreshed), an
undo, or a reload after an Obsidian / AI-agent edit.

The editor's commit then hands { ...draft, ...patch } — the whole stale
element — to patchItem, writing the pre-drag values back over the document.

The reported case is one instance. The same revert happened for title, colour and
task-link edits after any grid gesture.

Fix

Make the selection a derived value instead of a copy, so the staleness cannot
exist:

  • schedule-view.tsx stores only selectedId; the element is looked up in
    doc.items with useMemo. All call sites follow (file switch, undo/redo,
    Escape, Delete, grid selection, editor callbacks, element creation), and the
    arrow-key nudges now call patchItem alone.
  • item-editor.tsx renders straight from its item prop — the local draft state
    and its re-seeding effect are gone. commit builds { ...item, ...patch };
    the normalisation (start/end inversion guard, end = start for point kinds) is
    unchanged.
  • Recorded the pattern in .claude/rules/ui-conventions.md so future side panels
    do not reintroduce it.

Intended side effects: the panel now follows external file edits, and it closes
itself when the selected element is deleted.

Verification

  • npm run build — passed
  • npm test — 124/124 passed (10 files)

No component test added: the repo has no jsdom/testing-library setup, only
node-environment vitest for src/lib. Manual checks:

  1. Bar 7/5–7/6 → drag its right edge to 7/5 → switch kind to arrow: the period
    stays 7/5.
  2. Drag a bar sideways, then edit its title: the position does not jump back.
  3. Edit the note in Obsidian with the panel open: the panel shows the new values
    after the reload.

🤖 Generated with Claude Code

The schedule view kept the selected element as a copy in state, and the
item editor kept a second copy as a local draft. Every edit path that does
not pass through the editor -- a drag or resize on the grid, an arrow-key
nudge, an undo, a reload after an Obsidian or agent edit -- updated the
document only, leaving both copies behind. The editor's next patch then
spread its stale copy back over the document, reverting the earlier edit.

Reported case: shorten a bar from 7/5-7/6 to 7/5 by dragging, then switch
its kind to arrow in the panel, and the end date jumps back to 7/6. The
same revert happened for any panel edit after a grid gesture, not just the
kind field.

Store only the selected id and look the element up in the document, and
render the editor straight from its `item` prop. The panel now also follows
external file edits and closes itself when the element is deleted.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d367b208-1e20-4cb4-90c6-78d0a1b928cd

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/schedule-editor-stale-selection

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@atman-33
atman-33 merged commit d84836f into main Jul 27, 2026
2 checks passed
@atman-33
atman-33 deleted the fix/schedule-editor-stale-selection branch July 27, 2026 14:41
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