From b3b9d99519b6427f795329df8582679041714f65 Mon Sep 17 00:00:00 2001 From: dotta Date: Mon, 6 Apr 2026 15:38:02 -0500 Subject: [PATCH] Add optional Parent Issue column to inbox show/hide columns Adds a "parent" column option to the inbox column toggle dropdown. When enabled, sub-issues display the parent's identifier (e.g. PAP-123) with the parent title as a tooltip. Uses the existing issueById lookup map to resolve parent info without additional API calls. Co-Authored-By: Paperclip --- ui/src/lib/inbox.test.ts | 3 ++- ui/src/lib/inbox.ts | 2 +- ui/src/pages/Inbox.test.tsx | 4 ++++ ui/src/pages/Inbox.tsx | 27 ++++++++++++++++++++++++++- 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/ui/src/lib/inbox.test.ts b/ui/src/lib/inbox.test.ts index 784e38cb..8a755dc1 100644 --- a/ui/src/lib/inbox.test.ts +++ b/ui/src/lib/inbox.test.ts @@ -515,13 +515,14 @@ describe("inbox helpers", () => { }); it("hides the workspace column option unless isolated workspaces are enabled", () => { - expect(getAvailableInboxIssueColumns(false)).toEqual(["status", "id", "assignee", "project", "labels", "updated"]); + expect(getAvailableInboxIssueColumns(false)).toEqual(["status", "id", "assignee", "project", "parent", "labels", "updated"]); expect(getAvailableInboxIssueColumns(true)).toEqual([ "status", "id", "assignee", "project", "workspace", + "parent", "labels", "updated", ]); diff --git a/ui/src/lib/inbox.ts b/ui/src/lib/inbox.ts index 9f26e998..4cff8e65 100644 --- a/ui/src/lib/inbox.ts +++ b/ui/src/lib/inbox.ts @@ -9,7 +9,7 @@ export const INBOX_LAST_TAB_KEY = "paperclip:inbox:last-tab"; export const INBOX_ISSUE_COLUMNS_KEY = "paperclip:inbox:issue-columns"; export type InboxTab = "mine" | "recent" | "unread" | "all"; export type InboxApprovalFilter = "all" | "actionable" | "resolved"; -export const inboxIssueColumns = ["status", "id", "assignee", "project", "workspace", "labels", "updated"] as const; +export const inboxIssueColumns = ["status", "id", "assignee", "project", "workspace", "parent", "labels", "updated"] as const; export type InboxIssueColumn = (typeof inboxIssueColumns)[number]; export const DEFAULT_INBOX_ISSUE_COLUMNS: InboxIssueColumn[] = ["status", "id", "updated"]; export type InboxWorkItem = diff --git a/ui/src/pages/Inbox.test.tsx b/ui/src/pages/Inbox.test.tsx index adb161c2..e5f7beef 100644 --- a/ui/src/pages/Inbox.test.tsx +++ b/ui/src/pages/Inbox.test.tsx @@ -205,6 +205,8 @@ describe("InboxIssueTrailingColumns", () => { workspaceName={null} assigneeName={null} currentUserId={null} + parentIdentifier={null} + parentTitle={null} />, ); }); @@ -229,6 +231,8 @@ describe("InboxIssueTrailingColumns", () => { workspaceName={null} assigneeName={null} currentUserId={null} + parentIdentifier={null} + parentTitle={null} />, ); }); diff --git a/ui/src/pages/Inbox.tsx b/ui/src/pages/Inbox.tsx index 052dd7c7..8e0d5808 100644 --- a/ui/src/pages/Inbox.tsx +++ b/ui/src/pages/Inbox.tsx @@ -141,13 +141,14 @@ function readIssueIdFromRun(run: HeartbeatRun): string | null { type NonIssueUnreadState = "visible" | "fading" | "hidden" | null; -const trailingIssueColumns: InboxIssueColumn[] = ["assignee", "project", "workspace", "labels", "updated"]; +const trailingIssueColumns: InboxIssueColumn[] = ["assignee", "project", "workspace", "parent", "labels", "updated"]; const inboxIssueColumnLabels: Record = { status: "Status", id: "ID", assignee: "Assignee", project: "Project", workspace: "Workspace", + parent: "Parent issue", labels: "Tags", updated: "Last updated", }; @@ -157,6 +158,7 @@ const inboxIssueColumnDescriptions: Record = { assignee: "Assigned agent or board user.", project: "Linked project pill with its color.", workspace: "Execution or project workspace used for the issue.", + parent: "Parent issue identifier and title.", labels: "Issue labels and tags.", updated: "Latest visible activity time.", }; @@ -224,6 +226,7 @@ function issueTrailingGridTemplate(columns: InboxIssueColumn[]): string { if (column === "assignee") return "minmax(7.5rem, 9.5rem)"; if (column === "project") return "minmax(6.5rem, 8.5rem)"; if (column === "workspace") return "minmax(9rem, 12rem)"; + if (column === "parent") return "minmax(8rem, 12rem)"; if (column === "labels") return "minmax(8rem, 10rem)"; return "minmax(6rem, 7rem)"; }) @@ -238,6 +241,8 @@ export function InboxIssueTrailingColumns({ workspaceName, assigneeName, currentUserId, + parentIdentifier, + parentTitle, }: { issue: Issue; columns: InboxIssueColumn[]; @@ -246,6 +251,8 @@ export function InboxIssueTrailingColumns({ workspaceName: string | null; assigneeName: string | null; currentUserId: string | null; + parentIdentifier: string | null; + parentTitle: string | null; }) { const activityText = timeAgo(issue.lastActivityAt ?? issue.lastExternalCommentAt ?? issue.updatedAt); const userLabel = formatAssigneeUserLabel(issue.assigneeUserId, currentUserId) ?? "User"; @@ -348,6 +355,22 @@ export function InboxIssueTrailingColumns({ ); } + if (column === "parent") { + if (!issue.parentId) { + return