diff --git a/src/cli/commands/me/queries.rs b/src/cli/commands/me/queries.rs index 62fd982..9004f2a 100644 --- a/src/cli/commands/me/queries.rs +++ b/src/cli/commands/me/queries.rs @@ -38,10 +38,10 @@ pub fn query_open_issues( ) SELECT i.iid, i.title, p.path_with_namespace, i.status_name, i.updated_at, i.web_url, CASE - WHEN nt.others_ts IS NOT NULL AND (nt.my_ts IS NULL OR nt.others_ts > nt.my_ts) - THEN 'needs_attention' WHEN nt.any_ts IS NOT NULL AND nt.any_ts < (strftime('%s', 'now') * 1000 - {stale_ms}) THEN 'stale' + WHEN nt.others_ts IS NOT NULL AND (nt.my_ts IS NULL OR nt.others_ts > nt.my_ts) + THEN 'needs_attention' WHEN nt.my_ts IS NOT NULL AND nt.my_ts >= COALESCE(nt.others_ts, 0) THEN 'awaiting_response' ELSE 'not_started' @@ -52,17 +52,20 @@ pub fn query_open_issues( LEFT JOIN note_ts nt ON nt.issue_id = i.id WHERE ia.username = ?1 AND i.state = 'opened' + AND (i.status_name COLLATE NOCASE IN ('In Progress', 'In Review') OR i.status_name IS NULL) {project_clause} ORDER BY CASE WHEN nt.others_ts IS NOT NULL AND (nt.my_ts IS NULL OR nt.others_ts > nt.my_ts) + AND (nt.any_ts IS NULL OR nt.any_ts >= (strftime('%s', 'now') * 1000 - {stale_ms})) THEN 0 WHEN nt.any_ts IS NULL AND nt.my_ts IS NULL THEN 1 + WHEN nt.my_ts IS NOT NULL AND nt.my_ts >= COALESCE(nt.others_ts, 0) + AND (nt.any_ts IS NULL OR nt.any_ts >= (strftime('%s', 'now') * 1000 - {stale_ms})) + THEN 2 WHEN nt.any_ts IS NOT NULL AND nt.any_ts < (strftime('%s', 'now') * 1000 - {stale_ms}) THEN 3 - WHEN nt.my_ts IS NOT NULL AND nt.my_ts >= COALESCE(nt.others_ts, 0) - THEN 2 ELSE 1 END, i.updated_at DESC", @@ -119,10 +122,10 @@ pub fn query_authored_mrs( WHEN m.draft = 1 AND NOT EXISTS ( SELECT 1 FROM mr_reviewers WHERE merge_request_id = m.id ) THEN 'not_ready' - WHEN nt.others_ts IS NOT NULL AND (nt.my_ts IS NULL OR nt.others_ts > nt.my_ts) - THEN 'needs_attention' WHEN nt.any_ts IS NOT NULL AND nt.any_ts < (strftime('%s', 'now') * 1000 - {stale_ms}) THEN 'stale' + WHEN nt.others_ts IS NOT NULL AND (nt.my_ts IS NULL OR nt.others_ts > nt.my_ts) + THEN 'needs_attention' WHEN nt.my_ts IS NOT NULL AND nt.my_ts >= COALESCE(nt.others_ts, 0) THEN 'awaiting_response' ELSE 'not_started' @@ -136,10 +139,12 @@ pub fn query_authored_mrs( ORDER BY CASE WHEN m.draft = 1 AND NOT EXISTS (SELECT 1 FROM mr_reviewers WHERE merge_request_id = m.id) THEN 4 - WHEN nt.others_ts IS NOT NULL AND (nt.my_ts IS NULL OR nt.others_ts > nt.my_ts) THEN 0 + WHEN nt.others_ts IS NOT NULL AND (nt.my_ts IS NULL OR nt.others_ts > nt.my_ts) + AND (nt.any_ts IS NULL OR nt.any_ts >= (strftime('%s', 'now') * 1000 - {stale_ms})) THEN 0 WHEN nt.any_ts IS NULL AND nt.my_ts IS NULL THEN 1 + WHEN nt.my_ts IS NOT NULL AND nt.my_ts >= COALESCE(nt.others_ts, 0) + AND (nt.any_ts IS NULL OR nt.any_ts >= (strftime('%s', 'now') * 1000 - {stale_ms})) THEN 2 WHEN nt.any_ts IS NOT NULL AND nt.any_ts < (strftime('%s', 'now') * 1000 - {stale_ms}) THEN 3 - WHEN nt.my_ts IS NOT NULL AND nt.my_ts >= COALESCE(nt.others_ts, 0) THEN 2 ELSE 1 END, m.updated_at DESC", @@ -196,10 +201,10 @@ pub fn query_reviewing_mrs( m.author_username, m.updated_at, m.web_url, CASE -- not_ready is impossible here: JOIN mr_reviewers guarantees a reviewer exists - WHEN nt.others_ts IS NOT NULL AND (nt.my_ts IS NULL OR nt.others_ts > nt.my_ts) - THEN 'needs_attention' WHEN nt.any_ts IS NOT NULL AND nt.any_ts < (strftime('%s', 'now') * 1000 - {stale_ms}) THEN 'stale' + WHEN nt.others_ts IS NOT NULL AND (nt.my_ts IS NULL OR nt.others_ts > nt.my_ts) + THEN 'needs_attention' WHEN nt.my_ts IS NOT NULL AND nt.my_ts >= COALESCE(nt.others_ts, 0) THEN 'awaiting_response' ELSE 'not_started' @@ -213,10 +218,12 @@ pub fn query_reviewing_mrs( {project_clause} ORDER BY CASE - WHEN nt.others_ts IS NOT NULL AND (nt.my_ts IS NULL OR nt.others_ts > nt.my_ts) THEN 0 + WHEN nt.others_ts IS NOT NULL AND (nt.my_ts IS NULL OR nt.others_ts > nt.my_ts) + AND (nt.any_ts IS NULL OR nt.any_ts >= (strftime('%s', 'now') * 1000 - {stale_ms})) THEN 0 WHEN nt.any_ts IS NULL AND nt.my_ts IS NULL THEN 1 + WHEN nt.my_ts IS NOT NULL AND nt.my_ts >= COALESCE(nt.others_ts, 0) + AND (nt.any_ts IS NULL OR nt.any_ts >= (strftime('%s', 'now') * 1000 - {stale_ms})) THEN 2 WHEN nt.any_ts IS NOT NULL AND nt.any_ts < (strftime('%s', 'now') * 1000 - {stale_ms}) THEN 3 - WHEN nt.my_ts IS NOT NULL AND nt.my_ts >= COALESCE(nt.others_ts, 0) THEN 2 ELSE 1 END, m.updated_at DESC", @@ -264,13 +271,19 @@ pub fn query_activity( let project_clause = build_project_clause_at("p.id", project_ids, 3); // Build the "my items" subquery fragments for issue/MR association checks. - // These ensure we only see activity on items CURRENTLY associated with the user (AC-3.6). + // These ensure we only see activity on items CURRENTLY associated with the user + // AND currently open (AC-3.6). Without the state filter, activity would include + // events on closed/merged items that don't appear in the dashboard lists. let my_issue_check = "EXISTS ( - SELECT 1 FROM issue_assignees ia WHERE ia.issue_id = {entity_issue_id} AND ia.username = ?1 + SELECT 1 FROM issue_assignees ia + JOIN issues i2 ON ia.issue_id = i2.id + WHERE ia.issue_id = {entity_issue_id} AND ia.username = ?1 AND i2.state = 'opened' )"; let my_mr_check = "( - EXISTS (SELECT 1 FROM merge_requests mr2 WHERE mr2.id = {entity_mr_id} AND mr2.author_username = ?1) - OR EXISTS (SELECT 1 FROM mr_reviewers rv WHERE rv.merge_request_id = {entity_mr_id} AND rv.username = ?1) + EXISTS (SELECT 1 FROM merge_requests mr2 WHERE mr2.id = {entity_mr_id} AND mr2.author_username = ?1 AND mr2.state = 'opened') + OR EXISTS (SELECT 1 FROM mr_reviewers rv + JOIN merge_requests mr3 ON rv.merge_request_id = mr3.id + WHERE rv.merge_request_id = {entity_mr_id} AND rv.username = ?1 AND mr3.state = 'opened') )"; // Source 1: Human comments on my items @@ -282,7 +295,7 @@ pub fn query_activity( n.author_username, CASE WHEN n.author_username = ?1 THEN 1 ELSE 0 END, SUBSTR(n.body, 1, 200), - SUBSTR(n.body, 1, 200) + NULL FROM notes n JOIN discussions d ON n.discussion_id = d.id JOIN projects p ON d.project_id = p.id @@ -419,7 +432,8 @@ pub fn query_activity( UNION ALL {label_sql} UNION ALL {milestone_sql} UNION ALL {assign_sql} - ORDER BY 1 DESC" + ORDER BY 1 DESC + LIMIT 100" ); let mut params: Vec> = Vec::new();