Skip to content

Commit fd6aaf0

Browse files
committed
Merge branch 'main' into singletemplate
2 parents ebf36c2 + 0438430 commit fd6aaf0

File tree

13 files changed

+97
-69
lines changed

13 files changed

+97
-69
lines changed

examples/docker-image-builds/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ Edit the validation to include the new image:
5454

5555
```diff
5656
variable "docker_image" {
57-
description = "What Docker imagewould you like to use for your workspace?"
57+
description = "What Docker image would you like to use for your workspace?"
5858
default = "base"
5959

6060
# List of images available for the user to choose from.

examples/docker-image-builds/main.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ resource "coder_agent" "dev" {
5656
}
5757

5858
variable "docker_image" {
59-
description = "What Docker imagewould you like to use for your workspace?"
59+
description = "What Docker image would you like to use for your workspace?"
6060
default = "base"
6161

6262
# List of images available for the user to choose from.

examples/docker/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Edit the template:
2020
vim main.tf
2121
```
2222
variable "docker_image" {
23-
description = "What Docker imagewould you like to use for your workspace?"
23+
description = "What Docker image would you like to use for your workspace?"
2424
default = "codercom/enterprise-base:ubuntu"
2525
validation {
2626
- condition = contains(["codercom/enterprise-base:ubuntu", "codercom/enterprise-node:ubuntu", "codercom/enterprise-intellij:ubuntu"], var.docker_image)
@@ -46,7 +46,7 @@ To reduce drift, we recommend versioning images in your registry by creating tag
4646

4747
```sh
4848
variable "docker_image" {
49-
description = "What Docker imagewould you like to use for your workspace?"
49+
description = "What Docker image would you like to use for your workspace?"
5050
default = "codercom/enterprise-base:ubuntu"
5151
validation {
5252
- condition = contains(["my-org/base-development:v1.1", "myorg-java-development:v1.1"], var.docker_image)

site/src/components/Navbar/Navbar.test.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ beforeEach(() => {
1111
})
1212

1313
describe("Navbar", () => {
14-
describe("when user has permission to read all users", () => {
14+
describe("when user has permission to update users", () => {
1515
it("displays the admin menu", async () => {
1616
const checkUserPermissionsSpy = jest.spyOn(API, "checkUserPermissions").mockResolvedValueOnce({
17-
[checks.readAllUsers]: true,
17+
[checks.updateUsers]: true,
1818
})
1919

2020
renderWithAuth(<Navbar />)
@@ -25,10 +25,10 @@ describe("Navbar", () => {
2525
})
2626
})
2727

28-
describe("when user has NO permission to read all users", () => {
28+
describe("when user has NO permission to update users", () => {
2929
it("does not display the admin menu", async () => {
3030
const checkUserPermissionsSpy = jest.spyOn(API, "checkUserPermissions").mockResolvedValueOnce({
31-
[checks.readAllUsers]: false,
31+
[checks.updateUsers]: false,
3232
})
3333
renderWithAuth(<Navbar />)
3434

site/src/components/Navbar/Navbar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export const Navbar: React.FC = () => {
1111
const permissions = useSelector(xServices.authXService, selectPermissions)
1212
// When we have more options in the admin dropdown we may want to check this
1313
// for more permissions
14-
const displayAdminDropdown = !!permissions?.readAllUsers
14+
const displayAdminDropdown = !!permissions?.updateUsers
1515
const onSignOut = () => authSend("SIGN_OUT")
1616

1717
return <NavbarView user={me} onSignOut={onSignOut} displayAdminDropdown={displayAdminDropdown} />

site/src/components/UsersTable/UsersTable.stories.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@ export const Example = Template.bind({})
1414
Example.args = {
1515
users: [MockUser, MockUser2],
1616
roles: MockSiteRoles,
17+
canEditUsers: false,
18+
}
19+
20+
export const Editable = Template.bind({})
21+
Editable.args = {
22+
users: [MockUser, MockUser2],
23+
roles: MockSiteRoles,
24+
canEditUsers: true,
1725
}
1826

1927
export const Empty = Template.bind({})

site/src/components/UsersTable/UsersTable.tsx

Lines changed: 38 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,8 @@ import React from "react"
88
import * as TypesGen from "../../api/typesGenerated"
99
import { EmptyState } from "../EmptyState/EmptyState"
1010
import { RoleSelect } from "../RoleSelect/RoleSelect"
11-
import { TableHeaderRow } from "../TableHeaders/TableHeaders"
1211
import { TableLoader } from "../TableLoader/TableLoader"
1312
import { TableRowMenu } from "../TableRowMenu/TableRowMenu"
14-
import { TableTitle } from "../TableTitle/TableTitle"
1513
import { UserCell } from "../UserCell/UserCell"
1614

1715
export const Language = {
@@ -28,6 +26,8 @@ export interface UsersTableProps {
2826
users?: TypesGen.User[]
2927
roles?: TypesGen.Role[]
3028
isUpdatingUserRoles?: boolean
29+
canEditUsers?: boolean
30+
isLoading?: boolean
3131
onSuspendUser: (user: TypesGen.User) => void
3232
onResetUserPassword: (user: TypesGen.User) => void
3333
onUpdateUserRoles: (user: TypesGen.User, roles: TypesGen.Role["name"][]) => void
@@ -40,52 +40,57 @@ export const UsersTable: React.FC<UsersTableProps> = ({
4040
onResetUserPassword,
4141
onUpdateUserRoles,
4242
isUpdatingUserRoles,
43+
canEditUsers,
44+
isLoading,
4345
}) => {
44-
const isLoading = !users || !roles
45-
4646
return (
4747
<Table>
4848
<TableHead>
49-
<TableTitle title={Language.usersTitle} />
50-
<TableHeaderRow>
51-
<TableCell size="small">{Language.usernameLabel}</TableCell>
52-
<TableCell size="small">{Language.rolesLabel}</TableCell>
49+
<TableRow>
50+
<TableCell>{Language.usernameLabel}</TableCell>
51+
<TableCell>{Language.rolesLabel}</TableCell>
5352
{/* 1% is a trick to make the table cell width fit the content */}
54-
<TableCell size="small" width="1%" />
55-
</TableHeaderRow>
53+
{canEditUsers && <TableCell width="1%" />}
54+
</TableRow>
5655
</TableHead>
5756
<TableBody>
5857
{isLoading && <TableLoader />}
59-
{users &&
60-
roles &&
58+
{!isLoading &&
59+
users &&
6160
users.map((u) => (
6261
<TableRow key={u.id}>
6362
<TableCell>
6463
<UserCell Avatar={{ username: u.username }} primaryText={u.username} caption={u.email} />{" "}
6564
</TableCell>
6665
<TableCell>
67-
<RoleSelect
68-
roles={roles}
69-
selectedRoles={u.roles}
70-
loading={isUpdatingUserRoles}
71-
onChange={(roles) => onUpdateUserRoles(u, roles)}
72-
/>
73-
</TableCell>
74-
<TableCell>
75-
<TableRowMenu
76-
data={u}
77-
menuItems={[
78-
{
79-
label: Language.suspendMenuItem,
80-
onClick: onSuspendUser,
81-
},
82-
{
83-
label: Language.resetPasswordMenuItem,
84-
onClick: onResetUserPassword,
85-
},
86-
]}
87-
/>
66+
{canEditUsers ? (
67+
<RoleSelect
68+
roles={roles ?? []}
69+
selectedRoles={u.roles}
70+
loading={isUpdatingUserRoles}
71+
onChange={(roles) => onUpdateUserRoles(u, roles)}
72+
/>
73+
) : (
74+
<>{u.roles.map((r) => r.display_name).join(", ")}</>
75+
)}
8876
</TableCell>
77+
{canEditUsers && (
78+
<TableCell>
79+
<TableRowMenu
80+
data={u}
81+
menuItems={[
82+
{
83+
label: Language.suspendMenuItem,
84+
onClick: onSuspendUser,
85+
},
86+
{
87+
label: Language.resetPasswordMenuItem,
88+
onClick: onResetUserPassword,
89+
},
90+
]}
91+
/>
92+
</TableCell>
93+
)}
8994
</TableRow>
9095
))}
9196

site/src/pages/TemplatesPage/TemplatesPageView.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ export const TemplatesPageView: React.FC<TemplatesPageViewProps> = (props) => {
9292

9393
<TableCell>{Language.developerCount(template.workspace_owner_count)}</TableCell>
9494

95-
<TableCell>{dayjs().to(dayjs(template.updated_at))}</TableCell>
95+
<TableCell data-chromatic="ignore">{dayjs().to(dayjs(template.updated_at))}</TableCell>
9696
</TableRow>
9797
))}
9898
</TableBody>

site/src/pages/UsersPage/UsersPage.tsx

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import { useActor } from "@xstate/react"
1+
import { useActor, useSelector } from "@xstate/react"
22
import React, { useContext, useEffect } from "react"
33
import { useNavigate } from "react-router"
44
import { ConfirmDialog } from "../../components/ConfirmDialog/ConfirmDialog"
55
import { ResetPasswordDialog } from "../../components/ResetPasswordDialog/ResetPasswordDialog"
6+
import { selectPermissions } from "../../xServices/auth/authSelectors"
67
import { XServiceContext } from "../../xServices/StateContext"
78
import { UsersPageView } from "./UsersPageView"
89

@@ -12,39 +13,38 @@ export const Language = {
1213
suspendDialogMessagePrefix: "Do you want to suspend the user",
1314
}
1415

15-
const useRoles = () => {
16-
const xServices = useContext(XServiceContext)
17-
const [rolesState, rolesSend] = useActor(xServices.siteRolesXService)
18-
const { roles } = rolesState.context
19-
20-
/**
21-
* Fetch roles on component mount
22-
*/
23-
useEffect(() => {
24-
rolesSend({
25-
type: "GET_ROLES",
26-
})
27-
}, [rolesSend])
28-
29-
return roles
30-
}
31-
3216
export const UsersPage: React.FC = () => {
3317
const xServices = useContext(XServiceContext)
3418
const [usersState, usersSend] = useActor(xServices.usersXService)
19+
const [rolesState, rolesSend] = useActor(xServices.siteRolesXService)
3520
const { users, getUsersError, userIdToSuspend, userIdToResetPassword, newUserPassword } = usersState.context
3621
const navigate = useNavigate()
3722
const userToBeSuspended = users?.find((u) => u.id === userIdToSuspend)
3823
const userToResetPassword = users?.find((u) => u.id === userIdToResetPassword)
39-
const roles = useRoles()
24+
const permissions = useSelector(xServices.authXService, selectPermissions)
25+
const canEditUsers = permissions && permissions.updateUsers
26+
const { roles } = rolesState.context
27+
// Is loading if
28+
// - permissions are not loaded or
29+
// - users are not loaded or
30+
// - the user can edit the users but the roles are not loaded yet
31+
const isLoading = !permissions || !users || (canEditUsers && !roles)
4032

41-
/**
42-
* Fetch users on component mount
43-
*/
33+
// Fetch users on component mount
4434
useEffect(() => {
4535
usersSend("GET_USERS")
4636
}, [usersSend])
4737

38+
// Fetch roles on component mount
39+
useEffect(() => {
40+
// Only fetch the roles if the user has permission for it
41+
if (canEditUsers) {
42+
rolesSend({
43+
type: "GET_ROLES",
44+
})
45+
}
46+
}, [canEditUsers, rolesSend])
47+
4848
return (
4949
<>
5050
<UsersPageView
@@ -68,6 +68,8 @@ export const UsersPage: React.FC = () => {
6868
}}
6969
error={getUsersError}
7070
isUpdatingUserRoles={usersState.matches("updatingUserRoles")}
71+
isLoading={isLoading}
72+
canEditUsers={canEditUsers}
7173
/>
7274

7375
<ConfirmDialog

site/src/pages/UsersPage/UsersPageView.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ export interface UsersPageViewProps {
1616
roles?: TypesGen.Role[]
1717
error?: unknown
1818
isUpdatingUserRoles?: boolean
19+
canEditUsers?: boolean
20+
isLoading?: boolean
1921
openUserCreationDialog: () => void
2022
onSuspendUser: (user: TypesGen.User) => void
2123
onResetUserPassword: (user: TypesGen.User) => void
@@ -31,6 +33,8 @@ export const UsersPageView: React.FC<UsersPageViewProps> = ({
3133
onUpdateUserRoles,
3234
error,
3335
isUpdatingUserRoles,
36+
canEditUsers,
37+
isLoading,
3438
}) => {
3539
return (
3640
<Stack spacing={4}>
@@ -46,6 +50,8 @@ export const UsersPageView: React.FC<UsersPageViewProps> = ({
4650
onResetUserPassword={onResetUserPassword}
4751
onUpdateUserRoles={onUpdateUserRoles}
4852
isUpdatingUserRoles={isUpdatingUserRoles}
53+
canEditUsers={canEditUsers}
54+
isLoading={isLoading}
4955
/>
5056
)}
5157
</Margins>

0 commit comments

Comments
 (0)