diff --git a/site/src/pages/UsersPage/CreateUserPage/CreateUserPage.tsx b/site/src/pages/UsersPage/CreateUserPage/CreateUserPage.tsx index 8b341aabdd..da4febd6df 100644 --- a/site/src/pages/UsersPage/CreateUserPage/CreateUserPage.tsx +++ b/site/src/pages/UsersPage/CreateUserPage/CreateUserPage.tsx @@ -1,7 +1,6 @@ import { useActor } from "@xstate/react" import React, { useContext } from "react" import { useNavigate } from "react-router" -import { isApiError, mapApiErrorToFieldErrors } from "../../../api/errors" import { CreateUserRequest } from "../../../api/typesGenerated" import { CreateUserForm } from "../../../components/CreateUserForm/CreateUserForm" import { XServiceContext } from "../../../xServices/StateContext" @@ -13,19 +12,18 @@ export const Language = { export const CreateUserPage = () => { const xServices = useContext(XServiceContext) const [usersState, usersSend] = useActor(xServices.usersXService) - const { createUserError } = usersState.context - const apiError = isApiError(createUserError) - const formErrors = apiError ? mapApiErrorToFieldErrors(createUserError.response.data) : undefined - const hasUnknownError = createUserError && !apiError + 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 return ( usersSend({ type: "CREATE", user })} onCancel={() => navigate("/users")} isLoading={usersState.hasTag("loading")} - error={hasUnknownError ? Language.unknownError : undefined} + error={genericError} /> ) } diff --git a/site/src/xServices/users/usersXService.ts b/site/src/xServices/users/usersXService.ts index 71c5129aff..7624250c19 100644 --- a/site/src/xServices/users/usersXService.ts +++ b/site/src/xServices/users/usersXService.ts @@ -1,6 +1,7 @@ import { NavigateFunction } from "react-router" import { assign, createMachine } from "xstate" import * as API from "../../api" +import { ApiError, FieldErrors, isApiError, mapApiErrorToFieldErrors } from "../../api/errors" import * as Types from "../../api/types" import * as TypesGen from "../../api/typesGenerated" import { displaySuccess } from "../../components/GlobalSnackbar/utils" @@ -14,6 +15,7 @@ export interface UsersContext { pager?: Types.Pager getUsersError?: Error | unknown createUserError?: Error | unknown + createUserFormErrors?: FieldErrors navigate?: NavigateFunction } @@ -73,10 +75,17 @@ export const usersMachine = createMachine( target: "idle", actions: ["displayCreateUserSuccess", "redirectToUsersPage", "clearCreateUserError"], }, - onError: { - target: "idle", - actions: ["assignCreateUserError"], - }, + onError: [ + { + target: "idle", + cond: "isFormError", + actions: ["assignCreateUserFormErrors"], + }, + { + target: "idle", + actions: ["assignCreateUserError"], + }, + ], }, tags: "loading", }, @@ -92,6 +101,9 @@ export const usersMachine = createMachine( getUsers: API.getUsers, createUser: (_, event) => API.createUser(event.user), }, + guards: { + isFormError: (_, event) => isApiError(event.data) + }, actions: { assignUsers: assign({ users: (_, event) => event.data.page, @@ -107,6 +119,10 @@ export const usersMachine = createMachine( assignCreateUserError: assign({ 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) => ({ ...context, createUserError: undefined, @@ -116,7 +132,7 @@ export const usersMachine = createMachine( }, redirectToUsersPage: (context) => { context.navigate && context.navigate("/users") - } + }, }, }, )