M-029 Pass 1 batch 3: migrate 3 three-mutation pages to useTrackedMutation

Drains 9 more useMutation sites (42 -> 33). HealthMonitorPage hoists the

shared invalidation pair into a healthCheckInvalidates const so the three

mutations don't repeat the array literal.

Pages migrated:

  - HealthMonitorPage.tsx  create + delete + acknowledge all invalidate

                            [['health-checks'], ['health-checks-summary']]

                            (hoisted to a shared const)

  - AgentGroupsPage.tsx    delete + create + update all invalidate [['agent-groups']]

                            (queryClient kept — modal onSuccess props still use it)

  - JobsPage.tsx           cancel + approve + reject all invalidate [['jobs']]

Verification:

  legacy useMutation count   42 -> 33 (-9)

  useTrackedMutation count   14 -> 23 (+9)

Closes 23 of 56 sites toward M-029 Pass 1 completion.
This commit is contained in:
Shankar
2026-04-27 02:43:02 +00:00
parent a5db17456a
commit 64c6cd05eb
3 changed files with 28 additions and 30 deletions
+8 -7
View File
@@ -1,5 +1,6 @@
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { useQuery, useQueryClient } from '@tanstack/react-query';
import { useTrackedMutation } from '../hooks/useTrackedMutation';
import { getAgentGroups, deleteAgentGroup, createAgentGroup, updateAgentGroup } from '../api/client'; import { getAgentGroups, deleteAgentGroup, createAgentGroup, updateAgentGroup } from '../api/client';
import PageHeader from '../components/PageHeader'; import PageHeader from '../components/PageHeader';
import DataTable from '../components/DataTable'; import DataTable from '../components/DataTable';
@@ -259,23 +260,23 @@ export default function AgentGroupsPage() {
queryFn: () => getAgentGroups(), queryFn: () => getAgentGroups(),
}); });
const deleteMutation = useMutation({ const deleteMutation = useTrackedMutation({
mutationFn: deleteAgentGroup, mutationFn: deleteAgentGroup,
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['agent-groups'] }), invalidates: [['agent-groups']],
}); });
const createMutation = useMutation({ const createMutation = useTrackedMutation({
mutationFn: createAgentGroup, mutationFn: createAgentGroup,
invalidates: [['agent-groups']],
onSuccess: () => { onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['agent-groups'] });
setShowCreate(false); setShowCreate(false);
}, },
}); });
const updateMutation = useMutation({ const updateMutation = useTrackedMutation({
mutationFn: ({ id, data }: { id: string; data: Partial<AgentGroup> }) => updateAgentGroup(id, data), mutationFn: ({ id, data }: { id: string; data: Partial<AgentGroup> }) => updateAgentGroup(id, data),
invalidates: [['agent-groups']],
onSuccess: () => { onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['agent-groups'] });
setEditingGroup(null); setEditingGroup(null);
}, },
}); });
+12 -15
View File
@@ -1,5 +1,6 @@
import { useState } from 'react'; import { useState } from 'react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import { useTrackedMutation } from '../hooks/useTrackedMutation';
import { import {
listHealthChecks, listHealthChecks,
createHealthCheck, createHealthCheck,
@@ -139,7 +140,6 @@ function SummaryBar({ summary }: { summary: HealthCheckSummary }) {
export default function HealthMonitorPage() { export default function HealthMonitorPage() {
const [showCreate, setShowCreate] = useState(false); const [showCreate, setShowCreate] = useState(false);
const [statusFilter, setStatusFilter] = useState<string | undefined>(); const [statusFilter, setStatusFilter] = useState<string | undefined>();
const queryClient = useQueryClient();
const { data, isLoading, error, refetch } = useQuery({ const { data, isLoading, error, refetch } = useQuery({
queryKey: ['health-checks', statusFilter], queryKey: ['health-checks', statusFilter],
@@ -153,29 +153,26 @@ export default function HealthMonitorPage() {
refetchInterval: 30000, refetchInterval: 30000,
}); });
const createMutation = useMutation({ // Every health-check mutation invalidates the same two queries: the list
// (rows reflect new state) and the summary (counts reflect new state).
const healthCheckInvalidates = [['health-checks'], ['health-checks-summary']];
const createMutation = useTrackedMutation({
mutationFn: createHealthCheck, mutationFn: createHealthCheck,
invalidates: healthCheckInvalidates,
onSuccess: () => { onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['health-checks'] });
queryClient.invalidateQueries({ queryKey: ['health-checks-summary'] });
setShowCreate(false); setShowCreate(false);
}, },
}); });
const deleteMutation = useMutation({ const deleteMutation = useTrackedMutation({
mutationFn: deleteHealthCheck, mutationFn: deleteHealthCheck,
onSuccess: () => { invalidates: healthCheckInvalidates,
queryClient.invalidateQueries({ queryKey: ['health-checks'] });
queryClient.invalidateQueries({ queryKey: ['health-checks-summary'] });
},
}); });
const acknowledgeMutation = useMutation({ const acknowledgeMutation = useTrackedMutation({
mutationFn: acknowledgeHealthCheck, mutationFn: acknowledgeHealthCheck,
onSuccess: () => { invalidates: healthCheckInvalidates,
queryClient.invalidateQueries({ queryKey: ['health-checks'] });
queryClient.invalidateQueries({ queryKey: ['health-checks-summary'] });
},
}); });
const columns: Column<EndpointHealthCheck>[] = [ const columns: Column<EndpointHealthCheck>[] = [
+8 -8
View File
@@ -1,6 +1,7 @@
import { useState } from 'react'; import { useState } from 'react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import { useTrackedMutation } from '../hooks/useTrackedMutation';
import { getJobs, cancelJob, approveRenewal, rejectRenewal } from '../api/client'; import { getJobs, cancelJob, approveRenewal, rejectRenewal } from '../api/client';
import PageHeader from '../components/PageHeader'; import PageHeader from '../components/PageHeader';
import DataTable from '../components/DataTable'; import DataTable from '../components/DataTable';
@@ -73,7 +74,6 @@ export default function JobsPage() {
const [statusFilter, setStatusFilter] = useState(''); const [statusFilter, setStatusFilter] = useState('');
const [typeFilter, setTypeFilter] = useState(''); const [typeFilter, setTypeFilter] = useState('');
const [rejectingJob, setRejectingJob] = useState<Job | null>(null); const [rejectingJob, setRejectingJob] = useState<Job | null>(null);
const queryClient = useQueryClient();
const params: Record<string, string> = {}; const params: Record<string, string> = {};
if (statusFilter) params.status = statusFilter; if (statusFilter) params.status = statusFilter;
@@ -85,20 +85,20 @@ export default function JobsPage() {
refetchInterval: 10000, refetchInterval: 10000,
}); });
const cancelMutation = useMutation({ const cancelMutation = useTrackedMutation({
mutationFn: cancelJob, mutationFn: cancelJob,
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['jobs'] }), invalidates: [['jobs']],
}); });
const approveMutation = useMutation({ const approveMutation = useTrackedMutation({
mutationFn: approveRenewal, mutationFn: approveRenewal,
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['jobs'] }), invalidates: [['jobs']],
}); });
const rejectMutation = useMutation({ const rejectMutation = useTrackedMutation({
mutationFn: ({ id, reason }: { id: string; reason: string }) => rejectRenewal(id, reason), mutationFn: ({ id, reason }: { id: string; reason: string }) => rejectRenewal(id, reason),
invalidates: [['jobs']],
onSuccess: () => { onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['jobs'] });
setRejectingJob(null); setRejectingJob(null);
}, },
}); });