From f0c044859c743d0c9654ab9a40ca0663ed2de768 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Wed, 8 Jul 2026 10:45:25 -0700 Subject: [PATCH 1/3] improvement(knowledge): open document tags from row context menu The document row context menu had a Tags entry that only navigated to the document detail page, requiring another click through the breadcrumb dropdown to actually edit tags. It now opens the tag editor directly, and shows even when the document has no tags yet so a first tag can be added. --- .../[workspaceId]/knowledge/[id]/base.tsx | 37 ++++++++++++------- .../document-context-menu.tsx | 8 ++-- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/base.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/base.tsx index f3c673c8325..8853c28c955 100644 --- a/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/base.tsx +++ b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/base.tsx @@ -49,6 +49,7 @@ import type { SortConfig, } from '@/app/workspace/[workspaceId]/components' import { FloatingOverflowText, Resource } from '@/app/workspace/[workspaceId]/components' +import { DocumentTagsModal } from '@/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components' import { ActionBar, AddConnectorModal, @@ -342,6 +343,8 @@ export function KnowledgeBase({ const [contextMenuDocument, setContextMenuDocument] = useState(null) const [showRenameModal, setShowRenameModal] = useState(false) const [documentToRename, setDocumentToRename] = useState(null) + const [showDocumentTagsModal, setShowDocumentTagsModal] = useState(false) + const [documentForTags, setDocumentForTags] = useState(null) const showAddConnectorModal = addConnectorType != null const updateAddConnectorParam = useCallback( (value: string | null) => { @@ -531,6 +534,14 @@ export function KnowledgeBase({ setShowRenameModal(true) } + /** + * Opens the document tags modal + */ + const handleViewDocumentTags = (doc: DocumentData) => { + setDocumentForTags(doc) + setShowDocumentTagsModal(true) + } + /** * Saves the renamed document */ @@ -1345,6 +1356,17 @@ export function KnowledgeBase({ /> )} + {documentForTags && ( + updateDocument(documentForTags.id, updates)} + /> + )} + 0 - : false - } selectedCount={selectedDocuments.size} enabledCount={enabledCount} disabledCount={disabledCount} @@ -1414,15 +1431,7 @@ export function KnowledgeBase({ } onViewTags={ contextMenuDocument && selectedDocuments.size === 1 - ? () => { - const urlParams = new URLSearchParams({ - kbName: knowledgeBaseName, - docName: contextMenuDocument.filename || 'Document', - }) - router.push( - `/workspace/${workspaceId}/knowledge/${id}/${contextMenuDocument.id}?${urlParams.toString()}` - ) - } + ? () => handleViewDocumentTags(contextMenuDocument) : undefined } onDelete={ diff --git a/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/components/document-context-menu/document-context-menu.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/components/document-context-menu/document-context-menu.tsx index bb751cf2502..7050da64725 100644 --- a/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/components/document-context-menu/document-context-menu.tsx +++ b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/components/document-context-menu/document-context-menu.tsx @@ -22,7 +22,6 @@ interface DocumentContextMenuProps { onAddDocument?: () => void isDocumentEnabled?: boolean hasDocument: boolean - hasTags?: boolean disableRename?: boolean disableToggleEnabled?: boolean disableDelete?: boolean @@ -50,7 +49,6 @@ export function DocumentContextMenu({ onAddDocument, isDocumentEnabled = true, hasDocument, - hasTags = false, disableRename = false, disableToggleEnabled = false, disableDelete = false, @@ -70,7 +68,7 @@ export function DocumentContextMenu({ } const hasNavigationSection = !isMultiSelect && (!!onOpenInNewTab || !!onOpenSource) - const hasEditSection = !isMultiSelect && (!!onRename || (hasTags && !!onViewTags)) + const hasEditSection = !isMultiSelect && (!!onRename || !!onViewTags) const hasStateSection = !!onToggleEnabled const hasDestructiveSection = !!onDelete @@ -121,10 +119,10 @@ export function DocumentContextMenu({ Rename )} - {!isMultiSelect && hasTags && onViewTags && ( + {!isMultiSelect && onViewTags && ( - View tags + Tags )} {hasEditSection && (hasStateSection || hasDestructiveSection) && ( From af39dee9d90e2acf783f5ccabe2848236259c18c Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Wed, 8 Jul 2026 10:48:54 -0700 Subject: [PATCH 2/3] fix(knowledge): gate document tags menu item on edit permission Matches the existing disableRename/disableDelete/disableToggleEnabled pattern; the document detail breadcrumb already hides its Tags entry for non-editors the same way. --- apps/sim/app/workspace/[workspaceId]/knowledge/[id]/base.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/base.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/base.tsx index 8853c28c955..68198ed677d 100644 --- a/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/base.tsx +++ b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/base.tsx @@ -1430,7 +1430,7 @@ export function KnowledgeBase({ : undefined } onViewTags={ - contextMenuDocument && selectedDocuments.size === 1 + contextMenuDocument && selectedDocuments.size === 1 && userPermissions.canEdit ? () => handleViewDocumentTags(contextMenuDocument) : undefined } From d5ccfe219daab33d455891d7bd1348cdf501a48e Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Wed, 8 Jul 2026 10:55:10 -0700 Subject: [PATCH 3/3] fix(knowledge): derive tags modal document data from live list cache The modal was fed a frozen document snapshot taken at right-click time. After a save, the mutation only invalidates the single-document and KB-detail queries (not the documents list query), so the modal's own sync effect rebuilt tags from the stale snapshot and could revert or drop the just-saved value. Track only the document id and look it up from the same documents array updateDocument() patches, so the modal always sees current data. --- .../workspace/[workspaceId]/knowledge/[id]/base.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/base.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/base.tsx index 68198ed677d..2d6863b3250 100644 --- a/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/base.tsx +++ b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/base.tsx @@ -344,7 +344,7 @@ export function KnowledgeBase({ const [showRenameModal, setShowRenameModal] = useState(false) const [documentToRename, setDocumentToRename] = useState(null) const [showDocumentTagsModal, setShowDocumentTagsModal] = useState(false) - const [documentForTags, setDocumentForTags] = useState(null) + const [documentForTagsId, setDocumentForTagsId] = useState(null) const showAddConnectorModal = addConnectorType != null const updateAddConnectorParam = useCallback( (value: string | null) => { @@ -538,7 +538,7 @@ export function KnowledgeBase({ * Opens the document tags modal */ const handleViewDocumentTags = (doc: DocumentData) => { - setDocumentForTags(doc) + setDocumentForTagsId(doc.id) setShowDocumentTagsModal(true) } @@ -1356,14 +1356,14 @@ export function KnowledgeBase({ /> )} - {documentForTags && ( + {documentForTagsId && ( updateDocument(documentForTags.id, updates)} + documentId={documentForTagsId} + documentData={documents.find((doc) => doc.id === documentForTagsId) ?? null} + onDocumentUpdate={(updates) => updateDocument(documentForTagsId, updates)} /> )}