mirror of
https://github.com/coder/coder.git
synced 2025-07-12 00:14:10 +00:00
Switch to using creation mode in XState
still problems in tests
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
import { useActor } from "@xstate/react"
|
||||
import React, { useContext } from "react"
|
||||
import { useNavigate } from "react-router"
|
||||
import { Navigate } from "react-router"
|
||||
import { CreateUserRequest } from "../../../api/typesGenerated"
|
||||
import { CreateUserForm } from "../../../components/CreateUserForm/CreateUserForm"
|
||||
import { XServiceContext } from "../../../xServices/StateContext"
|
||||
@ -13,17 +13,19 @@ export const CreateUserPage = () => {
|
||||
const xServices = useContext(XServiceContext)
|
||||
const [usersState, usersSend] = useActor(xServices.usersXService)
|
||||
const { createUserError, createUserFormErrors } = usersState.context
|
||||
const navigate = useNavigate()
|
||||
// There is no field for organization id in Community Edition, so handle its field error like a generic error
|
||||
const genericError = (createUserError || createUserFormErrors?.organization_id) ? Language.unknownError : undefined
|
||||
const genericError = createUserError || createUserFormErrors?.organization_id ? Language.unknownError : undefined
|
||||
|
||||
return (
|
||||
<CreateUserForm
|
||||
if (usersState.matches("creationMode")){
|
||||
return <CreateUserForm
|
||||
formErrors={createUserFormErrors}
|
||||
onSubmit={(user: CreateUserRequest) => usersSend({ type: "CREATE", user })}
|
||||
onCancel={() => navigate("/users")}
|
||||
onCancel={() => {usersSend("EXIT_CREATION_MODE")}}
|
||||
isLoading={usersState.hasTag("loading")}
|
||||
error={genericError}
|
||||
/>
|
||||
)
|
||||
} else {
|
||||
// on cancel or success, redirect
|
||||
return <Navigate to="/users"/>
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useActor } from "@xstate/react"
|
||||
import React, { useContext, useEffect } from "react"
|
||||
import { useNavigate } from "react-router"
|
||||
import { Navigate } from "react-router"
|
||||
import { ErrorSummary } from "../../components/ErrorSummary/ErrorSummary"
|
||||
import { XServiceContext } from "../../xServices/StateContext"
|
||||
import { UsersPageView } from "./UsersPageView"
|
||||
@ -9,7 +9,6 @@ export const UsersPage: React.FC = () => {
|
||||
const xServices = useContext(XServiceContext)
|
||||
const [usersState, usersSend] = useActor(xServices.usersXService)
|
||||
const { users, pager, getUsersError } = usersState.context
|
||||
const navigate = useNavigate()
|
||||
|
||||
/**
|
||||
* Fetch users on component mount
|
||||
@ -20,13 +19,16 @@ export const UsersPage: React.FC = () => {
|
||||
|
||||
if (usersState.matches("error")) {
|
||||
return <ErrorSummary error={getUsersError} />
|
||||
} else if (usersState.matches("creationMode")) {
|
||||
console.log("loop")
|
||||
return <Navigate to="/users/create" />
|
||||
} else {
|
||||
return (
|
||||
<UsersPageView
|
||||
users={users}
|
||||
pager={pager}
|
||||
openUserCreationDialog={() => {
|
||||
navigate("/users/create")
|
||||
usersSend("ENTER_CREATION_MODE")
|
||||
}}
|
||||
/>
|
||||
)
|
||||
|
@ -3,6 +3,7 @@ import { render as wrappedRender, RenderResult } from "@testing-library/react"
|
||||
import { createMemoryHistory } from "history"
|
||||
import React from "react"
|
||||
import { MemoryRouter, Route, Routes, unstable_HistoryRouter as HistoryRouter } from "react-router-dom"
|
||||
import { AppRouter } from "../AppRouter"
|
||||
import { RequireAuth } from "../components/RequireAuth/RequireAuth"
|
||||
import { dark } from "../theme"
|
||||
import { XServiceProvider } from "../xServices/StateContext"
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { useInterpret } from "@xstate/react"
|
||||
import React, { createContext } from "react"
|
||||
import { useNavigate } from "react-router"
|
||||
import { ActorRefFrom } from "xstate"
|
||||
import { authMachine } from "./auth/authXService"
|
||||
import { buildInfoMachine } from "./buildInfo/buildInfoXService"
|
||||
@ -23,13 +22,12 @@ interface XServiceContextType {
|
||||
export const XServiceContext = createContext({} as XServiceContextType)
|
||||
|
||||
export const XServiceProvider: React.FC = ({ children }) => {
|
||||
const navigate = useNavigate()
|
||||
return (
|
||||
<XServiceContext.Provider
|
||||
value={{
|
||||
authXService: useInterpret(authMachine),
|
||||
buildInfoXService: useInterpret(buildInfoMachine),
|
||||
usersXService: useInterpret(usersMachine.withContext({ users: [], navigate })),
|
||||
usersXService: useInterpret(usersMachine)
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { NavigateFunction } from "react-router"
|
||||
import { assign, createMachine } from "xstate"
|
||||
import * as API from "../../api"
|
||||
import { ApiError, FieldErrors, isApiError, mapApiErrorToFieldErrors } from "../../api/errors"
|
||||
@ -16,10 +15,13 @@ export interface UsersContext {
|
||||
getUsersError?: Error | unknown
|
||||
createUserError?: Error | unknown
|
||||
createUserFormErrors?: FieldErrors
|
||||
navigate?: NavigateFunction
|
||||
}
|
||||
|
||||
export type UsersEvent = { type: "GET_USERS" } | { type: "CREATE"; user: TypesGen.CreateUserRequest }
|
||||
export type UsersEvent =
|
||||
| { type: "GET_USERS" }
|
||||
| { type: "ENTER_CREATION_MODE" }
|
||||
| { type: "EXIT_CREATION_MODE" }
|
||||
| { type: "CREATE"; user: TypesGen.CreateUserRequest }
|
||||
|
||||
export const usersMachine = createMachine(
|
||||
{
|
||||
@ -45,7 +47,7 @@ export const usersMachine = createMachine(
|
||||
idle: {
|
||||
on: {
|
||||
GET_USERS: "gettingUsers",
|
||||
CREATE: "creatingUser",
|
||||
ENTER_CREATION_MODE: "creationMode",
|
||||
},
|
||||
},
|
||||
gettingUsers: {
|
||||
@ -67,28 +69,40 @@ export const usersMachine = createMachine(
|
||||
},
|
||||
tags: "loading",
|
||||
},
|
||||
creatingUser: {
|
||||
invoke: {
|
||||
src: "createUser",
|
||||
id: "createUser",
|
||||
onDone: {
|
||||
target: "idle",
|
||||
actions: ["displayCreateUserSuccess", "redirectToUsersPage", "clearCreateUserError"],
|
||||
creationMode: {
|
||||
initial: "idle",
|
||||
states: {
|
||||
idle: {
|
||||
on: {
|
||||
CREATE: "creatingUser",
|
||||
EXIT_CREATION_MODE: "#usersState.idle"
|
||||
},
|
||||
},
|
||||
onError: [
|
||||
{
|
||||
target: "idle",
|
||||
cond: "isFormError",
|
||||
actions: ["assignCreateUserFormErrors"],
|
||||
creatingUser: {
|
||||
invoke: {
|
||||
src: "createUser",
|
||||
id: "createUser",
|
||||
onDone: {
|
||||
target: "#usersState.idle",
|
||||
actions: ["displayCreateUserSuccess", "clearCreateUserError"],
|
||||
},
|
||||
onError: [
|
||||
{
|
||||
target: "idle",
|
||||
cond: "isFormError",
|
||||
actions: ["assignCreateUserFormErrors"],
|
||||
},
|
||||
{
|
||||
target: "idle",
|
||||
actions: ["assignCreateUserError"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
target: "idle",
|
||||
actions: ["assignCreateUserError"],
|
||||
},
|
||||
],
|
||||
tags: "loading",
|
||||
},
|
||||
},
|
||||
tags: "loading",
|
||||
},
|
||||
|
||||
error: {
|
||||
on: {
|
||||
GET_USERS: "gettingUsers",
|
||||
@ -102,7 +116,7 @@ export const usersMachine = createMachine(
|
||||
createUser: (_, event) => API.createUser(event.user),
|
||||
},
|
||||
guards: {
|
||||
isFormError: (_, event) => isApiError(event.data)
|
||||
isFormError: (_, event) => isApiError(event.data),
|
||||
},
|
||||
actions: {
|
||||
assignUsers: assign({
|
||||
@ -121,7 +135,7 @@ export const usersMachine = createMachine(
|
||||
}),
|
||||
assignCreateUserFormErrors: assign({
|
||||
// the guard ensures it is ApiError
|
||||
createUserFormErrors: (_, event) => mapApiErrorToFieldErrors((event.data as ApiError).response.data)
|
||||
createUserFormErrors: (_, event) => mapApiErrorToFieldErrors((event.data as ApiError).response.data),
|
||||
}),
|
||||
clearCreateUserError: assign((context: UsersContext) => ({
|
||||
...context,
|
||||
@ -130,9 +144,6 @@ export const usersMachine = createMachine(
|
||||
displayCreateUserSuccess: () => {
|
||||
displaySuccess(Language.createUserSuccess)
|
||||
},
|
||||
redirectToUsersPage: (context) => {
|
||||
context.navigate && context.navigate("/users")
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
|
Reference in New Issue
Block a user