mirror of
https://git.mirrors.martin98.com/https://github.com/infiniflow/ragflow.git
synced 2025-05-31 10:35:24 +08:00
### What problem does this PR solve? feat: Delete the files uploaded in the external dialog box #1880 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
parent
d3ff1a30bf
commit
7bdd5a48c0
@ -14,6 +14,8 @@
|
|||||||
}
|
}
|
||||||
.listWrapper {
|
.listWrapper {
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
|
overflow: auto;
|
||||||
|
max-height: 170px;
|
||||||
}
|
}
|
||||||
.inputWrapper {
|
.inputWrapper {
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
|
@ -1,13 +1,18 @@
|
|||||||
import { Authorization } from '@/constants/authorization';
|
import { Authorization } from '@/constants/authorization';
|
||||||
import { useTranslate } from '@/hooks/common-hooks';
|
import { useTranslate } from '@/hooks/common-hooks';
|
||||||
import {
|
import {
|
||||||
|
useDeleteDocument,
|
||||||
useFetchDocumentInfosByIds,
|
useFetchDocumentInfosByIds,
|
||||||
useRemoveNextDocument,
|
useRemoveNextDocument,
|
||||||
} from '@/hooks/document-hooks';
|
} from '@/hooks/document-hooks';
|
||||||
import { getAuthorization } from '@/utils/authorization-util';
|
import { getAuthorization } from '@/utils/authorization-util';
|
||||||
import { getExtension } from '@/utils/document-util';
|
import { getExtension } from '@/utils/document-util';
|
||||||
import { formatBytes } from '@/utils/file-util';
|
import { formatBytes } from '@/utils/file-util';
|
||||||
import { CloseCircleOutlined, LoadingOutlined } from '@ant-design/icons';
|
import {
|
||||||
|
CloseCircleOutlined,
|
||||||
|
InfoCircleOutlined,
|
||||||
|
LoadingOutlined,
|
||||||
|
} from '@ant-design/icons';
|
||||||
import type { GetProp, UploadFile } from 'antd';
|
import type { GetProp, UploadFile } from 'antd';
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
@ -41,6 +46,16 @@ const getFileIds = (fileList: UploadFile[]) => {
|
|||||||
return ids;
|
return ids;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isUploadError = (file: UploadFile) => {
|
||||||
|
const retcode = get(file, 'response.retcode');
|
||||||
|
return typeof retcode === 'number' && retcode !== 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
const isUploadSuccess = (file: UploadFile) => {
|
||||||
|
const retcode = get(file, 'response.retcode');
|
||||||
|
return typeof retcode === 'number' && retcode === 0;
|
||||||
|
};
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
value: string;
|
value: string;
|
||||||
@ -50,6 +65,7 @@ interface IProps {
|
|||||||
onInputChange: ChangeEventHandler<HTMLInputElement>;
|
onInputChange: ChangeEventHandler<HTMLInputElement>;
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
uploadUrl?: string;
|
uploadUrl?: string;
|
||||||
|
isShared?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const getBase64 = (file: FileType): Promise<string> =>
|
const getBase64 = (file: FileType): Promise<string> =>
|
||||||
@ -61,6 +77,7 @@ const getBase64 = (file: FileType): Promise<string> =>
|
|||||||
});
|
});
|
||||||
|
|
||||||
const MessageInput = ({
|
const MessageInput = ({
|
||||||
|
isShared = false,
|
||||||
disabled,
|
disabled,
|
||||||
value,
|
value,
|
||||||
onPressEnter,
|
onPressEnter,
|
||||||
@ -72,6 +89,7 @@ const MessageInput = ({
|
|||||||
}: IProps) => {
|
}: IProps) => {
|
||||||
const { t } = useTranslate('chat');
|
const { t } = useTranslate('chat');
|
||||||
const { removeDocument } = useRemoveNextDocument();
|
const { removeDocument } = useRemoveNextDocument();
|
||||||
|
const { deleteDocument } = useDeleteDocument();
|
||||||
const { data: documentInfos, setDocumentIds } = useFetchDocumentInfosByIds();
|
const { data: documentInfos, setDocumentIds } = useFetchDocumentInfosByIds();
|
||||||
|
|
||||||
const [fileList, setFileList] = useState<UploadFile[]>([]);
|
const [fileList, setFileList] = useState<UploadFile[]>([]);
|
||||||
@ -89,7 +107,7 @@ const MessageInput = ({
|
|||||||
|
|
||||||
const handlePressEnter = useCallback(async () => {
|
const handlePressEnter = useCallback(async () => {
|
||||||
if (isUploadingFile) return;
|
if (isUploadingFile) return;
|
||||||
const ids = getFileIds(fileList);
|
const ids = getFileIds(fileList.filter((x) => isUploadSuccess(x)));
|
||||||
|
|
||||||
onPressEnter(ids);
|
onPressEnter(ids);
|
||||||
setFileList([]);
|
setFileList([]);
|
||||||
@ -98,14 +116,24 @@ const MessageInput = ({
|
|||||||
const handleRemove = useCallback(
|
const handleRemove = useCallback(
|
||||||
async (file: UploadFile) => {
|
async (file: UploadFile) => {
|
||||||
const ids = get(file, 'response.data', []);
|
const ids = get(file, 'response.data', []);
|
||||||
if (ids.length) {
|
// Upload Successfully
|
||||||
await removeDocument(ids[0]);
|
if (Array.isArray(ids) && ids.length) {
|
||||||
|
if (isShared) {
|
||||||
|
await deleteDocument(ids);
|
||||||
|
} else {
|
||||||
|
await removeDocument(ids[0]);
|
||||||
|
}
|
||||||
setFileList((preList) => {
|
setFileList((preList) => {
|
||||||
return preList.filter((x) => getFileId(x) !== ids[0]);
|
return preList.filter((x) => getFileId(x) !== ids[0]);
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
// Upload failed
|
||||||
|
setFileList((preList) => {
|
||||||
|
return preList.filter((x) => x.uid !== file.uid);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[removeDocument],
|
[removeDocument, deleteDocument, isShared],
|
||||||
);
|
);
|
||||||
|
|
||||||
const getDocumentInfoById = useCallback(
|
const getDocumentInfoById = useCallback(
|
||||||
@ -192,6 +220,11 @@ const MessageInput = ({
|
|||||||
<LoadingOutlined style={{ fontSize: 24 }} spin />
|
<LoadingOutlined style={{ fontSize: 24 }} spin />
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
) : !getFileId(item) ? (
|
||||||
|
<InfoCircleOutlined
|
||||||
|
size={30}
|
||||||
|
// width={30}
|
||||||
|
></InfoCircleOutlined>
|
||||||
) : (
|
) : (
|
||||||
<FileIcon id={id} name={item.name}></FileIcon>
|
<FileIcon id={id} name={item.name}></FileIcon>
|
||||||
)}
|
)}
|
||||||
@ -202,26 +235,33 @@ const MessageInput = ({
|
|||||||
>
|
>
|
||||||
<b> {item.name}</b>
|
<b> {item.name}</b>
|
||||||
</Text>
|
</Text>
|
||||||
{item.percent !== 100 ? (
|
{isUploadError(item) ? (
|
||||||
t('uploading')
|
t('uploadFailed')
|
||||||
) : !item.response ? (
|
|
||||||
t('parsing')
|
|
||||||
) : (
|
) : (
|
||||||
<Space>
|
<>
|
||||||
<span>{fileExtension?.toUpperCase()},</span>
|
{item.percent !== 100 ? (
|
||||||
<span>
|
t('uploading')
|
||||||
{formatBytes(getDocumentInfoById(id)?.size ?? 0)}
|
) : !item.response ? (
|
||||||
</span>
|
t('parsing')
|
||||||
</Space>
|
) : (
|
||||||
|
<Space>
|
||||||
|
<span>{fileExtension?.toUpperCase()},</span>
|
||||||
|
<span>
|
||||||
|
{formatBytes(
|
||||||
|
getDocumentInfoById(id)?.size ?? 0,
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
</Space>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
{item.status !== 'uploading' && (
|
{item.status !== 'uploading' && (
|
||||||
<CloseCircleOutlined
|
<span className={styles.deleteIcon}>
|
||||||
className={styles.deleteIcon}
|
<CloseCircleOutlined onClick={() => handleRemove(item)} />
|
||||||
onClick={() => handleRemove(item)}
|
</span>
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
</Card>
|
</Card>
|
||||||
</List.Item>
|
</List.Item>
|
||||||
|
@ -313,3 +313,23 @@ export const useRemoveNextDocument = () => {
|
|||||||
|
|
||||||
return { data, loading, removeDocument: mutateAsync };
|
return { data, loading, removeDocument: mutateAsync };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useDeleteDocument = () => {
|
||||||
|
// const queryClient = useQueryClient();
|
||||||
|
const {
|
||||||
|
data,
|
||||||
|
isPending: loading,
|
||||||
|
mutateAsync,
|
||||||
|
} = useMutation({
|
||||||
|
mutationKey: ['deleteDocument'],
|
||||||
|
mutationFn: async (documentIds: string[]) => {
|
||||||
|
const data = await kbService.document_delete({ doc_ids: documentIds });
|
||||||
|
// if (data.retcode === 0) {
|
||||||
|
// queryClient.invalidateQueries({ queryKey: ['fetchFlowList'] });
|
||||||
|
// }
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return { data, loading, deleteDocument: mutateAsync };
|
||||||
|
};
|
||||||
|
@ -424,6 +424,7 @@ The above is the content you need to summarize.`,
|
|||||||
searching: 'searching...',
|
searching: 'searching...',
|
||||||
parsing: 'Parsing',
|
parsing: 'Parsing',
|
||||||
uploading: 'Uploading',
|
uploading: 'Uploading',
|
||||||
|
uploadFailed: 'Upload failed',
|
||||||
},
|
},
|
||||||
setting: {
|
setting: {
|
||||||
profile: 'Profile',
|
profile: 'Profile',
|
||||||
|
@ -394,6 +394,7 @@ export default {
|
|||||||
searching: '搜索中',
|
searching: '搜索中',
|
||||||
parsing: '解析中',
|
parsing: '解析中',
|
||||||
uploading: '上傳中',
|
uploading: '上傳中',
|
||||||
|
uploadFailed: '上傳失敗',
|
||||||
},
|
},
|
||||||
setting: {
|
setting: {
|
||||||
profile: '概述',
|
profile: '概述',
|
||||||
|
@ -411,6 +411,7 @@ export default {
|
|||||||
searching: '搜索中',
|
searching: '搜索中',
|
||||||
parsing: '解析中',
|
parsing: '解析中',
|
||||||
uploading: '上传中',
|
uploading: '上传中',
|
||||||
|
uploadFailed: '上传失败',
|
||||||
},
|
},
|
||||||
setting: {
|
setting: {
|
||||||
profile: '概要',
|
profile: '概要',
|
||||||
|
@ -65,6 +65,7 @@ const ChatContainer = () => {
|
|||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
<MessageInput
|
<MessageInput
|
||||||
|
isShared
|
||||||
value={value}
|
value={value}
|
||||||
disabled={false}
|
disabled={false}
|
||||||
sendDisabled={sendDisabled}
|
sendDisabled={sendDisabled}
|
||||||
|
@ -5,7 +5,7 @@ import {
|
|||||||
} from '@/hooks/chat-hooks';
|
} from '@/hooks/chat-hooks';
|
||||||
import { useSendMessageWithSse } from '@/hooks/logic-hooks';
|
import { useSendMessageWithSse } from '@/hooks/logic-hooks';
|
||||||
import { useOneNamespaceEffectsLoading } from '@/hooks/store-hooks';
|
import { useOneNamespaceEffectsLoading } from '@/hooks/store-hooks';
|
||||||
import { IAnswer } from '@/interfaces/database/chat';
|
import { IAnswer, Message } from '@/interfaces/database/chat';
|
||||||
import api from '@/utils/api';
|
import api from '@/utils/api';
|
||||||
import omit from 'lodash/omit';
|
import omit from 'lodash/omit';
|
||||||
import trim from 'lodash/trim';
|
import trim from 'lodash/trim';
|
||||||
@ -57,7 +57,7 @@ export const useSelectCurrentSharedConversation = (conversationId: string) => {
|
|||||||
|
|
||||||
const ref = useScrollToBottom(currentConversation);
|
const ref = useScrollToBottom(currentConversation);
|
||||||
|
|
||||||
const addNewestConversation = useCallback((message: string) => {
|
const addNewestConversation = useCallback((message: Partial<Message>) => {
|
||||||
setCurrentConversation((pre) => {
|
setCurrentConversation((pre) => {
|
||||||
return {
|
return {
|
||||||
...pre,
|
...pre,
|
||||||
@ -65,14 +65,15 @@ export const useSelectCurrentSharedConversation = (conversationId: string) => {
|
|||||||
...(pre.message ?? []),
|
...(pre.message ?? []),
|
||||||
{
|
{
|
||||||
role: MessageType.User,
|
role: MessageType.User,
|
||||||
content: message,
|
content: message.content,
|
||||||
|
doc_ids: message.doc_ids,
|
||||||
id: uuid(),
|
id: uuid(),
|
||||||
} as IMessage,
|
} as IMessage,
|
||||||
{
|
{
|
||||||
role: MessageType.Assistant,
|
role: MessageType.Assistant,
|
||||||
content: '',
|
content: '',
|
||||||
id: uuid(),
|
id: uuid(),
|
||||||
reference: [],
|
reference: {},
|
||||||
} as IMessage,
|
} as IMessage,
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
@ -140,7 +141,7 @@ export const useSendButtonDisabled = (value: string) => {
|
|||||||
|
|
||||||
export const useSendSharedMessage = (
|
export const useSendSharedMessage = (
|
||||||
conversation: IClientConversation,
|
conversation: IClientConversation,
|
||||||
addNewestConversation: (message: string) => void,
|
addNewestConversation: (message: Partial<Message>, answer?: string) => void,
|
||||||
removeLatestMessage: () => void,
|
removeLatestMessage: () => void,
|
||||||
setCurrentConversation: Dispatch<SetStateAction<IClientConversation>>,
|
setCurrentConversation: Dispatch<SetStateAction<IClientConversation>>,
|
||||||
addNewestAnswer: (answer: IAnswer) => void,
|
addNewestAnswer: (answer: IAnswer) => void,
|
||||||
@ -205,14 +206,17 @@ export const useSendSharedMessage = (
|
|||||||
}
|
}
|
||||||
}, [answer, addNewestAnswer]);
|
}, [answer, addNewestAnswer]);
|
||||||
|
|
||||||
const handlePressEnter = useCallback(() => {
|
const handlePressEnter = useCallback(
|
||||||
if (trim(value) === '') return;
|
(documentIds: string[]) => {
|
||||||
if (done) {
|
if (trim(value) === '') return;
|
||||||
setValue('');
|
if (done) {
|
||||||
addNewestConversation(value);
|
setValue('');
|
||||||
handleSendMessage(value.trim());
|
addNewestConversation({ content: value, doc_ids: documentIds });
|
||||||
}
|
handleSendMessage(value.trim());
|
||||||
}, [addNewestConversation, done, handleSendMessage, setValue, value]);
|
}
|
||||||
|
},
|
||||||
|
[addNewestConversation, done, handleSendMessage, setValue, value],
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
handlePressEnter,
|
handlePressEnter,
|
||||||
|
@ -12,6 +12,7 @@ const {
|
|||||||
get_document_list,
|
get_document_list,
|
||||||
document_change_status,
|
document_change_status,
|
||||||
document_rm,
|
document_rm,
|
||||||
|
document_delete,
|
||||||
document_create,
|
document_create,
|
||||||
document_change_parser,
|
document_change_parser,
|
||||||
document_thumbnails,
|
document_thumbnails,
|
||||||
@ -131,6 +132,10 @@ const methods = {
|
|||||||
url: knowledge_graph,
|
url: knowledge_graph,
|
||||||
method: 'get',
|
method: 'get',
|
||||||
},
|
},
|
||||||
|
document_delete: {
|
||||||
|
url: document_delete,
|
||||||
|
method: 'delete',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const kbService = registerServer<keyof typeof methods>(methods, request);
|
const kbService = registerServer<keyof typeof methods>(methods, request);
|
||||||
|
@ -41,6 +41,7 @@ export default {
|
|||||||
get_document_list: `${api_host}/document/list`,
|
get_document_list: `${api_host}/document/list`,
|
||||||
document_change_status: `${api_host}/document/change_status`,
|
document_change_status: `${api_host}/document/change_status`,
|
||||||
document_rm: `${api_host}/document/rm`,
|
document_rm: `${api_host}/document/rm`,
|
||||||
|
document_delete: `${api_host}/api/document`,
|
||||||
document_rename: `${api_host}/document/rename`,
|
document_rename: `${api_host}/document/rename`,
|
||||||
document_create: `${api_host}/document/create`,
|
document_create: `${api_host}/document/create`,
|
||||||
document_run: `${api_host}/document/run`,
|
document_run: `${api_host}/document/run`,
|
||||||
|
@ -6,6 +6,8 @@ type Service<T extends string> = Record<
|
|||||||
(params?: any, urlAppendix?: string) => any
|
(params?: any, urlAppendix?: string) => any
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
const Methods = ['post', 'delete', 'put'];
|
||||||
|
|
||||||
const registerServer = <T extends string>(
|
const registerServer = <T extends string>(
|
||||||
opt: Record<T, { url: string; method: string }>,
|
opt: Record<T, { url: string; method: string }>,
|
||||||
request: RequestMethod,
|
request: RequestMethod,
|
||||||
@ -18,7 +20,7 @@ const registerServer = <T extends string>(
|
|||||||
if (urlAppendix) {
|
if (urlAppendix) {
|
||||||
url = url + '/' + urlAppendix;
|
url = url + '/' + urlAppendix;
|
||||||
}
|
}
|
||||||
if (opt[key].method === 'post' || opt[key].method === 'POST') {
|
if (Methods.some((x) => x === opt[key].method.toLowerCase())) {
|
||||||
return request(url, {
|
return request(url, {
|
||||||
method: opt[key].method,
|
method: opt[key].method,
|
||||||
data: params,
|
data: params,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user