mirror of
https://github.com/arc53/DocsGPT.git
synced 2025-11-29 08:33:20 +00:00
Merge branch 'main' of https://github.com/arc53/DocsGPT into dependabot/npm_and_yarn/frontend/tailwindcss-4.1.10
This commit is contained in:
1
frontend/public/toolIcons/tool_duckduckgo.svg
Normal file
1
frontend/public/toolIcons/tool_duckduckgo.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 122.88 122.88"><defs><style>.a{fill:#d53;}.b{fill:#fff;}.c{fill:#ddd;}.d{fill:#fc0;}.e{fill:#6b5;}.f{fill:#4a4;}.g{fill:#148;}</style></defs><title>duckduckgo</title><path class="a" d="M122.88,61.44a61.44,61.44,0,1,0-61.44,61.44,61.44,61.44,0,0,0,61.44-61.44Z"/><path class="b" d="M114.37,61.44a52.92,52.92,0,1,0-15.5,37.43,52.76,52.76,0,0,0,15.5-37.43Zm-13.12-39.8A56.29,56.29,0,1,1,61.44,5.15a56.12,56.12,0,0,1,39.81,16.49Z"/><path class="c" d="M43.24,30.15C26.17,34.13,32.43,58,32.43,58l10.81,52.9,4,1.71-4-82.49Zm-4-10.24H34.7L41,22.19s-6.26,0-6.26,4C48.36,25.6,54.61,29,54.61,29l-15.36-9.1Zm0,0Z"/><path class="b" d="M75.66,115.48S62,93.87,62,79.64c0-26.73,17.63-4,17.63-25S62,28.44,62,28.44c-8.53-10.8-25-8.53-25-8.53l4,2.28s-4,1.13-5.12,2.27,10.81-1.7,15.93,2.85C30.72,29,34.13,46.08,34.13,46.08l11.95,68.27,29.58,1.13Zm0,0Z"/><path class="d" d="M75.66,60.87l21.62-5.69C116.62,58,80.78,68.84,78.51,68.27c-17.07-2.85-12,11.37,8.53,6.82s5.12,11.38-13.65,5.12c-26.74-7.39-12.52-20.48,2.27-19.34Z"/><path class="e" d="M70,105.81l1.14-1.7c12.52,4.55,13.09,6.25,12.52-5.12s0-11.38-13.09-1.71c0-2.84-7.39-1.71-8.53,0-11.95-5.12-13.09-6.83-12.52,1.14,1.14,16.5.57,13.65,11.95,8l8.53-.57Zm0,0Z"/><path class="f" d="M60.87,99.56v6.82c.57,1.14,9.67,1.14,9.67-1.14s-4.55,1.71-7.39.57S62,98.42,62,98.42l-1.14,1.14Zm0,0Z"/><path class="g" d="M48.36,43.24c-2.85-3.42-10.24-.57-8.54,4,.57-2.28,4.55-5.69,8.54-4Zm18.2,0c.57-3.42,6.26-4,8-.57a8,8,0,0,0-8,.57Zm-18.77,9.1a1.14,1.14,0,1,1,0,.57v-.57Zm-4.55,2.27a4,4,0,1,0,0-.57v.57Zm29.58-4a1.14,1.14,0,1,1,0,.57v-.57ZM69.4,52.91a3.42,3.42,0,1,0,0-.57v.57Zm0,0Z"/></svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
@@ -288,136 +288,101 @@ const ConversationBubble = forwardRef<
|
||||
{DisableSourceFE ||
|
||||
type === 'ERROR' ||
|
||||
sources?.length === 0 ||
|
||||
sources?.some((source) => source.link === 'None') ? null : !sources &&
|
||||
chunks !== '0' &&
|
||||
selectedDocs ? (
|
||||
<div className="mb-4 flex flex-col flex-wrap items-start self-start lg:flex-nowrap">
|
||||
<div className="my-2 flex flex-row items-center justify-center gap-3">
|
||||
<Avatar
|
||||
className="h-[26px] w-[30px] text-xl"
|
||||
avatar={
|
||||
<img
|
||||
src={Sources}
|
||||
alt={t('conversation.sources.title')}
|
||||
className="h-full w-full object-fill"
|
||||
sources?.some((source) => source.link === 'None')
|
||||
? null
|
||||
: sources && (
|
||||
<div className="mb-4 flex flex-col flex-wrap items-start self-start lg:flex-nowrap">
|
||||
<div className="my-2 flex flex-row items-center justify-center gap-3">
|
||||
<Avatar
|
||||
className="h-[26px] w-[30px] text-xl"
|
||||
avatar={
|
||||
<img
|
||||
src={Sources}
|
||||
alt={t('conversation.sources.title')}
|
||||
className="h-full w-full object-fill"
|
||||
/>
|
||||
}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<p className="text-base font-semibold">
|
||||
{t('conversation.sources.title')}
|
||||
</p>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-2 lg:grid-cols-4">
|
||||
{Array.from({ length: 4 }).map((_, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="bg-gray-1000 text-purple-30 dark:bg-gun-metal flex h-28 cursor-pointer flex-col items-start gap-1 rounded-[20px] p-4 hover:bg-[#F1F1F1] hover:text-[#6D3ECC] dark:hover:bg-[#2C2E3C] dark:hover:text-[#8C67D7]"
|
||||
>
|
||||
<span className="h-px w-10 animate-pulse cursor-pointer rounded-[20px] bg-[#B2B2B2] p-1"></span>
|
||||
<span className="h-px w-24 animate-pulse cursor-pointer rounded-[20px] bg-[#B2B2B2] p-1"></span>
|
||||
<span className="h-px w-16 animate-pulse cursor-pointer rounded-[20px] bg-[#B2B2B2] p-1"></span>
|
||||
<span className="h-px w-32 animate-pulse cursor-pointer rounded-[20px] bg-[#B2B2B2] p-1"></span>
|
||||
<span className="h-px w-24 animate-pulse cursor-pointer rounded-[20px] bg-[#B2B2B2] p-1"></span>
|
||||
<span className="h-px w-20 animate-pulse cursor-pointer rounded-[20px] bg-[#B2B2B2] p-1"></span>
|
||||
<p className="text-base font-semibold">
|
||||
{t('conversation.sources.title')}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
sources && (
|
||||
<div className="mb-4 flex flex-col flex-wrap items-start self-start lg:flex-nowrap">
|
||||
<div className="my-2 flex flex-row items-center justify-center gap-3">
|
||||
<Avatar
|
||||
className="h-[26px] w-[30px] text-xl"
|
||||
avatar={
|
||||
<img
|
||||
src={Sources}
|
||||
alt={t('conversation.sources.title')}
|
||||
className="h-full w-full object-fill"
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<p className="text-base font-semibold">
|
||||
{t('conversation.sources.title')}
|
||||
</p>
|
||||
</div>
|
||||
<div className="fade-in mr-5 ml-3 max-w-[90vw] md:max-w-[70vw] lg:max-w-[50vw]">
|
||||
<div className="grid grid-cols-2 gap-2 lg:grid-cols-4">
|
||||
{sources?.slice(0, 3)?.map((source, index) => (
|
||||
<div key={index} className="relative">
|
||||
<div
|
||||
className="bg-gray-1000 dark:bg-gun-metal h-28 cursor-pointer rounded-[20px] p-4 hover:bg-[#F1F1F1] dark:hover:bg-[#2C2E3C]"
|
||||
onMouseOver={() => setActiveTooltip(index)}
|
||||
onMouseOut={() => setActiveTooltip(null)}
|
||||
>
|
||||
<p className="ellipsis-text h-12 text-xs break-words">
|
||||
{source.text}
|
||||
</p>
|
||||
<div className="fade-in mr-5 ml-3 max-w-[90vw] md:max-w-[70vw] lg:max-w-[50vw]">
|
||||
<div className="grid grid-cols-2 gap-2 lg:grid-cols-4">
|
||||
{sources?.slice(0, 3)?.map((source, index) => (
|
||||
<div key={index} className="relative">
|
||||
<div
|
||||
className={`mt-[14px] flex flex-row items-center gap-[6px] underline-offset-2 ${
|
||||
source.link && source.link !== 'local'
|
||||
? 'hover:text-[#007DFF] hover:underline dark:hover:text-[#48A0FF]'
|
||||
: ''
|
||||
}`}
|
||||
onClick={() =>
|
||||
source.link && source.link !== 'local'
|
||||
? window.open(
|
||||
source.link,
|
||||
'_blank',
|
||||
'noopener, noreferrer',
|
||||
)
|
||||
: null
|
||||
}
|
||||
>
|
||||
<img
|
||||
src={Document}
|
||||
alt="Document"
|
||||
className="h-[17px] w-[17px] object-fill"
|
||||
/>
|
||||
<p
|
||||
className="mt-[2px] truncate text-xs"
|
||||
title={
|
||||
source.link && source.link !== 'local'
|
||||
? source.link
|
||||
: source.title
|
||||
}
|
||||
>
|
||||
{source.link && source.link !== 'local'
|
||||
? source.link
|
||||
: source.title}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{activeTooltip === index && (
|
||||
<div
|
||||
className={`dark:bg-chinese-black dark:text-chinese-silver absolute left-1/2 z-50 max-h-48 w-40 translate-x-[-50%] translate-y-[3px] rounded-xl bg-[#FBFBFB] p-4 text-black shadow-xl sm:w-56`}
|
||||
className="bg-gray-1000 dark:bg-gun-metal h-28 cursor-pointer rounded-[20px] p-4 hover:bg-[#F1F1F1] dark:hover:bg-[#2C2E3C]"
|
||||
onMouseOver={() => setActiveTooltip(index)}
|
||||
onMouseOut={() => setActiveTooltip(null)}
|
||||
>
|
||||
<p className="line-clamp-6 max-h-[164px] overflow-hidden rounded-md text-sm break-words text-ellipsis">
|
||||
<p className="ellipsis-text h-12 text-xs break-words">
|
||||
{source.text}
|
||||
</p>
|
||||
<div
|
||||
className={`mt-[14px] flex flex-row items-center gap-[6px] underline-offset-2 ${
|
||||
source.link && source.link !== 'local'
|
||||
? 'hover:text-[#007DFF] hover:underline dark:hover:text-[#48A0FF]'
|
||||
: ''
|
||||
}`}
|
||||
onClick={() =>
|
||||
source.link && source.link !== 'local'
|
||||
? window.open(
|
||||
source.link,
|
||||
'_blank',
|
||||
'noopener, noreferrer',
|
||||
)
|
||||
: null
|
||||
}
|
||||
>
|
||||
<img
|
||||
src={Document}
|
||||
alt="Document"
|
||||
className="h-[17px] w-[17px] object-fill"
|
||||
/>
|
||||
<p
|
||||
className="mt-[2px] truncate text-xs"
|
||||
title={
|
||||
source.link && source.link !== 'local'
|
||||
? source.link
|
||||
: source.title
|
||||
}
|
||||
>
|
||||
{source.link && source.link !== 'local'
|
||||
? source.link
|
||||
: source.title}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
{(sources?.length ?? 0) > 3 && (
|
||||
<div
|
||||
className="bg-gray-1000 text-purple-30 dark:bg-gun-metal flex h-28 cursor-pointer flex-col-reverse rounded-[20px] p-4 hover:bg-[#F1F1F1] hover:text-[#6D3ECC] dark:hover:bg-[#2C2E3C] dark:hover:text-[#8C67D7]"
|
||||
onClick={() => setIsSidebarOpen(true)}
|
||||
>
|
||||
<p className="ellipsis-text h-22 text-xs">
|
||||
{t('conversation.sources.view_more', {
|
||||
count: sources?.length ? sources.length - 3 : 0,
|
||||
})}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
{activeTooltip === index && (
|
||||
<div
|
||||
className={`dark:bg-chinese-black dark:text-chinese-silver absolute left-1/2 z-50 max-h-48 w-40 translate-x-[-50%] translate-y-[3px] rounded-xl bg-[#FBFBFB] p-4 text-black shadow-xl sm:w-56`}
|
||||
onMouseOver={() => setActiveTooltip(index)}
|
||||
onMouseOut={() => setActiveTooltip(null)}
|
||||
>
|
||||
<p className="line-clamp-6 max-h-[164px] overflow-hidden rounded-md text-sm break-words text-ellipsis">
|
||||
{source.text}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
{(sources?.length ?? 0) > 3 && (
|
||||
<div
|
||||
className="bg-gray-1000 text-purple-30 dark:bg-gun-metal flex h-28 cursor-pointer flex-col-reverse rounded-[20px] p-4 hover:bg-[#F1F1F1] hover:text-[#6D3ECC] dark:hover:bg-[#2C2E3C] dark:hover:text-[#8C67D7]"
|
||||
onClick={() => setIsSidebarOpen(true)}
|
||||
>
|
||||
<p className="ellipsis-text h-22 text-xs">
|
||||
{t('conversation.sources.view_more', {
|
||||
count: sources?.length ? sources.length - 3 : 0,
|
||||
})}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
)}
|
||||
)}
|
||||
{toolCalls && toolCalls.length > 0 && (
|
||||
<ToolCalls toolCalls={toolCalls} />
|
||||
)}
|
||||
|
||||
@@ -284,14 +284,9 @@ export const conversationSlice = createSlice({
|
||||
query: Partial<Query>;
|
||||
}>,
|
||||
) {
|
||||
const { conversationId, index, query } = action.payload;
|
||||
if (state.conversationId !== conversationId) return;
|
||||
|
||||
if (!state.queries[index].sources) {
|
||||
state.queries[index].sources = query?.sources;
|
||||
} else if (query.sources) {
|
||||
state.queries[index].sources!.push(...query.sources);
|
||||
}
|
||||
const { index, query } = action.payload;
|
||||
if (query.sources !== undefined)
|
||||
state.queries[index].sources = query.sources;
|
||||
},
|
||||
updateToolCall(state, action) {
|
||||
const { index, tool_call } = action.payload;
|
||||
|
||||
@@ -33,6 +33,19 @@ export default function ChunkModal({
|
||||
setChunkText(originalText || '');
|
||||
}, [originalTitle, originalText]);
|
||||
|
||||
const resetForm = () => {
|
||||
setTitle('');
|
||||
setChunkText('');
|
||||
};
|
||||
|
||||
const handleDeleteConfirmed = () => {
|
||||
if (handleDelete) {
|
||||
handleDelete();
|
||||
}
|
||||
setDeleteModal('INACTIVE');
|
||||
setModalState('INACTIVE');
|
||||
};
|
||||
|
||||
if (modalState !== 'ACTIVE') return null;
|
||||
|
||||
const content = (
|
||||
@@ -71,6 +84,7 @@ export default function ChunkModal({
|
||||
onClick={() => {
|
||||
handleSubmit(title, chunkText);
|
||||
setModalState('INACTIVE');
|
||||
resetForm();
|
||||
}}
|
||||
className="bg-purple-30 hover:bg-violets-are-blue rounded-3xl px-5 py-2 text-sm text-white transition-all"
|
||||
>
|
||||
@@ -79,6 +93,7 @@ export default function ChunkModal({
|
||||
<button
|
||||
onClick={() => {
|
||||
setModalState('INACTIVE');
|
||||
resetForm();
|
||||
}}
|
||||
className="dark:text-light-gray cursor-pointer rounded-3xl px-5 py-2 text-sm font-medium hover:bg-gray-100 dark:bg-transparent dark:hover:bg-[#767183]/50"
|
||||
>
|
||||
@@ -124,6 +139,7 @@ export default function ChunkModal({
|
||||
<WrapperModal
|
||||
close={() => setModalState('INACTIVE')}
|
||||
className="sm:w-[620px]"
|
||||
isPerformingTask={true}
|
||||
>
|
||||
{content}
|
||||
</WrapperModal>
|
||||
@@ -133,13 +149,7 @@ export default function ChunkModal({
|
||||
message={t('modals.chunk.deleteConfirmation')}
|
||||
modalState={deleteModal}
|
||||
setModalState={setDeleteModal}
|
||||
handleSubmit={
|
||||
handleDelete
|
||||
? handleDelete
|
||||
: () => {
|
||||
/* no-op */
|
||||
}
|
||||
}
|
||||
handleSubmit={handleDeleteConfirmed}
|
||||
submitLabel={t('modals.chunk.delete')}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -29,33 +29,40 @@ export default function ConfirmationModal({
|
||||
? 'rounded-3xl bg-rosso-corsa px-5 py-2 text-sm text-lotion transition-all hover:bg-red-2000 hover:font-bold tracking-[0.019em] hover:tracking-normal'
|
||||
: 'rounded-3xl bg-purple-30 px-5 py-2 text-sm text-lotion transition-all hover:bg-violets-are-blue';
|
||||
|
||||
const handleSubmitClick = (e: React.MouseEvent) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
handleSubmit();
|
||||
setModalState('INACTIVE');
|
||||
};
|
||||
|
||||
const handleCancelClick = (e: React.MouseEvent) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setModalState('INACTIVE');
|
||||
handleCancel?.();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{modalState === 'ACTIVE' && (
|
||||
<WrapperModal close={() => setModalState('INACTIVE')}>
|
||||
<div className="relative">
|
||||
<div>
|
||||
<p className="font-base mb-1 w-[90%] break-words text-lg text-jet dark:text-bright-gray">
|
||||
<p className="font-base text-jet dark:text-bright-gray mb-1 w-[90%] text-lg break-words">
|
||||
{message}
|
||||
</p>
|
||||
<div>
|
||||
<div className="mt-6 flex flex-row-reverse gap-1">
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handleSubmit();
|
||||
}}
|
||||
onClick={handleSubmitClick}
|
||||
className={submitButtonClasses}
|
||||
>
|
||||
{submitLabel}
|
||||
</button>
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setModalState('INACTIVE');
|
||||
handleCancel && handleCancel();
|
||||
}}
|
||||
className="cursor-pointer rounded-3xl px-5 py-2 text-sm font-medium hover:bg-gray-100 dark:bg-transparent dark:text-light-gray dark:hover:bg-[#767183]/50"
|
||||
onClick={handleCancelClick}
|
||||
className="dark:text-light-gray cursor-pointer rounded-3xl px-5 py-2 text-sm font-medium hover:bg-gray-100 dark:bg-transparent dark:hover:bg-[#767183]/50"
|
||||
>
|
||||
{cancelLabel ? cancelLabel : t('cancel')}
|
||||
</button>
|
||||
|
||||
@@ -3,38 +3,33 @@ import { createPortal } from 'react-dom';
|
||||
|
||||
import Exit from '../assets/exit.svg';
|
||||
|
||||
interface WrapperModalPropsType {
|
||||
type WrapperModalPropsType = {
|
||||
children: React.ReactNode;
|
||||
close: () => void;
|
||||
isPerformingTask?: boolean;
|
||||
className?: string;
|
||||
contentClassName?: string;
|
||||
}
|
||||
};
|
||||
|
||||
export default function WrapperModal({
|
||||
children,
|
||||
close,
|
||||
isPerformingTask = false,
|
||||
className = '', // Default width, but can be overridden
|
||||
contentClassName = '', // Default padding, but can be overridden
|
||||
className = '',
|
||||
contentClassName = '',
|
||||
}: WrapperModalPropsType) {
|
||||
const modalRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (isPerformingTask) return;
|
||||
|
||||
const handleClickOutside = (event: MouseEvent) => {
|
||||
if (
|
||||
modalRef.current &&
|
||||
!modalRef.current.contains(event.target as Node)
|
||||
) {
|
||||
if (modalRef.current && !modalRef.current.contains(event.target as Node))
|
||||
close();
|
||||
}
|
||||
};
|
||||
|
||||
const handleEscapePress = (event: KeyboardEvent) => {
|
||||
if (event.key === 'Escape') {
|
||||
close();
|
||||
}
|
||||
if (event.key === 'Escape') close();
|
||||
};
|
||||
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
@@ -44,17 +39,17 @@ export default function WrapperModal({
|
||||
document.removeEventListener('mousedown', handleClickOutside);
|
||||
document.removeEventListener('keydown', handleEscapePress);
|
||||
};
|
||||
}, [close]);
|
||||
}, [close, isPerformingTask]);
|
||||
|
||||
const modalContent = (
|
||||
<div className="fixed left-0 top-0 z-30 flex h-screen w-screen items-center justify-center bg-gray-alpha bg-opacity-50">
|
||||
<div className="bg-gray-alpha bg-opacity-50 fixed top-0 left-0 z-30 flex h-screen w-screen items-center justify-center">
|
||||
<div
|
||||
ref={modalRef}
|
||||
className={`relative w-11/12 rounded-2xl bg-white p-8 dark:bg-[#26272E] sm:w-[512px] ${className}`}
|
||||
className={`relative w-11/12 rounded-2xl bg-white p-8 sm:w-[512px] dark:bg-[#26272E] ${className}`}
|
||||
>
|
||||
{!isPerformingTask && (
|
||||
<button
|
||||
className="absolute right-4 top-3 z-50 m-2 w-3"
|
||||
className="absolute top-3 right-4 z-50 m-2 w-3"
|
||||
onClick={close}
|
||||
>
|
||||
<img className="filter dark:invert" src={Exit} alt="Close" />
|
||||
|
||||
@@ -9,8 +9,10 @@ import Edit from '../assets/edit.svg';
|
||||
import EyeView from '../assets/eye-view.svg';
|
||||
import NoFilesDarkIcon from '../assets/no-files-dark.svg';
|
||||
import NoFilesIcon from '../assets/no-files.svg';
|
||||
import SyncIcon from '../assets/sync.svg';
|
||||
import Trash from '../assets/red-trash.svg';
|
||||
import SyncIcon from '../assets/sync.svg';
|
||||
import ThreeDots from '../assets/three-dots.svg';
|
||||
import ContextMenu, { MenuOption } from '../components/ContextMenu';
|
||||
import Pagination from '../components/DocumentPagination';
|
||||
import DropdownMenu from '../components/DropdownMenu';
|
||||
import Input from '../components/Input';
|
||||
@@ -29,8 +31,6 @@ import {
|
||||
import Upload from '../upload/Upload';
|
||||
import { formatDate } from '../utils/dateTimeUtils';
|
||||
import { ChunkType } from './types';
|
||||
import ContextMenu, { MenuOption } from '../components/ContextMenu';
|
||||
import ThreeDots from '../assets/three-dots.svg';
|
||||
|
||||
const formatTokens = (tokens: number): string => {
|
||||
const roundToTwoDecimals = (num: number): string => {
|
||||
@@ -766,19 +766,23 @@ function DocumentChunks({
|
||||
setModalState={setAddModal}
|
||||
handleSubmit={handleAddChunk}
|
||||
/>
|
||||
<ChunkModal
|
||||
type="EDIT"
|
||||
modalState={editModal.state}
|
||||
setModalState={(state) => setEditModal((prev) => ({ ...prev, state }))}
|
||||
handleSubmit={(title, text) => {
|
||||
handleUpdateChunk(title, text, editModal.chunk as ChunkType);
|
||||
}}
|
||||
originalText={editModal.chunk?.text}
|
||||
originalTitle={editModal.chunk?.metadata?.title}
|
||||
handleDelete={() => {
|
||||
handleDeleteChunk(editModal.chunk as ChunkType);
|
||||
}}
|
||||
/>
|
||||
{editModal.chunk && (
|
||||
<ChunkModal
|
||||
type="EDIT"
|
||||
modalState={editModal.state}
|
||||
setModalState={(state) =>
|
||||
setEditModal((prev) => ({ ...prev, state }))
|
||||
}
|
||||
handleSubmit={(title, text) => {
|
||||
handleUpdateChunk(title, text, editModal.chunk as ChunkType);
|
||||
}}
|
||||
originalText={editModal.chunk?.text ?? ''}
|
||||
originalTitle={editModal.chunk?.metadata?.title ?? ''}
|
||||
handleDelete={() => {
|
||||
handleDeleteChunk(editModal.chunk as ChunkType);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user