### What problem does this PR solve? Use use-chunk-request.ts to replace chunk-hooks.ts; implement chunk selectAll, enable, disable and other functions [#3221](https://github.com/infiniflow/ragflow/issues/3221) ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)tags/v0.20.0
| import message from '@/components/ui/message'; | |||||
| import { ResponseGetType } from '@/interfaces/database/base'; | import { ResponseGetType } from '@/interfaces/database/base'; | ||||
| import { IChunk, IKnowledgeFile } from '@/interfaces/database/knowledge'; | import { IChunk, IKnowledgeFile } from '@/interfaces/database/knowledge'; | ||||
| import kbService from '@/services/knowledge-service'; | import kbService from '@/services/knowledge-service'; | ||||
| import { useQuery } from '@tanstack/react-query'; | |||||
| import { useMutation, useQuery } from '@tanstack/react-query'; | |||||
| import { useDebounce } from 'ahooks'; | import { useDebounce } from 'ahooks'; | ||||
| import { useCallback, useState } from 'react'; | import { useCallback, useState } from 'react'; | ||||
| import { useTranslation } from 'react-i18next'; | |||||
| import { IChunkListResult } from './chunk-hooks'; | import { IChunkListResult } from './chunk-hooks'; | ||||
| import { | import { | ||||
| useGetPaginationWithRouter, | useGetPaginationWithRouter, | ||||
| handleSetAvailable, | handleSetAvailable, | ||||
| }; | }; | ||||
| }; | }; | ||||
| export const useSwitchChunk = () => { | |||||
| const { t } = useTranslation(); | |||||
| const { | |||||
| data, | |||||
| isPending: loading, | |||||
| mutateAsync, | |||||
| } = useMutation({ | |||||
| mutationKey: ['switchChunk'], | |||||
| mutationFn: async (params: { | |||||
| chunk_ids?: string[]; | |||||
| available_int?: number; | |||||
| doc_id: string; | |||||
| }) => { | |||||
| const { data } = await kbService.switch_chunk(params); | |||||
| if (data.code === 0) { | |||||
| message.success(t('message.modified')); | |||||
| } | |||||
| return data?.code; | |||||
| }, | |||||
| }); | |||||
| return { data, loading, switchChunk: mutateAsync }; | |||||
| }; |
| import { Ban, CircleCheck, Trash2 } from 'lucide-react'; | import { Ban, CircleCheck, Trash2 } from 'lucide-react'; | ||||
| import { useCallback } from 'react'; | import { useCallback } from 'react'; | ||||
| export default ({ selectAllChunk, checked }) => { | |||||
| type ICheckboxSetProps = { | |||||
| selectAllChunk: (e: any) => void; | |||||
| removeChunk: (e?: any) => void; | |||||
| switchChunk: (available: number) => void; | |||||
| checked: boolean; | |||||
| }; | |||||
| export default (props: ICheckboxSetProps) => { | |||||
| const { selectAllChunk, removeChunk, switchChunk, checked } = props; | |||||
| const handleSelectAllCheck = useCallback( | const handleSelectAllCheck = useCallback( | ||||
| (e: any) => { | (e: any) => { | ||||
| console.log('eee=', e); | console.log('eee=', e); | ||||
| [selectAllChunk], | [selectAllChunk], | ||||
| ); | ); | ||||
| const handleDeleteClick = useCallback(() => { | |||||
| removeChunk(); | |||||
| }, [removeChunk]); | |||||
| const handleEnabledClick = useCallback(() => { | |||||
| switchChunk(1); | |||||
| }, [switchChunk]); | |||||
| const handleDisabledClick = useCallback(() => { | |||||
| switchChunk(0); | |||||
| }, [switchChunk]); | |||||
| return ( | return ( | ||||
| <div className="flex gap-[40px]"> | |||||
| <div className="flex gap-[40px] p-4"> | |||||
| <div className="flex items-center gap-3 cursor-pointer"> | <div className="flex items-center gap-3 cursor-pointer"> | ||||
| <Checkbox | <Checkbox | ||||
| id="all_chunks_checkbox" | id="all_chunks_checkbox" | ||||
| onCheckedChange={handleSelectAllCheck} | onCheckedChange={handleSelectAllCheck} | ||||
| checked={checked} | checked={checked} | ||||
| className=" data-[state=checked]:bg-[#1668dc] data-[state=checked]:border-[#1668dc] data-[state=checked]:text-white" | |||||
| /> | /> | ||||
| <Label htmlFor="all_chunks_checkbox">All Chunks</Label> | <Label htmlFor="all_chunks_checkbox">All Chunks</Label> | ||||
| </div> | </div> | ||||
| <div className="flex items-center cursor-pointer"> | |||||
| <div | |||||
| className="flex items-center cursor-pointer" | |||||
| onClick={handleEnabledClick} | |||||
| > | |||||
| <CircleCheck size={16} /> | <CircleCheck size={16} /> | ||||
| <span className="block ml-1">Enable</span> | <span className="block ml-1">Enable</span> | ||||
| </div> | </div> | ||||
| <div className="flex items-center cursor-pointer"> | |||||
| <div | |||||
| className="flex items-center cursor-pointer" | |||||
| onClick={handleDisabledClick} | |||||
| > | |||||
| <Ban size={16} /> | <Ban size={16} /> | ||||
| <span className="block ml-1">Disable</span> | <span className="block ml-1">Disable</span> | ||||
| </div> | </div> | ||||
| <div className="flex items-center text-red-500 cursor-pointer"> | |||||
| <div | |||||
| className="flex items-center text-red-500 cursor-pointer" | |||||
| onClick={handleDeleteClick} | |||||
| > | |||||
| <Trash2 size={16} /> | <Trash2 size={16} /> | ||||
| <span className="block ml-1">Delete</span> | <span className="block ml-1">Delete</span> | ||||
| </div> | </div> |
| .chunkContainer { | .chunkContainer { | ||||
| display: flex; | display: flex; | ||||
| // height: calc(100vh - 332px); | // height: calc(100vh - 332px); | ||||
| height: calc(100vh - 270px); | |||||
| height: calc(100vh - 300px); | |||||
| } | } | ||||
| .chunkOtherContainer { | .chunkOtherContainer { | ||||
| .pageFooter { | .pageFooter { | ||||
| padding-top: 10px; | padding-top: 10px; | ||||
| padding-right: 10px; | |||||
| height: 32px; | height: 32px; | ||||
| } | } | ||||
| } | } |
| import { useFetchNextChunkList, useSwitchChunk } from '@/hooks/chunk-hooks'; | |||||
| import { | |||||
| useFetchNextChunkList, | |||||
| useSwitchChunk, | |||||
| } from '@/hooks/use-chunk-request'; | |||||
| import classNames from 'classnames'; | import classNames from 'classnames'; | ||||
| import { useCallback, useState } from 'react'; | |||||
| import { useCallback, useEffect, useState } from 'react'; | |||||
| import { useTranslation } from 'react-i18next'; | import { useTranslation } from 'react-i18next'; | ||||
| import ChunkCard from './components/chunk-card'; | import ChunkCard from './components/chunk-card'; | ||||
| import CreatingModal from './components/chunk-creating-modal'; | import CreatingModal from './components/chunk-creating-modal'; | ||||
| const { t } = useTranslation(); | const { t } = useTranslation(); | ||||
| const { changeChunkTextMode, textMode } = useChangeChunkTextMode(); | const { changeChunkTextMode, textMode } = useChangeChunkTextMode(); | ||||
| const { switchChunk } = useSwitchChunk(); | const { switchChunk } = useSwitchChunk(); | ||||
| const [chunkList, setChunkList] = useState(data); | |||||
| const { | const { | ||||
| chunkUpdatingLoading, | chunkUpdatingLoading, | ||||
| onChunkUpdatingOk, | onChunkUpdatingOk, | ||||
| documentId, | documentId, | ||||
| } = useUpdateChunk(); | } = useUpdateChunk(); | ||||
| useEffect(() => { | |||||
| setChunkList(data); | |||||
| }, [data]); | |||||
| const onPaginationChange: RAGFlowPaginationType['onChange'] = ( | const onPaginationChange: RAGFlowPaginationType['onChange'] = ( | ||||
| page, | page, | ||||
| size, | size, | ||||
| available_int: available, | available_int: available, | ||||
| doc_id: documentId, | doc_id: documentId, | ||||
| }); | }); | ||||
| if (!chunkIds && resCode === 0) { | |||||
| if (ids?.length && resCode === 0) { | |||||
| chunkList.forEach((x: any) => { | |||||
| if (ids.indexOf(x['chunk_id']) > -1) { | |||||
| x['available_int'] = available; | |||||
| } | |||||
| }); | |||||
| setChunkList(chunkList); | |||||
| } | } | ||||
| }, | }, | ||||
| [switchChunk, documentId, selectedChunkIds, showSelectedChunkWarning], | |||||
| [ | |||||
| switchChunk, | |||||
| documentId, | |||||
| selectedChunkIds, | |||||
| showSelectedChunkWarning, | |||||
| chunkList, | |||||
| ], | |||||
| ); | ); | ||||
| const { highlights, setWidthAndHeight } = | const { highlights, setWidthAndHeight } = | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <div className=" rounded-[16px] bg-[#FFF]/10 pl-[20px] pb-[20px] pt-[20px] box-border "> | |||||
| <div className=" rounded-[16px] bg-[#FFF]/10 pl-[20px] pb-[20px] pt-[20px] box-border mb-2"> | |||||
| <ChunkResultBar | <ChunkResultBar | ||||
| handleInputChange={handleInputChange} | handleInputChange={handleInputChange} | ||||
| searchString={searchString} | searchString={searchString} | ||||
| <div className="pt-[5px] pb-[5px]"> | <div className="pt-[5px] pb-[5px]"> | ||||
| <CheckboxSets | <CheckboxSets | ||||
| selectAllChunk={selectAllChunk} | selectAllChunk={selectAllChunk} | ||||
| switchChunk={handleSwitchChunk} | |||||
| removeChunk={handleRemoveChunk} | |||||
| checked={selectedChunkIds.length === data.length} | checked={selectedChunkIds.length === data.length} | ||||
| /> | /> | ||||
| </div> | </div> | ||||
| 'flex flex-col gap-4', | 'flex flex-col gap-4', | ||||
| )} | )} | ||||
| > | > | ||||
| {data.map((item) => ( | |||||
| {chunkList.map((item) => ( | |||||
| <ChunkCard | <ChunkCard | ||||
| item={item} | item={item} | ||||
| key={item.chunk_id} | key={item.chunk_id} | ||||
| ))} | ))} | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <div className={styles.pageFooter}> | |||||
| <RAGFlowPagination | |||||
| pageSize={pagination.pageSize} | |||||
| current={pagination.current} | |||||
| total={total} | |||||
| onChange={(page, pageSize) => { | |||||
| onPaginationChange(page, pageSize); | |||||
| }} | |||||
| ></RAGFlowPagination> | |||||
| </div> | |||||
| </div> | </div> | ||||
| </Spin> | </Spin> | ||||
| <div className={styles.pageFooter}> | |||||
| <RAGFlowPagination | |||||
| pageSize={pagination.pageSize} | |||||
| current={pagination.current} | |||||
| total={total} | |||||
| onChange={(page, pageSize) => { | |||||
| onPaginationChange(page, pageSize); | |||||
| }} | |||||
| ></RAGFlowPagination> | |||||
| </div> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> |