mirror of
https://github.com/arc53/DocsGPT.git
synced 2026-05-01 14:36:40 +00:00
(fix:responsive) tools and source pop
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import React, { useRef, useEffect, useState } from 'react';
|
import React, { useRef, useEffect, useState, useLayoutEffect } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
import { Doc } from '../models/misc';
|
import { Doc } from '../models/misc';
|
||||||
@@ -32,6 +32,7 @@ export default function SourcesPopup({
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const popupRef = useRef<HTMLDivElement>(null);
|
const popupRef = useRef<HTMLDivElement>(null);
|
||||||
const [searchTerm, setSearchTerm] = useState('');
|
const [searchTerm, setSearchTerm] = useState('');
|
||||||
|
const [popupPosition, setPopupPosition] = useState({ top: 0, left: 0, maxHeight: 0, showAbove: false });
|
||||||
|
|
||||||
const embeddingsName =
|
const embeddingsName =
|
||||||
import.meta.env.VITE_EMBEDDINGS_NAME ||
|
import.meta.env.VITE_EMBEDDINGS_NAME ||
|
||||||
@@ -44,19 +45,36 @@ export default function SourcesPopup({
|
|||||||
option.name.toLowerCase().includes(searchTerm.toLowerCase())
|
option.name.toLowerCase().includes(searchTerm.toLowerCase())
|
||||||
);
|
);
|
||||||
|
|
||||||
const getPopupPosition = () => {
|
useLayoutEffect(() => {
|
||||||
if (!anchorRef.current) return {};
|
if (!isOpen || !anchorRef.current) return;
|
||||||
|
|
||||||
const rect = anchorRef.current.getBoundingClientRect();
|
const updatePosition = () => {
|
||||||
|
if (!anchorRef.current) return;
|
||||||
return {
|
|
||||||
position: 'fixed' as const,
|
const rect = anchorRef.current.getBoundingClientRect();
|
||||||
top: `${rect.top - 8}px`,
|
const viewportHeight = window.innerHeight;
|
||||||
left: `${rect.left}px`,
|
const viewportWidth = window.innerWidth;
|
||||||
minWidth: `${rect.width}px`,
|
const spaceAbove = rect.top;
|
||||||
transform: 'translateY(-100%)',
|
const spaceBelow = viewportHeight - rect.bottom;
|
||||||
|
const showAbove = spaceAbove > spaceBelow && spaceAbove >= 300;
|
||||||
|
const maxHeight = showAbove ? spaceAbove - 16 : spaceBelow - 16;
|
||||||
|
const left = Math.min(
|
||||||
|
rect.left,
|
||||||
|
viewportWidth - Math.min(480, viewportWidth * 0.95) - 10
|
||||||
|
);
|
||||||
|
|
||||||
|
setPopupPosition({
|
||||||
|
top: showAbove ? rect.top - 8 : rect.bottom + 8,
|
||||||
|
left,
|
||||||
|
maxHeight: Math.min(600, maxHeight),
|
||||||
|
showAbove
|
||||||
|
});
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
updatePosition();
|
||||||
|
window.addEventListener('resize', updatePosition);
|
||||||
|
return () => window.removeEventListener('resize', updatePosition);
|
||||||
|
}, [isOpen, anchorRef]);
|
||||||
|
|
||||||
const handleEmptyDocumentSelect = () => {
|
const handleEmptyDocumentSelect = () => {
|
||||||
dispatch(setSelectedDocs(null));
|
dispatch(setSelectedDocs(null));
|
||||||
@@ -93,112 +111,118 @@ export default function SourcesPopup({
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={popupRef}
|
ref={popupRef}
|
||||||
style={getPopupPosition()}
|
className="fixed z-50 bg-lotion dark:bg-charleston-green-2 rounded-xl shadow-[0px_9px_46px_8px_#0000001F,0px_24px_38px_3px_#00000024,0px_11px_15px_-7px_#00000033] flex flex-col"
|
||||||
className="bg-lotion dark:bg-charleston-green-2 rounded-xl shadow-[0px_9px_46px_8px_#0000001F,0px_24px_38px_3px_#00000024,0px_11px_15px_-7px_#00000033] w-full max-w-[95vw] md:max-w-md flex flex-col z-50 fixed"
|
style={{
|
||||||
|
top: popupPosition.showAbove ? popupPosition.top : undefined,
|
||||||
|
bottom: popupPosition.showAbove ? undefined : window.innerHeight - popupPosition.top,
|
||||||
|
left: popupPosition.left,
|
||||||
|
maxWidth: Math.min(480, window.innerWidth * 0.95),
|
||||||
|
width: '100%',
|
||||||
|
height: popupPosition.maxHeight,
|
||||||
|
transform: popupPosition.showAbove ? 'translateY(-100%)' : 'none',
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<div className="px-4 md:px-6 py-4">
|
<div className="flex flex-col h-full">
|
||||||
<h2 className="text-lg font-bold text-[#141414] dark:text-bright-gray mb-4 dark:text-[20px]">
|
<div className="px-4 md:px-6 py-4 flex-shrink-0">
|
||||||
{t('conversation.sources.text')}
|
<h2 className="text-lg font-bold text-[#141414] dark:text-bright-gray mb-4 dark:text-[20px]">
|
||||||
</h2>
|
{t('conversation.sources.text')}
|
||||||
|
</h2>
|
||||||
<Input
|
|
||||||
id="source-search"
|
<Input
|
||||||
name="source-search"
|
id="source-search"
|
||||||
type="text"
|
name="source-search"
|
||||||
value={searchTerm}
|
type="text"
|
||||||
onChange={(e) => setSearchTerm(e.target.value)}
|
value={searchTerm}
|
||||||
placeholder={t('settings.documents.searchPlaceholder')}
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
borderVariant="thin"
|
placeholder={t('settings.documents.searchPlaceholder')}
|
||||||
className="mb-4"
|
borderVariant="thin"
|
||||||
labelBgClassName="bg-lotion dark:bg-charleston-green-2"
|
className="mb-4"
|
||||||
/>
|
labelBgClassName="bg-lotion dark:bg-charleston-green-2"
|
||||||
</div>
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="overflow-y-auto mx-4 border border-[#D9D9D9] dark:border-dim-gray rounded-md [&::-webkit-scrollbar-thumb]:bg-[#888] [&::-webkit-scrollbar-thumb]:hover:bg-[#555] [&::-webkit-scrollbar-track]:bg-[#E2E8F0] dark:[&::-webkit-scrollbar-track]:bg-[#2C2E3C]"
|
<div className="flex-grow overflow-y-auto mx-4 border border-[#D9D9D9] dark:border-dim-gray rounded-md [&::-webkit-scrollbar-thumb]:bg-[#888] [&::-webkit-scrollbar-thumb]:hover:bg-[#555] [&::-webkit-scrollbar-track]:bg-[#E2E8F0] dark:[&::-webkit-scrollbar-track]:bg-[#2C2E3C]">
|
||||||
style={{
|
{options ? (
|
||||||
height: 'min(488px, calc(100vh - 220px))',
|
<>
|
||||||
maxHeight: 'calc(100vh - 220px)'
|
{filteredOptions?.map((option: any, index: number) => {
|
||||||
}}>
|
if (option.model === embeddingsName) {
|
||||||
{options ? (
|
return (
|
||||||
<>
|
<div
|
||||||
{filteredOptions?.map((option: any, index: number) => {
|
key={index}
|
||||||
if (option.model === embeddingsName) {
|
className="flex cursor-pointer items-center p-3 hover:bg-gray-100 dark:hover:bg-[#2C2E3C] transition-colors border-b border-[#D9D9D9] dark:border-dim-gray border-opacity-80 dark:text-[14px]"
|
||||||
return (
|
onClick={() => {
|
||||||
<div
|
dispatch(setSelectedDocs(option));
|
||||||
key={index}
|
handlePostDocumentSelect(option);
|
||||||
className="flex cursor-pointer items-center p-3 hover:bg-gray-100 dark:hover:bg-[#2C2E3C] transition-colors border-b border-[#D9D9D9] dark:border-dim-gray border-opacity-80 dark:text-[14px]"
|
onClose();
|
||||||
onClick={() => {
|
}}
|
||||||
dispatch(setSelectedDocs(option));
|
>
|
||||||
handlePostDocumentSelect(option);
|
<img
|
||||||
onClose();
|
src={SourceIcon}
|
||||||
}}
|
alt="Source"
|
||||||
>
|
width={14} height={14}
|
||||||
<img
|
className="mr-3 flex-shrink-0"
|
||||||
src={SourceIcon}
|
/>
|
||||||
alt="Source"
|
<span className="text-[#5D5D5D] dark:text-bright-gray font-medium flex-grow overflow-hidden overflow-ellipsis whitespace-nowrap mr-3">
|
||||||
width={14} height={14}
|
{option.name}
|
||||||
className="mr-3 flex-shrink-0"
|
</span>
|
||||||
/>
|
<div className={`w-4 h-4 border flex-shrink-0 flex items-center justify-center p-[0.5px] dark:border-[#757783] border-[#C6C6C6]`}>
|
||||||
<span className="text-[#5D5D5D] dark:text-bright-gray font-medium flex-grow overflow-hidden overflow-ellipsis whitespace-nowrap mr-3">
|
{selectedDocs &&
|
||||||
{option.name}
|
(option.id ?
|
||||||
</span>
|
selectedDocs.id === option.id : // For documents with MongoDB IDs
|
||||||
<div className={`w-4 h-4 border flex-shrink-0 flex items-center justify-center p-[0.5px] dark:border-[#757783] border-[#C6C6C6]`}>
|
selectedDocs.date === option.date) && // For preloaded sources
|
||||||
{selectedDocs &&
|
<img
|
||||||
(option.id ?
|
src={CheckIcon}
|
||||||
selectedDocs.id === option.id : // For documents with MongoDB IDs
|
alt="Selected"
|
||||||
selectedDocs.date === option.date) && // For preloaded sources
|
className="h-3 w-3"
|
||||||
<img
|
/>
|
||||||
src={CheckIcon}
|
}
|
||||||
alt="Selected"
|
</div>
|
||||||
className="h-3 w-3"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
);
|
||||||
);
|
}
|
||||||
}
|
return null;
|
||||||
return null;
|
})}
|
||||||
})}
|
<div
|
||||||
<div
|
className="flex cursor-pointer items-center p-3 hover:bg-gray-100 dark:hover:bg-[#2C2E3C] transition-colors border-b border-[#D9D9D9] dark:border-dim-gray border-opacity-80 dark:text-[14px]"
|
||||||
className="flex cursor-pointer items-center p-3 hover:bg-gray-100 dark:hover:bg-[#2C2E3C] transition-colors border-b border-[#D9D9D9] dark:border-dim-gray border-opacity-80 dark:text-[14px]"
|
onClick={handleEmptyDocumentSelect}
|
||||||
onClick={handleEmptyDocumentSelect}
|
>
|
||||||
>
|
<img width={14} height={14} src={SourceIcon} alt="Source" className="mr-3 flex-shrink-0" />
|
||||||
<img width={14} height={14} src={SourceIcon} alt="Source" className="mr-3 flex-shrink-0" />
|
<span className="text-[#5D5D5D] dark:text-bright-gray font-medium flex-grow mr-3">
|
||||||
<span className="text-[#5D5D5D] dark:text-bright-gray font-medium flex-grow mr-3">
|
{t('none')}
|
||||||
{t('none')}
|
</span>
|
||||||
</span>
|
<div className={`w-4 h-4 border flex-shrink-0 flex items-center justify-center p-[0.5px] dark:border-[#757783] border-[#C6C6C6]`}>
|
||||||
<div className={`w-4 h-4 border flex-shrink-0 flex items-center justify-center p-[0.5px] dark:border-[#757783] border-[#C6C6C6]`}>
|
{selectedDocs === null && (
|
||||||
{selectedDocs === null && (
|
<img src={CheckIcon} alt="Selected" className="h-3 w-3" />
|
||||||
<img src={CheckIcon} alt="Selected" className="h-3 w-3" />
|
)}
|
||||||
)}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<div className="p-4 text-center text-gray-500 dark:text-bright-gray dark:text-[14px]">
|
||||||
|
{t('noSourcesAvailable')}
|
||||||
</div>
|
</div>
|
||||||
</>
|
)}
|
||||||
) : (
|
</div>
|
||||||
<div className="p-4 text-center text-gray-500 dark:text-bright-gray dark:text-[14px]">
|
|
||||||
{t('noSourcesAvailable')}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="px-4 md:px-6 py-4 opacity-75 hover:opacity-100 transition-opacity duration-200">
|
<div className="px-4 md:px-6 py-4 opacity-75 hover:opacity-100 transition-opacity duration-200 flex-shrink-0">
|
||||||
<a
|
<a
|
||||||
href="/settings/documents"
|
href="/settings/documents"
|
||||||
className="text-violets-are-blue text-base font-medium flex items-center gap-2"
|
className="text-violets-are-blue text-base font-medium flex items-center gap-2"
|
||||||
onClick={onClose}
|
onClick={onClose}
|
||||||
>
|
>
|
||||||
Go to Documents
|
Go to Documents
|
||||||
<img src={RedirectIcon} alt="Redirect" className="w-3 h-3" />
|
<img src={RedirectIcon} alt="Redirect" className="w-3 h-3" />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="px-4 md:px-6 py-3 flex justify-start">
|
<div className="px-4 md:px-6 py-3 flex justify-start flex-shrink-0">
|
||||||
<button
|
<button
|
||||||
onClick={handleUploadClick}
|
onClick={handleUploadClick}
|
||||||
className="py-2 px-4 rounded-full border text-violets-are-blue hover:bg-violets-are-blue border-violets-are-blue hover:text-white transition-colors duration-200 text-[14px] font-medium w-auto"
|
className="py-2 px-4 rounded-full border text-violets-are-blue hover:bg-violets-are-blue border-violets-are-blue hover:text-white transition-colors duration-200 text-[14px] font-medium w-auto"
|
||||||
>
|
>
|
||||||
Upload new
|
Upload new
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export default function ToolsPopup({
|
|||||||
const [searchTerm, setSearchTerm] = useState('');
|
const [searchTerm, setSearchTerm] = useState('');
|
||||||
const [isDarkTheme] = useDarkTheme();
|
const [isDarkTheme] = useDarkTheme();
|
||||||
const popupRef = useRef<HTMLDivElement>(null);
|
const popupRef = useRef<HTMLDivElement>(null);
|
||||||
const [popupPosition, setPopupPosition] = useState({ bottom: 0, left: 0 });
|
const [popupPosition, setPopupPosition] = useState({ top: 0, left: 0, maxHeight: 0, showAbove: false });
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
if (!isOpen || !anchorRef.current) return;
|
if (!isOpen || !anchorRef.current) return;
|
||||||
@@ -38,15 +38,24 @@ export default function ToolsPopup({
|
|||||||
if (!anchorRef.current) return;
|
if (!anchorRef.current) return;
|
||||||
|
|
||||||
const rect = anchorRef.current.getBoundingClientRect();
|
const rect = anchorRef.current.getBoundingClientRect();
|
||||||
|
const viewportHeight = window.innerHeight;
|
||||||
|
const viewportWidth = window.innerWidth;
|
||||||
|
|
||||||
|
const spaceAbove = rect.top;
|
||||||
|
const spaceBelow = viewportHeight - rect.bottom;
|
||||||
|
const showAbove = spaceAbove > spaceBelow && spaceAbove >= 300;
|
||||||
|
const maxHeight = showAbove ? spaceAbove - 16 : spaceBelow - 16;
|
||||||
|
|
||||||
|
const left = Math.min(
|
||||||
|
rect.left,
|
||||||
|
viewportWidth - Math.min(462, viewportWidth * 0.95) - 10
|
||||||
|
);
|
||||||
|
|
||||||
setPopupPosition({
|
setPopupPosition({
|
||||||
bottom: Math.min(
|
top: showAbove ? rect.top - 8 : rect.bottom + 8,
|
||||||
window.innerHeight - rect.top + 10,
|
left,
|
||||||
window.innerHeight - 20
|
maxHeight: Math.min(600, maxHeight),
|
||||||
),
|
showAbove
|
||||||
left: Math.min(
|
|
||||||
rect.left,
|
|
||||||
window.innerWidth - Math.min(462, window.innerWidth * 0.95) - 10
|
|
||||||
)
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -67,11 +76,13 @@ export default function ToolsPopup({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
document.addEventListener('mousedown', handleClickOutside);
|
if (isOpen) {
|
||||||
|
document.addEventListener('mousedown', handleClickOutside);
|
||||||
|
}
|
||||||
return () => {
|
return () => {
|
||||||
document.removeEventListener('mousedown', handleClickOutside);
|
document.removeEventListener('mousedown', handleClickOutside);
|
||||||
};
|
};
|
||||||
}, [onClose, anchorRef]);
|
}, [onClose, anchorRef, isOpen]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isOpen) {
|
if (isOpen) {
|
||||||
@@ -113,45 +124,51 @@ export default function ToolsPopup({
|
|||||||
|
|
||||||
if (!isOpen) return null;
|
if (!isOpen) return null;
|
||||||
|
|
||||||
|
const filteredTools = userTools.filter((tool) =>
|
||||||
|
tool.displayName.toLowerCase().includes(searchTerm.toLowerCase())
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={popupRef}
|
ref={popupRef}
|
||||||
className="absolute z-10 w-[462px] max-w-[95vw] rounded-lg border border-light-silver dark:border-dim-gray bg-lotion dark:bg-charleston-green-2 shadow-[0px_9px_46px_8px_#0000001F,0px_24px_38px_3px_#00000024,0px_11px_15px_-7px_#00000033]"
|
className="fixed z-[9999] rounded-lg border border-light-silver dark:border-dim-gray bg-lotion dark:bg-charleston-green-2 shadow-[0px_9px_46px_8px_#0000001F,0px_24px_38px_3px_#00000024,0px_11px_15px_-7px_#00000033]"
|
||||||
style={{
|
style={{
|
||||||
bottom: popupPosition.bottom,
|
top: popupPosition.showAbove ? popupPosition.top : undefined,
|
||||||
|
bottom: popupPosition.showAbove ? undefined : window.innerHeight - popupPosition.top,
|
||||||
left: popupPosition.left,
|
left: popupPosition.left,
|
||||||
position: 'fixed',
|
maxWidth: Math.min(462, window.innerWidth * 0.95),
|
||||||
zIndex: 9999,
|
width: '100%',
|
||||||
|
height: popupPosition.maxHeight,
|
||||||
|
transform: popupPosition.showAbove ? 'translateY(-100%)' : 'none',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="p-4">
|
<div className="flex flex-col h-full">
|
||||||
<h3 className="text-lg font-medium text-gray-900 dark:text-white mb-4">
|
<div className="p-4 flex-shrink-0">
|
||||||
{t('settings.tools.label')}
|
<h3 className="text-lg font-medium text-gray-900 dark:text-white mb-4">
|
||||||
</h3>
|
{t('settings.tools.label')}
|
||||||
|
</h3>
|
||||||
|
|
||||||
<Input
|
<Input
|
||||||
id="tool-search"
|
id="tool-search"
|
||||||
name="tool-search"
|
name="tool-search"
|
||||||
type="text"
|
type="text"
|
||||||
value={searchTerm}
|
value={searchTerm}
|
||||||
onChange={(e) => setSearchTerm(e.target.value)}
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
placeholder={t('settings.tools.searchPlaceholder')}
|
placeholder={t('settings.tools.searchPlaceholder')}
|
||||||
labelBgClassName="bg-lotion dark:bg-charleston-green-2"
|
labelBgClassName="bg-lotion dark:bg-charleston-green-2"
|
||||||
borderVariant="thin"
|
borderVariant="thin"
|
||||||
className="mb-4"
|
className="mb-4"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<div className="flex justify-center py-4">
|
<div className="flex justify-center py-4 flex-grow">
|
||||||
<div className="animate-spin rounded-full h-6 w-6 border-b-2 border-gray-900 dark:border-white"></div>
|
<div className="animate-spin rounded-full h-6 w-6 border-b-2 border-gray-900 dark:border-white"></div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="border border-[#D9D9D9] dark:border-dim-gray rounded-md overflow-hidden">
|
<div className="mx-4 border border-[#D9D9D9] dark:border-dim-gray rounded-md overflow-hidden flex-grow">
|
||||||
<div
|
<div className="h-full overflow-y-auto [&::-webkit-scrollbar-thumb]:bg-[#888] [&::-webkit-scrollbar-thumb]:hover:bg-[#555] [&::-webkit-scrollbar-track]:bg-[#E2E8F0] dark:[&::-webkit-scrollbar-track]:bg-[#2C2E3C]">
|
||||||
className="h-[calc(min(480px,100vh-220px))] overflow-y-auto [&::-webkit-scrollbar-thumb]:bg-[#888] [&::-webkit-scrollbar-thumb]:hover:bg-[#555] [&::-webkit-scrollbar-track]:bg-[#E2E8F0] dark:[&::-webkit-scrollbar-track]:bg-[#2C2E3C]"
|
{filteredTools.length === 0 ? (
|
||||||
|
|
||||||
>
|
|
||||||
{userTools.length === 0 ? (
|
|
||||||
<div className="flex flex-col items-center justify-center h-full py-8">
|
<div className="flex flex-col items-center justify-center h-full py-8">
|
||||||
<img
|
<img
|
||||||
src={isDarkTheme ? NoFilesDarkIcon : NoFilesIcon}
|
src={isDarkTheme ? NoFilesDarkIcon : NoFilesIcon}
|
||||||
@@ -163,50 +180,44 @@ export default function ToolsPopup({
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
userTools
|
filteredTools.map((tool) => (
|
||||||
.filter((tool) =>
|
<div
|
||||||
tool.displayName
|
key={tool.id}
|
||||||
.toLowerCase()
|
onClick={() => updateToolStatus(tool.id, !tool.status)}
|
||||||
.includes(searchTerm.toLowerCase()),
|
className="flex items-center justify-between p-3 border-b border-[#D9D9D9] dark:border-dim-gray hover:bg-gray-100 dark:hover:bg-charleston-green-3"
|
||||||
)
|
>
|
||||||
.map((tool) => (
|
<div className="flex items-center flex-grow mr-3">
|
||||||
<div
|
<img
|
||||||
key={tool.id}
|
src={`/toolIcons/tool_${tool.name}.svg`}
|
||||||
onClick={() => updateToolStatus(tool.id, !tool.status)}
|
alt={`${tool.displayName} icon`}
|
||||||
className="flex items-center justify-between p-3 border-b border-[#D9D9D9] dark:border-dim-gray hover:bg-gray-100 dark:hover:bg-charleston-green-3"
|
className="h-5 w-5 mr-4 flex-shrink-0"
|
||||||
>
|
/>
|
||||||
<div className="flex items-center flex-grow mr-3">
|
<div className="overflow-hidden">
|
||||||
<img
|
<p className="text-xs font-medium text-gray-900 dark:text-white overflow-hidden overflow-ellipsis whitespace-nowrap">
|
||||||
src={`/toolIcons/tool_${tool.name}.svg`}
|
{tool.displayName}
|
||||||
alt={`${tool.displayName} icon`}
|
</p>
|
||||||
className="h-5 w-5 mr-4 flex-shrink-0"
|
|
||||||
/>
|
|
||||||
<div className="overflow-hidden">
|
|
||||||
<p className="text-xs font-medium text-gray-900 dark:text-white overflow-hidden overflow-ellipsis whitespace-nowrap">
|
|
||||||
{tool.displayName}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center flex-shrink-0">
|
|
||||||
<div className={`w-4 h-4 border flex items-center justify-center p-[0.5px] dark:border-[#757783] border-[#C6C6C6]`}>
|
|
||||||
{tool.status && (
|
|
||||||
<img
|
|
||||||
src={CheckmarkIcon}
|
|
||||||
alt="Tool enabled"
|
|
||||||
width={12}
|
|
||||||
height={12}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))
|
<div className="flex items-center flex-shrink-0">
|
||||||
|
<div className={`w-4 h-4 border flex items-center justify-center p-[0.5px] dark:border-[#757783] border-[#C6C6C6]`}>
|
||||||
|
{tool.status && (
|
||||||
|
<img
|
||||||
|
src={CheckmarkIcon}
|
||||||
|
alt="Tool enabled"
|
||||||
|
width={12}
|
||||||
|
height={12}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="mt-4 flex justify-start">
|
<div className="p-4 flex-shrink-0">
|
||||||
<a
|
<a
|
||||||
href="/settings/tools"
|
href="/settings/tools"
|
||||||
className="text-base text-purple-30 font-medium hover:text-violets-are-blue flex items-center"
|
className="text-base text-purple-30 font-medium hover:text-violets-are-blue flex items-center"
|
||||||
@@ -222,4 +233,4 @@ export default function ToolsPopup({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user