Fix project/milestone association and redesign AppHeader navigation
Backend: - routes/tasks.py: POST + PUT were silently dropping project_id, milestone_id, parent_id from request body — root cause of association not saving from the task editor - routes/tasks.py: GET /api/tasks/:id now includes parent_title in response (secondary lookup when parent_id is set) - routes/notes.py: add PATCH /api/notes/:id for partial updates (used by sub-task status toggle; PUT already existed but PATCH was missing) - routes/projects.py: GET /api/projects/:id/notes now fetches milestone IDs and passes them via milestone_ids so tasks assigned to a milestone (but lacking project_id) are included in the project view - services/notes.py: create_note() auto-sets project_id from milestone when milestone_id is provided and project_id is omitted; list_notes() gains milestone_ids param — when combined with project_id uses OR condition (project_id=X OR milestone_id IN (...)) Frontend: - NoteEditorView: add MilestoneSelector; milestone resets when project changes; all save paths (save/create/auto-save) include milestone_id - stores/notes.ts: add milestone_id to createNote + updateNote types - TaskEditorView: sub-tasks now inherit milestone_id from parent task - AppHeader: three-zone layout — brand left, Notes/Projects/Tasks/Chat centered (absolute positioning), right rail with status/theme/? and gear dropdown containing Settings/Users/Logs; mobile dropdown unchanged Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -81,6 +81,9 @@ async def create_task_route():
|
||||
priority=priority,
|
||||
due_date=due_date,
|
||||
tags=tags,
|
||||
project_id=data.get("project_id"),
|
||||
milestone_id=data.get("milestone_id"),
|
||||
parent_id=data.get("parent_id"),
|
||||
)
|
||||
return jsonify(task.to_dict()), 201
|
||||
|
||||
@@ -92,7 +95,11 @@ async def get_task_route(task_id: int):
|
||||
task = await get_note(uid, task_id)
|
||||
if task is None:
|
||||
return jsonify({"error": "Task not found"}), 404
|
||||
return jsonify(task.to_dict())
|
||||
data = task.to_dict()
|
||||
if task.parent_id:
|
||||
parent = await get_note(uid, task.parent_id)
|
||||
data["parent_title"] = parent.title if parent else None
|
||||
return jsonify(data)
|
||||
|
||||
|
||||
@tasks_bp.route("/<int:task_id>", methods=["PUT"])
|
||||
@@ -123,6 +130,10 @@ async def update_task_route(task_id: int):
|
||||
if "tags" in data:
|
||||
fields["tags"] = data["tags"]
|
||||
|
||||
for key in ("project_id", "milestone_id", "parent_id"):
|
||||
if key in data:
|
||||
fields[key] = data[key]
|
||||
|
||||
task = await update_note(uid, task_id, **fields)
|
||||
if task is None:
|
||||
return jsonify({"error": "Task not found"}), 404
|
||||
|
||||
Reference in New Issue
Block a user