-
Notifications
You must be signed in to change notification settings - Fork 894
feat(site): dismiss health section warnings #11059
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
12302ad
da70544
ca11cd2
3ac588d
711ebee
dd722f6
bf1f95a
a731a31
c22b453
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,40 @@ | ||
import * as API from "api/api"; | ||
import { QueryClient } from "react-query"; | ||
import { HealthSettings } from "api/typesGenerated"; | ||
import { QueryClient, UseMutationOptions } from "react-query"; | ||
|
||
export const HEALTH_QUERY_KEY = ["health"]; | ||
export const HEALTH_QUERY_SETTINGS_KEY = ["health", "settings"]; | ||
|
||
export const health = () => ({ | ||
queryKey: ["health"], | ||
queryKey: HEALTH_QUERY_KEY, | ||
queryFn: async () => API.getHealth(), | ||
}); | ||
|
||
export const refreshHealth = (queryClient: QueryClient) => { | ||
return { | ||
mutationFn: async () => { | ||
await queryClient.cancelQueries(["health"]); | ||
await queryClient.cancelQueries(HEALTH_QUERY_KEY); | ||
const newHealthData = await API.getHealth(true); | ||
queryClient.setQueryData(["health"], newHealthData); | ||
queryClient.setQueryData(HEALTH_QUERY_KEY, newHealthData); | ||
}, | ||
}; | ||
}; | ||
|
||
export const healthSettings = () => { | ||
return { | ||
queryKey: HEALTH_QUERY_SETTINGS_KEY, | ||
queryFn: API.getHealthSettings, | ||
}; | ||
}; | ||
|
||
export const updateHealthSettings = ( | ||
queryClient: QueryClient, | ||
): UseMutationOptions<void, unknown, HealthSettings, unknown> => { | ||
return { | ||
mutationFn: API.updateHealthSettings, | ||
onSuccess: async (_, newSettings) => { | ||
await queryClient.invalidateQueries(HEALTH_QUERY_KEY); | ||
queryClient.setQueryData(HEALTH_QUERY_SETTINGS_KEY, newSettings); | ||
}, | ||
}; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import NotificationOutlined from "@mui/icons-material/NotificationsOutlined"; | ||
import NotificationsOffOutlined from "@mui/icons-material/NotificationsOffOutlined"; | ||
import { healthSettings, updateHealthSettings } from "api/queries/debug"; | ||
import { useMutation, useQuery, useQueryClient } from "react-query"; | ||
import { displaySuccess } from "components/GlobalSnackbar/utils"; | ||
import LoadingButton from "@mui/lab/LoadingButton"; | ||
import Skeleton from "@mui/material/Skeleton"; | ||
import { HealthSection } from "api/typesGenerated"; | ||
|
||
export const DismissWarningButton = (props: { healthcheck: HealthSection }) => { | ||
const queryClient = useQueryClient(); | ||
const healthSettingsQuery = useQuery(healthSettings()); | ||
// They call the same mutation but are used in diff contexts so we don't want | ||
// to merge their states | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What edge cases were you running into by having just one mutation? I trust you, but I'm just curious, since the output looks so similar across each of the if branches There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated the comments to include a use case: They call the same mutation but are used in diff contexts so we don't want
to merge their states. Eg. You dismiss a warning and when it is done it
will show the enable button but since the mutation is still invalidating
other queries it will be in the loading state when it should be idle. |
||
const enableMutation = useMutation(updateHealthSettings(queryClient)); | ||
const dismissMutation = useMutation(updateHealthSettings(queryClient)); | ||
|
||
if (!healthSettingsQuery.data) { | ||
return ( | ||
<Skeleton | ||
variant="rectangular" | ||
height={36} | ||
width={170} | ||
css={{ borderRadius: 8 }} | ||
/> | ||
); | ||
} | ||
|
||
const { dismissed_healthchecks } = healthSettingsQuery.data; | ||
const isDismissed = dismissed_healthchecks.includes(props.healthcheck); | ||
|
||
if (isDismissed) { | ||
return ( | ||
<LoadingButton | ||
disabled={healthSettingsQuery.isLoading} | ||
loading={enableMutation.isLoading} | ||
loadingPosition="start" | ||
startIcon={<NotificationsOffOutlined />} | ||
onClick={async () => { | ||
const updatedSettings = dismissed_healthchecks.filter( | ||
(dismissedHealthcheck) => | ||
dismissedHealthcheck !== props.healthcheck, | ||
); | ||
await enableMutation.mutateAsync({ | ||
dismissed_healthchecks: updatedSettings, | ||
}); | ||
displaySuccess("Warnings enabled successfully!"); | ||
}} | ||
> | ||
Enable warnings | ||
</LoadingButton> | ||
); | ||
} | ||
|
||
return ( | ||
<LoadingButton | ||
disabled={healthSettingsQuery.isLoading} | ||
loading={dismissMutation.isLoading} | ||
loadingPosition="start" | ||
startIcon={<NotificationOutlined />} | ||
onClick={async () => { | ||
const updatedSettings = [...dismissed_healthchecks, props.healthcheck]; | ||
await dismissMutation.mutateAsync({ | ||
dismissed_healthchecks: updatedSettings, | ||
}); | ||
displaySuccess("Warnings dismissed successfully!"); | ||
}} | ||
> | ||
Dismiss warnings | ||
</LoadingButton> | ||
); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { useQueryClient } from "react-query"; | ||
import { | ||
reactRouterParameters, | ||
reactRouterOutlet, | ||
RouteDefinition, | ||
} from "storybook-addon-react-router-v6"; | ||
import { MockHealth, MockHealthSettings } from "testHelpers/entities"; | ||
import { Meta } from "@storybook/react"; | ||
import { HEALTH_QUERY_KEY, HEALTH_QUERY_SETTINGS_KEY } from "api/queries/debug"; | ||
|
||
type MetaOptions = { | ||
element: RouteDefinition; | ||
path: string; | ||
}; | ||
|
||
export const generateMeta = ({ element, path }: MetaOptions): Meta => { | ||
return { | ||
parameters: { | ||
layout: "fullscreen", | ||
reactRouter: reactRouterParameters({ | ||
routing: reactRouterOutlet({ path: `/health/${path}` }, element), | ||
}), | ||
}, | ||
decorators: [ | ||
(Story) => { | ||
const queryClient = useQueryClient(); | ||
queryClient.setQueryData(HEALTH_QUERY_KEY, MockHealth); | ||
queryClient.setQueryData(HEALTH_QUERY_SETTINGS_KEY, MockHealthSettings); | ||
return <Story />; | ||
}, | ||
], | ||
}; | ||
}; |
Uh oh!
There was an error while loading. Please reload this page.