### What problem does this PR solve? fix: use @tanstack/react-query to get knowledge base data #1306 ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)tags/v0.9.0
| @@ -6,7 +6,6 @@ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; | |||
| import { message } from 'antd'; | |||
| import { useCallback, useEffect } from 'react'; | |||
| import { useDispatch, useSearchParams, useSelector } from 'umi'; | |||
| import { useGetKnowledgeSearchParams } from './route-hook'; | |||
| export const useKnowledgeBaseId = (): string => { | |||
| const [searchParams] = useSearchParams(); | |||
| @@ -41,44 +40,6 @@ export const useDeleteDocumentById = (): { | |||
| }; | |||
| }; | |||
| export const useFetchKnowledgeDetail = () => { | |||
| const dispatch = useDispatch(); | |||
| const { knowledgeId } = useGetKnowledgeSearchParams(); | |||
| const fetchKnowledgeDetail = useCallback( | |||
| (knowledgeId: string) => { | |||
| dispatch({ | |||
| type: 'knowledgeModel/getKnowledgeDetail', | |||
| payload: { kb_id: knowledgeId }, | |||
| }); | |||
| }, | |||
| [dispatch], | |||
| ); | |||
| useEffect(() => { | |||
| fetchKnowledgeDetail(knowledgeId); | |||
| }, [fetchKnowledgeDetail, knowledgeId]); | |||
| return fetchKnowledgeDetail; | |||
| }; | |||
| export const useSelectKnowledgeDetail = () => { | |||
| const knowledge: IKnowledge = useSelector( | |||
| (state: any) => state.knowledgeModel.knowledge, | |||
| ); | |||
| return knowledge; | |||
| }; | |||
| export const useGetDocumentDefaultParser = () => { | |||
| const item = useSelectKnowledgeDetail(); | |||
| return { | |||
| defaultParserId: item?.parser_id ?? '', | |||
| parserConfig: item?.parser_config ?? '', | |||
| }; | |||
| }; | |||
| export const useDeleteChunkByIds = (): { | |||
| removeChunk: (chunkIds: string[], documentId: string) => Promise<number>; | |||
| } => { | |||
| @@ -111,21 +72,21 @@ export const useDeleteChunkByIds = (): { | |||
| }; | |||
| export const useFetchKnowledgeBaseConfiguration = () => { | |||
| const dispatch = useDispatch(); | |||
| const knowledgeBaseId = useKnowledgeBaseId(); | |||
| const fetchKnowledgeBaseConfiguration = useCallback(() => { | |||
| dispatch({ | |||
| type: 'kSModel/getKbDetail', | |||
| payload: { | |||
| const { data, isFetching: loading } = useQuery({ | |||
| queryKey: ['fetchKnowledgeDetail'], | |||
| initialData: {}, | |||
| gcTime: 0, | |||
| queryFn: async () => { | |||
| const { data } = await kbService.get_kb_detail({ | |||
| kb_id: knowledgeBaseId, | |||
| }, | |||
| }); | |||
| }, [dispatch, knowledgeBaseId]); | |||
| }); | |||
| return data?.data ?? {}; | |||
| }, | |||
| }); | |||
| useEffect(() => { | |||
| fetchKnowledgeBaseConfiguration(); | |||
| }, [fetchKnowledgeBaseConfiguration]); | |||
| return { data, loading }; | |||
| }; | |||
| export const useNextFetchKnowledgeList = ( | |||
| @@ -228,27 +189,30 @@ export const useFetchFileThumbnails = (docIds?: Array<string>) => { | |||
| //#region knowledge configuration | |||
| export const useUpdateKnowledge = () => { | |||
| const dispatch = useDispatch(); | |||
| const saveKnowledgeConfiguration = useCallback( | |||
| (payload: any) => { | |||
| dispatch({ | |||
| type: 'kSModel/updateKb', | |||
| payload, | |||
| const knowledgeBaseId = useKnowledgeBaseId(); | |||
| const queryClient = useQueryClient(); | |||
| const { | |||
| data, | |||
| isPending: loading, | |||
| mutateAsync, | |||
| } = useMutation({ | |||
| mutationKey: ['saveKnowledge'], | |||
| mutationFn: async (params: Record<string, any>) => { | |||
| const { data = {} } = await kbService.updateKb({ | |||
| kb_id: knowledgeBaseId, | |||
| ...params, | |||
| }); | |||
| if (data.retcode === 0) { | |||
| message.success(i18n.t(`message.updated`)); | |||
| queryClient.invalidateQueries({ queryKey: ['fetchKnowledgeDetail'] }); | |||
| } | |||
| return data; | |||
| }, | |||
| [dispatch], | |||
| ); | |||
| }); | |||
| return saveKnowledgeConfiguration; | |||
| return { data, loading, saveKnowledgeConfiguration: mutateAsync }; | |||
| }; | |||
| export const useSelectKnowledgeDetails = () => { | |||
| const knowledgeDetails: IKnowledge = useSelector( | |||
| (state: any) => state.kSModel.knowledgeDetails, | |||
| ); | |||
| return knowledgeDetails; | |||
| }; | |||
| //#endregion | |||
| //#region Retrieval testing | |||
| @@ -1,86 +0,0 @@ | |||
| .uploadWrapper { | |||
| display: flex; | |||
| flex-direction: column; | |||
| padding: 64px 32px 32px; | |||
| height: 100%; | |||
| .backToList { | |||
| display: none; | |||
| padding-bottom: 60px; | |||
| } | |||
| .footer { | |||
| text-align: center; | |||
| padding-top: 16px; | |||
| .nextButton { | |||
| // background-color: @purple; | |||
| font-weight: 700; | |||
| font-size: 24px; | |||
| display: inline-flex; | |||
| align-items: center; | |||
| padding: 26px 40px; | |||
| justify-content: center; | |||
| width: 10%; | |||
| } | |||
| } | |||
| .uploadContent { | |||
| flex: 1; | |||
| padding-top: 60px; | |||
| } | |||
| .uploader { | |||
| :global(.ant-upload) { | |||
| height: 126px; | |||
| } | |||
| } | |||
| .hiddenUploader { | |||
| :global(.ant-upload-drag) { | |||
| display: none; | |||
| } | |||
| } | |||
| .fileIcon { | |||
| font-size: 40px; | |||
| align-items: end; | |||
| } | |||
| .uploaderButton { | |||
| padding: 10px; | |||
| vertical-align: middle; | |||
| height: 40px; | |||
| } | |||
| .uploaderIcon { | |||
| svg { | |||
| width: 20px; | |||
| height: 20px; | |||
| } | |||
| } | |||
| .deleteIcon { | |||
| font-size: 20px; | |||
| } | |||
| .uploaderItem { | |||
| margin-top: 16px; | |||
| :global(.ant-card-body) { | |||
| padding: 16px; | |||
| } | |||
| } | |||
| .uploaderItemProgress { | |||
| padding-left: 50px; | |||
| } | |||
| .uploaderItemTextWrapper { | |||
| flex: 1; | |||
| text-align: left; | |||
| padding-left: 10px; | |||
| } | |||
| } | |||
| .progressWrapper { | |||
| text-align: center; | |||
| } | |||
| .progress { | |||
| width: 50%; | |||
| margin: 0; | |||
| } | |||
| .selectFilesText { | |||
| transform: translateX(10%); | |||
| } | |||
| .changeSpecificCategoryText { | |||
| transform: translateX(30%); | |||
| } | |||
| @@ -1,310 +0,0 @@ | |||
| import { ReactComponent as SelectFilesEndIcon } from '@/assets/svg/select-files-end.svg'; | |||
| import { ReactComponent as SelectFilesStartIcon } from '@/assets/svg/select-files-start.svg'; | |||
| import ChunkMethodModal from '@/components/chunk-method-modal'; | |||
| import { KnowledgeRouteKey } from '@/constants/knowledge'; | |||
| import { | |||
| useRunDocument, | |||
| useSelectDocumentList, | |||
| useUploadDocument, | |||
| } from '@/hooks/document-hooks'; | |||
| import { | |||
| useDeleteDocumentById, | |||
| useFetchKnowledgeDetail, | |||
| useKnowledgeBaseId, | |||
| } from '@/hooks/knowledge-hooks'; | |||
| import { | |||
| useChangeDocumentParser, | |||
| useSetSelectedRecord, | |||
| } from '@/hooks/logic-hooks'; | |||
| import { useFetchTenantInfo } from '@/hooks/user-setting-hooks'; | |||
| import { IKnowledgeFile } from '@/interfaces/database/knowledge'; | |||
| import { getExtension, isFileUploadDone } from '@/utils/documentUtils'; | |||
| import { | |||
| ArrowLeftOutlined, | |||
| CloudUploadOutlined, | |||
| DeleteOutlined, | |||
| EditOutlined, | |||
| FileDoneOutlined, | |||
| } from '@ant-design/icons'; | |||
| import { | |||
| Button, | |||
| Card, | |||
| Flex, | |||
| Progress, | |||
| Space, | |||
| Upload, | |||
| UploadFile, | |||
| UploadProps, | |||
| } from 'antd'; | |||
| import classNames from 'classnames'; | |||
| import { ReactElement, useCallback, useMemo, useRef, useState } from 'react'; | |||
| import { Link, useNavigate } from 'umi'; | |||
| import { useTranslate } from '@/hooks/common-hooks'; | |||
| import styles from './index.less'; | |||
| const { Dragger } = Upload; | |||
| type UploadRequestOption = Parameters< | |||
| NonNullable<UploadProps['customRequest']> | |||
| >[0]; | |||
| const UploaderItem = ({ | |||
| file, | |||
| isUpload, | |||
| remove, | |||
| handleEdit, | |||
| }: { | |||
| isUpload: boolean; | |||
| originNode: ReactElement; | |||
| file: UploadFile; | |||
| fileList: object[]; | |||
| showModal: () => void; | |||
| remove: (id: string) => void; | |||
| setRecord: (record: IKnowledgeFile) => void; | |||
| handleEdit: (id: string) => void; | |||
| }) => { | |||
| const { removeDocument } = useDeleteDocumentById(); | |||
| const documentId = file?.response?.id; | |||
| const handleRemove = async () => { | |||
| if (file.status === 'error') { | |||
| remove(documentId); | |||
| } else { | |||
| const ret: any = await removeDocument(documentId); | |||
| if (ret === 0) { | |||
| remove(documentId); | |||
| } | |||
| } | |||
| }; | |||
| const handleEditClick = () => { | |||
| if (file.status === 'done') { | |||
| handleEdit(documentId); | |||
| } | |||
| }; | |||
| return ( | |||
| <Card className={styles.uploaderItem}> | |||
| <Flex justify="space-between"> | |||
| <FileDoneOutlined className={styles.fileIcon} /> | |||
| <section className={styles.uploaderItemTextWrapper}> | |||
| <div> | |||
| <b>{file.name}</b> | |||
| </div> | |||
| <span>{file.size}</span> | |||
| </section> | |||
| {isUpload ? ( | |||
| <DeleteOutlined | |||
| className={styles.deleteIcon} | |||
| onClick={handleRemove} | |||
| /> | |||
| ) : ( | |||
| <EditOutlined onClick={handleEditClick} /> | |||
| )} | |||
| </Flex> | |||
| <Flex> | |||
| <Progress | |||
| showInfo={false} | |||
| percent={100} | |||
| className={styles.uploaderItemProgress} | |||
| strokeColor=" | |||
| rgba(127, 86, 217, 1) | |||
| " | |||
| /> | |||
| <span>100%</span> | |||
| </Flex> | |||
| </Card> | |||
| ); | |||
| }; | |||
| const KnowledgeUploadFile = () => { | |||
| const knowledgeBaseId = useKnowledgeBaseId(); | |||
| const [isUpload, setIsUpload] = useState(true); | |||
| const [uploadedFileIds, setUploadedFileIds] = useState<string[]>([]); | |||
| const fileListRef = useRef<UploadFile[]>([]); | |||
| const navigate = useNavigate(); | |||
| const { currentRecord, setRecord } = useSetSelectedRecord(); | |||
| const { | |||
| changeParserLoading, | |||
| onChangeParserOk, | |||
| changeParserVisible, | |||
| hideChangeParserModal, | |||
| showChangeParserModal, | |||
| } = useChangeDocumentParser(currentRecord.id); | |||
| const documentList = useSelectDocumentList(); | |||
| const runDocumentByIds = useRunDocument(); | |||
| const uploadDocument = useUploadDocument(); | |||
| const { t } = useTranslate('knowledgeDetails'); | |||
| const enabled = useMemo(() => { | |||
| if (isUpload) { | |||
| return ( | |||
| uploadedFileIds.length > 0 && | |||
| fileListRef.current.filter((x) => isFileUploadDone(x)).length === | |||
| uploadedFileIds.length | |||
| ); | |||
| } | |||
| return true; | |||
| }, [uploadedFileIds, isUpload]); | |||
| const createRequest: (props: UploadRequestOption) => void = async function ({ | |||
| file, | |||
| onSuccess, | |||
| onError, | |||
| // onProgress, | |||
| }) { | |||
| const data = await uploadDocument(file as UploadFile); | |||
| if (data?.retcode === 0) { | |||
| setUploadedFileIds((pre) => { | |||
| return pre.concat(data.data.id); | |||
| }); | |||
| if (onSuccess) { | |||
| onSuccess(data.data); | |||
| } | |||
| } else { | |||
| if (onError) { | |||
| onError(data?.data); | |||
| } | |||
| } | |||
| }; | |||
| const removeIdFromUploadedIds = useCallback((id: string) => { | |||
| setUploadedFileIds((pre) => { | |||
| return pre.filter((x) => x !== id); | |||
| }); | |||
| }, []); | |||
| const handleItemEdit = useCallback( | |||
| (id: string) => { | |||
| const document = documentList.find((x) => x.id === id); | |||
| if (document) { | |||
| setRecord(document); | |||
| } | |||
| showChangeParserModal(); | |||
| }, | |||
| [documentList, showChangeParserModal, setRecord], | |||
| ); | |||
| const props: UploadProps = { | |||
| name: 'file', | |||
| multiple: true, | |||
| itemRender(originNode, file, fileList, actions) { | |||
| fileListRef.current = fileList; | |||
| const remove = (id: string) => { | |||
| if (isFileUploadDone(file)) { | |||
| removeIdFromUploadedIds(id); | |||
| } | |||
| actions.remove(); | |||
| }; | |||
| return ( | |||
| <UploaderItem | |||
| isUpload={isUpload} | |||
| file={file} | |||
| fileList={fileList} | |||
| originNode={originNode} | |||
| remove={remove} | |||
| showModal={showChangeParserModal} | |||
| setRecord={setRecord} | |||
| handleEdit={handleItemEdit} | |||
| ></UploaderItem> | |||
| ); | |||
| }, | |||
| customRequest: createRequest, | |||
| onDrop(e) { | |||
| console.log('Dropped files', e.dataTransfer.files); | |||
| }, | |||
| }; | |||
| const runSelectedDocument = () => { | |||
| const ids = fileListRef.current.map((x) => x.response.id); | |||
| runDocumentByIds({ doc_ids: ids, run: 1 }); | |||
| }; | |||
| const handleNextClick = () => { | |||
| if (!isUpload) { | |||
| runSelectedDocument(); | |||
| navigate(`/knowledge/${KnowledgeRouteKey.Dataset}?id=${knowledgeBaseId}`); | |||
| } else { | |||
| setIsUpload(false); | |||
| } | |||
| }; | |||
| useFetchTenantInfo(); | |||
| useFetchKnowledgeDetail(); | |||
| return ( | |||
| <> | |||
| <div className={styles.uploadWrapper}> | |||
| <section> | |||
| <Space className={styles.backToList}> | |||
| <ArrowLeftOutlined /> | |||
| <Link to={`/knowledge/dataset?id=${knowledgeBaseId}`}> | |||
| Back to select files | |||
| </Link> | |||
| </Space> | |||
| <div className={styles.progressWrapper}> | |||
| <Flex align="center" justify="center"> | |||
| <SelectFilesStartIcon></SelectFilesStartIcon> | |||
| <Progress | |||
| percent={100} | |||
| showInfo={false} | |||
| className={styles.progress} | |||
| strokeColor=" | |||
| rgba(127, 86, 217, 1) | |||
| " | |||
| /> | |||
| <SelectFilesEndIcon></SelectFilesEndIcon> | |||
| </Flex> | |||
| <Flex justify="space-around"> | |||
| <p className={styles.selectFilesText}> | |||
| <b>{t('selectFiles')}</b> | |||
| </p> | |||
| <p className={styles.changeSpecificCategoryText}> | |||
| <b>{t('changeSpecificCategory')}</b> | |||
| </p> | |||
| </Flex> | |||
| </div> | |||
| </section> | |||
| <section className={styles.uploadContent}> | |||
| <Dragger | |||
| {...props} | |||
| className={classNames(styles.uploader, { | |||
| [styles.hiddenUploader]: !isUpload, | |||
| })} | |||
| > | |||
| <Button className={styles.uploaderButton}> | |||
| <CloudUploadOutlined className={styles.uploaderIcon} /> | |||
| </Button> | |||
| <p className="ant-upload-text">{t('uploadTitle')}</p> | |||
| <p className="ant-upload-hint">{t('uploadDescription')}</p> | |||
| </Dragger> | |||
| </section> | |||
| <section className={styles.footer}> | |||
| <Button | |||
| type="primary" | |||
| className={styles.nextButton} | |||
| onClick={handleNextClick} | |||
| disabled={!enabled} | |||
| size="large" | |||
| > | |||
| {t('next', { keyPrefix: 'common' })} | |||
| </Button> | |||
| </section> | |||
| </div> | |||
| <ChunkMethodModal | |||
| documentId={currentRecord.id} | |||
| parserId={currentRecord.parser_id} | |||
| parserConfig={currentRecord.parser_config} | |||
| documentExtension={getExtension(currentRecord.name)} | |||
| onOk={onChangeParserOk} | |||
| visible={changeParserVisible} | |||
| hideModal={hideChangeParserModal} | |||
| loading={changeParserLoading} | |||
| /> | |||
| </> | |||
| ); | |||
| }; | |||
| export default KnowledgeUploadFile; | |||
| @@ -1,12 +1,9 @@ | |||
| import { | |||
| useFetchKnowledgeBaseConfiguration, | |||
| useKnowledgeBaseId, | |||
| useSelectKnowledgeDetails, | |||
| useUpdateKnowledge, | |||
| } from '@/hooks/knowledge-hooks'; | |||
| import { useFetchLlmList, useSelectLlmOptions } from '@/hooks/llm-hooks'; | |||
| import { useNavigateToDataset } from '@/hooks/route-hook'; | |||
| import { useOneNamespaceEffectsLoading } from '@/hooks/store-hooks'; | |||
| import { | |||
| useFetchTenantInfo, | |||
| useSelectParserList, | |||
| @@ -15,6 +12,7 @@ import { | |||
| getBase64FromUploadFileList, | |||
| getUploadFileListFromBase64, | |||
| } from '@/utils/fileUtil'; | |||
| import { useIsFetching } from '@tanstack/react-query'; | |||
| import { Form, UploadFile } from 'antd'; | |||
| import { FormInstance } from 'antd/lib'; | |||
| import pick from 'lodash/pick'; | |||
| @@ -22,32 +20,32 @@ import { useCallback, useEffect } from 'react'; | |||
| import { LlmModelType } from '../../constant'; | |||
| export const useSubmitKnowledgeConfiguration = (form: FormInstance) => { | |||
| const save = useUpdateKnowledge(); | |||
| const knowledgeBaseId = useKnowledgeBaseId(); | |||
| const submitLoading = useOneNamespaceEffectsLoading('kSModel', ['updateKb']); | |||
| const { saveKnowledgeConfiguration, loading } = useUpdateKnowledge(); | |||
| const navigateToDataset = useNavigateToDataset(); | |||
| const submitKnowledgeConfiguration = useCallback(async () => { | |||
| const values = await form.validateFields(); | |||
| const avatar = await getBase64FromUploadFileList(values.avatar); | |||
| save({ | |||
| saveKnowledgeConfiguration({ | |||
| ...values, | |||
| avatar, | |||
| kb_id: knowledgeBaseId, | |||
| }); | |||
| navigateToDataset(); | |||
| }, [save, knowledgeBaseId, form, navigateToDataset]); | |||
| }, [saveKnowledgeConfiguration, form, navigateToDataset]); | |||
| return { submitKnowledgeConfiguration, submitLoading, navigateToDataset }; | |||
| return { | |||
| submitKnowledgeConfiguration, | |||
| submitLoading: loading, | |||
| navigateToDataset, | |||
| }; | |||
| }; | |||
| export const useFetchKnowledgeConfigurationOnMount = (form: FormInstance) => { | |||
| const knowledgeDetails = useSelectKnowledgeDetails(); | |||
| const parserList = useSelectParserList(); | |||
| const embeddingModelOptions = useSelectLlmOptions(); | |||
| useFetchTenantInfo(); | |||
| useFetchKnowledgeBaseConfiguration(); | |||
| const { data: knowledgeDetails } = useFetchKnowledgeBaseConfiguration(); | |||
| useFetchLlmList(LlmModelType.Embedding); | |||
| useEffect(() => { | |||
| @@ -76,7 +74,7 @@ export const useFetchKnowledgeConfigurationOnMount = (form: FormInstance) => { | |||
| }; | |||
| export const useSelectKnowledgeDetailsLoading = () => | |||
| useOneNamespaceEffectsLoading('kSModel', ['getKbDetail']); | |||
| useIsFetching({ queryKey: ['fetchKnowledgeDetail'] }) > 0; | |||
| export const useHandleChunkMethodChange = () => { | |||
| const [form] = Form.useForm(); | |||
| @@ -1,49 +0,0 @@ | |||
| import { IKnowledge } from '@/interfaces/database/knowledge'; | |||
| import i18n from '@/locales/config'; | |||
| import kbService from '@/services/knowledge-service'; | |||
| import { message } from 'antd'; | |||
| import { DvaModel } from 'umi'; | |||
| export interface KSModelState { | |||
| isShowPSwModal: boolean; | |||
| tenantIfo: any; | |||
| knowledgeDetails: IKnowledge; | |||
| } | |||
| const model: DvaModel<KSModelState> = { | |||
| namespace: 'kSModel', | |||
| state: { | |||
| isShowPSwModal: false, | |||
| tenantIfo: {}, | |||
| knowledgeDetails: {} as any, | |||
| }, | |||
| reducers: { | |||
| updateState(state, { payload }) { | |||
| return { | |||
| ...state, | |||
| ...payload, | |||
| }; | |||
| }, | |||
| setKnowledgeDetails(state, { payload }) { | |||
| return { ...state, knowledgeDetails: payload }; | |||
| }, | |||
| }, | |||
| effects: { | |||
| *updateKb({ payload = {} }, { call, put }) { | |||
| const { data } = yield call(kbService.updateKb, payload); | |||
| const { retcode } = data; | |||
| if (retcode === 0) { | |||
| yield put({ type: 'getKbDetail', payload: { kb_id: payload.kb_id } }); | |||
| message.success(i18n.t('message.updated')); | |||
| } | |||
| }, | |||
| *getKbDetail({ payload = {} }, { call, put }) { | |||
| const { data } = yield call(kbService.get_kb_detail, payload); | |||
| if (data.retcode === 0) { | |||
| yield put({ type: 'setKnowledgeDetails', payload: data.data }); | |||
| } | |||
| return data; | |||
| }, | |||
| }, | |||
| }; | |||
| export default model; | |||
| @@ -3,7 +3,6 @@ import { ReactComponent as DatasetIcon } from '@/assets/svg/knowledge-dataset.sv | |||
| import { ReactComponent as TestingIcon } from '@/assets/svg/knowledge-testing.svg'; | |||
| import { useFetchKnowledgeBaseConfiguration } from '@/hooks/knowledge-hooks'; | |||
| import { useSecondPathName } from '@/hooks/route-hook'; | |||
| import { IKnowledge } from '@/interfaces/database/knowledge'; | |||
| import { getWidth } from '@/utils'; | |||
| import { Avatar, Menu, MenuProps, Space } from 'antd'; | |||
| import classNames from 'classnames'; | |||
| @@ -11,6 +10,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react'; | |||
| import { useTranslation } from 'react-i18next'; | |||
| import { useNavigate, useSelector } from 'umi'; | |||
| import { KnowledgeRouteKey } from '../../constant'; | |||
| import styles from './index.less'; | |||
| const KnowledgeSidebar = () => { | |||
| @@ -18,13 +18,11 @@ const KnowledgeSidebar = () => { | |||
| const { id } = kAModel; | |||
| let navigate = useNavigate(); | |||
| const activeKey = useSecondPathName(); | |||
| const knowledgeDetails: IKnowledge = useSelector( | |||
| (state: any) => state.kSModel.knowledgeDetails, | |||
| ); | |||
| const [windowWidth, setWindowWidth] = useState(getWidth()); | |||
| const [collapsed, setCollapsed] = useState(false); | |||
| const { t } = useTranslation(); | |||
| const { data: knowledgeDetails } = useFetchKnowledgeBaseConfiguration(); | |||
| const handleSelect: MenuProps['onSelect'] = (e) => { | |||
| navigate(`/knowledge/${e.key}?id=${id}`); | |||
| @@ -94,8 +92,6 @@ const KnowledgeSidebar = () => { | |||
| }; | |||
| }, []); | |||
| useFetchKnowledgeBaseConfiguration(); | |||
| return ( | |||
| <div className={styles.sidebarWrapper}> | |||
| <div className={styles.sidebarTop}> | |||
| @@ -1,63 +0,0 @@ | |||
| import { IKnowledge } from '@/interfaces/database/knowledge'; | |||
| import kbService from '@/services/knowledge-service'; | |||
| import { DvaModel } from 'umi'; | |||
| export interface KnowledgeModelState { | |||
| data: IKnowledge[]; | |||
| knowledge: IKnowledge; | |||
| } | |||
| const model: DvaModel<KnowledgeModelState> = { | |||
| namespace: 'knowledgeModel', | |||
| state: { | |||
| data: [], | |||
| knowledge: {} as IKnowledge, | |||
| }, | |||
| reducers: { | |||
| updateState(state, { payload }) { | |||
| return { | |||
| ...state, | |||
| ...payload, | |||
| }; | |||
| }, | |||
| setKnowledge(state, { payload }) { | |||
| return { | |||
| ...state, | |||
| knowledge: payload, | |||
| }; | |||
| }, | |||
| }, | |||
| effects: { | |||
| *rmKb({ payload = {} }, { call, put }) { | |||
| const { data } = yield call(kbService.rmKb, payload); | |||
| const { retcode } = data; | |||
| if (retcode === 0) { | |||
| yield put({ | |||
| type: 'getList', | |||
| payload: {}, | |||
| }); | |||
| } | |||
| }, | |||
| *getList({ payload = {} }, { call, put }) { | |||
| const { data } = yield call(kbService.getList, payload); | |||
| const { retcode, data: res } = data; | |||
| if (retcode === 0) { | |||
| yield put({ | |||
| type: 'updateState', | |||
| payload: { | |||
| data: res, | |||
| }, | |||
| }); | |||
| } | |||
| }, | |||
| *getKnowledgeDetail({ payload = {} }, { call, put }) { | |||
| const { data } = yield call(kbService.get_kb_detail, payload); | |||
| if (data.retcode === 0) { | |||
| yield put({ type: 'setKnowledge', payload: data.data }); | |||
| } | |||
| return data.retcode; | |||
| }, | |||
| }, | |||
| }; | |||
| export default model; | |||
| @@ -32,11 +32,6 @@ const routes = [ | |||
| path: '/knowledge/dataset', | |||
| component: '@/pages/add-knowledge/components/knowledge-file', | |||
| }, | |||
| { | |||
| path: '/knowledge/dataset/upload', | |||
| component: | |||
| '@/pages/add-knowledge/components/knowledge-dataset/knowledge-upload-file', | |||
| }, | |||
| { | |||
| path: '/knowledge/dataset/chunk', | |||
| component: '@/pages/add-knowledge/components/knowledge-chunk', | |||
| @@ -1,39 +1,35 @@ | |||
| import { ChunkModelState } from '@/pages/add-knowledge/components/knowledge-chunk/model'; | |||
| import { KFModelState } from '@/pages/add-knowledge/components/knowledge-file/model'; | |||
| import { KSModelState } from '@/pages/add-knowledge/components/knowledge-setting/model'; | |||
| import { TestingModelState } from '@/pages/add-knowledge/components/knowledge-testing/model'; | |||
| import { kAModelState } from '@/pages/add-knowledge/model'; | |||
| import { ChatModelState } from '@/pages/chat/model'; | |||
| import { FileManagerModelState } from '@/pages/file-manager/model'; | |||
| import { KnowledgeModelState } from '@/pages/knowledge/model'; | |||
| import { LoginModelState } from '@/pages/login/model'; | |||
| import { SettingModelState } from '@/pages/user-setting/model'; | |||
| declare module 'lodash'; | |||
| function useSelector<TState = RootState, TSelected = unknown>( | |||
| selector: (state: TState) => TSelected, | |||
| equalityFn?: (left: TSelected, right: TSelected) => boolean, | |||
| ): TSelected; | |||
| export interface RootState { | |||
| // loading: Loading; | |||
| fileManager: FileManagerModelState; | |||
| chatModel: ChatModelState; | |||
| loginModel: LoginModelState; | |||
| knowledgeModel: KnowledgeModelState; | |||
| settingModel: SettingModelState; | |||
| kFModel: KFModelState; | |||
| kAModel: kAModelState; | |||
| chunkModel: ChunkModelState; | |||
| kSModel: KSModelState; | |||
| testingModel: TestingModelState; | |||
| } | |||
| declare global { | |||
| type Nullable<T> = T | null; | |||
| } | |||
| declare module 'umi' { | |||
| export { useSelector }; | |||
| } | |||
| import { ChunkModelState } from '@/pages/add-knowledge/components/knowledge-chunk/model'; | |||
| import { KFModelState } from '@/pages/add-knowledge/components/knowledge-file/model'; | |||
| import { TestingModelState } from '@/pages/add-knowledge/components/knowledge-testing/model'; | |||
| import { kAModelState } from '@/pages/add-knowledge/model'; | |||
| import { ChatModelState } from '@/pages/chat/model'; | |||
| import { FileManagerModelState } from '@/pages/file-manager/model'; | |||
| import { LoginModelState } from '@/pages/login/model'; | |||
| import { SettingModelState } from '@/pages/user-setting/model'; | |||
| declare module 'lodash'; | |||
| function useSelector<TState = RootState, TSelected = unknown>( | |||
| selector: (state: TState) => TSelected, | |||
| equalityFn?: (left: TSelected, right: TSelected) => boolean, | |||
| ): TSelected; | |||
| export interface RootState { | |||
| // loading: Loading; | |||
| fileManager: FileManagerModelState; | |||
| chatModel: ChatModelState; | |||
| loginModel: LoginModelState; | |||
| settingModel: SettingModelState; | |||
| kFModel: KFModelState; | |||
| kAModel: kAModelState; | |||
| chunkModel: ChunkModelState; | |||
| testingModel: TestingModelState; | |||
| } | |||
| declare global { | |||
| type Nullable<T> = T | null; | |||
| } | |||
| declare module 'umi' { | |||
| export { useSelector }; | |||
| } | |||