Skip to content

Commit a878128

Browse files
committed
add url params tracking
1 parent 1ac7a74 commit a878128

24 files changed

Lines changed: 914 additions & 292 deletions

app/app.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@ import PageTitleService from 'ember-page-title/services/page-title';
99
const routes = import.meta.glob('./routes/**/*.ts', { eager: true });
1010
const templates = import.meta.glob('./templates/**/*.gts', { eager: true });
1111
const services = import.meta.glob('./services/**/*.ts', { eager: true });
12+
const controllers = import.meta.glob('./controllers/**/*.ts', { eager: true });
1213

1314
const slimModules = {
1415
'./router': Router,
1516
...routes,
1617
...templates,
1718
...services,
19+
...controllers,
1820
'./services/page-title': PageTitleService,
1921
}
2022

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import { field, input, SessionResource } from "../../../core/utils/storage-resource";
2+
3+
/**
4+
* QuerParam + sessionStorage rules
5+
*
6+
* - the url value comes first
7+
* - if url param is empty, transition to sessionStorage value
8+
* - if sessionStorage value is empty, use default value
9+
* - allow some params to hide if other params aren't set (like lat/lng/zoom when active is false)
10+
*/
11+
12+
@SessionResource((map: MapState) => `map-state:${map.id}`)
13+
class MapState {
14+
id: string;
15+
16+
constructor(id: string) {
17+
this.id = id;
18+
}
19+
20+
get activeParam(): string {
21+
return this.active ? '1' : '';
22+
}
23+
set activeParam(value: string) {
24+
this.active = value === '1';
25+
}
26+
27+
get zoomParam(): string {
28+
return this.active ? (this.zoom !== this.defaultZoom ? this.zoom.toString() : '') : '';
29+
}
30+
set zoomParam(value: string) {
31+
if (!value) {
32+
return;
33+
}
34+
const zoom = Number(value);
35+
if (!isNaN(zoom)) {
36+
this.zoom = zoom;
37+
}
38+
}
39+
40+
get latParam(): string {
41+
return this.active ? (this.lat !== this.defaultLat ? this.lat.toFixed(5) : '') : '';
42+
}
43+
set latParam(value: string) {
44+
if (!value) {
45+
return;
46+
}
47+
const lat = Number(value);
48+
if (!isNaN(lat)) {
49+
this.lat = lat;
50+
}
51+
}
52+
53+
get lngParam(): string {
54+
return this.active ? (this.lng !== this.defaultLng ? this.lng.toFixed(5) : '') : '';
55+
}
56+
set lngParam(value: string) {
57+
if (!value) {
58+
return;
59+
}
60+
const lng = Number(value);
61+
if (!isNaN(lng)) {
62+
this.lng = lng;
63+
}
64+
}
65+
66+
@input('number')
67+
@field
68+
zoom: number = 114;
69+
70+
@field
71+
defaultZoom: number = 12;
72+
73+
@input('number')
74+
@field
75+
lat: number = 0;
76+
77+
@field
78+
defaultLat: number = 100;
79+
80+
@input('number')
81+
@field
82+
lng: number = 50;
83+
84+
@field
85+
defaultLng: number = 500;
86+
87+
@input('boolean')
88+
@field
89+
active: boolean = false;
90+
91+
initialize(options: { lat: number; lng: number; zoom: number }) {
92+
const { defaultLat, defaultLng, defaultZoom } = this;
93+
if (defaultLat !== options.lat || defaultLng !== options.lng || defaultZoom !== options.zoom) {
94+
// update only if different from existing defaults
95+
96+
this.lat = options.lat;
97+
this.lng = options.lng;
98+
this.zoom = options.zoom;
99+
this.defaultLat = options.lat;
100+
this.defaultLng = options.lng;
101+
this.defaultZoom = options.zoom;
102+
return;
103+
}
104+
}
105+
}
106+
107+
export { MapState };

app/components/maps/maplibre-fullscreen-map.gts

Lines changed: 52 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -16,33 +16,31 @@ import { getDevicePreferences } from '#app/core/preferences.ts';
1616
import type { Map } from 'maplibre-gl';
1717
import type { StyleSpecification } from 'maplibre-gl';
1818
import type { PolygonPoint } from '#app/utils/tile-preloader.ts';
19+
import type { MapState } from './-utils/map-state';
20+
import { excludeNull, or } from '#app/utils/comparison.ts';
1921

2022
interface MapLibreFullscreenMapSignature {
2123
Args: {
2224
/**
23-
* Location ID for caching
25+
* The MapState instance to persist map state
26+
* like center and zoom level
2427
*/
25-
locationId: string;
28+
mapState: MapState;
2629

2730
/**
2831
* Location name for display
2932
*/
3033
locationName: string;
3134

3235
/**
33-
* Center latitude
36+
* Location latitude
3437
*/
35-
lat: number;
38+
lat?: number;
3639

3740
/**
38-
* Center longitude
41+
* Location longitude
3942
*/
40-
lng: number;
41-
42-
/**
43-
* Initial zoom level (default: 14)
44-
*/
45-
zoom?: number;
43+
lng?: number;
4644

4745
/**
4846
* Map style (default: OpenStreetMap style)
@@ -62,7 +60,6 @@ export default class MapLibreFullscreenMap extends Component<MapLibreFullscreenM
6260
preferences = getDevicePreferences();
6361

6462
map: Map | null = null;
65-
currentZoom: number = this.args.zoom ?? 14;
6663
locationWatchId: number | null = null;
6764

6865
@tracked
@@ -127,7 +124,6 @@ export default class MapLibreFullscreenMap extends Component<MapLibreFullscreenM
127124
// Watch position with high accuracy
128125
this.locationWatchId = navigator.geolocation.watchPosition(
129126
(position) => {
130-
console.log('Received location update:', position);
131127
const { latitude, longitude } = position.coords;
132128

133129
this.userLocation = { lat: latitude, lng: longitude };
@@ -152,9 +148,10 @@ export default class MapLibreFullscreenMap extends Component<MapLibreFullscreenM
152148
this.userLocation = null;
153149
};
154150

155-
storeMapReference = (context: { map: Map } | null) => {
151+
storeMapReference = (context: Map| null) => {
152+
// console.log('Storing map reference in fullscreen map component', context, this.map);
156153
if (context && !this.map) {
157-
this.map = context.map;
154+
this.map = context;
158155
}
159156
}
160157

@@ -183,6 +180,22 @@ export default class MapLibreFullscreenMap extends Component<MapLibreFullscreenM
183180
this.polygon = null;
184181
};
185182

183+
updateLocation = () => {
184+
const center = this.map?.getCenter();
185+
if (center) {
186+
this.args.mapState.lng = center.lng // Number(center.lng.toFixed(5));
187+
this.args.mapState.lat = center.lat // Number(center.lat.toFixed(5));
188+
}
189+
}
190+
191+
updateZoom = () => {
192+
const zoom = this.map?.getZoom();
193+
console.log('Map zoom updated:', zoom);
194+
if (zoom) {
195+
this.args.mapState.zoom = zoom;
196+
}
197+
}
198+
186199
<template>
187200
{{#in-element this.portals.takeover}}
188201
{{! template-lint-disable no-inline-styles }}
@@ -201,10 +214,10 @@ export default class MapLibreFullscreenMap extends Component<MapLibreFullscreenM
201214
{{! Download button - bottom right }}
202215
<div class="fullscreen-map-download">
203216
<MapDownloadButton
204-
@locationId={{@locationId}}
217+
@locationId={{@mapState.id}}
205218
@locationName={{@locationName}}
206-
@lat={{@lat}}
207-
@lng={{@lng}}
219+
@lat={{@mapState.lat}}
220+
@lng={{@mapState.lng}}
208221
@getMap={{this.getMap}}
209222
@polygon={{this.polygon}}
210223
@onStartPolygonSelection={{this.startPolygonSelection}}
@@ -225,34 +238,34 @@ export default class MapLibreFullscreenMap extends Component<MapLibreFullscreenM
225238

226239
<MapLibreBoundary>
227240
<MapLibreMap
228-
@lat={{@lat}}
229-
@lng={{@lng}}
230-
@zoom={{this.currentZoom}}
241+
@lat={{or @mapState.lat @mapState.defaultLat}}
242+
@lng={{or @mapState.lng @mapState.defaultLng}}
243+
@zoom={{or @mapState.zoom @mapState.defaultZoom}}
244+
@onMoveEnd={{this.updateLocation}}
245+
@onZoomEnd={{this.updateZoom}}
231246
@style={{@style}}
232247
as |context|
233248
>
234-
{{#if context}}
235-
{{this.storeMapReference context}}
249+
{{this.storeMapReference context}}
250+
<MapLibreMarker
251+
@context={{context}}
252+
@lat={{excludeNull (or @mapState.defaultLat @lat)}}
253+
@lng={{excludeNull (or @mapState.defaultLng @lng)}}
254+
@title={{@locationName}}
255+
/>
256+
257+
{{! User location marker }}
258+
{{#if this.userLocation}}
259+
{{#if this.userLocationElement}}
236260
<MapLibreMarker
237261
@context={{context}}
238-
@lat={{@lat}}
239-
@lng={{@lng}}
240-
@title={{@locationName}}
262+
@lat={{this.userLocation.lat}}
263+
@lng={{this.userLocation.lng}}
264+
@title="Your Location"
265+
@element={{this.userLocationElement}}
241266
/>
242-
243-
{{! User location marker }}
244-
{{#if this.userLocation}}
245-
{{#if this.userLocationElement}}
246-
<MapLibreMarker
247-
@context={{context}}
248-
@lat={{this.userLocation.lat}}
249-
@lng={{this.userLocation.lng}}
250-
@title="Your Location"
251-
@element={{this.userLocationElement}}
252-
/>
253-
{{/if}}
254-
{{/if}}
255267
{{/if}}
268+
{{/if}}
256269
</MapLibreMap>
257270
</MapLibreBoundary>
258271
</div>

0 commit comments

Comments
 (0)