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