Skip to content

chore(site): move templates fetching to react-query #9622

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

Merged
merged 3 commits into from
Sep 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions site/src/api/queries/templates.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import * as API from "api/api";

const getTemplatesQueryKey = (orgId: string) => [orgId, "templates"];

export const templates = (orgId: string) => {
return {
queryKey: getTemplatesQueryKey(orgId),
queryFn: () => API.getTemplates(orgId),
};
};

export const templateExamples = (orgId: string) => {
return {
queryKey: [...getTemplatesQueryKey(orgId), "examples"],
queryFn: () => API.getTemplateExamples(orgId),
};
};
7 changes: 3 additions & 4 deletions site/src/pages/TemplatesPage/EmptyTemplates.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { FC } from "react";
import { useTranslation } from "react-i18next";
import { Link as RouterLink } from "react-router-dom";
import { docs } from "utils/docs";
import { Permissions } from "xServices/auth/authXService";

// Those are from https://github.com/coder/coder/tree/main/examples/templates
const featuredExampleIds = [
Expand Down Expand Up @@ -38,14 +37,14 @@ const findFeaturedExamples = (examples: TemplateExample[]) => {
};

export const EmptyTemplates: FC<{
permissions: Permissions;
canCreateTemplates: boolean;
examples: TemplateExample[];
}> = ({ permissions, examples }) => {
}> = ({ canCreateTemplates, examples }) => {
const styles = useStyles();
const { t } = useTranslation("templatesPage");
const featuredExamples = findFeaturedExamples(examples);

if (permissions.createTemplates) {
if (canCreateTemplates) {
return (
<TableEmpty
message={t("empty.message")}
Expand Down
21 changes: 13 additions & 8 deletions site/src/pages/TemplatesPage/TemplatesPage.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,33 @@
import { useMachine } from "@xstate/react";
import { useOrganizationId } from "hooks/useOrganizationId";
import { usePermissions } from "hooks/usePermissions";
import { FC } from "react";
import { Helmet } from "react-helmet-async";
import { pageTitle } from "../../utils/page";
import { templatesMachine } from "../../xServices/templates/templatesXService";
import { TemplatesPageView } from "./TemplatesPageView";
import { templateExamples, templates } from "api/queries/templates";
import { useQuery } from "@tanstack/react-query";

export const TemplatesPage: FC = () => {
const organizationId = useOrganizationId();
const permissions = usePermissions();
const [templatesState] = useMachine(templatesMachine, {
context: {
organizationId,
permissions,
},
const templatesQuery = useQuery(templates(organizationId));
const examplesQuery = useQuery({
...templateExamples(organizationId),
enabled: permissions.createTemplates,
});
const error = templatesQuery.error || examplesQuery.error;

return (
<>
<Helmet>
<title>{pageTitle("Templates")}</title>
</Helmet>
<TemplatesPageView context={templatesState.context} />
<TemplatesPageView
error={error}
canCreateTemplates={permissions.createTemplates}
examples={examplesQuery.data}
templates={templatesQuery.data}
/>
</>
);
};
Expand Down
94 changes: 37 additions & 57 deletions site/src/pages/TemplatesPage/TemplatesPageView.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import {
mockApiError,
MockOrganization,
MockPermissions,
MockTemplate,
MockTemplateExample,
MockTemplateExample2,
Expand All @@ -19,32 +17,29 @@ type Story = StoryObj<typeof TemplatesPageView>;

export const WithTemplates: Story = {
args: {
context: {
organizationId: MockOrganization.id,
permissions: MockPermissions,
error: undefined,
templates: [
MockTemplate,
{
...MockTemplate,
active_user_count: -1,
description: "🚀 Some new template that has no activity data",
icon: "/icon/goland.svg",
},
{
...MockTemplate,
active_user_count: 150,
description: "😮 Wow, this one has a bunch of usage!",
icon: "",
},
{
...MockTemplate,
description:
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. ",
},
],
examples: [],
},
canCreateTemplates: true,
error: undefined,
templates: [
MockTemplate,
{
...MockTemplate,
active_user_count: -1,
description: "🚀 Some new template that has no activity data",
icon: "/icon/goland.svg",
},
{
...MockTemplate,
active_user_count: 150,
description: "😮 Wow, this one has a bunch of usage!",
icon: "",
},
{
...MockTemplate,
description:
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. ",
},
],
examples: [],
},
};

Expand All @@ -59,44 +54,29 @@ export const WithTemplatesSmallViewPort: Story = {

export const EmptyCanCreate: Story = {
args: {
context: {
organizationId: MockOrganization.id,
permissions: MockPermissions,
error: undefined,
templates: [],
examples: [MockTemplateExample, MockTemplateExample2],
},
canCreateTemplates: true,
error: undefined,
templates: [],
examples: [MockTemplateExample, MockTemplateExample2],
},
};

export const EmptyCannotCreate: Story = {
args: {
context: {
organizationId: MockOrganization.id,
permissions: {
...MockPermissions,
createTemplates: false,
},
error: undefined,
templates: [],
examples: [MockTemplateExample, MockTemplateExample2],
},
error: undefined,
templates: [],
examples: [MockTemplateExample, MockTemplateExample2],
canCreateTemplates: false,
},
};

export const Error: Story = {
args: {
context: {
organizationId: MockOrganization.id,
permissions: {
...MockPermissions,
createTemplates: false,
},
error: mockApiError({
message: "Something went wrong fetching templates.",
}),
templates: undefined,
examples: undefined,
},
error: mockApiError({
message: "Something went wrong fetching templates.",
}),
templates: undefined,
examples: undefined,
canCreateTemplates: false,
},
};
32 changes: 18 additions & 14 deletions site/src/pages/TemplatesPage/TemplatesPageView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,18 @@ import {
formatTemplateBuildTime,
formatTemplateActiveDevelopers,
} from "utils/templates";
import { AvatarData } from "../../components/AvatarData/AvatarData";
import { Margins } from "../../components/Margins/Margins";
import { AvatarData } from "components/AvatarData/AvatarData";
import { Margins } from "components/Margins/Margins";
import {
PageHeader,
PageHeaderSubtitle,
PageHeaderTitle,
} from "../../components/PageHeader/PageHeader";
import { Stack } from "../../components/Stack/Stack";
} from "components/PageHeader/PageHeader";
import { Stack } from "components/Stack/Stack";
import {
TableLoaderSkeleton,
TableRowSkeleton,
} from "../../components/TableLoader/TableLoader";
} from "components/TableLoader/TableLoader";
import {
HelpTooltip,
HelpTooltipLink,
Expand All @@ -36,9 +36,8 @@ import {
HelpTooltipTitle,
} from "components/HelpTooltip/HelpTooltip";
import { EmptyTemplates } from "./EmptyTemplates";
import { TemplatesContext } from "xServices/templates/templatesXService";
import { useClickableTableRow } from "hooks/useClickableTableRow";
import { Template } from "api/typesGenerated";
import { Template, TemplateExample } from "api/typesGenerated";
import { combineClasses } from "utils/combineClasses";
import { colors } from "theme/colors";
import ArrowForwardOutlined from "@mui/icons-material/ArrowForwardOutlined";
Expand Down Expand Up @@ -141,21 +140,26 @@ const TemplateRow: FC<{ template: Template }> = ({ template }) => {
};

export interface TemplatesPageViewProps {
context: TemplatesContext;
error?: unknown;
examples: TemplateExample[] | undefined;
templates: Template[] | undefined;
canCreateTemplates: boolean;
}

export const TemplatesPageView: FC<
React.PropsWithChildren<TemplatesPageViewProps>
> = ({ context }) => {
const { templates, error, examples, permissions } = context;
export const TemplatesPageView: FC<TemplatesPageViewProps> = ({
templates,
error,
examples,
canCreateTemplates,
}) => {
const isLoading = !templates;
const isEmpty = Boolean(templates && templates.length === 0);

return (
<Margins>
<PageHeader
actions={
<Maybe condition={permissions.createTemplates}>
<Maybe condition={canCreateTemplates}>
<Button component={RouterLink} to="/starter-templates">
Starter Templates
</Button>
Expand Down Expand Up @@ -208,7 +212,7 @@ export const TemplatesPageView: FC<
<ChooseOne>
<Cond condition={isEmpty}>
<EmptyTemplates
permissions={permissions}
canCreateTemplates={canCreateTemplates}
examples={examples ?? []}
/>
</Cond>
Expand Down
77 changes: 0 additions & 77 deletions site/src/xServices/templates/templatesXService.ts

This file was deleted.