feat: Hook env vars editor up when adding/editing extensions (#1859)
This commit is contained in:
@@ -55,7 +55,7 @@ export default function Modal({
|
|||||||
ref={modalRef}
|
ref={modalRef}
|
||||||
className="relative w-[500px] max-w-full bg-bgApp rounded-xl my-10 max-h-[90vh] flex flex-col"
|
className="relative w-[500px] max-w-full bg-bgApp rounded-xl my-10 max-h-[90vh] flex flex-col"
|
||||||
>
|
>
|
||||||
<div className="p-8 max-h-[calc(90vh-180px)]">{children}</div>
|
<div className="p-8 max-h-[calc(90vh-180px)] overflow-y-auto">{children}</div>
|
||||||
{footer && (
|
{footer && (
|
||||||
<div className="border-t border-borderSubtle bg-bgApp w-full rounded-b-xl overflow-hidden">
|
<div className="border-t border-borderSubtle bg-bgApp w-full rounded-b-xl overflow-hidden">
|
||||||
{footer}
|
{footer}
|
||||||
|
|||||||
@@ -2,14 +2,14 @@ import React from 'react';
|
|||||||
import { Button } from '../../../ui/button';
|
import { Button } from '../../../ui/button';
|
||||||
import { Plus, X } from 'lucide-react';
|
import { Plus, X } from 'lucide-react';
|
||||||
import { Input } from '../../../ui/input';
|
import { Input } from '../../../ui/input';
|
||||||
|
import { cn } from '../../../../utils';
|
||||||
|
|
||||||
interface EnvVarsSectionProps {
|
interface EnvVarsSectionProps {
|
||||||
envVars: { key: string; value: string }[];
|
envVars: { key: string; value: string }[];
|
||||||
onAdd: () => void;
|
onAdd: (key: string, value: string) => void;
|
||||||
onRemove: (index: number) => void;
|
onRemove: (index: number) => void;
|
||||||
onChange: (index: number, field: 'key' | 'value', value: string) => void;
|
onChange: (index: number, field: 'key' | 'value', value: string) => void;
|
||||||
submitAttempted: boolean;
|
submitAttempted: boolean;
|
||||||
isValid: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function EnvVarsSection({
|
export default function EnvVarsSection({
|
||||||
@@ -17,24 +17,46 @@ export default function EnvVarsSection({
|
|||||||
onAdd,
|
onAdd,
|
||||||
onRemove,
|
onRemove,
|
||||||
onChange,
|
onChange,
|
||||||
submitAttempted,
|
|
||||||
isValid,
|
|
||||||
}: EnvVarsSectionProps) {
|
}: EnvVarsSectionProps) {
|
||||||
|
const [newKey, setNewKey] = React.useState('');
|
||||||
|
const [newValue, setNewValue] = React.useState('');
|
||||||
|
const [validationError, setValidationError] = React.useState<string | null>(null);
|
||||||
|
const [invalidFields, setInvalidFields] = React.useState<{ key: boolean; value: boolean }>({
|
||||||
|
key: false,
|
||||||
|
value: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleAdd = () => {
|
||||||
|
const keyEmpty = !newKey.trim();
|
||||||
|
const valueEmpty = !newValue.trim();
|
||||||
|
|
||||||
|
if (keyEmpty || valueEmpty) {
|
||||||
|
setInvalidFields({
|
||||||
|
key: keyEmpty,
|
||||||
|
value: valueEmpty,
|
||||||
|
});
|
||||||
|
setValidationError('Both variable name and value must be entered');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setValidationError(null);
|
||||||
|
setInvalidFields({ key: false, value: false });
|
||||||
|
onAdd(newKey, newValue);
|
||||||
|
setNewKey('');
|
||||||
|
setNewValue('');
|
||||||
|
};
|
||||||
|
|
||||||
|
const clearValidation = () => {
|
||||||
|
setValidationError(null);
|
||||||
|
setInvalidFields({ key: false, value: false });
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="relative mb-2">
|
<div className="relative mb-2">
|
||||||
{' '}
|
|
||||||
{/* Added relative positioning with minimal margin */}
|
|
||||||
<label className="text-sm font-medium text-textStandard mb-2 block">
|
<label className="text-sm font-medium text-textStandard mb-2 block">
|
||||||
Environment Variables
|
Environment Variables
|
||||||
</label>
|
</label>
|
||||||
{submitAttempted && !isValid && (
|
|
||||||
<div className="text-xs text-red-500 mt-1">
|
|
||||||
{' '}
|
|
||||||
{/* Removed absolute positioning */}
|
|
||||||
Environment variables must consist of sets of variable names and values
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-[1fr_1fr_auto] gap-2 items-center">
|
<div className="grid grid-cols-[1fr_1fr_auto] gap-2 items-center">
|
||||||
{/* Existing environment variables */}
|
{/* Existing environment variables */}
|
||||||
@@ -46,6 +68,7 @@ export default function EnvVarsSection({
|
|||||||
onChange={(e) => onChange(index, 'key', e.target.value)}
|
onChange={(e) => onChange(index, 'key', e.target.value)}
|
||||||
placeholder="Variable name"
|
placeholder="Variable name"
|
||||||
className={`w-full border-borderSubtle text-textStandard`}
|
className={`w-full border-borderSubtle text-textStandard`}
|
||||||
|
disabled
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
@@ -54,6 +77,7 @@ export default function EnvVarsSection({
|
|||||||
onChange={(e) => onChange(index, 'value', e.target.value)}
|
onChange={(e) => onChange(index, 'value', e.target.value)}
|
||||||
placeholder="Value"
|
placeholder="Value"
|
||||||
className={`w-full border-borderSubtle text-textStandard`}
|
className={`w-full border-borderSubtle text-textStandard`}
|
||||||
|
disabled
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
@@ -68,23 +92,38 @@ export default function EnvVarsSection({
|
|||||||
|
|
||||||
{/* Empty row with Add button */}
|
{/* Empty row with Add button */}
|
||||||
<Input
|
<Input
|
||||||
|
value={newKey}
|
||||||
|
onChange={(e) => {
|
||||||
|
setNewKey(e.target.value);
|
||||||
|
clearValidation();
|
||||||
|
}}
|
||||||
placeholder="Variable name"
|
placeholder="Variable name"
|
||||||
className="w-full border-borderStandard text-textStandard"
|
className={cn(
|
||||||
disabled
|
'w-full border-borderStandard text-textStandard',
|
||||||
|
invalidFields.key && 'border-red-500 focus:border-red-500'
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
<Input
|
<Input
|
||||||
|
value={newValue}
|
||||||
|
onChange={(e) => {
|
||||||
|
setNewValue(e.target.value);
|
||||||
|
clearValidation();
|
||||||
|
}}
|
||||||
placeholder="Value"
|
placeholder="Value"
|
||||||
className="w-full border-borderStandard text-textStandard"
|
className={cn(
|
||||||
disabled
|
'w-full border-borderStandard text-textStandard',
|
||||||
|
invalidFields.value && 'border-red-500 focus:border-red-500'
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
onClick={onAdd}
|
onClick={handleAdd}
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
className="flex items-center justify-start gap-1 px-2 pr-4 text-s font-medium rounded-full dark:bg-slate-400 dark:text-gray-300 bg-gray-300 dark:bg-slate text-slate-400 dark:hover:bg-slate-300 hover:bg-gray-500 hover:text-white dark:hover:text-gray-900 transition-colors min-w-[60px] h-9"
|
className="flex items-center justify-start gap-1 px-2 pr-4 text-s font-medium rounded-full dark:bg-slate-400 dark:text-gray-300 bg-gray-300 dark:bg-slate text-slate-400 dark:hover:bg-slate-300 hover:bg-gray-500 hover:text-white dark:hover:text-gray-900 transition-colors min-w-[60px] h-9"
|
||||||
>
|
>
|
||||||
<Plus className="h-3 w-3" /> Add
|
<Plus className="h-3 w-3" /> Submit
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
{validationError && <div className="mt-2 text-red-500 text-sm">{validationError}</div>}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { Button } from '../../../ui/button';
|
import { Button } from '../../../ui/button';
|
||||||
import Modal from '../../../Modal';
|
import Modal from '../../../Modal';
|
||||||
import { Input } from '../../../ui/input';
|
|
||||||
import Select from 'react-select';
|
|
||||||
import { createDarkSelectStyles, darkSelectTheme } from '../../../ui/select-styles';
|
|
||||||
import { ExtensionFormData } from '../utils';
|
import { ExtensionFormData } from '../utils';
|
||||||
import EnvVarsSection from './EnvVarsSection';
|
import EnvVarsSection from './EnvVarsSection';
|
||||||
import ExtensionConfigFields from './ExtensionConfigFields';
|
import ExtensionConfigFields from './ExtensionConfigFields';
|
||||||
@@ -33,10 +30,10 @@ export default function ExtensionModal({
|
|||||||
const [showDeleteConfirmation, setShowDeleteConfirmation] = useState(false);
|
const [showDeleteConfirmation, setShowDeleteConfirmation] = useState(false);
|
||||||
const [submitAttempted, setSubmitAttempted] = useState(false);
|
const [submitAttempted, setSubmitAttempted] = useState(false);
|
||||||
|
|
||||||
const handleAddEnvVar = () => {
|
const handleAddEnvVar = (key: string, value: string) => {
|
||||||
setFormData({
|
setFormData({
|
||||||
...formData,
|
...formData,
|
||||||
envVars: [...formData.envVars, { key: '', value: '' }],
|
envVars: [...formData.envVars, { key, value }],
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -208,7 +205,6 @@ export default function ExtensionModal({
|
|||||||
onRemove={handleRemoveEnvVar}
|
onRemove={handleRemoveEnvVar}
|
||||||
onChange={Object.assign(handleEnvVarChange, { setSubmitAttempted })}
|
onChange={Object.assign(handleEnvVarChange, { setSubmitAttempted })}
|
||||||
submitAttempted={submitAttempted}
|
submitAttempted={submitAttempted}
|
||||||
isValid={isEnvVarsValid()}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|||||||
Reference in New Issue
Block a user