diff --git a/frontend/src/locale/en.json b/frontend/src/locale/en.json index 6c1559b7..b9859635 100644 --- a/frontend/src/locale/en.json +++ b/frontend/src/locale/en.json @@ -119,7 +119,10 @@ "settingsIconAlt": "Settings icon", "configureToolAria": "Configure {toolName}", "toggleToolAria": "Toggle {toolName}", - "manageTools": "Go to Tools" + "manageTools": "Go to Tools", + "edit": "Edit", + "delete": "Delete", + "deleteWarning": "Are you sure you want to delete {toolName}?" } }, "modals": { diff --git a/frontend/src/settings/ToolConfig.tsx b/frontend/src/settings/ToolConfig.tsx index b2e26507..8c8d83f8 100644 --- a/frontend/src/settings/ToolConfig.tsx +++ b/frontend/src/settings/ToolConfig.tsx @@ -28,6 +28,9 @@ export default function ToolConfig({ const [authKey, setAuthKey] = React.useState( 'token' in tool.config ? tool.config.token : '', ); + const [customName, setCustomName] = React.useState( + tool.customName || '', + ); const [actionModalState, setActionModalState] = React.useState('INACTIVE'); const { t } = useTranslation(); @@ -66,6 +69,7 @@ export default function ToolConfig({ id: tool.id, name: tool.name, displayName: tool.displayName, + customName: customName, description: tool.description, config: tool.name === 'api_tool' ? tool.config : { token: authKey }, actions: 'actions' in tool ? tool.actions : [], @@ -132,6 +136,21 @@ export default function ToolConfig({ {tool.name}

+ {/* Custom name section */} +
+

+ Custom Name +

+
+ setCustomName(e.target.value)} + borderVariant="thin" + placeholder="Enter a custom name (optional)" + /> +
+
{Object.keys(tool?.config).length !== 0 && tool.name !== 'api_tool' && (

diff --git a/frontend/src/settings/Tools.tsx b/frontend/src/settings/Tools.tsx index 9c7b6906..722b90d4 100644 --- a/frontend/src/settings/Tools.tsx +++ b/frontend/src/settings/Tools.tsx @@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next'; import { useSelector } from 'react-redux'; import userService from '../api/services/userService'; -import CogwheelIcon from '../assets/cogwheel.svg'; +import ThreeDotsIcon from '../assets/three-dots.svg'; import NoFilesIcon from '../assets/no-files.svg'; import NoFilesDarkIcon from '../assets/no-files-dark.svg'; import Input from '../components/Input'; @@ -15,6 +15,10 @@ import { ActiveState } from '../models/misc'; import { selectToken } from '../preferences/preferenceSlice'; import ToolConfig from './ToolConfig'; import { APIToolType, UserToolType } from './types'; +import ContextMenu, { MenuOption } from '../components/ContextMenu'; +import Edit from '../assets/edit.svg'; +import Trash from '../assets/red-trash.svg'; +import ConfirmationModal from '../modals/ConfirmationModal'; export default function Tools() { const { t } = useTranslation(); @@ -29,6 +33,57 @@ export default function Tools() { UserToolType | APIToolType | null >(null); const [loading, setLoading] = React.useState(false); + const [activeMenuId, setActiveMenuId] = React.useState(null); + const menuRefs = React.useRef<{ + [key: string]: React.RefObject; + }>({}); + const [deleteModalState, setDeleteModalState] = + React.useState('INACTIVE'); + const [toolToDelete, setToolToDelete] = React.useState( + null, + ); + + React.useEffect(() => { + userTools.forEach((tool) => { + if (!menuRefs.current[tool.id]) { + menuRefs.current[tool.id] = React.createRef(); + } + }); + }, [userTools]); + + const handleDeleteTool = (tool: UserToolType) => { + setToolToDelete(tool); + setDeleteModalState('ACTIVE'); + }; + + const confirmDeleteTool = () => { + if (toolToDelete) { + userService.deleteTool({ id: toolToDelete.id }, token).then(() => { + getUserTools(); + setDeleteModalState('INACTIVE'); + setToolToDelete(null); + }); + } + }; + + const getMenuOptions = (tool: UserToolType): MenuOption[] => [ + { + icon: Edit, + label: t('settings.tools.edit'), + onClick: () => handleSettingsClick(tool), + variant: 'primary', + iconWidth: 14, + iconHeight: 14, + }, + { + icon: Trash, + label: t('settings.tools.delete'), + onClick: () => handleDeleteTool(tool), + variant: 'danger', + iconWidth: 18, + iconHeight: 18, + }, + ]; const getUserTools = () => { setLoading(true); @@ -157,21 +212,34 @@ export default function Tools() { .map((tool, index) => (

- + { + setActiveMenuId(isOpen ? tool.id : null); + }} + options={getMenuOptions(tool)} + anchorRef={menuRefs.current[tool.id]} + position="top-right" + offset={{ x: 0, y: 0 }} + /> +
+
)}
diff --git a/frontend/src/settings/types/index.ts b/frontend/src/settings/types/index.ts index 0795fbb0..5ce3733f 100644 --- a/frontend/src/settings/types/index.ts +++ b/frontend/src/settings/types/index.ts @@ -41,6 +41,7 @@ export type UserToolType = { id: string; name: string; displayName: string; + customName?: string; description: string; status: boolean; config: { @@ -81,6 +82,7 @@ export type APIToolType = { id: string; name: string; displayName: string; + customName?: string; description: string; status: boolean; config: { actions: { [key: string]: APIActionType } };