Skip to content

Commit ddc3490

Browse files
authored
Merge pull request #155 from dschoepel/fix/add-toggle-for-integration-api-key
feat: add optional Use API Key checkbox to AI configuration
2 parents 7475b8f + e24dd2e commit ddc3490

File tree

2 files changed

+82
-34
lines changed

2 files changed

+82
-34
lines changed

app/(config)/_components/IntegrationsConfigEditor.jsx

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,25 @@ const IntegrationsConfigEditor = ({
1616
isLoading,
1717
onDirtyChange
1818
}) => {
19-
// Pass data as-is - let YAML serializer handle quoting naturally
19+
// Strip internal UI flags before saving, then pass to onSave
2020
const handleSaveWithTransform = useCallback((formData) => {
21-
onSave(formData);
21+
const output = JSON.parse(JSON.stringify(formData));
22+
if (output?.ai?.configuration) {
23+
delete output.ai.configuration.useApiKey;
24+
}
25+
onSave(output);
2226
}, [onSave]);
2327

28+
// Inject useApiKey flag derived from whether a key value exists
29+
const processedInitialData = useMemo(() => {
30+
if (!initialData?.ai?.configuration) return initialData;
31+
const data = JSON.parse(JSON.stringify(initialData));
32+
if (data.ai.configuration.useApiKey === undefined) {
33+
data.ai.configuration.useApiKey = !!data.ai.configuration.key;
34+
}
35+
return data;
36+
}, [initialData]);
37+
2438
// Custom validation for integrations fields
2539
const validateIntegrationsFields = useCallback((formData, getNestedValue) => {
2640
const errors = {};
@@ -47,8 +61,9 @@ const IntegrationsConfigEditor = ({
4761
}
4862

4963
if (aiConfig.configuration) {
50-
if (!aiConfig.configuration.key || aiConfig.configuration.key.trim() === '') {
51-
errors['ai.configuration.key'] = 'API key is required';
64+
if (aiConfig.configuration.useApiKey &&
65+
(!aiConfig.configuration.key || aiConfig.configuration.key.trim() === '')) {
66+
errors['ai.configuration.key'] = 'API key is required when "Use API Key" is enabled';
5267
}
5368

5469
if (!aiConfig.configuration.model || aiConfig.configuration.model.trim() === '') {
@@ -92,7 +107,7 @@ const IntegrationsConfigEditor = ({
92107
return (
93108
<BaseConfigEditor
94109
sectionName="integrations"
95-
initialData={initialData}
110+
initialData={processedInitialData}
96111
onSave={handleSaveWithTransform}
97112
onCancel={onCancel}
98113
isLoading={isLoading}

app/(config)/_components/integrations/AIConfigSection.jsx

Lines changed: 62 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,17 @@ const AIConfigSection = ({ config = {}, onChange, errors = {} }) => {
4545
});
4646
};
4747

48+
const handleToggleApiKey = (useKey) => {
49+
onChange({
50+
...config,
51+
configuration: {
52+
...config.configuration,
53+
useApiKey: useKey,
54+
key: useKey ? (config.configuration?.key || '') : ''
55+
}
56+
});
57+
};
58+
4859
return (
4960
<Box
5061
p={4}
@@ -169,38 +180,59 @@ const AIConfigSection = ({ config = {}, onChange, errors = {} }) => {
169180
Provider Configuration
170181
</Text>
171182

172-
{/* API Key */}
173-
<Field.Root invalid={!!errors['ai.configuration.key']}>
174-
<Field.Label fontSize={{ base: "xs", sm: "sm" }}>API Key</Field.Label>
175-
<HStack gap={2}>
176-
<Input
177-
type={showApiKey ? "text" : "password"}
178-
value={config.configuration?.key || ''}
179-
onChange={(e) => handleUpdateConfig('key', e.target.value)}
180-
placeholder="YOUR-API-KEY"
181-
bg="inputBg"
182-
size={{ base: "sm", sm: "md" }}
183-
flex={1}
184-
/>
185-
<IconButton
186-
aria-label={showApiKey ? "Hide API key" : "Show API key"}
187-
onClick={() => setShowApiKey(!showApiKey)}
188-
size={{ base: "sm", sm: "md" }}
189-
variant="ghost"
190-
>
191-
{showApiKey ? <MdVisibilityOff /> : <MdVisibility />}
192-
</IconButton>
193-
</HStack>
194-
{errors['ai.configuration.key'] && (
195-
<Field.ErrorText fontSize={{ base: "xs", sm: "sm" }}>
196-
{errors['ai.configuration.key']}
197-
</Field.ErrorText>
198-
)}
183+
{/* Use API Key */}
184+
<Field.Root>
185+
<Checkbox.Root
186+
checked={!!config.configuration?.useApiKey}
187+
onCheckedChange={(e) => handleToggleApiKey(e.checked)}
188+
colorPalette="blue"
189+
size={{ base: "sm", sm: "md" }}
190+
>
191+
<Checkbox.HiddenInput />
192+
<Checkbox.Control>
193+
<Checkbox.Indicator />
194+
</Checkbox.Control>
195+
<Checkbox.Label fontSize={{ base: "xs", sm: "sm" }}>Use API Key</Checkbox.Label>
196+
</Checkbox.Root>
199197
<Field.HelperText fontSize={{ base: "xs", sm: "sm" }}>
200-
Your API key for the selected provider
198+
Enable to provide an API key for authentication with the selected provider
201199
</Field.HelperText>
202200
</Field.Root>
203201

202+
{/* API Key */}
203+
{config.configuration?.useApiKey && (
204+
<Field.Root invalid={!!errors['ai.configuration.key']}>
205+
<Field.Label fontSize={{ base: "xs", sm: "sm" }}>API Key</Field.Label>
206+
<HStack gap={2}>
207+
<Input
208+
type={showApiKey ? "text" : "password"}
209+
value={config.configuration?.key || ''}
210+
onChange={(e) => handleUpdateConfig('key', e.target.value)}
211+
placeholder="YOUR-API-KEY"
212+
bg="inputBg"
213+
size={{ base: "sm", sm: "md" }}
214+
flex={1}
215+
/>
216+
<IconButton
217+
aria-label={showApiKey ? "Hide API key" : "Show API key"}
218+
onClick={() => setShowApiKey(!showApiKey)}
219+
size={{ base: "sm", sm: "md" }}
220+
variant="ghost"
221+
>
222+
{showApiKey ? <MdVisibilityOff /> : <MdVisibility />}
223+
</IconButton>
224+
</HStack>
225+
{errors['ai.configuration.key'] && (
226+
<Field.ErrorText fontSize={{ base: "xs", sm: "sm" }}>
227+
{errors['ai.configuration.key']}
228+
</Field.ErrorText>
229+
)}
230+
<Field.HelperText fontSize={{ base: "xs", sm: "sm" }}>
231+
Your API key for the selected provider
232+
</Field.HelperText>
233+
</Field.Root>
234+
)}
235+
204236
{/* Model */}
205237
<Field.Root invalid={!!errors['ai.configuration.model']}>
206238
<Field.Label fontSize={{ base: "xs", sm: "sm" }}>Model Name</Field.Label>
@@ -259,7 +291,8 @@ AIConfigSection.propTypes = {
259291
configuration: PropTypes.shape({
260292
key: PropTypes.string,
261293
model: PropTypes.string,
262-
url: PropTypes.string
294+
url: PropTypes.string,
295+
useApiKey: PropTypes.bool
263296
})
264297
}),
265298
onChange: PropTypes.func.isRequired,

0 commit comments

Comments
 (0)