Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/openstatusHQ/openstatus. ๐ซ Status page with uptime monitoring & API monitoring as code ๐ซ openstatus.dev
bun drizzle-orm monitoring monitoring-as-code nextjs observability on-call open-source shadcn-ui status-page statuspage synthetic-monitoring tinybird turso uptime uptime-checker uptime-monitor
Something went wrong. Try again.
8.2 kB ยท 263 lines
TSX
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264"use client";
import { deserialize } from "@openstatus/assertions";import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";import { useParams, useRouter } from "next/navigation";
import { FormCardGroup } from "@/components/forms/form-card";import { useTRPC } from "@/lib/trpc/client";
import { FormDangerZone } from "./form-danger-zone";import { FOLLOW_REDIRECTS_DEFAULT, FormFollowRedirect,} from "./form-follow-redirect";import { FormGeneral } from "./form-general";import { FormNotifiers } from "./form-notifiers";import { FormOtel } from "./form-otel";import { FormResponseTime } from "./form-response-time";import { FormRetry, RETRY_DEFAULT } from "./form-retry";import { FormSchedulingRegions } from "./form-scheduling-regions";import { FormTags } from "./form-tags";import { FormVisibility } from "./form-visibility";
export function FormMonitorUpdate() { const { id } = useParams<{ id: string }>(); const trpc = useTRPC(); const router = useRouter(); const queryClient = useQueryClient(); const { data: monitor, refetch } = useQuery( trpc.monitor.get.queryOptions({ id: Number.parseInt(id) }), ); const { data: statusPages } = useQuery(trpc.page.list.queryOptions()); const { data: privateLocations } = useQuery( trpc.privateLocation.list.queryOptions(), ); const { data: notifications } = useQuery( trpc.notification.list.queryOptions(), ); const { data: workspace } = useQuery(trpc.workspace.get.queryOptions()); const updateRetryMutation = useMutation( trpc.monitor.updateRetry.mutationOptions({ onSuccess: () => refetch(), }), ); const updateOtelMutation = useMutation( trpc.monitor.updateOtel.mutationOptions({ onSuccess: () => refetch(), }), ); const updatePublicMutation = useMutation( trpc.monitor.updatePublic.mutationOptions({ onSuccess: () => refetch(), }), ); const updateSchedulingRegionsMutation = useMutation( trpc.monitor.updateSchedulingRegions.mutationOptions({ onSuccess: () => refetch(), }), ); const updateResponseTimeMutation = useMutation( trpc.monitor.updateResponseTime.mutationOptions({ onSuccess: () => refetch(), }), ); const updateTagsMutation = useMutation( trpc.monitor.updateTags.mutationOptions({ onSuccess: () => refetch(), }), ); const updateFollowRedirectsMutation = useMutation( trpc.monitor.updateFollowRedirects.mutationOptions({ onSuccess: () => refetch(), }), );
const updateGeneralMutation = useMutation( trpc.monitor.updateGeneral.mutationOptions({ onSuccess: () => { // NOTE: invalidate the list query to update the monitor in the list (especially the name) queryClient.invalidateQueries({ queryKey: trpc.monitor.list.queryKey(), }); refetch(); }, onError: (err) => { // TODO: open dialog console.error(err); }, }), );
const updateNotifiersMutation = useMutation( trpc.monitor.updateNotifiers.mutationOptions({ onSuccess: () => refetch(), }), );
const deleteMonitorMutation = useMutation( trpc.monitor.delete.mutationOptions({ onSuccess: () => { queryClient.invalidateQueries({ queryKey: trpc.monitor.list.queryKey(), }); router.push("/monitors"); }, }), );
if ( !monitor || !statusPages || !notifications || !workspace || !privateLocations ) return null;
return ( <FormCardGroup> <FormGeneral defaultValues={{ type: monitor.jobType as "http" | "tcp" | "dns" | "icmp" | "grpc", url: monitor.url, name: monitor.name, method: monitor.method as "GET" | "POST" | "PUT" | "PATCH" | "DELETE", headers: monitor.headers ?? [], body: monitor.body, active: monitor.active ?? true, // TODO: move to server after migration assertions: monitor?.assertions ? deserialize(monitor?.assertions).map((a) => a.schema) : [], grpcService: monitor.grpcService ?? "", grpcTls: monitor.grpcTls ?? "tls", skipCheck: false, saveCheck: false, }} onSubmit={async (values) => { await updateGeneralMutation.mutateAsync({ id: Number.parseInt(id), name: values.name, jobType: values.type, url: values.url, method: values.method, headers: values.headers, body: values.body, assertions: values.assertions, grpcService: values.grpcService, grpcTls: values.grpcTls, skipCheck: values.skipCheck, saveCheck: values.saveCheck, active: values.active, }); }} /> <FormResponseTime defaultValues={{ timeout: monitor.timeout, degradedAfter: monitor.degradedAfter ?? undefined, }} onSubmit={async (values) => { await updateResponseTimeMutation.mutateAsync({ id: Number.parseInt(id), timeout: values.timeout, degradedAfter: values.degradedAfter ?? undefined, }); }} /> <FormTags defaultValues={{ tags: monitor.tags, }} onSubmit={async (values) => { await updateTagsMutation.mutateAsync({ id: Number.parseInt(id), tags: values.tags.map((tag) => tag.id), }); }} /> <FormSchedulingRegions privateLocations={privateLocations} defaultValues={{ regions: monitor.regions, periodicity: monitor.periodicity, privateLocations: monitor.privateLocations.map(({ id }) => id), }} onSubmit={async (values) => { await updateSchedulingRegionsMutation.mutateAsync({ id: Number.parseInt(id), regions: values.regions, periodicity: values.periodicity, privateLocations: values.privateLocations, }); }} /> <FormNotifiers notifiers={notifications} defaultValues={{ notifiers: monitor.notifications.map(({ id }) => id), }} onSubmit={async (values) => { await updateNotifiersMutation.mutateAsync({ id: Number.parseInt(id), notifiers: values.notifiers, }); }} /> <FormRetry defaultValues={{ retry: monitor.retry ?? RETRY_DEFAULT, }} onSubmit={async (values) => await updateRetryMutation.mutateAsync({ id: Number.parseInt(id), retry: values.retry ?? RETRY_DEFAULT, }) } /> <FormFollowRedirect defaultValues={{ followRedirects: monitor.followRedirects ?? FOLLOW_REDIRECTS_DEFAULT, }} onSubmit={async (values) => await updateFollowRedirectsMutation.mutateAsync({ id: Number.parseInt(id), followRedirects: values.followRedirects ?? FOLLOW_REDIRECTS_DEFAULT, }) } /> <FormOtel locked={workspace.limits.otel === false} defaultValues={{ endpoint: monitor.otelEndpoint ?? "", headers: monitor.otelHeaders ?? [], }} onSubmit={async (values) => { await updateOtelMutation.mutateAsync({ id: Number.parseInt(id), otelEndpoint: values.endpoint, otelHeaders: values.headers, }); }} /> <FormVisibility defaultValues={{ visibility: monitor.public ?? false, }} onSubmit={async (values) => { await updatePublicMutation.mutateAsync({ id: Number.parseInt(id), public: values.visibility, }); }} /> <FormDangerZone title={monitor.name} onSubmit={async () => { await deleteMonitorMutation.mutateAsync({ id: Number.parseInt(id) }); }} /> </FormCardGroup> );}