feat(review): notify manager on review + UI approve/request changes
This commit is contained in:
@@ -152,6 +152,17 @@ def update_task(
|
|||||||
if "status" in data and data["status"] not in ALLOWED_STATUSES:
|
if "status" in data and data["status"] not in ALLOWED_STATUSES:
|
||||||
raise HTTPException(status_code=400, detail="Invalid status")
|
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():
|
for k, v in data.items():
|
||||||
setattr(task, k, v)
|
setattr(task, k, v)
|
||||||
task.updated_at = datetime.utcnow()
|
task.updated_at = datetime.utcnow()
|
||||||
|
|||||||
@@ -340,6 +340,10 @@ export default function ProjectDetailPage() {
|
|||||||
assignee.openclaw_session_key,
|
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 (
|
return (
|
||||||
<div key={t.id ?? t.title} className="rounded-md border p-2 text-sm">
|
<div key={t.id ?? t.title} className="rounded-md border p-2 text-sm">
|
||||||
<div className="font-medium">{t.title}</div>
|
<div className="font-medium">{t.title}</div>
|
||||||
@@ -391,6 +395,34 @@ export default function ProjectDetailPage() {
|
|||||||
Trigger
|
Trigger
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
{canReviewActions ? (
|
||||||
|
<>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
onClick={() =>
|
||||||
|
updateTask.mutate({
|
||||||
|
taskId: Number(t.id),
|
||||||
|
data: { status: "done" },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Approve
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => {
|
||||||
|
setCommentTaskId(Number(t.id));
|
||||||
|
setReplyToCommentId(null);
|
||||||
|
}}
|
||||||
|
title="Leave a comment asking for changes, then move status back to in_progress"
|
||||||
|
>
|
||||||
|
Request changes
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
variant="destructive"
|
variant="destructive"
|
||||||
size="sm"
|
size="sm"
|
||||||
|
|||||||
Reference in New Issue
Block a user