Skip to content

Commit f22d56a

Browse files
committed
feat: show template versions
1 parent c98f87b commit f22d56a

File tree

10 files changed

+172
-5
lines changed

10 files changed

+172
-5
lines changed

site/src/api/api.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,15 @@ export const getTemplateVersionResources = async (
136136
return response.data
137137
}
138138

139+
export const getTemplateVersions = async (
140+
templateId: string,
141+
): Promise<TypesGen.TemplateVersion[]> => {
142+
const response = await axios.get<TypesGen.TemplateVersion[]>(
143+
`/api/v2/templates/${templateId}/versions`,
144+
)
145+
return response.data
146+
}
147+
139148
export const getWorkspace = async (
140149
workspaceId: string,
141150
params?: TypesGen.WorkspaceOptions,
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { ComponentMeta, Story } from "@storybook/react"
2+
import { MockTemplateVersion } from "../../testHelpers/entities"
3+
import { VersionsTable, VersionsTableProps } from "./VersionsTable"
4+
5+
export default {
6+
title: "components/VersionsTable",
7+
component: VersionsTable,
8+
} as ComponentMeta<typeof VersionsTable>
9+
10+
const Template: Story<VersionsTableProps> = (args) => <VersionsTable {...args} />
11+
12+
export const Example = Template.bind({})
13+
Example.args = {
14+
versions: [
15+
MockTemplateVersion,
16+
{
17+
...MockTemplateVersion,
18+
name: "test-template-version-2",
19+
created_at: "2022-05-18T18:39:01.382927298Z",
20+
},
21+
],
22+
}
23+
24+
export const Empty = Template.bind({})
25+
Empty.args = {
26+
versions: [],
27+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import Box from "@material-ui/core/Box"
2+
import { Theme } from "@material-ui/core/styles"
3+
import Table from "@material-ui/core/Table"
4+
import TableBody from "@material-ui/core/TableBody"
5+
import TableCell from "@material-ui/core/TableCell"
6+
import TableHead from "@material-ui/core/TableHead"
7+
import TableRow from "@material-ui/core/TableRow"
8+
import useTheme from "@material-ui/styles/useTheme"
9+
import { FC } from "react"
10+
import * as TypesGen from "../../api/typesGenerated"
11+
import { EmptyState } from "../EmptyState/EmptyState"
12+
import { TableLoader } from "../TableLoader/TableLoader"
13+
14+
export const Language = {
15+
emptyMessage: "No versions found",
16+
nameLabel: "Version name",
17+
createdAtLabel: "Created at",
18+
createdByLabel: "Created by",
19+
}
20+
21+
export interface VersionsTableProps {
22+
versions?: TypesGen.TemplateVersion[]
23+
}
24+
25+
export const VersionsTable: FC<VersionsTableProps> = ({ versions }) => {
26+
const isLoading = !versions
27+
const theme: Theme = useTheme()
28+
29+
return (
30+
<Table data-testid="versions-table">
31+
<TableHead>
32+
<TableRow>
33+
<TableCell width="30%">{Language.nameLabel}</TableCell>
34+
<TableCell width="30%">{Language.createdAtLabel}</TableCell>
35+
<TableCell width="40%">{Language.createdByLabel}</TableCell>
36+
</TableRow>
37+
</TableHead>
38+
<TableBody>
39+
{isLoading && <TableLoader />}
40+
{versions &&
41+
versions
42+
.slice()
43+
.reverse()
44+
.map((version) => {
45+
return (
46+
<TableRow hover key={version.id} data-testid={`version-${version.id}`} tabIndex={0}>
47+
<TableCell>{version.name}</TableCell>
48+
<TableCell>
49+
<span style={{ color: theme.palette.text.secondary }}>
50+
{new Date(version.created_at).toLocaleString()}
51+
</span>
52+
</TableCell>
53+
<TableCell>
54+
<span style={{ color: theme.palette.text.secondary }}>
55+
{version.created_by_name}
56+
</span>
57+
</TableCell>
58+
</TableRow>
59+
)
60+
})}
61+
62+
{versions && versions.length === 0 && (
63+
<TableRow>
64+
<TableCell colSpan={999}>
65+
<Box p={4}>
66+
<EmptyState message={Language.emptyMessage} />
67+
</Box>
68+
</TableCell>
69+
</TableRow>
70+
)}
71+
</TableBody>
72+
</Table>
73+
)
74+
}

site/src/pages/TemplatePage/TemplatePage.test.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { screen } from "@testing-library/react"
22
import {
33
MockTemplate,
4+
MockTemplateVersion,
45
MockWorkspaceResource,
56
renderWithAuth,
67
} from "../../testHelpers/renderHelpers"
@@ -15,5 +16,6 @@ describe("TemplatePage", () => {
1516
await screen.findByText(MockTemplate.name)
1617
screen.getByTestId("markdown")
1718
screen.getByText(MockWorkspaceResource.name)
19+
screen.getByTestId(`version-${MockTemplateVersion.id}`)
1820
})
1921
})

site/src/pages/TemplatePage/TemplatePage.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,9 @@ export const TemplatePage: FC = () => {
2727
organizationId,
2828
},
2929
})
30-
const { template, activeTemplateVersion, templateResources } = templateState.context
31-
const isLoading = !template || !activeTemplateVersion || !templateResources
30+
const { template, activeTemplateVersion, templateResources, templateVersions } =
31+
templateState.context
32+
const isLoading = !template || !activeTemplateVersion || !templateResources || !templateVersions
3233

3334
if (isLoading) {
3435
return <Loader />
@@ -43,6 +44,7 @@ export const TemplatePage: FC = () => {
4344
template={template}
4445
activeTemplateVersion={activeTemplateVersion}
4546
templateResources={templateResources}
47+
templateVersions={templateVersions}
4648
/>
4749
</>
4850
)

site/src/pages/TemplatePage/TemplatePageView.stories.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Example.args = {
1414
template: Mocks.MockTemplate,
1515
activeTemplateVersion: Mocks.MockTemplateVersion,
1616
templateResources: [Mocks.MockWorkspaceResource, Mocks.MockWorkspaceResource2],
17+
templateVersions: [Mocks.MockTemplateVersion],
1718
}
1819

1920
export const SmallViewport = Template.bind({})
@@ -33,6 +34,7 @@ You can add instructions here
3334
\`\`\``,
3435
},
3536
templateResources: [Mocks.MockWorkspaceResource, Mocks.MockWorkspaceResource2],
37+
templateVersions: [Mocks.MockTemplateVersion],
3638
}
3739
SmallViewport.parameters = {
3840
chromatic: { viewports: [600] },

site/src/pages/TemplatePage/TemplatePageView.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,25 +16,29 @@ import {
1616
import { Stack } from "../../components/Stack/Stack"
1717
import { TemplateResourcesTable } from "../../components/TemplateResourcesTable/TemplateResourcesTable"
1818
import { TemplateStats } from "../../components/TemplateStats/TemplateStats"
19+
import { VersionsTable } from "../../components/VersionsTable/VersionsTable"
1920
import { WorkspaceSection } from "../../components/WorkspaceSection/WorkspaceSection"
2021

2122
const Language = {
2223
createButton: "Create workspace",
2324
noDescription: "",
2425
readmeTitle: "README",
2526
resourcesTitle: "Resources",
27+
versionsTitle: "Version history",
2628
}
2729

2830
export interface TemplatePageViewProps {
2931
template: Template
3032
activeTemplateVersion: TemplateVersion
3133
templateResources: WorkspaceResource[]
34+
templateVersions?: TemplateVersion[]
3235
}
3336

3437
export const TemplatePageView: FC<TemplatePageViewProps> = ({
3538
template,
3639
activeTemplateVersion,
3740
templateResources,
41+
templateVersions,
3842
}) => {
3943
const styles = useStyles()
4044
const readme = frontMatter(activeTemplateVersion.readme)
@@ -88,6 +92,12 @@ export const TemplatePageView: FC<TemplatePageViewProps> = ({
8892
</ReactMarkdown>
8993
</div>
9094
</WorkspaceSection>
95+
<WorkspaceSection
96+
title={Language.versionsTitle}
97+
contentsProps={{ className: styles.versionsTableContents }}
98+
>
99+
<VersionsTable versions={templateVersions} />
100+
</WorkspaceSection>
91101
</Stack>
92102
</Margins>
93103
)
@@ -111,5 +121,8 @@ export const useStyles = makeStyles((theme) => {
111121
resourcesTableContents: {
112122
margin: 0,
113123
},
124+
versionsTableContents: {
125+
margin: 0,
126+
},
114127
}
115128
})

site/src/testHelpers/entities.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,9 @@ export const MockRunningProvisionerJob: TypesGen.ProvisionerJob = {
101101

102102
export const MockTemplateVersion: TypesGen.TemplateVersion = {
103103
id: "test-template-version",
104-
created_at: "",
105-
updated_at: "",
104+
created_at: "2022-05-17T17:39:01.382927298Z",
105+
updated_at: "2022-05-17T17:39:01.382927298Z",
106+
template_id: "test-template",
106107
job: MockProvisionerJob,
107108
name: "test-version",
108109
readme: `---

site/src/testHelpers/handlers.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ export const handlers = [
2525
rest.get("/api/v2/templates/:templateId", async (req, res, ctx) => {
2626
return res(ctx.status(200), ctx.json(M.MockTemplate))
2727
}),
28+
rest.get("/api/v2/templates/:templateId/versions", async (req, res, ctx) => {
29+
return res(ctx.status(200), ctx.json([M.MockTemplateVersion]))
30+
}),
2831
rest.get("/api/v2/templateversions/:templateVersionId", async (req, res, ctx) => {
2932
return res(ctx.status(200), ctx.json(M.MockTemplateVersion))
3033
}),

site/src/xServices/template/templateXService.ts

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import { assign, createMachine } from "xstate"
2-
import { getTemplateByName, getTemplateVersion, getTemplateVersionResources } from "../../api/api"
2+
import {
3+
getTemplateByName,
4+
getTemplateVersion,
5+
getTemplateVersionResources,
6+
getTemplateVersions,
7+
} from "../../api/api"
38
import { Template, TemplateVersion, WorkspaceResource } from "../../api/typesGenerated"
49

510
interface TemplateContext {
@@ -8,6 +13,7 @@ interface TemplateContext {
813
template?: Template
914
activeTemplateVersion?: TemplateVersion
1015
templateResources?: WorkspaceResource[]
16+
templateVersions?: TemplateVersion[]
1117
}
1218

1319
export const templateMachine = createMachine(
@@ -24,6 +30,9 @@ export const templateMachine = createMachine(
2430
getTemplateResources: {
2531
data: WorkspaceResource[]
2632
}
33+
getTemplateVersions: {
34+
data: TemplateVersion[]
35+
}
2736
},
2837
},
2938
tsTypes: {} as import("./templateXService.typegen").Typegen0,
@@ -72,6 +81,21 @@ export const templateMachine = createMachine(
7281
success: { type: "final" },
7382
},
7483
},
84+
templateVersions: {
85+
initial: "gettingTemplateVersions",
86+
states: {
87+
gettingTemplateVersions: {
88+
invoke: {
89+
src: "getTemplateVersions",
90+
onDone: {
91+
actions: ["assignTemplateVersions"],
92+
target: "success",
93+
},
94+
},
95+
},
96+
success: { type: "final" },
97+
},
98+
},
7599
},
76100
},
77101
loaded: {},
@@ -94,6 +118,13 @@ export const templateMachine = createMachine(
94118

95119
return getTemplateVersionResources(ctx.template.active_version_id)
96120
},
121+
getTemplateVersions: (ctx) => {
122+
if (!ctx.template) {
123+
throw new Error("Template not loaded")
124+
}
125+
126+
return getTemplateVersions(ctx.template.id)
127+
},
97128
},
98129
actions: {
99130
assignTemplate: assign({
@@ -105,6 +136,9 @@ export const templateMachine = createMachine(
105136
assignTemplateResources: assign({
106137
templateResources: (_, event) => event.data,
107138
}),
139+
assignTemplateVersions: assign({
140+
templateVersions: (_, event) => event.data,
141+
}),
108142
},
109143
},
110144
)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy