Fix click to show document issue. Table doesn't auto-select first document anymore. (#1864)

This commit is contained in:
Laurent Nguyen 2024-06-07 16:28:08 +02:00 committed by GitHub
parent 416743c548
commit 06d4829422
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 81 additions and 76 deletions

View File

@ -86,6 +86,9 @@ export class DocumentsTabV2 extends TabsBase {
}
}
// Use this value to initialize the very time the component is rendered
const RESET_INDEX = -1;
const filterButtonStyle: CSSProperties = {
marginLeft: 8,
};
@ -465,7 +468,7 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
const [selectedDocumentContentBaseline, setSelectedDocumentContentBaseline] = useState<string>(undefined);
// Table user clicked on this row
const [clickedRow, setClickedRow] = useState<TableRowId>(undefined);
const [clickedRowIndex, setClickedRowIndex] = useState<number>(RESET_INDEX);
// Table multiple selection
const [selectedRows, setSelectedRows] = React.useState<Set<TableRowId>>(() => new Set<TableRowId>([0]));
@ -490,6 +493,23 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
}
}, [isFilterFocused]);
// Clicked row must be defined
useEffect(() => {
if (documentIds.length > 0) {
let currentClickedRowIndex = clickedRowIndex;
if (
(currentClickedRowIndex === RESET_INDEX &&
editorState === ViewModels.DocumentExplorerState.noDocumentSelected) ||
currentClickedRowIndex > documentIds.length - 1
) {
// reset clicked row or the current clicked row is out of bounds
currentClickedRowIndex = 0;
setSelectedRows(new Set([0]));
onDocumentClicked(currentClickedRowIndex, documentIds);
}
}
}, [documentIds, clickedRowIndex, editorState]);
let lastFilterContents = ['WHERE c.id = "foo"', "ORDER BY c._ts DESC", 'WHERE c.id = "foo" ORDER BY c._ts DESC'];
const applyFilterButton = {
@ -550,7 +570,7 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
if (!documentsIterator) {
try {
refreshDocumentsGrid();
refreshDocumentsGrid(false);
} catch (error) {
if (onLoadStartKey !== null && onLoadStartKey !== undefined) {
TelemetryProcessor.traceFailure(
@ -657,7 +677,7 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
setSelectedDocumentContent(defaultDocument);
setSelectedDocumentContentBaseline(defaultDocument);
setSelectedRows(new Set());
setClickedRow(undefined);
setClickedRowIndex(undefined);
setEditorState(ViewModels.DocumentExplorerState.newDocumentValid);
};
@ -673,8 +693,10 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
return createDocument(_collection, document)
.then(
(savedDocument: DataModels.DocumentId) => {
// TODO: Reuse initDocumentEditor() to remove code duplication
const value: string = renderObjectForEditor(savedDocument || {}, null, 4);
setSelectedDocumentContentBaseline(value);
setSelectedDocumentContent(value);
setInitialDocumentContent(value);
const partitionKeyValueArray: PartitionKey[] = extractPartitionKeyValues(
savedDocument,
@ -738,7 +760,7 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
partitionKey as PartitionKeyDefinition,
);
const selectedDocumentId = documentIds[clickedRow as number];
const selectedDocumentId = documentIds[clickedRowIndex as number];
selectedDocumentId.partitionKeyValue = partitionKeyValueArray;
onExecutionErrorChange(false);
@ -786,7 +808,15 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
},
)
.finally(() => setIsExecuting(false));
}, [onExecutionErrorChange, tabTitle, selectedDocumentContent, _collection, partitionKey, documentIds, clickedRow]);
}, [
onExecutionErrorChange,
tabTitle,
selectedDocumentContent,
_collection,
partitionKey,
documentIds,
clickedRowIndex,
]);
const onRevertExistingDocumentClick = useCallback((): void => {
setSelectedDocumentContentBaseline(initialDocumentContent);
@ -850,7 +880,7 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
setDocumentIds(newDocumentIds);
setSelectedDocumentContent(undefined);
setClickedRow(undefined);
setClickedRowIndex(undefined);
setSelectedRows(new Set());
setEditorState(ViewModels.DocumentExplorerState.noDocumentSelected);
useDialog
@ -974,8 +1004,27 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
return true;
};
const updateDocumentIds = (newDocumentsIds: DocumentId[]): void => {
setDocumentIds(newDocumentsIds);
if (onLoadStartKey !== null && onLoadStartKey !== undefined) {
TelemetryProcessor.traceSuccess(
Action.Tab,
{
databaseName: _collection.databaseId,
collectionName: _collection.id(),
dataExplorerArea: Constants.Areas.Tab,
tabTitle,
},
onLoadStartKey,
);
setOnLoadStartKey(undefined);
}
};
let loadNextPage = useCallback(
(iterator: QueryIterator<ItemDefinition & Resource>, applyFilterButtonClicked?: boolean): Promise<unknown> => {
(iterator: QueryIterator<ItemDefinition & Resource>, applyFilterButtonClicked: boolean): Promise<unknown> => {
setIsExecuting(true);
onExecutionErrorChange(false);
let automaticallyCancelQueryAfterTimeout: boolean;
@ -1028,21 +1077,7 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
});
const merged = currentDocuments.concat(nextDocumentIds);
setDocumentIds(merged);
if (onLoadStartKey !== null && onLoadStartKey !== undefined) {
TelemetryProcessor.traceSuccess(
Action.Tab,
{
databaseName: _collection.databaseId,
collectionName: _collection.id(),
dataExplorerArea: Constants.Areas.Tab,
tabTitle,
},
onLoadStartKey,
);
setOnLoadStartKey(undefined);
}
updateDocumentIds(merged);
},
(error) => {
onExecutionErrorChange(true);
@ -1112,7 +1147,7 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
const onLoadMoreKeyInput: KeyboardEventHandler<HTMLAnchorElement> = (event) => {
if (event.key === " " || event.key === "Enter") {
const focusElement = event.target as HTMLElement;
loadNextPage(documentsIterator.iterator);
loadNextPage(documentsIterator.iterator, false);
focusElement && focusElement.focus();
event.stopPropagation();
event.preventDefault();
@ -1158,10 +1193,10 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
* Document has been clicked on in table
* @param tabRowId
*/
const onDocumentClicked = (tabRowId: TableRowId) => {
const onDocumentClicked = (tabRowId: TableRowId, currentDocumentIds: DocumentId[]) => {
const index = tabRowId as number;
setClickedRow(index);
loadDocument(documentIds[index]);
setClickedRowIndex(index);
loadDocument(currentDocumentIds[index]);
};
let loadDocument = (documentId: DocumentId) =>
@ -1267,13 +1302,13 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
confirmDiscardingChange(() => {
if (selectedRows.size === 0) {
setSelectedDocumentContent(undefined);
setClickedRow(undefined);
setClickedRowIndex(undefined);
setEditorState(ViewModels.DocumentExplorerState.noDocumentSelected);
}
// Find if clickedRow is in selectedRows.If not, clear clickedRow and content
if (clickedRow !== undefined && !selectedRows.has(clickedRow)) {
setClickedRow(undefined);
if (clickedRowIndex !== undefined && !selectedRows.has(clickedRowIndex)) {
setClickedRowIndex(undefined);
setSelectedDocumentContent(undefined);
setEditorState(ViewModels.DocumentExplorerState.noDocumentSelected);
}
@ -1281,6 +1316,7 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
// If only one selection, we consider as a click
if (selectedRows.size === 1) {
setEditorState(ViewModels.DocumentExplorerState.existingDocumentNoEdits);
onDocumentClicked(selectedRows.values().next().value, documentIds);
}
setSelectedRows(selectedRows);
@ -1441,6 +1477,8 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
const value: string = renderObjectForEditor(savedDocument || {}, null, 4);
setSelectedDocumentContentBaseline(value);
setSelectedDocumentContent(value);
setInitialDocumentContent(value);
setDocumentIds(ids);
setEditorState(ViewModels.DocumentExplorerState.existingDocumentNoEdits);
@ -1491,7 +1529,7 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
tabTitle,
});
const selectedDocumentId = documentIds[clickedRow as number];
const selectedDocumentId = documentIds[clickedRowIndex as number];
return MongoProxyClient.updateDocument(
_collection.databaseId,
_collection as ViewModels.Collection,
@ -1559,8 +1597,7 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
.then(
({ continuationToken: newContinuationToken, documents }) => {
setContinuationToken(newContinuationToken);
let currentDocuments = documentIds;
const currentDocumentsRids = currentDocuments.map((currentDocument) => currentDocument.rid);
const currentDocumentsRids = documentIds.map((currentDocument) => currentDocument.rid);
const nextDocumentIds = documents
.filter((d: { _rid: string }) => {
return currentDocumentsRids.indexOf(d._rid) < 0;
@ -1569,34 +1606,10 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
.map((rawDocument: any) => {
const partitionKeyValue = rawDocument._partitionKeyValue;
return newDocumentId(rawDocument, partitionKeyProperties, [partitionKeyValue]);
// return new DocumentId(this, rawDocument, [partitionKeyValue]);
});
const merged = currentDocuments.concat(nextDocumentIds);
setDocumentIds(merged);
currentDocuments = merged;
if (filterContent.length > 0 && currentDocuments.length > 0) {
currentDocuments[0].click();
} else {
setSelectedDocumentContent("");
setEditorState(ViewModels.DocumentExplorerState.noDocumentSelected);
}
if (_onLoadStartKey !== null && _onLoadStartKey !== undefined) {
TelemetryProcessor.traceSuccess(
Action.Tab,
{
databaseName: _collection.databaseId,
collectionName: _collection.id(),
dataExplorerArea: Constants.Areas.Tab,
tabTitle,
},
_onLoadStartKey,
);
setOnLoadStartKey(undefined);
}
const merged = documentIds.concat(nextDocumentIds);
updateDocumentIds(merged);
},
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(error: any) => {
@ -1624,7 +1637,7 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
// ***************** Mongo ***************************
const refreshDocumentsGrid = useCallback(
async (applyFilterButtonPressed?: boolean): Promise<void> => {
(applyFilterButtonPressed: boolean): void => {
// clear documents grid
setDocumentIds([]);
setContinuationToken(undefined); // For mongo
@ -1638,6 +1651,13 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
// collapse filter
setAppliedFilter(filterContent);
setIsFilterExpanded(false);
// If apply filter is pressed, reset current selected document
if (applyFilterButtonPressed) {
setClickedRowIndex(RESET_INDEX);
setEditorState(ViewModels.DocumentExplorerState.noDocumentSelected);
setSelectedDocumentContent(undefined);
}
} catch (error) {
console.error(error);
useDialog.getState().showOkModalDialog("Refresh documents grid failed", getErrorMessage(error));
@ -1774,7 +1794,7 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
>
<DocumentsTableComponent
items={tableItems}
onItemClicked={onDocumentClicked}
onItemClicked={(index) => onDocumentClicked(index, documentIds)}
onSelectedRowsChange={onSelectedRowsChange}
selectedRows={selectedRows}
size={tableContainerSizePx}

View File

@ -25,7 +25,7 @@ import {
import { NormalizedEventKey } from "Common/Constants";
import { selectionHelper } from "Explorer/Tabs/DocumentsTabV2/SelectionHelper";
import { isEnvironmentCtrlPressed, isEnvironmentShiftPressed } from "Utils/KeyboardUtils";
import React, { useCallback, useEffect, useMemo } from "react";
import React, { useCallback, useMemo } from "react";
import { FixedSizeList as List, ListChildComponentProps } from "react-window";
export type DocumentsTableComponentItem = {
@ -59,7 +59,6 @@ interface ReactWindowRenderFnProps extends ListChildComponentProps {
export const DocumentsTableComponent: React.FC<IDocumentsTableComponentProps> = ({
items,
onItemClicked,
onSelectedRowsChange,
selectedRows,
style,
@ -67,8 +66,6 @@ export const DocumentsTableComponent: React.FC<IDocumentsTableComponentProps> =
columnHeaders,
isSelectionDisabled,
}: IDocumentsTableComponentProps) => {
const [activeItemIndex, setActiveItemIndex] = React.useState<number>(undefined);
const initialSizingOptions: TableColumnSizingOptions = {
id: {
idealWidth: 280,
@ -250,18 +247,6 @@ export const DocumentsTableComponent: React.FC<IDocumentsTableComponentProps> =
[toggleAllRows],
);
// Load document depending on selection
useEffect(() => {
if (selectedRows.size === 1 && items.length > 0) {
const newActiveItemIndex = selectedRows.values().next().value;
if (newActiveItemIndex !== activeItemIndex) {
onItemClicked(newActiveItemIndex);
setActiveItemIndex(newActiveItemIndex);
setSelectionStartIndex(newActiveItemIndex);
}
}
}, [selectedRows, items, activeItemIndex, onItemClicked]);
// Cell keyboard navigation
const keyboardNavAttr = useArrowNavigationGroup({ axis: "grid" });