feat(site): add refresh button on health page (#10719)

Adds a button on DeploymentHealth page to immediately re-run the healthcheck.

Co-authored-by: BrunoQuaresma <bruno_nonato_quaresma@hotmail.com>
This commit is contained in:
Cian Johnston
2023-11-17 15:26:25 +00:00
committed by GitHub
co-authored by BrunoQuaresma
parent e6f11a383a
commit befb42b6fd
5 changed files with 66 additions and 15 deletions
+3 -2
View File
@@ -1565,9 +1565,10 @@ export const getInsightsTemplate = async (
return response.data;
};
export const getHealth = async () => {
export const getHealth = async (force: boolean = false) => {
const params = new URLSearchParams({ force: force.toString() });
const response = await axios.get<TypesGen.HealthcheckReport>(
"/api/v2/debug/health",
`/api/v2/debug/health?${params}`,
);
return response.data;
};
+17
View File
@@ -0,0 +1,17 @@
import * as API from "api/api";
import { QueryClient } from "react-query";
export const health = () => ({
queryKey: ["health"],
queryFn: async () => API.getHealth(),
});
export const refreshHealth = (queryClient: QueryClient) => {
return {
mutationFn: async () => {
await queryClient.cancelQueries(["health"]);
const newHealthData = await API.getHealth(true);
queryClient.setQueryData(["health"], newHealthData);
},
};
};
-7
View File
@@ -21,13 +21,6 @@ export const deploymentStats = () => {
};
};
export const health = () => {
return {
queryKey: ["deployment", "health"],
queryFn: API.getHealth,
};
};
export const deploymentSSHConfig = () => {
return {
queryKey: ["deployment", "sshConfig"],
@@ -1,9 +1,10 @@
import { type FC } from "react";
import { useQuery } from "react-query";
import { deploymentStats, health } from "api/queries/deployment";
import { deploymentStats } from "api/queries/deployment";
import { usePermissions } from "hooks/usePermissions";
import { DeploymentBannerView } from "./DeploymentBannerView";
import { useDashboard } from "../DashboardProvider";
import { health } from "api/queries/debug";
export const DeploymentBanner: FC = () => {
const dashboard = useDashboard();
+44 -5
View File
@@ -1,6 +1,6 @@
import { type Interpolation, type Theme } from "@emotion/react";
import Box from "@mui/material/Box";
import { useQuery } from "react-query";
import { useMutation, useQuery, useQueryClient } from "react-query";
import { getHealth } from "api/api";
import { Loader } from "components/Loader/Loader";
import { useTab } from "hooks";
@@ -19,6 +19,10 @@ import {
import { Stats, StatsItem } from "components/Stats/Stats";
import { createDayString } from "utils/createDayString";
import { DashboardFullPage } from "components/Dashboard/DashboardLayout";
import { LoadingButton } from "@mui/lab";
import ReplayIcon from "@mui/icons-material/Replay";
import { FC } from "react";
import { health, refreshHealth } from "api/queries/debug";
const sections = {
derp: "DERP",
@@ -29,11 +33,14 @@ const sections = {
export default function HealthPage() {
const tab = useTab("tab", "derp");
const queryClient = useQueryClient();
const { data: healthStatus } = useQuery({
queryKey: ["health"],
queryFn: () => getHealth(),
refetchInterval: 120_000,
...health(),
refetchInterval: 30_000,
});
const { mutate: forceRefresh, isLoading: isRefreshing } = useMutation(
refreshHealth(queryClient),
);
return (
<>
@@ -42,7 +49,12 @@ export default function HealthPage() {
</Helmet>
{healthStatus ? (
<HealthPageView healthStatus={healthStatus} tab={tab} />
<HealthPageView
tab={tab}
healthStatus={healthStatus}
forceRefresh={forceRefresh}
isRefreshing={isRefreshing}
/>
) : (
<Loader />
)}
@@ -53,9 +65,13 @@ export default function HealthPage() {
export function HealthPageView({
healthStatus,
tab,
forceRefresh,
isRefreshing,
}: {
healthStatus: Awaited<ReturnType<typeof getHealth>>;
tab: ReturnType<typeof useTab>;
forceRefresh: () => void;
isRefreshing: boolean;
}) {
return (
<DashboardFullPage>
@@ -109,6 +125,7 @@ export function HealthPageView({
value={healthStatus.coder_version}
/>
</Stats>
<RefreshButton loading={isRefreshing} handleAction={forceRefresh} />
</FullWidthPageHeader>
<Box
sx={{
@@ -254,3 +271,25 @@ const styles = {
},
},
} satisfies Record<string, Interpolation<Theme>>;
interface HealthcheckAction {
handleAction: () => void;
loading: boolean;
}
export const RefreshButton: FC<HealthcheckAction> = ({
handleAction,
loading,
}) => {
return (
<LoadingButton
loading={loading}
loadingPosition="start"
data-testid="healthcheck-refresh-button"
startIcon={<ReplayIcon />}
onClick={handleAction}
>
Refresh
</LoadingButton>
);
};