refactor(ops): decompose ops-client into panels + components (slice 6)
956-line ops-client.tsx → a 230-line orchestrator + ops/panels/{kb,secrets,
area-leads}-panel.tsx (kb+processes share kb-panel via a variant prop) +
ops/components/{kb-modal,secret-modal,area-lead-modal,secret-row,kb-entry-row}.tsx
+ types.ts, following the customize/ exemplar. Behavior preserved (direct writes
kept as-is for now — the secrets one is fixed in the next commit). tsc 0, build ok.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
f86fff62d0
commit
7bc6609ac2
@@ -0,0 +1,72 @@
|
||||
'use client'
|
||||
|
||||
import { Lock } from 'lucide-react'
|
||||
import { Empty, EmptyHeader, EmptyMedia, EmptyTitle, EmptyContent } from '@/components/ui/empty'
|
||||
import { SecretRow } from '../components/secret-row'
|
||||
import type { AclRoleOption, Secret } from '../types'
|
||||
|
||||
// ─── Secrets & Credentials Panel ───────────────────────────────────────────────
|
||||
export function SecretsPanel({
|
||||
canSeeSecrets,
|
||||
secrets,
|
||||
search,
|
||||
onAdd,
|
||||
onDelete,
|
||||
canManageAcl,
|
||||
aclRoleOptions,
|
||||
aclByEntity,
|
||||
}: {
|
||||
canSeeSecrets: boolean
|
||||
secrets: Secret[]
|
||||
search: string
|
||||
onAdd: () => void
|
||||
onDelete: (id: string) => void
|
||||
canManageAcl?: boolean
|
||||
aclRoleOptions?: AclRoleOption[]
|
||||
aclByEntity?: Record<string, string[]>
|
||||
}) {
|
||||
return (
|
||||
<div>
|
||||
{!canSeeSecrets ? (
|
||||
<Empty className="bg-card border border-dashed border-border">
|
||||
<EmptyHeader>
|
||||
<EmptyMedia variant="icon"><Lock /></EmptyMedia>
|
||||
<EmptyTitle>Admin or board access required to view secrets</EmptyTitle>
|
||||
</EmptyHeader>
|
||||
</Empty>
|
||||
) : secrets.length > 0 ? (
|
||||
<div className="bg-card rounded border border-border divide-y divide-border">
|
||||
{secrets.map(s => (
|
||||
<SecretRow
|
||||
key={s.id}
|
||||
secret={s}
|
||||
onDelete={onDelete}
|
||||
canManageAcl={canManageAcl}
|
||||
aclRoleOptions={aclRoleOptions}
|
||||
aclInitial={aclByEntity?.[`secret:${s.id}`] ?? []}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<Empty className="bg-card border border-dashed border-border">
|
||||
<EmptyHeader>
|
||||
<EmptyMedia variant="icon"><Lock /></EmptyMedia>
|
||||
<EmptyTitle>
|
||||
{search ? `No results for "${search}"` : 'No secrets stored yet'}
|
||||
</EmptyTitle>
|
||||
</EmptyHeader>
|
||||
{!search && (
|
||||
<EmptyContent>
|
||||
<button
|
||||
onClick={onAdd}
|
||||
className="font-mono text-xs text-primary hover:underline"
|
||||
>
|
||||
+ Add first secret
|
||||
</button>
|
||||
</EmptyContent>
|
||||
)}
|
||||
</Empty>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user