feat(ui): add auth pages, company rail, inbox redesign, and page improvements

Add Auth sign-in/sign-up page and InviteLanding page for invite acceptance.
Add CloudAccessGate that checks deployment mode and redirects to /auth when
session is required. Add CompanyRail with drag-and-drop company switching.
Add MarkdownBody prose renderer. Redesign Inbox with category filters and
inline join-request approval. Refactor AgentDetail to overview/configure/runs
views with claude-login support. Replace navigate() anti-patterns with <Link>
components in Dashboard and MetricCard. Add live-run indicators in sidebar
agents. Fix LiveUpdatesProvider cache key resolution for issue identifiers.
Add auth, health, and access API clients.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Forgotten
2026-02-23 14:41:21 -06:00
parent 5b983ca4d3
commit 2ec45c49af
48 changed files with 2794 additions and 1067 deletions

View File

@@ -1,9 +1,9 @@
import { useMemo, useRef, useState } from "react";
import { Link } from "react-router-dom";
import Markdown from "react-markdown";
import type { IssueComment, Agent } from "@paperclip/shared";
import { Button } from "@/components/ui/button";
import { Identity } from "./Identity";
import { MarkdownBody } from "./MarkdownBody";
import { MarkdownEditor, type MarkdownEditorRef, type MentionOption } from "./MarkdownEditor";
import { formatDateTime } from "../lib/utils";
@@ -17,11 +17,12 @@ interface CommentThreadProps {
onAdd: (body: string, reopen?: boolean) => Promise<void>;
issueStatus?: string;
agentMap?: Map<string, Agent>;
imageUploadHandler?: (file: File) => Promise<string>;
}
const CLOSED_STATUSES = new Set(["done", "cancelled"]);
export function CommentThread({ comments, onAdd, issueStatus, agentMap }: CommentThreadProps) {
export function CommentThread({ comments, onAdd, issueStatus, agentMap, imageUploadHandler }: CommentThreadProps) {
const [body, setBody] = useState("");
const [reopen, setReopen] = useState(true);
const [submitting, setSubmitting] = useState(false);
@@ -35,13 +36,15 @@ export function CommentThread({ comments, onAdd, issueStatus, agentMap }: Commen
[comments],
);
// Build mention options from agent map
// Build mention options from agent map (exclude terminated agents)
const mentions = useMemo<MentionOption[]>(() => {
if (!agentMap) return [];
return Array.from(agentMap.values()).map((a) => ({
id: a.id,
name: a.name,
}));
return Array.from(agentMap.values())
.filter((a) => a.status !== "terminated")
.map((a) => ({
id: a.id,
name: a.name,
}));
}, [agentMap]);
async function handleSubmit() {
@@ -84,9 +87,7 @@ export function CommentThread({ comments, onAdd, issueStatus, agentMap }: Commen
{formatDateTime(comment.createdAt)}
</span>
</div>
<div className="text-sm prose prose-sm prose-invert max-w-none prose-p:my-1 prose-ul:my-1 prose-ol:my-1 prose-li:my-0 prose-pre:my-2 prose-headings:my-2 prose-headings:text-sm">
<Markdown>{comment.body}</Markdown>
</div>
<MarkdownBody className="text-sm">{comment.body}</MarkdownBody>
{comment.runId && comment.runAgentId && (
<div className="mt-2 pt-2 border-t border-border/60">
<Link
@@ -109,6 +110,7 @@ export function CommentThread({ comments, onAdd, issueStatus, agentMap }: Commen
placeholder="Leave a comment..."
mentions={mentions}
onSubmit={handleSubmit}
imageUploadHandler={imageUploadHandler}
contentClassName="min-h-[60px] text-sm"
/>
<div className="flex items-center justify-end gap-3">