Model Form Styling

This commit is contained in:
blessedcoolant 2022-12-27 04:07:40 +13:00
parent df858eb3f9
commit ce6fb8ea29
9 changed files with 161 additions and 141 deletions

View File

@ -6,7 +6,7 @@ interface IAIInputProps extends InputProps {
label?: string;
width?: string | number;
value?: string;
onChange: (e: ChangeEvent<HTMLInputElement>) => void;
onChange?: (e: ChangeEvent<HTMLInputElement>) => void;
}
export default function IAIInput(props: IAIInputProps) {
@ -26,17 +26,19 @@ export default function IAIInput(props: IAIInputProps) {
isInvalid={isInvalid}
isDisabled={isDisabled}
>
<FormLabel
fontSize={fontSize}
fontWeight="bold"
alignItems="center"
whiteSpace="nowrap"
marginBottom={0}
marginRight={0}
className="input-label"
>
{label}
</FormLabel>
{label !== '' && (
<FormLabel
fontSize={fontSize}
fontWeight="bold"
alignItems="center"
whiteSpace="nowrap"
marginBottom={0}
marginRight={0}
className="input-label"
>
{label}
</FormLabel>
)}
<Input {...rest} className="input-entry" size={'sm'} width={width} />
</FormControl>
);

View File

@ -24,7 +24,7 @@ interface Props extends Omit<NumberInputProps, 'onChange'> {
labelFontSize?: string | number;
width?: string | number;
showStepper?: boolean;
value: number;
value?: number;
onChange: (v: number) => void;
min: number;
max: number;

View File

@ -1,40 +1,40 @@
import {
Button,
Flex,
FormControl,
FormErrorMessage,
FormHelperText,
FormLabel,
HStack,
Input,
Modal,
ModalBody,
ModalCloseButton,
ModalContent,
ModalHeader,
ModalOverlay,
NumberDecrementStepper,
NumberIncrementStepper,
NumberInput,
NumberInputField,
NumberInputStepper,
Text,
useDisclosure,
VStack,
} from '@chakra-ui/react';
import React from 'react';
import { FaPlus } from 'react-icons/fa';
import { Field, FieldInputProps, Formik, FormikProps } from 'formik';
import type { RootState } from 'app/store';
import { addNewModel } from 'app/socketio/actions';
import type { InvokeModelConfigProps } from 'app/invokeai';
import IAIInput from 'common/components/IAIInput';
import IAINumberInput from 'common/components/IAINumberInput';
import IAICheckbox from 'common/components/IAICheckbox';
import IAIButton from 'common/components/IAIButton';
import SearchModels from './SearchModels';
import { addNewModel } from 'app/socketio/actions';
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
import { FaPlus } from 'react-icons/fa';
import { Field, Formik } from 'formik';
import { useTranslation } from 'react-i18next';
import type { FieldInputProps, FormikProps } from 'formik';
import type { RootState } from 'app/store';
import type { InvokeModelConfigProps } from 'app/invokeai';
const MIN_MODEL_SIZE = 64;
const MAX_MODEL_SIZE = 2048;
@ -128,16 +128,17 @@ export default function AddModel() {
isInvalid={!!errors.name && touched.name}
isRequired
>
<FormLabel htmlFor="name">
<FormLabel htmlFor="name" fontSize="sm">
{t('modelmanager:name')}
</FormLabel>
<VStack alignItems={'start'}>
<Field
as={Input}
as={IAIInput}
id="name"
name="name"
type="text"
validate={baseValidation}
width="lg"
/>
{!!errors.name && touched.name ? (
<FormErrorMessage>{errors.name}</FormErrorMessage>
@ -154,15 +155,16 @@ export default function AddModel() {
isInvalid={!!errors.description && touched.description}
isRequired
>
<FormLabel htmlFor="description">
<FormLabel htmlFor="description" fontSize="sm">
{t('modelmanager:description')}
</FormLabel>
<VStack alignItems={'start'}>
<Field
as={Input}
as={IAIInput}
id="description"
name="description"
type="text"
width="lg"
/>
{!!errors.description && touched.description ? (
<FormErrorMessage>
@ -181,15 +183,16 @@ export default function AddModel() {
isInvalid={!!errors.config && touched.config}
isRequired
>
<FormLabel htmlFor="config">
<FormLabel htmlFor="config" fontSize="sm">
{t('modelmanager:config')}
</FormLabel>
<VStack alignItems={'start'}>
<Field
as={Input}
as={IAIInput}
id="config"
name="config"
type="text"
width="lg"
/>
{!!errors.config && touched.config ? (
<FormErrorMessage>{errors.config}</FormErrorMessage>
@ -206,15 +209,16 @@ export default function AddModel() {
isInvalid={!!errors.weights && touched.weights}
isRequired
>
<FormLabel htmlFor="config">
<FormLabel htmlFor="config" fontSize="sm">
{t('modelmanager:modelLocation')}
</FormLabel>
<VStack alignItems={'start'}>
<Field
as={Input}
as={IAIInput}
id="weights"
name="weights"
type="text"
width="lg"
/>
{!!errors.weights && touched.weights ? (
<FormErrorMessage>
@ -230,11 +234,17 @@ export default function AddModel() {
{/* VAE */}
<FormControl isInvalid={!!errors.vae && touched.vae}>
<FormLabel htmlFor="vae">
<FormLabel htmlFor="vae" fontSize="sm">
{t('modelmanager:vaeLocation')}
</FormLabel>
<VStack alignItems={'start'}>
<Field as={Input} id="vae" name="vae" type="text" />
<Field
as={IAIInput}
id="vae"
name="vae"
type="text"
width="lg"
/>
{!!errors.vae && touched.vae ? (
<FormErrorMessage>{errors.vae}</FormErrorMessage>
) : (
@ -250,7 +260,7 @@ export default function AddModel() {
<FormControl
isInvalid={!!errors.width && touched.width}
>
<FormLabel htmlFor="width">
<FormLabel htmlFor="width" fontSize="sm">
{t('modelmanager:width')}
</FormLabel>
<VStack alignItems={'start'}>
@ -262,26 +272,20 @@ export default function AddModel() {
field: FieldInputProps<number>;
form: FormikProps<InvokeModelConfigProps>;
}) => (
<NumberInput
{...field}
<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)
)
}
>
<NumberInputField />
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
/>
)}
</Field>
@ -301,7 +305,7 @@ export default function AddModel() {
<FormControl
isInvalid={!!errors.height && touched.height}
>
<FormLabel htmlFor="height">
<FormLabel htmlFor="height" fontSize="sm">
{t('modelmanager:height')}
</FormLabel>
<VStack alignItems={'start'}>
@ -313,26 +317,20 @@ export default function AddModel() {
field: FieldInputProps<number>;
form: FormikProps<InvokeModelConfigProps>;
}) => (
<NumberInput
{...field}
<IAINumberInput
id="height"
name="height"
min={MIN_MODEL_SIZE}
max={MAX_MODEL_SIZE}
step={64}
value={form.values.height}
onChange={(value) =>
form.setFieldValue(
field.name,
Number(value)
)
}
>
<NumberInputField />
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
/>
)}
</Field>
@ -349,13 +347,13 @@ export default function AddModel() {
</FormControl>
</HStack>
<Button
<IAIButton
type="submit"
className="modal-close-btn"
isLoading={isProcessing}
>
{t('modelmanager:addModel')}
</Button>
</IAIButton>
</VStack>
</form>
)}

View File

@ -1,31 +1,34 @@
import { createSelector } from '@reduxjs/toolkit';
import type { RootState } from 'app/store';
import React, { useEffect, useState } from 'react';
import IAIInput from 'common/components/IAIInput';
import IAINumberInput from 'common/components/IAINumberInput';
import IAIButton from 'common/components/IAIButton';
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
import { systemSelector } from 'features/system/store/systemSelectors';
import React, { useEffect, useState } from 'react';
import _ from 'lodash';
import type { InvokeModelConfigProps } from 'app/invokeai';
import {
Button,
Flex,
FormControl,
FormErrorMessage,
FormHelperText,
FormLabel,
Input,
NumberDecrementStepper,
NumberIncrementStepper,
NumberInput,
NumberInputField,
NumberInputStepper,
HStack,
Text,
VStack,
} from '@chakra-ui/react';
import { Field, Formik } from 'formik';
import type { FieldInputProps, FormikProps } from 'formik';
import { useTranslation } from 'react-i18next';
import { addNewModel } from 'app/socketio/actions';
import _ from 'lodash';
import type { RootState } from 'app/store';
import type { FieldInputProps, FormikProps } from 'formik';
import type { InvokeModelConfigProps } from 'app/invokeai';
const selector = createSelector(
[systemSelector],
(system) => {
@ -115,15 +118,16 @@ export default function ModelEdit() {
isInvalid={!!errors.description && touched.description}
isRequired
>
<FormLabel htmlFor="description">
<FormLabel htmlFor="description" fontSize="sm">
{t('modelmanager:description')}
</FormLabel>
<VStack alignItems={'start'}>
<Field
as={Input}
as={IAIInput}
id="description"
name="description"
type="text"
width="lg"
/>
{!!errors.description && touched.description ? (
<FormErrorMessage>{errors.description}</FormErrorMessage>
@ -140,11 +144,17 @@ export default function ModelEdit() {
isInvalid={!!errors.config && touched.config}
isRequired
>
<FormLabel htmlFor="config">
<FormLabel htmlFor="config" fontSize="sm">
{t('modelmanager:config')}
</FormLabel>
<VStack alignItems={'start'}>
<Field as={Input} id="config" name="config" type="text" />
<Field
as={IAIInput}
id="config"
name="config"
type="text"
width="lg"
/>
{!!errors.config && touched.config ? (
<FormErrorMessage>{errors.config}</FormErrorMessage>
) : (
@ -160,11 +170,17 @@ export default function ModelEdit() {
isInvalid={!!errors.weights && touched.weights}
isRequired
>
<FormLabel htmlFor="config">
<FormLabel htmlFor="config" fontSize="sm">
{t('modelmanager:modelLocation')}
</FormLabel>
<VStack alignItems={'start'}>
<Field as={Input} id="weights" name="weights" type="text" />
<Field
as={IAIInput}
id="weights"
name="weights"
type="text"
width="lg"
/>
{!!errors.weights && touched.weights ? (
<FormErrorMessage>{errors.weights}</FormErrorMessage>
) : (
@ -177,11 +193,17 @@ export default function ModelEdit() {
{/* VAE */}
<FormControl isInvalid={!!errors.vae && touched.vae}>
<FormLabel htmlFor="vae">
<FormLabel htmlFor="vae" fontSize="sm">
{t('modelmanager:vaeLocation')}
</FormLabel>
<VStack alignItems={'start'}>
<Field as={Input} id="vae" name="vae" type="text" />
<Field
as={IAIInput}
id="vae"
name="vae"
type="text"
width="lg"
/>
{!!errors.vae && touched.vae ? (
<FormErrorMessage>{errors.vae}</FormErrorMessage>
) : (
@ -192,10 +214,10 @@ export default function ModelEdit() {
</VStack>
</FormControl>
<VStack width={'100%'}>
<HStack width={'100%'}>
{/* Width */}
<FormControl isInvalid={!!errors.width && touched.width}>
<FormLabel htmlFor="width">
<FormLabel htmlFor="width" fontSize="sm">
{t('modelmanager:width')}
</FormLabel>
<VStack alignItems={'start'}>
@ -207,23 +229,17 @@ export default function ModelEdit() {
field: FieldInputProps<number>;
form: FormikProps<InvokeModelConfigProps>;
}) => (
<NumberInput
{...field}
<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))
}
>
<NumberInputField />
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
/>
)}
</Field>
@ -239,7 +255,7 @@ export default function ModelEdit() {
{/* Height */}
<FormControl isInvalid={!!errors.height && touched.height}>
<FormLabel htmlFor="height">
<FormLabel htmlFor="height" fontSize="sm">
{t('modelmanager:height')}
</FormLabel>
<VStack alignItems={'start'}>
@ -251,23 +267,17 @@ export default function ModelEdit() {
field: FieldInputProps<number>;
form: FormikProps<InvokeModelConfigProps>;
}) => (
<NumberInput
{...field}
<IAINumberInput
id="height"
name="height"
min={MIN_MODEL_SIZE}
max={MAX_MODEL_SIZE}
step={64}
value={form.values.height}
onChange={(value) =>
form.setFieldValue(field.name, Number(value))
}
>
<NumberInputField />
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
/>
)}
</Field>
@ -280,15 +290,15 @@ export default function ModelEdit() {
)}
</VStack>
</FormControl>
</VStack>
</HStack>
<Button
<IAIButton
type="submit"
className="modal-close-btn"
isLoading={isProcessing}
>
{t('modelmanager:updateModel')}
</Button>
</IAIButton>
</VStack>
</form>
)}

View File

@ -1,15 +1,20 @@
import { useState, ChangeEvent, ReactNode } from 'react';
import { useState } from 'react';
import { Flex, Text } from '@chakra-ui/react';
import { createSelector } from '@reduxjs/toolkit';
import { RootState } from 'app/store';
import { SystemState } from 'features/system/store/systemSlice';
import IAIInput from 'common/components/IAIInput';
import AddModel from './AddModel';
import ModelListItem from './ModelListItem';
import _ from 'lodash';
import IAIInput from 'common/components/IAIInput';
import { useAppSelector } from 'app/storeHooks';
import { useTranslation } from 'react-i18next';
import _ from 'lodash';
import type { ChangeEvent, ReactNode } from 'react';
import type { RootState } from 'app/store';
import type { SystemState } from 'features/system/store/systemSlice';
const modelListSelector = createSelector(
(state: RootState) => state.system,
(system: SystemState) => {

View File

@ -1,17 +1,11 @@
import { EditIcon, DeleteIcon } from '@chakra-ui/icons';
import {
Button,
Flex,
IconButton,
Spacer,
Text,
Tooltip,
} from '@chakra-ui/react';
import { Button, Flex, Spacer, Text, Tooltip } from '@chakra-ui/react';
import { ModelStatus } from 'app/invokeai';
import { deleteModel, requestModelChange } from 'app/socketio/actions';
import { RootState } from 'app/store';
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
import IAIAlertDialog from 'common/components/IAIAlertDialog';
import IAIIconButton from 'common/components/IAIIconButton';
import { setOpenModel } from 'features/system/store/systemSlice';
import React from 'react';
import { useTranslation } from 'react-i18next';
@ -37,12 +31,13 @@ export default function ModelListItem(props: ModelListItemProps) {
dispatch(requestModelChange(name));
};
const openModel = () => {
dispatch(setOpenModel(name));
const openModel = () => {
dispatch(setOpenModel(name));
};
const handleModelDelete = () => {
dispatch(deleteModel(name));
dispatch(setOpenModel(null));
};
const statusTextColor = () => {
@ -63,9 +58,8 @@ export default function ModelListItem(props: ModelListItemProps) {
</Tooltip>
<Spacer />
<Flex gap={4} alignItems="center">
<Flex gap={2} alignItems="center">
<Text color={statusTextColor()}>{status}</Text>
<Button
size={'sm'}
onClick={handleChangeModel}
@ -74,25 +68,26 @@ export default function ModelListItem(props: ModelListItemProps) {
>
{t('modelmanager:load')}
</Button>
<IconButton
icon={<EditIcon />}
size={'sm'}
onClick={openModel}
aria-label="Modify Config"
isDisabled={status === 'active' || isProcessing || !isConnected}
className=" modal-close-btn"
/>
<IAIIconButton
icon={<EditIcon />}
size={'sm'}
onClick={openModel}
aria-label="Modify Config"
isDisabled={status === 'active' || isProcessing || !isConnected}
className=" modal-close-btn"
/>
<IAIAlertDialog
title={t('modelmanager:deleteModel')}
acceptCallback={handleModelDelete}
acceptButtonText={t('modelmanager:delete')}
triggerComponent={
<IconButton
<IAIIconButton
icon={<DeleteIcon />}
size={'sm'}
aria-label={t('modelmanager:deleteConfig')}
isDisabled={status === 'active' || isProcessing || !isConnected}
className=" modal-close-btn"
style={{ backgroundColor: 'var(--btn-delete-image)' }}
/>
}
>

View File

@ -7,11 +7,14 @@ import {
ModalOverlay,
useDisclosure,
} from '@chakra-ui/react';
import React, { cloneElement, ReactElement } from 'react';
import React, { cloneElement } from 'react';
import { useTranslation } from 'react-i18next';
import ModelEdit from './ModelEdit';
import ModelList from './ModelList';
import type { ReactElement } from 'react';
type ModelManagerModalProps = {
children: ReactElement;
};

View File

@ -1,23 +1,29 @@
import { Box, Flex, VStack } from '@chakra-ui/react';
import { addNewModel, searchForModels } from 'app/socketio/actions';
import { RootState } from 'app/store';
import React from 'react';
import IAICheckbox from 'common/components/IAICheckbox';
import React, { ReactNode, ChangeEvent } from 'react';
import { MdFindInPage } from 'react-icons/md';
import _ from 'lodash';
import IAIButton from 'common/components/IAIButton';
import IAIIconButton from 'common/components/IAIIconButton';
import { createSelector } from '@reduxjs/toolkit';
import { systemSelector } from 'features/system/store/systemSelectors';
import { Box, Flex, VStack } from '@chakra-ui/react';
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
import { useTranslation } from 'react-i18next';
import { FaPlus } from 'react-icons/fa';
import { MdFindInPage } from 'react-icons/md';
import { addNewModel, searchForModels } from 'app/socketio/actions';
import {
setFoundModels,
setSearchFolder,
} from 'features/system/store/systemSlice';
import { createSelector } from '@reduxjs/toolkit';
import { systemSelector } from 'features/system/store/systemSelectors';
import { setShouldShowExistingModelsInSearch } from 'features/options/store/optionsSlice';
import { FoundModel } from 'app/invokeai';
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
import { useTranslation } from 'react-i18next';
import _ from 'lodash';
import type { RootState } from 'app/store';
import type { ReactNode, ChangeEvent } from 'react';
import type { FoundModel } from 'app/invokeai';
const existingModelsSelector = createSelector([systemSelector], (system) => {
const { model_list } = system;

View File

@ -23,6 +23,7 @@ import ModelManagerModal from './ModelManager/ModelManagerModal';
import LanguagePicker from './LanguagePicker';
import { useTranslation } from 'react-i18next';
import { MdSettings } from 'react-icons/md';
/**
* Header, includes color mode toggle, settings button, status message.
@ -120,9 +121,9 @@ const SiteHeader = () => {
tooltip={t('common:settingsLabel')}
variant="link"
data-variant="link"
fontSize={20}
fontSize={22}
size={'sm'}
icon={<FaWrench />}
icon={<MdSettings />}
/>
</SettingsModal>
</div>