Skip to content

Commit b3bdc36

Browse files
committed
Add workspaces table
1 parent 6b37868 commit b3bdc36

File tree

4 files changed

+109
-61
lines changed

4 files changed

+109
-61
lines changed

site/src/components/NavbarView/NavbarView.stories.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Story } from "@storybook/react"
22
import React from "react"
3+
import { MockUser, MockUser2 } from "../../testHelpers/entities"
34
import { NavbarView, NavbarViewProps } from "./NavbarView"
45

56
export default {
@@ -14,15 +15,15 @@ const Template: Story<NavbarViewProps> = (args: NavbarViewProps) => <NavbarView
1415

1516
export const ForAdmin = Template.bind({})
1617
ForAdmin.args = {
17-
user: { id: "1", username: "Administrator", email: "admin@coder.com", created_at: "dawn" },
18+
user: MockUser,
1819
onSignOut: () => {
1920
return Promise.resolve()
2021
},
2122
}
2223

2324
export const ForMember = Template.bind({})
2425
ForMember.args = {
25-
user: { id: "1", username: "CathyCoder", email: "cathy@coder.com", created_at: "dawn" },
26+
user: MockUser2,
2627
onSignOut: () => {
2728
return Promise.resolve()
2829
},
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { ComponentMeta, Story } from "@storybook/react"
2+
import React from "react"
3+
import { MockTemplate, MockWorkspace } from "../../testHelpers/entities"
4+
import { WorkspacesTable, WorkspacesTableProps } from "./WorkspacesTable"
5+
6+
export default {
7+
title: "components/WorkspacesTable",
8+
component: WorkspacesTable,
9+
} as ComponentMeta<typeof WorkspacesTable>
10+
11+
const Template: Story<WorkspacesTableProps> = (args) => <WorkspacesTable {...args} />
12+
13+
export const Example = Template.bind({})
14+
Example.args = {
15+
templateInfo: MockTemplate,
16+
workspaces: [MockWorkspace],
17+
onCreateWorkspace: () => {
18+
console.info("Create workspace")
19+
},
20+
}
21+
22+
export const Empty = Template.bind({})
23+
Empty.args = {
24+
templateInfo: MockTemplate,
25+
workspaces: [],
26+
onCreateWorkspace: () => {
27+
console.info("Create workspace")
28+
},
29+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import Box from "@material-ui/core/Box"
2+
import Button from "@material-ui/core/Button"
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 React from "react"
9+
import { Link } from "react-router-dom"
10+
import * as TypesGen from "../../api/typesGenerated"
11+
import { EmptyState } from "../EmptyState/EmptyState"
12+
import { TableHeaderRow } from "../TableHeaders/TableHeaders"
13+
import { TableLoader } from "../TableLoader/TableLoader"
14+
import { TableTitle } from "../TableTitle/TableTitle"
15+
16+
export const Language = {
17+
title: "Workspaces",
18+
nameLabel: "Name",
19+
emptyMessage: "No workspaces have been created yet",
20+
emptyDescription: "Create a workspace to get started",
21+
ctaAction: "Create workspace",
22+
}
23+
24+
export interface WorkspacesTableProps {
25+
templateInfo?: TypesGen.Template
26+
workspaces?: TypesGen.Workspace[]
27+
onCreateWorkspace: () => void
28+
}
29+
30+
export const WorkspacesTable: React.FC<WorkspacesTableProps> = ({ templateInfo, workspaces, onCreateWorkspace }) => {
31+
const isLoading = !templateInfo || !workspaces
32+
33+
return (
34+
<Table>
35+
<TableHead>
36+
<TableTitle title={Language.title} />
37+
<TableHeaderRow>
38+
<TableCell size="small">{Language.nameLabel}</TableCell>
39+
</TableHeaderRow>
40+
</TableHead>
41+
<TableBody>
42+
{isLoading && <TableLoader />}
43+
{workspaces &&
44+
workspaces.map((w) => (
45+
<TableRow key={w.id}>
46+
<TableCell>
47+
<Link to={`/workspaces/${w.id}`}>{w.name}</Link>
48+
</TableCell>
49+
</TableRow>
50+
))}
51+
52+
{workspaces && workspaces.length === 0 && (
53+
<TableRow>
54+
<TableCell colSpan={999}>
55+
<Box p={4}>
56+
<EmptyState
57+
message={Language.emptyMessage}
58+
description={Language.emptyDescription}
59+
cta={
60+
<Button variant="contained" color="primary" onClick={onCreateWorkspace}>
61+
{Language.ctaAction}
62+
</Button>
63+
}
64+
/>
65+
</Box>
66+
</TableCell>
67+
</TableRow>
68+
)}
69+
</TableBody>
70+
</Table>
71+
)
72+
}

site/src/pages/TemplatesPages/OrganizationPage/TemplatePage/TemplatePage.tsx

Lines changed: 5 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,17 @@
1-
import Box from "@material-ui/core/Box"
2-
import Button from "@material-ui/core/Button"
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"
81
import React from "react"
9-
import { Link, useNavigate, useParams } from "react-router-dom"
2+
import { useNavigate, useParams } from "react-router-dom"
103
import useSWR from "swr"
114
import * as TypesGen from "../../../../api/typesGenerated"
12-
import { EmptyState } from "../../../../components/EmptyState/EmptyState"
135
import { ErrorSummary } from "../../../../components/ErrorSummary/ErrorSummary"
146
import { Header } from "../../../../components/Header/Header"
157
import { Margins } from "../../../../components/Margins/Margins"
168
import { Stack } from "../../../../components/Stack/Stack"
17-
import { TableHeaderRow } from "../../../../components/TableHeaders/TableHeaders"
18-
import { TableLoader } from "../../../../components/TableLoader/TableLoader"
19-
import { TableTitle } from "../../../../components/TableTitle/TableTitle"
9+
import { WorkspacesTable } from "../../../../components/WorkspacesTable/WorkspacesTable"
2010
import { unsafeSWRArgument } from "../../../../util"
2111
import { firstOrItem } from "../../../../util/array"
2212

2313
export const Language = {
24-
tableTitle: "Workspaces",
25-
nameLabel: "Name",
26-
emptyMessage: "No workspaces have been created yet",
27-
emptyDescription: "Create a workspace to get started",
28-
totalLabel: "total",
29-
ctaAction: "Create workspace",
30-
subtitlePosfix: "workspaces",
14+
subtitle: "workspaces",
3115
}
3216

3317
export const TemplatePage: React.FC = () => {
@@ -44,13 +28,11 @@ export const TemplatePage: React.FC = () => {
4428

4529
// This just grabs all workspaces... and then later filters them to match the
4630
// current template.
47-
4831
const { data: workspaces, error: workspacesError } = useSWR<TypesGen.Workspace[], Error>(
4932
() => `/api/v2/organizations/${unsafeSWRArgument(organizationInfo).id}/workspaces`,
5033
)
5134

5235
const hasError = organizationError || templateError || workspacesError
53-
const isLoading = !templateInfo || !workspaces
5436

5537
const createWorkspace = () => {
5638
navigate(`/templates/${organizationName}/${templateName}/create`)
@@ -68,7 +50,7 @@ export const TemplatePage: React.FC = () => {
6850
<Header
6951
title={firstOrItem(templateName, "")}
7052
description={firstOrItem(organizationName, "")}
71-
subTitle={perTemplateWorkspaces ? `${perTemplateWorkspaces.length} ${Language.subtitlePosfix}` : ""}
53+
subTitle={perTemplateWorkspaces ? `${perTemplateWorkspaces.length} ${Language.subtitle}` : ""}
7254
action={{
7355
text: "Create Workspace",
7456
onClick: createWorkspace,
@@ -80,43 +62,7 @@ export const TemplatePage: React.FC = () => {
8062
{templateError && <ErrorSummary error={templateError} />}
8163
{workspacesError && <ErrorSummary error={workspacesError} />}
8264
{!hasError && (
83-
<Table>
84-
<TableHead>
85-
<TableTitle title={Language.tableTitle} />
86-
<TableHeaderRow>
87-
<TableCell size="small">{Language.nameLabel}</TableCell>
88-
</TableHeaderRow>
89-
</TableHead>
90-
<TableBody>
91-
{isLoading && <TableLoader />}
92-
{workspaces &&
93-
workspaces.map((w) => (
94-
<TableRow key={w.id}>
95-
<TableCell>
96-
<Link to={`/workspaces/${w.id}`}>{w.name}</Link>
97-
</TableCell>
98-
</TableRow>
99-
))}
100-
101-
{workspaces && workspaces.length === 0 && (
102-
<TableRow>
103-
<TableCell colSpan={999}>
104-
<Box p={4}>
105-
<EmptyState
106-
message={Language.emptyMessage}
107-
description={Language.emptyDescription}
108-
cta={
109-
<Button variant="contained" color="primary" onClick={createWorkspace}>
110-
{Language.ctaAction}
111-
</Button>
112-
}
113-
/>
114-
</Box>
115-
</TableCell>
116-
</TableRow>
117-
)}
118-
</TableBody>
119-
</Table>
65+
<WorkspacesTable templateInfo={templateInfo} workspaces={workspaces} onCreateWorkspace={createWorkspace} />
12066
)}
12167
</Margins>
12268
</Stack>

0 commit comments

Comments
 (0)