Skip to content

Commit c9b078a

Browse files
committed
Trim inputs, polish UI
1 parent 035e6da commit c9b078a

1 file changed

Lines changed: 39 additions & 70 deletions

File tree

webapp/_webapp/src/views/settings/sections/api-key-settings.tsx

Lines changed: 39 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useRef, useState } from "react";
1+
import { useState } from "react";
22
import { Icon } from "@iconify/react";
33
import { Modal } from "../../../components/modal";
44
import { SettingsSectionContainer, SettingsSectionTitle } from "./components";
@@ -12,7 +12,6 @@ export const ApiKeySettings = () => {
1212

1313
const handleCustomModelChange = (newModel: CustomModel, isDelete: boolean) => {
1414
const otherCustomModels = Array.from(settings?.customModels || []).filter((model) => model.id != newModel.id);
15-
console.log(otherCustomModels);
1615

1716
if (isDelete) {
1817
updateSettings({
@@ -53,22 +52,25 @@ export const ApiKeySettings = () => {
5352
{Array.from(settings?.customModels || [])
5453
.sort((a, b) => a.name.localeCompare(b.name))
5554
.map((m) => (
56-
<CustomModelSection
57-
isNew={false}
58-
onChange={handleCustomModelChange}
59-
key={m.id}
60-
model={{
61-
id: m.id,
62-
name: m.name,
63-
baseUrl: m.baseUrl,
64-
slug: m.slug,
65-
apiKey: m.apiKey,
66-
contextWindow: m.contextWindow,
67-
maxOutput: m.maxOutput,
68-
inputPrice: m.inputPrice,
69-
outputPrice: m.outputPrice,
70-
}}
71-
/>
55+
<>
56+
<hr></hr>
57+
<CustomModelSection
58+
isNew={false}
59+
onChange={handleCustomModelChange}
60+
key={m.id}
61+
model={{
62+
id: m.id,
63+
name: m.name,
64+
baseUrl: m.baseUrl,
65+
slug: m.slug,
66+
apiKey: m.apiKey,
67+
contextWindow: m.contextWindow,
68+
maxOutput: m.maxOutput,
69+
inputPrice: m.inputPrice,
70+
outputPrice: m.outputPrice,
71+
}}
72+
/>
73+
</>
7274
))}
7375
</div>
7476
}
@@ -113,19 +115,19 @@ const CustomModelSection = ({ isNew, onChange, model: customModel }: CustomModel
113115
const [maxOutput, setMaxOutput] = useState<number>(customModel?.maxOutput || 0);
114116
const [inputPrice, setInputPrice] = useState<number>(customModel?.inputPrice || 0);
115117
const [outputPrice, setOutputPrice] = useState<number>(customModel?.outputPrice || 0);
116-
const [modelName, setModelName] = useState(customModel?.name || "My Model");
117-
const isModelNameEdited = useRef(false);
118+
const [modelName, setModelName] = useState(customModel?.name || "");
118119

119-
const baseInputClassName = "hover:cursor-pointer bg-transparent p-1 focus:outline-none";
120-
const nameInputClassName = `${baseInputClassName} text-sm text-default-900 font-medium flex-1 truncate`;
120+
const baseInputClassName = "bg-transparent p-1 focus:outline-none mt-[4px]";
121+
const modelNameInputClassName = `${baseInputClassName} text-sm text-default-900 font-medium flex-1 truncate`;
121122
const labelClassName = `${baseInputClassName} text-xs text-default-900 w-auto`;
122-
const detailInputClassName = `${baseInputClassName} text-xs text-default-400 font-normal flex-1`;
123+
const detailInputClassName = `${baseInputClassName} flex-1 noselect focus:outline-none
124+
rnd-cancel px-2 py-1 border !border-gray-200 dark:!border-default-200 rounded-md
125+
text-xs text-default-700 dark:text-default-300 placeholder:text-default-400 disabled:opacity-70 disabled:cursor-not-allowed`;
123126

124127
const handleOnChange = (isDelete: boolean) => {
125-
// TODO: Input validation
126-
// TODO: Add loader
127-
128-
console.log("Id: ", id);
128+
if (modelName.length < 1 || slug.length < 1 || baseUrl.length < 1 || apiKey.length < 1) {
129+
return;
130+
}
129131

130132
onChange(
131133
{
@@ -143,7 +145,7 @@ const CustomModelSection = ({ isNew, onChange, model: customModel }: CustomModel
143145
);
144146

145147
if (isNew) {
146-
setModelName("My Model");
148+
setModelName("");
147149
setBaseUrl("");
148150
setSlug("");
149151
setApiKey("");
@@ -158,14 +160,12 @@ const CustomModelSection = ({ isNew, onChange, model: customModel }: CustomModel
158160
<div className="flex flex-col w-full pl-1">
159161
<div className="flex flex-row justify-between">
160162
<input
161-
className={nameInputClassName}
163+
className={modelNameInputClassName}
162164
value={modelName}
165+
placeholder="My Model"
163166
type="text"
164167
disabled={!isEditing}
165-
onChange={(e) => {
166-
isModelNameEdited.current = true;
167-
setModelName(e.target.value);
168-
}}
168+
onChange={(e) => setModelName(e.target.value.trim())}
169169
></input>
170170

171171
{isNew ? (
@@ -203,54 +203,22 @@ const CustomModelSection = ({ isNew, onChange, model: customModel }: CustomModel
203203
<input
204204
className={detailInputClassName}
205205
value={slug}
206+
placeholder="e.g., google/gemini-2.5-flash"
206207
type="text"
207208
disabled={!isEditing}
208-
onChange={(e) => setSlug(e.target.value)}
209+
onChange={(e) => setSlug(e.target.value.trim())}
209210
/>
210211
</div>
211212

212-
{/* <div className="pr-1">
213-
<div className="flex flex-row">
214-
<label className={labelClassName}>Slug</label>
215-
<select
216-
className={detailInputClassName}
217-
disabled={!isEditing}
218-
onChange={(e) => {
219-
setSlug(e.target.value);
220-
if (!isModelNameEdited.current && isNew) {
221-
// Custom name not yet defined, default to the selected model's name
222-
const m = availableModels.find((mo) => mo.slug == e.target.value);
223-
if (m) setModelName(m.name);
224-
}
225-
}}
226-
value={slug}
227-
>
228-
{isNew ? (
229-
availableModels.length > 0 ? (
230-
availableModels.map((m) => (
231-
<option key={m.slug} value={m.slug}>
232-
{m.slug}
233-
</option>
234-
))
235-
) : (
236-
<option disabled value="">
237-
No available models
238-
</option>
239-
)
240-
) : (
241-
<option>{slug}</option>
242-
)}
243-
</select>
244-
</div> */}
245-
246213
<div className="flex flex-row">
247214
<label className={labelClassName}>Base URL</label>
248215
<input
249216
className={detailInputClassName}
250217
value={baseUrl}
218+
placeholder="An OpenAI-compatible endpoint"
251219
type="text"
252220
disabled={!isEditing}
253-
onChange={(e) => setBaseUrl(e.target.value)}
221+
onChange={(e) => setBaseUrl(e.target.value.trim())}
254222
/>
255223
</div>
256224

@@ -259,9 +227,10 @@ const CustomModelSection = ({ isNew, onChange, model: customModel }: CustomModel
259227
<input
260228
className={detailInputClassName}
261229
value={apiKey}
230+
placeholder="Your API Key"
262231
type={!isEditing && !isNew ? "password" : "text"}
263232
disabled={!isEditing}
264-
onChange={(e) => setApiKey(e.target.value)}
233+
onChange={(e) => setApiKey(e.target.value.trim())}
265234
/>
266235
</div>
267236

0 commit comments

Comments
 (0)