feat: add loading overlays and animations across various pages

- Implemented new CSS animations for UI elements including bobbing, pulsing, rotating, and spinning effects.
- Integrated loading overlays in CrowdSecConfig, Login, ProxyHosts, Security, and WafConfig pages to enhance user experience during asynchronous operations.
- Added contextual messages for loading states to inform users about ongoing processes.
- Created tests for Login and Security pages to ensure overlays function correctly during login attempts and security operations.
This commit is contained in:
GitHub Actions
2025-12-04 15:10:02 +00:00
parent 33c31a32c6
commit 3e4323155f
29 changed files with 5575 additions and 1344 deletions

View File

@@ -4,6 +4,7 @@ import { Button } from '../components/ui/Button'
import { Input } from '../components/ui/Input'
import { useRuleSets, useUpsertRuleSet, useDeleteRuleSet } from '../hooks/useSecurity'
import type { SecurityRuleSet, UpsertRuleSetPayload } from '../api/security'
import { ConfigReloadOverlay } from '../components/LoadingStates'
/**
* Confirmation dialog for destructive actions
@@ -187,6 +188,24 @@ export default function WafConfig() {
const [editingRuleSet, setEditingRuleSet] = useState<SecurityRuleSet | null>(null)
const [deleteConfirm, setDeleteConfirm] = useState<SecurityRuleSet | null>(null)
// Determine if any security operation is in progress
const isApplyingConfig = upsertMutation.isPending || deleteMutation.isPending
// Determine contextual message based on operation
const getMessage = () => {
if (upsertMutation.isPending) {
return editingRuleSet
? { message: 'Cerberus awakens...', submessage: 'Guardian of the gates stands watch' }
: { message: 'Forging new defenses...', submessage: 'Security rules inscribing' }
}
if (deleteMutation.isPending) {
return { message: 'Lowering a barrier...', submessage: 'Defense layer removed' }
}
return { message: 'Cerberus awakens...', submessage: 'Guardian of the gates stands watch' }
}
const { message, submessage } = getMessage()
const handleCreate = (data: UpsertRuleSetPayload) => {
upsertMutation.mutate(data, {
onSuccess: () => setShowCreateForm(false),
@@ -228,7 +247,15 @@ export default function WafConfig() {
const ruleSetList = ruleSets?.rulesets || []
return (
<div className="space-y-6">
<>
{isApplyingConfig && (
<ConfigReloadOverlay
message={message}
submessage={submessage}
type="cerberus"
/>
)}
<div className="space-y-6">
{/* Header */}
<div className="flex items-center justify-between">
<div>
@@ -430,6 +457,7 @@ export default function WafConfig() {
</table>
</div>
)}
</div>
</div>
</>
)
}