Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7a50bc1

Browse files
committed
Merge main
2 parents 6ffd38b + f500b5e commit 7a50bc1

File tree

15 files changed

+163
-193
lines changed

15 files changed

+163
-193
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ require (
5151
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8
5252
github.com/powersj/whatsthis v1.3.0
5353
github.com/quasilyte/go-ruleguard/dsl v0.3.17
54-
github.com/spf13/cobra v1.3.0
54+
github.com/spf13/cobra v1.4.0
5555
github.com/stretchr/testify v1.7.0
5656
github.com/tabbed/pqtype v0.1.1
5757
github.com/unrolled/secure v1.10.0

go.sum

Lines changed: 4 additions & 87 deletions
Large diffs are not rendered by default.

site/api.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ export interface Workspace {
8484

8585
export namespace Workspace {
8686
export const create = async (request: CreateWorkspaceRequest): Promise<Workspace> => {
87-
const response = await fetch(`/api/v2/workspaces/me`, {
87+
const response = await fetch(`/api/v2/users/me/workspaces`, {
8888
method: "POST",
8989
headers: {
9090
"Content-Type": "application/json",

site/app.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import LoginPage from "./pages/login"
1313
import ProjectsPage from "./pages/projects"
1414
import ProjectPage from "./pages/projects/[organization]/[project]"
1515
import CreateWorkspacePage from "./pages/projects/[organization]/[project]/create"
16-
import WorkspacePage from "./pages/workspaces/[user]/[workspace]"
16+
import WorkspacePage from "./pages/workspaces/[workspace]"
1717

1818
export const App: React.FC = () => {
1919
return (
@@ -50,9 +50,7 @@ export const App: React.FC = () => {
5050
</Route>
5151

5252
<Route path="workspaces">
53-
<Route path=":user">
54-
<Route path=":workspace" element={<WorkspacePage />} />
55-
</Route>
53+
<Route path=":workspace" element={<WorkspacePage />} />
5654
</Route>
5755

5856
{/* Using path="*"" means "match anything", so this route

site/components/Workspace/Workspace.test.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { screen } from "@testing-library/react"
22
import React from "react"
33
import { Workspace } from "./Workspace"
4-
import { MockWorkspace, render } from "../../test_helpers"
4+
import { MockOrganization, MockProject, MockWorkspace, render } from "../../test_helpers"
55

66
describe("Workspace", () => {
77
it("renders", async () => {
88
// When
9-
render(<Workspace workspace={MockWorkspace} />)
9+
render(<Workspace organization={MockOrganization} project={MockProject} workspace={MockWorkspace} />)
1010

1111
// Then
1212
const element = await screen.findByText(MockWorkspace.name)

site/components/Workspace/Workspace.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,21 @@ import * as API from "../../api"
1010
import { WorkspaceSection } from "./WorkspaceSection"
1111

1212
export interface WorkspaceProps {
13+
organization: API.Organization
1314
workspace: API.Workspace
15+
project: API.Project
1416
}
1517

1618
/**
1719
* Workspace is the top-level component for viewing an individual workspace
1820
*/
19-
export const Workspace: React.FC<WorkspaceProps> = ({ workspace }) => {
21+
export const Workspace: React.FC<WorkspaceProps> = ({ organization, project, workspace }) => {
2022
const styles = useStyles()
2123

2224
return (
2325
<div className={styles.root}>
2426
<div className={styles.vertical}>
25-
<WorkspaceHeader workspace={workspace} />
27+
<WorkspaceHeader organization={organization} project={project} workspace={workspace} />
2628
<div className={styles.horizontal}>
2729
<div className={styles.sidebarContainer}>
2830
<WorkspaceSection title="Applications">
@@ -54,17 +56,19 @@ export const Workspace: React.FC<WorkspaceProps> = ({ workspace }) => {
5456
/**
5557
* Component for the header at the top of the workspace page
5658
*/
57-
export const WorkspaceHeader: React.FC<WorkspaceProps> = ({ workspace }) => {
59+
export const WorkspaceHeader: React.FC<WorkspaceProps> = ({ organization, project, workspace }) => {
5860
const styles = useStyles()
5961

62+
const projectLink = `/projects/${organization.name}/${project.name}`
63+
6064
return (
6165
<Paper elevation={0} className={styles.section}>
6266
<div className={styles.horizontal}>
6367
<WorkspaceHeroIcon />
6468
<div className={styles.vertical}>
6569
<Typography variant="h4">{workspace.name}</Typography>
6670
<Typography variant="body2" color="textSecondary">
67-
<Link to="javascript:;">{workspace.project_id}</Link>
71+
<Link to={projectLink}>{project.name}</Link>
6872
</Typography>
6973
</div>
7074
</div>

site/components/index.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
export * from "./Button"
22
export * from "./EmptyState"
33
export * from "./Page"
4-
export * from "./Redirect"

site/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
"@types/express": "4.17.13",
3636
"@types/jest": "27.4.1",
3737
"@types/node": "14.18.12",
38-
"@types/react": "17.0.39",
38+
"@types/react": "17.0.40",
3939
"@types/react-dom": "17.0.13",
4040
"@types/superagent": "4.1.15",
4141
"@typescript-eslint/eslint-plugin": "4.33.0",

site/pages/projects/[organization]/[project]/create.tsx

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,36 @@ import { useUser } from "../../../../contexts/UserContext"
88
import { ErrorSummary } from "../../../../components/ErrorSummary"
99
import { FullScreenLoader } from "../../../../components/Loader/FullScreenLoader"
1010
import { CreateWorkspaceForm } from "../../../../forms/CreateWorkspaceForm"
11+
import { unsafeSWRArgument } from "../../../../util"
1112

1213
const CreateWorkspacePage: React.FC = () => {
13-
const { organization, project: projectName } = useParams()
14+
const { organization: organizationName, project: projectName } = useParams()
1415
const navigate = useNavigate()
1516
const styles = useStyles()
1617
const { me } = useUser(/* redirectOnError */ true)
17-
const { data: project, error: projectError } = useSWR<API.Project, Error>(
18-
`/api/v2/projects/${organization}/${projectName}`,
18+
19+
const { data: organizationInfo, error: organizationError } = useSWR<API.Organization, Error>(
20+
() => `/api/v2/users/me/organizations/${organizationName}`,
1921
)
2022

23+
const { data: project, error: projectError } = useSWR<API.Project, Error>(() => {
24+
return `/api/v2/organizations/${unsafeSWRArgument(organizationInfo).id}/projects/${projectName}`
25+
})
26+
2127
const onCancel = useCallback(async () => {
22-
navigate(`/projects/${organization}/${projectName}`)
23-
}, [navigate, organization, projectName])
28+
navigate(`/projects/${organizationName}/${projectName}`)
29+
}, [navigate, organizationName, projectName])
2430

2531
const onSubmit = async (req: API.CreateWorkspaceRequest) => {
2632
const workspace = await API.Workspace.create(req)
27-
navigate(`/workspaces/me/${workspace.name}`)
33+
navigate(`/workspaces/${workspace.id}`)
2834
return workspace
2935
}
3036

37+
if (organizationError) {
38+
return <ErrorSummary error={organizationError} />
39+
}
40+
3141
if (projectError) {
3242
return <ErrorSummary error={projectError} />
3343
}

site/pages/projects/[organization]/[project]/index.tsx

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import Paper from "@material-ui/core/Paper"
44
import { Link, useNavigate, useParams } from "react-router-dom"
55
import useSWR from "swr"
66

7-
import { Project, Workspace } from "../../../../api"
7+
import { Organization, Project, Workspace } from "../../../../api"
88
import { Header } from "../../../../components/Header"
99
import { FullScreenLoader } from "../../../../components/Loader/FullScreenLoader"
1010
import { Navbar } from "../../../../components/Navbar"
@@ -14,20 +14,31 @@ import { useUser } from "../../../../contexts/UserContext"
1414
import { ErrorSummary } from "../../../../components/ErrorSummary"
1515
import { firstOrItem } from "../../../../util/array"
1616
import { EmptyState } from "../../../../components/EmptyState"
17+
import { unsafeSWRArgument } from "../../../../util"
1718

1819
const ProjectPage: React.FC = () => {
1920
const styles = useStyles()
2021
const { me, signOut } = useUser(true)
2122
const navigate = useNavigate()
22-
const { project, organization } = useParams()
23+
const { project: projectName, organization: organizationName } = useParams()
2324

24-
const { data: projectInfo, error: projectError } = useSWR<Project, Error>(
25-
() => `/api/v2/projects/${organization}/${project}`,
25+
const { data: organizationInfo, error: organizationError } = useSWR<Organization, Error>(
26+
() => `/api/v2/users/me/organizations/${organizationName}`,
2627
)
27-
const { data: workspaces, error: workspacesError } = useSWR<Workspace[], Error>(
28-
() => `/api/v2/projects/${organization}/${project}/workspaces`,
28+
29+
const { data: projectInfo, error: projectError } = useSWR<Project, Error>(
30+
() => `/api/v2/organizations/${unsafeSWRArgument(organizationInfo).id}/projects/${projectName}`,
2931
)
3032

33+
// TODO: The workspaces endpoint was recently changed, so that we can't get
34+
// workspaces per-project. This just grabs all workspaces... and then
35+
// later filters them to match the current project.
36+
const { data: workspaces, error: workspacesError } = useSWR<Workspace[], Error>(() => `/api/v2/users/me/workspaces`)
37+
38+
if (organizationError) {
39+
return <ErrorSummary error={organizationError} />
40+
}
41+
3142
if (projectError) {
3243
return <ErrorSummary error={projectError} />
3344
}
@@ -41,7 +52,7 @@ const ProjectPage: React.FC = () => {
4152
}
4253

4354
const createWorkspace = () => {
44-
navigate(`/projects/${organization}/${project}/create`)
55+
navigate(`/projects/${organizationName}/${projectName}/create`)
4556
}
4657

4758
const emptyState = (
@@ -59,26 +70,31 @@ const ProjectPage: React.FC = () => {
5970
{
6071
key: "name",
6172
name: "Name",
62-
renderer: (nameField: string) => {
63-
return <Link to={`/workspaces/me/${nameField}`}>{nameField}</Link>
73+
renderer: (nameField: string, workspace: Workspace) => {
74+
return <Link to={`/workspaces/${workspace.id}`}>{nameField}</Link>
75+
6476
},
6577
},
6678
]
6779

80+
const perProjectWorkspaces = workspaces.filter((workspace) => {
81+
return workspace.project_id === projectInfo.id
82+
})
83+
6884
const tableProps = {
6985
title: "Workspaces",
7086
columns,
71-
data: workspaces,
87+
data: perProjectWorkspaces,
7288
emptyState: emptyState,
7389
}
7490

7591
return (
7692
<div className={styles.root}>
7793
<Navbar user={me} onSignOut={signOut} />
7894
<Header
79-
title={firstOrItem(project, "")}
80-
description={firstOrItem(organization, "")}
81-
subTitle={`${workspaces.length} workspaces`}
95+
title={firstOrItem(projectName, "")}
96+
description={firstOrItem(organizationName, "")}
97+
subTitle={`${perProjectWorkspaces.length} workspaces`}
8298
action={{
8399
text: "Create Workspace",
84100
onClick: createWorkspace,

site/pages/workspaces/[user]/[workspace].tsx

Lines changed: 0 additions & 69 deletions
This file was deleted.

site/pages/workspaces/[workspace].tsx

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import React from "react"
2+
import useSWR from "swr"
3+
import { makeStyles } from "@material-ui/core/styles"
4+
import { useParams } from "react-router-dom"
5+
import { Navbar } from "../../components/Navbar"
6+
import { Footer } from "../../components/Page"
7+
import { useUser } from "../../contexts/UserContext"
8+
import { firstOrItem } from "../../util/array"
9+
import { ErrorSummary } from "../../components/ErrorSummary"
10+
import { FullScreenLoader } from "../../components/Loader/FullScreenLoader"
11+
import { Workspace } from "../../components/Workspace"
12+
import { unsafeSWRArgument } from "../../util"
13+
import * as API from "../../api"
14+
15+
const WorkspacesPage: React.FC = () => {
16+
const styles = useStyles()
17+
const { workspace: workspaceQueryParam } = useParams()
18+
const { me, signOut } = useUser(true)
19+
20+
const { data: workspace, error: workspaceError } = useSWR<API.Workspace, Error>(() => {
21+
const workspaceParam = firstOrItem(workspaceQueryParam, null)
22+
23+
return `/api/v2/workspaces/${workspaceParam}`
24+
})
25+
26+
// Fetch parent project
27+
const { data: project, error: projectError } = useSWR<API.Project, Error>(() => {
28+
return `/api/v2/projects/${unsafeSWRArgument(workspace).project_id}`
29+
})
30+
31+
const { data: organization, error: organizationError } = useSWR<API.Project, Error>(() => {
32+
return `/api/v2/organizations/${unsafeSWRArgument(project).organization_id}`
33+
})
34+
35+
if (workspaceError) {
36+
return <ErrorSummary error={workspaceError} />
37+
}
38+
39+
if (projectError) {
40+
return <ErrorSummary error={projectError} />
41+
}
42+
43+
if (organizationError) {
44+
return <ErrorSummary error={organizationError} />
45+
}
46+
47+
if (!me || !workspace || !project || !organization) {
48+
return <FullScreenLoader />
49+
}
50+
51+
return (
52+
<div className={styles.root}>
53+
<Navbar user={me} onSignOut={signOut} />
54+
55+
<div className={styles.inner}>
56+
<Workspace organization={organization} project={project} workspace={workspace} />
57+
</div>
58+
59+
<Footer />
60+
</div>
61+
)
62+
}
63+
64+
const useStyles = makeStyles(() => ({
65+
root: {
66+
display: "flex",
67+
flexDirection: "column",
68+
},
69+
inner: {
70+
maxWidth: "1380px",
71+
margin: "1em auto",
72+
width: "100%",
73+
},
74+
}))
75+
76+
export default WorkspacesPage

site/util/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from "./array"
2+
export * from "./swr"

0 commit comments

Comments
 (0)