Skip to content

Commit cf8442f

Browse files
committed
Switch to using creation mode in XState
still problems in tests
1 parent 30b8799 commit cf8442f

File tree

5 files changed

+54
-40
lines changed

5 files changed

+54
-40
lines changed
Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { useActor } from "@xstate/react"
22
import React, { useContext } from "react"
3-
import { useNavigate } from "react-router"
3+
import { Navigate } from "react-router"
44
import { CreateUserRequest } from "../../../api/typesGenerated"
55
import { CreateUserForm } from "../../../components/CreateUserForm/CreateUserForm"
66
import { XServiceContext } from "../../../xServices/StateContext"
@@ -13,17 +13,19 @@ export const CreateUserPage = () => {
1313
const xServices = useContext(XServiceContext)
1414
const [usersState, usersSend] = useActor(xServices.usersXService)
1515
const { createUserError, createUserFormErrors } = usersState.context
16-
const navigate = useNavigate()
1716
// There is no field for organization id in Community Edition, so handle its field error like a generic error
18-
const genericError = (createUserError || createUserFormErrors?.organization_id) ? Language.unknownError : undefined
17+
const genericError = createUserError || createUserFormErrors?.organization_id ? Language.unknownError : undefined
1918

20-
return (
21-
<CreateUserForm
19+
if (usersState.matches("creationMode")){
20+
return <CreateUserForm
2221
formErrors={createUserFormErrors}
2322
onSubmit={(user: CreateUserRequest) => usersSend({ type: "CREATE", user })}
24-
onCancel={() => navigate("/users")}
23+
onCancel={() => {usersSend("EXIT_CREATION_MODE")}}
2524
isLoading={usersState.hasTag("loading")}
2625
error={genericError}
2726
/>
28-
)
27+
} else {
28+
// on cancel or success, redirect
29+
return <Navigate to="/users"/>
30+
}
2931
}

site/src/pages/UsersPage/UsersPage.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { useActor } from "@xstate/react"
22
import React, { useContext, useEffect } from "react"
3-
import { useNavigate } from "react-router"
3+
import { Navigate } from "react-router"
44
import { ErrorSummary } from "../../components/ErrorSummary/ErrorSummary"
55
import { XServiceContext } from "../../xServices/StateContext"
66
import { UsersPageView } from "./UsersPageView"
@@ -9,7 +9,6 @@ export const UsersPage: React.FC = () => {
99
const xServices = useContext(XServiceContext)
1010
const [usersState, usersSend] = useActor(xServices.usersXService)
1111
const { users, pager, getUsersError } = usersState.context
12-
const navigate = useNavigate()
1312

1413
/**
1514
* Fetch users on component mount
@@ -20,13 +19,16 @@ export const UsersPage: React.FC = () => {
2019

2120
if (usersState.matches("error")) {
2221
return <ErrorSummary error={getUsersError} />
22+
} else if (usersState.matches("creationMode")) {
23+
console.log("loop")
24+
return <Navigate to="/users/create" />
2325
} else {
2426
return (
2527
<UsersPageView
2628
users={users}
2729
pager={pager}
2830
openUserCreationDialog={() => {
29-
navigate("/users/create")
31+
usersSend("ENTER_CREATION_MODE")
3032
}}
3133
/>
3234
)

site/src/testHelpers/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { render as wrappedRender, RenderResult } from "@testing-library/react"
33
import { createMemoryHistory } from "history"
44
import React from "react"
55
import { MemoryRouter, Route, Routes, unstable_HistoryRouter as HistoryRouter } from "react-router-dom"
6+
import { AppRouter } from "../AppRouter"
67
import { RequireAuth } from "../components/RequireAuth/RequireAuth"
78
import { dark } from "../theme"
89
import { XServiceProvider } from "../xServices/StateContext"

site/src/xServices/StateContext.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { useInterpret } from "@xstate/react"
22
import React, { createContext } from "react"
3-
import { useNavigate } from "react-router"
43
import { ActorRefFrom } from "xstate"
54
import { authMachine } from "./auth/authXService"
65
import { buildInfoMachine } from "./buildInfo/buildInfoXService"
@@ -23,13 +22,12 @@ interface XServiceContextType {
2322
export const XServiceContext = createContext({} as XServiceContextType)
2423

2524
export const XServiceProvider: React.FC = ({ children }) => {
26-
const navigate = useNavigate()
2725
return (
2826
<XServiceContext.Provider
2927
value={{
3028
authXService: useInterpret(authMachine),
3129
buildInfoXService: useInterpret(buildInfoMachine),
32-
usersXService: useInterpret(usersMachine.withContext({ users: [], navigate })),
30+
usersXService: useInterpret(usersMachine)
3331
}}
3432
>
3533
{children}

site/src/xServices/users/usersXService.ts

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { NavigateFunction } from "react-router"
21
import { assign, createMachine } from "xstate"
32
import * as API from "../../api"
43
import { ApiError, FieldErrors, isApiError, mapApiErrorToFieldErrors } from "../../api/errors"
@@ -16,10 +15,13 @@ export interface UsersContext {
1615
getUsersError?: Error | unknown
1716
createUserError?: Error | unknown
1817
createUserFormErrors?: FieldErrors
19-
navigate?: NavigateFunction
2018
}
2119

22-
export type UsersEvent = { type: "GET_USERS" } | { type: "CREATE"; user: TypesGen.CreateUserRequest }
20+
export type UsersEvent =
21+
| { type: "GET_USERS" }
22+
| { type: "ENTER_CREATION_MODE" }
23+
| { type: "EXIT_CREATION_MODE" }
24+
| { type: "CREATE"; user: TypesGen.CreateUserRequest }
2325

2426
export const usersMachine = createMachine(
2527
{
@@ -45,7 +47,7 @@ export const usersMachine = createMachine(
4547
idle: {
4648
on: {
4749
GET_USERS: "gettingUsers",
48-
CREATE: "creatingUser",
50+
ENTER_CREATION_MODE: "creationMode",
4951
},
5052
},
5153
gettingUsers: {
@@ -67,28 +69,40 @@ export const usersMachine = createMachine(
6769
},
6870
tags: "loading",
6971
},
70-
creatingUser: {
71-
invoke: {
72-
src: "createUser",
73-
id: "createUser",
74-
onDone: {
75-
target: "idle",
76-
actions: ["displayCreateUserSuccess", "redirectToUsersPage", "clearCreateUserError"],
77-
},
78-
onError: [
79-
{
80-
target: "idle",
81-
cond: "isFormError",
82-
actions: ["assignCreateUserFormErrors"],
72+
creationMode: {
73+
initial: "idle",
74+
states: {
75+
idle: {
76+
on: {
77+
CREATE: "creatingUser",
78+
EXIT_CREATION_MODE: "#usersState.idle"
8379
},
84-
{
85-
target: "idle",
86-
actions: ["assignCreateUserError"],
80+
},
81+
creatingUser: {
82+
invoke: {
83+
src: "createUser",
84+
id: "createUser",
85+
onDone: {
86+
target: "#usersState.idle",
87+
actions: ["displayCreateUserSuccess", "clearCreateUserError"],
88+
},
89+
onError: [
90+
{
91+
target: "idle",
92+
cond: "isFormError",
93+
actions: ["assignCreateUserFormErrors"],
94+
},
95+
{
96+
target: "idle",
97+
actions: ["assignCreateUserError"],
98+
},
99+
],
87100
},
88-
],
101+
tags: "loading",
102+
},
89103
},
90-
tags: "loading",
91104
},
105+
92106
error: {
93107
on: {
94108
GET_USERS: "gettingUsers",
@@ -102,7 +116,7 @@ export const usersMachine = createMachine(
102116
createUser: (_, event) => API.createUser(event.user),
103117
},
104118
guards: {
105-
isFormError: (_, event) => isApiError(event.data)
119+
isFormError: (_, event) => isApiError(event.data),
106120
},
107121
actions: {
108122
assignUsers: assign({
@@ -121,7 +135,7 @@ export const usersMachine = createMachine(
121135
}),
122136
assignCreateUserFormErrors: assign({
123137
// the guard ensures it is ApiError
124-
createUserFormErrors: (_, event) => mapApiErrorToFieldErrors((event.data as ApiError).response.data)
138+
createUserFormErrors: (_, event) => mapApiErrorToFieldErrors((event.data as ApiError).response.data),
125139
}),
126140
clearCreateUserError: assign((context: UsersContext) => ({
127141
...context,
@@ -130,9 +144,6 @@ export const usersMachine = createMachine(
130144
displayCreateUserSuccess: () => {
131145
displaySuccess(Language.createUserSuccess)
132146
},
133-
redirectToUsersPage: (context) => {
134-
context.navigate && context.navigate("/users")
135-
},
136147
},
137148
},
138149
)

0 commit comments

Comments
 (0)