diff --git a/apps/web/src/components/cloud-agent-next/ProfilesListDialog.tsx b/apps/web/src/components/cloud-agent-next/ProfilesListDialog.tsx index a396f3afee..b6cc431b78 100644 --- a/apps/web/src/components/cloud-agent-next/ProfilesListDialog.tsx +++ b/apps/web/src/components/cloud-agent-next/ProfilesListDialog.tsx @@ -11,6 +11,7 @@ import { AlertCircle, ChevronDown, ChevronRight, + ChevronUp, Eye, EyeOff, Lock, @@ -536,6 +537,10 @@ function ProfileEditPanel({ profileId, organizationId }: ProfileEditPanelProps) const [isAddingCommand, setIsAddingCommand] = useState(false); const [newCommand, setNewCommand] = useState(''); + // State for editing existing command + const [editingCommandIndex, setEditingCommandIndex] = useState(null); + const [editingCommandValue, setEditingCommandValue] = useState(''); + // Loading states const [savingVarKey, setSavingVarKey] = useState(null); const [deletingVarKey, setDeletingVarKey] = useState(null); @@ -711,6 +716,74 @@ function ProfileEditPanel({ profileId, organizationId }: ProfileEditPanelProps) } }; + const resetEditCommandForm = () => { + setEditingCommandIndex(null); + setEditingCommandValue(''); + }; + + const handleStartEditCommand = (index: number) => { + const cmd = profile?.commands[index]; + if (!cmd) return; + setEditingCommandIndex(index); + setEditingCommandValue(cmd.command); + }; + + const handleSaveCommand = async (index: number) => { + if (!editingCommandValue.trim()) { + toast.error('Command is required'); + return; + } + + const currentCommands = profile?.commands.map(c => c.command) || []; + const updatedCommands = currentCommands.map((c, i) => + i === index ? editingCommandValue.trim() : c + ); + + setSavingCommands(true); + try { + await setCommands.mutateAsync({ + profileId, + commands: updatedCommands, + organizationId, + }); + toast.success('Command updated'); + resetEditCommandForm(); + } catch (err) { + console.error('Failed to update command:', err); + toast.error('Failed to update command'); + } finally { + setSavingCommands(false); + } + }; + + const handleMoveCommand = async (index: number, direction: 'up' | 'down') => { + const currentCommands = profile?.commands.map(c => c.command) || []; + const targetIndex = direction === 'up' ? index - 1 : index + 1; + if (targetIndex < 0 || targetIndex >= currentCommands.length) return; + + const updatedCommands = [...currentCommands]; + [updatedCommands[index], updatedCommands[targetIndex]] = [ + updatedCommands[targetIndex], + updatedCommands[index], + ]; + + setSavingCommands(true); + try { + await setCommands.mutateAsync({ + profileId, + commands: updatedCommands, + organizationId, + }); + } catch (err) { + console.error('Failed to reorder command:', err); + toast.error('Failed to reorder command'); + } finally { + setSavingCommands(false); + } + }; + + const commandActionsDisabled = savingCommands || editingCommandIndex !== null; + if (isLoading) { return (
@@ -1006,21 +1079,97 @@ function ProfileEditPanel({ profileId, organizationId }: ProfileEditPanelProps) {profile?.commands.map((cmd, index) => (
- {index + 1}. - - {cmd.command} - - + {editingCommandIndex === index ? ( + // Edit mode +
+ setEditingCommandValue(e.target.value)} + placeholder="npm install" + className="font-mono" + autoFocus + disabled={savingCommands} + onKeyDown={e => { + if (savingCommands) return; + if (e.key === 'Enter') { + e.preventDefault(); + void handleSaveCommand(index); + } else if (e.key === 'Escape') { + resetEditCommandForm(); + } + }} + /> +
+ + +
+
+ ) : ( + // View mode +
+ {index + 1}. + + {cmd.command} + +
+ + + + +
+
+ )}
))}