Move error type predicate to xservice

This commit is contained in:
Presley
2022-04-27 02:43:33 +00:00
parent 6a490c2ee6
commit 7d98c13175
2 changed files with 26 additions and 12 deletions

View File

@ -1,7 +1,6 @@
import { useActor } from "@xstate/react" import { useActor } from "@xstate/react"
import React, { useContext } from "react" import React, { useContext } from "react"
import { useNavigate } from "react-router" import { useNavigate } from "react-router"
import { isApiError, mapApiErrorToFieldErrors } from "../../../api/errors"
import { CreateUserRequest } from "../../../api/typesGenerated" import { CreateUserRequest } from "../../../api/typesGenerated"
import { CreateUserForm } from "../../../components/CreateUserForm/CreateUserForm" import { CreateUserForm } from "../../../components/CreateUserForm/CreateUserForm"
import { XServiceContext } from "../../../xServices/StateContext" import { XServiceContext } from "../../../xServices/StateContext"
@ -13,19 +12,18 @@ export const Language = {
export const CreateUserPage = () => { export const CreateUserPage = () => {
const xServices = useContext(XServiceContext) const xServices = useContext(XServiceContext)
const [usersState, usersSend] = useActor(xServices.usersXService) const [usersState, usersSend] = useActor(xServices.usersXService)
const { createUserError } = usersState.context const { createUserError, createUserFormErrors } = usersState.context
const apiError = isApiError(createUserError)
const formErrors = apiError ? mapApiErrorToFieldErrors(createUserError.response.data) : undefined
const hasUnknownError = createUserError && !apiError
const navigate = useNavigate() 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
return ( return (
<CreateUserForm <CreateUserForm
formErrors={formErrors} formErrors={createUserFormErrors}
onSubmit={(user: CreateUserRequest) => usersSend({ type: "CREATE", user })} onSubmit={(user: CreateUserRequest) => usersSend({ type: "CREATE", user })}
onCancel={() => navigate("/users")} onCancel={() => navigate("/users")}
isLoading={usersState.hasTag("loading")} isLoading={usersState.hasTag("loading")}
error={hasUnknownError ? Language.unknownError : undefined} error={genericError}
/> />
) )
} }

View File

@ -1,6 +1,7 @@
import { NavigateFunction } from "react-router" import { NavigateFunction } from "react-router"
import { assign, createMachine } from "xstate" import { assign, createMachine } from "xstate"
import * as API from "../../api" import * as API from "../../api"
import { ApiError, FieldErrors, isApiError, mapApiErrorToFieldErrors } from "../../api/errors"
import * as Types from "../../api/types" import * as Types from "../../api/types"
import * as TypesGen from "../../api/typesGenerated" import * as TypesGen from "../../api/typesGenerated"
import { displaySuccess } from "../../components/GlobalSnackbar/utils" import { displaySuccess } from "../../components/GlobalSnackbar/utils"
@ -14,6 +15,7 @@ export interface UsersContext {
pager?: Types.Pager pager?: Types.Pager
getUsersError?: Error | unknown getUsersError?: Error | unknown
createUserError?: Error | unknown createUserError?: Error | unknown
createUserFormErrors?: FieldErrors
navigate?: NavigateFunction navigate?: NavigateFunction
} }
@ -73,10 +75,17 @@ export const usersMachine = createMachine(
target: "idle", target: "idle",
actions: ["displayCreateUserSuccess", "redirectToUsersPage", "clearCreateUserError"], actions: ["displayCreateUserSuccess", "redirectToUsersPage", "clearCreateUserError"],
}, },
onError: { onError: [
target: "idle", {
actions: ["assignCreateUserError"], target: "idle",
}, cond: "isFormError",
actions: ["assignCreateUserFormErrors"],
},
{
target: "idle",
actions: ["assignCreateUserError"],
},
],
}, },
tags: "loading", tags: "loading",
}, },
@ -92,6 +101,9 @@ export const usersMachine = createMachine(
getUsers: API.getUsers, getUsers: API.getUsers,
createUser: (_, event) => API.createUser(event.user), createUser: (_, event) => API.createUser(event.user),
}, },
guards: {
isFormError: (_, event) => isApiError(event.data)
},
actions: { actions: {
assignUsers: assign({ assignUsers: assign({
users: (_, event) => event.data.page, users: (_, event) => event.data.page,
@ -107,6 +119,10 @@ export const usersMachine = createMachine(
assignCreateUserError: assign({ assignCreateUserError: assign({
createUserError: (_, event) => event.data, createUserError: (_, event) => event.data,
}), }),
assignCreateUserFormErrors: assign({
// the guard ensures it is ApiError
createUserFormErrors: (_, event) => mapApiErrorToFieldErrors((event.data as ApiError).response.data)
}),
clearCreateUserError: assign((context: UsersContext) => ({ clearCreateUserError: assign((context: UsersContext) => ({
...context, ...context,
createUserError: undefined, createUserError: undefined,
@ -116,7 +132,7 @@ export const usersMachine = createMachine(
}, },
redirectToUsersPage: (context) => { redirectToUsersPage: (context) => {
context.navigate && context.navigate("/users") context.navigate && context.navigate("/users")
} },
}, },
}, },
) )