mirror of
https://github.com/coder/coder.git
synced 2026-09-22 13:10:21 +08:00
refactor: Load users from the API (#1218)
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
import axios, { AxiosRequestHeaders } from "axios"
|
||||
import { mutate } from "swr"
|
||||
import { MockPager, MockUser, MockUser2 } from "../testHelpers/entities"
|
||||
import * as Types from "./types"
|
||||
import * as TypesGen from "./typesGenerated"
|
||||
|
||||
@@ -76,13 +75,9 @@ export const getApiKey = async (): Promise<Types.APIKeyResponse> => {
|
||||
return response.data
|
||||
}
|
||||
|
||||
export const getUsers = async (): Promise<Types.PagedUsers> => {
|
||||
// const response = await axios.get<Types.UserResponse[]>("/api/v2/users")
|
||||
// return response.data
|
||||
return Promise.resolve({
|
||||
page: [MockUser, MockUser2],
|
||||
pager: MockPager,
|
||||
})
|
||||
export const getUsers = async (): Promise<TypesGen.User[]> => {
|
||||
const response = await axios.get<TypesGen.User[]>("/api/v2/users?offset=0&limit=1000")
|
||||
return response.data
|
||||
}
|
||||
|
||||
export const createUser = async (user: Types.CreateUserRequest): Promise<TypesGen.User> => {
|
||||
|
||||
@@ -88,15 +88,6 @@ export interface UserAgent {
|
||||
readonly os: string
|
||||
}
|
||||
|
||||
export interface Pager {
|
||||
total: number
|
||||
}
|
||||
|
||||
export interface PagedUsers {
|
||||
page: UserResponse[]
|
||||
pager: Pager
|
||||
}
|
||||
|
||||
export interface WorkspaceAutostartRequest {
|
||||
schedule: string
|
||||
}
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
import { screen } from "@testing-library/react"
|
||||
import React from "react"
|
||||
import { MockPager, render } from "../../testHelpers"
|
||||
import { render } from "../../testHelpers"
|
||||
import { UsersPage } from "./UsersPage"
|
||||
import { Language } from "./UsersPageView"
|
||||
|
||||
describe("Users Page", () => {
|
||||
it("has a header with the total number of users", async () => {
|
||||
render(<UsersPage />)
|
||||
const total = await screen.findByText(/\d+ total/)
|
||||
expect(total.innerHTML).toEqual(Language.pageSubtitle(MockPager))
|
||||
})
|
||||
it("shows users", async () => {
|
||||
render(<UsersPage />)
|
||||
const users = await screen.findAllByText(/.*@coder.com/)
|
||||
|
||||
@@ -2,13 +2,14 @@ import { useActor } from "@xstate/react"
|
||||
import React, { useContext, useEffect } from "react"
|
||||
import { useNavigate } from "react-router"
|
||||
import { ErrorSummary } from "../../components/ErrorSummary/ErrorSummary"
|
||||
import { FullScreenLoader } from "../../components/Loader/FullScreenLoader"
|
||||
import { XServiceContext } from "../../xServices/StateContext"
|
||||
import { UsersPageView } from "./UsersPageView"
|
||||
|
||||
export const UsersPage: React.FC = () => {
|
||||
const xServices = useContext(XServiceContext)
|
||||
const [usersState, usersSend] = useActor(xServices.usersXService)
|
||||
const { users, pager, getUsersError } = usersState.context
|
||||
const { users, getUsersError } = usersState.context
|
||||
const navigate = useNavigate()
|
||||
|
||||
/**
|
||||
@@ -20,11 +21,14 @@ export const UsersPage: React.FC = () => {
|
||||
|
||||
if (usersState.matches("error")) {
|
||||
return <ErrorSummary error={getUsersError} />
|
||||
}
|
||||
|
||||
if (!users) {
|
||||
return <FullScreenLoader />
|
||||
} else {
|
||||
return (
|
||||
<UsersPageView
|
||||
users={users}
|
||||
pager={pager}
|
||||
openUserCreationDialog={() => {
|
||||
navigate("/users/create")
|
||||
}}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ComponentMeta, Story } from "@storybook/react"
|
||||
import React from "react"
|
||||
import { MockPager, MockUser, MockUser2 } from "../../testHelpers"
|
||||
import { MockUser, MockUser2 } from "../../testHelpers"
|
||||
import { UsersPageView, UsersPageViewProps } from "./UsersPageView"
|
||||
|
||||
export default {
|
||||
@@ -13,7 +13,6 @@ const Template: Story<UsersPageViewProps> = (args) => <UsersPageView {...args} /
|
||||
export const Ready = Template.bind({})
|
||||
Ready.args = {
|
||||
users: [MockUser, MockUser2],
|
||||
pager: MockPager,
|
||||
}
|
||||
export const Empty = Template.bind({})
|
||||
Empty.args = {
|
||||
|
||||
@@ -1,32 +1,29 @@
|
||||
import Paper from "@material-ui/core/Paper"
|
||||
import { makeStyles } from "@material-ui/core/styles"
|
||||
import React from "react"
|
||||
import { Pager, UserResponse } from "../../api/types"
|
||||
import { UserResponse } from "../../api/types"
|
||||
import { Header } from "../../components/Header/Header"
|
||||
import { UsersTable } from "../../components/UsersTable/UsersTable"
|
||||
|
||||
export const Language = {
|
||||
pageTitle: "Users",
|
||||
pageSubtitle: (pager: Pager | undefined): string => (pager ? `${pager.total} total` : ""),
|
||||
newUserButton: "New User",
|
||||
}
|
||||
|
||||
export interface UsersPageViewProps {
|
||||
users: UserResponse[]
|
||||
pager?: Pager
|
||||
openUserCreationDialog: () => void
|
||||
}
|
||||
|
||||
export const UsersPageView: React.FC<UsersPageViewProps> = ({ users, pager, openUserCreationDialog }) => {
|
||||
export const UsersPageView: React.FC<UsersPageViewProps> = ({ users, openUserCreationDialog }) => {
|
||||
const styles = useStyles()
|
||||
|
||||
return (
|
||||
<div className={styles.flexColumn}>
|
||||
<Header
|
||||
title={Language.pageTitle}
|
||||
subTitle={Language.pageSubtitle(pager)}
|
||||
action={{ text: Language.newUserButton, onClick: openUserCreationDialog }}
|
||||
/>
|
||||
<UsersTable users={users} />
|
||||
<Header title={Language.pageTitle} action={{ text: Language.newUserButton, onClick: openUserCreationDialog }} />
|
||||
<Paper style={{ maxWidth: "1380px", margin: "1em auto", width: "100%" }}>
|
||||
<UsersTable users={users} />
|
||||
</Paper>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {
|
||||
BuildInfoResponse,
|
||||
Organization,
|
||||
Pager,
|
||||
Provisioner,
|
||||
Template,
|
||||
UserAgent,
|
||||
@@ -38,10 +37,6 @@ export const MockUser2: UserResponse = {
|
||||
organization_ids: ["fc0774ce-cc9e-48d4-80ae-88f7a4d4a8b0"],
|
||||
}
|
||||
|
||||
export const MockPager: Pager = {
|
||||
total: 2,
|
||||
}
|
||||
|
||||
export const MockOrganization: Organization = {
|
||||
id: "test-org",
|
||||
name: "Test Organization",
|
||||
|
||||
@@ -22,7 +22,7 @@ export const handlers = [
|
||||
|
||||
// users
|
||||
rest.get("/api/v2/users", async (req, res, ctx) => {
|
||||
return res(ctx.status(200), ctx.json({ page: [M.MockUser, M.MockUser2], pager: M.MockPager }))
|
||||
return res(ctx.status(200), ctx.json([M.MockUser, M.MockUser2]))
|
||||
}),
|
||||
rest.post("/api/v2/users", async (req, res, ctx) => {
|
||||
return res(ctx.status(200), ctx.json(M.MockUser))
|
||||
|
||||
@@ -10,8 +10,7 @@ export const Language = {
|
||||
}
|
||||
|
||||
export interface UsersContext {
|
||||
users: Types.UserResponse[]
|
||||
pager?: Types.Pager
|
||||
users?: TypesGen.User[]
|
||||
getUsersError?: Error | unknown
|
||||
createUserError?: Error | unknown
|
||||
createUserFormErrors?: FieldErrors
|
||||
@@ -27,7 +26,7 @@ export const usersMachine = createMachine(
|
||||
events: {} as UsersEvent,
|
||||
services: {} as {
|
||||
getUsers: {
|
||||
data: Types.PagedUsers
|
||||
data: TypesGen.User[]
|
||||
}
|
||||
createUser: {
|
||||
data: TypesGen.User
|
||||
@@ -104,8 +103,7 @@ export const usersMachine = createMachine(
|
||||
},
|
||||
actions: {
|
||||
assignUsers: assign({
|
||||
users: (_, event) => event.data.page,
|
||||
pager: (_, event) => event.data.pager,
|
||||
users: (_, event) => event.data,
|
||||
}),
|
||||
assignGetUsersError: assign({
|
||||
getUsersError: (_, event) => event.data,
|
||||
|
||||
Reference in New Issue
Block a user