Skip to content

Commit 18c6727

Browse files
authored
Merge pull request #41 from UW-Macrostrat/styling
Clustering
2 parents 499c288 + 689e7c3 commit 18c6727

File tree

17 files changed

+1106
-223
lines changed

17 files changed

+1106
-223
lines changed

pages/+Page.client.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import { Image, Footer } from "./index";
2-
import "./main.sass";
2+
import styles from "./main.module.sass";
33
import "./main-page.styl";
44
import "@macrostrat/style-system";
5-
import h from "@macrostrat/hyper";
5+
import hyper from "@macrostrat/hyper";
66
import "@macrostrat/style-system";
77

8+
const h = hyper.styled(styles);
9+
810

911
export function Page() {
1012
return h("div", { className: "main-page" }, [

pages/checkin/index.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import h from "@macrostrat/hyper";
1+
import hyper from "@macrostrat/hyper";
22
import { LngLatCoords } from "@macrostrat/map-interface";
33
import { useEffect, useState, useRef } from 'react';
44
import 'mapbox-gl/dist/mapbox-gl.css';
55
import { BlankImage, imageExists, Footer, apiURL, apiURLOld, useRockdAPI } from "../index";
66
import { Icon } from "@blueprintjs/core";
7-
import "../main.sass";
7+
import styles from "../main.module.sass";
88
import { SETTINGS } from "@macrostrat-web/settings";
99
import { DarkModeButton } from "@macrostrat/ui-components";
1010
import "./main.sass";
@@ -14,6 +14,8 @@ import 'mapbox-gl/dist/mapbox-gl.css';
1414
import { MapPosition } from "@macrostrat/mapbox-utils";
1515
import { PanelCard } from "@macrostrat/map-interface";
1616

17+
const h = hyper.styled(styles);
18+
1719
export function Checkins({checkinID}) {
1820
const checkinData = useRockdAPI("protected/checkins?checkin_id=" + checkinID);
1921
const [overlayOpen, setOverlayOpen] = useState(false);
@@ -40,7 +42,7 @@ export function Checkins({checkinID}) {
4042
lng: checkin.lng
4143
}
4244

43-
let profile_pic = h(BlankImage, {src: apiURL + "protected/gravatar/" + checkin.person_id, className: "profile-pic"});
45+
let profile_pic = h(BlankImage, {src: apiURL + "protected/gravatar/" + checkin.person_id, className: "profile-picture"});
4446

4547
// format rating
4648
let ratingArr = [];
@@ -121,7 +123,7 @@ export function Checkins({checkinID}) {
121123

122124
let main = h('div', { className: "container" }, [
123125
h('div', { className: showMap ? 'hide' : 'main'}, [
124-
h('div', { className: "checkin-header" }, [
126+
h('div', { className: "checkin-head" }, [
125127
h('h1', checkin.notes),
126128
h(DarkModeButton, { className: 'dark-mode-button', showText: true }),
127129
]),

pages/checkin/main.sass

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,13 @@ h1, p
8484
align-items: center
8585
cursor: pointer
8686

87-
.profile-pic
87+
.profile-picture
8888
height: 100px
8989
width: 100px
9090
display: grid
9191
margin: auto
9292
margin-left: 50px
93+
border-radius: 50%
9394

9495
.stop-main-info
9596
text-align: left
@@ -111,7 +112,7 @@ h4
111112
padding: 0
112113
margin: 0
113114

114-
.checkin-header
115+
.checkin-head
115116
padding: 30px 0
116117
width: 100%
117118
display: grid

pages/explore/+Page.client.ts

Lines changed: 134 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import h from "@macrostrat/hyper";
1+
import hyper from "@macrostrat/hyper";
22

33
import { useMapRef } from "@macrostrat/mapbox-react";
44
import { Spinner, Icon, Divider } from "@blueprintjs/core";
@@ -15,11 +15,15 @@ import { mergeStyles } from "@macrostrat/mapbox-utils";
1515
import { useDarkMode, DarkModeButton } from "@macrostrat/ui-components";
1616
import mapboxgl from "mapbox-gl";
1717
import { useCallback, useEffect, useState } from "react";
18-
import "../main.sass";
18+
import styles from "../main.module.sass";
1919
import { createCheckins, useRockdAPI, Image } from "../index";
2020
import "./main.sass";
2121
import "@macrostrat/style-system";
2222
import { LngLatCoords } from "@macrostrat/map-interface";
23+
import { set } from "react-datepicker/dist/date_utils";
24+
import { configDefinitionsBuiltInGlobal } from "vike/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn";
25+
26+
const h = hyper.styled(styles);
2327

2428
let count = 0;
2529

@@ -46,7 +50,14 @@ const type =
4650
};
4751

4852
function weaverStyle(type: object) {
49-
const color = type?.color ?? "dodgerblue";
53+
const colors = {
54+
a: "#51bbd6",
55+
b: "#f1f075",
56+
c: "#f28cb1",
57+
};
58+
59+
const clusterThreshold = 1;
60+
5061
return {
5162
sources: {
5263
weaver: {
@@ -56,34 +67,59 @@ function weaverStyle(type: object) {
5667
},
5768
layers: [
5869
{
59-
id: "weaver",
70+
id: "clusters",
6071
type: "circle",
6172
source: "weaver",
6273
"source-layer": "default",
74+
filter: ['>', ['get', 'n'], clusterThreshold],
6375
paint: {
6476
"circle-radius": [
6577
"step",
6678
["get", "n"],
67-
2,
68-
1,
69-
2,
70-
5,
71-
4,
72-
10,
73-
8,
74-
50,
75-
12,
79+
15,
7680
100,
77-
16,
78-
200,
7981
20,
82+
750,
83+
30
84+
],
85+
'circle-color': [
86+
'step',
87+
['get', 'n'],
88+
colors.a,
89+
100,
90+
colors.b,
91+
750,
92+
colors.c
8093
],
81-
"circle-color": color,
8294
"circle-opacity": .8,
8395
"circle-stroke-width": 0.5,
84-
"circle-stroke-color": color,
96+
"circle-stroke-color": "#000",
8597
},
8698
},
99+
{
100+
id: 'cluster-count',
101+
type: 'symbol',
102+
source: 'weaver',
103+
"source-layer": "default",
104+
filter: ['has', 'n'],
105+
layout: {
106+
'text-field': ['get', 'n'],
107+
'text-size': 12
108+
}
109+
},
110+
{
111+
id: 'unclustered-point',
112+
type: 'circle',
113+
source: 'weaver',
114+
"source-layer": "default",
115+
filter: ['<=', ['get', 'n'], clusterThreshold],
116+
paint: {
117+
'circle-color': colors.a,
118+
'circle-radius': 4,
119+
'circle-stroke-width': 1,
120+
'circle-stroke-color': '#fff'
121+
}
122+
},
87123
],
88124
};
89125
}
@@ -98,10 +134,11 @@ function WeaverMap({
98134
}) {
99135
const [showSatelite, setSatelite] = useState(false);
100136
const style = useMapStyle(type, mapboxToken, showSatelite);
137+
const [selectedCheckin, setSelectedCheckin] = useState(null);
138+
const [selectedCheckinPoint, setSelectedCheckinPoint] = useState(null);
101139

102140
// overlay
103-
const [inspectPosition, setInspectPosition] =
104-
useState<mapboxgl.LngLat | null>(null);
141+
const [inspectPosition, setInspectPosition] = useState<mapboxgl.LngLat | null>(null);
105142

106143
const onSelectPosition = useCallback((position: mapboxgl.LngLat) => {
107144
setInspectPosition(position);
@@ -111,9 +148,7 @@ function WeaverMap({
111148
});
112149
}, []);
113150

114-
const selectedResult = getSelectedCheckins(inspectPosition?.lat - .05, inspectPosition?.lat + .05, inspectPosition?.lng - .05, inspectPosition?.lng + .05)?.success.data;
115151
const featuredCheckin = h(FeatureDetails, {setInspectPosition});
116-
const selectedCheckin = h(SelectedCheckins, {selectedResult, inspectPosition, setInspectPosition});
117152
let overlay;
118153

119154
const LngLatProps = {
@@ -125,34 +160,39 @@ function WeaverMap({
125160
zoom: 10
126161
};
127162

128-
if (inspectPosition && selectedResult.length > 0) {
163+
// handle selected checkins
164+
const checkinData = useRockdAPI(
165+
selectedCheckin ? `protected/checkins?checkin_id=${selectedCheckin}` : null
166+
);
167+
168+
if(selectedCheckin && checkinData) {
169+
const clickedCheckins = h(createSelectedCheckins, {data: checkinData?.success.data, setInspectPosition});
170+
129171
overlay = h("div.sidebox", [
130172
h('div.title', [
131173
h('div', { className: "selected-center" }, [
132174
h("h1", "Selected Checkins"),
133175
h('h3', { className: "coordinates" }, LngLatCoords(LngLatProps))
134176
]),
135-
// h(DarkModeButton, { className: "dark-btn", showText: true } )
136177
]),
137178
h("button", {
138179
className: "close-btn",
139180
onClick: () => {
140-
setInspectPosition(null);
181+
setSelectedCheckin(null);
141182

142183
let previousSelected = document.querySelectorAll('.selected_pin');
143184
previousSelected.forEach((marker) => {
144185
marker.remove();
145186
});
146187
}
147188
}, "X"),
148-
h("div.overlay-div", selectedCheckin),
189+
h("div.overlay-div", clickedCheckins),
149190
]);
150191
} else {
151192
overlay = h("div.sidebox", [
152193
h('div.sidebox-header', [
153194
h('div.title', [
154195
h("h1", "Featured Checkins"),
155-
// h(DarkModeButton, { className: "dark-btn", showText: true } )
156196
]),
157197
]),
158198
h("div.overlay-div", featuredCheckin),
@@ -181,6 +221,7 @@ function WeaverMap({
181221

182222
// The Overlay Div
183223
overlay,
224+
h(ClickedCheckins, {setSelectedCheckin}),
184225
]
185226
),
186227
]
@@ -261,9 +302,7 @@ function SelectedCheckins({selectedResult, inspectPosition, setInspectPosition})
261302
selectedCords.push([checkin.lng, checkin.lat]);
262303
});
263304

264-
let selectedStop = 0;
265305
selectedCords.forEach((coord) => {
266-
selectedStop++;
267306
// marker
268307
const el = document.createElement('div');
269308
el.className = 'selected_pin';
@@ -280,7 +319,6 @@ function SelectedCheckins({selectedResult, inspectPosition, setInspectPosition})
280319
}
281320

282321
function FeatureDetails({setInspectPosition}) {
283-
// return null;
284322
const mapRef = useMapRef();
285323
const map = mapRef.current;
286324
const [bounds, setBounds] = useState(map?.getBounds());
@@ -352,4 +390,71 @@ function Toolbar({showSatelite, setSatelite}) {
352390
]),
353391
])
354392
]);
393+
}
394+
395+
function handleClusterClick() {
396+
const mapRef = useMapRef();
397+
const map = mapRef.current;
398+
// handle cluster click
399+
map?.on('click', 'clusters', (e) => {
400+
console.log("cluster click");
401+
const features = map.queryRenderedFeatures(e.point, {
402+
layers: ['clusters']
403+
});
404+
405+
console.log("features", features[0].properties.expansion_zoom);
406+
});
407+
408+
return null;
409+
}
410+
411+
function ClickedCheckins({setSelectedCheckin}) {
412+
const mapRef = useMapRef();
413+
const map = mapRef.current;
414+
415+
useEffect(() => {
416+
if (!map) return;
417+
418+
const handleClick = (e) => {
419+
const features = map.queryRenderedFeatures(e.point, {
420+
layers: ['unclustered-point']
421+
});
422+
423+
if (features.length > 0) {
424+
const checkinId = features[0].properties.id;
425+
426+
// add marker
427+
const coord = features[0].geometry.coordinates.slice();
428+
console.log("coordinates", coord);
429+
430+
const el = document.createElement('div');
431+
el.className = 'selected_pin';
432+
433+
new mapboxgl.Marker(el)
434+
.setLngLat(coord)
435+
.addTo(map);
436+
437+
console.log("data", features[0]);
438+
setSelectedCheckin(checkinId);
439+
} else {
440+
setSelectedCheckin(null);
441+
}
442+
};
443+
444+
map.on('click', handleClick);
445+
446+
return () => {
447+
map.off('click', handleClick);
448+
};
449+
}, [map]);
450+
451+
return null;
452+
}
453+
454+
function createSelectedCheckins(result, setInspectPosition) {
455+
const mapRef = useMapRef();
456+
457+
console.log("data", result);
458+
459+
return createCheckins(result.data, mapRef, setInspectPosition);
355460
}

0 commit comments

Comments
 (0)