refactor(admin): split rbac page.tsx into colocated components
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
97
admin-compliance/app/sdk/rbac/_components/PoliciesTab.tsx
Normal file
97
admin-compliance/app/sdk/rbac/_components/PoliciesTab.tsx
Normal file
@@ -0,0 +1,97 @@
|
||||
'use client'
|
||||
|
||||
import React from 'react'
|
||||
import type { LLMPolicy } from '../_types'
|
||||
|
||||
interface Props {
|
||||
policies: LLMPolicy[]
|
||||
onCreate: () => void
|
||||
onEdit: (p: LLMPolicy) => void
|
||||
onDelete: (id: string) => void
|
||||
onToggleActive: (p: LLMPolicy) => void
|
||||
}
|
||||
|
||||
export function PoliciesTab({ policies, onCreate, onEdit, onDelete, onToggleActive }: Props) {
|
||||
return (
|
||||
<div>
|
||||
<div className="flex justify-between items-center mb-4">
|
||||
<h2 className="text-lg font-semibold">{policies.length} LLM-Policies</h2>
|
||||
<button
|
||||
onClick={onCreate}
|
||||
className="px-4 py-2 bg-purple-600 text-white rounded-lg text-sm hover:bg-purple-700"
|
||||
>
|
||||
+ Policy erstellen
|
||||
</button>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
||||
{policies.map(policy => (
|
||||
<div key={policy.id} className={`bg-white rounded-xl border p-5 ${
|
||||
policy.is_active ? 'border-gray-200' : 'border-gray-100 opacity-60'
|
||||
}`}>
|
||||
<div className="flex items-start justify-between mb-3">
|
||||
<div>
|
||||
<h3 className="font-semibold text-gray-900">{policy.name}</h3>
|
||||
<p className="text-xs text-gray-500 mt-0.5">{policy.description}</p>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => onToggleActive(policy)}
|
||||
className={`px-2 py-0.5 rounded text-xs font-medium ${
|
||||
policy.is_active ? 'bg-green-50 text-green-700' : 'bg-gray-100 text-gray-500'
|
||||
}`}
|
||||
>
|
||||
{policy.is_active ? 'Aktiv' : 'Inaktiv'}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2 text-sm">
|
||||
{(policy.allowed_models || []).length > 0 && (
|
||||
<div>
|
||||
<span className="text-gray-500">Erlaubte Models: </span>
|
||||
<div className="flex flex-wrap gap-1 mt-1">
|
||||
{policy.allowed_models.map(m => (
|
||||
<span key={m} className="px-1.5 py-0.5 bg-blue-50 text-blue-700 rounded text-xs">{m}</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex justify-between text-gray-600">
|
||||
<span>Rate-Limit</span>
|
||||
<span className="font-mono text-xs">{policy.rate_limit_rpm} req/min, {policy.rate_limit_tpd} tok/tag</span>
|
||||
</div>
|
||||
<div className="flex justify-between text-gray-600">
|
||||
<span>Max Tokens/Request</span>
|
||||
<span className="font-mono text-xs">{policy.max_tokens_per_request}</span>
|
||||
</div>
|
||||
<div className="flex gap-3">
|
||||
{policy.pii_detection_required && (
|
||||
<span className="px-2 py-0.5 bg-amber-50 text-amber-700 rounded text-xs">PII-Erkennung</span>
|
||||
)}
|
||||
{policy.pii_redaction_required && (
|
||||
<span className="px-2 py-0.5 bg-red-50 text-red-700 rounded text-xs">PII-Redaktion</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end gap-2 mt-3 pt-3 border-t border-gray-100">
|
||||
<button
|
||||
onClick={() => onEdit(policy)}
|
||||
className="text-sm text-purple-600 hover:text-purple-700"
|
||||
>
|
||||
Bearbeiten
|
||||
</button>
|
||||
<button
|
||||
onClick={() => onDelete(policy.id)}
|
||||
className="text-sm text-red-600 hover:text-red-700"
|
||||
>
|
||||
Loeschen
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
{policies.length === 0 && (
|
||||
<div className="text-center py-12 text-gray-400">Keine LLM-Policies vorhanden</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user