add API call, disable create button if username field empty

This commit is contained in:
jenny-s51 2021-03-03 16:17:01 -05:00
parent 3b9edc483a
commit 117ccf05b0
3 changed files with 49 additions and 18 deletions

View file

@ -21,7 +21,10 @@ export type UserFormProps = {
save: (user: UserRepresentation) => void; save: (user: UserRepresentation) => void;
}; };
export const UserForm = ({ form, save }: UserFormProps) => { export const UserForm = ({
form: { handleSubmit, register, errors, watch, control },
save,
}: UserFormProps) => {
const { t } = useTranslation("users"); const { t } = useTranslation("users");
const { realm } = useRealm(); const { realm } = useRealm();
@ -32,6 +35,8 @@ export const UserForm = ({ form, save }: UserFormProps) => {
const [selected, setSelected] = useState<string[]>([]); const [selected, setSelected] = useState<string[]>([]);
const history = useHistory(); const history = useHistory();
const watchUsernameInput = watch("username");
const requiredUserActionsOptions = [ const requiredUserActionsOptions = [
<SelectOption key={0} value="Configure OTP"> <SelectOption key={0} value="Configure OTP">
{t("configureOTP")} {t("configureOTP")}
@ -58,7 +63,7 @@ export const UserForm = ({ form, save }: UserFormProps) => {
return ( return (
<FormAccess <FormAccess
isHorizontal isHorizontal
onSubmit={form.handleSubmit(save)} onSubmit={handleSubmit(save)}
role="manage-users" role="manage-users"
className="pf-u-mt-lg" className="pf-u-mt-lg"
> >
@ -66,24 +71,25 @@ export const UserForm = ({ form, save }: UserFormProps) => {
label={t("username")} label={t("username")}
fieldId="kc-username" fieldId="kc-username"
isRequired isRequired
validated={form.errors.username ? "error" : "default"} validated={errors.username ? "error" : "default"}
helperTextInvalid={t("common:required")} helperTextInvalid={t("common:required")}
> >
<TextInput <TextInput
ref={form.register()} ref={register({ required: true })}
type="text" type="text"
id="kc-username" id="kc-username"
name="username" name="username"
/> />
</FormGroup> </FormGroup>
<FormGroup <FormGroup
label={t("email")} label={t("email")}
fieldId="kc-description" fieldId="kc-description"
validated={form.errors.email ? "error" : "default"} validated={errors.email ? "error" : "default"}
helperTextInvalid={form.errors.email?.message} helperTextInvalid={errors.email?.message}
> >
<TextInput <TextInput
ref={form.register()} ref={register()}
type="text" type="text"
id="kc-email" id="kc-email"
name="email" name="email"
@ -105,7 +111,7 @@ export const UserForm = ({ form, save }: UserFormProps) => {
<Controller <Controller
name="user-email-verified" name="user-email-verified"
defaultValue={false} defaultValue={false}
control={form.control} control={control}
render={({ onChange, value }) => ( render={({ onChange, value }) => (
<Switch <Switch
id={"kc-user-email-verified"} id={"kc-user-email-verified"}
@ -121,11 +127,11 @@ export const UserForm = ({ form, save }: UserFormProps) => {
<FormGroup <FormGroup
label={t("firstName")} label={t("firstName")}
fieldId="kc-firstname" fieldId="kc-firstname"
validated={form.errors.firstName ? "error" : "default"} validated={errors.firstName ? "error" : "default"}
helperTextInvalid={t("common:required")} helperTextInvalid={t("common:required")}
> >
<TextInput <TextInput
ref={form.register()} ref={register()}
type="text" type="text"
id="kc-firstname" id="kc-firstname"
name="firstname" name="firstname"
@ -134,10 +140,10 @@ export const UserForm = ({ form, save }: UserFormProps) => {
<FormGroup <FormGroup
label={t("lastName")} label={t("lastName")}
fieldId="kc-name" fieldId="kc-name"
validated={form.errors.lastName ? "error" : "default"} validated={errors.lastName ? "error" : "default"}
> >
<TextInput <TextInput
ref={form.register()} ref={register()}
type="text" type="text"
id="kc-lastname" id="kc-lastname"
name="lastname" name="lastname"
@ -158,7 +164,7 @@ export const UserForm = ({ form, save }: UserFormProps) => {
<Controller <Controller
name="user-enabled" name="user-enabled"
defaultValue={false} defaultValue={false}
control={form.control} control={control}
render={({ onChange, value }) => ( render={({ onChange, value }) => (
<Switch <Switch
id={"kc-user-enabled"} id={"kc-user-enabled"}
@ -174,7 +180,7 @@ export const UserForm = ({ form, save }: UserFormProps) => {
<FormGroup <FormGroup
label={t("requiredUserActions")} label={t("requiredUserActions")}
fieldId="kc-required-user-actions" fieldId="kc-required-user-actions"
validated={form.errors.requiredActions ? "error" : "default"} validated={errors.requiredActions ? "error" : "default"}
helperTextInvalid={t("common:required")} helperTextInvalid={t("common:required")}
labelIcon={ labelIcon={
<HelpItem <HelpItem
@ -188,7 +194,7 @@ export const UserForm = ({ form, save }: UserFormProps) => {
name="required-user-actions" name="required-user-actions"
defaultValue={["0"]} defaultValue={["0"]}
typeAheadAriaLabel="Select an action" typeAheadAriaLabel="Select an action"
control={form.control} control={control}
render={() => ( render={() => (
<Select <Select
placeholderText="Select action" placeholderText="Select action"
@ -217,7 +223,11 @@ export const UserForm = ({ form, save }: UserFormProps) => {
></Controller> ></Controller>
</FormGroup> </FormGroup>
<ActionGroup> <ActionGroup>
<Button variant="primary" type="submit"> <Button
isDisabled={!watchUsernameInput}
variant="primary"
type="submit"
>
{t("common:Create")} {t("common:Create")}
</Button> </Button>
<Button <Button

View file

@ -1,15 +1,34 @@
import React from "react"; import React from "react";
import { PageSection } from "@patternfly/react-core"; import { AlertVariant, PageSection } from "@patternfly/react-core";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { ViewHeader } from "../components/view-header/ViewHeader"; import { ViewHeader } from "../components/view-header/ViewHeader";
import UserRepresentation from "keycloak-admin/lib/defs/userRepresentation"; import UserRepresentation from "keycloak-admin/lib/defs/userRepresentation";
import { UserForm } from "./UserForm"; import { UserForm } from "./UserForm";
import { useAlerts } from "../components/alert/Alerts";
import { useAdminClient } from "../context/auth/AdminClient";
export const UsersTabs = () => { export const UsersTabs = () => {
const { t } = useTranslation("roles"); const { t } = useTranslation("roles");
const form = useForm<UserRepresentation>({ mode: "onChange" }); const form = useForm<UserRepresentation>({ mode: "onChange" });
const { addAlert } = useAlerts();
const adminClient = useAdminClient();
const save = async (user: UserRepresentation) => {
try {
await adminClient.users.create({ username: user!.username });
addAlert(t("users:userCreated"), AlertVariant.success);
} catch (error) {
addAlert(
t("users:userCreateError", {
error: error.response.data?.errorMessage || error,
}),
AlertVariant.danger
);
}
};
return ( return (
<> <>
@ -19,7 +38,7 @@ export const UsersTabs = () => {
dividerComponent="div" dividerComponent="div"
/> />
<PageSection variant="light"> <PageSection variant="light">
<UserForm form={form} save={() => {}} /> <UserForm form={form} save={save} />
</PageSection> </PageSection>
</> </>
); );

View file

@ -26,6 +26,8 @@
"deleteConfirm": "Delete user?", "deleteConfirm": "Delete user?",
"deleteConfirmDialog": "Are you sure you want to permanently delete {{count}} selected user", "deleteConfirmDialog": "Are you sure you want to permanently delete {{count}} selected user",
"deleteConfirmDialog_plural": "Are you sure you want to permanently delete {{count}} selected users", "deleteConfirmDialog_plural": "Are you sure you want to permanently delete {{count}} selected users",
"userCreated": "The user has been created",
"userCreateError": "Could not create user: {{error}}",
"userDeletedSuccess": "The user has been deleted", "userDeletedSuccess": "The user has been deleted",
"userDeletedError": "The user could not be deleted {{error}}", "userDeletedError": "The user could not be deleted {{error}}",
"configureOTP": "Configure OTP", "configureOTP": "Configure OTP",