M7: unify compose + edit into one NoteEditor (DRY)
CI & Build / Python lint (push) Successful in 2s
CI & Build / TypeScript typecheck (push) Successful in 4s
CI & Build / Python tests (push) Successful in 7s
CI & Build / Build & push image (push) Successful in 40s

The 'Take a note' composer (QuickAdd) and the note editor were two components with duplicated field logic and unequal capabilities — composing lacked [[ links, labels, images, reminders. Merge them into a single NoteEditor with two frames: inline on the board (compose), modal on a card (edit). Same fields, styling, [[ autocomplete and toolbar in both (task 1920).

Compose is now a draft that persists on first real action: on commit-with-content, or on the first label/image/reminder/checklist use (ensureDraft) — so no empty-note litter. Rich controls light up once there's content; note-lifecycle actions (pin/archive/trash, links/backlinks) stay in the modal. notes.create() now returns the created note (for the draft id). QuickAdd.vue deleted; BoardView renders <NoteEditor inline>.

Pure frontend — no backend/DB/migration. Sets up the editor<->card morph (task 1914).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FRgehjoz7Yv8LkUfADxACm
This commit is contained in:
2026-07-22 14:05:00 -04:00
co-authored by Claude Opus 4.8
parent ae0c748507
commit bb33d5c495
4 changed files with 347 additions and 288 deletions
+3 -4
View File
@@ -3,7 +3,6 @@ import { computed, onBeforeUnmount, onMounted, ref, watch } from "vue";
import { useRoute, useRouter } from "vue-router";
import { useNotesStore, type Note, type NoteView } from "../stores/notes";
import { useUiStore } from "../stores/ui";
import QuickAdd from "../components/QuickAdd.vue";
import NoteCard from "../components/NoteCard.vue";
import NoteEditor from "../components/NoteEditor.vue";
@@ -13,14 +12,14 @@ const ui = useUiStore();
const router = useRouter();
const editing = ref<Note | null>(null);
const quickAdd = ref<InstanceType<typeof QuickAdd> | null>(null);
const composer = ref<InstanceType<typeof NoteEditor> | null>(null);
const loadError = ref("");
// The global `c` shortcut bumps composeTick; reopen the composer when we're
// already on the board (a fresh navigation autofocuses it via the prop).
watch(
() => ui.composeTick,
() => quickAdd.value?.open(),
() => composer.value?.open(),
);
// The command palette opens a note by navigating here with ?open=<id>.
@@ -175,7 +174,7 @@ async function onDrop(target: Note) {
<template>
<div class="mx-auto w-full max-w-6xl px-4 py-6">
<QuickAdd v-if="isMainBoard" ref="quickAdd" autofocus class="mb-8" />
<NoteEditor v-if="isMainBoard" ref="composer" inline autofocus class="mb-8" />
<div v-if="notes.loading" class="py-24 text-center text-sm text-neutral-400">Loading</div>