mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-08-17 22:08:29 +08:00
fix(search): show honest empty state when mind map has no content (#18294)
This commit is contained in:
@@ -86,7 +86,7 @@ func runMindMap(ctx context.Context, config mindMapRunConfig) (mindMapNode, erro
|
||||
sb.WriteString(delta)
|
||||
}
|
||||
fullText := sb.String()
|
||||
if fullText == "" {
|
||||
if strings.TrimSpace(fullText) == "" {
|
||||
return mindMapNode{ID: "root", Children: []mindMapNode{}}, nil
|
||||
}
|
||||
return parseMindMapMarkdown(fullText), nil
|
||||
|
||||
72
internal/handler/mindmap_test.go
Normal file
72
internal/handler/mindmap_test.go
Normal file
@@ -0,0 +1,72 @@
|
||||
//
|
||||
// Copyright 2026 The InfiniFlow Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
package handler
|
||||
|
||||
import "testing"
|
||||
|
||||
// The mind map contract: when there is nothing to map, the backend returns an
|
||||
// honest empty tree (root with no children) and the frontend renders an empty
|
||||
// state. No synthetic nodes are fabricated.
|
||||
func TestParseMindMapMarkdownEmpty(t *testing.T) {
|
||||
t.Run("prose without headings or list items yields an empty tree", func(t *testing.T) {
|
||||
node := parseMindMapMarkdown("I cannot summarize this text right now.")
|
||||
if node.ID != "root" || len(node.Children) != 0 {
|
||||
t.Fatalf("expected root-only tree, got %+v", node)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("think-only answer yields an empty tree", func(t *testing.T) {
|
||||
node := parseMindMapMarkdown("<think>reasoning without any outline</think>")
|
||||
if node.ID != "root" || len(node.Children) != 0 {
|
||||
t.Fatalf("expected root-only tree, got %+v", node)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("blank answer yields an empty tree", func(t *testing.T) {
|
||||
node := parseMindMapMarkdown(" \n\n")
|
||||
if node.ID != "root" || len(node.Children) != 0 {
|
||||
t.Fatalf("expected root-only tree, got %+v", node)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestParseMindMapMarkdownTree(t *testing.T) {
|
||||
t.Run("headings and nested lists build a real tree", func(t *testing.T) {
|
||||
node := parseMindMapMarkdown("# Title\n## Section A\n- point 1\n - point 1.1\n## Section B\n")
|
||||
if node.ID != "Title" {
|
||||
t.Fatalf("expected single top heading as root, got %+v", node)
|
||||
}
|
||||
if len(node.Children) != 2 {
|
||||
t.Fatalf("expected 2 sections, got %+v", node.Children)
|
||||
}
|
||||
sectionA := node.Children[0]
|
||||
if sectionA.ID != "Section A" || len(sectionA.Children) != 1 {
|
||||
t.Fatalf("unexpected Section A: %+v", sectionA)
|
||||
}
|
||||
point := sectionA.Children[0]
|
||||
if point.ID != "point 1" || len(point.Children) != 1 || point.Children[0].ID != "point 1.1" {
|
||||
t.Fatalf("unexpected nested list parse: %+v", point)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("multiple top headings keep an explicit root with children", func(t *testing.T) {
|
||||
node := parseMindMapMarkdown("# Alpha\n# Beta\n")
|
||||
if node.ID != "root" || len(node.Children) != 2 {
|
||||
t.Fatalf("expected root with 2 children, got %+v", node)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -34,6 +34,10 @@ interface IProps extends IModalProps<any> {
|
||||
const MindMapSheet = ({ data, hideModal, loading, visible }: IProps) => {
|
||||
const { t } = useTranslation();
|
||||
const percent = usePendingMindMap();
|
||||
// An empty tree (no children) means the backend honestly found nothing to
|
||||
// map. Render an explicit empty state instead of a ghost "root" node.
|
||||
const isEmptyMindMap =
|
||||
!data || !Array.isArray(data.children) || data.children.length === 0;
|
||||
return (
|
||||
<Sheet open={visible} modal={false}>
|
||||
<SheetContent
|
||||
@@ -61,7 +65,14 @@ const MindMapSheet = ({ data, hideModal, loading, visible }: IProps) => {
|
||||
<Progress value={percent} className="h-1 flex-1 min-w-10" />
|
||||
</div>
|
||||
)}
|
||||
{!loading && (
|
||||
{!loading && isEmptyMindMap && (
|
||||
<div className="bg-bg-card rounded-lg w-full h-full flex items-center justify-center">
|
||||
<p className="text-text-secondary">
|
||||
{t('knowledgeDetails.noStructureMindmap')}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
{!loading && !isEmptyMindMap && (
|
||||
<div className="bg-bg-card rounded-lg w-full h-full">
|
||||
<IndentedTree data={data}></IndentedTree>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user