ui: change add model modal to 'switch model' and add form validation (#1878)

This commit is contained in:
Lily Delalande
2025-03-27 11:01:41 -04:00
committed by GitHub
parent e58ccf3d37
commit 369acf8fe6
@@ -10,7 +10,7 @@ import { useConfig } from '../../../ConfigContext';
import { changeModel as switchModel } from '../index'; import { changeModel as switchModel } from '../index';
import type { View } from '../../../../App'; import type { View } from '../../../../App';
const ModalButtons = ({ onSubmit, onCancel }) => ( const ModalButtons = ({ onSubmit, onCancel, isValid, validationErrors }) => (
<div> <div>
<Button <Button
type="submit" type="submit"
@@ -18,7 +18,7 @@ const ModalButtons = ({ onSubmit, onCancel }) => (
onClick={onSubmit} onClick={onSubmit}
className="w-full h-[60px] rounded-none border-borderSubtle text-base hover:bg-bgSubtle text-textProminent font-regular" className="w-full h-[60px] rounded-none border-borderSubtle text-base hover:bg-bgSubtle text-textProminent font-regular"
> >
Add model Select model
</Button> </Button>
<Button <Button
type="button" type="button"
@@ -42,12 +42,53 @@ export const AddModelModal = ({ onClose, setView }: AddModelModalProps) => {
const [provider, setProvider] = useState<string | null>(null); const [provider, setProvider] = useState<string | null>(null);
const [model, setModel] = useState<string>(''); const [model, setModel] = useState<string>('');
const [isCustomModel, setIsCustomModel] = useState(false); const [isCustomModel, setIsCustomModel] = useState(false);
const [validationErrors, setValidationErrors] = useState({
provider: '',
model: '',
});
const [isValid, setIsValid] = useState(true);
const [attemptedSubmit, setAttemptedSubmit] = useState(false);
// Validate form data
const validateForm = () => {
const errors = {
provider: '',
model: '',
};
let formIsValid = true;
if (!provider) {
errors.provider = 'Please select a provider';
formIsValid = false;
}
if (!model) {
errors.model = 'Please select or enter a model';
formIsValid = false;
}
setValidationErrors(errors);
setIsValid(formIsValid);
return formIsValid;
};
const changeModel = async () => { const changeModel = async () => {
await switchModel({ model: model, provider: provider, writeToConfig: upsert }); setAttemptedSubmit(true);
onClose(); // Add this line to close the modal after changing the model const isFormValid = validateForm();
if (isFormValid) {
await switchModel({ model: model, provider: provider, writeToConfig: upsert });
onClose();
}
}; };
// Re-validate when inputs change and after attempted submission
useEffect(() => {
if (attemptedSubmit) {
validateForm();
}
}, [provider, model, attemptedSubmit]);
useEffect(() => { useEffect(() => {
(async () => { (async () => {
try { try {
@@ -114,11 +155,21 @@ export const AddModelModal = ({ onClose, setView }: AddModelModalProps) => {
return ( return (
<div className="z-10"> <div className="z-10">
<Modal onClose={onClose} footer={<ModalButtons onSubmit={changeModel} onCancel={onClose} />}> <Modal
onClose={onClose}
footer={
<ModalButtons
onSubmit={changeModel}
onCancel={onClose}
isValid={isValid}
validationErrors={validationErrors}
/>
}
>
<div className="flex flex-col items-center gap-8"> <div className="flex flex-col items-center gap-8">
<div className="flex flex-col items-center gap-3"> <div className="flex flex-col items-center gap-3">
<Plus size={24} className="text-textStandard" /> <Plus size={24} className="text-textStandard" />
<div className="text-textStandard font-medium">Add model</div> <div className="text-textStandard font-medium">Switch models</div>
<div className="text-textSubtle text-center"> <div className="text-textSubtle text-center">
Configure your AI model providers by adding their API keys. Your keys are stored Configure your AI model providers by adding their API keys. Your keys are stored
securely and encrypted locally. securely and encrypted locally.
@@ -137,40 +188,50 @@ export const AddModelModal = ({ onClose, setView }: AddModelModalProps) => {
</div> </div>
<div className="w-full flex flex-col gap-4"> <div className="w-full flex flex-col gap-4">
<Select <div>
options={providerOptions} <Select
value={providerOptions.find((option) => option.value === provider) || null} options={providerOptions}
onChange={(option) => { value={providerOptions.find((option) => option.value === provider) || null}
if (option?.value === 'configure_providers') { onChange={(option) => {
// Navigate to ConfigureProviders view if (option?.value === 'configure_providers') {
setView('ConfigureProviders'); // Navigate to ConfigureProviders view
onClose(); // Close the current modal setView('ConfigureProviders');
} else { onClose(); // Close the current modal
setProvider(option?.value || null); } else {
setModel(''); setProvider(option?.value || null);
setIsCustomModel(false); setModel('');
} setIsCustomModel(false);
}} }
placeholder="Provider" }}
isClearable placeholder="Provider"
/> isClearable
/>
{attemptedSubmit && validationErrors.provider && (
<div className="text-red-500 text-sm mt-1">{validationErrors.provider}</div>
)}
</div>
{provider && ( {provider && (
<> <>
{!isCustomModel ? ( {!isCustomModel ? (
<Select <div>
options={filteredModelOptions} <Select
onChange={handleModelChange} options={filteredModelOptions}
value={model ? { value: model, label: model } : null} onChange={handleModelChange}
placeholder="Select a model" value={model ? { value: model, label: model } : null}
/> placeholder="Select a model"
/>
{attemptedSubmit && validationErrors.model && (
<div className="text-red-500 text-sm mt-1">{validationErrors.model}</div>
)}
</div>
) : ( ) : (
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
<div className="flex justify-between"> <div className="flex justify-between">
<label className="text-sm text-textSubtle">Custom model name</label> <label className="text-sm text-textSubtle">Custom model name</label>
<button <button
onClick={() => setIsCustomModel(false)} onClick={() => setIsCustomModel(false)}
className="text-sm text-blue-500 hover:text-blue-700" className="text-sm text-textSubtle"
> >
Back to model list Back to model list
</button> </button>
@@ -181,6 +242,9 @@ export const AddModelModal = ({ onClose, setView }: AddModelModalProps) => {
onChange={(event) => setModel(event.target.value)} onChange={(event) => setModel(event.target.value)}
value={model} value={model}
/> />
{attemptedSubmit && validationErrors.model && (
<div className="text-red-500 text-sm mt-1">{validationErrors.model}</div>
)}
</div> </div>
)} )}
</> </>