Skip to content

Commit 79d4179

Browse files
chore(site): migrate a few services to react-query used in the DashboardProvider (#9667)
1 parent 3b088a5 commit 79d4179

29 files changed

+222
-521
lines changed

site/src/api/queries/appearance.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { QueryClient } from "@tanstack/react-query";
2+
import * as API from "api/api";
3+
import { AppearanceConfig } from "api/typesGenerated";
4+
import { getMetadataAsJSON } from "utils/metadata";
5+
6+
export const appearance = () => {
7+
return {
8+
queryKey: ["appearance"],
9+
queryFn: async () =>
10+
getMetadataAsJSON<AppearanceConfig>("appearance") ?? API.getAppearance(),
11+
};
12+
};
13+
14+
export const updateAppearance = (queryClient: QueryClient) => {
15+
return {
16+
mutationFn: API.updateAppearance,
17+
onSuccess: (newConfig: AppearanceConfig) => {
18+
queryClient.setQueryData(["appearance"], newConfig);
19+
},
20+
};
21+
};

site/src/api/queries/buildInfo.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import * as API from "api/api";
2+
import { BuildInfoResponse } from "api/typesGenerated";
3+
import { getMetadataAsJSON } from "utils/metadata";
4+
5+
export const buildInfo = () => {
6+
return {
7+
queryKey: ["buildInfo"],
8+
queryFn: async () =>
9+
getMetadataAsJSON<BuildInfoResponse>("build-info") ?? API.getBuildInfo(),
10+
};
11+
};

site/src/api/queries/entitlements.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { QueryClient } from "@tanstack/react-query";
2+
import * as API from "api/api";
3+
import { Entitlements } from "api/typesGenerated";
4+
import { getMetadataAsJSON } from "utils/metadata";
5+
6+
const ENTITLEMENTS_QUERY_KEY = ["entitlements"];
7+
8+
export const entitlements = () => {
9+
return {
10+
queryKey: ENTITLEMENTS_QUERY_KEY,
11+
queryFn: async () =>
12+
getMetadataAsJSON<Entitlements>("entitlements") ?? API.getEntitlements(),
13+
};
14+
};
15+
16+
export const refreshEntitlements = (queryClient: QueryClient) => {
17+
return {
18+
mutationFn: API.refreshEntitlements,
19+
onSuccess: async () => {
20+
await queryClient.invalidateQueries({
21+
queryKey: ENTITLEMENTS_QUERY_KEY,
22+
});
23+
},
24+
};
25+
};

site/src/api/queries/experiments.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import * as API from "api/api";
2+
import { Experiments } from "api/typesGenerated";
3+
import { getMetadataAsJSON } from "utils/metadata";
4+
5+
export const experiments = () => {
6+
return {
7+
queryKey: ["experiments"],
8+
queryFn: async () =>
9+
getMetadataAsJSON<Experiments>("experiments") ?? API.getExperiments(),
10+
};
11+
};

site/src/components/Dashboard/DashboardProvider.tsx

Lines changed: 29 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,27 @@
1-
import { useMachine } from "@xstate/react";
1+
import { useQuery } from "@tanstack/react-query";
2+
import { buildInfo } from "api/queries/buildInfo";
3+
import { experiments } from "api/queries/experiments";
4+
import { entitlements } from "api/queries/entitlements";
25
import {
36
AppearanceConfig,
47
BuildInfoResponse,
58
Entitlements,
69
Experiments,
710
} from "api/typesGenerated";
811
import { FullScreenLoader } from "components/Loader/FullScreenLoader";
9-
import { createContext, FC, PropsWithChildren, useContext } from "react";
10-
import { appearanceMachine } from "xServices/appearance/appearanceXService";
11-
import { buildInfoMachine } from "xServices/buildInfo/buildInfoXService";
12-
import { entitlementsMachine } from "xServices/entitlements/entitlementsXService";
13-
import { experimentsMachine } from "xServices/experiments/experimentsMachine";
12+
import {
13+
createContext,
14+
FC,
15+
PropsWithChildren,
16+
useContext,
17+
useState,
18+
} from "react";
19+
import { appearance } from "api/queries/appearance";
1420

1521
interface Appearance {
1622
config: AppearanceConfig;
17-
preview: boolean;
23+
isPreview: boolean;
1824
setPreview: (config: AppearanceConfig) => void;
19-
save: (config: AppearanceConfig) => void;
2025
}
2126

2227
interface DashboardProviderValue {
@@ -31,29 +36,16 @@ export const DashboardProviderContext = createContext<
3136
>(undefined);
3237

3338
export const DashboardProvider: FC<PropsWithChildren> = ({ children }) => {
34-
const [buildInfoState] = useMachine(buildInfoMachine);
35-
const [entitlementsState] = useMachine(entitlementsMachine);
36-
const [appearanceState, appearanceSend] = useMachine(appearanceMachine);
37-
const [experimentsState] = useMachine(experimentsMachine);
38-
const { buildInfo } = buildInfoState.context;
39-
const { entitlements } = entitlementsState.context;
40-
const { appearance, preview } = appearanceState.context;
41-
const { experiments } = experimentsState.context;
42-
const isLoading = !buildInfo || !entitlements || !appearance || !experiments;
43-
44-
const setAppearancePreview = (config: AppearanceConfig) => {
45-
appearanceSend({
46-
type: "SET_PREVIEW_APPEARANCE",
47-
appearance: config,
48-
});
49-
};
50-
51-
const saveAppearance = (config: AppearanceConfig) => {
52-
appearanceSend({
53-
type: "SAVE_APPEARANCE",
54-
appearance: config,
55-
});
56-
};
39+
const buildInfoQuery = useQuery(buildInfo());
40+
const entitlementsQuery = useQuery(entitlements());
41+
const experimentsQuery = useQuery(experiments());
42+
const appearanceQuery = useQuery(appearance());
43+
const isLoading =
44+
!buildInfoQuery.data ||
45+
!entitlementsQuery.data ||
46+
!appearanceQuery.data ||
47+
!experimentsQuery.data;
48+
const [configPreview, setConfigPreview] = useState<AppearanceConfig>();
5749

5850
if (isLoading) {
5951
return <FullScreenLoader />;
@@ -62,14 +54,13 @@ export const DashboardProvider: FC<PropsWithChildren> = ({ children }) => {
6254
return (
6355
<DashboardProviderContext.Provider
6456
value={{
65-
buildInfo,
66-
entitlements,
67-
experiments,
57+
buildInfo: buildInfoQuery.data,
58+
entitlements: entitlementsQuery.data,
59+
experiments: experimentsQuery.data,
6860
appearance: {
69-
preview,
70-
config: appearance,
71-
setPreview: setAppearancePreview,
72-
save: saveAppearance,
61+
config: configPreview ?? appearanceQuery.data,
62+
setPreview: setConfigPreview,
63+
isPreview: configPreview !== undefined,
7364
},
7465
}}
7566
>

site/src/components/Dashboard/ServiceBanner/ServiceBanner.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export const ServiceBanner: React.FC = () => {
1515
<ServiceBannerView
1616
message={message}
1717
backgroundColor={background_color}
18-
preview={appearance.preview}
18+
isPreview={appearance.isPreview}
1919
/>
2020
);
2121
} else {

site/src/components/Dashboard/ServiceBanner/ServiceBannerView.stories.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ export const Preview: Story = {
2020
args: {
2121
message: "weeeee",
2222
backgroundColor: "#000000",
23-
preview: true,
23+
isPreview: true,
2424
},
2525
};

site/src/components/Dashboard/ServiceBanner/ServiceBannerView.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ import { hex } from "color-convert";
77
export interface ServiceBannerViewProps {
88
message: string;
99
backgroundColor: string;
10-
preview: boolean;
10+
isPreview: boolean;
1111
}
1212

1313
export const ServiceBannerView: React.FC<ServiceBannerViewProps> = ({
1414
message,
1515
backgroundColor,
16-
preview,
16+
isPreview,
1717
}) => {
1818
const styles = useStyles();
1919
// We don't want anything funky like an image or a heading in the service
@@ -34,7 +34,7 @@ export const ServiceBannerView: React.FC<ServiceBannerViewProps> = ({
3434
className={styles.container}
3535
style={{ backgroundColor: backgroundColor }}
3636
>
37-
{preview && <Pill text="Preview" type="info" lightBorder />}
37+
{isPreview && <Pill text="Preview" type="info" lightBorder />}
3838
<div
3939
className={styles.centerContent}
4040
style={{

site/src/components/RequireAuth/RequireAuth.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { embedRedirect } from "../../utils/redirect";
66
import { FullScreenLoader } from "../Loader/FullScreenLoader";
77
import { DashboardProvider } from "components/Dashboard/DashboardProvider";
88
import { ProxyProvider } from "contexts/ProxyContext";
9+
import { isApiError } from "api/errors";
910

1011
export const RequireAuth: FC = () => {
1112
const [authState, authSend] = useAuth();
@@ -18,11 +19,11 @@ export const RequireAuth: FC = () => {
1819
useEffect(() => {
1920
const interceptorHandle = axios.interceptors.response.use(
2021
(okResponse) => okResponse,
21-
(error) => {
22+
(error: unknown) => {
2223
// 401 Unauthorized
2324
// If we encountered an authentication error, then our token is probably
2425
// invalid and we should update the auth state to reflect that.
25-
if (error.response.status === 401) {
26+
if (isApiError(error) && error.response.status === 401) {
2627
authSend("SIGN_OUT");
2728
}
2829

site/src/components/WorkspaceStatusBadge/WorkspaceStatusBadge.stories.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,16 @@ import {
1212
MockBuildInfo,
1313
MockEntitlementsWithScheduling,
1414
MockExperiments,
15-
MockAppearance,
15+
MockAppearanceConfig,
1616
} from "testHelpers/entities";
1717
import { WorkspaceStatusBadge } from "./WorkspaceStatusBadge";
1818
import { DashboardProviderContext } from "components/Dashboard/DashboardProvider";
1919
import type { Meta, StoryObj } from "@storybook/react";
2020

2121
const MockedAppearance = {
22-
config: MockAppearance,
23-
preview: false,
24-
setPreview: () => null,
25-
save: () => null,
22+
config: MockAppearanceConfig,
23+
isPreview: false,
24+
setPreview: () => {},
2625
};
2726

2827
const meta: Meta<typeof WorkspaceStatusBadge> = {

0 commit comments

Comments
 (0)