ConnorYoh 23d86deae7
Feature/v2/automate (#4248)
* automate feature
* Moved all providers to app level to simplify homepage 
* Circular dependency fixes
* You will see that now toolRegistry gets a tool config and a tool
settings object. These enable automate to run the tools using as much
static code as possible.

---------

Co-authored-by: Connor Yoh <connor@stirlingpdf.com>
2025-08-22 14:40:27 +01:00

149 lines
5.2 KiB
TypeScript

import React from 'react';
import { useTranslation } from 'react-i18next';
import { Text, Stack, Group, ActionIcon } from '@mantine/core';
import DeleteIcon from '@mui/icons-material/Delete';
import SettingsIcon from '@mui/icons-material/Settings';
import CloseIcon from '@mui/icons-material/Close';
import AddCircleOutline from '@mui/icons-material/AddCircleOutline';
import { AutomationTool } from '../../../types/automation';
import { ToolRegistryEntry } from '../../../data/toolsTaxonomy';
import ToolSelector from './ToolSelector';
import AutomationEntry from './AutomationEntry';
interface ToolListProps {
tools: AutomationTool[];
toolRegistry: Record<string, ToolRegistryEntry>;
onToolUpdate: (index: number, updates: Partial<AutomationTool>) => void;
onToolRemove: (index: number) => void;
onToolConfigure: (index: number) => void;
onToolAdd: () => void;
getToolName: (operation: string) => string;
getToolDefaultParameters: (operation: string) => Record<string, any>;
}
export default function ToolList({
tools,
toolRegistry,
onToolUpdate,
onToolRemove,
onToolConfigure,
onToolAdd,
getToolName,
getToolDefaultParameters
}: ToolListProps) {
const { t } = useTranslation();
const handleToolSelect = (index: number, newOperation: string) => {
const defaultParams = getToolDefaultParameters(newOperation);
onToolUpdate(index, {
operation: newOperation,
name: getToolName(newOperation),
configured: false,
parameters: defaultParams
});
};
return (
<div>
<Text size="sm" fw={500} mb="xs" style={{ color: 'var(--mantine-color-text)' }}>
{t('automate.creation.tools.selected', 'Selected Tools')} ({tools.length})
</Text>
<Stack gap="0">
{tools.map((tool, index) => (
<React.Fragment key={tool.id}>
<div
style={{
border: '1px solid var(--mantine-color-gray-2)',
borderRadius: 'var(--mantine-radius-sm)',
position: 'relative',
padding: 'var(--mantine-spacing-xs)'
}}
>
{/* Delete X in top right */}
<ActionIcon
variant="subtle"
size="xs"
onClick={() => onToolRemove(index)}
title={t('automate.creation.tools.remove', 'Remove tool')}
style={{
position: 'absolute',
top: '4px',
right: '4px',
zIndex: 1,
color: 'var(--mantine-color-gray-6)'
}}
>
<CloseIcon style={{ fontSize: 12 }} />
</ActionIcon>
<div style={{ paddingRight: '1.25rem' }}>
{/* Tool Selection Dropdown with inline settings cog */}
<Group gap="xs" align="center" wrap="nowrap">
<div style={{ flex: 1, minWidth: 0 }}>
<ToolSelector
key={`tool-selector-${tool.id}`}
onSelect={(newOperation) => handleToolSelect(index, newOperation)}
excludeTools={['automate']}
toolRegistry={toolRegistry}
selectedValue={tool.operation}
placeholder={tool.name}
/>
</div>
{/* Settings cog - only show if tool is selected, aligned right */}
{tool.operation && (
<ActionIcon
variant="subtle"
size="sm"
onClick={() => onToolConfigure(index)}
title={t('automate.creation.tools.configure', 'Configure tool')}
style={{ color: 'var(--mantine-color-gray-6)' }}
>
<SettingsIcon style={{ fontSize: 16 }} />
</ActionIcon>
)}
</Group>
{/* Configuration status underneath */}
{tool.operation && !tool.configured && (
<Text pl="md" size="xs" c="dimmed" mt="xs">
{t('automate.creation.tools.notConfigured', "! Not Configured")}
</Text>
)}
</div>
</div>
{index < tools.length - 1 && (
<div style={{ textAlign: 'center', padding: '8px 0' }}>
<Text size="xs" c="dimmed"></Text>
</div>
)}
</React.Fragment>
))}
{/* Arrow before Add Tool Button */}
{tools.length > 0 && (
<div style={{ textAlign: 'center', padding: '8px 0' }}>
<Text size="xs" c="dimmed"></Text>
</div>
)}
{/* Add Tool Button */}
<div style={{
border: '1px solid var(--mantine-color-gray-2)',
borderRadius: 'var(--mantine-radius-sm)',
overflow: 'hidden'
}}>
<AutomationEntry
title={t('automate.creation.tools.addTool', 'Add Tool')}
badgeIcon={AddCircleOutline}
operations={[]}
onClick={onToolAdd}
keepIconColor={true}
/>
</div>
</Stack>
</div>
);
}