feat(ui): Quick-Toggles, Config-Preview, Dashboard-Alerts, Domain-Detail-Health
Quick-Toggle-Switches (kein Modal nötig) für: Backends, Backend-Server, DNS-Zonen, DNS-Records, Domains (active), Firewall-Rules, NAT-Rules, Forward-Proxy ACLs, Routing-Rules. Dashboard: Alert-Banner für komplett ausgefallene Backends (HAProxy-Stats) und Domains im Maintenance-Mode. Domain-Detail: HAProxy-Live-Health-Badge (15s Polling), TLS-Cert ausstellen/erneuern direkt aus dem Detail, Routing-Rules-Panel inline. Config-Preview (Settings): alle 4 Generatoren (haproxy, nftables, squid, unbound) rendern via RenderToString ohne Disk-Write — GET /system/config-preview. ActionButtons: Viewer-Rolle blendet Delete aus (RBAC-Ergänzung). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { Button, Popconfirm, Space, Tooltip } from 'antd'
|
||||
import { DeleteOutlined, EditOutlined } from '@ant-design/icons'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useAuthStore } from '../stores/auth'
|
||||
|
||||
// ActionButtons is the standard "Edit / Delete" pair used at the
|
||||
// end of every CRUD table row. Centralising it means we only style
|
||||
@@ -8,6 +9,9 @@ import { useTranslation } from 'react-i18next'
|
||||
//
|
||||
// Either prop may be omitted to suppress that button — useful for
|
||||
// rows that aren't editable (e.g. builtin services).
|
||||
// Viewer-role accounts automatically get delete disabled — mutations
|
||||
// are blocked at the API level too, but hiding the button avoids
|
||||
// confusing "access denied" errors for read-only users.
|
||||
interface ActionButtonsProps {
|
||||
onEdit?: () => void
|
||||
onDelete?: () => void
|
||||
@@ -28,6 +32,14 @@ export default function ActionButtons({
|
||||
editDisabledReason, deleteDisabledReason,
|
||||
}: ActionButtonsProps) {
|
||||
const { t } = useTranslation()
|
||||
const role = useAuthStore((s) => s.user?.role)
|
||||
const isViewer = role === 'viewer'
|
||||
|
||||
const delDisabled = deleteDisabled || isViewer
|
||||
const delDisabledReason = isViewer
|
||||
? t('auth.viewerBadge')
|
||||
: deleteDisabledReason
|
||||
|
||||
return (
|
||||
<Space size={4}>
|
||||
{onEdit && (
|
||||
@@ -42,8 +54,8 @@ export default function ActionButtons({
|
||||
</Tooltip>
|
||||
)}
|
||||
{onDelete && (
|
||||
deleteDisabled ? (
|
||||
<Tooltip title={deleteDisabledReason ?? t('common.delete')}>
|
||||
delDisabled ? (
|
||||
<Tooltip title={delDisabledReason ?? t('common.delete')}>
|
||||
<Button type="text" size="small" danger icon={<DeleteOutlined />} disabled />
|
||||
</Tooltip>
|
||||
) : (
|
||||
|
||||
Reference in New Issue
Block a user