search cleanup

This commit is contained in:
2025-11-19 01:25:56 +01:00
parent 6923a68837
commit e1b47ed153
9 changed files with 175 additions and 156 deletions
-1
View File
@@ -28,7 +28,6 @@ const AppLayout: React.FC = () => {
onDocumentsSortFieldChange: documentsPreferences.handleDocumentsSortFieldChange, onDocumentsSortFieldChange: documentsPreferences.handleDocumentsSortFieldChange,
onDocumentsSortDirectionToggle: documentsPreferences.handleDocumentsSortDirectionToggle, onDocumentsSortDirectionToggle: documentsPreferences.handleDocumentsSortDirectionToggle,
searchIncludeDescendants: documentsPreferences.searchIncludeDescendants, searchIncludeDescendants: documentsPreferences.searchIncludeDescendants,
onToggleSearchIncludeDescendants: documentsPreferences.toggleSearchIncludeDescendants,
onSetSearchIncludeDescendants: documentsPreferences.setSearchIncludeDescendants, onSetSearchIncludeDescendants: documentsPreferences.setSearchIncludeDescendants,
sortRefreshReadyRef: documentsPreferences.sortRefreshReadyRef, sortRefreshReadyRef: documentsPreferences.sortRefreshReadyRef,
}); });
+27 -12
View File
@@ -2,6 +2,10 @@ import React, { useCallback, useEffect, useMemo } from 'react';
import type { ReactNode } from 'react'; import type { ReactNode } from 'react';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { useAppShell } from '../appShellContext'; import { useAppShell } from '../appShellContext';
import {
DocumentsFilterProvider,
} from '../documents/context/DocumentsFilterContext';
import type { DocumentsFilterValue } from '../documents/context/DocumentsFilterContext';
import { useWorkspaceSurface } from './useWorkspaceSurface'; import { useWorkspaceSurface } from './useWorkspaceSurface';
import { DocumentsHeaderBreadcrumb } from '../documents/panel/DocumentsPanelHeader'; import { DocumentsHeaderBreadcrumb } from '../documents/panel/DocumentsPanelHeader';
import { SidebarProvider, useSidebarContext } from '../sidebar/SidebarContext'; import { SidebarProvider, useSidebarContext } from '../sidebar/SidebarContext';
@@ -43,6 +47,7 @@ interface DocumentsRouteAppShell {
ensureAssetUrl?: EnsureAssetUrl; ensureAssetUrl?: EnsureAssetUrl;
getDocumentAsset?: GetDocumentAsset; getDocumentAsset?: GetDocumentAsset;
notifyApiError?: NotifyApiError; notifyApiError?: NotifyApiError;
documentsFilter: DocumentsFilterValue;
} }
const DocumentsRouteContent: React.FC = () => { const DocumentsRouteContent: React.FC = () => {
@@ -62,7 +67,8 @@ const DocumentsRouteContent: React.FC = () => {
ensureAssetUrl, ensureAssetUrl,
getDocumentAsset, getDocumentAsset,
notifyApiError, notifyApiError,
} = useAppShell() as DocumentsRouteAppShell; documentsFilter,
} = useAppShell() as unknown as DocumentsRouteAppShell;
const navigate = useNavigate(); const navigate = useNavigate();
const { collapsed: sidebarCollapsed } = useSidebarContext(); const { collapsed: sidebarCollapsed } = useSidebarContext();
const { const {
@@ -124,26 +130,35 @@ const DocumentsRouteContent: React.FC = () => {
}; };
}, []); }, []);
if (!surface) { const renderSurface = () => {
if (!surface) {
return (
<main className={`documents-main${sidebarHidden ? ' documents-main--sidebar-hidden' : ''}`}>
{!sidebarHidden ? <Sidebar {...sidebarPropsWithActions} /> : null}
<div className="main-content">
<div className="main-content__body" />
</div>
</main>
);
}
const surfaceDetail = (surface as { detail?: ReactNode }).detail || null;
return ( return (
<main className={`documents-main${sidebarHidden ? ' documents-main--sidebar-hidden' : ''}`}> <main className={`documents-main${sidebarHidden ? ' documents-main--sidebar-hidden' : ''}`}>
{!sidebarHidden ? <Sidebar {...sidebarPropsWithActions} /> : null} {!sidebarHidden ? <Sidebar {...sidebarPropsWithActions} /> : null}
<div className="main-content"> <div className="main-content">
<div className="main-content__body" /> <div className="main-content__body">{surface.content}</div>
{surfaceDetail}
</div> </div>
</main> </main>
); );
} };
const surfaceDetail = (surface as { detail?: ReactNode }).detail || null; const content = renderSurface();
return ( return (
<main className={`documents-main${sidebarHidden ? ' documents-main--sidebar-hidden' : ''}`}> <DocumentsFilterProvider value={documentsFilter}>
{!sidebarHidden ? <Sidebar {...sidebarPropsWithActions} /> : null} {content}
<div className="main-content"> </DocumentsFilterProvider>
<div className="main-content__body">{surface.content}</div>
{surfaceDetail}
</div>
</main>
); );
}; };
+49
View File
@@ -47,6 +47,21 @@ interface UseDocumentsSearchResult {
clearFilters: () => void; clearFilters: () => void;
handleSearchChange: (value: string) => void; handleSearchChange: (value: string) => void;
handleSearchSubmit: () => void; handleSearchSubmit: () => void;
documentsFilterValue: {
query: string;
searchResults: DocumentLike[] | null;
searchLoading: boolean;
includeDescendants: boolean;
activeTagIds: Identifier[];
activeCorrespondentIds: Identifier[];
isActive: boolean;
setQuery: (value: string) => void;
submit: () => void;
clear: () => void;
toggleTag: (tagId: Identifier) => void;
toggleCorrespondent: (correspondentId?: Identifier | null) => void;
toggleIncludeDescendants: () => void;
};
} }
const useDocumentsSearch = ({ const useDocumentsSearch = ({
@@ -124,6 +139,39 @@ const useDocumentsSearch = ({
} }
}, [navigate, selectedFolder, isDocumentsRoute, locationPathname]); }, [navigate, selectedFolder, isDocumentsRoute, locationPathname]);
const documentsFilterValue = useMemo(
() => ({
query: searchQuery,
searchResults,
searchLoading,
includeDescendants: Boolean(searchIncludeDescendants),
activeTagIds: activeTagFilters,
activeCorrespondentIds: activeCorrespondentFilters,
isActive: isFilterActive,
setQuery: handleSearchChange,
submit: handleSearchSubmit,
clear: clearFilters,
toggleTag: toggleTagFilter,
toggleCorrespondent: toggleCorrespondentFilter,
toggleIncludeDescendants: () => setSearchIncludeDescendants(!searchIncludeDescendants),
}),
[
searchQuery,
searchResults,
searchLoading,
searchIncludeDescendants,
activeTagFilters,
activeCorrespondentFilters,
isFilterActive,
handleSearchChange,
handleSearchSubmit,
clearFilters,
toggleTagFilter,
toggleCorrespondentFilter,
setSearchIncludeDescendants,
],
);
useEffect(() => { useEffect(() => {
if (!token) return undefined; if (!token) return undefined;
@@ -237,6 +285,7 @@ const useDocumentsSearch = ({
clearFilters, clearFilters,
handleSearchChange, handleSearchChange,
handleSearchSubmit, handleSearchSubmit,
documentsFilterValue,
}; };
}; };
@@ -0,0 +1,40 @@
import React, { createContext, useContext } from 'react';
type Identifier = string | number;
export interface DocumentsFilterValue {
query: string;
searchResults: Array<Record<string, unknown>> | null;
searchLoading: boolean;
includeDescendants: boolean;
activeTagIds: Identifier[];
activeCorrespondentIds: Identifier[];
isActive: boolean;
setQuery: (value: string) => void;
submit: () => void;
clear: () => void;
toggleTag: (tagId: Identifier) => void;
toggleCorrespondent: (correspondentId?: Identifier | null) => void;
toggleIncludeDescendants: () => void;
}
const DocumentsFilterContext = createContext<DocumentsFilterValue | null>(null);
interface DocumentsFilterProviderProps {
value: DocumentsFilterValue;
children: React.ReactNode;
}
export const DocumentsFilterProvider: React.FC<DocumentsFilterProviderProps> = ({ value, children }) => (
<DocumentsFilterContext.Provider value={value}>{children}</DocumentsFilterContext.Provider>
);
export const useDocumentsFilter = (): DocumentsFilterValue => {
const context = useContext(DocumentsFilterContext);
if (!context) {
throw new Error('useDocumentsFilter must be used within a DocumentsFilterProvider');
}
return context;
};
export default DocumentsFilterContext;
@@ -28,7 +28,6 @@ export interface UseDocumentsPanelPropsArgs {
currentSubfolders?: unknown[]; currentSubfolders?: unknown[];
documents?: unknown[]; documents?: unknown[];
searchResults?: unknown[] | null; searchResults?: unknown[] | null;
isFilterActive?: boolean;
folderClickHandlers: FolderClickHandlers; folderClickHandlers: FolderClickHandlers;
selectFolder?: (...args: unknown[]) => void; selectFolder?: (...args: unknown[]) => void;
handleFolderDragStart?: (...args: unknown[]) => void; handleFolderDragStart?: (...args: unknown[]) => void;
@@ -46,16 +45,12 @@ export interface UseDocumentsPanelPropsArgs {
activeCorrespondentFilters?: Identifier[]; activeCorrespondentFilters?: Identifier[];
ensureAssetUrl?: (...args: unknown[]) => void; ensureAssetUrl?: (...args: unknown[]) => void;
getDocumentAsset?: (...args: unknown[]) => unknown; getDocumentAsset?: (...args: unknown[]) => unknown;
toggleTagFilter?: (...args: unknown[]) => void;
toggleCorrespondentFilter?: (...args: unknown[]) => void;
handleDocumentTagDrop?: (...args: unknown[]) => void; handleDocumentTagDrop?: (...args: unknown[]) => void;
documentsViewMode?: string; documentsViewMode?: string;
documentsSortField?: string; documentsSortField?: string;
documentsSortDirection?: string; documentsSortDirection?: string;
handleDocumentsSortFieldChange?: (field: string) => void; handleDocumentsSortFieldChange?: (field: string) => void;
handleDocumentsSortDirectionToggle?: () => void; handleDocumentsSortDirectionToggle?: () => void;
searchIncludeDescendants?: boolean;
toggleSearchIncludeDescendants?: () => void;
handleDocumentsViewModeChange?: (mode: string) => void; handleDocumentsViewModeChange?: (mode: string) => void;
clearDocumentSelection?: () => void; clearDocumentSelection?: () => void;
handleDeleteSelection?: () => void; handleDeleteSelection?: () => void;
@@ -86,7 +81,6 @@ const useDocumentsPanelProps = (props: UseDocumentsPanelPropsArgs) => {
currentSubfolders, currentSubfolders,
documents, documents,
searchResults, searchResults,
isFilterActive,
folderClickHandlers, folderClickHandlers,
selectFolder, selectFolder,
handleFolderDragStart, handleFolderDragStart,
@@ -104,16 +98,12 @@ const useDocumentsPanelProps = (props: UseDocumentsPanelPropsArgs) => {
activeCorrespondentFilters, activeCorrespondentFilters,
ensureAssetUrl, ensureAssetUrl,
getDocumentAsset, getDocumentAsset,
toggleTagFilter,
toggleCorrespondentFilter,
handleDocumentTagDrop, handleDocumentTagDrop,
documentsViewMode, documentsViewMode,
documentsSortField, documentsSortField,
documentsSortDirection, documentsSortDirection,
handleDocumentsSortFieldChange, handleDocumentsSortFieldChange,
handleDocumentsSortDirectionToggle, handleDocumentsSortDirectionToggle,
searchIncludeDescendants,
toggleSearchIncludeDescendants,
handleDocumentsViewModeChange, handleDocumentsViewModeChange,
handleDeleteSelection, handleDeleteSelection,
handleEntryPointerCore, handleEntryPointerCore,
@@ -141,7 +131,6 @@ const useDocumentsPanelProps = (props: UseDocumentsPanelPropsArgs) => {
subfolders: currentSubfolders, subfolders: currentSubfolders,
documents, documents,
searchResults, searchResults,
isFilterActive,
onFolderSelect: selectFolder, onFolderSelect: selectFolder,
onFolderDrop: folderClickHandlers.onDrop, onFolderDrop: folderClickHandlers.onDrop,
onFolderDragOver: folderClickHandlers.onDragOver, onFolderDragOver: folderClickHandlers.onDragOver,
@@ -161,16 +150,12 @@ const useDocumentsPanelProps = (props: UseDocumentsPanelPropsArgs) => {
activeCorrespondentIds: activeCorrespondentFilters, activeCorrespondentIds: activeCorrespondentFilters,
ensureAssetUrl, ensureAssetUrl,
getDocumentAsset, getDocumentAsset,
onTagClick: toggleTagFilter,
onCorrespondentClick: toggleCorrespondentFilter,
onDocumentTagDrop: handleDocumentTagDrop, onDocumentTagDrop: handleDocumentTagDrop,
viewMode: documentsViewMode, viewMode: documentsViewMode,
sortField: documentsSortField, sortField: documentsSortField,
sortDirection: documentsSortDirection, sortDirection: documentsSortDirection,
onSortFieldChange: handleDocumentsSortFieldChange, onSortFieldChange: handleDocumentsSortFieldChange,
onSortDirectionToggle: handleDocumentsSortDirectionToggle, onSortDirectionToggle: handleDocumentsSortDirectionToggle,
searchIncludeDescendants,
onToggleSearchIncludeDescendants: toggleSearchIncludeDescendants,
onViewModeChange: handleDocumentsViewModeChange, onViewModeChange: handleDocumentsViewModeChange,
onDeleteSelection: handleDeleteSelection, onDeleteSelection: handleDeleteSelection,
onEntryPointer: handleEntryPointerCore, onEntryPointer: handleEntryPointerCore,
@@ -222,19 +207,14 @@ const useDocumentsPanelProps = (props: UseDocumentsPanelPropsArgs) => {
handleFolderDragStart, handleFolderDragStart,
handleFolderRename, handleFolderRename,
inspectDocument, inspectDocument,
isFilterActive,
moveDocumentsToFolder, moveDocumentsToFolder,
openDocumentPreview, openDocumentPreview,
refreshCurrentFolder, refreshCurrentFolder,
searchIncludeDescendants,
searchLoading, searchLoading,
searchResults, searchResults,
selectFolder, selectFolder,
tagLookupById, tagLookupById,
tags, tags,
toggleCorrespondentFilter,
toggleSearchIncludeDescendants,
toggleTagFilter,
ensureAssetUrl, ensureAssetUrl,
getDocumentAsset, getDocumentAsset,
folderOptions, folderOptions,
+16 -13
View File
@@ -17,6 +17,7 @@ import DocumentsPanelHeader, {
} from './DocumentsPanelHeader'; } from './DocumentsPanelHeader';
import { SelectionFloatingPanel } from '../SelectionFloatingActions'; import { SelectionFloatingPanel } from '../SelectionFloatingActions';
import { createDocumentsTableHeaderActions } from './DocumentsToolbar'; import { createDocumentsTableHeaderActions } from './DocumentsToolbar';
import { useDocumentsFilter } from '../context/DocumentsFilterContext';
const DEFAULT_GRID_ICON_SIZE = 144; const DEFAULT_GRID_ICON_SIZE = 144;
@@ -47,7 +48,6 @@ const DocumentsPanelInner: React.FC<DocumentsPanelInnerProps> = ({
subfolders, subfolders,
documents, documents,
searchResults, searchResults,
isFilterActive = false,
onFolderSelect, onFolderSelect,
onFolderDrop, onFolderDrop,
onFolderDragOver, onFolderDragOver,
@@ -66,8 +66,6 @@ const DocumentsPanelInner: React.FC<DocumentsPanelInnerProps> = ({
activeCorrespondentIds = [], activeCorrespondentIds = [],
ensureAssetUrl = null, ensureAssetUrl = null,
getDocumentAsset = defaultGetDocumentAsset, getDocumentAsset = defaultGetDocumentAsset,
onTagClick,
onCorrespondentClick,
isSearchLoading = false, isSearchLoading = false,
onDocumentTagDrop, onDocumentTagDrop,
viewMode = 'list', viewMode = 'list',
@@ -80,8 +78,6 @@ const DocumentsPanelInner: React.FC<DocumentsPanelInnerProps> = ({
sortDirection, sortDirection,
onSortFieldChange, onSortFieldChange,
onSortDirectionToggle, onSortDirectionToggle,
searchIncludeDescendants,
onToggleSearchIncludeDescendants,
onDeleteSelection, onDeleteSelection,
documentLookup, documentLookup,
tags, tags,
@@ -101,6 +97,13 @@ const DocumentsPanelInner: React.FC<DocumentsPanelInnerProps> = ({
handleEntrySelection, handleEntrySelection,
clearSelection, clearSelection,
} = useWorkspaceSelectionContext(); } = useWorkspaceSelectionContext();
const {
isActive: isFilterActive,
includeDescendants,
toggleIncludeDescendants,
toggleTag: toggleTagFilter,
toggleCorrespondent: toggleCorrespondentFilter,
} = useDocumentsFilter();
const showingSearchResults = searchResults !== null; const showingSearchResults = searchResults !== null;
const rows = showingSearchResults ? searchResults : documents; const rows = showingSearchResults ? searchResults : documents;
const documentLinkMap = documentLinks instanceof Map ? documentLinks : null; const documentLinkMap = documentLinks instanceof Map ? documentLinks : null;
@@ -121,8 +124,8 @@ const DocumentsPanelInner: React.FC<DocumentsPanelInnerProps> = ({
sortDirection, sortDirection,
onSortDirectionToggle, onSortDirectionToggle,
isFilterActive, isFilterActive,
includeDescendants: searchIncludeDescendants, includeDescendants,
onToggleIncludeDescendants: onToggleSearchIncludeDescendants, onToggleIncludeDescendants: toggleIncludeDescendants,
}), }),
[ [
viewMode, viewMode,
@@ -133,8 +136,8 @@ const DocumentsPanelInner: React.FC<DocumentsPanelInnerProps> = ({
sortDirection, sortDirection,
onSortDirectionToggle, onSortDirectionToggle,
isFilterActive, isFilterActive,
searchIncludeDescendants, includeDescendants,
onToggleSearchIncludeDescendants, toggleIncludeDescendants,
], ],
); );
const floatingActions = useMemo(() => ( const floatingActions = useMemo(() => (
@@ -740,9 +743,9 @@ const DocumentsPanelInner: React.FC<DocumentsPanelInnerProps> = ({
getDocumentAsset={getDocumentAsset} getDocumentAsset={getDocumentAsset}
gridIconSize={gridIconSize} gridIconSize={gridIconSize}
tagLookupById={tagLookupById} tagLookupById={tagLookupById}
onTagClick={onTagClick} onTagClick={toggleTagFilter}
scrollRef={scrollRef} scrollRef={scrollRef}
onCorrespondentClick={onCorrespondentClick} onCorrespondentClick={toggleCorrespondentFilter}
activeCorrespondentIdSet={activeCorrespondentIdSet} activeCorrespondentIdSet={activeCorrespondentIdSet}
onDocumentRename={onDocumentRename} onDocumentRename={onDocumentRename}
onFolderRename={onFolderRename} onFolderRename={onFolderRename}
@@ -775,8 +778,8 @@ const DocumentsPanelInner: React.FC<DocumentsPanelInnerProps> = ({
onDocumentTagDrop={handleDocumentTagDrop} onDocumentTagDrop={handleDocumentTagDrop}
onDocumentRename={onDocumentRename} onDocumentRename={onDocumentRename}
tagLookupById={tagLookupById} tagLookupById={tagLookupById}
onTagClick={onTagClick} onTagClick={toggleTagFilter}
onCorrespondentClick={onCorrespondentClick} onCorrespondentClick={toggleCorrespondentFilter}
activeCorrespondentIdSet={activeCorrespondentIdSet} activeCorrespondentIdSet={activeCorrespondentIdSet}
scrollRef={scrollRef} scrollRef={scrollRef}
/> />
@@ -93,7 +93,6 @@ interface UseDocumentsWorkspaceOptions {
onDocumentsSortFieldChange?: (field: string) => void; onDocumentsSortFieldChange?: (field: string) => void;
onDocumentsSortDirectionToggle?: () => void; onDocumentsSortDirectionToggle?: () => void;
searchIncludeDescendants?: boolean; searchIncludeDescendants?: boolean;
onToggleSearchIncludeDescendants?: () => void;
onSetSearchIncludeDescendants?: (value: boolean) => void; onSetSearchIncludeDescendants?: (value: boolean) => void;
sortRefreshReadyRef?: MutableRefObject<boolean>; sortRefreshReadyRef?: MutableRefObject<boolean>;
} }
@@ -108,14 +107,12 @@ const useDocumentsWorkspace = ({
onDocumentsSortFieldChange, onDocumentsSortFieldChange,
onDocumentsSortDirectionToggle, onDocumentsSortDirectionToggle,
searchIncludeDescendants = true, searchIncludeDescendants = true,
onToggleSearchIncludeDescendants,
onSetSearchIncludeDescendants, onSetSearchIncludeDescendants,
sortRefreshReadyRef, sortRefreshReadyRef,
}: UseDocumentsWorkspaceOptions = {}) => { }: UseDocumentsWorkspaceOptions = {}) => {
const handleDocumentsViewModeChange = onDocumentsViewModeChange || noop; const handleDocumentsViewModeChange = onDocumentsViewModeChange || noop;
const handleDocumentsSortFieldChange = onDocumentsSortFieldChange || noop; const handleDocumentsSortFieldChange = onDocumentsSortFieldChange || noop;
const handleDocumentsSortDirectionToggle = onDocumentsSortDirectionToggle || noop; const handleDocumentsSortDirectionToggle = onDocumentsSortDirectionToggle || noop;
const toggleSearchIncludeDescendants = onToggleSearchIncludeDescendants || noop;
const setSearchIncludeDescendants = onSetSearchIncludeDescendants || noop; const setSearchIncludeDescendants = onSetSearchIncludeDescendants || noop;
const fallbackSortFieldRef = useRef(documentsSortField); const fallbackSortFieldRef = useRef(documentsSortField);
@@ -348,12 +345,8 @@ const useDocumentsWorkspace = ({
setActiveTagFilters, setActiveTagFilters,
activeCorrespondentFilters, activeCorrespondentFilters,
setActiveCorrespondentFilters, setActiveCorrespondentFilters,
toggleTagFilter,
toggleCorrespondentFilter,
isFilterActive, isFilterActive,
clearFilters, documentsFilterValue,
handleSearchChange,
handleSearchSubmit,
} = useDocumentsSearch({ } = useDocumentsSearch({
api, api,
assetManager, assetManager,
@@ -370,6 +363,8 @@ const useDocumentsWorkspace = ({
setSearchIncludeDescendants, setSearchIncludeDescendants,
}); });
const documentsFilter = documentsFilterValue;
useEffect(() => { useEffect(() => {
setSearchResultsRef.current = setSearchResults; setSearchResultsRef.current = setSearchResults;
}, [setSearchResults]); }, [setSearchResults]);
@@ -1495,7 +1490,6 @@ const useDocumentsWorkspace = ({
currentSubfolders, currentSubfolders,
documents, documents,
searchResults, searchResults,
isFilterActive,
folderClickHandlers, folderClickHandlers,
handleFolderDragStart, handleFolderDragStart,
handleFolderDragEnd, handleFolderDragEnd,
@@ -1511,16 +1505,12 @@ const useDocumentsWorkspace = ({
activeCorrespondentFilters, activeCorrespondentFilters,
ensureAssetUrl, ensureAssetUrl,
getDocumentAsset, getDocumentAsset,
toggleTagFilter,
toggleCorrespondentFilter,
handleDocumentTagDrop, handleDocumentTagDrop,
documentsViewMode, documentsViewMode,
documentsSortField, documentsSortField,
documentsSortDirection, documentsSortDirection,
handleDocumentsSortFieldChange, handleDocumentsSortFieldChange,
handleDocumentsSortDirectionToggle, handleDocumentsSortDirectionToggle,
searchIncludeDescendants,
toggleSearchIncludeDescendants,
handleDocumentsViewModeChange, handleDocumentsViewModeChange,
clearDocumentSelection, clearDocumentSelection,
handleDeleteSelection, handleDeleteSelection,
@@ -1562,21 +1552,12 @@ const useDocumentsWorkspace = ({
handlePromptCreateFolder, handlePromptCreateFolder,
creatingFolder, creatingFolder,
tags, tags,
activeTagFilters,
toggleTagFilter,
handleTagCreate, handleTagCreate,
correspondents, correspondents,
activeCorrespondentFilters,
toggleCorrespondentFilter,
handleCorrespondentCreate, handleCorrespondentCreate,
appStatus, appStatus,
loading, loading,
previewActive, previewActive,
searchQuery,
handleSearchChange,
handleSearchSubmit,
clearFilters,
isFilterActive,
handleLogout, handleLogout,
status, status,
tenantName, tenantName,
@@ -1639,6 +1620,7 @@ const useDocumentsWorkspace = ({
openDetailPanel, openDetailPanel,
uploadQueue, uploadQueue,
clearUploadQueue, clearUploadQueue,
documentsFilter,
}), }),
[ [
token, token,
@@ -1690,6 +1672,7 @@ const useDocumentsWorkspace = ({
openDetailPanel, openDetailPanel,
uploadQueue, uploadQueue,
clearUploadQueue, clearUploadQueue,
documentsFilter,
], ],
); );
+38 -43
View File
@@ -25,6 +25,7 @@ import {
} from '../ui/icons'; } from '../ui/icons';
import PanelHeader from '../ui/PanelHeader'; import PanelHeader from '../ui/PanelHeader';
import useFloatingMenu from '../ui/useFloatingMenu'; import useFloatingMenu from '../ui/useFloatingMenu';
import { useDocumentsFilter } from '../documents/context/DocumentsFilterContext';
import { getTagColorStyle } from '../utils/colors'; import { getTagColorStyle } from '../utils/colors';
import { useSidebarContext } from './SidebarContext'; import { useSidebarContext } from './SidebarContext';
@@ -126,20 +127,11 @@ interface SidebarProps {
creatingFolder?: boolean; creatingFolder?: boolean;
tags?: TagEntry[]; tags?: TagEntry[];
untaggedFilterId?: Identifier | null; untaggedFilterId?: Identifier | null;
activeTagIds?: Array<Identifier | null>;
onToggleTagFilter?: (tagId: Identifier | null) => void;
correspondents?: CorrespondentEntry[]; correspondents?: CorrespondentEntry[];
activeCorrespondentIds?: Array<Identifier | null>;
onToggleCorrespondentFilter?: (correspondentId: Identifier | null) => void;
onManageTags?: () => void; onManageTags?: () => void;
onManageCorrespondents?: () => void; onManageCorrespondents?: () => void;
onCreateTag?: (label: string) => Promise<void> | void; onCreateTag?: (label: string) => Promise<void> | void;
onCreateCorrespondent?: (name: string) => Promise<void> | void; onCreateCorrespondent?: (name: string) => Promise<void> | void;
searchQuery?: string;
onSearchChange?: (value: string) => void;
onSearchSubmit?: () => void;
onSearchClear?: () => void;
isFilterActive?: boolean;
onLogout?: () => void; onLogout?: () => void;
status?: StatusMessage | null; status?: StatusMessage | null;
tenantName?: string | null; tenantName?: string | null;
@@ -301,20 +293,11 @@ const Sidebar: React.FC<SidebarProps> = ({
creatingFolder = false, creatingFolder = false,
tags = [], tags = [],
untaggedFilterId = null, untaggedFilterId = null,
activeTagIds = [],
onToggleTagFilter,
correspondents = [], correspondents = [],
activeCorrespondentIds = [],
onToggleCorrespondentFilter,
onManageTags, onManageTags,
onManageCorrespondents, onManageCorrespondents,
onCreateTag, onCreateTag,
onCreateCorrespondent, onCreateCorrespondent,
searchQuery = '',
onSearchChange,
onSearchSubmit,
onSearchClear,
isFilterActive = false,
onLogout, onLogout,
status = null, status = null,
tenantName, tenantName,
@@ -342,6 +325,17 @@ const Sidebar: React.FC<SidebarProps> = ({
sidebarSuppressed, sidebarSuppressed,
collapseSidebar, collapseSidebar,
} = usePanelManager(); } = usePanelManager();
const {
query: searchQuery,
activeTagIds = [],
activeCorrespondentIds = [],
isActive: isFilterActive,
setQuery: setFilterQuery,
submit: submitFilter,
clear: clearFilterState,
toggleTag: toggleTagFilter,
toggleCorrespondent: toggleCorrespondentFilter,
} = useDocumentsFilter();
const uploadInputRef = useRef<HTMLInputElement | null>(null); const uploadInputRef = useRef<HTMLInputElement | null>(null);
const sidebarRef = useRef<HTMLDivElement | null>(null); const sidebarRef = useRef<HTMLDivElement | null>(null);
const { const {
@@ -371,9 +365,12 @@ const Sidebar: React.FC<SidebarProps> = ({
); );
const handleToggleTag = useCallback( const handleToggleTag = useCallback(
(tagId: Identifier | null) => { (tagId: Identifier | null) => {
onToggleTagFilter?.(tagId); if (tagId == null) {
return;
}
toggleTagFilter(tagId);
}, },
[onToggleTagFilter], [toggleTagFilter],
); );
const activeTagSet = useMemo( const activeTagSet = useMemo(
() => new Set<Identifier | null>(activeTagIds || []), () => new Set<Identifier | null>(activeTagIds || []),
@@ -623,20 +620,20 @@ const Sidebar: React.FC<SidebarProps> = ({
const handleSearchInputChange = useCallback( const handleSearchInputChange = useCallback(
(event: React.ChangeEvent<HTMLInputElement>) => { (event: React.ChangeEvent<HTMLInputElement>) => {
onSearchChange?.(event.target.value); setFilterQuery(event.target.value);
}, },
[onSearchChange], [setFilterQuery],
); );
const handleSearchFormSubmit = useCallback( const handleSearchFormSubmit = useCallback(
(event: React.FormEvent<HTMLFormElement>) => { (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault(); event.preventDefault();
onSearchSubmit?.(); submitFilter();
}, },
[onSearchSubmit], [submitFilter],
); );
const handleSearchClear = useCallback(() => { const handleSearchClear = useCallback(() => {
onSearchClear?.(); clearFilterState();
}, [onSearchClear]); }, [clearFilterState]);
const tenantButtonRef = useRef<HTMLButtonElement | null>(null); const tenantButtonRef = useRef<HTMLButtonElement | null>(null);
const { const {
isOpen: tenantMenuOpen, isOpen: tenantMenuOpen,
@@ -869,22 +866,20 @@ const Sidebar: React.FC<SidebarProps> = ({
<div className={`status-banner ${status.variant}`}>{status.message}</div> <div className={`status-banner ${status.variant}`}>{status.message}</div>
</div> </div>
)} )}
{onSearchChange && ( <form className="sidebar__search" onSubmit={handleSearchFormSubmit}>
<form className="sidebar__search" onSubmit={handleSearchFormSubmit}> <input
<input type="search"
type="search" value={searchQuery}
value={searchQuery} onChange={handleSearchInputChange}
onChange={handleSearchInputChange} placeholder="Search documents"
placeholder="Search documents" aria-label="Search documents"
aria-label="Search documents" />
/> {isFilterActive && (
{isFilterActive && ( <button type="button" onClick={handleSearchClear}>
<button type="button" onClick={handleSearchClear}> Clear
Clear </button>
</button> )}
)} </form>
</form>
)}
<div className="sidebar-section sidebar-section--folders"> <div className="sidebar-section sidebar-section--folders">
<div className="sidebar-section__header"> <div className="sidebar-section__header">
<h3>Folders</h3> <h3>Folders</h3>
@@ -1011,7 +1006,7 @@ const Sidebar: React.FC<SidebarProps> = ({
const className = `sidebar-correspondent-item${isActive ? ' active' : ''}`; const className = `sidebar-correspondent-item${isActive ? ' active' : ''}`;
const handleSelect = () => { const handleSelect = () => {
const nextId = isActive ? null : correspondent.id; const nextId = isActive ? null : correspondent.id;
onToggleCorrespondentFilter?.(nextId); toggleCorrespondentFilter(nextId);
}; };
return ( return (
<li key={correspondent.id}> <li key={correspondent.id}>
-45
View File
@@ -80,12 +80,8 @@ interface UseSidebarPropsArgs {
handlePromptCreateFolder?: () => void; handlePromptCreateFolder?: () => void;
creatingFolder: boolean; creatingFolder: boolean;
tags: TagOption[]; tags: TagOption[];
activeTagFilters: Identifier[];
toggleTagFilter: (tagId: Identifier) => void;
handleTagCreate: (payload: { label?: string }) => void | Promise<void>; handleTagCreate: (payload: { label?: string }) => void | Promise<void>;
correspondents: CorrespondentOption[]; correspondents: CorrespondentOption[];
activeCorrespondentFilters: Identifier[];
toggleCorrespondentFilter: (correspondentId: Identifier) => void;
handleCorrespondentCreate: (payload: { name?: string }) => handleCorrespondentCreate: (payload: { name?: string }) =>
| Promise<CorrespondentOption | null | void> | Promise<CorrespondentOption | null | void>
| CorrespondentOption | CorrespondentOption
@@ -94,11 +90,6 @@ interface UseSidebarPropsArgs {
appStatus: string; appStatus: string;
loading: boolean; loading: boolean;
previewActive: boolean; previewActive: boolean;
searchQuery: string;
handleSearchChange: (value: string) => void;
handleSearchSubmit: () => void;
clearFilters: () => void;
isFilterActive: boolean;
handleLogout: () => void | Promise<void>; handleLogout: () => void | Promise<void>;
status: StatusMessage | null; status: StatusMessage | null;
tenantName: string | null; tenantName: string | null;
@@ -127,21 +118,12 @@ interface SidebarHookResult {
creatingFolder: boolean; creatingFolder: boolean;
tags: TagOption[]; tags: TagOption[];
untaggedFilterId: typeof TAG_FILTER_UNTAGGED; untaggedFilterId: typeof TAG_FILTER_UNTAGGED;
activeTagIds: Identifier[];
onToggleTagFilter: UseSidebarPropsArgs['toggleTagFilter'];
onCreateTag: (label: string) => void; onCreateTag: (label: string) => void;
correspondents: CorrespondentOption[]; correspondents: CorrespondentOption[];
activeCorrespondentIds: Identifier[];
onToggleCorrespondentFilter: UseSidebarPropsArgs['toggleCorrespondentFilter'];
onCreateCorrespondent: (name: string) => void; onCreateCorrespondent: (name: string) => void;
appStatus: string; appStatus: string;
loading: boolean; loading: boolean;
previewActive: boolean; previewActive: boolean;
searchQuery: string;
onSearchChange: UseSidebarPropsArgs['handleSearchChange'];
onSearchSubmit: UseSidebarPropsArgs['handleSearchSubmit'];
onSearchClear: UseSidebarPropsArgs['clearFilters'];
isFilterActive: boolean;
onLogout: UseSidebarPropsArgs['handleLogout']; onLogout: UseSidebarPropsArgs['handleLogout'];
status: StatusMessage | null; status: StatusMessage | null;
tenantName: string | null; tenantName: string | null;
@@ -165,21 +147,12 @@ const useSidebarProps = ({
handlePromptCreateFolder, handlePromptCreateFolder,
creatingFolder, creatingFolder,
tags, tags,
activeTagFilters,
toggleTagFilter,
handleTagCreate, handleTagCreate,
correspondents, correspondents,
activeCorrespondentFilters,
toggleCorrespondentFilter,
handleCorrespondentCreate, handleCorrespondentCreate,
appStatus, appStatus,
loading, loading,
previewActive, previewActive,
searchQuery,
handleSearchChange,
handleSearchSubmit,
clearFilters,
isFilterActive,
handleLogout, handleLogout,
status, status,
tenantName, tenantName,
@@ -208,21 +181,12 @@ const useSidebarProps = ({
creatingFolder, creatingFolder,
tags, tags,
untaggedFilterId: TAG_FILTER_UNTAGGED, untaggedFilterId: TAG_FILTER_UNTAGGED,
activeTagIds: activeTagFilters,
onToggleTagFilter: toggleTagFilter,
onCreateTag: (label) => handleTagCreate({ label }), onCreateTag: (label) => handleTagCreate({ label }),
correspondents, correspondents,
activeCorrespondentIds: activeCorrespondentFilters,
onToggleCorrespondentFilter: toggleCorrespondentFilter,
onCreateCorrespondent: (name) => handleCorrespondentCreate({ name }), onCreateCorrespondent: (name) => handleCorrespondentCreate({ name }),
appStatus, appStatus,
loading, loading,
previewActive, previewActive,
searchQuery,
onSearchChange: handleSearchChange,
onSearchSubmit: handleSearchSubmit,
onSearchClear: clearFilters,
isFilterActive,
onLogout: handleLogout, onLogout: handleLogout,
status, status,
tenantName, tenantName,
@@ -249,10 +213,7 @@ const useSidebarProps = ({
[ [
handleFileSelection, handleFileSelection,
uploadQueue, uploadQueue,
activeCorrespondentFilters,
activeTagFilters,
appStatus, appStatus,
clearFilters,
correspondents, correspondents,
creatingFolder, creatingFolder,
currentTenantId, currentTenantId,
@@ -265,23 +226,17 @@ const useSidebarProps = ({
handleFolderRename, handleFolderRename,
handleLogout, handleLogout,
handlePromptCreateFolder, handlePromptCreateFolder,
handleSearchChange,
handleSearchSubmit,
handleTagCreate, handleTagCreate,
handleTenantSelect, handleTenantSelect,
isFilterActive,
loading, loading,
openSettings, openSettings,
previewActive, previewActive,
searchQuery,
draggedFolderId, draggedFolderId,
selectedFolder, selectedFolder,
status, status,
tags, tags,
tenantName, tenantName,
tenantOptions, tenantOptions,
toggleCorrespondentFilter,
toggleTagFilter,
], ],
); );