Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 3.8k
fix(resource): prevent permission-gated breadcrumb items from flashing on load#4732
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
f54b904da54dcff5d22b9b96b7e7File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -219,6 +219,36 @@ export const ResourceTable = memo(function ResourceTable({ | ||
| direction: 'desc', | ||
| }) | ||
| const [contextMenuRowId, setContextMenuRowId] = useState<string | null>(null) | ||
| const wrappedOnRowContextMenu = useCallback( | ||
| (e: React.MouseEvent, rowId: string) => { | ||
| setContextMenuRowId(rowId) | ||
| onRowContextMenu?.(e, rowId) | ||
| }, | ||
| [onRowContextMenu] | ||
| ) | ||
| useEffect(() => { | ||
| if (!contextMenuRowId) return | ||
| const clear = () => setContextMenuRowId(null) | ||
| const handleKeyDown = (e: KeyboardEvent) => { | ||
| if (e.key === 'Escape') { | ||
| document.removeEventListener('keydown', handleKeyDown) | ||
| clear() | ||
| } | ||
| } | ||
| const timeoutId = setTimeout(() => { | ||
| document.addEventListener('pointerdown', clear, { once: true }) | ||
| document.addEventListener('keydown', handleKeyDown) | ||
| }, 0) | ||
| return () => { | ||
| clearTimeout(timeoutId) | ||
| document.removeEventListener('pointerdown', clear) | ||
| document.removeEventListener('keydown', handleKeyDown) | ||
| } | ||
| }, [contextMenuRowId]) | ||
waleedlatif1 marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. waleedlatif1 marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| const handleSort = useCallback((column: string, direction: 'asc' | 'desc') => { | ||
| setInternalSort({ column, direction }) | ||
| }, []) | ||
| @@ -343,7 +373,8 @@ export const ResourceTable = memo(function ResourceTable({ | ||
| rowDragDrop={rowDragDrop} | ||
| onRowClick={onRowClick} | ||
| onRowHover={onRowHover} | ||
| onRowContextMenu={onRowContextMenu} | ||
| onRowContextMenu={onRowContextMenu ? wrappedOnRowContextMenu : undefined} | ||
| isContextMenuTarget={contextMenuRowId === row.id} | ||
| hasCheckbox={hasCheckbox} | ||
| /> | ||
| ))} | ||
| @@ -403,17 +434,18 @@ const Pagination = memo(function Pagination({ | ||
| } | ||
| if (page < 1 || page > totalPages) return null | ||
| return ( | ||
| <button | ||
| <Button | ||
| key={page} | ||
| type='button' | ||
| variant='ghost' | ||
| onClick={() => onPageChange(page)} | ||
| className={cn( | ||
| 'font-medium text-sm transition-colors hover-hover:text-[var(--text-body)]', | ||
| 'h-auto p-0 font-medium text-sm transition-colors hover-hover:bg-transparent hover-hover:text-[var(--text-body)]', | ||
| page === currentPage ? 'text-[var(--text-body)]' : 'text-[var(--text-secondary)]' | ||
| )} | ||
| > | ||
| {page} | ||
| </button> | ||
| </Button> | ||
| ) | ||
| })} | ||
| </div> | ||
| @@ -460,6 +492,7 @@ interface DataRowProps { | ||
| onRowClick?: (rowId: string) => void | ||
| onRowHover?: (rowId: string) => void | ||
| onRowContextMenu?: (e: React.MouseEvent, rowId: string) => void | ||
| isContextMenuTarget?: boolean | ||
| hasCheckbox: boolean | ||
| } | ||
| @@ -472,6 +505,7 @@ const DataRow = memo(function DataRow({ | ||
| onRowClick, | ||
| onRowHover, | ||
| onRowContextMenu, | ||
| isContextMenuTarget, | ||
| hasCheckbox, | ||
| }: DataRowProps) { | ||
| const isSelected = selectable?.selectedIds.has(row.id) ?? false | ||
| @@ -554,7 +588,7 @@ const DataRow = memo(function DataRow({ | ||
| onRowClick && 'cursor-pointer', | ||
| isDraggable && 'cursor-grab active:cursor-grabbing', | ||
| isDropTarget && 'data-[drop-target=true]:outline-offset-[-1px]', | ||
| (selectedRowId === row.id || isSelected) && 'bg-[var(--surface-3)]', | ||
| (selectedRowId === row.id || isSelected || isContextMenuTarget) && 'bg-[var(--surface-3)]', | ||
| isActiveDropTarget && 'bg-[var(--surface-4)] outline outline-1 outline-[var(--accent)]', | ||
| (isDragging || (isAnyDragActive && isSelected && !isActiveDropTarget)) && 'opacity-50' | ||
| )} | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -814,24 +814,42 @@ export function KnowledgeBase({ | ||
| } | ||
| : undefined, | ||
| dropdownItems: [ | ||
| ...(userPermissions.canEdit | ||
| ...(userPermissions.canEdit || userPermissions.isLoading | ||
| ? [ | ||
| { | ||
| label: 'Rename', | ||
| icon: Pencil, | ||
| disabled: !userPermissions.canEdit, | ||
| onClick: () => kbRename.startRename(id, knowledgeBaseName), | ||
| }, | ||
| { label: 'Tags', icon: Tag, onClick: () => setShowTagsModal(true) }, | ||
| { label: 'Delete', icon: Trash, onClick: () => setShowDeleteDialog(true) }, | ||
| { | ||
| label: 'Tags', | ||
| icon: Tag, | ||
| disabled: !userPermissions.canEdit, | ||
| onClick: () => setShowTagsModal(true), | ||
| }, | ||
| { | ||
| label: 'Delete', | ||
| icon: Trash, | ||
| disabled: !userPermissions.canEdit, | ||
| onClick: () => setShowDeleteDialog(true), | ||
| }, | ||
| ] | ||
| : []), | ||
waleedlatif1 marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| ], | ||
| }, | ||
| ] | ||
| const headerActions: HeaderAction[] = [ | ||
| ...(userPermissions.canEdit | ||
| ? [{ label: 'New connector', icon: Plus, onClick: () => setShowAddConnectorModal(true) }] | ||
| ...(userPermissions.canEdit || userPermissions.isLoading | ||
| ? [ | ||
| { | ||
| label: 'New connector', | ||
| icon: Plus, | ||
| disabled: !userPermissions.canEdit, | ||
| onClick: () => setShowAddConnectorModal(true), | ||
| }, | ||
| ] | ||
| : []), | ||
| ] | ||
| @@ -886,18 +904,18 @@ export function KnowledgeBase({ | ||
| /> | ||
| </div> | ||
| {enabledFilter.length > 0 && ( | ||
| <button | ||
| type='button' | ||
| <Button | ||
| variant='ghost' | ||
| onClick={() => { | ||
| setEnabledFilter([]) | ||
| setCurrentPage(1) | ||
| setSelectedDocuments(new Set()) | ||
| setIsSelectAllMode(false) | ||
| }} | ||
| className='flex h-[32px] w-full items-center justify-center rounded-md text-[var(--text-secondary)] text-caption transition-colors hover-hover:bg-[var(--surface-active)]' | ||
| className='h-[32px] w-full text-[var(--text-secondary)] text-caption' | ||
| > | ||
| Clear status filter | ||
| </button> | ||
| </Button> | ||
| )} | ||
| <TagFilterSection | ||
| tagDefinitions={tagDefinitions} | ||
| @@ -1322,7 +1340,7 @@ export function KnowledgeBase({ | ||
| )} | ||
| <Modal open={showConnectorsModal} onOpenChange={setShowConnectorsModal}> | ||
| <ModalContent size='lg'> | ||
| <ModalContent size='md'> | ||
| <ModalHeader>Connected Sources</ModalHeader> | ||
| <ModalDescription className='sr-only'> | ||
| Manage connected data sources for this knowledge base | ||
| @@ -1535,13 +1553,13 @@ function TagFilterSection({ tagDefinitions, entries, onChange }: TagFilterSectio | ||
| > | ||
| <div className='flex items-center justify-between'> | ||
| <Label className='text-[var(--text-muted)] text-xs'>Tag</Label> | ||
| <button | ||
| type='button' | ||
| <Button | ||
| variant='ghost' | ||
| className='size-5 p-0 text-[var(--text-muted)] hover-hover:text-[var(--text-error)]' | ||
| onClick={() => removeFilter(entry.id)} | ||
| className='text-[var(--text-muted)] transition-colors hover-hover:text-[var(--text-error)]' | ||
| > | ||
| <X className='size-3' /> | ||
| </button> | ||
| </Button> | ||
| </div> | ||
| <Combobox | ||
| options={tagOptions} | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.