Clean automationcreation

This commit is contained in:
Connor Yoh 2025-08-19 14:35:18 +01:00
parent 6ea300ddd3
commit 58e2a50b74

View File

@ -2,28 +2,24 @@ import React, { useState, useEffect } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { import {
Button, Button,
Card,
Text, Text,
Title, Title,
Stack, Stack,
Group, Group,
Select, Select,
TextInput, TextInput,
Textarea,
Badge,
ActionIcon, ActionIcon,
Modal, Divider
Box
} from '@mantine/core'; } from '@mantine/core';
import AddIcon from '@mui/icons-material/Add'; import AddIcon from '@mui/icons-material/Add';
import DeleteIcon from '@mui/icons-material/Delete'; import DeleteIcon from '@mui/icons-material/Delete';
import SettingsIcon from '@mui/icons-material/Settings'; import SettingsIcon from '@mui/icons-material/Settings';
import ArrowForwardIcon from '@mui/icons-material/ArrowForward';
import ArrowBackIcon from '@mui/icons-material/ArrowBack'; import ArrowBackIcon from '@mui/icons-material/ArrowBack';
import CheckIcon from '@mui/icons-material/Check'; import CheckIcon from '@mui/icons-material/Check';
import CloseIcon from '@mui/icons-material/Close'; import CloseIcon from '@mui/icons-material/Close';
import { useToolWorkflow } from '../../../contexts/ToolWorkflowContext'; import { useToolWorkflow } from '../../../contexts/ToolWorkflowContext';
import ToolConfigurationModal from './ToolConfigurationModal'; import ToolConfigurationModal from './ToolConfigurationModal';
import AutomationEntry from './AutomationEntry';
interface AutomationCreationProps { interface AutomationCreationProps {
mode: 'custom' | 'suggested' | 'create'; mode: 'custom' | 'suggested' | 'create';
@ -45,7 +41,6 @@ export default function AutomationCreation({ mode, existingAutomation, onBack, o
const { toolRegistry } = useToolWorkflow(); const { toolRegistry } = useToolWorkflow();
const [automationName, setAutomationName] = useState(''); const [automationName, setAutomationName] = useState('');
const [automationDescription, setAutomationDescription] = useState('');
const [selectedTools, setSelectedTools] = useState<AutomationTool[]>([]); const [selectedTools, setSelectedTools] = useState<AutomationTool[]>([]);
const [configModalOpen, setConfigModalOpen] = useState(false); const [configModalOpen, setConfigModalOpen] = useState(false);
const [configuraingToolIndex, setConfiguringToolIndex] = useState(-1); const [configuraingToolIndex, setConfiguringToolIndex] = useState(-1);
@ -54,7 +49,6 @@ export default function AutomationCreation({ mode, existingAutomation, onBack, o
useEffect(() => { useEffect(() => {
if (mode === 'suggested' && existingAutomation) { if (mode === 'suggested' && existingAutomation) {
setAutomationName(existingAutomation.name); setAutomationName(existingAutomation.name);
setAutomationDescription(existingAutomation.description || '');
const tools = existingAutomation.operations.map((op: string) => ({ const tools = existingAutomation.operations.map((op: string) => ({
id: `${op}-${Date.now()}`, id: `${op}-${Date.now()}`,
@ -77,7 +71,7 @@ export default function AutomationCreation({ mode, existingAutomation, onBack, o
if (!toolRegistry) return []; if (!toolRegistry) return [];
return Object.entries(toolRegistry) return Object.entries(toolRegistry)
.filter(([key]) => key !== 'automate') // Don't allow recursive automations .filter(([key]) => key !== 'automate')
.map(([key, tool]) => ({ .map(([key, tool]) => ({
value: key, value: key,
label: (tool as any).name label: (tool as any).name
@ -139,7 +133,7 @@ export default function AutomationCreation({ mode, existingAutomation, onBack, o
const automation = { const automation = {
name: automationName.trim(), name: automationName.trim(),
description: automationDescription.trim(), description: '',
operations: selectedTools.map(tool => ({ operations: selectedTools.map(tool => ({
operation: tool.operation, operation: tool.operation,
parameters: tool.parameters parameters: tool.parameters
@ -152,63 +146,35 @@ export default function AutomationCreation({ mode, existingAutomation, onBack, o
onComplete(); onComplete();
} catch (error) { } catch (error) {
console.error('Error saving automation:', error); console.error('Error saving automation:', error);
// TODO: Show error notification to user
} }
}; };
const currentConfigTool = configuraingToolIndex >= 0 ? selectedTools[configuraingToolIndex] : null; const currentConfigTool = configuraingToolIndex >= 0 ? selectedTools[configuraingToolIndex] : null;
return ( return (
<Stack gap="xl">
<Group justify="space-between" align="center">
<div> <div>
<Title order={2} mb="xs"> <Group justify="space-between" align="center" mb="md">
<Title order={3} size="h4" fw={600} style={{ color: 'var(--mantine-color-text)' }}>
{mode === 'create' {mode === 'create'
? t('automate.creation.title.create', 'Create New Automation') ? t('automate.creation.title.create', 'Create Automation')
: mode === 'suggested' : t('automate.creation.title.configure', 'Configure Automation')
? t('automate.creation.title.configure', 'Configure Automation')
: t('automate.creation.title.edit', 'Edit Automation')
} }
</Title> </Title>
<Text size="sm" c="dimmed"> <ActionIcon variant="subtle" onClick={onBack}>
{t('automate.creation.description', 'Add and configure tools to create your workflow')} <ArrowBackIcon />
</Text> </ActionIcon>
</div>
<Button
leftSection={<ArrowBackIcon />}
variant="light"
onClick={onBack}
>
{t('automate.creation.back', 'Back')}
</Button>
</Group> </Group>
{/* Automation Details */}
<Card shadow="sm" padding="md" radius="md" withBorder>
<Stack gap="md"> <Stack gap="md">
{/* Automation Name */}
<TextInput <TextInput
label={t('automate.creation.name.label', 'Automation Name')} placeholder={t('automate.creation.name.placeholder', 'Automation name')}
placeholder={t('automate.creation.name.placeholder', 'Enter a name for this automation')}
value={automationName} value={automationName}
onChange={(e) => setAutomationName(e.currentTarget.value)} onChange={(e) => setAutomationName(e.currentTarget.value)}
required size="sm"
/> />
<Textarea
label={t('automate.creation.description.label', 'Description')}
placeholder={t('automate.creation.description.placeholder', 'Optional description of what this automation does')}
value={automationDescription}
onChange={(e) => setAutomationDescription(e.currentTarget.value)}
minRows={2}
/>
</Stack>
</Card>
{/* Tool Selection */} {/* Add Tool Selector */}
<Card shadow="sm" padding="md" radius="md" withBorder>
<Group justify="space-between" align="center" mb="md">
<Text fw={600}>
{t('automate.creation.tools.title', 'Tools in Workflow')}
</Text>
<Select <Select
placeholder={t('automate.creation.tools.add', 'Add a tool...')} placeholder={t('automate.creation.tools.add', 'Add a tool...')}
data={getAvailableTools()} data={getAvailableTools()}
@ -217,82 +183,71 @@ export default function AutomationCreation({ mode, existingAutomation, onBack, o
value={null} value={null}
onChange={addTool} onChange={addTool}
leftSection={<AddIcon />} leftSection={<AddIcon />}
size="sm"
/> />
{/* Selected Tools */}
{selectedTools.length > 0 && (
<Stack gap="xs">
{selectedTools.map((tool, index) => (
<Group key={tool.id} gap="xs" align="center">
<Text size="xs" c="dimmed" style={{ minWidth: '1rem', textAlign: 'center' }}>
{index + 1}
</Text>
<div style={{ flex: 1 }}>
<Group justify="space-between" align="center">
<Group gap="xs" align="center">
<Text size="sm" style={{ color: 'var(--mantine-color-text)' }}>
{tool.name}
</Text>
{tool.configured ? (
<CheckIcon style={{ fontSize: 14, color: 'green' }} />
) : (
<CloseIcon style={{ fontSize: 14, color: 'orange' }} />
)}
</Group> </Group>
{selectedTools.length === 0 ? (
<Text size="sm" c="dimmed" ta="center" py="md">
{t('automate.creation.tools.empty', 'No tools added yet. Select a tool from the dropdown above.')}
</Text>
) : (
<Stack gap="sm">
{selectedTools.map((tool, index) => (
<Box key={tool.id}>
<Group gap="sm" align="center">
<Badge size="sm" variant="light">
{index + 1}
</Badge>
<Card
shadow="xs"
padding="sm"
radius="sm"
withBorder
style={{ flex: 1 }}
>
<Group justify="space-between" align="center">
<div>
<Group gap="xs" align="center">
<Text fw={500}>{tool.name}</Text>
{tool.configured ? (
<Badge size="xs" color="green" leftSection={<CheckIcon style={{ fontSize: 10 }} />}>
{t('automate.creation.tools.configured', 'Configured')}
</Badge>
) : (
<Badge size="xs" color="orange" leftSection={<CloseIcon style={{ fontSize: 10 }} />}>
{t('automate.creation.tools.needsConfig', 'Needs Configuration')}
</Badge>
)}
</Group>
</div>
<Group gap="xs"> <Group gap="xs">
<ActionIcon <ActionIcon
variant="light" variant="subtle"
size="sm"
onClick={() => configureTool(index)} onClick={() => configureTool(index)}
title={t('automate.creation.tools.configure', 'Configure')}
> >
<SettingsIcon /> <SettingsIcon style={{ fontSize: 16 }} />
</ActionIcon> </ActionIcon>
<ActionIcon <ActionIcon
variant="light" variant="subtle"
size="sm"
color="red" color="red"
onClick={() => removeTool(index)} onClick={() => removeTool(index)}
title={t('automate.creation.tools.remove', 'Remove')}
> >
<DeleteIcon /> <DeleteIcon style={{ fontSize: 16 }} />
</ActionIcon> </ActionIcon>
</Group> </Group>
</Group> </Group>
</Card> </div>
{index < selectedTools.length - 1 && ( {index < selectedTools.length - 1 && (
<ArrowForwardIcon style={{ color: 'var(--mantine-color-dimmed)' }} /> <Text size="xs" c="dimmed"></Text>
)} )}
</Group> </Group>
</Box>
))} ))}
</Stack> </Stack>
)} )}
</Card>
<Divider />
{/* Save Button */} {/* Save Button */}
<Group justify="flex-end">
<Button <Button
leftSection={<CheckIcon />} leftSection={<CheckIcon />}
onClick={saveAutomation} onClick={saveAutomation}
disabled={!canSaveAutomation()} disabled={!canSaveAutomation()}
fullWidth
> >
{t('automate.creation.save', 'Save Automation')} {t('automate.creation.save', 'Save Automation')}
</Button> </Button>
</Group> </Stack>
{/* Tool Configuration Modal */} {/* Tool Configuration Modal */}
{currentConfigTool && ( {currentConfigTool && (
@ -303,6 +258,6 @@ export default function AutomationCreation({ mode, existingAutomation, onBack, o
onCancel={handleToolConfigCancel} onCancel={handleToolConfigCancel}
/> />
)} )}
</Stack> </div>
); );
} }