From 4aa97e680f6dd869fe301dd1c67f728589d9391b Mon Sep 17 00:00:00 2001 From: Presley Date: Mon, 25 Apr 2022 19:59:31 +0000 Subject: [PATCH] Handle api errors --- .../components/CreateUserForm/CreateUserForm.tsx | 12 +++++++----- .../UsersPage/CreateUserPage/CreateUserPage.tsx | 14 ++++++++++++-- site/src/xServices/users/usersXService.ts | 13 ++++++++++--- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/site/src/components/CreateUserForm/CreateUserForm.tsx b/site/src/components/CreateUserForm/CreateUserForm.tsx index 50d7fd9702..5e7d422fe2 100644 --- a/site/src/components/CreateUserForm/CreateUserForm.tsx +++ b/site/src/components/CreateUserForm/CreateUserForm.tsx @@ -1,6 +1,6 @@ import Button from "@material-ui/core/Button" import TextField from "@material-ui/core/TextField" -import { FormikContextType, useFormik } from "formik" +import { FormikContextType, FormikErrors, useFormik } from "formik" import React from "react" import * as Yup from "yup" import { CreateUserRequest } from "../../api/typesGenerated" @@ -22,6 +22,7 @@ const Language = { export interface CreateUserFormProps { onSubmit: (user: CreateUserRequest) => void onCancel: () => void + formErrors?: FormikErrors } const validationSchema = Yup.object({ @@ -30,7 +31,7 @@ const validationSchema = Yup.object({ username: Yup.string().required(), }) -export const CreateUserForm: React.FC = ({ onSubmit, onCancel }) => { +export const CreateUserForm: React.FC = ({ onSubmit, onCancel, formErrors }) => { const form: FormikContextType = useFormik({ initialValues: { email: "", @@ -40,11 +41,12 @@ export const CreateUserForm: React.FC = ({ onSubmit, onCanc validationSchema, onSubmit, }) + const getFieldHelpers = getFormHelpers(form, formErrors) return (
(form, "username")} + {...getFieldHelpers("username")} onChange={onChangeTrimmed(form)} autoFocus autoComplete="username" @@ -53,7 +55,7 @@ export const CreateUserForm: React.FC = ({ onSubmit, onCanc variant="outlined" /> (form, "email")} + {...getFieldHelpers("email")} onChange={onChangeTrimmed(form)} autoFocus autoComplete="email" @@ -62,7 +64,7 @@ export const CreateUserForm: React.FC = ({ onSubmit, onCanc variant="outlined" /> (form, "password")} + {...getFieldHelpers("password")} autoComplete="current-password" fullWidth id="password" diff --git a/site/src/pages/UsersPage/CreateUserPage/CreateUserPage.tsx b/site/src/pages/UsersPage/CreateUserPage/CreateUserPage.tsx index 57bdac412f..db376bb30d 100644 --- a/site/src/pages/UsersPage/CreateUserPage/CreateUserPage.tsx +++ b/site/src/pages/UsersPage/CreateUserPage/CreateUserPage.tsx @@ -1,14 +1,24 @@ 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" export const CreateUserPage = () => { const xServices = useContext(XServiceContext) - const [_, usersSend] = useActor(xServices.usersXService) + const [usersState, usersSend] = useActor(xServices.usersXService) + const { createUserError } = usersState.context + const formErrors = + createUserError && isApiError(createUserError) ? mapApiErrorToFieldErrors(createUserError.response.data) : undefined const navigate = useNavigate() - return usersSend({ type: "CREATE", user })} onCancel={() => navigate("/users")} /> + return ( + usersSend({ type: "CREATE", user })} + onCancel={() => navigate("/users")} + /> + ) } diff --git a/site/src/xServices/users/usersXService.ts b/site/src/xServices/users/usersXService.ts index ef6e0a1f2b..ce03056545 100644 --- a/site/src/xServices/users/usersXService.ts +++ b/site/src/xServices/users/usersXService.ts @@ -70,11 +70,11 @@ export const usersMachine = createMachine( id: "createUser", onDone: { target: "idle", - actions: "displayCreateUserSuccess", + actions: ["displayCreateUserSuccess", "clearCreateUserError"], }, onError: { target: "idle", - actions: "displayCreateUserError", + actions: ["assignCreateUserError", "displayCreateUserError"], }, }, tags: "loading", @@ -103,7 +103,14 @@ export const usersMachine = createMachine( ...context, getUsersError: undefined, })), - displayCreateUserError: () => { + assignCreateUserError: assign({ + createUserError: (_, event) => event.data + }), + clearCreateUserError: assign((context: UsersContext) => ({ + ...context, + createUserError: undefined + })), + displayCreateUserError: (_, event) => { displayError(Language.createUserError) }, displayCreateUserSuccess: () => {