mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-07-05 19:08:38 +08:00
### What problem does this PR solve? Fix #14801 to allow search dataset list when add, following on #14825 <img width="2172" height="857" alt="image" src="https://github.com/user-attachments/assets/65ea7647-56f4-4c16-8437-121b834811f0" /> ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)
This commit is contained in:
@@ -2,8 +2,9 @@ import { DocumentParserType } from '@/constants/knowledge';
|
||||
import { useFetchKnowledgeList } from '@/hooks/use-knowledge-request';
|
||||
import { IDataset } from '@/interfaces/database/dataset';
|
||||
import { useBuildQueryVariableOptions } from '@/pages/agent/hooks/use-get-begin-query';
|
||||
import { useDebounce } from 'ahooks';
|
||||
import { toLower } from 'lodash';
|
||||
import { useMemo } from 'react';
|
||||
import { type ReactNode, useCallback, useMemo, useRef, useState } from 'react';
|
||||
import { useFormContext, useWatch } from 'react-hook-form';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { RAGFlowAvatar } from './ragflow-avatar';
|
||||
@@ -23,17 +24,43 @@ function DatasetLabel({ text }: { text: string }) {
|
||||
}
|
||||
|
||||
export function useDisableDifferenceEmbeddingDataset(name: string) {
|
||||
const { list: datasetListOrigin } = useFetchKnowledgeList(true);
|
||||
const form = useFormContext();
|
||||
const datasetId = useWatch({ name, control: form.control });
|
||||
const [searchString, setSearchString] = useState('');
|
||||
const debouncedSearchString = useDebounce(searchString, { wait: 500 });
|
||||
const { list: datasetListOrigin, loading } = useFetchKnowledgeList(
|
||||
true,
|
||||
debouncedSearchString,
|
||||
);
|
||||
const datasetCacheRef = useRef(new Map<string, IDataset>());
|
||||
|
||||
const selectedEmbedId = useMemo(() => {
|
||||
const data = datasetListOrigin?.find((item) => item.id === datasetId?.[0]);
|
||||
return data?.embedding_model ?? '';
|
||||
const datasetList = useMemo(() => {
|
||||
datasetListOrigin.forEach((dataset) => {
|
||||
datasetCacheRef.current.set(dataset.id, dataset);
|
||||
});
|
||||
|
||||
const selectedDatasetIds = Array.isArray(datasetId) ? datasetId : [];
|
||||
const selectedDatasets = selectedDatasetIds
|
||||
.map((id) => datasetCacheRef.current.get(id))
|
||||
.filter(Boolean) as IDataset[];
|
||||
|
||||
return Array.from(
|
||||
new Map(
|
||||
[...datasetListOrigin, ...selectedDatasets].map((dataset) => [
|
||||
dataset.id,
|
||||
dataset,
|
||||
]),
|
||||
).values(),
|
||||
);
|
||||
}, [datasetId, datasetListOrigin]);
|
||||
|
||||
const selectedEmbedId = useMemo(() => {
|
||||
const data = datasetList?.find((item) => item.id === datasetId?.[0]);
|
||||
return data?.embedding_model ?? '';
|
||||
}, [datasetId, datasetList]);
|
||||
|
||||
const nextOptions = useMemo(() => {
|
||||
const datasetListMap = datasetListOrigin
|
||||
const datasetListMap = datasetList
|
||||
.filter((x) => x.chunk_method !== DocumentParserType.Tag)
|
||||
.map((item: IDataset) => {
|
||||
return {
|
||||
@@ -58,10 +85,17 @@ export function useDisableDifferenceEmbeddingDataset(name: string) {
|
||||
});
|
||||
|
||||
return datasetListMap;
|
||||
}, [datasetListOrigin, selectedEmbedId]);
|
||||
}, [datasetList, selectedEmbedId]);
|
||||
|
||||
const handleSearchChange = useCallback((value: string) => {
|
||||
setSearchString(value);
|
||||
}, []);
|
||||
|
||||
return {
|
||||
datasetOptions: nextOptions,
|
||||
handleSearchChange,
|
||||
loading,
|
||||
searchString,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -76,7 +110,8 @@ export function KnowledgeBaseFormField({
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { datasetOptions } = useDisableDifferenceEmbeddingDataset(name);
|
||||
const { datasetOptions, handleSearchChange, loading, searchString } =
|
||||
useDisableDifferenceEmbeddingDataset(name);
|
||||
|
||||
const nextOptions = buildQueryVariableOptionsByShowVariable(showVariable)();
|
||||
|
||||
@@ -89,17 +124,26 @@ export function KnowledgeBaseFormField({
|
||||
options: knowledgeOptions,
|
||||
},
|
||||
...nextOptions.map((x) => {
|
||||
const groupLabel = (('label' in x
|
||||
? x.label
|
||||
: 'title' in x
|
||||
? x.title
|
||||
: '') ?? '') as ReactNode;
|
||||
|
||||
return {
|
||||
...x,
|
||||
label: groupLabel,
|
||||
options: x.options
|
||||
.filter((y) => toLower(y.type).includes('string'))
|
||||
.map((x) => ({
|
||||
...x,
|
||||
label: x.label ?? x.value ?? '',
|
||||
value: x.value ?? '',
|
||||
icon: () => (
|
||||
<RAGFlowAvatar
|
||||
className="size-4 mr-2"
|
||||
avatar={x.label}
|
||||
name={x.label}
|
||||
avatar={String(x.label ?? '')}
|
||||
name={String(x.label ?? '')}
|
||||
/>
|
||||
),
|
||||
})),
|
||||
@@ -130,6 +174,10 @@ export function KnowledgeBaseFormField({
|
||||
showSelectAll={false}
|
||||
popoverTestId="datasets-options"
|
||||
optionTestIdPrefix="datasets"
|
||||
searchValue={searchString}
|
||||
onSearchChange={handleSearchChange}
|
||||
isSearching={loading}
|
||||
shouldFilter={false}
|
||||
{...field}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -188,6 +188,10 @@ interface MultiSelectProps
|
||||
showSelectAll?: boolean;
|
||||
popoverTestId?: string;
|
||||
optionTestIdPrefix?: string;
|
||||
searchValue?: string;
|
||||
onSearchChange?: (value: string) => void;
|
||||
isSearching?: boolean;
|
||||
shouldFilter?: boolean;
|
||||
}
|
||||
|
||||
export const MultiSelect = React.forwardRef<
|
||||
@@ -209,6 +213,10 @@ export const MultiSelect = React.forwardRef<
|
||||
showSelectAll = true,
|
||||
popoverTestId,
|
||||
optionTestIdPrefix,
|
||||
searchValue,
|
||||
onSearchChange,
|
||||
isSearching = false,
|
||||
shouldFilter,
|
||||
...props
|
||||
},
|
||||
ref,
|
||||
@@ -434,15 +442,19 @@ export const MultiSelect = React.forwardRef<
|
||||
onEscapeKeyDown={() => setIsPopoverOpen(false)}
|
||||
data-testid={popoverTestId}
|
||||
>
|
||||
<Command className="p-5 pb-8">
|
||||
{options && options.length > 0 && (
|
||||
<Command className="p-5 pb-8" shouldFilter={shouldFilter}>
|
||||
{((options && options.length > 0) || onSearchChange) && (
|
||||
<CommandInput
|
||||
placeholder={t('common.search') + '...'}
|
||||
onKeyDown={handleInputKeyDown}
|
||||
value={searchValue}
|
||||
onValueChange={onSearchChange}
|
||||
/>
|
||||
)}
|
||||
<CommandList className="mt-2">
|
||||
<CommandEmpty>No results found.</CommandEmpty>
|
||||
<CommandEmpty>
|
||||
{isSearching ? t('common.searching') : t('common.noDataFound')}
|
||||
</CommandEmpty>
|
||||
<CommandGroup>
|
||||
{showSelectAll && options && options.length > 0 && (
|
||||
<CommandItem
|
||||
|
||||
@@ -424,16 +424,29 @@ export const useRemoveKnowledgeGraph = () => {
|
||||
|
||||
export const useFetchKnowledgeList = (
|
||||
shouldFilterListWithoutDocument: boolean = false,
|
||||
keywords = '',
|
||||
): {
|
||||
list: IDataset[];
|
||||
loading: boolean;
|
||||
} => {
|
||||
const { data, isFetching: loading } = useQuery({
|
||||
queryKey: [KnowledgeApiAction.FetchKnowledgeList],
|
||||
queryKey: [
|
||||
KnowledgeApiAction.FetchKnowledgeList,
|
||||
shouldFilterListWithoutDocument,
|
||||
keywords,
|
||||
],
|
||||
initialData: [],
|
||||
gcTime: 0, // https://tanstack.com/query/latest/docs/framework/react/guides/caching?from=reactQueryV3
|
||||
queryFn: async () => {
|
||||
const { data } = await listDataset();
|
||||
const { data } = await listDataset(
|
||||
keywords
|
||||
? {
|
||||
ext: {
|
||||
keywords,
|
||||
},
|
||||
}
|
||||
: undefined,
|
||||
);
|
||||
const list = data?.data ?? [];
|
||||
return shouldFilterListWithoutDocument
|
||||
? list.filter((x: IDataset) => x.chunk_count > 0)
|
||||
|
||||
Reference in New Issue
Block a user