mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-17 18:35:19 +02:00
refactor: replace DocumentsDataTable with DocumentMentionPicker for improved document selection
- Introduced DocumentMentionPicker component to enhance document selection experience in the chat interface. - Updated InlineMentionEditor and Composer components to utilize the new DocumentMentionPicker. - Removed the deprecated DocumentsDataTable component to streamline the codebase and improve maintainability. - Enhanced type safety and validation in document handling logic.
This commit is contained in:
parent
9bc3f193c3
commit
2fdf567b71
5 changed files with 327 additions and 299 deletions
|
|
@ -45,6 +45,27 @@ interface InlineMentionEditorProps {
|
|||
const CHIP_DATA_ATTR = "data-mention-chip";
|
||||
const CHIP_ID_ATTR = "data-mention-id";
|
||||
|
||||
/**
|
||||
* Type guard to check if a node is a chip element
|
||||
*/
|
||||
function isChipElement(node: Node | null): node is HTMLSpanElement {
|
||||
return (
|
||||
node !== null &&
|
||||
node.nodeType === Node.ELEMENT_NODE &&
|
||||
(node as Element).hasAttribute(CHIP_DATA_ATTR)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely parse chip ID from element attribute
|
||||
*/
|
||||
function getChipId(element: Element): number | null {
|
||||
const idStr = element.getAttribute(CHIP_ID_ATTR);
|
||||
if (!idStr) return null;
|
||||
const id = parseInt(idStr, 10);
|
||||
return Number.isNaN(id) ? null : id;
|
||||
}
|
||||
|
||||
export const InlineMentionEditor = forwardRef<InlineMentionEditorRef, InlineMentionEditorProps>(
|
||||
(
|
||||
{
|
||||
|
|
@ -177,6 +198,12 @@ export const InlineMentionEditor = forwardRef<InlineMentionEditorRef, InlineMent
|
|||
(doc: Document) => {
|
||||
if (!editorRef.current) return;
|
||||
|
||||
// Validate required fields for type safety
|
||||
if (typeof doc.id !== "number" || typeof doc.title !== "string") {
|
||||
console.warn("[InlineMentionEditor] Invalid document passed to insertDocumentChip:", doc);
|
||||
return;
|
||||
}
|
||||
|
||||
const mentionDoc: MentionedDocument = {
|
||||
id: doc.id,
|
||||
title: doc.title,
|
||||
|
|
@ -381,19 +408,21 @@ export const InlineMentionEditor = forwardRef<InlineMentionEditorRef, InlineMent
|
|||
const offset = range.startOffset;
|
||||
|
||||
if (node.nodeType === Node.TEXT_NODE && offset === 0) {
|
||||
// Check previous sibling
|
||||
// Check previous sibling using type guard
|
||||
const prevSibling = node.previousSibling;
|
||||
if (prevSibling && (prevSibling as Element).hasAttribute?.(CHIP_DATA_ATTR)) {
|
||||
if (isChipElement(prevSibling)) {
|
||||
e.preventDefault();
|
||||
const chipId = Number((prevSibling as Element).getAttribute(CHIP_ID_ATTR));
|
||||
prevSibling.parentNode?.removeChild(prevSibling);
|
||||
setMentionedDocs((prev) => {
|
||||
const next = new Map(prev);
|
||||
next.delete(chipId);
|
||||
return next;
|
||||
});
|
||||
// Notify parent that a document was removed
|
||||
onDocumentRemove?.(chipId);
|
||||
const chipId = getChipId(prevSibling);
|
||||
if (chipId !== null) {
|
||||
prevSibling.remove();
|
||||
setMentionedDocs((prev) => {
|
||||
const next = new Map(prev);
|
||||
next.delete(chipId);
|
||||
return next;
|
||||
});
|
||||
// Notify parent that a document was removed
|
||||
onDocumentRemove?.(chipId);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Check if we're about to delete @ at the start
|
||||
|
|
@ -414,19 +443,21 @@ export const InlineMentionEditor = forwardRef<InlineMentionEditorRef, InlineMent
|
|||
}, 0);
|
||||
}
|
||||
} else if (node.nodeType === Node.ELEMENT_NODE && offset > 0) {
|
||||
// Check if previous child is a chip
|
||||
// Check if previous child is a chip using type guard
|
||||
const prevChild = (node as Element).childNodes[offset - 1];
|
||||
if (prevChild && (prevChild as Element).hasAttribute?.(CHIP_DATA_ATTR)) {
|
||||
if (isChipElement(prevChild)) {
|
||||
e.preventDefault();
|
||||
const chipId = Number((prevChild as Element).getAttribute(CHIP_ID_ATTR));
|
||||
prevChild.parentNode?.removeChild(prevChild);
|
||||
setMentionedDocs((prev) => {
|
||||
const next = new Map(prev);
|
||||
next.delete(chipId);
|
||||
return next;
|
||||
});
|
||||
// Notify parent that a document was removed
|
||||
onDocumentRemove?.(chipId);
|
||||
const chipId = getChipId(prevChild);
|
||||
if (chipId !== null) {
|
||||
prevChild.remove();
|
||||
setMentionedDocs((prev) => {
|
||||
const next = new Map(prev);
|
||||
next.delete(chipId);
|
||||
return next;
|
||||
});
|
||||
// Notify parent that a document was removed
|
||||
onDocumentRemove?.(chipId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,9 +72,9 @@ import { MarkdownText } from "@/components/assistant-ui/markdown-text";
|
|||
import { ToolFallback } from "@/components/assistant-ui/tool-fallback";
|
||||
import { TooltipIconButton } from "@/components/assistant-ui/tooltip-icon-button";
|
||||
import {
|
||||
DocumentsDataTable,
|
||||
type DocumentsDataTableRef,
|
||||
} from "@/components/new-chat/DocumentsDataTable";
|
||||
DocumentMentionPicker,
|
||||
type DocumentMentionPickerRef,
|
||||
} from "@/components/new-chat/DocumentMentionPicker";
|
||||
import {
|
||||
ChainOfThought,
|
||||
ChainOfThoughtContent,
|
||||
|
|
@ -404,7 +404,7 @@ const Composer: FC = () => {
|
|||
const [mentionQuery, setMentionQuery] = useState("");
|
||||
const editorRef = useRef<InlineMentionEditorRef>(null);
|
||||
const editorContainerRef = useRef<HTMLDivElement>(null);
|
||||
const documentPickerRef = useRef<DocumentsDataTableRef>(null);
|
||||
const documentPickerRef = useRef<DocumentMentionPickerRef>(null);
|
||||
const { search_space_id } = useParams();
|
||||
const setMentionedDocumentIds = useSetAtom(mentionedDocumentIdsAtom);
|
||||
const composerRuntime = useComposerRuntime();
|
||||
|
|
@ -598,7 +598,7 @@ const Composer: FC = () => {
|
|||
: "50%",
|
||||
}}
|
||||
>
|
||||
<DocumentsDataTable
|
||||
<DocumentMentionPicker
|
||||
ref={documentPickerRef}
|
||||
searchSpaceId={Number(search_space_id)}
|
||||
onSelectionChange={handleDocumentsMention}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue