diff --git a/site/src/pages/StarterTemplatePage/StarterTemplatePage.tsx b/site/src/pages/StarterTemplatePage/StarterTemplatePage.tsx index 289f7f0bb359d..3dddb37b1f432 100644 --- a/site/src/pages/StarterTemplatePage/StarterTemplatePage.tsx +++ b/site/src/pages/StarterTemplatePage/StarterTemplatePage.tsx @@ -1,31 +1,30 @@ -import { useMachine } from "@xstate/react"; import { useOrganizationId } from "hooks/useOrganizationId"; import { FC } from "react"; import { Helmet } from "react-helmet-async"; import { useParams } from "react-router-dom"; import { pageTitle } from "utils/page"; -import { starterTemplateMachine } from "xServices/starterTemplates/starterTemplateXService"; import { StarterTemplatePageView } from "./StarterTemplatePageView"; +import { useQuery } from "@tanstack/react-query"; +import { templateExamples } from "api/queries/templates"; const StarterTemplatePage: FC = () => { const { exampleId } = useParams() as { exampleId: string }; const organizationId = useOrganizationId(); - const [state] = useMachine(starterTemplateMachine, { - context: { - organizationId, - exampleId, - }, - }); + const templateExamplesQuery = useQuery(templateExamples(organizationId)); + const starterTemplate = templateExamplesQuery.data?.find( + (example) => example.id === exampleId, + ); return ( <> - - {pageTitle(state.context.starterTemplate?.name ?? exampleId)} - + {pageTitle(starterTemplate?.name ?? exampleId)} - + ); }; diff --git a/site/src/pages/StarterTemplatePage/StarterTemplatePageView.stories.tsx b/site/src/pages/StarterTemplatePage/StarterTemplatePageView.stories.tsx index 4434ab57e6df2..c2d753b3ea793 100644 --- a/site/src/pages/StarterTemplatePage/StarterTemplatePageView.stories.tsx +++ b/site/src/pages/StarterTemplatePage/StarterTemplatePageView.stories.tsx @@ -1,8 +1,4 @@ -import { - mockApiError, - MockOrganization, - MockTemplateExample, -} from "testHelpers/entities"; +import { mockApiError, MockTemplateExample } from "testHelpers/entities"; import { StarterTemplatePageView } from "./StarterTemplatePageView"; import type { Meta, StoryObj } from "@storybook/react"; @@ -17,23 +13,15 @@ type Story = StoryObj; export const Default: Story = { args: { - context: { - exampleId: MockTemplateExample.id, - organizationId: MockOrganization.id, - error: undefined, - starterTemplate: MockTemplateExample, - }, + error: undefined, + starterTemplate: MockTemplateExample, }, }; export const Error: Story = { args: { - context: { - exampleId: MockTemplateExample.id, - organizationId: MockOrganization.id, - error: mockApiError({ - message: `Example ${MockTemplateExample.id} not found.`, - }), - starterTemplate: undefined, - }, + error: mockApiError({ + message: `Example ${MockTemplateExample.id} not found.`, + }), + starterTemplate: undefined, }, }; diff --git a/site/src/pages/StarterTemplatePage/StarterTemplatePageView.tsx b/site/src/pages/StarterTemplatePage/StarterTemplatePageView.tsx index d1abe96270ad5..0264ce0eef4b4 100644 --- a/site/src/pages/StarterTemplatePage/StarterTemplatePageView.tsx +++ b/site/src/pages/StarterTemplatePage/StarterTemplatePageView.tsx @@ -9,27 +9,28 @@ import { PageHeaderTitle, } from "components/PageHeader/PageHeader"; import { FC } from "react"; -import { StarterTemplateContext } from "xServices/starterTemplates/starterTemplateXService"; import ViewCodeIcon from "@mui/icons-material/OpenInNewOutlined"; import PlusIcon from "@mui/icons-material/AddOutlined"; import { Stack } from "components/Stack/Stack"; import { Link } from "react-router-dom"; import { ErrorAlert } from "components/Alert/ErrorAlert"; +import { TemplateExample } from "api/typesGenerated"; export interface StarterTemplatePageViewProps { - context: StarterTemplateContext; + starterTemplate?: TemplateExample; + error?: unknown; } export const StarterTemplatePageView: FC = ({ - context, + starterTemplate, + error, }) => { const styles = useStyles(); - const { starterTemplate } = context; - if (context.error) { + if (error) { return ( - + ); } diff --git a/site/src/pages/StarterTemplatesPage/StarterTemplatesPage.tsx b/site/src/pages/StarterTemplatesPage/StarterTemplatesPage.tsx index 997d2610bbc53..c83e5f73db404 100644 --- a/site/src/pages/StarterTemplatesPage/StarterTemplatesPage.tsx +++ b/site/src/pages/StarterTemplatesPage/StarterTemplatesPage.tsx @@ -1,16 +1,18 @@ -import { useMachine } from "@xstate/react"; import { useOrganizationId } from "hooks/useOrganizationId"; import { FC } from "react"; import { Helmet } from "react-helmet-async"; import { pageTitle } from "utils/page"; -import { starterTemplatesMachine } from "xServices/starterTemplates/starterTemplatesXService"; import { StarterTemplatesPageView } from "./StarterTemplatesPageView"; +import { useQuery } from "@tanstack/react-query"; +import { templateExamples } from "api/queries/templates"; +import { getTemplatesByTag } from "utils/starterTemplates"; const StarterTemplatesPage: FC = () => { const organizationId = useOrganizationId(); - const [state] = useMachine(starterTemplatesMachine, { - context: { organizationId }, - }); + const templateExamplesQuery = useQuery(templateExamples(organizationId)); + const starterTemplatesByTag = templateExamplesQuery.data + ? getTemplatesByTag(templateExamplesQuery.data) + : undefined; return ( <> @@ -18,7 +20,10 @@ const StarterTemplatesPage: FC = () => { {pageTitle("Starter Templates")} - + ); }; diff --git a/site/src/pages/StarterTemplatesPage/StarterTemplatesPageView.stories.tsx b/site/src/pages/StarterTemplatesPage/StarterTemplatesPageView.stories.tsx index e5c67ca2f5bbd..81cea380541d0 100644 --- a/site/src/pages/StarterTemplatesPage/StarterTemplatesPageView.stories.tsx +++ b/site/src/pages/StarterTemplatesPage/StarterTemplatesPageView.stories.tsx @@ -1,6 +1,5 @@ import { mockApiError, - MockOrganization, MockTemplateExample, MockTemplateExample2, } from "testHelpers/entities"; @@ -18,25 +17,19 @@ type Story = StoryObj; export const Default: Story = { args: { - context: { - organizationId: MockOrganization.id, - error: undefined, - starterTemplatesByTag: getTemplatesByTag([ - MockTemplateExample, - MockTemplateExample2, - ]), - }, + error: undefined, + starterTemplatesByTag: getTemplatesByTag([ + MockTemplateExample, + MockTemplateExample2, + ]), }, }; export const Error: Story = { args: { - context: { - organizationId: MockOrganization.id, - error: mockApiError({ - message: "Error on loading the template examples", - }), - starterTemplatesByTag: undefined, - }, + error: mockApiError({ + message: "Error on loading the template examples", + }), + starterTemplatesByTag: undefined, }, }; diff --git a/site/src/pages/StarterTemplatesPage/StarterTemplatesPageView.tsx b/site/src/pages/StarterTemplatesPage/StarterTemplatesPageView.tsx index 82c0a962405c8..0fd768acaa60e 100644 --- a/site/src/pages/StarterTemplatesPage/StarterTemplatesPageView.tsx +++ b/site/src/pages/StarterTemplatesPage/StarterTemplatesPageView.tsx @@ -13,7 +13,7 @@ import { TemplateExampleCard } from "components/TemplateExampleCard/TemplateExam import { FC } from "react"; import { Link, useSearchParams } from "react-router-dom"; import { combineClasses } from "utils/combineClasses"; -import { StarterTemplatesContext } from "xServices/starterTemplates/starterTemplatesXService"; +import { StarterTemplatesByTag } from "utils/starterTemplates"; const getTagLabel = (tag: string) => { const labelByTag: Record = { @@ -26,22 +26,25 @@ const getTagLabel = (tag: string) => { return labelByTag[tag] ?? tag; }; -const selectTags = ({ starterTemplatesByTag }: StarterTemplatesContext) => { +const selectTags = (starterTemplatesByTag: StarterTemplatesByTag) => { return starterTemplatesByTag ? Object.keys(starterTemplatesByTag).sort((a, b) => a.localeCompare(b)) : undefined; }; export interface StarterTemplatesPageViewProps { - context: StarterTemplatesContext; + starterTemplatesByTag?: StarterTemplatesByTag; + error?: unknown; } export const StarterTemplatesPageView: FC = ({ - context, + starterTemplatesByTag, + error, }) => { const [urlParams] = useSearchParams(); const styles = useStyles(); - const { starterTemplatesByTag } = context; - const tags = selectTags(context); + const tags = starterTemplatesByTag + ? selectTags(starterTemplatesByTag) + : undefined; const activeTag = urlParams.get("tag") ?? "all"; const visibleTemplates = starterTemplatesByTag ? starterTemplatesByTag[activeTag] @@ -56,8 +59,8 @@ export const StarterTemplatesPageView: FC = ({ - - + + diff --git a/site/src/xServices/starterTemplates/starterTemplateXService.ts b/site/src/xServices/starterTemplates/starterTemplateXService.ts deleted file mode 100644 index 5104b9729b8b7..0000000000000 --- a/site/src/xServices/starterTemplates/starterTemplateXService.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { getTemplateExamples } from "api/api"; -import { TemplateExample } from "api/typesGenerated"; -import { assign, createMachine } from "xstate"; - -export interface StarterTemplateContext { - organizationId: string; - exampleId: string; - starterTemplate?: TemplateExample; - error?: unknown; -} - -export const starterTemplateMachine = createMachine( - { - id: "starterTemplate", - predictableActionArguments: true, - schema: { - context: {} as StarterTemplateContext, - services: {} as { - loadStarterTemplate: { - data: TemplateExample; - }; - }, - }, - tsTypes: {} as import("./starterTemplateXService.typegen").Typegen0, - initial: "loading", - states: { - loading: { - invoke: { - src: "loadStarterTemplate", - onDone: { - actions: ["assignStarterTemplate"], - target: "idle.ok", - }, - onError: { - actions: ["assignError"], - target: "idle.error", - }, - }, - }, - idle: { - initial: "ok", - states: { - ok: { type: "final" }, - error: { type: "final" }, - }, - }, - }, - }, - { - services: { - loadStarterTemplate: async ({ organizationId, exampleId }) => { - const examples = await getTemplateExamples(organizationId); - const starterTemplate = examples.find( - (example) => example.id === exampleId, - ); - if (!starterTemplate) { - throw new Error(`Example ${exampleId} not found.`); - } - return starterTemplate; - }, - }, - actions: { - assignError: assign({ - error: (_, { data }) => data, - }), - assignStarterTemplate: assign({ - starterTemplate: (_, { data }) => data, - }), - }, - }, -); diff --git a/site/src/xServices/starterTemplates/starterTemplatesXService.ts b/site/src/xServices/starterTemplates/starterTemplatesXService.ts deleted file mode 100644 index 7771b4538a7c1..0000000000000 --- a/site/src/xServices/starterTemplates/starterTemplatesXService.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { getTemplateExamples } from "api/api"; -import { TemplateExample } from "api/typesGenerated"; -import { - getTemplatesByTag, - StarterTemplatesByTag, -} from "utils/starterTemplates"; -import { assign, createMachine } from "xstate"; - -export interface StarterTemplatesContext { - organizationId: string; - starterTemplatesByTag?: StarterTemplatesByTag; - error?: unknown; -} - -export const starterTemplatesMachine = createMachine( - { - id: "starterTemplates", - predictableActionArguments: true, - schema: { - context: {} as StarterTemplatesContext, - services: {} as { - loadStarterTemplates: { - data: TemplateExample[]; - }; - }, - }, - tsTypes: {} as import("./starterTemplatesXService.typegen").Typegen0, - initial: "loading", - states: { - loading: { - invoke: { - src: "loadStarterTemplates", - onDone: { - actions: ["assignStarterTemplates"], - target: "idle.ok", - }, - onError: { - actions: ["assignError"], - target: "idle.error", - }, - }, - }, - idle: { - initial: "ok", - states: { - ok: { type: "final" }, - error: { type: "final" }, - }, - }, - }, - }, - { - services: { - loadStarterTemplates: ({ organizationId }) => - getTemplateExamples(organizationId), - }, - actions: { - assignError: assign({ - error: (_, { data }) => data, - }), - assignStarterTemplates: assign({ - starterTemplatesByTag: (_, { data }) => getTemplatesByTag(data), - }), - }, - }, -);