Openstatus www.openstatus.dev
at main 257 lines 7.9 kB view raw
1"use client"; 2 3import { FormCardGroup } from "@/components/forms/form-card"; 4import { useTRPC } from "@/lib/trpc/client"; 5import { deserialize } from "@openstatus/assertions"; 6import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; 7import { useParams, useRouter } from "next/navigation"; 8import { FormDangerZone } from "./form-danger-zone"; 9import { 10 FOLLOW_REDIRECTS_DEFAULT, 11 FormFollowRedirect, 12} from "./form-follow-redirect"; 13import { FormGeneral } from "./form-general"; 14import { FormNotifiers } from "./form-notifiers"; 15import { FormOtel } from "./form-otel"; 16import { FormResponseTime } from "./form-response-time"; 17import { FormRetry, RETRY_DEFAULT } from "./form-retry"; 18import { FormSchedulingRegions } from "./form-scheduling-regions"; 19import { FormTags } from "./form-tags"; 20import { FormVisibility } from "./form-visibility"; 21 22export function FormMonitorUpdate() { 23 const { id } = useParams<{ id: string }>(); 24 const trpc = useTRPC(); 25 const router = useRouter(); 26 const queryClient = useQueryClient(); 27 const { data: monitor, refetch } = useQuery( 28 trpc.monitor.get.queryOptions({ id: Number.parseInt(id) }), 29 ); 30 const { data: statusPages } = useQuery(trpc.page.list.queryOptions()); 31 const { data: privateLocations } = useQuery( 32 trpc.privateLocation.list.queryOptions(), 33 ); 34 const { data: notifications } = useQuery( 35 trpc.notification.list.queryOptions(), 36 ); 37 const { data: workspace } = useQuery(trpc.workspace.get.queryOptions()); 38 const updateRetryMutation = useMutation( 39 trpc.monitor.updateRetry.mutationOptions({ 40 onSuccess: () => refetch(), 41 }), 42 ); 43 const updateOtelMutation = useMutation( 44 trpc.monitor.updateOtel.mutationOptions({ 45 onSuccess: () => refetch(), 46 }), 47 ); 48 const updatePublicMutation = useMutation( 49 trpc.monitor.updatePublic.mutationOptions({ 50 onSuccess: () => refetch(), 51 }), 52 ); 53 const updateSchedulingRegionsMutation = useMutation( 54 trpc.monitor.updateSchedulingRegions.mutationOptions({ 55 onSuccess: () => refetch(), 56 }), 57 ); 58 const updateResponseTimeMutation = useMutation( 59 trpc.monitor.updateResponseTime.mutationOptions({ 60 onSuccess: () => refetch(), 61 }), 62 ); 63 const updateTagsMutation = useMutation( 64 trpc.monitor.updateTags.mutationOptions({ 65 onSuccess: () => refetch(), 66 }), 67 ); 68 const updateFollowRedirectsMutation = useMutation( 69 trpc.monitor.updateFollowRedirects.mutationOptions({ 70 onSuccess: () => refetch(), 71 }), 72 ); 73 74 const updateGeneralMutation = useMutation( 75 trpc.monitor.updateGeneral.mutationOptions({ 76 onSuccess: () => { 77 // NOTE: invalidate the list query to update the monitor in the list (especially the name) 78 queryClient.invalidateQueries({ 79 queryKey: trpc.monitor.list.queryKey(), 80 }); 81 refetch(); 82 }, 83 onError: (err) => { 84 // TODO: open dialog 85 console.error(err); 86 }, 87 }), 88 ); 89 90 const updateNotifiersMutation = useMutation( 91 trpc.monitor.updateNotifiers.mutationOptions({ 92 onSuccess: () => refetch(), 93 }), 94 ); 95 96 const deleteMonitorMutation = useMutation( 97 trpc.monitor.delete.mutationOptions({ 98 onSuccess: () => { 99 queryClient.invalidateQueries({ 100 queryKey: trpc.monitor.list.queryKey(), 101 }); 102 router.push("/monitors"); 103 }, 104 }), 105 ); 106 107 if ( 108 !monitor || 109 !statusPages || 110 !notifications || 111 !workspace || 112 !privateLocations 113 ) 114 return null; 115 116 return ( 117 <FormCardGroup> 118 <FormGeneral 119 defaultValues={{ 120 type: monitor.jobType as "http" | "tcp", 121 url: monitor.url, 122 name: monitor.name, 123 method: monitor.method as "GET" | "POST" | "PUT" | "PATCH" | "DELETE", 124 headers: monitor.headers ?? [], 125 body: monitor.body, 126 active: monitor.active ?? true, 127 // TODO: move to server after migration 128 assertions: monitor?.assertions 129 ? deserialize(monitor?.assertions).map((a) => a.schema) 130 : [], 131 skipCheck: false, 132 saveCheck: false, 133 }} 134 onSubmit={async (values) => { 135 await updateGeneralMutation.mutateAsync({ 136 id: Number.parseInt(id), 137 name: values.name, 138 jobType: values.type, 139 url: values.url, 140 method: values.method, 141 headers: values.headers, 142 body: values.body, 143 assertions: values.assertions, 144 skipCheck: values.skipCheck, 145 saveCheck: values.saveCheck, 146 active: values.active, 147 }); 148 }} 149 /> 150 <FormResponseTime 151 defaultValues={{ 152 timeout: monitor.timeout, 153 degradedAfter: monitor.degradedAfter ?? undefined, 154 }} 155 onSubmit={async (values) => { 156 await updateResponseTimeMutation.mutateAsync({ 157 id: Number.parseInt(id), 158 timeout: values.timeout, 159 degradedAfter: values.degradedAfter ?? undefined, 160 }); 161 }} 162 /> 163 <FormTags 164 defaultValues={{ 165 tags: monitor.tags, 166 }} 167 onSubmit={async (values) => { 168 await updateTagsMutation.mutateAsync({ 169 id: Number.parseInt(id), 170 tags: values.tags.map((tag) => tag.id), 171 }); 172 }} 173 /> 174 <FormSchedulingRegions 175 privateLocations={privateLocations} 176 defaultValues={{ 177 regions: monitor.regions, 178 periodicity: monitor.periodicity, 179 privateLocations: monitor.privateLocations.map(({ id }) => id), 180 }} 181 onSubmit={async (values) => { 182 await updateSchedulingRegionsMutation.mutateAsync({ 183 id: Number.parseInt(id), 184 regions: values.regions, 185 periodicity: values.periodicity, 186 privateLocations: values.privateLocations, 187 }); 188 }} 189 /> 190 <FormNotifiers 191 notifiers={notifications} 192 defaultValues={{ 193 notifiers: monitor.notifications.map(({ id }) => id), 194 }} 195 onSubmit={async (values) => { 196 await updateNotifiersMutation.mutateAsync({ 197 id: Number.parseInt(id), 198 notifiers: values.notifiers, 199 }); 200 }} 201 /> 202 <FormRetry 203 defaultValues={{ 204 retry: monitor.retry ?? RETRY_DEFAULT, 205 }} 206 onSubmit={async (values) => 207 await updateRetryMutation.mutateAsync({ 208 id: Number.parseInt(id), 209 retry: values.retry ?? RETRY_DEFAULT, 210 }) 211 } 212 /> 213 <FormFollowRedirect 214 defaultValues={{ 215 followRedirects: monitor.followRedirects ?? FOLLOW_REDIRECTS_DEFAULT, 216 }} 217 onSubmit={async (values) => 218 await updateFollowRedirectsMutation.mutateAsync({ 219 id: Number.parseInt(id), 220 followRedirects: values.followRedirects ?? FOLLOW_REDIRECTS_DEFAULT, 221 }) 222 } 223 /> 224 <FormOtel 225 locked={workspace.limits.otel === false} 226 defaultValues={{ 227 endpoint: monitor.otelEndpoint ?? "", 228 headers: monitor.otelHeaders ?? [], 229 }} 230 onSubmit={async (values) => { 231 await updateOtelMutation.mutateAsync({ 232 id: Number.parseInt(id), 233 otelEndpoint: values.endpoint, 234 otelHeaders: values.headers, 235 }); 236 }} 237 /> 238 <FormVisibility 239 defaultValues={{ 240 visibility: monitor.public ?? false, 241 }} 242 onSubmit={async (values) => { 243 await updatePublicMutation.mutateAsync({ 244 id: Number.parseInt(id), 245 public: values.visibility, 246 }); 247 }} 248 /> 249 <FormDangerZone 250 title={monitor.name} 251 onSubmit={async () => { 252 await deleteMonitorMutation.mutateAsync({ id: Number.parseInt(id) }); 253 }} 254 /> 255 </FormCardGroup> 256 ); 257}