ui(admin): add 'externalId' field for users

This commit is contained in:
Matthew Penner 2021-11-17 14:26:23 -07:00
parent 9c92d51e28
commit 81ff03c2a3
No known key found for this signature in database
GPG key ID: BAB67850901908A8
4 changed files with 63 additions and 42 deletions

View file

@ -2,6 +2,7 @@ import http from '@/api/http';
import { User, rawDataToUser } from '@/api/admin/users/getUsers'; import { User, rawDataToUser } from '@/api/admin/users/getUsers';
export interface Values { export interface Values {
externalId: string;
username: string; username: string;
email: string; email: string;
password: string; password: string;

View file

@ -39,6 +39,7 @@ const UserAboutContainer = () => {
<UserForm <UserForm
title={'Edit User'} title={'Edit User'}
initialValues={{ initialValues={{
externalId: user.externalId,
username: user.username, username: user.username,
email: user.email, email: user.email,
adminRoleId: user.adminRoleId, adminRoleId: user.adminRoleId,
@ -46,7 +47,8 @@ const UserAboutContainer = () => {
rootAdmin: user.rootAdmin, rootAdmin: user.rootAdmin,
}} }}
onSubmit={submit} onSubmit={submit}
role={user?.relationships.role || null} uuid={user.uuid}
role={user.relationships.role || null}
> >
<div css={tw`flex`}> <div css={tw`flex`}>
<UserDeleteButton <UserDeleteButton

View file

@ -1,4 +1,7 @@
import CopyOnClick from '@/components/elements/CopyOnClick';
import FormikSwitch from '@/components/elements/FormikSwitch'; import FormikSwitch from '@/components/elements/FormikSwitch';
import Input from '@/components/elements/Input';
import Label from '@/components/elements/Label';
import React from 'react'; import React from 'react';
import tw from 'twin.macro'; import tw from 'twin.macro';
import { action, Action, createContextStore } from 'easy-peasy'; import { action, Action, createContextStore } from 'easy-peasy';
@ -10,7 +13,7 @@ import { bool, object, string } from 'yup';
import { Role } from '@/api/admin/roles/getRoles'; import { Role } from '@/api/admin/roles/getRoles';
import { Values } from '@/api/admin/users/updateUser'; import { Values } from '@/api/admin/users/updateUser';
import Button from '@/components/elements/Button'; import Button from '@/components/elements/Button';
import Field from '@/components/elements/Field'; import Field, { FieldRow } from '@/components/elements/Field';
import RoleSelect from '@/components/admin/users/RoleSelect'; import RoleSelect from '@/components/admin/users/RoleSelect';
interface ctx { interface ctx {
@ -33,16 +36,18 @@ export interface Params {
onSubmit: (values: Values, helpers: FormikHelpers<Values>) => void; onSubmit: (values: Values, helpers: FormikHelpers<Values>) => void;
uuid?: string;
role: Role | null; role: Role | null;
} }
export default function UserForm ({ title, initialValues, children, onSubmit, role }: Params) { export default function UserForm ({ title, initialValues, children, onSubmit, uuid, role }: Params) {
const submit = (values: Values, helpers: FormikHelpers<Values>) => { const submit = (values: Values, helpers: FormikHelpers<Values>) => {
onSubmit(values, helpers); onSubmit(values, helpers);
}; };
if (!initialValues) { if (!initialValues) {
initialValues = { initialValues = {
externalId: '',
username: '', username: '',
email: '', email: '',
password: '', password: '',
@ -68,28 +73,40 @@ export default function UserForm ({ title, initialValues, children, onSubmit, ro
<SpinnerOverlay visible={isSubmitting}/> <SpinnerOverlay visible={isSubmitting}/>
<Form css={tw`mb-0`}> <Form css={tw`mb-0`}>
<div css={tw`md:w-full md:flex md:flex-row`}> <FieldRow>
<div css={tw`md:w-full md:flex md:flex-col md:mr-4 mt-6 md:mt-0`}> {uuid &&
<div>
<Label>UUID</Label>
<CopyOnClick text={uuid}>
<Input
type={'text'}
value={uuid}
readOnly
/>
</CopyOnClick>
</div>
}
<Field
id={'externalId'}
name={'externalId'}
label={'External ID'}
type={'text'}
description={'Used by external integrations, this field should not be modified unless you know what you are doing.'}
/>
<Field <Field
id={'username'} id={'username'}
name={'username'} name={'username'}
label={'Username'} label={'Username'}
type={'text'} type={'text'}
description={'The user\'s username, what else would go here?'}
/> />
</div>
<div css={tw`md:w-full md:flex md:flex-col md:ml-4 mt-6 md:mt-0`}>
<Field <Field
id={'email'} id={'email'}
name={'email'} name={'email'}
label={'Email Address'} label={'Email Address'}
type={'email'} type={'email'}
description={'The user\'s email address, what else would go here?'}
/> />
</div>
</div>
<div css={tw`md:w-full md:flex md:flex-row mt-6`}>
<div css={tw`md:w-full md:flex md:flex-col md:mr-4 mt-6 md:mt-0`}>
<Field <Field
id={'password'} id={'password'}
name={'password'} name={'password'}
@ -97,16 +114,15 @@ export default function UserForm ({ title, initialValues, children, onSubmit, ro
type={'password'} type={'password'}
placeholder={'••••••••'} placeholder={'••••••••'}
autoComplete={'new-password'} autoComplete={'new-password'}
/* TODO: Change description depending on if user is being created or updated. */
description={'Leave empty to email the user a link where they will be required to set a password.'}
/> />
</div>
<div css={tw`md:w-full md:flex md:flex-col md:ml-4 mt-6 md:mt-0`}>
<RoleSelect selected={role}/> <RoleSelect selected={role}/>
</div> </FieldRow>
</div>
{/* TODO: Remove toggle once role permissions are implemented. */}
<div css={tw`w-full flex flex-row mb-6`}> <div css={tw`w-full flex flex-row mb-6`}>
<div css={tw`w-full bg-neutral-800 border border-neutral-900 shadow-inner mt-6 p-4 rounded`}> <div css={tw`w-full bg-neutral-800 border border-neutral-900 shadow-inner p-4 rounded`}>
<FormikSwitch <FormikSwitch
name={'rootAdmin'} name={'rootAdmin'}
label={'Root Admin'} label={'Root Admin'}

View file

@ -245,9 +245,11 @@ export const SearchableSelect = <T extends IdObj>({ id, name, label, placeholder
return ( return (
<div className={className}> <div className={className}>
<div css={tw`flex flex-row`}>
<Label htmlFor={id + '-select-label'}>{label}</Label> <Label htmlFor={id + '-select-label'}>{label}</Label>
</div>
<div css={tw`relative mt-1`}> <div css={tw`relative`}>
<InputSpinner visible={loading}> <InputSpinner visible={loading}>
<Input <Input
ref={searchInput} ref={searchInput}