fix(ui): Clean up manual add forms

This commit is contained in:
blessedcoolant 2023-03-19 19:09:22 +13:00 committed by psychedelicious
parent 5906888477
commit 2aefa06ef1
4 changed files with 250 additions and 221 deletions

View File

@ -333,6 +333,7 @@
"addNewModel": "Add New Model", "addNewModel": "Add New Model",
"addCheckpointModel": "Add Checkpoint / Safetensor Model", "addCheckpointModel": "Add Checkpoint / Safetensor Model",
"addDiffuserModel": "Add Diffusers", "addDiffuserModel": "Add Diffusers",
"scanForModels": "Scan For Models",
"addManually": "Add Manually", "addManually": "Add Manually",
"manual": "Manual", "manual": "Manual",
"name": "Name", "name": "Name",

View File

@ -0,0 +1,23 @@
import { Flex } from '@chakra-ui/react';
import { ReactElement } from 'react';
export function IAIFormItemWrapper({
children,
}: {
children: ReactElement | ReactElement[];
}) {
return (
<Flex
sx={{
flexDirection: 'column',
padding: 4,
rowGap: 4,
borderRadius: 'base',
width: 'full',
bg: 'base.900',
}}
>
{children}
</Flex>
);
}

View File

@ -1,4 +1,5 @@
import { import {
Flex,
FormControl, FormControl,
FormErrorMessage, FormErrorMessage,
FormHelperText, FormHelperText,
@ -28,6 +29,7 @@ import type { RootState } from 'app/store';
import { setAddNewModelUIOption } from 'features/ui/store/uiSlice'; import { setAddNewModelUIOption } from 'features/ui/store/uiSlice';
import type { FieldInputProps, FormikProps } from 'formik'; import type { FieldInputProps, FormikProps } from 'formik';
import IAIForm from 'common/components/IAIForm'; import IAIForm from 'common/components/IAIForm';
import { IAIFormItemWrapper } from 'common/components/IAIForms/IAIFormItemWrapper';
const MIN_MODEL_SIZE = 64; const MIN_MODEL_SIZE = 64;
const MAX_MODEL_SIZE = 2048; const MAX_MODEL_SIZE = 2048;
@ -71,14 +73,20 @@ export default function AddCheckpointModel() {
return ( return (
<VStack gap={2} alignItems="flex-start"> <VStack gap={2} alignItems="flex-start">
<SearchModels /> <Flex columnGap={4}>
<IAICheckbox <IAICheckbox
label={t('modelManager.addManually')} isChecked={!addManually}
isChecked={addManually} label={t('modelManager.scanForModels')}
onChange={() => setAddmanually(!addManually)} onChange={() => setAddmanually(!addManually)}
/> />
<IAICheckbox
label={t('modelManager.addManually')}
isChecked={addManually}
onChange={() => setAddmanually(!addManually)}
/>
</Flex>
{addManually && ( {addManually ? (
<Formik <Formik
initialValues={addModelFormValues} initialValues={addModelFormValues}
onSubmit={addModelFormSubmitHandler} onSubmit={addModelFormSubmitHandler}
@ -90,209 +98,225 @@ export default function AddCheckpointModel() {
{t('modelManager.manual')} {t('modelManager.manual')}
</Text> </Text>
{/* Name */} {/* Name */}
<FormControl <IAIFormItemWrapper>
isInvalid={!!errors.name && touched.name} <FormControl
isRequired isInvalid={!!errors.name && touched.name}
> isRequired
<FormLabel htmlFor="name" fontSize="sm"> >
{t('modelManager.name')} <FormLabel htmlFor="name" fontSize="sm">
</FormLabel> {t('modelManager.name')}
<VStack alignItems="start"> </FormLabel>
<Field <VStack alignItems="start">
as={IAIInput} <Field
id="name" as={IAIInput}
name="name" id="name"
type="text" name="name"
validate={baseValidation} type="text"
width="full" validate={baseValidation}
/> width="full"
{!!errors.name && touched.name ? ( />
<FormErrorMessage>{errors.name}</FormErrorMessage> {!!errors.name && touched.name ? (
) : ( <FormErrorMessage>{errors.name}</FormErrorMessage>
<FormHelperText margin={0}> ) : (
{t('modelManager.nameValidationMsg')} <FormHelperText margin={0}>
</FormHelperText> {t('modelManager.nameValidationMsg')}
)} </FormHelperText>
</VStack> )}
</FormControl> </VStack>
</FormControl>
</IAIFormItemWrapper>
{/* Description */} {/* Description */}
<FormControl <IAIFormItemWrapper>
isInvalid={!!errors.description && touched.description} <FormControl
isRequired isInvalid={!!errors.description && touched.description}
> isRequired
<FormLabel htmlFor="description" fontSize="sm"> >
{t('modelManager.description')} <FormLabel htmlFor="description" fontSize="sm">
</FormLabel> {t('modelManager.description')}
<VStack alignItems="start"> </FormLabel>
<Field <VStack alignItems="start">
as={IAIInput} <Field
id="description" as={IAIInput}
name="description" id="description"
type="text" name="description"
width="full" type="text"
/> width="full"
{!!errors.description && touched.description ? ( />
<FormErrorMessage>{errors.description}</FormErrorMessage> {!!errors.description && touched.description ? (
) : ( <FormErrorMessage>
<FormHelperText margin={0}> {errors.description}
{t('modelManager.descriptionValidationMsg')} </FormErrorMessage>
</FormHelperText> ) : (
)} <FormHelperText margin={0}>
</VStack> {t('modelManager.descriptionValidationMsg')}
</FormControl> </FormHelperText>
)}
</VStack>
</FormControl>
</IAIFormItemWrapper>
{/* Config */} {/* Config */}
<FormControl <IAIFormItemWrapper>
isInvalid={!!errors.config && touched.config} <FormControl
isRequired isInvalid={!!errors.config && touched.config}
> isRequired
<FormLabel htmlFor="config" fontSize="sm"> >
{t('modelManager.config')} <FormLabel htmlFor="config" fontSize="sm">
</FormLabel> {t('modelManager.config')}
<VStack alignItems="start"> </FormLabel>
<Field <VStack alignItems="start">
as={IAIInput} <Field
id="config" as={IAIInput}
name="config" id="config"
type="text" name="config"
width="full" type="text"
/> width="full"
{!!errors.config && touched.config ? ( />
<FormErrorMessage>{errors.config}</FormErrorMessage> {!!errors.config && touched.config ? (
) : ( <FormErrorMessage>{errors.config}</FormErrorMessage>
<FormHelperText margin={0}> ) : (
{t('modelManager.configValidationMsg')} <FormHelperText margin={0}>
</FormHelperText> {t('modelManager.configValidationMsg')}
)} </FormHelperText>
</VStack> )}
</FormControl> </VStack>
</FormControl>
</IAIFormItemWrapper>
{/* Weights */} {/* Weights */}
<FormControl <IAIFormItemWrapper>
isInvalid={!!errors.weights && touched.weights} <FormControl
isRequired isInvalid={!!errors.weights && touched.weights}
> isRequired
<FormLabel htmlFor="config" fontSize="sm"> >
{t('modelManager.modelLocation')} <FormLabel htmlFor="config" fontSize="sm">
</FormLabel> {t('modelManager.modelLocation')}
<VStack alignItems="start"> </FormLabel>
<Field <VStack alignItems="start">
as={IAIInput} <Field
id="weights" as={IAIInput}
name="weights" id="weights"
type="text" name="weights"
width="full" type="text"
/> width="full"
{!!errors.weights && touched.weights ? ( />
<FormErrorMessage>{errors.weights}</FormErrorMessage> {!!errors.weights && touched.weights ? (
) : ( <FormErrorMessage>{errors.weights}</FormErrorMessage>
<FormHelperText margin={0}> ) : (
{t('modelManager.modelLocationValidationMsg')} <FormHelperText margin={0}>
</FormHelperText> {t('modelManager.modelLocationValidationMsg')}
)} </FormHelperText>
</VStack> )}
</FormControl> </VStack>
</FormControl>
</IAIFormItemWrapper>
{/* VAE */} {/* VAE */}
<FormControl isInvalid={!!errors.vae && touched.vae}> <IAIFormItemWrapper>
<FormLabel htmlFor="vae" fontSize="sm"> <FormControl isInvalid={!!errors.vae && touched.vae}>
{t('modelManager.vaeLocation')} <FormLabel htmlFor="vae" fontSize="sm">
</FormLabel> {t('modelManager.vaeLocation')}
<VStack alignItems="start">
<Field
as={IAIInput}
id="vae"
name="vae"
type="text"
width="full"
/>
{!!errors.vae && touched.vae ? (
<FormErrorMessage>{errors.vae}</FormErrorMessage>
) : (
<FormHelperText margin={0}>
{t('modelManager.vaeLocationValidationMsg')}
</FormHelperText>
)}
</VStack>
</FormControl>
<HStack width="100%" gap={8}>
{/* Width */}
<FormControl isInvalid={!!errors.width && touched.width}>
<FormLabel htmlFor="width" fontSize="sm">
{t('modelManager.width')}
</FormLabel> </FormLabel>
<VStack alignItems="start"> <VStack alignItems="start">
<Field id="width" name="width"> <Field
{({ as={IAIInput}
field, id="vae"
form, name="vae"
}: { type="text"
field: FieldInputProps<number>; width="full"
form: FormikProps<InvokeModelConfigProps>; />
}) => ( {!!errors.vae && touched.vae ? (
<IAINumberInput <FormErrorMessage>{errors.vae}</FormErrorMessage>
id="width"
name="width"
min={MIN_MODEL_SIZE}
max={MAX_MODEL_SIZE}
step={64}
value={form.values.width}
onChange={(value) =>
form.setFieldValue(field.name, Number(value))
}
/>
)}
</Field>
{!!errors.width && touched.width ? (
<FormErrorMessage>{errors.width}</FormErrorMessage>
) : ( ) : (
<FormHelperText margin={0}> <FormHelperText margin={0}>
{t('modelManager.widthValidationMsg')} {t('modelManager.vaeLocationValidationMsg')}
</FormHelperText> </FormHelperText>
)} )}
</VStack> </VStack>
</FormControl> </FormControl>
</IAIFormItemWrapper>
<HStack width="100%">
{/* Width */}
<IAIFormItemWrapper>
<FormControl isInvalid={!!errors.width && touched.width}>
<FormLabel htmlFor="width" fontSize="sm">
{t('modelManager.width')}
</FormLabel>
<VStack alignItems="start">
<Field id="width" name="width">
{({
field,
form,
}: {
field: FieldInputProps<number>;
form: FormikProps<InvokeModelConfigProps>;
}) => (
<IAINumberInput
id="width"
name="width"
min={MIN_MODEL_SIZE}
max={MAX_MODEL_SIZE}
step={64}
value={form.values.width}
onChange={(value) =>
form.setFieldValue(field.name, Number(value))
}
/>
)}
</Field>
{!!errors.width && touched.width ? (
<FormErrorMessage>{errors.width}</FormErrorMessage>
) : (
<FormHelperText margin={0}>
{t('modelManager.widthValidationMsg')}
</FormHelperText>
)}
</VStack>
</FormControl>
</IAIFormItemWrapper>
{/* Height */} {/* Height */}
<FormControl isInvalid={!!errors.height && touched.height}> <IAIFormItemWrapper>
<FormLabel htmlFor="height" fontSize="sm"> <FormControl isInvalid={!!errors.height && touched.height}>
{t('modelManager.height')} <FormLabel htmlFor="height" fontSize="sm">
</FormLabel> {t('modelManager.height')}
<VStack alignItems="start"> </FormLabel>
<Field id="height" name="height"> <VStack alignItems="start">
{({ <Field id="height" name="height">
field, {({
form, field,
}: { form,
field: FieldInputProps<number>; }: {
form: FormikProps<InvokeModelConfigProps>; field: FieldInputProps<number>;
}) => ( form: FormikProps<InvokeModelConfigProps>;
<IAINumberInput }) => (
id="height" <IAINumberInput
name="height" id="height"
min={MIN_MODEL_SIZE} name="height"
max={MAX_MODEL_SIZE} min={MIN_MODEL_SIZE}
step={64} max={MAX_MODEL_SIZE}
value={form.values.height} step={64}
onChange={(value) => value={form.values.height}
form.setFieldValue(field.name, Number(value)) onChange={(value) =>
} form.setFieldValue(field.name, Number(value))
/> }
)} />
</Field> )}
</Field>
{!!errors.height && touched.height ? ( {!!errors.height && touched.height ? (
<FormErrorMessage>{errors.height}</FormErrorMessage> <FormErrorMessage>{errors.height}</FormErrorMessage>
) : ( ) : (
<FormHelperText margin={0}> <FormHelperText margin={0}>
{t('modelManager.heightValidationMsg')} {t('modelManager.heightValidationMsg')}
</FormHelperText> </FormHelperText>
)} )}
</VStack> </VStack>
</FormControl> </FormControl>
</IAIFormItemWrapper>
</HStack> </HStack>
<IAIButton <IAIButton
@ -306,6 +330,8 @@ export default function AddCheckpointModel() {
</IAIForm> </IAIForm>
)} )}
</Formik> </Formik>
) : (
<SearchModels />
)} )}
</VStack> </VStack>
); );

View File

@ -17,29 +17,8 @@ import { Field, Formik } from 'formik';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import type { RootState } from 'app/store'; import type { RootState } from 'app/store';
import type { ReactElement } from 'react';
import IAIForm from 'common/components/IAIForm'; import IAIForm from 'common/components/IAIForm';
import { IAIFormItemWrapper } from 'common/components/IAIForms/IAIFormItemWrapper';
function FormItemWrapper({
children,
}: {
children: ReactElement | ReactElement[];
}) {
return (
<Flex
sx={{
flexDirection: 'column',
padding: 4,
rowGap: 4,
borderRadius: 'base',
width: 'full',
bg: 'base.900',
}}
>
{children}
</Flex>
);
}
export default function AddDiffusersModel() { export default function AddDiffusersModel() {
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@ -95,7 +74,7 @@ export default function AddDiffusersModel() {
{({ handleSubmit, errors, touched }) => ( {({ handleSubmit, errors, touched }) => (
<IAIForm onSubmit={handleSubmit}> <IAIForm onSubmit={handleSubmit}>
<VStack rowGap={2}> <VStack rowGap={2}>
<FormItemWrapper> <IAIFormItemWrapper>
{/* Name */} {/* Name */}
<FormControl <FormControl
isInvalid={!!errors.name && touched.name} isInvalid={!!errors.name && touched.name}
@ -123,9 +102,9 @@ export default function AddDiffusersModel() {
)} )}
</VStack> </VStack>
</FormControl> </FormControl>
</FormItemWrapper> </IAIFormItemWrapper>
<FormItemWrapper> <IAIFormItemWrapper>
{/* Description */} {/* Description */}
<FormControl <FormControl
isInvalid={!!errors.description && touched.description} isInvalid={!!errors.description && touched.description}
@ -152,9 +131,9 @@ export default function AddDiffusersModel() {
)} )}
</VStack> </VStack>
</FormControl> </FormControl>
</FormItemWrapper> </IAIFormItemWrapper>
<FormItemWrapper> <IAIFormItemWrapper>
<Text fontWeight="bold" fontSize="sm"> <Text fontWeight="bold" fontSize="sm">
{t('modelManager.formMessageDiffusersModelLocation')} {t('modelManager.formMessageDiffusersModelLocation')}
</Text> </Text>
@ -213,9 +192,9 @@ export default function AddDiffusersModel() {
)} )}
</VStack> </VStack>
</FormControl> </FormControl>
</FormItemWrapper> </IAIFormItemWrapper>
<FormItemWrapper> <IAIFormItemWrapper>
{/* VAE Path */} {/* VAE Path */}
<Text fontWeight="bold"> <Text fontWeight="bold">
{t('modelManager.formMessageDiffusersVAELocation')} {t('modelManager.formMessageDiffusersVAELocation')}
@ -277,7 +256,7 @@ export default function AddDiffusersModel() {
)} )}
</VStack> </VStack>
</FormControl> </FormControl>
</FormItemWrapper> </IAIFormItemWrapper>
<IAIButton type="submit" isLoading={isProcessing}> <IAIButton type="submit" isLoading={isProcessing}>
{t('modelManager.addModel')} {t('modelManager.addModel')}