feat: add KnowledgeGraph component for visualizing, editing, and syncing handbook content with AI-driven analysis
This commit is contained in:
@@ -28,8 +28,19 @@ const KnowledgeGraph = () => {
|
|||||||
const [relations, setRelations] = useState([]);
|
const [relations, setRelations] = useState([]);
|
||||||
|
|
||||||
const reloadKb = useCallback(() => {
|
const reloadKb = useCallback(() => {
|
||||||
db.getTopics().then(setTopics);
|
Promise.all([db.getTopics(), db.getRelations()]).then(([allTopics, allRelations]) => {
|
||||||
db.getRelations().then(setRelations);
|
const topicIds = new Set(allTopics.map(t => t.id));
|
||||||
|
const validRelations = allRelations
|
||||||
|
.map(r => ({
|
||||||
|
...r,
|
||||||
|
source: r.source?.id || r.source,
|
||||||
|
target: r.target?.id || r.target
|
||||||
|
}))
|
||||||
|
.filter(r => topicIds.has(r.source) && topicIds.has(r.target));
|
||||||
|
|
||||||
|
setTopics(allTopics);
|
||||||
|
setRelations(validRelations);
|
||||||
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -164,7 +175,13 @@ const KnowledgeGraph = () => {
|
|||||||
const deleteNode = async () => {
|
const deleteNode = async () => {
|
||||||
if (confirm(`Are you sure you want to delete "${selectedNode.label}"? This will also remove any relations connected to it.`)) {
|
if (confirm(`Are you sure you want to delete "${selectedNode.label}"? This will also remove any relations connected to it.`)) {
|
||||||
const updatedTopics = topics.filter(t => t.id !== selectedNode.id);
|
const updatedTopics = topics.filter(t => t.id !== selectedNode.id);
|
||||||
const updatedRelations = relations.filter(r => r.source !== selectedNode.id && r.target !== selectedNode.id);
|
const updatedRelations = relations
|
||||||
|
.map(r => ({
|
||||||
|
...r,
|
||||||
|
source: r.source?.id || r.source,
|
||||||
|
target: r.target?.id || r.target
|
||||||
|
}))
|
||||||
|
.filter(r => r.source !== selectedNode.id && r.target !== selectedNode.id);
|
||||||
|
|
||||||
await db.saveTopics(updatedTopics);
|
await db.saveTopics(updatedTopics);
|
||||||
await db.saveRelations(updatedRelations);
|
await db.saveRelations(updatedRelations);
|
||||||
@@ -324,7 +341,19 @@ Analyze this graph and return ONLY the optimized JSON object with this EXACT str
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updatedRelations = updatedRelations.filter(r => r.source !== r.target);
|
// Ensure all relations only reference existing nodes and are normalized to string IDs
|
||||||
|
const finalTopicIds = new Set(updatedTopics.map(t => t.id));
|
||||||
|
updatedRelations = updatedRelations
|
||||||
|
.map(r => ({
|
||||||
|
...r,
|
||||||
|
source: r.source?.id || r.source,
|
||||||
|
target: r.target?.id || r.target
|
||||||
|
}))
|
||||||
|
.filter(r =>
|
||||||
|
r.source !== r.target &&
|
||||||
|
finalTopicIds.has(r.source) &&
|
||||||
|
finalTopicIds.has(r.target)
|
||||||
|
);
|
||||||
|
|
||||||
await db.saveTopics(updatedTopics);
|
await db.saveTopics(updatedTopics);
|
||||||
await db.saveRelations(updatedRelations);
|
await db.saveRelations(updatedRelations);
|
||||||
|
|||||||
Reference in New Issue
Block a user