Restore approvals review list grammar

This commit is contained in:
ZacharyZhang-NY committed 2026-04-19 17:38:04 -04:00
1 parent 5b686b0ce1
commit a86315168b
3 files changed
+166 -74

No files matched your search

@@ -17,37 +17,10 @@ impl AppRoot {
div()
.flex()
.flex_col()
.gap_8()
.child(section_title("Agent reviews in progress"))
.child(
div()
.grid()
.grid_cols(3)
.gap_3()
.when(!groups.board.is_empty(), |container| {
container.child(review_group_card("Board review", groups.board.as_slice()))
})
.when(!groups.user.is_empty(), |container| {
container.child(review_group_card("Human review", groups.user.as_slice()))
})
.when(!groups.manager.is_empty(), |container| {
container.child(review_group_card(
"Manager review",
groups.manager.as_slice(),
))
})
.when(
groups.board.is_empty()
&& groups.user.is_empty()
&& groups.manager.is_empty(),
|container| {
container.child(empty_group_card(
"No agent reviews are currently waiting on a human.",
))
},
),
)
.child(section_title("Pending approvals"))
.gap_6()
.child(section_label("AGENT REVIEWS IN PROGRESS"))
.child(render_review_groups_panel(&groups))
.child(section_label("PENDING APPROVALS"))
.child(
div()
.grid()
@@ -105,14 +78,14 @@ impl AppRoot {
.border_color(theme::panel_border())
.child(
div()
.text_base()
.text_sm()
.text_color(theme::text_primary())
.child(approval.payload_summary.clone()),
)
.child(
div()
.mt(px(4.0))
.text_sm()
.text_xs()
.text_color(theme::text_muted())
.child(format!(
"{} · {}",
@@ -223,6 +196,14 @@ struct ReviewRow<'a> {
task: &'a domain::Task,
assignee: Option<&'a domain::Agent>,
reviewer: Option<&'a domain::Agent>,
kind: ReviewKind,
}
#[derive(Clone, Copy)]
enum ReviewKind {
Board,
User,
Manager,
}
fn review_groups(snapshot: &domain::ProfileSnapshot) -> ReviewGroups<'_> {
@@ -249,20 +230,37 @@ fn review_groups(snapshot: &domain::ProfileSnapshot) -> ReviewGroups<'_> {
let reviewer = assignee
.and_then(|assignee| assignee.reports_to.as_ref())
.and_then(|manager_id| snapshot.agents.iter().find(|agent| &agent.id == manager_id));
let row = ReviewRow {
task,
assignee,
reviewer,
};
if pending_approval_task_ids
let row = if pending_approval_task_ids
.iter()
.any(|task_id| *task_id == task.id)
{
board.push(row);
ReviewRow {
task,
assignee,
reviewer: None,
kind: ReviewKind::Board,
}
} else if task.requires_user_review || reviewer.is_none() {
user.push(row);
ReviewRow {
task,
assignee,
reviewer: None,
kind: ReviewKind::User,
}
} else {
manager.push(row);
ReviewRow {
task,
assignee,
reviewer,
kind: ReviewKind::Manager,
}
};
match row.kind {
ReviewKind::Board => board.push(row),
ReviewKind::User => user.push(row),
ReviewKind::Manager => manager.push(row),
}
}
@@ -273,39 +271,91 @@ fn review_groups(snapshot: &domain::ProfileSnapshot) -> ReviewGroups<'_> {
}
}
fn review_group_card(title: &'static str, rows: &[ReviewRow<'_>]) -> impl IntoElement {
fn render_review_groups_panel(groups: &ReviewGroups<'_>) -> impl IntoElement {
let has_rows =
!(groups.board.is_empty() && groups.user.is_empty() && groups.manager.is_empty());
div()
.rounded_lg()
.border_1()
.border_color(theme::panel_border())
.bg(theme::panel())
.when(has_rows, |container| {
container
.when(!groups.board.is_empty(), |inner| {
inner.child(review_group_section(
"Board review",
groups.board.as_slice(),
))
})
.when(!groups.user.is_empty(), |inner| {
inner.child(review_group_section("Human review", groups.user.as_slice()))
})
.when(!groups.manager.is_empty(), |inner| {
inner.child(review_group_section(
"Manager review",
groups.manager.as_slice(),
))
})
})
.when(!has_rows, |container| {
container.child(
div()
.min_h(px(180.0))
.flex()
.items_center()
.justify_center()
.text_color(theme::text_muted())
.child("No agent reviews are currently waiting on a human."),
)
})
}
fn review_group_section<'a>(
title: &'static str,
rows: &'a [ReviewRow<'a>],
) -> impl IntoElement + 'a {
div()
.child(
div()
.px_4()
.pt_4()
.pb_2()
.pt_3()
.pb_1()
.text_xs()
.text_color(theme::text_muted())
.child(title),
)
.children(rows.iter().map(|row| {
div()
.flex()
.items_start()
.gap_3()
.px_4()
.py_3()
.border_b_1()
.border_color(theme::panel_border())
.child(
div()
.text_sm()
.text_color(theme::text_primary())
.child(row.task.title.clone()),
.w(px(28.0))
.h(px(28.0))
.rounded_lg()
.bg(theme::panel_muted()),
)
.child(
div()
.mt(px(4.0))
.text_xs()
.text_color(theme::text_muted())
.child(review_row_subtitle(row)),
.flex_1()
.child(
div()
.text_sm()
.text_color(theme::text_primary())
.child(row.task.title.clone()),
)
.child(
div()
.mt(px(4.0))
.text_xs()
.text_color(theme::text_muted())
.child(review_row_subtitle(row)),
),
)
}))
}
@@ -315,31 +365,18 @@ fn review_row_subtitle(row: &ReviewRow<'_>) -> String {
.assignee
.map(|agent| agent.name.clone())
.unwrap_or_else(|| "Unassigned".to_string());
match row.reviewer {
Some(reviewer) => format!("{} → reviewed by {}", assignee, reviewer.name),
None => format!("{} · awaiting human review", assignee),
match row.kind {
ReviewKind::Board => format!("{} · awaits board review", assignee),
ReviewKind::User => format!("{} · awaits human review", assignee),
ReviewKind::Manager => match row.reviewer {
Some(reviewer) => format!("{} → reviewed by {}", assignee, reviewer.name),
None => format!("{} · awaiting manager review", assignee),
},
}
}
fn empty_group_card(message: &'static str) -> impl IntoElement {
div()
.rounded_lg()
.border_1()
.border_color(theme::panel_border())
.bg(theme::panel())
.min_h(px(180.0))
.flex()
.items_center()
.justify_center()
.text_color(theme::text_muted())
.child(message)
}
fn section_title(title: &'static str) -> impl IntoElement {
div()
.text_2xl()
.text_color(theme::text_primary())
.child(title)
fn section_label(title: &'static str) -> impl IntoElement {
div().text_xs().text_color(theme::text_muted()).child(title)
}
fn pending_approvals(
+53
View File
@@ -238,6 +238,59 @@
"priority": 17,
"passes": true,
"notes": "Passed: native runs now restores the original operational shell more faithfully with a dedicated Run Queue panel on the left and a Run Detail column on the right. Runtime events, artifacts, and operator controls remain available but are demoted to secondary panels below the main detail hierarchy."
},
{
"id": "US-018",
"title": "Restore approvals shell and inspector grammar to original review surface",
"description": "As an operator, I want approvals and review grouping to mirror the original Electron review surface so that decision work feels identical.",
"acceptanceCriteria": [
"Approvals page restores source-aligned review grouping and pending approval inspector grammar",
"Typecheck passes",
"cargo test --workspace passes"
],
"priority": 18,
"passes": true,
"notes": "Passed: approvals now restore a source-aligned grouped review list on the upper half instead of custom parallel cards, while the pending approval list/detail decision surface stays wired to real approval state transitions."
},
{
"id": "US-019",
"title": "Restore document center and editor grammar to original operational surface",
"description": "As an operator, I want the native document center to mirror the original Electron prose/work-product/editor hierarchy so that company documents feel unchanged.",
"acceptanceCriteria": [
"Document Center restores source-aligned list, work-product, and editor grammar",
"Typecheck passes",
"cargo test --workspace passes"
],
"priority": 19,
"passes": false,
"notes": "Opened after strict current-directory-only source audit."
},
{
"id": "US-020",
"title": "Restore inbox and messages operational grammar to original communication surfaces",
"description": "As an operator, I want inbox and messages to mirror the original Electron communication hierarchy so that routing, filtering, and thread inspection feel identical.",
"acceptanceCriteria": [
"Inbox and messages restore source-aligned shell grammar and interaction sequence",
"Typecheck passes",
"cargo test --workspace passes"
],
"priority": 20,
"passes": false,
"notes": "Opened after strict current-directory-only source audit."
},
{
"id": "US-021",
"title": "Run current-directory-only final UI parity re-audit",
"description": "As a maintainer, I want a final parity audit constrained to current-directory files so that we can honestly track what is still off-source without touching parent repos.",
"acceptanceCriteria": [
"Current-directory native surfaces are re-audited against original source files",
"Remaining deviations are documented in current-directory artifacts only",
"cargo clippy --workspace --all-targets --all-features -- -D warnings passes",
"cargo test --workspace passes"
],
"priority": 21,
"passes": false,
"notes": "Opened after all current-directory surface stories close."
}
]
}
+2
View File
@@ -22,3 +22,5 @@ Started: 2026-04-19
- Completed US-016 dashboard topology remediation. Native overview now follows the original dashboard grammar more closely: recovery and budget banners lead, metric cards are actionable, performance is followed by budget utilization, attention rows route into the correct sections, active work exposes an All runs affordance, and recent activity remains a dedicated trailing section.
- Completed US-017 runs shell remediation. Native runs now follow the original RunQueue + RunDetail grammar more closely: the queue is a dedicated left panel with filtering/search/list rows, the right side is a primary run detail column, and runtime events/artifacts/operator actions are preserved as secondary panels instead of dominating the main operational shell.
- Completed US-018 approvals remediation. Native approvals now use a grouped review-list grammar closer to the original PendingReviewList surface instead of parallel summary cards, while the lower pending-approval inspector still preserves the real approve/reject chain.