Skip to content

Commit a047a51

Browse files
committed
Fixed coderabbit comments and removed the __temp_PK to identifier based of first column or rowdata
1 parent eddc9ce commit a047a51

File tree

1 file changed

+56
-24
lines changed

1 file changed

+56
-24
lines changed

web/pgadmin/tools/sqleditor/static/js/components/sections/GeometryViewer.jsx

Lines changed: 56 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
// This software is released under the PostgreSQL Licence
77
//
88
//////////////////////////////////////////////////////////////
9-
import React, { useEffect, useRef } from 'react';
9+
import React, { useEffect, useRef, useMemo } from 'react';
1010
import { styled } from '@mui/material/styles';
1111
import ReactDOMServer from 'react-dom/server';
1212
import _ from 'lodash';
@@ -49,6 +49,8 @@ const StyledBox = styled(Box)(({theme}) => ({
4949
},
5050
}));
5151

52+
const PK_COLUMN_NAMES = ['id', 'oid', 'ctid'];
53+
5254
function parseEwkbData(rows, column) {
5355
let key = column.key;
5456
const maxRenderByteLength = 20 * 1024 * 1024; //render geometry data up to 20MB
@@ -191,6 +193,33 @@ function parseData(rows, columns, column) {
191193
};
192194
}
193195

196+
// Find primary key column from columns array
197+
function findPkColumn(columns) {
198+
return columns.find(c => PK_COLUMN_NAMES.includes(c.name));
199+
}
200+
201+
// Get unique row identifier using PK column or first column
202+
function getRowIdentifier(row, pkColumn, columns) {
203+
if (pkColumn?.key && row[pkColumn.key] !== undefined) {
204+
return row[pkColumn.key];
205+
}
206+
const firstKey = columns[0]?.key;
207+
return firstKey && row[firstKey] !== undefined ? row[firstKey] : JSON.stringify(row);
208+
}
209+
210+
// Create Set of row identifiers
211+
function createIdentifierSet(rowData, pkColumn, columns) {
212+
return new Set(rowData.map(row => getRowIdentifier(row, pkColumn, columns)));
213+
}
214+
215+
// Match rows from previous selection to current rows
216+
function matchRowSelection(prevRowData, currentRows, pkColumn, columns) {
217+
if (prevRowData.length === 0) return [];
218+
219+
const prevIdSet = createIdentifierSet(prevRowData, pkColumn, columns);
220+
return currentRows.filter(row => prevIdSet.has(getRowIdentifier(row, pkColumn, columns)));
221+
}
222+
194223
function PopupTable({data}) {
195224

196225
return (
@@ -438,20 +467,22 @@ export function GeometryViewer({rows, columns, column}) {
438467
const contentRef = React.useRef();
439468
const queryToolCtx = React.useContext(QueryToolContext);
440469

441-
// Track previous state to detect changes
470+
// Track previous column state AND selected row data
442471
const prevStateRef = React.useRef({
443472
columnKey: null,
444473
columnNames: null,
445-
selectedRowPKs: [],
474+
selectedRowData: [],
446475
});
447476

448477
const [mapKey, setMapKey] = React.useState(0);
449-
const currentColumnKey = column?.key;
478+
const currentColumnKey = useMemo(() => column?.key, [column]);
450479
const currentColumnNames = React.useMemo(
451480
() => columns.map(c => c.key).sort().join(','),
452481
[columns]
453482
);
454483

484+
const pkColumn = useMemo(() => findPkColumn(columns), [columns]);
485+
455486
// Detect when to clear, filter, or re-render the map based on changes in geometry column, columns list, or rows
456487
useEffect(() => {
457488
const prevState = prevStateRef.current;
@@ -461,7 +492,7 @@ export function GeometryViewer({rows, columns, column}) {
461492
prevStateRef.current = {
462493
columnKey: null,
463494
columnNames: null,
464-
selectedRowPKs: [],
495+
selectedRowData: [],
465496
};
466497
return;
467498
}
@@ -472,38 +503,39 @@ export function GeometryViewer({rows, columns, column}) {
472503
prevStateRef.current = {
473504
columnKey: currentColumnKey,
474505
columnNames: currentColumnNames,
475-
selectedRowPKs: [],
506+
selectedRowData: [],
476507
};
477508
return;
478509
}
479510

480511
if (currentColumnKey === prevState.columnKey &&
481512
currentColumnNames === prevState.columnNames &&
482513
rows.length > 0) {
483-
484-
// If user previously selected specific rows, filter them from new data
485-
if (prevState.selectedRowPKs.length > 0 && prevState.selectedRowPKs.length < rows.length) {
486-
const newSelectedPKs = rows
487-
.filter(row => prevState.selectedRowPKs.includes(row.__temp_PK))
488-
.map(row => row.__temp_PK);
489-
490-
prevStateRef.current.selectedRowPKs = newSelectedPKs.length > 0 ? newSelectedPKs : rows.map(r => r.__temp_PK);
514+
let newSelectedRowData;
515+
if (prevState.selectedRowData.length === 0) {
516+
// No previous selection, show all rows
517+
newSelectedRowData = rows;
518+
} else if (prevState.selectedRowData.length < rows.length) {
519+
const matched = matchRowSelection(prevState.selectedRowData, rows, pkColumn, columns);
520+
newSelectedRowData = matched.length > 0 ? matched : rows;
491521
} else {
492-
// All rows are displayed
493-
const allPKs = rows.map(r => r.__temp_PK);
494-
prevStateRef.current.selectedRowPKs = allPKs;
522+
newSelectedRowData = rows;
495523
}
524+
prevStateRef.current.selectedRowData = newSelectedRowData;
496525
}
497-
}, [currentColumnKey, currentColumnNames, rows]);
526+
}, [currentColumnKey, currentColumnNames, rows, pkColumn, columns]);
498527

528+
// Get rows to display based on selection
499529
const displayRows = React.useMemo(() => {
500530
if (!currentColumnKey || rows.length === 0) return [];
531+
const prevState = prevStateRef.current;
532+
if (currentColumnKey !== prevState.columnKey || currentColumnNames !== prevState.columnNames) {
533+
return rows;
534+
}
501535

502-
const selectedPKs = prevStateRef.current.selectedRowPKs;
503-
return selectedPKs.length > 0 && selectedPKs.length < rows.length
504-
? rows.filter(row => selectedPKs.includes(row.__temp_PK))
505-
: rows;
506-
}, [rows, currentColumnKey]);
536+
const selected = prevState.selectedRowData;
537+
return selected.length > 0 && selected.length < rows.length ? selected : rows;
538+
}, [rows, currentColumnKey, currentColumnNames]);
507539

508540
// Parse geometry data only when needed
509541
const data = React.useMemo(() => {
@@ -537,7 +569,7 @@ export function GeometryViewer({rows, columns, column}) {
537569
};
538570
}, [queryToolCtx]);
539571

540-
// Dyanmic CRS is not supported. Use srid and mapKey as key and recreate the map on change
572+
// Dynamic CRS is not supported. Use srid and mapKey as key and recreate the map on change
541573
return (
542574
<StyledBox ref={contentRef} width="100%" height="100%" key={`${data.selectedSRID}-${mapKey}`}>
543575
<MapContainer

0 commit comments

Comments
 (0)