Skip to content

Commit 217771f

Browse files
committed
Fixed review comments
1. Used hash function in place of JSON.stringify(row) 2. Storing row identifiers in place of complete row object. 3. Removed Leaflet's infoControl and added a react div
1 parent bc672e2 commit 217771f

File tree

1 file changed

+62
-51
lines changed

1 file changed

+62
-51
lines changed

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

Lines changed: 62 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { PANELS } from '../QueryToolConstants';
2222
import { QueryToolContext } from '../QueryToolComponent';
2323

2424
const StyledBox = styled(Box)(({theme}) => ({
25+
position: 'relative',
2526
'& .GeometryViewer-mapContainer': {
2627
backgroundColor: theme.palette.background.default,
2728
height: '100%',
@@ -193,31 +194,40 @@ function parseData(rows, columns, column) {
193194
};
194195
}
195196

196-
// Find primary key column from columns array
197+
// Find primary key column i.e a column with unique values from columns array in Data Output tab
197198
function findPkColumn(columns) {
198199
return columns.find(c => PK_COLUMN_NAMES.includes(c.name));
199200
}
200201

202+
// Hash function for row objects
203+
function hashRow(row) {
204+
const str = Object.keys(row).sort().map(k => `${k}:${row[k]}`).join('|');
205+
let hash = 0;
206+
for (let i = 0; i < str.length; i++) {
207+
const char = str.charCodeAt(i);
208+
hash = ((hash << 5) - hash) + char;
209+
hash = hash & hash;
210+
}
211+
return `hash_${hash}`;
212+
}
213+
201214
// Get unique row identifier using PK column or first column
202215
function getRowIdentifier(row, pkColumn, columns) {
203216
if (pkColumn?.key && row[pkColumn.key] !== undefined) {
204217
return row[pkColumn.key];
205218
}
206219
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)));
220+
if (firstKey && row[firstKey] !== undefined) {
221+
return row[firstKey];
222+
}
223+
return hashRow(row);
213224
}
214225

215226
// Match rows from previous selection to current rows
216-
function matchRowSelection(prevRowData, currentRows, pkColumn, columns) {
217-
if (prevRowData.length === 0) return [];
227+
function matchRowSelection(prevIdentifiers, currentRows, pkColumn, columns) {
228+
if (prevIdentifiers.size === 0) return [];
218229

219-
const prevIdSet = createIdentifierSet(prevRowData, pkColumn, columns);
220-
return currentRows.filter(row => prevIdSet.has(getRowIdentifier(row, pkColumn, columns)));
230+
return currentRows.filter(row => prevIdentifiers.has(getRowIdentifier(row, pkColumn, columns)));
221231
}
222232

223233
function PopupTable({data}) {
@@ -314,41 +324,10 @@ GeoJsonLayer.propTypes = {
314324

315325
function TheMap({data}) {
316326
const mapObj = useMap();
317-
const infoControl = useRef(null);
318327
const resetLayersKey = useRef(0);
319328
const zoomControlWithHome = useRef(null);
320329
const homeCoordinates = useRef(null);
321330
useEffect(()=>{
322-
infoControl.current = Leaflet.control({position: 'topright'});
323-
infoControl.current.onAdd = function () {
324-
let ele = Leaflet.DomUtil.create('div', 'geometry-viewer-info-control');
325-
ele.innerHTML = data.infoList.join('<br />');
326-
// Style the parent control container after it's added to the map
327-
setTimeout(() => {
328-
let controlContainer = ele.closest('.leaflet-control');
329-
if(controlContainer) {
330-
controlContainer.style.cssText = `
331-
position: fixed;
332-
top: 70%;
333-
left: 50%;
334-
transform: translate(-50%, -50%);
335-
margin: 0;
336-
max-width: 80%;
337-
text-align: center;
338-
white-space: normal;
339-
word-wrap: break-word;
340-
background: none;
341-
box-shadow: none;
342-
border: none;
343-
font-size: 16px;
344-
`;
345-
}
346-
}, 0);
347-
return ele;
348-
};
349-
if(data.infoList.length > 0) {
350-
infoControl.current.addTo(mapObj);
351-
}
352331
resetLayersKey.current++;
353332

354333
zoomControlWithHome.current = Leaflet.control.zoom({
@@ -398,7 +377,6 @@ function TheMap({data}) {
398377
zoomControlWithHome.current.addTo(mapObj);
399378

400379
return ()=>{
401-
infoControl.current?.remove();
402380
zoomControlWithHome.current?.remove();
403381
};
404382
}, [data]);
@@ -409,6 +387,25 @@ function TheMap({data}) {
409387

410388
return (
411389
<>
390+
{data.infoList.length > 0 && (
391+
<div style={{
392+
position: 'absolute',
393+
top: '50%',
394+
left: '50%',
395+
transform: 'translate(-50%, -50%)',
396+
zIndex: 1000,
397+
maxWidth: '80%',
398+
textAlign: 'center',
399+
whiteSpace: 'normal',
400+
wordWrap: 'break-word',
401+
fontSize: '16px',
402+
pointerEvents: 'none',
403+
}}>
404+
{data.infoList.map((info, idx) => (
405+
<div key={idx}>{info}</div>
406+
))}
407+
</div>
408+
)}
412409
{data.selectedSRID === 4326 &&
413410
<LayersControl position="topright">
414411
<LayersControl.BaseLayer checked name={gettext('Empty')}>
@@ -492,7 +489,7 @@ export function GeometryViewer({rows, columns, column}) {
492489
const prevStateRef = React.useRef({
493490
columnKey: null,
494491
columnNames: null,
495-
selectedRowData: [],
492+
selectedRowIdentifiers: new Set(),
496493
});
497494

498495
const [mapKey, setMapKey] = React.useState(0);
@@ -513,7 +510,7 @@ export function GeometryViewer({rows, columns, column}) {
513510
prevStateRef.current = {
514511
columnKey: null,
515512
columnNames: null,
516-
selectedRowData: [],
513+
selectedRowIdentifiers: new Set(),
517514
};
518515
return;
519516
}
@@ -524,32 +521,46 @@ export function GeometryViewer({rows, columns, column}) {
524521
prevStateRef.current = {
525522
columnKey: currentColumnKey,
526523
columnNames: currentColumnNames,
527-
selectedRowData: rows,
524+
selectedRowIdentifiers: new Set(rows.map(r => getRowIdentifier(r, pkColumn, columns))),
528525
};
529526
return;
530527
}
531528

532529
if (currentColumnKey === prevState.columnKey &&
533530
currentColumnNames === prevState.columnNames &&
534531
rows.length > 0) {
535-
prevStateRef.current.selectedRowData = displayRows;
532+
prevStateRef.current.selectedRowIdentifiers = new Set(
533+
displayRows.map(r => getRowIdentifier(r, pkColumn, columns))
534+
);
536535
}
537536
}, [currentColumnKey, currentColumnNames, rows, pkColumn, columns]);
538537

539538
// Get rows to display based on selection
540539
const displayRows = React.useMemo(() => {
540+
// No geometry column selected or no rows available - nothing to display
541541
if (!currentColumnKey || rows.length === 0) return [];
542542
const prevState = prevStateRef.current;
543+
544+
// Column context changed (different geometry column or different query schema)
545+
// Show all new rows since previous selection is no longer valid
543546
if (currentColumnKey !== prevState.columnKey || currentColumnNames !== prevState.columnNames) {
544547
return rows;
545548
}
546549

547-
const prevSelected = prevState.selectedRowData;
548-
if (prevSelected.length === 0) return rows;
549-
if (prevSelected.length < rows.length) {
550-
const matched = matchRowSelection(prevSelected, rows, pkColumn, columns);
550+
const prevIdentifiers = prevState.selectedRowIdentifiers;
551+
// No previous selection recorded - show all rows
552+
if (prevIdentifiers.size === 0) return rows;
553+
554+
// Previous selection was a subset of total rows, meaning user had specific rows selected.
555+
// Try to match those previously selected rows in the new result set using stable
556+
// row identifiers (PK value, first column value, or hash fallback).
557+
// This handles the case where same query reruns with more/fewer rows
558+
if (prevIdentifiers.size < rows.length) {
559+
const matched = matchRowSelection(prevIdentifiers, rows, pkColumn, columns);
560+
// If matched rows found, show only those; otherwise fall back to all rows
551561
return matched.length > 0 ? matched : rows;
552562
}
563+
// Previous selection covered all rows (or same count) - show all current rows
553564
return rows;
554565
}, [rows, currentColumnKey, currentColumnNames, pkColumn, columns]);
555566

0 commit comments

Comments
 (0)