fix: Implement Phase 2 major fixes
Database: - Add missing indexes for api_key_hash, status, metrics queries - New migration: 005_add_missing_indexes.sql Server: - Fix WebSocket Ping/Pong protocol (RFC 6455 compliance) - Use separate channel for Pong responses Agent: - Replace format!() path construction with PathBuf::join() - Replace todo!() macros with proper errors for macOS support Dashboard: - Fix duplicate filter values in Agents page (__unassigned__ sentinel) - Add onError handlers to all mutations in Agents, Clients, Sites pages All changes reviewed and approved. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -101,6 +101,10 @@ export function Agents() {
|
||||
queryClient.invalidateQueries({ queryKey: ["agents"] });
|
||||
setDeleteConfirm(null);
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
console.error("Failed to delete agent:", error);
|
||||
alert(`Failed to delete agent: ${error.message}`);
|
||||
},
|
||||
});
|
||||
|
||||
const moveMutation = useMutation({
|
||||
@@ -111,6 +115,10 @@ export function Agents() {
|
||||
queryClient.invalidateQueries({ queryKey: ["sites"] });
|
||||
setMovingAgent(null);
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
console.error("Failed to move agent:", error);
|
||||
alert(`Failed to move agent: ${error.message}`);
|
||||
},
|
||||
});
|
||||
|
||||
// Get unique clients from agents
|
||||
@@ -124,7 +132,17 @@ export function Agents() {
|
||||
(agent.client_name && agent.client_name.toLowerCase().includes(search.toLowerCase())) ||
|
||||
(agent.site_name && agent.site_name.toLowerCase().includes(search.toLowerCase()));
|
||||
|
||||
const matchesClient = !filterClient || agent.client_name === filterClient;
|
||||
// Handle special __unassigned__ filter value
|
||||
let matchesClient: boolean;
|
||||
if (filterClient === "__unassigned__") {
|
||||
// Show only agents without a site/client assignment
|
||||
matchesClient = !agent.site_id;
|
||||
} else if (filterClient) {
|
||||
matchesClient = agent.client_name === filterClient;
|
||||
} else {
|
||||
matchesClient = true;
|
||||
}
|
||||
|
||||
const matchesSite = !filterSite || agent.site_id === filterSite;
|
||||
|
||||
return matchesSearch && matchesClient && matchesSite;
|
||||
@@ -173,7 +191,7 @@ export function Agents() {
|
||||
className="px-3 py-2 rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--background))] text-sm"
|
||||
>
|
||||
<option value="">All Clients</option>
|
||||
<option value="">-- Unassigned --</option>
|
||||
<option value="__unassigned__">Unassigned Only</option>
|
||||
{clients.map((client) => (
|
||||
<option key={client} value={client || ""}>
|
||||
{client}
|
||||
|
||||
@@ -101,6 +101,10 @@ export function Clients() {
|
||||
queryClient.invalidateQueries({ queryKey: ["clients"] });
|
||||
setShowModal(false);
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
console.error("Failed to create client:", error);
|
||||
alert(`Failed to create client: ${error.message}`);
|
||||
},
|
||||
});
|
||||
|
||||
const updateMutation = useMutation({
|
||||
@@ -111,6 +115,10 @@ export function Clients() {
|
||||
setShowModal(false);
|
||||
setEditingClient(undefined);
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
console.error("Failed to update client:", error);
|
||||
alert(`Failed to update client: ${error.message}`);
|
||||
},
|
||||
});
|
||||
|
||||
const deleteMutation = useMutation({
|
||||
@@ -119,6 +127,10 @@ export function Clients() {
|
||||
queryClient.invalidateQueries({ queryKey: ["clients"] });
|
||||
setDeleteConfirm(null);
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
console.error("Failed to delete client:", error);
|
||||
alert(`Failed to delete client: ${error.message}`);
|
||||
},
|
||||
});
|
||||
|
||||
const handleSave = (data: ClientFormData) => {
|
||||
|
||||
@@ -195,6 +195,10 @@ export function Sites() {
|
||||
const data = response.data as CreateSiteResponse;
|
||||
setNewSiteApiKey({ apiKey: data.api_key, siteCode: data.site.site_code });
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
console.error("Failed to create site:", error);
|
||||
alert(`Failed to create site: ${error.message}`);
|
||||
},
|
||||
});
|
||||
|
||||
const updateMutation = useMutation({
|
||||
@@ -205,6 +209,10 @@ export function Sites() {
|
||||
setShowModal(false);
|
||||
setEditingSite(undefined);
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
console.error("Failed to update site:", error);
|
||||
alert(`Failed to update site: ${error.message}`);
|
||||
},
|
||||
});
|
||||
|
||||
const deleteMutation = useMutation({
|
||||
@@ -214,6 +222,10 @@ export function Sites() {
|
||||
queryClient.invalidateQueries({ queryKey: ["clients"] });
|
||||
setDeleteConfirm(null);
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
console.error("Failed to delete site:", error);
|
||||
alert(`Failed to delete site: ${error.message}`);
|
||||
},
|
||||
});
|
||||
|
||||
const regenerateKeyMutation = useMutation({
|
||||
@@ -226,6 +238,11 @@ export function Sites() {
|
||||
});
|
||||
setRegeneratingKey(null);
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
console.error("Failed to regenerate API key:", error);
|
||||
alert(`Failed to regenerate API key: ${error.message}`);
|
||||
setRegeneratingKey(null);
|
||||
},
|
||||
});
|
||||
|
||||
const handleSave = (data: SiteFormData) => {
|
||||
|
||||
Reference in New Issue
Block a user