From 6b4773130cb6f07dce10a1775fe96068e3860bd9 Mon Sep 17 00:00:00 2001 From: Abhimanyu Saharan Date: Mon, 2 Feb 2026 20:42:55 +0530 Subject: [PATCH] feat(review): notify manager on review + UI approve/request changes --- backend/app/api/work.py | 11 +++++++++ frontend/src/app/projects/[id]/page.tsx | 32 +++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/backend/app/api/work.py b/backend/app/api/work.py index bb1de890..817c9b9c 100644 --- a/backend/app/api/work.py +++ b/backend/app/api/work.py @@ -152,6 +152,17 @@ def update_task( if "status" in data and data["status"] not in ALLOWED_STATUSES: raise HTTPException(status_code=400, detail="Invalid status") + # If a task is sent to review and no reviewer is set, default reviewer to assignee's manager. + if ( + data.get("status") in {"review", "ready_for_review"} + and data.get("reviewer_employee_id") is None + ): + assignee_id = data.get("assignee_employee_id", task.assignee_employee_id) + if assignee_id is not None: + assignee = session.get(Employee, assignee_id) + if assignee is not None and assignee.manager_id is not None: + data["reviewer_employee_id"] = assignee.manager_id + for k, v in data.items(): setattr(task, k, v) task.updated_at = datetime.utcnow() diff --git a/frontend/src/app/projects/[id]/page.tsx b/frontend/src/app/projects/[id]/page.tsx index 253faeb3..b1b918e0 100644 --- a/frontend/src/app/projects/[id]/page.tsx +++ b/frontend/src/app/projects/[id]/page.tsx @@ -340,6 +340,10 @@ export default function ProjectDetailPage() { assignee.openclaw_session_key, ); + const actorId = getActorEmployeeId(); + const isReviewer = Boolean(actorId && t.reviewer_employee_id && Number(t.reviewer_employee_id) === actorId); + const canReviewActions = Boolean(t.id != null && isReviewer && (t.status ?? "") === "review"); + return (
{t.title}
@@ -391,6 +395,34 @@ export default function ProjectDetailPage() { Trigger + {canReviewActions ? ( + <> + + + + ) : null} +