Skip to content

Commit

Permalink
fix: Make the workspace URL pretty (#2101)
Browse files Browse the repository at this point in the history
This adds the `@username/workspacename` format to the
workspace page!
  • Loading branch information
kylecarbs committed Jun 6, 2022
1 parent e2b2580 commit 74d9fee
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 36 deletions.
36 changes: 17 additions & 19 deletions site/src/AppRouter.tsx
Expand Up @@ -65,25 +65,6 @@ export const AppRouter: FC = () => (
</RequireAuth>
}
/>

<Route path=":workspace">
<Route
index
element={
<AuthAndFrame>
<WorkspacePage />
</AuthAndFrame>
}
/>
<Route
path="schedule"
element={
<RequireAuth>
<WorkspaceSchedulePage />
</RequireAuth>
}
/>
</Route>
</Route>

<Route path="templates">
Expand Down Expand Up @@ -142,6 +123,23 @@ export const AppRouter: FC = () => (

<Route path="/@:username">
<Route path=":workspace">
<Route
index
element={
<AuthAndFrame>
<WorkspacePage />
</AuthAndFrame>
}
/>
<Route
path="schedule"
element={
<RequireAuth>
<WorkspaceSchedulePage />
</RequireAuth>
}
/>

<Route
path="terminal"
element={
Expand Down
9 changes: 7 additions & 2 deletions site/src/components/NavbarView/NavbarView.tsx
@@ -1,9 +1,10 @@
import List from "@material-ui/core/List"
import ListItem from "@material-ui/core/ListItem"
import { fade, makeStyles } from "@material-ui/core/styles"
import { NavLink } from "react-router-dom"
import { NavLink, useLocation } from "react-router-dom"
import * as TypesGen from "../../api/typesGenerated"
import { navHeight } from "../../theme/constants"
import { combineClasses } from "../../util/combineClasses"
import { Logo } from "../Icons/Logo"
import { UserDropdown } from "../UserDropdown/UsersDropdown"

Expand All @@ -20,6 +21,7 @@ export const Language = {

export const NavbarView: React.FC<NavbarViewProps> = ({ user, onSignOut }) => {
const styles = useStyles()
const location = useLocation()
return (
<nav className={styles.root}>
<List className={styles.fixed}>
Expand All @@ -29,7 +31,10 @@ export const NavbarView: React.FC<NavbarViewProps> = ({ user, onSignOut }) => {
</NavLink>
</ListItem>
<ListItem button className={styles.item}>
<NavLink className={styles.link} to="/workspaces">
<NavLink
className={combineClasses([styles.link, location.pathname.startsWith("/@") && "active"])}
to="/workspaces"
>
{Language.workspaces}
</NavLink>
</ListItem>
Expand Down
18 changes: 12 additions & 6 deletions site/src/pages/WorkspacePage/WorkspacePage.test.tsx
Expand Up @@ -27,7 +27,10 @@ import { WorkspacePage } from "./WorkspacePage"

// It renders the workspace page and waits for it be loaded
const renderWorkspacePage = async () => {
renderWithAuth(<WorkspacePage />, { route: `/workspaces/${MockWorkspace.id}`, path: "/workspaces/:workspace" })
renderWithAuth(<WorkspacePage />, {
route: `/@${MockWorkspace.owner_name}/${MockWorkspace.name}`,
path: "/@:username/:workspace",
})
await screen.findByText(MockWorkspace.name)
}

Expand All @@ -47,7 +50,7 @@ const testButton = async (label: string, actionMock: jest.SpyInstance) => {

const testStatus = async (mock: Workspace, label: string) => {
server.use(
rest.get(`/api/v2/workspaces/${MockWorkspace.id}`, (req, res, ctx) => {
rest.get(`/api/v2/users/:username/workspace/:workspaceName`, (req, res, ctx) => {
return res(ctx.status(200), ctx.json(mock))
}),
)
Expand Down Expand Up @@ -87,7 +90,7 @@ describe("Workspace Page", () => {
})
it("requests a start job when the user presses Start", async () => {
server.use(
rest.get(`/api/v2/workspaces/${MockWorkspace.id}`, (req, res, ctx) => {
rest.get(`/api/v2/users/:userId/workspace/:workspaceName`, (req, res, ctx) => {
return res(ctx.status(200), ctx.json(MockStoppedWorkspace))
}),
)
Expand All @@ -98,7 +101,7 @@ describe("Workspace Page", () => {
})
it("requests cancellation when the user presses Cancel", async () => {
server.use(
rest.get(`/api/v2/workspaces/${MockWorkspace.id}`, (req, res, ctx) => {
rest.get(`/api/v2/users/:userId/workspace/:workspaceName`, (req, res, ctx) => {
return res(ctx.status(200), ctx.json(MockStartingWorkspace))
}),
)
Expand All @@ -110,7 +113,7 @@ describe("Workspace Page", () => {
it("requests a template when the user presses Update", async () => {
const getTemplateMock = jest.spyOn(api, "getTemplate").mockResolvedValueOnce(MockTemplate)
server.use(
rest.get(`/api/v2/workspaces/${MockWorkspace.id}`, (req, res, ctx) => {
rest.get(`/api/v2/users/:userId/workspace/:workspaceName`, (req, res, ctx) => {
return res(ctx.status(200), ctx.json(MockOutdatedWorkspace))
}),
)
Expand Down Expand Up @@ -159,7 +162,10 @@ describe("Workspace Page", () => {

describe("Resources", () => {
it("shows the status of each agent in each resource", async () => {
renderWithAuth(<WorkspacePage />, { route: `/workspaces/${MockWorkspace.id}`, path: "/workspaces/:workspace" })
renderWithAuth(<WorkspacePage />, {
route: `/@${MockWorkspace.owner_name}/${MockWorkspace.name}`,
path: "/@:username/:workspace",
})
const agent1Names = await screen.findAllByText(MockWorkspaceAgent.name)
expect(agent1Names.length).toEqual(2)
const agent2Names = await screen.findAllByText(MockWorkspaceAgentDisconnected.name)
Expand Down
9 changes: 5 additions & 4 deletions site/src/pages/WorkspacePage/WorkspacePage.tsx
Expand Up @@ -14,9 +14,10 @@ import { workspaceMachine } from "../../xServices/workspace/workspaceXService"
import { workspaceScheduleBannerMachine } from "../../xServices/workspaceSchedule/workspaceScheduleBannerXService"

export const WorkspacePage: React.FC = () => {
const { workspace: workspaceQueryParam } = useParams()
const { username: usernameQueryParam, workspace: workspaceQueryParam } = useParams()
const navigate = useNavigate()
const workspaceId = firstOrItem(workspaceQueryParam, null)
const username = firstOrItem(usernameQueryParam, null)
const workspaceName = firstOrItem(workspaceQueryParam, null)

const [workspaceState, workspaceSend] = useMachine(workspaceMachine)
const { workspace, resources, getWorkspaceError, getResourcesError, builds } = workspaceState.context
Expand All @@ -28,8 +29,8 @@ export const WorkspacePage: React.FC = () => {
* workspaceSend should not change.
*/
useEffect(() => {
workspaceId && workspaceSend({ type: "GET_WORKSPACE", workspaceId })
}, [workspaceId, workspaceSend])
username && workspaceName && workspaceSend({ type: "GET_WORKSPACE", username, workspaceName })
}, [username, workspaceName, workspaceSend])

if (workspaceState.matches("error")) {
return <ErrorSummary error={getWorkspaceError} />
Expand Down
2 changes: 1 addition & 1 deletion site/src/pages/WorkspacesPage/WorkspacesPageView.tsx
Expand Up @@ -74,7 +74,7 @@ export const WorkspacesPageView: FC<WorkspacesPageViewProps> = ({ loading, works
<AvatarData
title={workspace.name}
subtitle={workspace.owner_name}
link={`/workspaces/${workspace.id}`}
link={`/@${workspace.owner_name}/${workspace.name}`}
/>
</TableCell>
<TableCell>{workspace.template_name}</TableCell>
Expand Down
6 changes: 3 additions & 3 deletions site/src/xServices/workspace/workspaceXService.ts
Expand Up @@ -37,7 +37,7 @@ export interface WorkspaceContext {
}

export type WorkspaceEvent =
| { type: "GET_WORKSPACE"; workspaceId: string }
| { type: "GET_WORKSPACE"; workspaceName: string; username: string }
| { type: "START" }
| { type: "STOP" }
| { type: "ASK_DELETE" }
Expand Down Expand Up @@ -431,7 +431,7 @@ export const workspaceMachine = createMachine(
},
services: {
getWorkspace: async (_, event) => {
return await API.getWorkspace(event.workspaceId)
return await API.getWorkspaceByOwnerAndName(event.username, event.workspaceName)
},
getTemplate: async (context) => {
if (context.workspace) {
Expand Down Expand Up @@ -470,7 +470,7 @@ export const workspaceMachine = createMachine(
},
refreshWorkspace: async (context) => {
if (context.workspace) {
return await API.getWorkspace(context.workspace.id)
return await API.getWorkspaceByOwnerAndName(context.workspace.owner_name, context.workspace.name)
} else {
throw Error("Cannot refresh workspace without id")
}
Expand Down
2 changes: 1 addition & 1 deletion site/webpack.dev.ts
Expand Up @@ -63,7 +63,7 @@ const config: Configuration = {
port: process.env.PORT || 8080,
proxy: {
"/api": {
target: "http://localhost:3000",
target: "https://dev.coder.com",
ws: true,
secure: false,
},
Expand Down

0 comments on commit 74d9fee

Please sign in to comment.