289 lines
8.5 KiB
TypeScript
289 lines
8.5 KiB
TypeScript
import { useMemo } from 'react';
|
|
import type { DragEvent } from 'react';
|
|
import { TAG_FILTER_UNTAGGED } from '../app/appLayoutUtils';
|
|
import type { StatusMessage } from '../hooks/documents/store/useDocumentsStore';
|
|
|
|
type Identifier = string | number;
|
|
|
|
interface FolderTreeNode {
|
|
id: Identifier;
|
|
name?: string;
|
|
hasChildren?: boolean;
|
|
loaded?: boolean;
|
|
expanded?: boolean;
|
|
children: Identifier[];
|
|
[key: string]: unknown;
|
|
}
|
|
|
|
type FolderNodeMap = Map<Identifier, FolderTreeNode>;
|
|
|
|
type FolderToggleHandler = (folderId: Identifier) => void | Promise<void>;
|
|
type FolderDropHandler = (
|
|
event: DragEvent<HTMLElement>,
|
|
folderId: Identifier,
|
|
) => void | Promise<void>;
|
|
|
|
interface FolderClickHandlers {
|
|
onToggle: FolderToggleHandler;
|
|
onSelect: (folderId: Identifier | null) => void;
|
|
onDrop: FolderDropHandler;
|
|
onDragOver: (event: DragEvent<HTMLElement>, folderId: Identifier) => void;
|
|
onDragLeave: (event: DragEvent<HTMLElement>) => void;
|
|
}
|
|
|
|
interface TagOption {
|
|
id?: Identifier;
|
|
label?: string;
|
|
color?: string | null;
|
|
[key: string]: unknown;
|
|
}
|
|
|
|
interface CorrespondentOption {
|
|
id?: Identifier;
|
|
name?: string;
|
|
[key: string]: unknown;
|
|
}
|
|
|
|
interface TenantOption {
|
|
id?: Identifier;
|
|
name?: string;
|
|
[key: string]: unknown;
|
|
}
|
|
|
|
interface UploadQueueItem {
|
|
id: string;
|
|
name?: string;
|
|
size?: number | null;
|
|
folderId?: Identifier | 'root';
|
|
status?: string;
|
|
error?: unknown;
|
|
code?: number | null;
|
|
document?: unknown;
|
|
conflictDocumentId?: Identifier | null;
|
|
[key: string]: unknown;
|
|
}
|
|
|
|
type UploadFilesHandler = (
|
|
files: FileList | File[] | Iterable<File>,
|
|
targetFolderId: Identifier | 'root',
|
|
) => void | Promise<void>;
|
|
|
|
interface UseSidebarPropsArgs {
|
|
folderNodes: FolderNodeMap;
|
|
folderClickHandlers: FolderClickHandlers;
|
|
handleFolderDelete: (folderId: Identifier) => void | Promise<void>;
|
|
handleFolderRename: (folderId: Identifier, name: string) => void | Promise<void>;
|
|
selectedFolder: Identifier | null;
|
|
handleFolderDragStart: (event: DragEvent<HTMLElement>, folderId: Identifier) => void;
|
|
handleFolderDragEnd: (event: DragEvent<HTMLElement>) => void;
|
|
draggedFolderId: Identifier | null;
|
|
handlePromptCreateFolder?: () => void;
|
|
creatingFolder: boolean;
|
|
tags: TagOption[];
|
|
activeTagFilters: Identifier[];
|
|
toggleTagFilter: (tagId: Identifier) => void;
|
|
handleTagCreate: (payload: { label?: string }) => void | Promise<void>;
|
|
correspondents: CorrespondentOption[];
|
|
activeCorrespondentFilters: Identifier[];
|
|
toggleCorrespondentFilter: (correspondentId: Identifier) => void;
|
|
handleCorrespondentCreate: (payload: { name?: string }) =>
|
|
| Promise<CorrespondentOption | null | void>
|
|
| CorrespondentOption
|
|
| null
|
|
| void;
|
|
appStatus: string;
|
|
loading: boolean;
|
|
previewActive: boolean;
|
|
searchQuery: string;
|
|
handleSearchChange: (value: string) => void;
|
|
handleSearchSubmit: () => void;
|
|
clearFilters: () => void;
|
|
isFilterActive: boolean;
|
|
handleLogout: () => void | Promise<void>;
|
|
status: StatusMessage | null;
|
|
tenantName: string | null;
|
|
tenantOptions: TenantOption[];
|
|
currentTenantId: Identifier | null;
|
|
handleTenantSelect: (tenant: TenantOption | null, options?: { refreshOnly?: boolean }) => void | Promise<void>;
|
|
openSettings?: () => void;
|
|
handleFileSelection?: UploadFilesHandler;
|
|
uploadQueue?: UploadQueueItem[];
|
|
}
|
|
|
|
interface SidebarHookResult {
|
|
folderNodes: FolderNodeMap;
|
|
onToggle: FolderClickHandlers['onToggle'];
|
|
onSelect: FolderClickHandlers['onSelect'];
|
|
onDrop: FolderClickHandlers['onDrop'];
|
|
onDragOver: FolderClickHandlers['onDragOver'];
|
|
onDragLeave: FolderClickHandlers['onDragLeave'];
|
|
onDeleteFolder: UseSidebarPropsArgs['handleFolderDelete'];
|
|
onRenameFolder: UseSidebarPropsArgs['handleFolderRename'];
|
|
selectedFolder: Identifier | null;
|
|
onFolderDragStart: UseSidebarPropsArgs['handleFolderDragStart'];
|
|
onFolderDragEnd: UseSidebarPropsArgs['handleFolderDragEnd'];
|
|
draggedFolderId: Identifier | null;
|
|
onCreateFolder: UseSidebarPropsArgs['handlePromptCreateFolder'];
|
|
creatingFolder: boolean;
|
|
tags: TagOption[];
|
|
untaggedFilterId: typeof TAG_FILTER_UNTAGGED;
|
|
activeTagIds: Identifier[];
|
|
onToggleTagFilter: UseSidebarPropsArgs['toggleTagFilter'];
|
|
onCreateTag: (label: string) => void;
|
|
correspondents: CorrespondentOption[];
|
|
activeCorrespondentIds: Identifier[];
|
|
onToggleCorrespondentFilter: UseSidebarPropsArgs['toggleCorrespondentFilter'];
|
|
onCreateCorrespondent: (name: string) => void;
|
|
appStatus: string;
|
|
loading: boolean;
|
|
previewActive: boolean;
|
|
searchQuery: string;
|
|
onSearchChange: UseSidebarPropsArgs['handleSearchChange'];
|
|
onSearchSubmit: UseSidebarPropsArgs['handleSearchSubmit'];
|
|
onSearchClear: UseSidebarPropsArgs['clearFilters'];
|
|
isFilterActive: boolean;
|
|
onLogout: UseSidebarPropsArgs['handleLogout'];
|
|
status: StatusMessage | null;
|
|
tenantName: string | null;
|
|
tenants: TenantOption[];
|
|
activeTenantId: Identifier | null;
|
|
onSelectTenant: UseSidebarPropsArgs['handleTenantSelect'];
|
|
onOpenSettings: UseSidebarPropsArgs['openSettings'];
|
|
onUploadFiles: (files: FileList | File[] | Iterable<File>, targetFolderId?: Identifier | 'root') => void;
|
|
uploadQueue?: UploadQueueItem[];
|
|
}
|
|
|
|
const useSidebarProps = ({
|
|
folderNodes,
|
|
folderClickHandlers,
|
|
handleFolderDelete,
|
|
handleFolderRename,
|
|
selectedFolder,
|
|
handleFolderDragStart,
|
|
handleFolderDragEnd,
|
|
draggedFolderId,
|
|
handlePromptCreateFolder,
|
|
creatingFolder,
|
|
tags,
|
|
activeTagFilters,
|
|
toggleTagFilter,
|
|
handleTagCreate,
|
|
correspondents,
|
|
activeCorrespondentFilters,
|
|
toggleCorrespondentFilter,
|
|
handleCorrespondentCreate,
|
|
appStatus,
|
|
loading,
|
|
previewActive,
|
|
searchQuery,
|
|
handleSearchChange,
|
|
handleSearchSubmit,
|
|
clearFilters,
|
|
isFilterActive,
|
|
handleLogout,
|
|
status,
|
|
tenantName,
|
|
tenantOptions,
|
|
currentTenantId,
|
|
handleTenantSelect,
|
|
openSettings,
|
|
handleFileSelection,
|
|
uploadQueue,
|
|
}: UseSidebarPropsArgs): SidebarHookResult =>
|
|
useMemo(
|
|
() => ({
|
|
folderNodes,
|
|
onToggle: folderClickHandlers.onToggle,
|
|
onSelect: folderClickHandlers.onSelect,
|
|
onDrop: folderClickHandlers.onDrop,
|
|
onDragOver: folderClickHandlers.onDragOver,
|
|
onDragLeave: folderClickHandlers.onDragLeave,
|
|
onDeleteFolder: handleFolderDelete,
|
|
onRenameFolder: handleFolderRename,
|
|
selectedFolder,
|
|
onFolderDragStart: handleFolderDragStart,
|
|
onFolderDragEnd: handleFolderDragEnd,
|
|
draggedFolderId,
|
|
onCreateFolder: handlePromptCreateFolder,
|
|
creatingFolder,
|
|
tags,
|
|
untaggedFilterId: TAG_FILTER_UNTAGGED,
|
|
activeTagIds: activeTagFilters,
|
|
onToggleTagFilter: toggleTagFilter,
|
|
onCreateTag: (label) => handleTagCreate({ label }),
|
|
correspondents,
|
|
activeCorrespondentIds: activeCorrespondentFilters,
|
|
onToggleCorrespondentFilter: toggleCorrespondentFilter,
|
|
onCreateCorrespondent: (name) => handleCorrespondentCreate({ name }),
|
|
appStatus,
|
|
loading,
|
|
previewActive,
|
|
searchQuery,
|
|
onSearchChange: handleSearchChange,
|
|
onSearchSubmit: handleSearchSubmit,
|
|
onSearchClear: clearFilters,
|
|
isFilterActive,
|
|
onLogout: handleLogout,
|
|
status,
|
|
tenantName,
|
|
tenants: tenantOptions,
|
|
activeTenantId: currentTenantId,
|
|
onSelectTenant: handleTenantSelect,
|
|
onOpenSettings: openSettings,
|
|
onUploadFiles: (files, targetFolderId) => {
|
|
if (!handleFileSelection) {
|
|
return;
|
|
}
|
|
if (!files) {
|
|
return;
|
|
}
|
|
const normalizedFiles = Array.isArray(files) ? files : Array.from(files);
|
|
if (normalizedFiles.length === 0) {
|
|
return;
|
|
}
|
|
const folderId = targetFolderId ?? selectedFolder ?? 'root';
|
|
handleFileSelection(normalizedFiles, folderId);
|
|
},
|
|
uploadQueue,
|
|
}),
|
|
[
|
|
handleFileSelection,
|
|
uploadQueue,
|
|
activeCorrespondentFilters,
|
|
activeTagFilters,
|
|
appStatus,
|
|
clearFilters,
|
|
correspondents,
|
|
creatingFolder,
|
|
currentTenantId,
|
|
folderClickHandlers,
|
|
folderNodes,
|
|
handleCorrespondentCreate,
|
|
handleFolderDragEnd,
|
|
handleFolderDragStart,
|
|
handleFolderDelete,
|
|
handleFolderRename,
|
|
handleLogout,
|
|
handlePromptCreateFolder,
|
|
handleSearchChange,
|
|
handleSearchSubmit,
|
|
handleTagCreate,
|
|
handleTenantSelect,
|
|
isFilterActive,
|
|
loading,
|
|
openSettings,
|
|
previewActive,
|
|
searchQuery,
|
|
draggedFolderId,
|
|
selectedFolder,
|
|
status,
|
|
tags,
|
|
tenantName,
|
|
tenantOptions,
|
|
toggleCorrespondentFilter,
|
|
toggleTagFilter,
|
|
],
|
|
);
|
|
|
|
export default useSidebarProps;
|