1+ import h from "./main.module.sass" ;
2+ import { useAPIResult } from "@macrostrat/ui-components" ;
3+ import {
4+ MapAreaContainer ,
5+ MapView ,
6+ } from "@macrostrat/map-interface" ;
7+ import { mapboxAccessToken } from "@macrostrat-web/settings" ;
8+ import { Footer } from "~/components/general" ;
9+ import { Divider , Spinner } from "@blueprintjs/core" ;
10+
11+ export function Page ( ) {
12+ const coords = getAllCoords ( ) ;
13+
14+ return h ( 'div.main' , [
15+ h ( 'div.heatmap-page' , [
16+ h ( PageHeader , { coords } ) ,
17+ h ( Map , { coords } )
18+ ] ) ,
19+ h ( Footer )
20+ ] )
21+ }
22+
23+ function PageHeader ( { coords } ) {
24+ const visitsToday = getVisitsToday ( ) ;
25+
26+ const { visits, visitors } = visitsToday || { } ;
27+
28+ const Visit = ! visitsToday ?
29+ h ( 'p' , 'Loading visits...' ) :
30+ h ( 'div.visits-today' , [
31+ h ( 'h3' , `${ visits . toLocaleString ( ) } visits today` ) ,
32+ h . if ( coords ?. length ) ( 'h3' , `${ coords ?. length . toLocaleString ( ) } visits this year` ) ,
33+ ] )
34+
35+ return h ( 'div.page-header' , [
36+ h ( 'h1' , 'Heatmap' ) ,
37+ Visit ,
38+ h ( Divider ) ,
39+ h ( 'p' , 'This is a heatmap of all the locations where Macrostrat has been accessed.' ) ,
40+ h ( 'p' , 'The blue markers indicate today\'s accesses, while the grey markers indicate accesses from other days.' ) ,
41+ ] ) ;
42+ }
43+
44+ function Map ( { coords} ) {
45+ const today = getTodayCoords ( ) ;
46+
47+ const style = 'mapbox://styles/mapbox/dark-v10' ;
48+
49+ if ( ! coords || ! today ) {
50+ return h ( "div.map-area-container.loading" , [
51+ h ( Spinner , { size : 50 } ) ,
52+ ] ) ;
53+ }
54+
55+ const handleMapLoaded = ( map ) => {
56+ map . on ( 'load' , ( ) => {
57+ // Combine coords and today coords, marking today's points
58+ const allFeatures = coords . map ( ( coord ) => ( {
59+ type : 'Feature' ,
60+ geometry : {
61+ type : 'Point' ,
62+ coordinates : [ coord . longitude , coord . latitude ] ,
63+ } ,
64+ properties : {
65+ isToday : false ,
66+ } ,
67+ } ) ) . concat (
68+ today . map ( ( coord ) => ( {
69+ type : 'Feature' ,
70+ geometry : {
71+ type : 'Point' ,
72+ coordinates : [ coord . longitude , coord . latitude ] ,
73+ } ,
74+ properties : {
75+ isToday : true ,
76+ } ,
77+ } ) )
78+ ) ;
79+
80+ map . addSource ( 'markers' , {
81+ type : 'geojson' ,
82+ data : {
83+ type : 'FeatureCollection' ,
84+ features : allFeatures ,
85+ } ,
86+ } ) ;
87+
88+ // Individual points - others (grey)
89+ map . addLayer ( {
90+ id : 'markers-other' ,
91+ type : 'circle' ,
92+ source : 'markers' ,
93+ filter : [ 'all' , [ '!' , [ 'has' , 'point_count' ] ] , [ '==' , [ 'get' , 'isToday' ] , false ] ] ,
94+ paint : {
95+ 'circle-radius' : 2 ,
96+ 'circle-color' : '#888' ,
97+ } ,
98+ } ) ;
99+
100+ // Individual points - today (blue)
101+ map . addLayer ( {
102+ id : 'markers-today' ,
103+ type : 'circle' ,
104+ source : 'markers' ,
105+ filter : [ 'all' , [ '!' , [ 'has' , 'point_count' ] ] , [ '==' , [ 'get' , 'isToday' ] , true ] ] ,
106+ paint : {
107+ 'circle-radius' : 3 ,
108+ 'circle-color' : '#007cbf' ,
109+ } ,
110+ } ) ;
111+ } ) ;
112+ } ;
113+
114+ return h (
115+ "div.map-container" ,
116+ [
117+ h (
118+ MapAreaContainer ,
119+ {
120+ className : "map-area-container" ,
121+ } ,
122+ [
123+ h ( MapView , {
124+ style,
125+ mapboxToken : mapboxAccessToken ,
126+ onMapLoaded : handleMapLoaded ,
127+ mapPosition : {
128+ camera : {
129+ lat : 39 ,
130+ lng : - 98 ,
131+ altitude : 6000000 ,
132+ } ,
133+ } ,
134+ } ) ,
135+ ] ) ,
136+ ]
137+ ) ;
138+ }
139+
140+ function getAllCoords ( ) {
141+ return useAPIResult ( '/api/matomo' , {
142+ date : '2025-01-01,today' ,
143+ period : 'range' ,
144+ filter_limit : 10000 ,
145+ filter_offset : 0 ,
146+ showColumns : 'latitude,longitude' ,
147+ doNotFetchActions : true ,
148+ } )
149+ }
150+
151+ function getTodayCoords ( ) : Array < { latitude : number , longitude : number } > | undefined {
152+ return useAPIResult ( '/api/matomo' , {
153+ date : 'today' ,
154+ period : 'day' ,
155+ filter_limit : 10000 ,
156+ filter_offset : 0 ,
157+ showColumns : 'latitude,longitude' ,
158+ doNotFetchActions : true ,
159+ } )
160+ }
161+
162+ function getVisitsToday ( ) : { visits : number , visitors : number } | undefined {
163+ return useAPIResult ( '/api/matomo' , {
164+ method : "Live.getCounters" ,
165+ idSite : 1 ,
166+ lastMinutes : 1440
167+ } ) ?. [ 0 ]
168+ }
0 commit comments