From 50d6b7a6f862ed3fafd07b9e13a8be3b513b1c23 Mon Sep 17 00:00:00 2001 From: ManishMadan2882 Date: Thu, 22 May 2025 15:24:58 +0530 Subject: [PATCH 01/12] (fix/input) placeholder --- frontend/src/components/Input.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/Input.tsx b/frontend/src/components/Input.tsx index 1278b813..474036ba 100644 --- a/frontend/src/components/Input.tsx +++ b/frontend/src/components/Input.tsx @@ -36,6 +36,8 @@ const Input = ({ const inputRef = useRef(null); + const hasValue = value !== undefined && value !== null && value !== ''; + return (
{placeholder} {required && ( From f82042ff007d8633bfbc56b4bc0c68b81db018b1 Mon Sep 17 00:00:00 2001 From: ManishMadan2882 Date: Thu, 22 May 2025 15:27:29 +0530 Subject: [PATCH 02/12] (feat:config) custom name --- frontend/src/locale/en.json | 5 +- frontend/src/settings/ToolConfig.tsx | 19 ++++++ frontend/src/settings/Tools.tsx | 98 +++++++++++++++++++++++++--- frontend/src/settings/types/index.ts | 2 + 4 files changed, 113 insertions(+), 11 deletions(-) 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 } }; From a340aff63a7c5ea19a25d41acb55261e930c3f91 Mon Sep 17 00:00:00 2001 From: ManishMadan2882 Date: Thu, 22 May 2025 17:14:05 +0530 Subject: [PATCH 03/12] (feat:tools) store custom names --- application/api/user/routes.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/application/api/user/routes.py b/application/api/user/routes.py index 218bb79d..ae653c39 100644 --- a/application/api/user/routes.py +++ b/application/api/user/routes.py @@ -2870,6 +2870,9 @@ class CreateTool(Resource): "config": fields.Raw( required=True, description="Configuration of the tool" ), + "customName": fields.String( + required=False, description="Custom name for the tool" + ), "actions": fields.List( fields.Raw, required=True, @@ -2916,6 +2919,7 @@ class CreateTool(Resource): "name": data["name"], "displayName": data["displayName"], "description": data["description"], + "customName": data.get("customName", ""), "actions": transformed_actions, "config": data["config"], "status": data["status"], @@ -2937,6 +2941,7 @@ class UpdateTool(Resource): "id": fields.String(required=True, description="Tool ID"), "name": fields.String(description="Name of the tool"), "displayName": fields.String(description="Display name for the tool"), + "customName": fields.String(description="Custom name for the tool"), "description": fields.String(description="Tool description"), "config": fields.Raw(description="Configuration of the tool"), "actions": fields.List( @@ -2963,6 +2968,8 @@ class UpdateTool(Resource): update_data["name"] = data["name"] if "displayName" in data: update_data["displayName"] = data["displayName"] + if "customName" in data: + update_data["customName"] = data["customName"] if "description" in data: update_data["description"] = data["description"] if "actions" in data: From 5ab7602f2f2cac2fb0bc8d64b247c4999aa7c6c1 Mon Sep 17 00:00:00 2001 From: ManishMadan2882 Date: Thu, 22 May 2025 17:14:52 +0530 Subject: [PATCH 04/12] (feat:tools) ask for custom names --- frontend/src/modals/ConfigToolModal.tsx | 12 ++++++++++++ frontend/src/settings/Tools.tsx | 12 ++++++------ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/frontend/src/modals/ConfigToolModal.tsx b/frontend/src/modals/ConfigToolModal.tsx index 4a183e0b..8d413a4a 100644 --- a/frontend/src/modals/ConfigToolModal.tsx +++ b/frontend/src/modals/ConfigToolModal.tsx @@ -25,6 +25,7 @@ export default function ConfigToolModal({ const { t } = useTranslation(); const token = useSelector(selectToken); const [authKey, setAuthKey] = React.useState(''); + const [customName, setCustomName] = React.useState(''); const handleAddTool = (tool: AvailableToolType) => { userService @@ -34,6 +35,7 @@ export default function ConfigToolModal({ displayName: tool.displayName, description: tool.description, config: { token: authKey }, + customName: customName, actions: tool.actions, status: true, }, @@ -58,6 +60,16 @@ export default function ConfigToolModal({ {t('modals.configTool.type')}:{' '} {tool?.name}

+
+ setCustomName(e.target.value)} + borderVariant="thin" + placeholder="Enter custom name (optional)" + labelBgClassName="bg-white dark:bg-charleston-green-2" + /> +
handleDeleteTool(tool), variant: 'danger', - iconWidth: 18, - iconHeight: 18, + iconWidth: 12, + iconHeight: 12, }, ]; @@ -205,7 +205,7 @@ export default function Tools() { ) : ( userTools .filter((tool) => - tool.displayName + (tool.customName || tool.displayName) .toLowerCase() .includes(searchTerm.toLowerCase()), ) @@ -250,10 +250,10 @@ export default function Tools() {

- {tool.displayName} + {tool.customName || tool.displayName}

{tool.description} @@ -269,7 +269,7 @@ export default function Tools() { size="small" id={`toolToggle-${index}`} ariaLabel={t('settings.tools.toggleToolAria', { - toolName: tool.displayName, + toolName: tool.customName || tool.displayName, })} />

From ebf8f00302e0304533f9bb54fd4a3ec3210e4666 Mon Sep 17 00:00:00 2001 From: ManishMadan2882 Date: Fri, 23 May 2025 00:56:50 +0530 Subject: [PATCH 05/12] (fix/input) minor details --- frontend/src/components/Input.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/Input.tsx b/frontend/src/components/Input.tsx index 474036ba..a968511c 100644 --- a/frontend/src/components/Input.tsx +++ b/frontend/src/components/Input.tsx @@ -60,7 +60,7 @@ const Input = ({ {placeholder && (