Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple marker selection via BoundsDriftMarker and SemanticMarkers #588

Merged
merged 58 commits into from
Dec 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
36e3809
multi-selecting markers
moontrip Sep 20, 2023
8762a17
Merge branch 'main' into 431-multi-select-marker
moontrip Sep 20, 2023
107ff4e
map panning behavior, refactoring, etc
moontrip Sep 27, 2023
bc2072e
Merge branch 'main' and resolve conflicts
moontrip Sep 27, 2023
a6eff5b
geohash level-based, not zoom level-based
moontrip Oct 3, 2023
4598db1
Merge branch 'main' into 431-multi-select-marker
moontrip Oct 3, 2023
ba54206
remove unnecessary useState
moontrip Oct 3, 2023
de58292
testing multiple markers selection with SAM
moontrip Oct 4, 2023
3c1817a
Merge branch 'main' into 431-multi-select-marker
moontrip Oct 16, 2023
70d404d
Merge branch 'main' into multiple-marker-selection-test-with-SAM
moontrip Oct 16, 2023
b967b13
Merge branch '431-multi-select-marker' into multiple-marker-selection…
moontrip Oct 16, 2023
f2e906d
address feedbacks - bubble marker etc
moontrip Oct 17, 2023
e2a50e1
Merge branch '431-multi-select-marker' into multiple-marker-selection…
moontrip Oct 17, 2023
7dbb296
add bubble marker case
moontrip Oct 17, 2023
f039262
Merge branch 'main' into 431-multi-select-marker
moontrip Oct 17, 2023
c4dd96c
Merge branch '431-multi-select-marker' into multiple-marker-selection…
moontrip Oct 17, 2023
d935c70
commented out data for markerData prop
moontrip Oct 18, 2023
985ae32
Merge branch '431-multi-select-marker' into multiple-marker-selection…
moontrip Oct 18, 2023
3e235e5
Merge branch 'main' into 431-multi-select-marker
moontrip Oct 18, 2023
ab96bed
Merge branch '431-multi-select-marker' into multiple-marker-selection…
moontrip Oct 18, 2023
a8243c6
Merge branch 'main', resolve conflicts, implement marker selection
moontrip Nov 1, 2023
894b15c
Merge pull request #581 from VEuPathDB/multiple-marker-selection-bran…
moontrip Nov 1, 2023
a92d7ab
Merge branch 'main' into multiple-marker-selection-test-with-SAM
moontrip Nov 1, 2023
2c52bbd
stripped markerDataProps and pan/zoom logic which needs replacing
bobular Nov 2, 2023
2ed061f
move some logic to SemanticMarkers - still not working
bobular Nov 2, 2023
d9285fc
basic pan now working
bobular Nov 2, 2023
928572d
remove some props
bobular Nov 2, 2023
d0c04cf
more react-like highlighting
bobular Nov 2, 2023
27c2eb0
added effect to remove off-screen or wrong-zoom level selectedMarkers
bobular Nov 2, 2023
69d0db9
fix errors and enable multi-selection marker for SAM
moontrip Nov 3, 2023
4f3c0ee
Merge pull request #589 from VEuPathDB/fix-errors
moontrip Nov 3, 2023
5c5e106
address popup positions
moontrip Nov 8, 2023
ba81346
remove unnecessary comments
moontrip Nov 8, 2023
a0cb77c
Merge branch 'main' into multiple-marker-selection-test-with-SAM
bobular Nov 8, 2023
7c8d796
simple merge conflict resolution
bobular Nov 8, 2023
ecb5795
Merge remote-tracking branch 'origin/multiple-marker-selection-simpli…
bobular Nov 8, 2023
43792d2
address marker double-click
moontrip Nov 9, 2023
8585d03
Merge pull request #610 from VEuPathDB/address-popup-location-issue
moontrip Nov 9, 2023
b7fc15e
Merge branch 'multiple-marker-selection-simplified' into address-mark…
moontrip Nov 9, 2023
bccb490
Merge pull request #615 from VEuPathDB/address-marker-double-click
moontrip Nov 9, 2023
d5a8369
disable multiple markers for merge
bobular Nov 10, 2023
6d08167
Merge remote-tracking branch 'origin/main' into multiple-marker-selec…
bobular Nov 10, 2023
bab05f5
Merge branch 'main' into multiple-marker-selection-simplified
moontrip Nov 13, 2023
4ca816b
marker popup highlight
moontrip Nov 15, 2023
581f16f
Merge branch 'main' into map-marker-popup-highlight
moontrip Nov 15, 2023
c3d4764
Merge remote-tracking branch 'origin/main' into multiple-marker-selec…
bobular Nov 17, 2023
9a745bd
Merge remote-tracking branch 'origin/main' into map-marker-popup-high…
bobular Nov 17, 2023
be47073
Merge branch 'multiple-marker-selection-simplified' of https://github…
moontrip Nov 18, 2023
f6d730a
Merge branch 'multiple-marker-selection-simplified' of https://github…
moontrip Nov 18, 2023
059ebae
Merge branch 'map-marker-popup-highlight' of https://github.com/VEuPa…
moontrip Nov 18, 2023
2360aa6
fix instability due to empty array reference
bobular Nov 18, 2023
ae06ea1
Merge branch 'multiple-marker-selection-simplified' into map-marker-p…
bobular Nov 18, 2023
87c1283
Merge pull request #644 from VEuPathDB/map-marker-popup-highlight
moontrip Nov 18, 2023
1cc3c06
Merge branch 'main' into multiple-marker-selection-simplified
moontrip Nov 28, 2023
54984a0
a solution to prevent single click while double clicking
moontrip Nov 29, 2023
8a219f6
simplify and cleanup
moontrip Nov 29, 2023
64596db
Merge pull request #683 from VEuPathDB/prevent-single-click-when-doub…
moontrip Nov 29, 2023
e23b37e
resolved minor conflicts
bobular Dec 2, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 30 additions & 29 deletions packages/libs/components/public/css/vb-popbio-maps.css
Original file line number Diff line number Diff line change
Expand Up @@ -95,16 +95,10 @@ body {
text-align: left;
line-height: 15px;
color: #555555;
/* DKDK changed margin-bottom from 5 to 0 */
margin-bottom: 0px !important;
border-radius: 0 !important;
/* DKDK change these for mapveu v2
width : 280px;
min-height : 300px; */
width: 250px;
min-height: 210px;
/* DKDK combine with other CSS defined */
/* padding: 6px 8px 6px 8px; */
padding: 0px 0px 0px 0px;
background: white;
/*max-width : 230px;
Expand All @@ -128,17 +122,14 @@ body {
min-width: 50px;
text-align: right;
font-weight: 600;
/*DKDK VB-8650*/
width: 27%;
}

.summ-by-value {
float: left;
/*DKDK VB-8650 */
/*width: 79%;*/
}

/*DKDK VB-8650 add below class to handle active-legend and external link separately*/
/* VB-8650 add below class to handle active-legend and external link separately*/
.active-legend-area {
float: left;
width: 73%;
Expand All @@ -150,18 +141,11 @@ body {

.legend {
position: absolute;
/* DKDK set bottom to be smaller
bottom: 40px; */
bottom: 10px;
right: 0px;
z-index: 10000;
}

/* .legend > div {
/* DKDK change padding from 0 8px to 0 4px
padding: 0 2px;
} */

.legend p {
font-size: smaller;
word-wrap: break-word;
Expand Down Expand Up @@ -212,7 +196,7 @@ body {

.mapboxbottom .overlaybottom {
position: absolute;
/*DKDK VB-8707 change bottom from 3 to 25 px*/
/* VB-8707 change bottom from 3 to 25 px*/
bottom: 25px;
left: 40%;
width: 30%;
Expand Down Expand Up @@ -278,12 +262,29 @@ path,
text-shadow: -1px -1px 0 #ffffff, 1px -1px 0 #ffffff, -1px 1px 0 #ffffff,
1px 1px 0 #ffffff;
}
.highlight-marker {
background-clip: padding-box;
border-radius: 30px;
box-shadow: 0px 0px 0px 4px rgba(255, 255, 0, 1);

/* donut and bubble markers highlight */
.highlight-marker.donut-marker,
.highlight-marker.bubble-marker {
/* background-clip: padding-box; */
border-radius: 50%;
/* add inset to reduce a gap between the element and the box-shadow */
box-shadow: 2.5px 2.5px 0px 6px rgba(255, 255, 0, 1),
2.5px 2.5px 0px 2px rgba(255, 255, 0, 1) inset;
z-index: 9999 !important;
}

/* chart marker highlight */
.highlight-marker.chart-marker {
/* background-clip: padding-box; */
/* the rounded corner of the chart marker has 10px in radius */
border-radius: 10px;
/* add inset to reduce a gap between the element and the box-shadow */
box-shadow: -1px -0.5px 0px 6px rgba(255, 255, 0, 1),
-1px -0.5px 0px 2px rgba(255, 255, 0, 1) inset;
z-index: 9999 !important;
}

.top-marker {
z-index: 3100 !important;
}
Expand Down Expand Up @@ -449,7 +450,7 @@ path,
fill: none;
stroke: #000000;
stroke-width: 1px;
/* DKDK temporarily block below */
/* temporarily block below */
/* color-rendering : optimizeQuality !important; */
shape-rendering: crispEdges !important;
text-rendering: geometricPrecision !important;
Expand Down Expand Up @@ -541,7 +542,7 @@ html {
border-radius: 0px;
box-shadow: none;
}
/* x-jsrender active terms DKDK VB-8650 */
/* x-jsrender active terms VB-8650 */
.active-term,
.active-legend,
.active-others,
Expand Down Expand Up @@ -741,13 +742,13 @@ div.hint div {
text-overflow: ellipsis;
}

/* DKDK VB-8650 */
/* VB-8650 */
.active-legend,
.insertExternalLinkLegend {
line-height: 17px;
}

/* DKDK VB-8650 */
/* VB-8650 */
/* .active-legend i, #Other-Terms-List i{ */
.active-legend .summ-by-value .summ-by-value-item,
.insertExternalLinkLegend .summ-by-value .summ-by-value-item,
Expand Down Expand Up @@ -1079,7 +1080,7 @@ div.hint div {
text-align: center;
}

/*DKDK add vectorbase-icon*/
/* add vectorbase-icon*/
#vectorbase-icon {
height: 40px;
font-size: 12pt;
Expand Down Expand Up @@ -1274,7 +1275,7 @@ div.hint div {
text-align: center;
}

/* DKDK VB-8112 disabling cursor change on pie chart legend */
/* VB-8112 disabling cursor change on pie chart legend */
.nvd3 .nv-legend .nv-series {
cursor: default !important;
}
Expand All @@ -1291,7 +1292,7 @@ div.hint div {
cursor: ew-resize;
}

/* DKDK VB-8650 related CSS */
/* VB-8650 related CSS */
/*.insertExternalLinkLegend .insertExternalLink {
float: initial;
}
Expand Down
73 changes: 59 additions & 14 deletions packages/libs/components/src/map/BoundsDriftMarker.tsx
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
import { useMap, Popup } from 'react-leaflet';
import { useRef, useEffect } from 'react';
import { useRef, useEffect, useState } from 'react';
// use new ReactLeafletDriftMarker instead of DriftMarker
import ReactLeafletDriftMarker from 'react-leaflet-drift-marker';
import { MarkerProps, Bounds } from './Types';
import L, { LeafletMouseEvent, LatLngBounds } from 'leaflet';

import { debounce } from 'lodash';

export interface BoundsDriftMarkerProps extends MarkerProps {
bounds: Bounds;
duration: number;
// A class to add to the popup element
popupClass?: string;
// selectedMarkers state
selectedMarkers?: string[];
// selectedMarkers setState
setSelectedMarkers?: React.Dispatch<React.SetStateAction<string[]>>;
}

/**
Expand Down Expand Up @@ -39,8 +45,12 @@ export default function BoundsDriftMarker({
popupContent,
popupClass,
zIndexOffset,
selectedMarkers,
setSelectedMarkers,
...props
}: BoundsDriftMarkerProps) {
const map = useMap();

const boundingBox = new LatLngBounds([
[bounds.southWest.lat, bounds.southWest.lng],
[bounds.northEast.lat, bounds.northEast.lng],
Expand Down Expand Up @@ -171,20 +181,20 @@ export default function BoundsDriftMarker({
markerRef.current._icon.firstChild.getBoundingClientRect();
const anchorRect = popupRef.current._tipContainer.getBoundingClientRect();
const { height: anchorHeight, width: anchorWidth } = anchorRect;
const popupRect = popupRef.current._container.getBoundingClientRect();

/**
* Within each conditional block, we will:
* 1. check the position of the gray box vs the marker to determine which element the popup should
* be anchored to
* 2. set the popupRef's offset accordingly (with some fuzzy calculations)
*/
// with the marker clicl event for selectedMarkers, popupRef is not used as it changes by click event
if (orientation === 'down') {
const yOffset =
(markerIconRect.bottom > grayBoundsRect.bottom
? markerIconRect.bottom
: grayBoundsRect.bottom) -
popupRect.top +
markerRect.bottom +
anchorHeight -
FINE_ADJUSTMENT / 2;
popupRef.current.options.offset = [FINE_ADJUSTMENT / 2, yOffset];
Expand All @@ -194,14 +204,14 @@ export default function BoundsDriftMarker({
? markerIconRect.right
: grayBoundsRect.right) +
anchorWidth / 2 -
popupRect.left;
markerRect.right;
popupRef.current.options.offset = [xOffset, DEFAULT_OFFSET[1]];
} else if (orientation === 'left') {
const xOffset =
(markerRect.left < grayBoundsRect.left
? markerRect.left
: grayBoundsRect.left) -
popupRect.right -
markerRect.left -
anchorWidth / 2;
popupRef.current.options.offset = [xOffset, DEFAULT_OFFSET[1]];
} else {
Expand All @@ -210,7 +220,7 @@ export default function BoundsDriftMarker({
? markerRect.top
: grayBoundsRect.top) -
FINE_ADJUSTMENT / 2 -
popupRect.bottom;
markerRect.y;
popupRef.current.options.offset = [FINE_ADJUSTMENT / 2, yOffset];
}
};
Expand Down Expand Up @@ -270,12 +280,30 @@ export default function BoundsDriftMarker({
e.target.closePopup();
};

// add click events for highlighting markers
const handleClick = (e: LeafletMouseEvent) => {
// Sometimes clicking throws off the popup's orientation, so reorient it
orientPopup(popupOrientationRef.current);
// Default popup behavior is to open on marker click
// Prevent by immediately closing it
e.target.closePopup();
// check the number of mouse click and enable function for single click only
if (e.originalEvent.detail === 1) {
if (setSelectedMarkers) {
if (selectedMarkers?.find((id) => id === props.id)) {
setSelectedMarkers((prevSelectedMarkers: string[]) =>
prevSelectedMarkers.filter((id: string) => id !== props.id)
);
} else {
// select
setSelectedMarkers((prevSelectedMarkers: string[]) => [
...prevSelectedMarkers,
props.id,
]);
}
}

// Sometimes clicking throws off the popup's orientation, so reorient it
orientPopup(popupOrientationRef.current);
// Default popup behavior is to open on marker click
// Prevent by immediately closing it
e.target.closePopup();
}
};

const handleDoubleClick = () => {
Expand All @@ -284,6 +312,22 @@ export default function BoundsDriftMarker({
}
};

// debounce single click to be prevented when double clicking marker
const debounceSingleClick = debounce(handleClick, 300);

// set this marker as highlighted
if (icon && selectedMarkers?.find((id) => id === props.id))
icon.options.className += ' highlight-marker';

// set this marker's popup as highlighted
if (popupContent && popupRef.current && popupRef.current._container) {
if (selectedMarkers?.find((id) => id === props.id)) {
popupRef.current._container.classList.add('marker-popup-highlight');
} else {
popupRef.current._container.classList.remove('marker-popup-highlight');
}
}

// DriftMarker misbehaves if icon=undefined is provided
// is this the most elegant way?
const optionalIconProp = icon ? { icon } : {};
Expand All @@ -296,9 +340,10 @@ export default function BoundsDriftMarker({
position={position}
// new way to handle mouse events
eventHandlers={{
click: (e: LeafletMouseEvent) => handleClick(e),
mouseover: (e: LeafletMouseEvent) => handleMouseOver(e),
mouseout: (e: LeafletMouseEvent) => handleMouseOut(e),
// debounce single click to be prevented when double clicking marker
click: debounceSingleClick,
mouseover: handleMouseOver,
mouseout: handleMouseOut,
dblclick: handleDoubleClick,
}}
zIndexOffset={zIndexOffset}
Expand Down
10 changes: 8 additions & 2 deletions packages/libs/components/src/map/BubbleMarker.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// import React from 'react';
import L from 'leaflet';
import BoundsDriftMarker, { BoundsDriftMarkerProps } from './BoundsDriftMarker';

Expand Down Expand Up @@ -26,11 +25,15 @@ export interface BubbleMarkerProps extends BoundsDriftMarkerProps {
* this is a SVG bubble marker icon
*/
export default function BubbleMarker(props: BubbleMarkerProps) {
const selectedMarkers = props.selectedMarkers;
const setSelectedMarkers = props.setSelectedMarkers;

const { html: svgHTML, diameter: size } = bubbleMarkerSVGIcon(props);

// set icon as divIcon
const SVGBubbleIcon = L.divIcon({
className: 'leaflet-canvas-icon', // may need to change this className but just leave it as it for now
className:
'leaflet-canvas-icon ' + 'marker-id-' + props.id + ' bubble-marker',
iconSize: new L.Point(size, size), // this will make icon to cover up SVG area!
iconAnchor: new L.Point(size / 2, size / 2), // location of topleft corner: this is used for centering of the icon like transform/translate in CSS
html: svgHTML, // divIcon HTML svg code generated above
Expand Down Expand Up @@ -74,6 +77,9 @@ export default function BubbleMarker(props: BubbleMarkerProps) {
},
}}
showPopup={props.showPopup}
// pass selectedMarkers state and setState
selectedMarkers={selectedMarkers}
setSelectedMarkers={setSelectedMarkers}
/>
);
}
Expand Down
11 changes: 9 additions & 2 deletions packages/libs/components/src/map/ChartMarker.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import React from 'react';
import L from 'leaflet';

import BoundsDriftMarker, { BoundsDriftMarkerProps } from './BoundsDriftMarker';
Expand Down Expand Up @@ -46,11 +45,16 @@ export interface ChartMarkerProps
* - accordingly icon size could be reduced
*/
export default function ChartMarker(props: ChartMarkerProps) {
const selectedMarkers = props.selectedMarkers;
const setSelectedMarkers = props.setSelectedMarkers;

const { html: svgHTML, size, sumValuesString } = chartMarkerSVGIcon(props);

// set icon
let HistogramIcon: any = L.divIcon({
className: 'leaflet-canvas-icon',
// add class, highlight-chartmarker, for panning
className:
'leaflet-canvas-icon ' + 'marker-id-' + props.id + ' chart-marker',
iconSize: new L.Point(size, size),
iconAnchor: new L.Point(size / 2, size / 2), // location of topleft corner: this is used for centering of the icon like transform/translate in CSS
html: svgHTML, // divIcon HTML svg code generated above
Expand Down Expand Up @@ -116,6 +120,9 @@ export default function ChartMarker(props: ChartMarkerProps) {
}}
showPopup={props.showPopup}
popupClass="histogram-popup"
// pass // selectedMarkers state and setState
selectedMarkers={selectedMarkers}
setSelectedMarkers={setSelectedMarkers}
/>
);
}
Expand Down
Loading
Loading