mirror of
https://github.com/arc53/DocsGPT.git
synced 2025-11-29 08:33:20 +00:00
(fix:ui) tool cards
This commit is contained in:
@@ -8,10 +8,10 @@ export type InputProps = {
|
|||||||
maxLength?: number;
|
maxLength?: number;
|
||||||
name?: string;
|
name?: string;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
label?: string;
|
|
||||||
required?: boolean;
|
required?: boolean;
|
||||||
className?: string;
|
className?: string;
|
||||||
children?: React.ReactElement;
|
children?: React.ReactElement;
|
||||||
|
labelBgClassName?: string;
|
||||||
onChange: (
|
onChange: (
|
||||||
e: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>,
|
e: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>,
|
||||||
) => void;
|
) => void;
|
||||||
|
|||||||
@@ -94,57 +94,60 @@ export default function AddToolModal({
|
|||||||
{modalState === 'ACTIVE' && (
|
{modalState === 'ACTIVE' && (
|
||||||
<WrapperComponent
|
<WrapperComponent
|
||||||
close={() => setModalState('INACTIVE')}
|
close={() => setModalState('INACTIVE')}
|
||||||
className="h-[85vh] w-[90vw] md:w-[75vw]"
|
className="max-w-[950px] w-[90vw] md:w-[85vw] lg:w-[75vw] h-[85vh]"
|
||||||
>
|
>
|
||||||
<div className="flex flex-col gap-4 h-full">
|
<div className="flex flex-col h-full">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="font-semibold text-xl text-jet dark:text-bright-gray px-3">
|
<h2 className="font-semibold text-xl text-jet dark:text-bright-gray px-3">
|
||||||
{t('settings.tools.selectToolSetup')}
|
{t('settings.tools.selectToolSetup')}
|
||||||
</h2>
|
</h2>
|
||||||
<div className="mt-5 flex flex-col sm:grid sm:grid-cols-3 gap-4 h-[73vh] overflow-auto px-3 py-px">
|
<div className="mt-5 h-[73vh] overflow-auto px-3 py-px">
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<div className="h-full col-span-3 flex items-center justify-center">
|
<div className="h-full flex items-center justify-center">
|
||||||
<Spinner />
|
<Spinner />
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
availableTools.map((tool, index) => (
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 auto-rows-fr">
|
||||||
<div
|
{availableTools.map((tool, index) => (
|
||||||
role="button"
|
<div
|
||||||
tabIndex={0}
|
role="button"
|
||||||
key={index}
|
tabIndex={0}
|
||||||
className="h-52 w-full p-6 border rounded-2xl border-silver dark:border-[#4D4E58] flex flex-col justify-between dark:bg-[#32333B] cursor-pointer hover:border-[#9d9d9d] hover:dark:border-[#717179]"
|
key={index}
|
||||||
onClick={() => {
|
className="h-52 w-full p-6 border rounded-2xl border-light-gainsboro dark:border-arsenic bg-white-3000 dark:bg-gunmetal flex flex-col justify-between cursor-pointer hover:border-[#9d9d9d] hover:dark:border-[#717179]"
|
||||||
setSelectedTool(tool);
|
onClick={() => {
|
||||||
handleAddTool(tool);
|
|
||||||
}}
|
|
||||||
onKeyDown={(e) => {
|
|
||||||
if (e.key === 'Enter' || e.key === ' ') {
|
|
||||||
setSelectedTool(tool);
|
setSelectedTool(tool);
|
||||||
handleAddTool(tool);
|
handleAddTool(tool);
|
||||||
}
|
}}
|
||||||
}}
|
onKeyDown={(e) => {
|
||||||
>
|
if (e.key === 'Enter' || e.key === ' ') {
|
||||||
<div className="w-full">
|
setSelectedTool(tool);
|
||||||
<div className="px-1 w-full flex items-center justify-between">
|
handleAddTool(tool);
|
||||||
<img
|
}
|
||||||
src={`/toolIcons/tool_${tool.name}.svg`}
|
}}
|
||||||
className="h-8 w-8"
|
>
|
||||||
/>
|
<div className="w-full">
|
||||||
</div>
|
<div className="px-1 w-full flex items-center justify-between">
|
||||||
<div className="mt-[9px]">
|
<img
|
||||||
<p
|
src={`/toolIcons/tool_${tool.name}.svg`}
|
||||||
title={tool.displayName}
|
className="h-6 w-6"
|
||||||
className="px-1 text-sm font-semibold text-eerie-black dark:text-white leading-relaxed capitalize truncate"
|
alt={`${tool.name} icon`}
|
||||||
>
|
/>
|
||||||
{tool.displayName}
|
</div>
|
||||||
</p>
|
<div className="mt-[9px]">
|
||||||
<p className="mt-1 px-1 h-24 overflow-auto text-sm text-gray-600 dark:text-[#8a8a8c] leading-relaxed">
|
<p
|
||||||
{tool.description}
|
title={tool.displayName}
|
||||||
</p>
|
className="px-1 text-[13px] font-semibold text-raisin-black-light dark:text-bright-gray leading-relaxed capitalize truncate"
|
||||||
|
>
|
||||||
|
{tool.displayName}
|
||||||
|
</p>
|
||||||
|
<p className="mt-1 px-1 h-24 overflow-auto text-[12px] text-old-silver dark:text-sonic-silver-light leading-relaxed">
|
||||||
|
{tool.description}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
))}
|
||||||
))
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,19 +3,16 @@ import { useTranslation } from 'react-i18next';
|
|||||||
|
|
||||||
import userService from '../api/services/userService';
|
import userService from '../api/services/userService';
|
||||||
import CogwheelIcon from '../assets/cogwheel.svg';
|
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 Input from '../components/Input';
|
||||||
import Spinner from '../components/Spinner';
|
import Spinner from '../components/Spinner';
|
||||||
import { useDarkTheme } from '../hooks';
|
|
||||||
import AddToolModal from '../modals/AddToolModal';
|
import AddToolModal from '../modals/AddToolModal';
|
||||||
import { ActiveState } from '../models/misc';
|
import { ActiveState } from '../models/misc';
|
||||||
import ToolConfig from './ToolConfig';
|
import ToolConfig from './ToolConfig';
|
||||||
import { APIToolType, UserToolType } from './types';
|
import { APIToolType, UserToolType } from './types';
|
||||||
|
import ToggleSwitch from '../components/ToggleSwitch';
|
||||||
|
|
||||||
export default function Tools() {
|
export default function Tools() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [isDarkTheme] = useDarkTheme();
|
|
||||||
const [searchTerm, setSearchTerm] = React.useState('');
|
const [searchTerm, setSearchTerm] = React.useState('');
|
||||||
const [addToolModalState, setAddToolModalState] =
|
const [addToolModalState, setAddToolModalState] =
|
||||||
React.useState<ActiveState>('INACTIVE');
|
React.useState<ActiveState>('INACTIVE');
|
||||||
@@ -114,7 +111,7 @@ export default function Tools() {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
className="rounded-full min-w-[160px] bg-purple-30 px-6 py-3 text-white hover:bg-[#6F3FD1] text-nowrap"
|
className="rounded-full w-[108px] h-[30px] text-sm bg-purple-30 text-white hover:bg-[#6F3FD1] flex items-center justify-center"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setAddToolModalState('ACTIVE');
|
setAddToolModalState('ACTIVE');
|
||||||
}}
|
}}
|
||||||
@@ -122,6 +119,7 @@ export default function Tools() {
|
|||||||
{t('settings.tools.addTool')}
|
{t('settings.tools.addTool')}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="border-b border-light-silver dark:border-dim-gray mb-8 mt-5" />
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<div className="grid grid-cols-2 lg:grid-cols-3 gap-6">
|
<div className="grid grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
<div className="mt-24 h-32 col-span-2 lg:col-span-3 flex items-center justify-center">
|
<div className="mt-24 h-32 col-span-2 lg:col-span-3 flex items-center justify-center">
|
||||||
@@ -129,90 +127,66 @@ export default function Tools() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="grid grid-cols-2 lg:grid-cols-3 gap-6">
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 gap-4">
|
||||||
{userTools.filter((tool) =>
|
{userTools
|
||||||
tool.displayName
|
.filter((tool) =>
|
||||||
.toLowerCase()
|
tool.displayName
|
||||||
.includes(searchTerm.toLowerCase()),
|
.toLowerCase()
|
||||||
).length === 0 ? (
|
.includes(searchTerm.toLowerCase()),
|
||||||
<div className="mt-24 col-span-2 lg:col-span-3 text-center text-gray-500 dark:text-gray-400">
|
)
|
||||||
<img
|
.map((tool, index) => (
|
||||||
src={isDarkTheme ? NoFilesDarkIcon : NoFilesIcon}
|
<div
|
||||||
alt="No tools found"
|
key={index}
|
||||||
className="h-24 w-24 mx-auto mb-2"
|
className="relative h-52 border rounded-2xl border-light-gainsboro dark:border-arsenic"
|
||||||
/>
|
>
|
||||||
{t('settings.tools.noToolsFound')}
|
<div className="h-full flex flex-col p-6">
|
||||||
</div>
|
<button
|
||||||
) : (
|
onClick={() => handleSettingsClick(tool)}
|
||||||
userTools
|
aria-label={t('settings.tools.configureToolAria', {
|
||||||
.filter((tool) =>
|
toolName: tool.displayName,
|
||||||
tool.displayName
|
})}
|
||||||
.toLowerCase()
|
className="absolute top-4 right-4"
|
||||||
.includes(searchTerm.toLowerCase()),
|
>
|
||||||
)
|
<img
|
||||||
.map((tool, index) => (
|
src={CogwheelIcon}
|
||||||
<div
|
alt={t('settings.tools.settingsIconAlt')}
|
||||||
key={index}
|
className="h-[19px] w-[19px]"
|
||||||
className="relative h-56 w-full p-6 border rounded-2xl border-silver dark:border-silver/40 flex flex-col justify-between"
|
/>
|
||||||
>
|
</button>
|
||||||
<div className="w-full">
|
<div className="flex-1">
|
||||||
<div className="w-full flex items-center justify-between">
|
<div className="flex flex-col items-start space-y-3">
|
||||||
<img
|
<img
|
||||||
src={`/toolIcons/tool_${tool.name}.svg`}
|
src={`/toolIcons/tool_${tool.name}.svg`}
|
||||||
alt={`${tool.displayName} icon`}
|
alt={`${tool.displayName} icon`}
|
||||||
className="h-8 w-8"
|
className="h-6 w-6"
|
||||||
/>
|
/>
|
||||||
<button
|
<p
|
||||||
className="absolute top-3 right-3 cursor-pointer"
|
title={tool.displayName}
|
||||||
onClick={() => handleSettingsClick(tool)}
|
className="w-[calc(100%-24px)] text-[13px] font-semibold text-raisin-black-light dark:text-bright-gray capitalize truncate"
|
||||||
aria-label={t(
|
|
||||||
'settings.tools.configureToolAria',
|
|
||||||
{
|
|
||||||
toolName: tool.displayName,
|
|
||||||
},
|
|
||||||
)}
|
|
||||||
>
|
>
|
||||||
<img
|
|
||||||
src={CogwheelIcon}
|
|
||||||
alt={t('settings.tools.settingsIconAlt')}
|
|
||||||
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}
|
{tool.displayName}
|
||||||
</p>
|
</p>
|
||||||
<p className="mt-1 h-16 overflow-auto text-[13px] text-gray-600 dark:text-gray-400 leading-relaxed pr-1">
|
<p className="h-20 overflow-auto text-[12px] text-old-silver dark:text-sonic-silver-light">
|
||||||
{tool.description}
|
{tool.description}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="absolute bottom-3 right-3">
|
<div className="flex justify-end pt-2">
|
||||||
<label
|
<ToggleSwitch
|
||||||
htmlFor={`toolToggle-${index}`}
|
checked={tool.status}
|
||||||
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]"
|
onChange={(checked) =>
|
||||||
>
|
updateToolStatus(tool.id, checked)
|
||||||
<span className="sr-only">
|
}
|
||||||
{t('settings.tools.toggleToolAria', {
|
size="small"
|
||||||
toolName: tool.displayName,
|
id={`toolToggle-${index}`}
|
||||||
})}
|
ariaLabel={t('settings.tools.toggleToolAria', {
|
||||||
</span>
|
toolName: tool.displayName,
|
||||||
<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>
|
||||||
))
|
</div>
|
||||||
)}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user