feat(knowledge): note types, counts, new-note button, audit fixes

- Add note_type (note/person/place/list) selector + entity metadata fields
  (relationship, email, phone / address, hours) to NoteEditorView
- Pre-select type via ?type= query param from KnowledgeView new-note dropdown
- KnowledgeView: add split "New note / ▾" button with type dropdown
- KnowledgeView: show per-type counts on sidebar filter buttons (when > 1)
- Fix: filter-btn now flex layout so count badge aligns to right edge
- Fix: list_notes count_query was missing parent_id filter (inflated totals)
- Fix: PATCH /api/notes/:id now fires upsert_note_embedding (workspace autosave)
- Fix: get_knowledge_counts endpoint for per-type counts
- Fix: get_knowledge_tags was silently discarding note_type filter (double-stmt bug)
- Fix: NoteEditorView onMounted stray brace from edit session

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-04 12:53:09 -04:00
parent 738245af5c
commit ed715dcc23
8 changed files with 328 additions and 58 deletions
+9 -2
View File
@@ -188,6 +188,7 @@ async def list_notes(
if parent_id is not None:
query = query.where(Note.parent_id == parent_id)
count_query = count_query.where(Note.parent_id == parent_id)
if no_project:
query = query.where(Note.project_id.is_(None))
@@ -242,9 +243,15 @@ async def update_note(user_id: int, note_id: int, **fields: object) -> Note | No
if not hasattr(note, key):
continue
if key == "status" and isinstance(value, str):
value = TaskStatus(value).value
try:
value = TaskStatus(value).value
except ValueError:
raise ValueError(f"Invalid status: {value!r}. Must be one of: {[s.value for s in TaskStatus]}")
elif key == "priority" and isinstance(value, str):
value = TaskPriority(value).value
try:
value = TaskPriority(value).value
except ValueError:
raise ValueError(f"Invalid priority: {value!r}. Must be one of: {[p.value for p in TaskPriority]}")
elif key == "tags" and isinstance(value, list):
value = _normalize_tags(value)
setattr(note, key, value)