Q153: the approval button that reviews a request is called Review, and leads to where the request can change
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
e8634afb82
commit
af831abd53
3 files changed
+32
-5
No files matched your search
@@ -40,6 +40,9 @@ export const zh: Record<string, string> = {
|
||||
"Reopen": "重新打开",
|
||||
"Back to backlog": "退回待办",
|
||||
"Delete this task?": "删除这个任务?",
|
||||
"Review": "审阅",
|
||||
"Edit the task": "编辑任务",
|
||||
"Changing the task replaces this request with a fresh one.": "修改任务会用新的申请替换这一项。",
|
||||
"Delete task": "删除任务",
|
||||
"Nothing else is affected.": "不影响其他内容。",
|
||||
"{n} sessions and their action records are deleted.": "{n} 次会话及其操作记录将被删除。",
|
||||
|
||||
@@ -116,7 +116,7 @@ export function ApprovalsPage({ snapshot, actions, navigate, focus }: PageProps)
|
||||
isBot={approval.requestedByType === "agent"}
|
||||
onApprove={() => decide(approval, "approved")}
|
||||
onDecline={() => decide(approval, "declined")}
|
||||
onEdit={() => setEditingId(approval.id)}
|
||||
onReview={() => setEditingId(approval.id)}
|
||||
/>
|
||||
))}
|
||||
|
||||
@@ -191,7 +191,12 @@ function ApprovalDetailDialog({
|
||||
<>
|
||||
<span style={{ color: "var(--text-3)" }}>{t("Source")}</span>
|
||||
{approval.sourceEntityType === "task" && approval.sourceEntityId
|
||||
? <button type="button" className="link-button" onClick={() => onOpenTask(approval.sourceEntityId!)}>{t("Open task")}</button>
|
||||
? (
|
||||
<span>
|
||||
<button type="button" className="link-button" onClick={() => onOpenTask(approval.sourceEntityId!)}>{t("Edit the task")}</button>
|
||||
<span style={{ color: "var(--text-3)" }}> · {t("Changing the task replaces this request with a fresh one.")}</span>
|
||||
</span>
|
||||
)
|
||||
: <span>{humanizeKind(approval.sourceEntityType)}</span>}
|
||||
</>
|
||||
)}
|
||||
@@ -254,14 +259,15 @@ function ApprovalRow({
|
||||
isBot,
|
||||
onApprove,
|
||||
onDecline,
|
||||
onEdit,
|
||||
onReview,
|
||||
}: {
|
||||
approval: ApprovalRecord;
|
||||
requester: string;
|
||||
isBot: boolean;
|
||||
onApprove: () => void;
|
||||
onDecline: () => void;
|
||||
onEdit: () => void;
|
||||
/** Opens the request to read it in full and decide with notes; what is requested is changed at its source. */
|
||||
onReview: () => void;
|
||||
}) {
|
||||
const tone = RISK_TONES[approval.risk];
|
||||
if (!tone) throw new Error("Approval risk tone is missing.");
|
||||
@@ -297,7 +303,7 @@ function ApprovalRow({
|
||||
</div>
|
||||
<div style={{ display: "flex", flexDirection: "column", gap: 6, alignItems: "flex-end" }}>
|
||||
<Button tone="primary" onClick={onApprove}>{t("Approve")}</Button>
|
||||
<Button onClick={onEdit}>{t("Edit")}</Button>
|
||||
<Button onClick={onReview}>{t("Review")}</Button>
|
||||
<Button tone="ghost" onClick={onDecline}>{t("Decline")}</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -97,6 +97,24 @@ test("the pinned CEO conversation is the Messages front door", async () => {
|
||||
return [task.writingMode, task.requiresFilesystem];
|
||||
});
|
||||
expect(edited).toEqual(["technical", true]);
|
||||
// A pending request opens for review: read it in full and decide with notes; nothing there pretends to edit it.
|
||||
await taskDialog.getByRole("button", { name: "Close" }).click();
|
||||
await page.evaluate(async () => {
|
||||
const api = (window as unknown as { agentCompany: {
|
||||
loadSnapshot: () => Promise<{ ok: true; data: { activeOrgId: string } }>;
|
||||
createApproval: (input: unknown) => Promise<{ ok: boolean }>;
|
||||
} }).agentCompany;
|
||||
const orgId = (await api.loadSnapshot()).data.activeOrgId;
|
||||
await api.createApproval({ orgId, kind: "budget_increase", title: "Raise the ads budget", details: "From $200 to $500.", risk: "medium", requestedByType: "system", requestedById: null });
|
||||
});
|
||||
await page.getByRole("button", { name: "Approvals" }).click();
|
||||
await expect(page.getByRole("button", { name: "Edit", exact: true })).toHaveCount(0);
|
||||
await page.getByRole("button", { name: "Review" }).first().click();
|
||||
const review = page.getByRole("dialog", { name: "Raise the ads budget" });
|
||||
await expect(review.getByRole("textbox", { name: "Decision notes" })).toBeVisible();
|
||||
await review.getByRole("button", { name: "Close" }).click();
|
||||
await page.getByRole("button", { name: "Work" }).click();
|
||||
await page.getByRole("button", { name: /Operationalize goal: Ship the FlowPilot MVP\./ }).first().click();
|
||||
// Blocking says why on the task and stops it; work can also move backwards.
|
||||
await taskDialog.getByRole("button", { name: "Block", exact: true }).click();
|
||||
await taskDialog.getByRole("textbox", { name: "Why is it blocked?" }).fill("Waiting for the legal review.");
|
||||
|
||||
Reference in new issue
Block a user