mirror of
https://github.com/arc53/DocsGPT.git
synced 2025-11-29 08:33:20 +00:00
refactor: UI enhancement in tools
This commit is contained in:
@@ -23,6 +23,7 @@ const endpoints = {
|
||||
CREATE_TOOL: '/api/create_tool',
|
||||
UPDATE_TOOL_STATUS: '/api/update_tool_status',
|
||||
UPDATE_TOOL: '/api/update_tool',
|
||||
DELETE_TOOL: '/api/delete_tool',
|
||||
},
|
||||
CONVERSATION: {
|
||||
ANSWER: '/api/answer',
|
||||
|
||||
@@ -45,6 +45,8 @@ const userService = {
|
||||
apiClient.post(endpoints.USER.UPDATE_TOOL_STATUS, data),
|
||||
updateTool: (data: any): Promise<any> =>
|
||||
apiClient.post(endpoints.USER.UPDATE_TOOL, data),
|
||||
deleteTool: (data: any): Promise<any> =>
|
||||
apiClient.post(endpoints.USER.DELETE_TOOL, data),
|
||||
};
|
||||
|
||||
export default userService;
|
||||
|
||||
15
frontend/src/assets/no-files-dark.svg
Normal file
15
frontend/src/assets/no-files-dark.svg
Normal file
@@ -0,0 +1,15 @@
|
||||
<svg width="113" height="124" viewBox="0 0 113 124" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="55.5" cy="71" r="53" fill="#2D2E33"/>
|
||||
<rect x="-0.599797" y="0.654564" width="43.9445" height="61.5222" rx="4.39444" transform="matrix(-0.999048 0.0436194 0.0436194 0.999048 68.9873 43.3176)" fill="#45464D" stroke="#5F6167" stroke-width="1.25556"/>
|
||||
<rect x="0.704349" y="-0.540466" width="46.4556" height="64.0333" rx="5.65" transform="matrix(-0.991445 -0.130526 -0.130526 0.991445 96.3673 40.893)" fill="#3F4147" stroke="#5F6167" stroke-width="1.25556"/>
|
||||
<path d="M94.3796 45.7849C94.7417 43.0349 92.8059 40.5122 90.0559 40.1501L55.2011 35.5614C52.4511 35.1994 49.9284 37.1352 49.5663 39.8851L48.3372 49.2212L93.1505 55.121L94.3796 45.7849Z" fill="#54555B"/>
|
||||
<rect width="1.88333" height="6.27778" rx="0.941667" transform="matrix(-0.130526 0.991445 0.991445 0.130526 40.4766 36.7888)" fill="#5F6167"/>
|
||||
<rect width="1.88333" height="6.27778" rx="0.941667" transform="matrix(-0.991445 -0.130526 -0.130526 0.991445 57.6758 26.3892)" fill="#5F6167"/>
|
||||
<rect width="1.88333" height="6.27778" rx="0.941667" transform="matrix(-0.793353 0.608761 0.608761 0.793353 46.6406 28.1023)" fill="#5F6167"/>
|
||||
<rect width="36.4111" height="2.51111" rx="1.25556" transform="matrix(-0.991445 -0.130526 -0.130526 0.991445 88.4668 57.0371)" fill="#5F6167"/>
|
||||
<rect width="36.4111" height="2.51111" rx="1.25556" transform="matrix(-0.991445 -0.130526 -0.130526 0.991445 86.8281 69.4851)" fill="#5F6167"/>
|
||||
<rect width="36.4111" height="2.51111" rx="1.25556" transform="matrix(-0.991445 -0.130526 -0.130526 0.991445 85.1895 81.9333)" fill="#5F6167"/>
|
||||
<rect width="13.1833" height="2.51111" rx="1.25556" transform="matrix(-0.991445 -0.130526 -0.130526 0.991445 87.8105 62.0164)" fill="#5F6167"/>
|
||||
<rect width="13.1833" height="2.51111" rx="1.25556" transform="matrix(-0.991445 -0.130526 -0.130526 0.991445 86.1719 74.4644)" fill="#5F6167"/>
|
||||
<rect width="13.1833" height="2.51111" rx="1.25556" transform="matrix(-0.991445 -0.130526 -0.130526 0.991445 84.5332 86.9126)" fill="#5F6167"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
15
frontend/src/assets/no-files.svg
Normal file
15
frontend/src/assets/no-files.svg
Normal file
@@ -0,0 +1,15 @@
|
||||
<svg width="113" height="124" viewBox="0 0 113 124" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="55.5" cy="71" r="53" fill="#F1F1F1" fill-opacity="0.5"/>
|
||||
<rect x="-0.599797" y="0.654564" width="43.9445" height="61.5222" rx="4.39444" transform="matrix(-0.999048 0.0436194 0.0436194 0.999048 68.9873 43.3176)" fill="#EEEEEE" stroke="#999999" stroke-width="1.25556"/>
|
||||
<rect x="0.704349" y="-0.540466" width="46.4556" height="64.0333" rx="5.65" transform="matrix(-0.991445 -0.130526 -0.130526 0.991445 96.3673 40.893)" fill="#FAFAFA" stroke="#999999" stroke-width="1.25556"/>
|
||||
<path d="M94.3796 45.7849C94.7417 43.0349 92.8059 40.5122 90.0559 40.1501L55.2011 35.5614C52.4511 35.1994 49.9284 37.1352 49.5663 39.8851L48.3372 49.2212L93.1505 55.121L94.3796 45.7849Z" fill="#EEEEEE"/>
|
||||
<rect width="1.88333" height="6.27778" rx="0.941667" transform="matrix(-0.130526 0.991445 0.991445 0.130526 40.4766 36.7888)" fill="#999999"/>
|
||||
<rect width="1.88333" height="6.27778" rx="0.941667" transform="matrix(-0.991445 -0.130526 -0.130526 0.991445 57.6758 26.3892)" fill="#999999"/>
|
||||
<rect width="1.88333" height="6.27778" rx="0.941667" transform="matrix(-0.793353 0.608761 0.608761 0.793353 46.6406 28.1023)" fill="#999999"/>
|
||||
<rect width="36.4111" height="2.51111" rx="1.25556" transform="matrix(-0.991445 -0.130526 -0.130526 0.991445 88.4668 57.0371)" fill="#DCDCDC"/>
|
||||
<rect width="36.4111" height="2.51111" rx="1.25556" transform="matrix(-0.991445 -0.130526 -0.130526 0.991445 86.8281 69.4851)" fill="#DCDCDC"/>
|
||||
<rect width="36.4111" height="2.51111" rx="1.25556" transform="matrix(-0.991445 -0.130526 -0.130526 0.991445 85.1895 81.9333)" fill="#DCDCDC"/>
|
||||
<rect width="13.1833" height="2.51111" rx="1.25556" transform="matrix(-0.991445 -0.130526 -0.130526 0.991445 87.8105 62.0164)" fill="#EEEEEE"/>
|
||||
<rect width="13.1833" height="2.51111" rx="1.25556" transform="matrix(-0.991445 -0.130526 -0.130526 0.991445 86.1719 74.4644)" fill="#EEEEEE"/>
|
||||
<rect width="13.1833" height="2.51111" rx="1.25556" transform="matrix(-0.991445 -0.130526 -0.130526 0.991445 84.5332 86.9126)" fill="#EEEEEE"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
@@ -84,7 +84,7 @@ export default function AddToolModal({
|
||||
<h2 className="font-semibold text-xl text-jet dark:text-bright-gray px-3">
|
||||
Select a tool to set up
|
||||
</h2>
|
||||
<div className="mt-5 grid grid-cols-3 gap-4 h-[73vh] overflow-auto px-3 py-px">
|
||||
<div className="mt-5 flex flex-col sm:grid sm:grid-cols-3 gap-4 h-[73vh] overflow-auto px-3 py-px">
|
||||
{availableTools.map((tool, index) => (
|
||||
<div
|
||||
role="button"
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { ActiveState } from '../models/misc';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { ActiveState } from '../models/misc';
|
||||
import WrapperModal from './WrapperModal';
|
||||
function ConfirmationModal({
|
||||
|
||||
export default function ConfirmationModal({
|
||||
message,
|
||||
modalState,
|
||||
setModalState,
|
||||
@@ -59,5 +61,3 @@ function ConfirmationModal({
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default ConfirmationModal;
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import { WrapperModalProps } from './types';
|
||||
import Exit from '../assets/exit.svg';
|
||||
|
||||
const WrapperModal: React.FC<WrapperModalProps> = ({
|
||||
import Exit from '../assets/exit.svg';
|
||||
import { WrapperModalProps } from './types';
|
||||
|
||||
export default function WrapperModal({
|
||||
children,
|
||||
close,
|
||||
isPerformingTask,
|
||||
}) => {
|
||||
}: WrapperModalProps) {
|
||||
const modalRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -39,10 +40,13 @@ const WrapperModal: React.FC<WrapperModalProps> = ({
|
||||
<div className="fixed top-0 left-0 z-30 flex h-screen w-screen items-center justify-center bg-gray-alpha bg-opacity-50">
|
||||
<div
|
||||
ref={modalRef}
|
||||
className="relative w-11/12 rounded-2xl bg-white p-10 dark:bg-outer-space sm:w-[512px]"
|
||||
className="relative w-11/12 rounded-2xl bg-white dark:bg-outer-space sm:w-[512px]"
|
||||
>
|
||||
{!isPerformingTask && (
|
||||
<button className="absolute top-3 right-4 m-2 w-3" onClick={close}>
|
||||
<button
|
||||
className="absolute top-3 right-4 m-2 w-3 z-50"
|
||||
onClick={close}
|
||||
>
|
||||
<img className="filter dark:invert" src={Exit} />
|
||||
</button>
|
||||
)}
|
||||
@@ -50,6 +54,4 @@ const WrapperModal: React.FC<WrapperModalProps> = ({
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default WrapperModal;
|
||||
}
|
||||
|
||||
@@ -58,6 +58,12 @@ export default function ToolConfig({
|
||||
handleGoBack();
|
||||
});
|
||||
};
|
||||
|
||||
const handleDelete = () => {
|
||||
userService.deleteTool({ id: tool.id }).then(() => {
|
||||
handleGoBack();
|
||||
});
|
||||
};
|
||||
return (
|
||||
<div className="mt-8 flex flex-col gap-4">
|
||||
<div className="mb-4 flex items-center gap-3 text-eerie-black dark:text-bright-gray text-sm">
|
||||
@@ -83,7 +89,7 @@ export default function ToolConfig({
|
||||
Authentication
|
||||
</p>
|
||||
)}
|
||||
<div className="mt-4 flex items-center gap-2">
|
||||
<div className="flex mt-4 flex-col sm:flex-row items-start sm:items-center gap-2">
|
||||
{Object.keys(tool?.config).length !== 0 && (
|
||||
<div className="relative w-96">
|
||||
<span className="absolute left-5 -top-2 bg-white px-2 text-xs text-gray-4000 dark:bg-[#26272E] dark:text-silver">
|
||||
@@ -98,12 +104,20 @@ export default function ToolConfig({
|
||||
></Input>
|
||||
</div>
|
||||
)}
|
||||
<button
|
||||
className="rounded-full h-10 w-36 bg-purple-30 text-white hover:bg-[#6F3FD1] text-nowrap text-sm"
|
||||
onClick={handleSaveChanges}
|
||||
>
|
||||
Save changes
|
||||
</button>
|
||||
<div className="flex items-center gap-2">
|
||||
<button
|
||||
className="rounded-full px-5 py-[10px] bg-purple-30 text-white hover:bg-[#6F3FD1] text-nowrap text-sm"
|
||||
onClick={handleSaveChanges}
|
||||
>
|
||||
Save changes
|
||||
</button>
|
||||
<button
|
||||
className="rounded-full px-5 py-[10px] border border-solid border-red-500 text-red-500 hover:bg-red-500 hover:text-white text-nowrap text-sm"
|
||||
onClick={handleDelete}
|
||||
>
|
||||
Delete
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col gap-4">
|
||||
@@ -118,7 +132,7 @@ export default function ToolConfig({
|
||||
key={actionIndex}
|
||||
className="w-full border border-silver dark:border-silver/40 rounded-xl"
|
||||
>
|
||||
<div className="h-10 bg-[#F9F9F9] dark:bg-[#28292D] rounded-t-xl border-b border-silver dark:border-silver/40 flex items-center justify-between px-5">
|
||||
<div className="h-10 bg-[#F9F9F9] dark:bg-[#28292D] rounded-t-xl border-b border-silver dark:border-silver/40 flex items-center justify-between px-5 flex-wrap">
|
||||
<p className="font-semibold text-eerie-black dark:text-bright-gray">
|
||||
{action.name}
|
||||
</p>
|
||||
@@ -146,7 +160,7 @@ export default function ToolConfig({
|
||||
<span className="absolute inset-y-0 start-0 m-[3px] size-[18px] rounded-full bg-white transition-all peer-checked:start-4"></span>
|
||||
</label>
|
||||
</div>
|
||||
<div className="mt-5 relative px-5 w-96">
|
||||
<div className="mt-5 relative px-5 w-full sm:w-96">
|
||||
<Input
|
||||
type="text"
|
||||
placeholder="Enter description"
|
||||
|
||||
@@ -2,13 +2,17 @@ import React from 'react';
|
||||
|
||||
import userService from '../api/services/userService';
|
||||
import CogwheelIcon from '../assets/cogwheel.svg';
|
||||
import NoFilesDarkIcon from '../assets/no-files-dark.svg';
|
||||
import NoFilesIcon from '../assets/no-files.svg';
|
||||
import Input from '../components/Input';
|
||||
import { useDarkTheme } from '../hooks';
|
||||
import AddToolModal from '../modals/AddToolModal';
|
||||
import { ActiveState } from '../models/misc';
|
||||
import { UserTool } from './types';
|
||||
import ToolConfig from './ToolConfig';
|
||||
import { UserTool } from './types';
|
||||
|
||||
export default function Tools() {
|
||||
const [isDarkTheme] = useDarkTheme();
|
||||
const [searchTerm, setSearchTerm] = React.useState('');
|
||||
const [addToolModalState, setAddToolModalState] =
|
||||
React.useState<ActiveState>('INACTIVE');
|
||||
@@ -86,62 +90,77 @@ export default function Tools() {
|
||||
</button>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{userTools
|
||||
.filter((tool) =>
|
||||
tool.displayName
|
||||
.toLowerCase()
|
||||
.includes(searchTerm.toLowerCase()),
|
||||
)
|
||||
.map((tool, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="relative h-56 w-full p-6 border rounded-2xl border-silver dark:border-silver/40 flex flex-col justify-between"
|
||||
>
|
||||
<div className="w-full">
|
||||
<div className="w-full flex items-center justify-between">
|
||||
<img
|
||||
src={`/toolIcons/tool_${tool.name}.svg`}
|
||||
className="h-8 w-8"
|
||||
/>
|
||||
<button
|
||||
className="absolute top-3 right-3 cursor-pointer"
|
||||
onClick={() => handleSettingsClick(tool)}
|
||||
>
|
||||
{userTools.filter((tool) =>
|
||||
tool.displayName
|
||||
.toLowerCase()
|
||||
.includes(searchTerm.toLowerCase()),
|
||||
).length === 0 ? (
|
||||
<div className="mt-24 col-span-2 lg:col-span-3 text-center text-gray-500 dark:text-gray-400">
|
||||
<img
|
||||
src={isDarkTheme ? NoFilesDarkIcon : NoFilesIcon}
|
||||
alt="No tools found"
|
||||
className="h-24 w-24 mx-auto mb-2"
|
||||
/>
|
||||
No tools found
|
||||
</div>
|
||||
) : (
|
||||
userTools
|
||||
.filter((tool) =>
|
||||
tool.displayName
|
||||
.toLowerCase()
|
||||
.includes(searchTerm.toLowerCase()),
|
||||
)
|
||||
.map((tool, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="relative h-56 w-full p-6 border rounded-2xl border-silver dark:border-silver/40 flex flex-col justify-between"
|
||||
>
|
||||
<div className="w-full">
|
||||
<div className="w-full flex items-center justify-between">
|
||||
<img
|
||||
src={CogwheelIcon}
|
||||
alt="settings"
|
||||
className="h-[19px] w-[19px]"
|
||||
src={`/toolIcons/tool_${tool.name}.svg`}
|
||||
className="h-8 w-8"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
className="absolute top-3 right-3 cursor-pointer"
|
||||
onClick={() => handleSettingsClick(tool)}
|
||||
>
|
||||
<img
|
||||
src={CogwheelIcon}
|
||||
alt="settings"
|
||||
className="h-[19px] w-[19px]"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<div className="mt-[9px]">
|
||||
<p className="text-sm font-semibold text-eerie-black dark:text-[#EEEEEE] leading-relaxed">
|
||||
{tool.displayName}
|
||||
</p>
|
||||
<p className="mt-1 h-16 overflow-auto text-[13px] text-gray-600 dark:text-gray-400 leading-relaxed pr-1">
|
||||
{tool.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-[9px]">
|
||||
<p className="text-sm font-semibold text-eerie-black dark:text-[#EEEEEE] leading-relaxed">
|
||||
{tool.displayName}
|
||||
</p>
|
||||
<p className="mt-1 h-16 overflow-auto text-[13px] text-gray-600 dark:text-gray-400 leading-relaxed pr-1">
|
||||
{tool.description}
|
||||
</p>
|
||||
<div className="absolute bottom-3 right-3">
|
||||
<label
|
||||
htmlFor={`toolToggle-${index}`}
|
||||
className="relative inline-block h-6 w-10 cursor-pointer rounded-full bg-gray-300 dark:bg-[#D2D5DA33]/20 transition [-webkit-tap-highlight-color:_transparent] has-[:checked]:bg-[#0C9D35CC] has-[:checked]:dark:bg-[#0C9D35CC]"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
id={`toolToggle-${index}`}
|
||||
className="peer sr-only"
|
||||
checked={tool.status}
|
||||
onChange={() =>
|
||||
updateToolStatus(tool.id, !tool.status)
|
||||
}
|
||||
/>
|
||||
<span className="absolute inset-y-0 start-0 m-[3px] size-[18px] rounded-full bg-white transition-all peer-checked:start-4"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div className="absolute bottom-3 right-3">
|
||||
<label
|
||||
htmlFor={`toolToggle-${index}`}
|
||||
className="relative inline-block h-6 w-10 cursor-pointer rounded-full bg-gray-300 dark:bg-[#D2D5DA33]/20 transition [-webkit-tap-highlight-color:_transparent] has-[:checked]:bg-[#0C9D35CC] has-[:checked]:dark:bg-[#0C9D35CC]"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
id={`toolToggle-${index}`}
|
||||
className="peer sr-only"
|
||||
checked={tool.status}
|
||||
onChange={() =>
|
||||
updateToolStatus(tool.id, !tool.status)
|
||||
}
|
||||
/>
|
||||
<span className="absolute inset-y-0 start-0 m-[3px] size-[18px] rounded-full bg-white transition-all peer-checked:start-4"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<AddToolModal
|
||||
|
||||
Reference in New Issue
Block a user