feat: add LoadingOverlay component with contextual busy messages for async operations across cluster sync, firewall preview/apply, IPAM discovery/export, node agent installer, and policy compilation
Add LoadingOverlay component with spinner, customizable title/message, and backdrop blur styling, implement busy state tracking with setBusyMessage in Clusters/FirewallPreview/Ipam/Nodes/Policies pages, wrap async operations (cluster test/sync, firewall preview/apply, IPAM discover/export CSV, node agent installer
This commit is contained in:
@@ -5,6 +5,7 @@ import { Eye, GitBranch, Pencil, Play, Plus, Trash2 } from "lucide-react";
|
||||
import { api, Policy, Project, ServiceCatalogItem } from "../api/client";
|
||||
import { DataTable } from "../components/DataTable";
|
||||
import { buttonClass, Field, iconButtonClass, inputClass, selectClass } from "../components/FormControls";
|
||||
import { LoadingOverlay } from "../components/LoadingOverlay";
|
||||
import { Modal } from "../components/Modal";
|
||||
import { PageHeader } from "../components/PageHeader";
|
||||
|
||||
@@ -45,6 +46,7 @@ export function Policies() {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [editing, setEditing] = useState<Policy | null>(null);
|
||||
const [form, setForm] = useState(defaultPolicyForm);
|
||||
const [busyMessage, setBusyMessage] = useState("");
|
||||
|
||||
const save = useMutation({
|
||||
mutationFn: () => {
|
||||
@@ -85,14 +87,24 @@ export function Policies() {
|
||||
}
|
||||
|
||||
async function compile(policy: Policy) {
|
||||
const data = await api<Policy>(`/policies/${policy.id}/compile`, { method: "POST" });
|
||||
setPreview(JSON.stringify(data.last_compiled, null, 2));
|
||||
await queryClient.invalidateQueries({ queryKey: ["policies"] });
|
||||
setBusyMessage(`Compiling ${policy.name}...`);
|
||||
try {
|
||||
const data = await api<Policy>(`/policies/${policy.id}/compile`, { method: "POST" });
|
||||
setPreview(JSON.stringify(data.last_compiled, null, 2));
|
||||
await queryClient.invalidateQueries({ queryKey: ["policies"] });
|
||||
} finally {
|
||||
setBusyMessage("");
|
||||
}
|
||||
}
|
||||
|
||||
async function firewallPreview(policy: Policy) {
|
||||
const data = await api<Record<string, unknown>>(`/firewall/preview/${policy.id}`, { method: "POST" });
|
||||
setPreview(JSON.stringify(data, null, 2));
|
||||
setBusyMessage(`Generating preview for ${policy.name}...`);
|
||||
try {
|
||||
const data = await api<Record<string, unknown>>(`/firewall/preview/${policy.id}`, { method: "POST" });
|
||||
setPreview(JSON.stringify(data, null, 2));
|
||||
} finally {
|
||||
setBusyMessage("");
|
||||
}
|
||||
}
|
||||
|
||||
function addPolicy() {
|
||||
@@ -140,6 +152,7 @@ export function Policies() {
|
||||
return (
|
||||
<>
|
||||
<PageHeader title="Policies" subtitle="Create versioned microsegmentation policies and compile firewall previews." />
|
||||
<LoadingOverlay open={Boolean(busyMessage)} message={busyMessage} />
|
||||
<div className="space-y-4">
|
||||
<button className={buttonClass} onClick={addPolicy}><Plus size={16} /> Add Policy</button>
|
||||
<Modal title={editing ? "Edit Policy" : "Add Policy"} open={open} onClose={() => setOpen(false)}>
|
||||
|
||||
Reference in New Issue
Block a user