Feat: Render the skills list using a tree view. (#17115)

### Summary
Feat: Render the skills list using a tree view.
This commit is contained in:
balibabu
2026-07-20 19:00:08 +08:00
committed by GitHub
parent aff9ff6d0a
commit 392b249404
33 changed files with 571 additions and 826 deletions

View File

@@ -37,7 +37,6 @@ import {
AutoQuestionsFormField,
} from '../auto-keywords-form-field';
import { ChildrenDelimiterForm } from '../children-delimiter-form';
import { CompilationTemplateFormField } from '../compilation-template-form-field';
import { DataFlowSelect } from '../data-pipeline-select';
import { DelimiterFormField } from '../delimiter-form-field';
import { EntityTypesFormField } from '../entity-types-form-field';
@@ -153,7 +152,6 @@ export function ChunkMethodDialog({
)
.optional(),
enable_metadata: z.boolean().optional(),
compilation_template_group_id: z.array(z.string()).optional(),
}),
})
.superRefine((data, ctx) => {
@@ -302,10 +300,6 @@ export function ChunkMethodDialog({
<ParseTypeItem />
{parseType === ParseType.BuiltIn && <ChunkMethodItem />}
{parseType === ParseType.BuiltIn && (
<CompilationTemplateFormField></CompilationTemplateFormField>
)}
{showPages && parseType === ParseType.BuiltIn && (
<DynamicPageRange />
)}

View File

@@ -42,7 +42,6 @@ export function useDefaultParserValues() {
metadata: [],
built_in_metadata: [],
enable_metadata: false,
compilation_template_group_id: [],
};
return defaultParserValues as IParserConfig;

View File

@@ -1,103 +1,25 @@
import { RAGFlowFormItem } from '@/components/ragflow-form';
import {
MultiSelect,
MultiSelectOptionType,
} from '@/components/ui/multi-select';
import { useFetchAllCompilationTemplateGroups } from '@/hooks/use-compilation-template-group-request';
import { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { SelectWithSearch } from './originui/select-with-search';
type CompilationTemplateFormFieldProps = {
horizontal?: boolean;
name?: string;
};
const ScopeTranslationKeyMap: Record<string, string> = {
file: 'scopeFile',
dataset: 'scopeDataset',
};
type CompilationTemplateMultiSelectProps = {
value?: string[];
onChange(value: string[]): void;
};
/**
* Renders a multi-select for compilation template groups.
*
* Selection rule:
* - Each group has a scope: "file" or "dataset".
* - At most one group per scope can be selected.
* - The two scopes can be combined (one file group + one dataset group).
* - Once a scope is selected, remaining options of the same scope are disabled.
* - The scope is displayed as a suffix after each option label.
*/
function CompilationTemplateMultiSelect({
value: rawValue = [],
onChange,
}: CompilationTemplateMultiSelectProps) {
const { t } = useTranslation();
const { groups } = useFetchAllCompilationTemplateGroups();
const value = useMemo(() => {
// Normalize legacy single-string values into an array during the migration.
if (Array.isArray(rawValue)) return rawValue;
if (typeof rawValue === 'string' && rawValue) return [rawValue];
return [];
}, [rawValue]);
// Collect scopes that are already selected by the current value.
const selectedScopes = useMemo(() => {
const scopes = new Set<string>();
value.forEach((id) => {
const group = groups?.find((g) => g.id === id);
if (group?.scope) {
scopes.add(group.scope);
}
});
return scopes;
}, [value, groups]);
const options = useMemo<MultiSelectOptionType[]>(() => {
return (groups ?? []).map((group) => {
const scopeTranslationKey = group.scope
? ScopeTranslationKeyMap[group.scope]
: undefined;
// Disable other options that share an already-selected scope.
const isSameScopeSelected =
!!group.scope &&
selectedScopes.has(group.scope) &&
!value.includes(group.id);
return {
label: group.name,
value: group.id,
disabled: isSameScopeSelected,
suffix: scopeTranslationKey ? (
<span className="text-text-secondary ml-1">
({t(`knowledgeConfiguration.${scopeTranslationKey}`)})
</span>
) : undefined,
};
});
}, [groups, selectedScopes, value, t]);
return (
<MultiSelect
options={options}
onValueChange={onChange}
defaultValue={value}
value={value}
showSelectAll={false}
/>
);
}
export function CompilationTemplateFormField({
horizontal,
name = 'parser_config.compilation_template_group_id',
}: CompilationTemplateFormFieldProps) {
const { t } = useTranslation();
const { groups } = useFetchAllCompilationTemplateGroups();
const options = useMemo(
() => groups?.map((group) => ({ label: group.name, value: group.id })),
[groups],
);
return (
<RAGFlowFormItem
@@ -107,9 +29,10 @@ export function CompilationTemplateFormField({
horizontal={horizontal}
>
{(field) => (
<CompilationTemplateMultiSelect
value={field.value ?? []}
<SelectWithSearch
value={field.value}
onChange={field.onChange}
options={options}
/>
)}
</RAGFlowFormItem>

View File

@@ -21,7 +21,9 @@ export default function MarkdownEditor({
const contentRef = useRef(content);
useEffect(() => {
contentRef.current = content;
if (content === contentRef.current) {
return;
}
if (showSource) setRawContent(content);
}, [showSource, content]);