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:
@@ -104,18 +104,26 @@ async def create_note_route():
|
||||
if proj:
|
||||
project_id = proj.id
|
||||
|
||||
note = await create_note(
|
||||
uid,
|
||||
title=data.get("title", ""),
|
||||
body=body,
|
||||
tags=tags,
|
||||
parent_id=data.get("parent_id"),
|
||||
project_id=project_id,
|
||||
milestone_id=data.get("milestone_id"),
|
||||
status=status,
|
||||
priority=priority,
|
||||
due_date=due_date,
|
||||
)
|
||||
note_type = data.get("note_type", "note")
|
||||
entity_meta = data.get("metadata") or None
|
||||
|
||||
try:
|
||||
note = await create_note(
|
||||
uid,
|
||||
title=data.get("title", ""),
|
||||
body=body,
|
||||
tags=tags,
|
||||
parent_id=data.get("parent_id"),
|
||||
project_id=project_id,
|
||||
milestone_id=data.get("milestone_id"),
|
||||
status=status,
|
||||
priority=priority,
|
||||
due_date=due_date,
|
||||
note_type=note_type,
|
||||
entity_meta=entity_meta,
|
||||
)
|
||||
except ValueError as e:
|
||||
return jsonify({"error": str(e)}), 400
|
||||
text = f"{note.title}\n{note.body}".strip() if note.body else (note.title or "")
|
||||
if text:
|
||||
asyncio.create_task(upsert_note_embedding(note.id, uid, text))
|
||||
@@ -207,9 +215,11 @@ async def update_note_route(note_id: int):
|
||||
uid = get_current_user_id()
|
||||
data = await request.get_json()
|
||||
fields = {}
|
||||
for key in ("title", "body", "parent_id", "project_id", "milestone_id", "status", "priority"):
|
||||
for key in ("title", "body", "parent_id", "project_id", "milestone_id", "status", "priority", "note_type"):
|
||||
if key in data:
|
||||
fields[key] = data[key]
|
||||
if "metadata" in data:
|
||||
fields["entity_meta"] = data["metadata"] or None
|
||||
|
||||
if "due_date" in data:
|
||||
if data["due_date"]:
|
||||
@@ -222,7 +232,10 @@ async def update_note_route(note_id: int):
|
||||
|
||||
if "tags" in data:
|
||||
fields["tags"] = data["tags"]
|
||||
note = await update_note(uid, note_id, **fields)
|
||||
try:
|
||||
note = await update_note(uid, note_id, **fields)
|
||||
except ValueError as e:
|
||||
return jsonify({"error": str(e)}), 400
|
||||
if note is None:
|
||||
return not_found("Note")
|
||||
text = f"{note.title}\n{note.body}".strip() if note.body else (note.title or "")
|
||||
@@ -237,19 +250,30 @@ async def patch_note_route(note_id: int):
|
||||
uid = get_current_user_id()
|
||||
data = await request.get_json()
|
||||
fields = {}
|
||||
for key in ("title", "body", "parent_id", "project_id", "milestone_id", "status", "priority"):
|
||||
for key in ("title", "body", "parent_id", "project_id", "milestone_id", "status", "priority", "note_type"):
|
||||
if key in data:
|
||||
fields[key] = data[key]
|
||||
if "metadata" in data:
|
||||
fields["entity_meta"] = data["metadata"] or None
|
||||
if "due_date" in data:
|
||||
result = parse_iso_date(data.get("due_date"), "due_date")
|
||||
if isinstance(result, tuple):
|
||||
return result
|
||||
fields["due_date"] = result
|
||||
if data["due_date"]:
|
||||
result = parse_iso_date(data["due_date"], "due_date")
|
||||
if isinstance(result, tuple):
|
||||
return result
|
||||
fields["due_date"] = result
|
||||
else:
|
||||
fields["due_date"] = None
|
||||
if "tags" in data:
|
||||
fields["tags"] = data["tags"]
|
||||
note = await update_note(uid, note_id, **fields)
|
||||
try:
|
||||
note = await update_note(uid, note_id, **fields)
|
||||
except ValueError as e:
|
||||
return jsonify({"error": str(e)}), 400
|
||||
if note is None:
|
||||
return not_found("Note")
|
||||
text = f"{note.title}\n{note.body}".strip() if note.body else (note.title or "")
|
||||
if text:
|
||||
asyncio.create_task(upsert_note_embedding(note.id, uid, text))
|
||||
return jsonify(note.to_dict())
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user