mirror of
https://github.com/tiennm99/ccs.git
synced 2026-09-02 16:19:27 +00:00
fix(accounts-ui): move action center content into left column
This commit is contained in:
+162
-228
@@ -5,15 +5,7 @@
|
|||||||
|
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import {
|
import { AlertTriangle, ArrowRight, ChevronDown, Plus, Users, Zap } from 'lucide-react';
|
||||||
AlertTriangle,
|
|
||||||
ArrowRight,
|
|
||||||
ChevronDown,
|
|
||||||
ChevronLeft,
|
|
||||||
Plus,
|
|
||||||
Users,
|
|
||||||
Zap,
|
|
||||||
} from 'lucide-react';
|
|
||||||
import { AccountsTable } from '@/components/account/accounts-table';
|
import { AccountsTable } from '@/components/account/accounts-table';
|
||||||
import { CreateAuthProfileDialog } from '@/components/account/create-auth-profile-dialog';
|
import { CreateAuthProfileDialog } from '@/components/account/create-auth-profile-dialog';
|
||||||
import { HistorySyncLearningMap } from '@/components/account/history-sync-learning-map';
|
import { HistorySyncLearningMap } from '@/components/account/history-sync-learning-map';
|
||||||
@@ -31,7 +23,6 @@ export function AccountsPage() {
|
|||||||
const { data, isLoading } = useAccounts();
|
const { data, isLoading } = useAccounts();
|
||||||
const confirmLegacyMutation = useConfirmLegacyAccountPolicies();
|
const confirmLegacyMutation = useConfirmLegacyAccountPolicies();
|
||||||
const [createDialogOpen, setCreateDialogOpen] = useState(false);
|
const [createDialogOpen, setCreateDialogOpen] = useState(false);
|
||||||
const [showGuideRail, setShowGuideRail] = useState(true);
|
|
||||||
const [guideOpen, setGuideOpen] = useState(false);
|
const [guideOpen, setGuideOpen] = useState(false);
|
||||||
|
|
||||||
const authAccounts = data?.accounts || [];
|
const authAccounts = data?.accounts || [];
|
||||||
@@ -63,34 +54,69 @@ export function AccountsPage() {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="h-[calc(100vh-100px)] hidden lg:flex">
|
<div className="h-[calc(100vh-100px)] hidden lg:flex">
|
||||||
{/* Left rail */}
|
{/* Left action column */}
|
||||||
<div className="w-80 border-r flex flex-col bg-muted/30 shrink-0">
|
<div className="w-80 border-r flex flex-col bg-muted/20 shrink-0">
|
||||||
<div className="p-4 border-b bg-background space-y-3">
|
<div className="p-4 border-b bg-background space-y-2">
|
||||||
<div>
|
<div className="flex items-center gap-2">
|
||||||
<div className="flex items-center gap-2">
|
<Users className="h-5 w-5 text-primary" />
|
||||||
<Users className="h-5 w-5 text-primary" />
|
<h1 className="font-semibold">Accounts</h1>
|
||||||
<h1 className="font-semibold">Accounts</h1>
|
<Badge variant="outline" className="ml-auto">
|
||||||
</div>
|
Action Center
|
||||||
<p className="mt-1 text-xs text-muted-foreground">
|
</Badge>
|
||||||
Dedicated
|
|
||||||
<code className="mx-1 rounded bg-muted px-1 py-0.5">ccs auth</code>
|
|
||||||
continuity controls.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
<p className="text-xs text-muted-foreground">
|
||||||
<div className="grid grid-cols-1 gap-2">
|
Manage
|
||||||
<Button onClick={() => setCreateDialogOpen(true)} size="sm" className="justify-start">
|
<code className="mx-1 rounded bg-muted px-1 py-0.5">ccs auth</code>
|
||||||
<Plus className="w-4 h-4 mr-2" />
|
accounts and pool onboarding from one panel.
|
||||||
Create Account
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<p className="text-[11px] text-muted-foreground">
|
|
||||||
Pool auth actions live in Action Center to avoid duplicate controls.
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ScrollArea className="flex-1">
|
<ScrollArea className="flex-1">
|
||||||
<div className="p-3 space-y-3">
|
<div className="p-4 space-y-3">
|
||||||
|
<Card>
|
||||||
|
<CardHeader className="pb-2">
|
||||||
|
<CardTitle className="text-sm">Immediate Actions</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="space-y-2">
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
className="w-full justify-start"
|
||||||
|
onClick={() => setCreateDialogOpen(true)}
|
||||||
|
>
|
||||||
|
<Plus className="w-4 h-4 mr-2" />
|
||||||
|
Create Account
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
className="w-full justify-start"
|
||||||
|
onClick={handleOpenClaudePoolAuth}
|
||||||
|
>
|
||||||
|
<Zap className="w-4 h-4 mr-2" />
|
||||||
|
Authenticate Claude in Pool
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
className="w-full justify-start"
|
||||||
|
onClick={handleOpenClaudePool}
|
||||||
|
>
|
||||||
|
Open Claude Pool Settings
|
||||||
|
<ArrowRight className="w-4 h-4 ml-auto" />
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
className="w-full justify-start"
|
||||||
|
onClick={handleConfirmLegacy}
|
||||||
|
disabled={confirmLegacyMutation.isPending || legacyTargetCount === 0}
|
||||||
|
>
|
||||||
|
{confirmLegacyMutation.isPending
|
||||||
|
? 'Confirming Legacy Policies...'
|
||||||
|
: `Confirm Legacy Policies (${legacyTargetCount})`}
|
||||||
|
</Button>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
{hasLegacyFollowUp && (
|
{hasLegacyFollowUp && (
|
||||||
<section className="space-y-2">
|
<section className="space-y-2">
|
||||||
<p className="text-[11px] font-medium uppercase tracking-wide text-muted-foreground">
|
<p className="text-[11px] font-medium uppercase tracking-wide text-muted-foreground">
|
||||||
@@ -116,218 +142,126 @@ export function AccountsPage() {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Button
|
|
||||||
variant="secondary"
|
|
||||||
size="sm"
|
|
||||||
className="w-full justify-start"
|
|
||||||
onClick={handleConfirmLegacy}
|
|
||||||
disabled={confirmLegacyMutation.isPending || legacyTargetCount === 0}
|
|
||||||
>
|
|
||||||
{confirmLegacyMutation.isPending
|
|
||||||
? 'Confirming Legacy Accounts...'
|
|
||||||
: `Confirm Current Policy for ${legacyTargetCount} Legacy Account${legacyTargetCount > 1 ? 's' : ''}`}
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!hasLegacyFollowUp && (
|
{!hasLegacyFollowUp && (
|
||||||
<div className="rounded-md border bg-background px-3 py-2 text-xs text-muted-foreground">
|
<div className="rounded-md border bg-background px-3 py-2 text-xs text-muted-foreground">
|
||||||
No legacy follow-up pending. Manage pool auth from Action Center.
|
No legacy follow-up pending.
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<Collapsible open={guideOpen} onOpenChange={setGuideOpen}>
|
||||||
|
<Card>
|
||||||
|
<CardHeader className="pb-2">
|
||||||
|
<CollapsibleTrigger asChild>
|
||||||
|
<Button variant="ghost" className="h-auto w-full justify-between px-0 py-0">
|
||||||
|
<div className="text-left">
|
||||||
|
<CardTitle className="text-sm">Continuity Guide</CardTitle>
|
||||||
|
<CardDescription className="mt-1">
|
||||||
|
Expand only when needed.
|
||||||
|
</CardDescription>
|
||||||
|
</div>
|
||||||
|
<ChevronDown
|
||||||
|
className={cn('h-4 w-4 transition-transform', guideOpen && 'rotate-180')}
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
</CollapsibleTrigger>
|
||||||
|
</CardHeader>
|
||||||
|
<CollapsibleContent>
|
||||||
|
<CardContent className="space-y-3 text-xs text-muted-foreground">
|
||||||
|
<div className="rounded-md border p-2.5">
|
||||||
|
<p className="font-semibold text-foreground">Shared Standard</p>
|
||||||
|
<p className="mt-1">
|
||||||
|
Project workspace sync only. Best default for most teams.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="rounded-md border p-2.5">
|
||||||
|
<p className="font-semibold text-foreground">Shared Deeper</p>
|
||||||
|
<p className="mt-1">
|
||||||
|
Adds <code>session-env</code>, <code>file-history</code>,{' '}
|
||||||
|
<code>shell-snapshots</code>, <code>todos</code>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="rounded-md border p-2.5">
|
||||||
|
<p className="font-semibold text-foreground">Isolated</p>
|
||||||
|
<p className="mt-1">No link. Best for strict separation.</p>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</CollapsibleContent>
|
||||||
|
</Card>
|
||||||
|
</Collapsible>
|
||||||
|
|
||||||
|
<Card>
|
||||||
|
<CardHeader className="pb-2">
|
||||||
|
<CardTitle className="text-sm">Quick Commands</CardTitle>
|
||||||
|
<CardDescription>Copy and run in terminal.</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="space-y-2">
|
||||||
|
<div className="rounded-md border bg-background px-2 py-2 font-mono text-[11px] flex items-start gap-2">
|
||||||
|
<span className="flex-1 break-all">
|
||||||
|
ccs auth create work --context-group sprint-a --deeper-continuity
|
||||||
|
</span>
|
||||||
|
<CopyButton
|
||||||
|
value="ccs auth create work --context-group sprint-a --deeper-continuity"
|
||||||
|
size="icon"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="rounded-md border bg-background px-2 py-2 font-mono text-[11px] flex items-start gap-2">
|
||||||
|
<span className="flex-1 break-all">ccs cliproxy auth claude</span>
|
||||||
|
<CopyButton value="ccs cliproxy auth claude" size="icon" />
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Main workspace */}
|
{/* Main workspace */}
|
||||||
<div className="flex-1 min-w-0 flex">
|
<div className="flex-1 min-w-0 flex flex-col bg-background">
|
||||||
{/* Table column */}
|
<div className="px-5 py-4 border-b bg-background">
|
||||||
<div className="flex-1 min-w-0 flex flex-col border-r bg-background">
|
<div className="flex items-center gap-2">
|
||||||
<div className="px-5 py-4 border-b bg-background">
|
<Badge variant="outline">ccs auth Workspace</Badge>
|
||||||
<div className="flex items-center gap-2">
|
<Badge variant="secondary">History Sync Controls</Badge>
|
||||||
<Badge variant="outline">ccs auth Workspace</Badge>
|
|
||||||
<Badge variant="secondary">History Sync Controls</Badge>
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
size="sm"
|
|
||||||
className="ml-auto"
|
|
||||||
onClick={() => setShowGuideRail((prev) => !prev)}
|
|
||||||
>
|
|
||||||
{showGuideRail ? 'Hide Action Center' : 'Show Action Center'}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<h2 className="mt-2 text-xl font-semibold tracking-tight">Auth Accounts</h2>
|
|
||||||
<p className="mt-1 text-sm text-muted-foreground">
|
|
||||||
This table is intentionally scoped to
|
|
||||||
<code className="mx-1 rounded bg-muted px-1 py-0.5">ccs auth</code>
|
|
||||||
accounts. Use
|
|
||||||
<code className="mx-1 rounded bg-muted px-1 py-0.5">Sync</code>
|
|
||||||
for mode/group/depth changes.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex-1 min-h-0 p-5 space-y-4 overflow-y-auto">
|
|
||||||
<HistorySyncLearningMap
|
|
||||||
isolatedCount={isolatedCount}
|
|
||||||
sharedStandardCount={sharedStandardCount}
|
|
||||||
deeperSharedCount={deeperSharedCount}
|
|
||||||
sharedGroups={sharedGroups}
|
|
||||||
legacyTargetCount={legacyTargetCount}
|
|
||||||
cliproxyCount={cliproxyCount}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Card className="flex flex-col">
|
|
||||||
<CardHeader className="pb-3">
|
|
||||||
<CardTitle className="text-lg">Account Matrix</CardTitle>
|
|
||||||
<CardDescription>
|
|
||||||
Shared total: {sharedCount}. Actions include Sync settings and legacy
|
|
||||||
confirmation.
|
|
||||||
</CardDescription>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
{isLoading ? (
|
|
||||||
<div className="text-muted-foreground">Loading accounts...</div>
|
|
||||||
) : (
|
|
||||||
<AccountsTable data={authAccounts} defaultAccount={data?.default ?? null} />
|
|
||||||
)}
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</div>
|
</div>
|
||||||
|
<h2 className="mt-2 text-xl font-semibold tracking-tight">Auth Accounts</h2>
|
||||||
|
<p className="mt-1 text-sm text-muted-foreground">
|
||||||
|
This table is intentionally scoped to
|
||||||
|
<code className="mx-1 rounded bg-muted px-1 py-0.5">ccs auth</code>
|
||||||
|
accounts. Use
|
||||||
|
<code className="mx-1 rounded bg-muted px-1 py-0.5">Sync</code>
|
||||||
|
for mode/group/depth changes.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Right action center */}
|
<div className="flex-1 min-h-0 p-5 space-y-4 overflow-y-auto">
|
||||||
{showGuideRail ? (
|
<HistorySyncLearningMap
|
||||||
<div className="w-80 shrink-0 flex flex-col bg-muted/20">
|
isolatedCount={isolatedCount}
|
||||||
<div className="p-4 border-b bg-background flex items-start justify-between gap-3">
|
sharedStandardCount={sharedStandardCount}
|
||||||
<div>
|
deeperSharedCount={deeperSharedCount}
|
||||||
<h3 className="font-semibold">Action Center</h3>
|
sharedGroups={sharedGroups}
|
||||||
<p className="mt-1 text-xs text-muted-foreground">
|
legacyTargetCount={legacyTargetCount}
|
||||||
High-value actions for pool auth and legacy cleanup.
|
cliproxyCount={cliproxyCount}
|
||||||
</p>
|
/>
|
||||||
</div>
|
|
||||||
<Button variant="ghost" size="icon" onClick={() => setShowGuideRail(false)}>
|
|
||||||
<ChevronLeft className="h-4 w-4" />
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<ScrollArea className="flex-1">
|
<Card className="flex flex-col">
|
||||||
<div className="p-4 space-y-3">
|
<CardHeader className="pb-3">
|
||||||
<Card>
|
<CardTitle className="text-lg">Account Matrix</CardTitle>
|
||||||
<CardHeader className="pb-2">
|
<CardDescription>
|
||||||
<CardTitle className="text-sm">Immediate Actions</CardTitle>
|
Shared total: {sharedCount}. Actions include Sync settings and legacy
|
||||||
</CardHeader>
|
confirmation.
|
||||||
<CardContent className="space-y-2">
|
</CardDescription>
|
||||||
<Button
|
</CardHeader>
|
||||||
size="sm"
|
<CardContent>
|
||||||
className="w-full justify-start"
|
{isLoading ? (
|
||||||
onClick={handleOpenClaudePoolAuth}
|
<div className="text-muted-foreground">Loading accounts...</div>
|
||||||
>
|
) : (
|
||||||
<Zap className="w-4 h-4 mr-2" />
|
<AccountsTable data={authAccounts} defaultAccount={data?.default ?? null} />
|
||||||
Authenticate Claude in Pool
|
)}
|
||||||
</Button>
|
</CardContent>
|
||||||
<Button
|
</Card>
|
||||||
variant="outline"
|
</div>
|
||||||
size="sm"
|
|
||||||
className="w-full justify-start"
|
|
||||||
onClick={handleOpenClaudePool}
|
|
||||||
>
|
|
||||||
Open Claude Pool Settings
|
|
||||||
<ArrowRight className="w-4 h-4 ml-auto" />
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
size="sm"
|
|
||||||
className="w-full justify-start"
|
|
||||||
onClick={handleConfirmLegacy}
|
|
||||||
disabled={confirmLegacyMutation.isPending || legacyTargetCount === 0}
|
|
||||||
>
|
|
||||||
{confirmLegacyMutation.isPending
|
|
||||||
? 'Confirming Legacy Policies...'
|
|
||||||
: `Confirm Legacy Policies (${legacyTargetCount})`}
|
|
||||||
</Button>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
|
|
||||||
<Collapsible open={guideOpen} onOpenChange={setGuideOpen}>
|
|
||||||
<Card>
|
|
||||||
<CardHeader className="pb-2">
|
|
||||||
<CollapsibleTrigger asChild>
|
|
||||||
<Button
|
|
||||||
variant="ghost"
|
|
||||||
className="h-auto w-full justify-between px-0 py-0"
|
|
||||||
>
|
|
||||||
<div className="text-left">
|
|
||||||
<CardTitle className="text-sm">Continuity Guide</CardTitle>
|
|
||||||
<CardDescription className="mt-1">
|
|
||||||
Expand only when needed.
|
|
||||||
</CardDescription>
|
|
||||||
</div>
|
|
||||||
<ChevronDown
|
|
||||||
className={cn(
|
|
||||||
'h-4 w-4 transition-transform',
|
|
||||||
guideOpen && 'rotate-180'
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</Button>
|
|
||||||
</CollapsibleTrigger>
|
|
||||||
</CardHeader>
|
|
||||||
<CollapsibleContent>
|
|
||||||
<CardContent className="space-y-3 text-xs text-muted-foreground">
|
|
||||||
<div className="rounded-md border p-2.5">
|
|
||||||
<p className="font-semibold text-foreground">Shared Standard</p>
|
|
||||||
<p className="mt-1">
|
|
||||||
Project workspace sync only. Best default for most teams.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="rounded-md border p-2.5">
|
|
||||||
<p className="font-semibold text-foreground">Shared Deeper</p>
|
|
||||||
<p className="mt-1">
|
|
||||||
Adds <code>session-env</code>, <code>file-history</code>,{' '}
|
|
||||||
<code>shell-snapshots</code>, <code>todos</code>.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="rounded-md border p-2.5">
|
|
||||||
<p className="font-semibold text-foreground">Isolated</p>
|
|
||||||
<p className="mt-1">No link. Best for strict separation.</p>
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
</CollapsibleContent>
|
|
||||||
</Card>
|
|
||||||
</Collapsible>
|
|
||||||
|
|
||||||
<Card>
|
|
||||||
<CardHeader className="pb-2">
|
|
||||||
<CardTitle className="text-sm">Quick Commands</CardTitle>
|
|
||||||
<CardDescription>Copy and run in terminal.</CardDescription>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent className="space-y-2">
|
|
||||||
<div className="rounded-md border bg-background px-2 py-2 font-mono text-[11px] flex items-start gap-2">
|
|
||||||
<span className="flex-1 break-all">
|
|
||||||
ccs auth create work --context-group sprint-a --deeper-continuity
|
|
||||||
</span>
|
|
||||||
<CopyButton
|
|
||||||
value="ccs auth create work --context-group sprint-a --deeper-continuity"
|
|
||||||
size="icon"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="rounded-md border bg-background px-2 py-2 font-mono text-[11px] flex items-start gap-2">
|
|
||||||
<span className="flex-1 break-all">ccs cliproxy auth claude</span>
|
|
||||||
<CopyButton value="ccs cliproxy auth claude" size="icon" />
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
</ScrollArea>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div className="w-14 shrink-0 border-l bg-muted/20 flex items-start justify-center pt-3">
|
|
||||||
<Button variant="ghost" size="icon" onClick={() => setShowGuideRail(true)}>
|
|
||||||
<ChevronLeft className="h-4 w-4 rotate-180" />
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user