fix
This commit is contained in:
@@ -3133,165 +3133,6 @@ const AppLayout = () => {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleDocumentListFocus = useCallback(() => {
|
|
||||||
if (focusedRowKey && navigableRowKeys.includes(focusedRowKey)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let resolvedKey = null;
|
|
||||||
for (let index = selectedEntries.length - 1; index >= 0; index -= 1) {
|
|
||||||
const candidate = selectedEntries[index];
|
|
||||||
if (navigableRowKeys.includes(candidate)) {
|
|
||||||
resolvedKey = candidate;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!resolvedKey && navigableRows.length) {
|
|
||||||
resolvedKey = navigableRows[0].key;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!resolvedKey) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (selectedEntries.length === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setFocusedRowKey(resolvedKey);
|
|
||||||
|
|
||||||
if (!selectedEntries.includes(resolvedKey) && selectedEntries.length > 0) {
|
|
||||||
applySelection([resolvedKey], { anchor: resolvedKey, interactedKeys: [resolvedKey] });
|
|
||||||
}
|
|
||||||
}, [
|
|
||||||
focusedRowKey,
|
|
||||||
navigableRowKeys,
|
|
||||||
selectedEntries,
|
|
||||||
navigableRows,
|
|
||||||
applySelection,
|
|
||||||
setFocusedRowKey,
|
|
||||||
]);
|
|
||||||
|
|
||||||
const handleDocumentListKeyDown = useCallback(
|
|
||||||
(event) => {
|
|
||||||
const { key, shiftKey } = event;
|
|
||||||
const triggers = ['ArrowUp', 'ArrowDown', 'Home', 'End', 'Enter', ' ', 'Space', 'Spacebar'];
|
|
||||||
if (!triggers.includes(key)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!navigableRows.length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
let activeKey =
|
|
||||||
focusedRowKey && navigableRowKeys.includes(focusedRowKey)
|
|
||||||
? focusedRowKey
|
|
||||||
: null;
|
|
||||||
|
|
||||||
let initializedFromEmptyState = false;
|
|
||||||
|
|
||||||
if (!activeKey) {
|
|
||||||
for (let index = selectedEntries.length - 1; index >= 0; index -= 1) {
|
|
||||||
const candidate = selectedEntries[index];
|
|
||||||
if (navigableRowKeys.includes(candidate)) {
|
|
||||||
activeKey = candidate;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!activeKey) {
|
|
||||||
if (key === 'ArrowUp') {
|
|
||||||
const lastKey = navigableRowKeys[navigableRowKeys.length - 1];
|
|
||||||
if (!lastKey) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
activeKey = lastKey;
|
|
||||||
} else {
|
|
||||||
activeKey = navigableRowKeys[0];
|
|
||||||
}
|
|
||||||
setFocusedRowKey(activeKey);
|
|
||||||
initializedFromEmptyState = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
let currentIndex = navigableRowKeys.indexOf(activeKey);
|
|
||||||
|
|
||||||
if (key === 'Enter' || key === ' ' || key === 'Space' || key === 'Spacebar') {
|
|
||||||
const row = currentIndex === -1 ? navigableRows[0] : navigableRows[currentIndex];
|
|
||||||
if (!row) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
handleEntrySelection(row.key, event);
|
|
||||||
if (row.type === 'folder') {
|
|
||||||
selectFolder(row.id);
|
|
||||||
} else if (row.type === 'document') {
|
|
||||||
openDocumentPreview(row.id);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let nextIndex = currentIndex;
|
|
||||||
|
|
||||||
if (key === 'ArrowDown') {
|
|
||||||
if (initializedFromEmptyState && selectedEntries.length === 0) {
|
|
||||||
handleEntrySelection(activeKey, {
|
|
||||||
shiftKey,
|
|
||||||
preventDefault: () => {},
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
nextIndex = currentIndex === -1 ? 0 : Math.min(currentIndex + 1, navigableRows.length - 1);
|
|
||||||
} else if (key === 'ArrowUp') {
|
|
||||||
if (initializedFromEmptyState && selectedEntries.length === 0) {
|
|
||||||
handleEntrySelection(activeKey, {
|
|
||||||
shiftKey,
|
|
||||||
preventDefault: () => {},
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
nextIndex = currentIndex === -1 ? navigableRows.length - 1 : Math.max(currentIndex - 1, 0);
|
|
||||||
} else if (key === 'Home') {
|
|
||||||
nextIndex = 0;
|
|
||||||
} else if (key === 'End') {
|
|
||||||
nextIndex = navigableRows.length - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nextIndex === -1 || nextIndex >= navigableRows.length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nextIndex === currentIndex && key !== 'Home' && key !== 'End') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const targetRow = navigableRows[nextIndex];
|
|
||||||
if (!targetRow) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setFocusedRowKey(targetRow.key);
|
|
||||||
|
|
||||||
handleEntrySelection(targetRow.key, {
|
|
||||||
shiftKey,
|
|
||||||
preventDefault: () => {},
|
|
||||||
});
|
|
||||||
},
|
|
||||||
[
|
|
||||||
navigableRows,
|
|
||||||
navigableRowKeys,
|
|
||||||
focusedRowKey,
|
|
||||||
selectedEntries,
|
|
||||||
handleEntrySelection,
|
|
||||||
selectFolder,
|
|
||||||
openDocumentPreview,
|
|
||||||
setFocusedRowKey,
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!previewDocumentId) return;
|
if (!previewDocumentId) return;
|
||||||
const handleKeyDown = (event) => {
|
const handleKeyDown = (event) => {
|
||||||
@@ -4728,8 +4569,7 @@ const AppLayout = () => {
|
|||||||
isSearchLoading: searchLoading,
|
isSearchLoading: searchLoading,
|
||||||
tagLookupById,
|
tagLookupById,
|
||||||
activeCorrespondentIds: activeCorrespondentFilters,
|
activeCorrespondentIds: activeCorrespondentFilters,
|
||||||
onDocumentListFocus: handleDocumentListFocus,
|
selectedEntries,
|
||||||
onDocumentListKeyDown: handleDocumentListKeyDown,
|
|
||||||
onFocusedRowChange: setFocusedRowKey,
|
onFocusedRowChange: setFocusedRowKey,
|
||||||
ensureAssetUrl,
|
ensureAssetUrl,
|
||||||
getDocumentAsset,
|
getDocumentAsset,
|
||||||
@@ -4741,6 +4581,7 @@ const AppLayout = () => {
|
|||||||
onClearSelection: clearDocumentSelection,
|
onClearSelection: clearDocumentSelection,
|
||||||
onDeleteSelection: handleDeleteSelection,
|
onDeleteSelection: handleDeleteSelection,
|
||||||
onEntryPointer: handleEntryPointer,
|
onEntryPointer: handleEntryPointer,
|
||||||
|
onEntrySelection: handleEntrySelection,
|
||||||
tags,
|
tags,
|
||||||
correspondents,
|
correspondents,
|
||||||
documentLookup,
|
documentLookup,
|
||||||
@@ -4764,14 +4605,14 @@ const AppLayout = () => {
|
|||||||
folderClickHandlers,
|
folderClickHandlers,
|
||||||
handleDocumentDragEnd,
|
handleDocumentDragEnd,
|
||||||
handleDocumentDragStart,
|
handleDocumentDragStart,
|
||||||
handleDocumentListFocus,
|
|
||||||
handleDocumentListKeyDown,
|
|
||||||
handleDocumentTagDrop,
|
handleDocumentTagDrop,
|
||||||
handleDocumentTitleUpdate,
|
handleDocumentTitleUpdate,
|
||||||
handleDocumentsViewModeChange,
|
handleDocumentsViewModeChange,
|
||||||
handleFolderDragEnd,
|
handleFolderDragEnd,
|
||||||
handleFolderDragStart,
|
handleFolderDragStart,
|
||||||
handleFolderRename,
|
handleFolderRename,
|
||||||
|
handleEntryPointer,
|
||||||
|
handleEntrySelection,
|
||||||
handleDeleteSelection,
|
handleDeleteSelection,
|
||||||
isFilterActive,
|
isFilterActive,
|
||||||
openDocumentPreview,
|
openDocumentPreview,
|
||||||
@@ -4780,12 +4621,12 @@ const AppLayout = () => {
|
|||||||
searchResults,
|
searchResults,
|
||||||
selectFolder,
|
selectFolder,
|
||||||
selectedDocumentIds,
|
selectedDocumentIds,
|
||||||
|
selectedEntries,
|
||||||
selectedFolderIds,
|
selectedFolderIds,
|
||||||
setFocusedRowKey,
|
setFocusedRowKey,
|
||||||
tagLookupById,
|
tagLookupById,
|
||||||
toggleCorrespondentFilter,
|
toggleCorrespondentFilter,
|
||||||
toggleTagFilter,
|
toggleTagFilter,
|
||||||
handleEntryPointer,
|
|
||||||
ensureAssetUrl,
|
ensureAssetUrl,
|
||||||
getDocumentAsset,
|
getDocumentAsset,
|
||||||
tags,
|
tags,
|
||||||
|
|||||||
@@ -158,24 +158,22 @@ const useDocumentDrag = () => {
|
|||||||
: [];
|
: [];
|
||||||
|
|
||||||
if (stackDocIdsOption && stackDocIdsOption.length) {
|
if (stackDocIdsOption && stackDocIdsOption.length) {
|
||||||
selectionIds = stackDocIdsOption;
|
const selectionSet = new Set(selectionIds);
|
||||||
|
stackDocIdsOption.forEach((value) => {
|
||||||
|
if (value != null) {
|
||||||
|
selectionSet.add(String(value));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
selectionIds = Array.from(selectionSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
const metaOrCtrl = event.metaKey || event.ctrlKey;
|
const metaOrCtrl = event.metaKey || event.ctrlKey;
|
||||||
if (!stackDocIdsOption && metaOrCtrl && !selectionIds.includes(docKey)) {
|
if (!stackDocIdsOption && metaOrCtrl && !selectionIds.includes(docKey)) {
|
||||||
selectionIds = [...selectionIds, docKey];
|
selectionIds = [...selectionIds, docKey];
|
||||||
}
|
}
|
||||||
let groupDocIds = [];
|
let groupDocIds = selectionIds
|
||||||
if (stackDocIdsOption && stackDocIdsOption.length) {
|
|
||||||
groupDocIds = stackDocIdsOption.filter((id, index, array) => {
|
|
||||||
const unique = array.indexOf(id) === index;
|
|
||||||
return unique && documentLookup.has(id);
|
|
||||||
});
|
|
||||||
} else if (selectionIds.includes(docKey) && selectionIds.length > 1) {
|
|
||||||
groupDocIds = selectionIds
|
|
||||||
.map((id) => String(id))
|
.map((id) => String(id))
|
||||||
.filter((id, index, array) => array.indexOf(id) === index && documentLookup.has(id));
|
.filter((id, index, array) => array.indexOf(id) === index && documentLookup.has(id));
|
||||||
}
|
|
||||||
if (!groupDocIds.includes(docKey)) {
|
if (!groupDocIds.includes(docKey)) {
|
||||||
groupDocIds.unshift(docKey);
|
groupDocIds.unshift(docKey);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,10 +49,9 @@ const DocumentsPanel = ({
|
|||||||
onDocumentDragEnd,
|
onDocumentDragEnd,
|
||||||
onDocumentRename,
|
onDocumentRename,
|
||||||
onEntryPointer = null,
|
onEntryPointer = null,
|
||||||
|
onEntrySelection = null,
|
||||||
tagLookupById,
|
tagLookupById,
|
||||||
activeCorrespondentIds = [],
|
activeCorrespondentIds = [],
|
||||||
onDocumentListFocus,
|
|
||||||
onDocumentListKeyDown,
|
|
||||||
onFocusedRowChange,
|
onFocusedRowChange,
|
||||||
ensureAssetUrl = null,
|
ensureAssetUrl = null,
|
||||||
getDocumentAsset = () => null,
|
getDocumentAsset = () => null,
|
||||||
@@ -63,6 +62,7 @@ const DocumentsPanel = ({
|
|||||||
viewMode = 'list',
|
viewMode = 'list',
|
||||||
onViewModeChange,
|
onViewModeChange,
|
||||||
onClearSelection,
|
onClearSelection,
|
||||||
|
selectedEntries = [],
|
||||||
showHeader = true,
|
showHeader = true,
|
||||||
}) => {
|
}) => {
|
||||||
const showingSearchResults = searchResults !== null;
|
const showingSearchResults = searchResults !== null;
|
||||||
@@ -198,6 +198,153 @@ const DocumentsPanel = ({
|
|||||||
[handleDocumentPreviewZoom],
|
[handleDocumentPreviewZoom],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const selectedRowKeySet = useMemo(() => new Set(selectedEntries || []), [selectedEntries]);
|
||||||
|
const navigableRows = useMemo(
|
||||||
|
() => entries.map((entry) => ({ key: entry.key, type: entry.type, id: entry.id })),
|
||||||
|
[entries],
|
||||||
|
);
|
||||||
|
const navigableRowKeys = useMemo(() => navigableRows.map((row) => row.key), [navigableRows]);
|
||||||
|
|
||||||
|
const getEntryByKey = useCallback(
|
||||||
|
(rowKey) => entries.find((entry) => entry.key === rowKey) || null,
|
||||||
|
[entries],
|
||||||
|
);
|
||||||
|
|
||||||
|
const handlePanelFocus = useCallback(() => {
|
||||||
|
let resolvedKey = null;
|
||||||
|
|
||||||
|
if (focusedRowKey && navigableRowKeys.includes(focusedRowKey)) {
|
||||||
|
resolvedKey = focusedRowKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!resolvedKey) {
|
||||||
|
for (let index = selectedEntries.length - 1; index >= 0; index -= 1) {
|
||||||
|
const candidate = selectedEntries[index];
|
||||||
|
if (navigableRowKeys.includes(candidate)) {
|
||||||
|
resolvedKey = candidate;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!resolvedKey && navigableRows.length) {
|
||||||
|
resolvedKey = navigableRows[0].key;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!resolvedKey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
onFocusedRowChange?.(resolvedKey);
|
||||||
|
|
||||||
|
if (!selectedRowKeySet.has(resolvedKey) && typeof onEntrySelection === 'function') {
|
||||||
|
onEntrySelection(resolvedKey, {
|
||||||
|
shiftKey: false,
|
||||||
|
preventDefault: () => {},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [
|
||||||
|
focusedRowKey,
|
||||||
|
navigableRowKeys,
|
||||||
|
navigableRows,
|
||||||
|
onEntrySelection,
|
||||||
|
onFocusedRowChange,
|
||||||
|
selectedEntries,
|
||||||
|
selectedRowKeySet,
|
||||||
|
]);
|
||||||
|
|
||||||
|
const handlePanelKeyDown = useCallback(
|
||||||
|
(event) => {
|
||||||
|
const { key, shiftKey } = event;
|
||||||
|
const triggers = ['ArrowUp', 'ArrowDown', 'Home', 'End', 'Enter', ' ', 'Space', 'Spacebar'];
|
||||||
|
if (!triggers.includes(key)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!navigableRows.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
let activeKey =
|
||||||
|
focusedRowKey && navigableRowKeys.includes(focusedRowKey)
|
||||||
|
? focusedRowKey
|
||||||
|
: null;
|
||||||
|
|
||||||
|
if (!activeKey) {
|
||||||
|
if (selectedEntries.length) {
|
||||||
|
for (let index = selectedEntries.length - 1; index >= 0; index -= 1) {
|
||||||
|
const candidate = selectedEntries[index];
|
||||||
|
if (navigableRowKeys.includes(candidate)) {
|
||||||
|
activeKey = candidate;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!activeKey) {
|
||||||
|
activeKey = key === 'ArrowUp' ? navigableRowKeys[navigableRowKeys.length - 1] : navigableRowKeys[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentIndex = navigableRowKeys.indexOf(activeKey);
|
||||||
|
const activeRow = currentIndex === -1 ? null : navigableRows[currentIndex];
|
||||||
|
|
||||||
|
if (key === 'Enter' || key === ' ' || key === 'Space' || key === 'Spacebar') {
|
||||||
|
if (activeRow) {
|
||||||
|
onEntrySelection?.(activeRow.key, event);
|
||||||
|
if (activeRow.type === EntryType.folder) {
|
||||||
|
onFolderSelect?.(activeRow.id);
|
||||||
|
} else {
|
||||||
|
const entry = getEntryByKey(activeRow.key);
|
||||||
|
if (entry?.document) {
|
||||||
|
handleDocumentActivate(entry.document, event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let nextIndex = currentIndex;
|
||||||
|
if (key === 'ArrowDown') {
|
||||||
|
nextIndex = currentIndex === -1 ? 0 : Math.min(currentIndex + 1, navigableRows.length - 1);
|
||||||
|
} else if (key === 'ArrowUp') {
|
||||||
|
nextIndex = currentIndex === -1 ? navigableRows.length - 1 : Math.max(currentIndex - 1, 0);
|
||||||
|
} else if (key === 'Home') {
|
||||||
|
nextIndex = 0;
|
||||||
|
} else if (key === 'End') {
|
||||||
|
nextIndex = navigableRows.length - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextIndex === -1 || nextIndex >= navigableRows.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const targetRow = navigableRows[nextIndex];
|
||||||
|
if (!targetRow) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
onFocusedRowChange?.(targetRow.key);
|
||||||
|
onEntrySelection?.(targetRow.key, {
|
||||||
|
shiftKey,
|
||||||
|
preventDefault: () => {},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[
|
||||||
|
focusedRowKey,
|
||||||
|
getEntryByKey,
|
||||||
|
handleDocumentActivate,
|
||||||
|
navigableRowKeys,
|
||||||
|
navigableRows,
|
||||||
|
onEntrySelection,
|
||||||
|
onFocusedRowChange,
|
||||||
|
onFolderSelect,
|
||||||
|
selectedEntries,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
const isListView = viewMode === 'list';
|
const isListView = viewMode === 'list';
|
||||||
const gridIconSize = DEFAULT_GRID_ICON_SIZE;
|
const gridIconSize = DEFAULT_GRID_ICON_SIZE;
|
||||||
const handleSetViewMode = useCallback(
|
const handleSetViewMode = useCallback(
|
||||||
@@ -482,16 +629,14 @@ const DocumentsPanel = ({
|
|||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
onFocus={(event) => {
|
onFocus={(event) => {
|
||||||
if (event.target === scrollRef.current) {
|
if (event.target === scrollRef.current) {
|
||||||
onDocumentListFocus?.();
|
handlePanelFocus();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onKeyDown={(event) => {
|
onKeyDown={(event) => {
|
||||||
if (event.target !== scrollRef.current) {
|
if (event.target !== scrollRef.current) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (onDocumentListKeyDown) {
|
handlePanelKeyDown(event);
|
||||||
onDocumentListKeyDown(event);
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
if (event.target === event.currentTarget) {
|
if (event.target === event.currentTarget) {
|
||||||
|
|||||||
Reference in New Issue
Block a user