From 4eb765091659bb7029d041eb1ad60017004cfc70 Mon Sep 17 00:00:00 2001 From: Timothy Cardoza Date: Thu, 19 Mar 2026 18:48:10 -0500 Subject: [PATCH] Notes linking confirmed --- src/views/NotepadView.tsx | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/src/views/NotepadView.tsx b/src/views/NotepadView.tsx index dcf8ee9..5c37193 100644 --- a/src/views/NotepadView.tsx +++ b/src/views/NotepadView.tsx @@ -1,5 +1,5 @@ import { type Component, createSignal, createMemo, createEffect, onCleanup, For, Show } from "solid-js"; -import { store, renameTagDefinition, updateNote, removeNote, restoreNote, setActiveNoteId, cleanupNoteAttachments, getFavoriteTag, fetchNoteById, updateStoreWithNote } from "@/store"; +import { store, renameTagDefinition, updateNote, updateTask, removeNote, restoreNote, setActiveNoteId, cleanupNoteAttachments, getFavoriteTag, fetchNoteById, updateStoreWithNote } from "@/store"; import { pb } from "@/lib/pocketbase"; import { type Note } from "@/store"; import { Plus, X, Lock, Unlock, Trash2, ChevronDown, Link as LinkIcon, MoreHorizontal, Type, FileText, Search, Star, ChevronRight } from "lucide-solid"; @@ -14,7 +14,7 @@ import { NotesSidebar } from "@/components/NotesSidebar"; import { toast } from "solid-sonner"; import { TextBubbleMenu } from "@/components/TextBubbleMenu"; import { TableBubbleMenu } from "@/components/TableBubbleMenu"; -import { normalizeNoteKey } from "@/lib/tags"; +import { buildNoteTag, normalizeNoteKey } from "@/lib/tags"; export const NotepadView: Component<{ selectedNoteId: string | null; @@ -106,12 +106,15 @@ export const NotepadView: Component<{ }; const handleRenameNote = async (id: string, oldTitle: string, newTitle: string) => { + const currentNote = store.notes.find(note => note.id === id); + const oldKey = currentNote?.key || normalizeNoteKey(oldTitle); + const newKey = normalizeNoteKey(newTitle); + // 1. Update the note title - await handleUpdateNote(id, { title: newTitle }); + await handleUpdateNote(id, { title: newTitle, key: newKey }); // 2. Rename the TagDefinition (preserves color) and propagate to all tagged tasks - // Use '#' prefix for note tags - await renameTagDefinition(`#${oldTitle}`, `#${newTitle}`); + await renameTagDefinition(buildNoteTag(oldKey), buildNoteTag(newKey)); }; const handleDeleteNote = async (id: string) => { @@ -134,8 +137,13 @@ export const NotepadView: Component<{ const handleLinkTask = async (taskId: string) => { const note = activeNote(); if (!note) return; + const task = store.tasks.find(existing => existing.id === taskId); + const noteTag = buildNoteTag(note.key || note.title); const newTasks = [...(note.tasks || []), taskId]; await handleUpdateNote(note.id, { tasks: newTasks }); + if (task && !task.tags.some(tag => tag.toLowerCase() === noteTag.toLowerCase())) { + await updateTask(taskId, { tags: [...task.tags, noteTag] }); + } setIsLinking(false); setLinkSearchQuery(""); }; @@ -143,20 +151,25 @@ export const NotepadView: Component<{ const handleUnlinkTask = async (taskId: string) => { const note = activeNote(); if (!note) return; + const task = store.tasks.find(existing => existing.id === taskId); + const noteTag = buildNoteTag(note.key || note.title).toLowerCase(); const newTasks = (note.tasks || []).filter(id => id !== taskId); await handleUpdateNote(note.id, { tasks: newTasks }); + if (task && task.tags.some(tag => tag.toLowerCase() === noteTag)) { + await updateTask(taskId, { tags: task.tags.filter(tag => tag.toLowerCase() !== noteTag) }); + } }; // Linked tasks calculation const linkedTasks = createMemo(() => { const note = activeNote(); if (!note) return []; - const noteTagName = `#${note.title}`; + const noteTagName = buildNoteTag(note.key || note.title).toLowerCase(); return store.tasks.filter(t => { // Explicit relation if (note.tasks && note.tasks.includes(t.id)) return true; - // Tag relation (case-insensitive title match with # prefix) - if (t.tags && t.tags.some(tag => tag.toLowerCase() === noteTagName.toLowerCase())) return true; + if (t.noteRefs && t.noteRefs.some(ref => ref.key === note.key || ref.noteId === note.id)) return true; + if (t.tags && t.tags.some(tag => tag.toLowerCase() === noteTagName)) return true; return false; }); }); @@ -184,7 +197,11 @@ export const NotepadView: Component<{ if (!hasPinnedBucket) return false; } - if (note.tasks && note.tasks.includes(t.id)) return false; // Already linked + const isAlreadyLinked = + (note.tasks && note.tasks.includes(t.id)) || + t.noteRefs?.some(ref => ref.key === note.key || ref.noteId === note.id) || + t.tags?.some(tag => tag.toLowerCase() === buildNoteTag(note.key || note.title).toLowerCase()); + if (isAlreadyLinked) return false; if (!q) return false; // Don't show all by default return t.title.toLowerCase().includes(q); }).slice(0, 10);