Align inbox non-issue selection styling
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
parent
facf994694
commit
1871a602df
2 changed files with 108 additions and 3 deletions
93
ui/src/pages/Inbox.test.tsx
Normal file
93
ui/src/pages/Inbox.test.tsx
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
// @vitest-environment jsdom
|
||||||
|
|
||||||
|
import { act } from "react";
|
||||||
|
import type { ComponentProps } from "react";
|
||||||
|
import { createRoot } from "react-dom/client";
|
||||||
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
|
import { FailedRunInboxRow } from "./Inbox";
|
||||||
|
|
||||||
|
vi.mock("@/lib/router", () => ({
|
||||||
|
Link: ({ children, className, ...props }: ComponentProps<"a">) => (
|
||||||
|
<a className={className} {...props}>{children}</a>
|
||||||
|
),
|
||||||
|
useLocation: () => ({ pathname: "/", search: "", hash: "" }),
|
||||||
|
useNavigate: () => () => {},
|
||||||
|
}));
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
(globalThis as any).IS_REACT_ACT_ENVIRONMENT = true;
|
||||||
|
|
||||||
|
describe("FailedRunInboxRow", () => {
|
||||||
|
let container: HTMLDivElement;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
container = document.createElement("div");
|
||||||
|
document.body.appendChild(container);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
container.remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("suppresses accent hover styling when selected", () => {
|
||||||
|
const root = createRoot(container);
|
||||||
|
const run = {
|
||||||
|
id: "run-1",
|
||||||
|
companyId: "company-1",
|
||||||
|
agentId: "agent-1",
|
||||||
|
invocationSource: "assignment",
|
||||||
|
triggerDetail: null,
|
||||||
|
status: "failed",
|
||||||
|
error: "boom",
|
||||||
|
wakeupRequestId: null,
|
||||||
|
exitCode: null,
|
||||||
|
signal: null,
|
||||||
|
usageJson: null,
|
||||||
|
resultJson: null,
|
||||||
|
sessionIdBefore: null,
|
||||||
|
sessionIdAfter: null,
|
||||||
|
logStore: null,
|
||||||
|
logRef: null,
|
||||||
|
logBytes: null,
|
||||||
|
logSha256: null,
|
||||||
|
logCompressed: false,
|
||||||
|
errorCode: null,
|
||||||
|
externalRunId: null,
|
||||||
|
processPid: null,
|
||||||
|
processStartedAt: null,
|
||||||
|
retryOfRunId: null,
|
||||||
|
processLossRetryCount: 0,
|
||||||
|
stdoutExcerpt: null,
|
||||||
|
stderrExcerpt: null,
|
||||||
|
contextSnapshot: null,
|
||||||
|
startedAt: new Date("2026-03-11T00:00:00.000Z"),
|
||||||
|
finishedAt: null,
|
||||||
|
createdAt: new Date("2026-03-11T00:00:00.000Z"),
|
||||||
|
updatedAt: new Date("2026-03-11T00:00:00.000Z"),
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
act(() => {
|
||||||
|
root.render(
|
||||||
|
<FailedRunInboxRow
|
||||||
|
run={run}
|
||||||
|
issueById={new Map()}
|
||||||
|
agentName="Agent"
|
||||||
|
issueLinkState={null}
|
||||||
|
onDismiss={() => {}}
|
||||||
|
onRetry={() => {}}
|
||||||
|
isRetrying={false}
|
||||||
|
selected
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const link = container.querySelector("a");
|
||||||
|
expect(link).not.toBeNull();
|
||||||
|
expect(link?.className).toContain("hover:bg-transparent");
|
||||||
|
expect(link?.className).not.toContain("hover:bg-accent/50");
|
||||||
|
|
||||||
|
act(() => {
|
||||||
|
root.unmount();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -101,7 +101,7 @@ function readIssueIdFromRun(run: HeartbeatRun): string | null {
|
||||||
|
|
||||||
type NonIssueUnreadState = "visible" | "fading" | "hidden" | null;
|
type NonIssueUnreadState = "visible" | "fading" | "hidden" | null;
|
||||||
|
|
||||||
function FailedRunInboxRow({
|
export function FailedRunInboxRow({
|
||||||
run,
|
run,
|
||||||
issueById,
|
issueById,
|
||||||
agentName: linkedAgentName,
|
agentName: linkedAgentName,
|
||||||
|
|
@ -113,6 +113,7 @@ function FailedRunInboxRow({
|
||||||
onMarkRead,
|
onMarkRead,
|
||||||
onArchive,
|
onArchive,
|
||||||
archiveDisabled,
|
archiveDisabled,
|
||||||
|
selected = false,
|
||||||
className,
|
className,
|
||||||
}: {
|
}: {
|
||||||
run: HeartbeatRun;
|
run: HeartbeatRun;
|
||||||
|
|
@ -126,6 +127,7 @@ function FailedRunInboxRow({
|
||||||
onMarkRead?: () => void;
|
onMarkRead?: () => void;
|
||||||
onArchive?: () => void;
|
onArchive?: () => void;
|
||||||
archiveDisabled?: boolean;
|
archiveDisabled?: boolean;
|
||||||
|
selected?: boolean;
|
||||||
className?: string;
|
className?: string;
|
||||||
}) {
|
}) {
|
||||||
const issueId = readIssueIdFromRun(run);
|
const issueId = readIssueIdFromRun(run);
|
||||||
|
|
@ -171,7 +173,10 @@ function FailedRunInboxRow({
|
||||||
) : null}
|
) : null}
|
||||||
<Link
|
<Link
|
||||||
to={`/agents/${run.agentId}/runs/${run.id}`}
|
to={`/agents/${run.agentId}/runs/${run.id}`}
|
||||||
className="flex min-w-0 flex-1 items-start gap-2 no-underline text-inherit transition-colors hover:bg-accent/50"
|
className={cn(
|
||||||
|
"flex min-w-0 flex-1 items-start gap-2 no-underline text-inherit transition-colors",
|
||||||
|
selected ? "hover:bg-transparent" : "hover:bg-accent/50",
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{!showUnreadSlot && <span className="hidden h-2 w-2 shrink-0 sm:inline-flex" aria-hidden="true" />}
|
{!showUnreadSlot && <span className="hidden h-2 w-2 shrink-0 sm:inline-flex" aria-hidden="true" />}
|
||||||
<span className="hidden h-3.5 w-3.5 shrink-0 sm:inline-flex" aria-hidden="true" />
|
<span className="hidden h-3.5 w-3.5 shrink-0 sm:inline-flex" aria-hidden="true" />
|
||||||
|
|
@ -260,6 +265,7 @@ function ApprovalInboxRow({
|
||||||
onMarkRead,
|
onMarkRead,
|
||||||
onArchive,
|
onArchive,
|
||||||
archiveDisabled,
|
archiveDisabled,
|
||||||
|
selected = false,
|
||||||
className,
|
className,
|
||||||
}: {
|
}: {
|
||||||
approval: Approval;
|
approval: Approval;
|
||||||
|
|
@ -271,6 +277,7 @@ function ApprovalInboxRow({
|
||||||
onMarkRead?: () => void;
|
onMarkRead?: () => void;
|
||||||
onArchive?: () => void;
|
onArchive?: () => void;
|
||||||
archiveDisabled?: boolean;
|
archiveDisabled?: boolean;
|
||||||
|
selected?: boolean;
|
||||||
className?: string;
|
className?: string;
|
||||||
}) {
|
}) {
|
||||||
const Icon = typeIcon[approval.type] ?? defaultTypeIcon;
|
const Icon = typeIcon[approval.type] ?? defaultTypeIcon;
|
||||||
|
|
@ -318,7 +325,10 @@ function ApprovalInboxRow({
|
||||||
) : null}
|
) : null}
|
||||||
<Link
|
<Link
|
||||||
to={`/approvals/${approval.id}`}
|
to={`/approvals/${approval.id}`}
|
||||||
className="flex min-w-0 flex-1 items-start gap-2 no-underline text-inherit transition-colors hover:bg-accent/50"
|
className={cn(
|
||||||
|
"flex min-w-0 flex-1 items-start gap-2 no-underline text-inherit transition-colors",
|
||||||
|
selected ? "hover:bg-transparent" : "hover:bg-accent/50",
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{!showUnreadSlot && <span className="hidden h-2 w-2 shrink-0 sm:inline-flex" aria-hidden="true" />}
|
{!showUnreadSlot && <span className="hidden h-2 w-2 shrink-0 sm:inline-flex" aria-hidden="true" />}
|
||||||
<span className="hidden h-3.5 w-3.5 shrink-0 sm:inline-flex" aria-hidden="true" />
|
<span className="hidden h-3.5 w-3.5 shrink-0 sm:inline-flex" aria-hidden="true" />
|
||||||
|
|
@ -1267,6 +1277,7 @@ export function Inbox() {
|
||||||
<ApprovalInboxRow
|
<ApprovalInboxRow
|
||||||
key={approvalKey}
|
key={approvalKey}
|
||||||
approval={item.approval}
|
approval={item.approval}
|
||||||
|
selected={isSelected}
|
||||||
requesterName={agentName(item.approval.requestedByAgentId)}
|
requesterName={agentName(item.approval.requestedByAgentId)}
|
||||||
onApprove={() => approveMutation.mutate(item.approval.id)}
|
onApprove={() => approveMutation.mutate(item.approval.id)}
|
||||||
onReject={() => rejectMutation.mutate(item.approval.id)}
|
onReject={() => rejectMutation.mutate(item.approval.id)}
|
||||||
|
|
@ -1302,6 +1313,7 @@ export function Inbox() {
|
||||||
<FailedRunInboxRow
|
<FailedRunInboxRow
|
||||||
key={runKey}
|
key={runKey}
|
||||||
run={item.run}
|
run={item.run}
|
||||||
|
selected={isSelected}
|
||||||
issueById={issueById}
|
issueById={issueById}
|
||||||
agentName={agentName(item.run.agentId)}
|
agentName={agentName(item.run.agentId)}
|
||||||
issueLinkState={issueLinkState}
|
issueLinkState={issueLinkState}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue