70 lines
2.6 KiB
TypeScript
70 lines
2.6 KiB
TypeScript
import React from 'react';
|
|
import { Card, CardContent, Typography, Box, Switch, Table, TableBody, TableCell, TableHead, TableRow, Chip } from '@mui/material';
|
|
import type { ModerationRole } from './api';
|
|
import { updateModerationRole } from './api';
|
|
|
|
interface Props {
|
|
roles: ModerationRole[];
|
|
onChanged: () => void;
|
|
onError: (msg: string) => void;
|
|
}
|
|
|
|
const TOGGLE_FIELDS: Array<keyof ModerationRole> = ['can_resolve', 'can_escalate', 'can_force_gold_brain', 'is_active'];
|
|
|
|
export const RolesCard: React.FC<Props> = ({ roles, onChanged, onError }) => {
|
|
const toggle = async (code: string, field: keyof ModerationRole, value: boolean) => {
|
|
try {
|
|
const res = await updateModerationRole(code, { [field]: value } as Partial<ModerationRole>);
|
|
if (res.success) onChanged();
|
|
else onError(res.error ?? 'Update failed');
|
|
} catch (e) {
|
|
onError((e as Error).message);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Card variant="outlined">
|
|
<CardContent>
|
|
<Typography variant="h6" fontWeight={700}>Roles & Permissions</Typography>
|
|
<Typography variant="caption" color="text.secondary">
|
|
Maps Keycloak realm roles to HIL actions. Toggle changes auto-sync to Redis.
|
|
</Typography>
|
|
|
|
<Table size="small" sx={{ mt: 2 }}>
|
|
<TableHead>
|
|
<TableRow>
|
|
<TableCell>Role</TableCell>
|
|
<TableCell align="center">can_resolve</TableCell>
|
|
<TableCell align="center">can_escalate</TableCell>
|
|
<TableCell align="center">can_force_gold_brain</TableCell>
|
|
<TableCell align="center">active</TableCell>
|
|
</TableRow>
|
|
</TableHead>
|
|
<TableBody>
|
|
{roles.map((role) => (
|
|
<TableRow key={role.role_code} hover>
|
|
<TableCell>
|
|
<Box>
|
|
<Chip label={role.role_code} size="small" color="primary" variant="outlined" />
|
|
<Typography variant="caption" display="block" color="text.secondary" mt={0.5}>
|
|
{role.role_label}
|
|
</Typography>
|
|
</Box>
|
|
</TableCell>
|
|
{TOGGLE_FIELDS.map((field) => (
|
|
<TableCell key={field} align="center">
|
|
<Switch
|
|
checked={!!role[field]}
|
|
onChange={(e) => toggle(role.role_code, field, e.target.checked)}
|
|
size="small"
|
|
/>
|
|
</TableCell>
|
|
))}
|
|
</TableRow>
|
|
))}
|
|
</TableBody>
|
|
</Table>
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
};
|