waygo-maps 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.babelrc +4 -0
- package/dist/014017f831c78bc6fd64841d8678a8d1.svg +1 -0
- package/dist/0680802a9353dabec5dd7049f4cd6263.svg +3 -0
- package/dist/0d1982dbcd8e3e8fcfbede8c102ab2f6.svg +3 -0
- package/dist/1b7f16a1f8c7a51acb29667188b93cd4.svg +3 -0
- package/dist/216edfa842a5ed98698739b69479f38c.svg +3 -0
- package/dist/392dbb2b5523bec74bc9a88df3f43dcf.svg +3 -0
- package/dist/49f8ed3d44d3320ea78c5da3231d00ca.svg +3 -0
- package/dist/4afa21a73de906916b62dd0baefae8fa.svg +3 -0
- package/dist/4b9ae054d996b09c84d311ff59d62135.svg +3 -0
- package/dist/4fc911a49bb7b090cdeeaed8fec429d3.svg +1 -0
- package/dist/507fada530642f8f1084a961a554e5a5.svg +3 -0
- package/dist/5dddcb86c4e0b23bd0209f44fd342d98.svg +3 -0
- package/dist/5e7fb034cbde37bc0e6ea8d3e6e4d954.svg +3 -0
- package/dist/63aa91aee195b612708db336ad5020db.svg +3 -0
- package/dist/709b5ad35fbbdaa1c4b5222a276444fa.svg +3 -0
- package/dist/73b73ceab46aea8192b55d504089b7b7.svg +3 -0
- package/dist/7cf71b89208aed47ca8d698707c7c1a1.svg +3 -0
- package/dist/7d2fb7c25b2d12614aeb1b025a51b86f.svg +4 -0
- package/dist/95d40a1236e53e308fb691adb40560da.svg +3 -0
- package/dist/bf15a356e49a659ec20974a7168c76ec.svg +12 -0
- package/dist/bundle.js +2 -0
- package/dist/bundle.js.LICENSE.txt +1 -0
- package/dist/d39d475496b3b4ce383f53bbf356f4f2.svg +2 -0
- package/dist/d8e06ee8b585e38158e77073a35d3cc1.svg +3 -0
- package/dist/da4aa51dbf8250628e654d4e01d44c06.svg +3 -0
- package/dist/e88ae66eec18595e40fc4b4bc894e4f6.svg +3 -0
- package/dist/f106fedfc261aa203f641adaf87ec68f.svg +3 -0
- package/dist/f8965838ad87362f7fd1507af2a45dfa.svg +4 -0
- package/index.html +137 -0
- package/package.json +27 -0
- package/src/Controls/CategoryBarControl.js +94 -0
- package/src/Controls/ContentPlacementControl.js +326 -0
- package/src/Controls/DirectionsControl.js +198 -0
- package/src/Controls/InteractionControl.js +521 -0
- package/src/Controls/SearchBoxControl.js +123 -0
- package/src/Controls/SearchResultsControl.js +86 -0
- package/src/WaygoMaps.js +29 -0
- package/src/api/ApiManager.js +55 -0
- package/src/api/MapApi.js +15 -0
- package/src/api/MapViewApi.js +20 -0
- package/src/api/SearchApi.js +38 -0
- package/src/assets/WaygoIcon.svg +3 -0
- package/src/assets/WaygoIconWhite.svg +3 -0
- package/src/assets/actionButtonIcons/missingIncorrect.svg +3 -0
- package/src/assets/actionButtonIcons/share.svg +3 -0
- package/src/assets/actionButtonIcons/signboard.svg +3 -0
- package/src/assets/actionButtonIcons/website.svg +3 -0
- package/src/assets/arrows/backArrow.svg +3 -0
- package/src/assets/arrows/leftArrow.svg +3 -0
- package/src/assets/arrows/leftBackArrow.svg +3 -0
- package/src/assets/arrows/rightArrow.svg +3 -0
- package/src/assets/cancel.svg +4 -0
- package/src/assets/directions.svg +3 -0
- package/src/assets/fonts/CircularXX-Book.woff2 +0 -0
- package/src/assets/fonts/CircularXX-Medium.woff2 +0 -0
- package/src/assets/fonts/CircularXX-Regular.woff2 +0 -0
- package/src/assets/location.svg +3 -0
- package/src/assets/locationPin.svg +3 -0
- package/src/assets/magnify.svg +4 -0
- package/src/assets/magnify_glass.svg +1 -0
- package/src/assets/missing.svg +3 -0
- package/src/assets/pin.svg +3 -0
- package/src/assets/pinOutlineIcon.svg +3 -0
- package/src/assets/search.svg +3 -0
- package/src/assets/volks.svg +1 -0
- package/src/assets/website.svg +3 -0
- package/src/components/ContentPlacementView/ContentChildButton.js +37 -0
- package/src/components/ContentPlacementView/ContentChildrenView.js +55 -0
- package/src/components/ContentPlacementView/ContentDetails.js +159 -0
- package/src/components/ContentPlacementView/ContentPlacementHeader.js +44 -0
- package/src/components/ContentPlacementView/ContentPlacementView.js +84 -0
- package/src/components/ContentPlacementView/ContextualLocationView.js +33 -0
- package/src/components/ContentPlacementView/DetailsView.js +53 -0
- package/src/components/DirectionsView/ContentStartEndCells.js +48 -0
- package/src/components/DirectionsView/DirectionsView.js +322 -0
- package/src/components/DirectionsView/StepsView.js +43 -0
- package/src/components/MapView/MapView.js +403 -0
- package/src/components/MapView/StateCoordinator.js +23 -0
- package/src/components/SearchBox/SearchBar.js +173 -0
- package/src/components/SearchBox/SearchBarSuggestionsView.js +49 -0
- package/src/components/SearchBox/SearchBarSuggestionsViewCell.js +34 -0
- package/src/components/SearchBox/SearchBox.js +110 -0
- package/src/components/SearchResultsView/SearchResultsView.js +71 -0
- package/src/components/SearchResultsView/SearchResultsViewCell.js +34 -0
- package/src/components/SliderBar.js +161 -0
- package/src/core/Component.js +72 -0
- package/src/core/Control.js +31 -0
- package/src/core/EventBus.js +38 -0
- package/src/core/Events.js +38 -0
- package/src/core/StateStore.js +34 -0
- package/src/index.js +23 -0
- package/src/styles.css +1499 -0
- package/src/utils/coordinateSystems.js +48 -0
- package/src/utils/debounce.js +8 -0
- package/src/utils/resourceLoader.js +41 -0
- package/test.json +58 -0
- package/webpack.config.js +47 -0
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
import { loadCSS, loadScript } from "../../utils/resourceLoader";
|
|
2
|
+
import waygoMaps from "../../WaygoMaps";
|
|
3
|
+
import getMapStyle from "../../api/MapApi";
|
|
4
|
+
import Component from "../../core/Component";
|
|
5
|
+
import Events from "../../core/Events";
|
|
6
|
+
import StateCoordinator from "./StateCoordinator";
|
|
7
|
+
import SearchResultsControl from "../../Controls/SearchResultsControl";
|
|
8
|
+
import mapboxgl from 'mapbox-gl';
|
|
9
|
+
import axios from 'axios';
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
import { convertVerticesToCoordinates } from "../../utils/coordinateSystems";
|
|
13
|
+
|
|
14
|
+
const mapboxCSS = 'https://api.mapbox.com/mapbox-gl-js/v3.5.1/mapbox-gl.css';
|
|
15
|
+
const mapboxJS = 'https://api.mapbox.com/mapbox-gl-js/v3.5.1/mapbox-gl.js';
|
|
16
|
+
const accessToken = 'pk.eyJ1Ijoid2F5Z28tbWFwcyIsImEiOiJjbGtxYzZ1N3QxdG43M210bXFuYmJ4a3gxIn0.tlbznj_fRJ8La6s2UUMO6A';
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
const mock = {
|
|
20
|
+
'c66d7e2c3ebd4a8fa60efa5bf3b5b301:2d4911eda2ef4950b307e51cd0ccf35e': {
|
|
21
|
+
'steps': [
|
|
22
|
+
'Leave Roundtable and make a left',
|
|
23
|
+
'Turn right after walking 177 feet',
|
|
24
|
+
'Turn left after walking 203 feet',
|
|
25
|
+
'Turn right after walking 100 feet',
|
|
26
|
+
'Continue straight in 242 feet',
|
|
27
|
+
'Arrive at Stage 4, on your left'
|
|
28
|
+
],
|
|
29
|
+
'path': [
|
|
30
|
+
[-81.557308010743881, -195.68687504906683],
|
|
31
|
+
[-66.793528483184829, -195.68687504906688],
|
|
32
|
+
[-66.793528483184829, -136.30367294932935],
|
|
33
|
+
[-6.7541584044446665, -136.30367294932955],
|
|
34
|
+
[-6.7541584044446195, -106.92078820451393],
|
|
35
|
+
[81.828518760909716, -106.92078820451393],
|
|
36
|
+
[81.828518760909716, -47.209502115275079],
|
|
37
|
+
[140.88363687114594, -47.209502115275079]
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const mockData = {
|
|
42
|
+
'b1800bf6e3ed480cae21526e42464676:a7fa2fb07ae04049b9026c296d015d66': {
|
|
43
|
+
'steps': [
|
|
44
|
+
'Leave Roundtable and make a left',
|
|
45
|
+
'Turn right after walking 177 feet',
|
|
46
|
+
'Turn left after walking 203 feet',
|
|
47
|
+
'Turn right after walking 100 feet',
|
|
48
|
+
'Continue straight in 242 feet',
|
|
49
|
+
'Arrive at Stage 4, on your left'
|
|
50
|
+
],
|
|
51
|
+
'path': [
|
|
52
|
+
[95.645948774511609, -118.96329432647396],
|
|
53
|
+
[41.840174496296385, -118.96329432647379],
|
|
54
|
+
[41.840174496296484, -56.955420310725756],
|
|
55
|
+
[10.344111504170499, -56.955420310725756],
|
|
56
|
+
[10.34411150417062, 18.175813285074767],
|
|
57
|
+
[0.17350782962993705, 18.175813285074767],
|
|
58
|
+
[0.17350782962999536, 54.265052130219125],
|
|
59
|
+
[-25.417043351472369, 54.26505213021921]
|
|
60
|
+
]
|
|
61
|
+
}, // ROUNDTABLE TO STAGE 4
|
|
62
|
+
'529803fcdd7e4d5db5ed71b9ff1ef0e2:899969e0115b4d8da8fb51bedf7caff2': {
|
|
63
|
+
'steps': [
|
|
64
|
+
"Leave Startups Info Point and make a left",
|
|
65
|
+
"Turn right in 12 feet",
|
|
66
|
+
"Turn left in 37 feet",
|
|
67
|
+
"Continue straight for 182 feet",
|
|
68
|
+
"Turn right in 36 feet",
|
|
69
|
+
"Turn left after 29 feet",
|
|
70
|
+
"Turn right after 57 feet",
|
|
71
|
+
"Turn left after walking 42 feet",
|
|
72
|
+
"Arrive at Alpha 1, on your right"
|
|
73
|
+
],
|
|
74
|
+
'path': [
|
|
75
|
+
[284.28160504078147, -119.85123601826949],
|
|
76
|
+
[258.75367051155007, -119.8512360182694],
|
|
77
|
+
[258.75367051155007, -57.515278013020058],
|
|
78
|
+
[-40.902596633706594, -57.515278013019092],
|
|
79
|
+
[-40.902596633706445, 19.584459519789313],
|
|
80
|
+
[-169.83960450772221, 19.584459519789728],
|
|
81
|
+
[-169.83960450772213, 78.311493640524645],
|
|
82
|
+
[-215.11519505890323, 78.311493640524787]
|
|
83
|
+
]
|
|
84
|
+
},
|
|
85
|
+
'd1910e5724844b40bf8e2a721fba172a:3673b48d96b04d7aa65937dec3276d3c': {
|
|
86
|
+
'steps': [
|
|
87
|
+
"Leave startup lounge and make a right",
|
|
88
|
+
"Continue straight for 22 feet, then turn left",
|
|
89
|
+
"Turn right in 37 feet",
|
|
90
|
+
"Continue straight for 143 feet, then turn left",
|
|
91
|
+
"Turn right in 32 feet",
|
|
92
|
+
"Continue straight for 210 feet",
|
|
93
|
+
"Turn right, and continue for 5 feet",
|
|
94
|
+
"Arrive at The Black Innovation Zone, on your right"
|
|
95
|
+
],
|
|
96
|
+
'path': [
|
|
97
|
+
[417.35544488563073, 75.74517709550193],
|
|
98
|
+
[356.33182283838664, 75.745177095502129],
|
|
99
|
+
[356.33182283838653, 17.674310953769847],
|
|
100
|
+
[121.7517703449482, 17.674310953770604],
|
|
101
|
+
[121.75177034494808, -56.800754663027305],
|
|
102
|
+
[-207.21694798680142, -56.80075466302624],
|
|
103
|
+
[-207.21694798680144, -78.116837633560053]
|
|
104
|
+
]
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const defaultMapOptions = {
|
|
111
|
+
container: 'map', // Default container ID
|
|
112
|
+
sourceId: 'collision-conference.2024.2xw_YUXYS8GoDTB2AQgN3A',
|
|
113
|
+
center: [0, 0], // Default map center [longitude, latitude]
|
|
114
|
+
zoom: 12, // Default zoom level
|
|
115
|
+
bearing: 0,
|
|
116
|
+
pitch: 0,
|
|
117
|
+
minPitch: 0,
|
|
118
|
+
maxPitch: 75,
|
|
119
|
+
minZoom: 0,
|
|
120
|
+
maxZoom: 22,
|
|
121
|
+
bounds: null, // The bounds of the map, would override center and zoom options.
|
|
122
|
+
doubleClickZoom: true,
|
|
123
|
+
dragPan: true,
|
|
124
|
+
dragRotate: true,
|
|
125
|
+
scrollZoom: true,
|
|
126
|
+
touchPitch: true,
|
|
127
|
+
touchZoomRotate: true,
|
|
128
|
+
interactive: true,
|
|
129
|
+
trackResize: true,
|
|
130
|
+
keyboard: true,
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
export class MapView extends Component {
|
|
135
|
+
constructor(options = {}) {
|
|
136
|
+
super({ ...defaultMapOptions, ...options});
|
|
137
|
+
this.mapViewApi = waygoMaps.getMapViewApi();
|
|
138
|
+
this.searchApi = waygoMaps.getSearchApi();
|
|
139
|
+
this.mapContainer = document.createElement('div');
|
|
140
|
+
this.mapContainer.className = 'inner-map-container';
|
|
141
|
+
this.ready = this._initialize(options);
|
|
142
|
+
|
|
143
|
+
// this._hiddenSymbolLayers = [];
|
|
144
|
+
|
|
145
|
+
this._stateCoordinator = new StateCoordinator(this);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
async _initialize() {
|
|
149
|
+
console.log('Initializing map view component..');
|
|
150
|
+
|
|
151
|
+
try {
|
|
152
|
+
await this._loadMapLibraries();
|
|
153
|
+
this.render();
|
|
154
|
+
const style = await this._fetchMapStyle();
|
|
155
|
+
if (typeof mapboxgl !== 'undefined' && style) {
|
|
156
|
+
mapboxgl.accessToken = accessToken;
|
|
157
|
+
this.map = new mapboxgl.Map({
|
|
158
|
+
container: this.mapContainer,
|
|
159
|
+
style: `mapbox://styles/waygo-maps/${style}`,
|
|
160
|
+
center: this.options.center,
|
|
161
|
+
zoom: this.options.zoom,
|
|
162
|
+
bearing: this.options.bearing,
|
|
163
|
+
pitch: this.options.pitch,
|
|
164
|
+
minPitch: this.options.minPitch,
|
|
165
|
+
maxPitch: this.options.maxPitch,
|
|
166
|
+
minZoom: this.options.minZoom,
|
|
167
|
+
maxZoom: this.options.maxZoom,
|
|
168
|
+
bounds: this.options.bounds,
|
|
169
|
+
doubleClickZoom: this.options.doubleClickZoom,
|
|
170
|
+
dragPan: this.options.dragPan,
|
|
171
|
+
dragRotate: this.options.dragRotate,
|
|
172
|
+
scrollZoom: this.options.scrollZoom,
|
|
173
|
+
touchPitch: this.options.touchPitch,
|
|
174
|
+
touchZoomRotate: this.options.touchZoomRotate,
|
|
175
|
+
interactive: this.options.interactive,
|
|
176
|
+
trackResize: this.options.trackResize,
|
|
177
|
+
keyboard: this.options.keyboard,
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
this.map.on('load', () => this.fire('load'));
|
|
181
|
+
this._initializeEventListeners();
|
|
182
|
+
} else {
|
|
183
|
+
console.error('Mapbox GL JS is not loaded.');
|
|
184
|
+
}
|
|
185
|
+
} catch (error) {
|
|
186
|
+
console.error('Failed to initialize the map:', error);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
_initializeEventListeners() {
|
|
191
|
+
this.mapContainer.addEventListener('mousedown', (event) => this.fire('mousedown', { originalEvent: event }));
|
|
192
|
+
// preclick
|
|
193
|
+
this.mapContainer.addEventListener('click', (event) => this.fire('click', { originalEvent: event }));
|
|
194
|
+
this.mapContainer.addEventListener('mouseover', (event) => this.fire('mouseover', { originalEvent: event }));
|
|
195
|
+
this.mapContainer.addEventListener('mousemove', (event) => this.fire('mousemove', { originalEvent: event }));
|
|
196
|
+
this.mapContainer.addEventListener('dblclick', (event) => this.fire('dblclick', { originalEvent: event }));
|
|
197
|
+
// mouseenter
|
|
198
|
+
// mouseleave
|
|
199
|
+
this.mapContainer.addEventListener('mouseout', (event) => this.fire('mouseout', { originalEvent: event }));
|
|
200
|
+
this.mapContainer.addEventListener('contextmenu', (event) => this.fire('contextmenu', { originalEvent: event }));
|
|
201
|
+
this.mapContainer.addEventListener('wheel', (event) => this.fire('wheel', { originalEvent: event }));
|
|
202
|
+
this.mapContainer.addEventListener('touchstart', (event) => this.fire('touchstart', { originalEvent: event }));
|
|
203
|
+
this.mapContainer.addEventListener('touchend', (event) => this.fire('touchend', { originalEvent: event }));
|
|
204
|
+
this.mapContainer.addEventListener('touchmove', (event) => this.fire('touchmove', { originalEvent: event }));
|
|
205
|
+
this.mapContainer.addEventListener('touchcancel', (event) => this.fire('touchcancel', { originalEvent: event }));
|
|
206
|
+
this.mapContainer.addEventListener('move', (event) => this.fire('move', { originalEvent: event }));
|
|
207
|
+
|
|
208
|
+
const movementEvents = [
|
|
209
|
+
'movestart',
|
|
210
|
+
'move',
|
|
211
|
+
'moveend',
|
|
212
|
+
'dragstart',
|
|
213
|
+
'drag',
|
|
214
|
+
'dragend',
|
|
215
|
+
'zoomstart',
|
|
216
|
+
'zoom',
|
|
217
|
+
'zoomend',
|
|
218
|
+
'rotatestart',
|
|
219
|
+
'rotate',
|
|
220
|
+
'rotateend',
|
|
221
|
+
'pitchstart',
|
|
222
|
+
'pitch',
|
|
223
|
+
'pitchend',
|
|
224
|
+
'boxzoomstart',
|
|
225
|
+
'boxzoomend',
|
|
226
|
+
'boxzoomcancel',
|
|
227
|
+
];
|
|
228
|
+
|
|
229
|
+
movementEvents.forEach(eventName => {
|
|
230
|
+
this.map.on(eventName, (event) => {
|
|
231
|
+
this.fire(eventName, { originalEvent: event });
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
async _fetchMapStyle() {
|
|
237
|
+
let parts = this.options.sourceId.split('.');
|
|
238
|
+
if (parts.length !== 3) {
|
|
239
|
+
console.error('The mapViewId format is incorrect. It should be in the format "businessId.mapId.mapViewId".');
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
let businessId = parts[0] || '';
|
|
243
|
+
let mapId = parts[1] || '';
|
|
244
|
+
let mapViewId = parts[2] || '';
|
|
245
|
+
|
|
246
|
+
try {
|
|
247
|
+
const data = await this.mapViewApi.fetchMapStyle(businessId, mapId, mapViewId);
|
|
248
|
+
console.log('Fetched map style:', data.style_id);
|
|
249
|
+
return data.style_id
|
|
250
|
+
} catch (err) {
|
|
251
|
+
console.error('Error fetching map style:', err);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
async _loadMapLibraries() {
|
|
256
|
+
console.log('Loading map libraries');
|
|
257
|
+
await loadCSS(mapboxCSS);
|
|
258
|
+
await loadScript(mapboxJS);
|
|
259
|
+
console.log('Map libraries loaded');
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
render() {
|
|
263
|
+
const targetContainer = document.getElementById(this.options.container);
|
|
264
|
+
if (targetContainer) {
|
|
265
|
+
targetContainer.appendChild(this.mapContainer);
|
|
266
|
+
this.mapContainer.style.width = '100%';
|
|
267
|
+
this.mapContainer.style.height = '100%';
|
|
268
|
+
this.mapContainer.style.position = 'relative';
|
|
269
|
+
} else {
|
|
270
|
+
console.error(`Container element with id "${this.containerId}" not found.`);
|
|
271
|
+
}
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// MARK: Controls
|
|
276
|
+
addControl(control) {
|
|
277
|
+
const container = control.onAdd(this);
|
|
278
|
+
this.mapContainer.appendChild(container);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
removeControl(control) {
|
|
282
|
+
this.map.removeControl(control);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// MARK: Map states
|
|
286
|
+
setToDefaultState() {
|
|
287
|
+
this._stateCoordinator.transitionTo('default');
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
async setToSearchState(query) {
|
|
291
|
+
const results = await this.search(query);
|
|
292
|
+
this._stateCoordinator.transitionTo('search', { query, results });
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
async setToSelectedContentState(contentPlacementIds) {
|
|
296
|
+
const lastContentPlacementId = contentPlacementIds[contentPlacementIds.length - 1];
|
|
297
|
+
const selectedContentPlacement = await this.getContentPlacementDetails(lastContentPlacementId);
|
|
298
|
+
this._stateCoordinator.transitionTo('selectedContent', { contentPlacementIds, selectedContentPlacement });
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
async setToDirectionsState(startContentPlacementId = null, endContentPlacementId = null) {
|
|
302
|
+
var startContentPlacement = null;
|
|
303
|
+
if (startContentPlacementId) {
|
|
304
|
+
startContentPlacement = await this.getContentPlacementDetails(startContentPlacementId);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
var endContentPlacement = null;
|
|
308
|
+
if (endContentPlacementId) {
|
|
309
|
+
endContentPlacement = await this.getContentPlacementDetails(endContentPlacementId);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
this._stateCoordinator.transitionTo('directions', { startContentPlacement, endContentPlacement });
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
initiateBack() {
|
|
316
|
+
this.fire('initiate:back');
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
initiateSetToSearchState() {
|
|
320
|
+
this.fire('initiate:search');
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
findPath(startContentPlacementId, endContentPlacementId) {
|
|
324
|
+
console.log("finding path", startContentPlacementId, endContentPlacementId);
|
|
325
|
+
|
|
326
|
+
const data = mock[`${startContentPlacementId}:${endContentPlacementId}`];
|
|
327
|
+
console.log("DATA", data);
|
|
328
|
+
|
|
329
|
+
const coordinates = convertVerticesToCoordinates(data.path, null, 10.0);
|
|
330
|
+
|
|
331
|
+
console.log("COORDINATES:", coordinates);
|
|
332
|
+
|
|
333
|
+
return { coordinates: coordinates, steps: data.steps };
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
// MARK: Map methods
|
|
338
|
+
_findFeatureByPlacementId(placementId) {
|
|
339
|
+
// Query all rendered features and filter by the desired property (placementId)
|
|
340
|
+
const features = this.map.queryRenderedFeatures({
|
|
341
|
+
// Use a filter to find the feature with the matching placementId
|
|
342
|
+
filter: ['==', ['get', 'placement_id'], placementId]
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
// Return the first feature that matches the placementId
|
|
346
|
+
return features.length > 0 ? features[0] : null;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
getCenter() {
|
|
350
|
+
// Update to convert from lat, lon, to x, y in meters
|
|
351
|
+
if (this.map) {
|
|
352
|
+
return this.map.getCenter();
|
|
353
|
+
} else {
|
|
354
|
+
console.error('Map is not initialized.');
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
setCenter(lngLat) {
|
|
359
|
+
// Update to convert from lat, lon, to x, y in meters
|
|
360
|
+
if (this.map) {
|
|
361
|
+
this.map.setCenter(lngLat);
|
|
362
|
+
} else {
|
|
363
|
+
console.error('Map is not initialized.');
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
async search(query) {
|
|
370
|
+
if (query === '') {
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
try {
|
|
374
|
+
return await this.searchApi.search(
|
|
375
|
+
'e9df990cbd084934973a87fc2f3b0e74',
|
|
376
|
+
'move-america-2024',
|
|
377
|
+
'FTdsy9btTs6qumoZ6E8Z2Q',
|
|
378
|
+
// 'collision-conference',
|
|
379
|
+
// '2024',
|
|
380
|
+
// '2xw_YUXYS8GoDTB2AQgN3A',
|
|
381
|
+
query
|
|
382
|
+
);
|
|
383
|
+
} catch (error) {
|
|
384
|
+
if (axios.isCancel(error)) {
|
|
385
|
+
console.log('Request canceled:', error.message);
|
|
386
|
+
} else {
|
|
387
|
+
console.error('Search error:', error);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
async getContentPlacementDetails(contentPlacementId) {
|
|
393
|
+
try {
|
|
394
|
+
return await this.searchApi.fetchContentPlacementDetails(contentPlacementId);
|
|
395
|
+
} catch (error) {
|
|
396
|
+
if (axios.isCancel(error)) {
|
|
397
|
+
console.log('Request canceled:', error.message);
|
|
398
|
+
} else {
|
|
399
|
+
console.error('Fetching content placement details error:', error);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
class StateCoordinator {
|
|
2
|
+
constructor(mapView) {
|
|
3
|
+
this.mapView = mapView;
|
|
4
|
+
this.state = 'default';
|
|
5
|
+
this.stateHistory = ['default'];
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
transitionTo(newState, data = {}) {
|
|
9
|
+
this.state = newState;
|
|
10
|
+
const lastState = this.stateHistory[this.stateHistory.length - 1];
|
|
11
|
+
|
|
12
|
+
if (newState == 'default') {
|
|
13
|
+
this.stateHistory = ['default'];
|
|
14
|
+
} else if (newState !== lastState) {
|
|
15
|
+
this.stateHistory.push(newState);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
console.log("STATE LENGTH PROPER", this.stateHistory.length, this.stateHistory);
|
|
19
|
+
this.mapView.fire(`state:${newState}`, data);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default StateCoordinator;
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import Component from "../../core/Component";
|
|
2
|
+
import magnifyingGlassIcon from '../../assets/magnify.svg'
|
|
3
|
+
import cancelIcon from '../../assets/cancel.svg'
|
|
4
|
+
|
|
5
|
+
import backArrow from '../../assets/arrows/backArrow.svg';
|
|
6
|
+
import waygoIcon from '../../assets/WaygoIcon.svg';
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class SearchBar extends Component {
|
|
10
|
+
constructor(options = {}) {
|
|
11
|
+
super(options);
|
|
12
|
+
this._initialize();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
_initialize() {
|
|
16
|
+
this.element = document.createElement('div');
|
|
17
|
+
this.element.className = 'search-bar-container';
|
|
18
|
+
|
|
19
|
+
this.input = document.createElement('input');
|
|
20
|
+
this.input.type = 'text';
|
|
21
|
+
this.input.placeholder = 'Search MOVE America 2024';
|
|
22
|
+
this.input.className = 'search-bar';
|
|
23
|
+
|
|
24
|
+
this.rightButton = document.createElement('button');
|
|
25
|
+
this.rightButton.className = 'search-bar-button-right';
|
|
26
|
+
this.updateRightButtonIcon('search');
|
|
27
|
+
|
|
28
|
+
this.leftButton = document.createElement('button');
|
|
29
|
+
this.leftButton.className = 'search-bar-button-left';
|
|
30
|
+
// this.updateLeftButtonIcon('logo');
|
|
31
|
+
this.updateLeftButtonIcon('none');
|
|
32
|
+
|
|
33
|
+
this.element.appendChild(this.leftButton);
|
|
34
|
+
this.element.appendChild(this.input);
|
|
35
|
+
this.element.appendChild(this.rightButton);
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
this._setupEventListeners();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
_setupEventListeners() {
|
|
42
|
+
this.input.addEventListener('input', (e) => this._handleInput(e));
|
|
43
|
+
this.input.addEventListener('focus', this._handleFocus.bind(this));
|
|
44
|
+
this.input.addEventListener('blur',this._handleBlur.bind(this));
|
|
45
|
+
this.input.addEventListener('keydown', (e) => {
|
|
46
|
+
if (e.key === 'Enter') {
|
|
47
|
+
this._handleEnterSelect(e)
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
this.rightButton.addEventListener('click', (e) => this._handleRightButtonSelect(e));
|
|
51
|
+
this.leftButton.addEventListener('click', (e) => this._handleLeftButtonSelect(e));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
_handleInput(e) {
|
|
55
|
+
// this.updateRightButtonIcon('cancel');
|
|
56
|
+
this.fire('input', { event: e, query: this.getText() } )
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
_handleFocus() {
|
|
60
|
+
// this.input.classList.add('with-results');
|
|
61
|
+
this.fire('focus');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
_handleBlur() {
|
|
65
|
+
setTimeout(() => {
|
|
66
|
+
const elem = document.activeElement;
|
|
67
|
+
if (elem === this.rightButton) {
|
|
68
|
+
this.updateStyleWithoutSuggestions();
|
|
69
|
+
// this.input.classList.remove('with-results');
|
|
70
|
+
this.fire('blur');
|
|
71
|
+
} else if (elem === this.input) {
|
|
72
|
+
} else {
|
|
73
|
+
this.updateStyleWithoutSuggestions();
|
|
74
|
+
// this.input.classList.remove('with-results');
|
|
75
|
+
this.fire('blur');
|
|
76
|
+
}
|
|
77
|
+
}, 150); // Timeout to allow clicks on results before hiding
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
_handleEnterSelect(e) {
|
|
81
|
+
const query = this.getText();
|
|
82
|
+
if (query.length > 0) {
|
|
83
|
+
this.fire('search', { query: query, event: e });
|
|
84
|
+
this.input.blur();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
_handleRightButtonSelect(e) {
|
|
89
|
+
if (this.rightButtonState === 'search') {
|
|
90
|
+
const query = this.getText();
|
|
91
|
+
if (query.length > 0) {
|
|
92
|
+
this.fire('search', { query: query, event: e });
|
|
93
|
+
this.input.blur();
|
|
94
|
+
}
|
|
95
|
+
} else if (this.rightButtonState === 'cancel') { // || this.rightButtonState === 'selectedContent') {
|
|
96
|
+
this.fire('cancel', {event: e});
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
_handleLeftButtonSelect(e) {
|
|
101
|
+
if (this.leftButtonState === 'logo') {
|
|
102
|
+
this.input.focus();
|
|
103
|
+
} else if (this.leftButtonState === 'back') { // || this.rightButtonState === 'selectedContent') {
|
|
104
|
+
this.fire('back');
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
updateStyleWithSuggestions() {
|
|
109
|
+
this.element.classList.add('with-results');
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
updateStyleWithoutSuggestions() {
|
|
113
|
+
this.element.classList.remove('with-results');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
updateRightButtonIcon(state) {
|
|
117
|
+
this.rightButtonState = state;
|
|
118
|
+
// if (state === 'default') {
|
|
119
|
+
if (state === 'search') {
|
|
120
|
+
this.rightButton.innerHTML = `<img src="${magnifyingGlassIcon}" alt="Search" />`;
|
|
121
|
+
this.rightButton.style.display = 'flex';
|
|
122
|
+
// this.input.style.paddingLeft = '100px';
|
|
123
|
+
} else if (state === 'cancel') {
|
|
124
|
+
this.rightButton.innerHTML = `<img src="${cancelIcon}" alt="Cancel" />`;
|
|
125
|
+
this.rightButton.style.display = 'flex';
|
|
126
|
+
// this.input.style.paddingLeft = '100px';
|
|
127
|
+
} else if (state === 'none') {
|
|
128
|
+
this.rightButton.style.display = 'none';
|
|
129
|
+
// this.input.style.paddingLeft = '24px';
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
updateLeftButtonIcon(state) {
|
|
134
|
+
this.leftButtonState = state;
|
|
135
|
+
if (state === 'logo') {
|
|
136
|
+
this.leftButton.innerHTML = `<img src="${waygoIcon}" alt="${state}" />`;
|
|
137
|
+
const imgElement = this.leftButton.querySelector('img');
|
|
138
|
+
imgElement.style.width = '16px';
|
|
139
|
+
imgElement.style.height = '16px';
|
|
140
|
+
this.leftButton.style.display = 'flex';
|
|
141
|
+
|
|
142
|
+
// this.input.style.paddingLeft = '50px';
|
|
143
|
+
} else if (state === 'back') {
|
|
144
|
+
this.leftButton.innerHTML = `<img src="${backArrow}" alt="${state}" />`;
|
|
145
|
+
const imgElement = this.leftButton.querySelector('img');
|
|
146
|
+
imgElement.style.width = '20px';
|
|
147
|
+
imgElement.style.height = '20px';
|
|
148
|
+
// this.input.style.paddingLeft = '50px';
|
|
149
|
+
this.leftButton.style.display = 'flex';
|
|
150
|
+
} else if (state === 'none') {
|
|
151
|
+
this.leftButton.style.display = 'none';
|
|
152
|
+
// this.input.style.paddingLeft = '24px';
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
getText() {
|
|
157
|
+
return this.input.value;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
setText(query) {
|
|
161
|
+
this.input.value = query;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
setPlaceholderText(placeholderText) {
|
|
165
|
+
this.input.placeholder = placeholderText;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
getElement() {
|
|
169
|
+
return this.element;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export default SearchBar;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import SearchBarSuggestionsViewCell from "./SearchBarSuggestionsViewCell";
|
|
2
|
+
import Component from "../../core/Component";
|
|
3
|
+
|
|
4
|
+
class SearchBarSuggestionsView extends Component {
|
|
5
|
+
constructor(options = {}) {
|
|
6
|
+
super(options);
|
|
7
|
+
this._initialize();
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
_initialize() {
|
|
11
|
+
this.results = [];
|
|
12
|
+
this.element = document.createElement('div');
|
|
13
|
+
this.element.className = 'search-bar-suggestions-view';
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
updateResults(results) {
|
|
17
|
+
this.results = results;
|
|
18
|
+
this.render();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
render() {
|
|
22
|
+
this.element.innerHTML = ''; // Clear previous results
|
|
23
|
+
|
|
24
|
+
this.results.forEach(r => {
|
|
25
|
+
const cell = new SearchBarSuggestionsViewCell(r);
|
|
26
|
+
cell.on('click', () => this.fire('selectCell', { result: r }));
|
|
27
|
+
this.element.appendChild(cell.getElement());
|
|
28
|
+
});
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
clearResults() {
|
|
33
|
+
this.updateResults([]);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
show() {
|
|
37
|
+
this.element.classList.add('visible');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
hide() {
|
|
41
|
+
this.element.classList.remove('visible');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
getElement() {
|
|
45
|
+
return this.element;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export default SearchBarSuggestionsView;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import Component from "../../core/Component";
|
|
2
|
+
|
|
3
|
+
class SearchBarSuggestionsViewCell extends Component {
|
|
4
|
+
constructor(result, options = {}) {
|
|
5
|
+
super(options);
|
|
6
|
+
this.result = result;
|
|
7
|
+
this._initialize();
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
_initialize() {
|
|
11
|
+
this.element = document.createElement('div');
|
|
12
|
+
this.element.className = 'search-bar-suggestions-view-cell';
|
|
13
|
+
this.render();
|
|
14
|
+
this._setupEventListeners();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
_setupEventListeners() {
|
|
18
|
+
this.element.addEventListener('click', () => this.fire('click', { result: this.result }));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
render() {
|
|
22
|
+
this.element.innerHTML = `
|
|
23
|
+
<div class="suggestion-title">${this.result.name}</div>
|
|
24
|
+
<div class="suggestion-subtitle">${this.result.contextual_location}</div>
|
|
25
|
+
`;
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
getElement() {
|
|
30
|
+
return this.element;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export default SearchBarSuggestionsViewCell;
|