@panoramax/web-viewer 4.0.1-develop-676dfe51 → 4.0.1-develop-35288366

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.
@@ -97,9 +97,10 @@ jest.mock("maplibre-gl", () => ({
97
97
  addControl() {;}
98
98
  addSource() {;}
99
99
  addLayer() {;}
100
- getLayer() {;}
100
+ getLayer(l) { return {id: l}; }
101
101
  setLayoutProperty() {;}
102
102
  setPaintProperty() {;}
103
+ loaded() { return true; }
103
104
  getStyle() {
104
105
  return {
105
106
  layers: [],
@@ -14,6 +14,7 @@
14
14
  * [.getBackground()](#Panoramax.components.ui.Map+getBackground) ⇒ <code>string</code>
15
15
  * [.setBackground(bg)](#Panoramax.components.ui.Map+setBackground)
16
16
  * [.getVisibleUsers()](#Panoramax.components.ui.Map+getVisibleUsers) ⇒ <code>Array.&lt;string&gt;</code>
17
+ * [.onceLayerReady(layerId)](#Panoramax.components.ui.Map+onceLayerReady) ⇒ <code>Promise</code>
17
18
  * [.setVisibleUsers(visibleIds)](#Panoramax.components.ui.Map+setVisibleUsers)
18
19
  * [.filterUserLayersContent(dataType, filter)](#Panoramax.components.ui.Map+filterUserLayersContent)
19
20
  * [.displayPictureMarker(lon, lat, heading, [skipCenter])](#Panoramax.components.ui.Map+displayPictureMarker)
@@ -109,6 +110,18 @@ Get the currently visible users
109
110
 
110
111
  **Kind**: instance method of [<code>Map</code>](#Panoramax.components.ui.Map)
111
112
  **Returns**: <code>Array.&lt;string&gt;</code> - List of visible users
113
+ <a name="Panoramax.components.ui.Map+onceLayerReady"></a>
114
+
115
+ ### map.onceLayerReady(layerId) ⇒ <code>Promise</code>
116
+ Wait for a given map layer to be really available.
117
+
118
+ **Kind**: instance method of [<code>Map</code>](#Panoramax.components.ui.Map)
119
+ **Fulfil**: <code>null</code> When layer is ready.
120
+
121
+ | Param | Type | Description |
122
+ | --- | --- | --- |
123
+ | layerId | <code>string</code> | the layer ID |
124
+
112
125
  <a name="Panoramax.components.ui.Map+setVisibleUsers"></a>
113
126
 
114
127
  ### map.setVisibleUsers(visibleIds)
@@ -14,6 +14,7 @@
14
14
  * [.getBackground()](Map.md/#Panoramax.components.ui.Map+getBackground) ⇒ <code>string</code>
15
15
  * [.setBackground(bg)](Map.md/#Panoramax.components.ui.Map+setBackground)
16
16
  * [.getVisibleUsers()](Map.md/#Panoramax.components.ui.Map+getVisibleUsers) ⇒ <code>Array.&lt;string&gt;</code>
17
+ * [.onceLayerReady(layerId)](Map.md/#Panoramax.components.ui.Map+onceLayerReady) ⇒ <code>Promise</code>
17
18
  * [.setVisibleUsers(visibleIds)](Map.md/#Panoramax.components.ui.Map+setVisibleUsers)
18
19
  * [.filterUserLayersContent(dataType, filter)](Map.md/#Panoramax.components.ui.Map+filterUserLayersContent)
19
20
  * [.displayPictureMarker(lon, lat, heading, [skipCenter])](#Panoramax.components.ui.Map+displayPictureMarker)
@@ -109,6 +110,18 @@ Get the currently visible users
109
110
 
110
111
  **Kind**: instance method of [<code>MapMore</code>](#Panoramax.components.ui.MapMore)
111
112
  **Returns**: <code>Array.&lt;string&gt;</code> - List of visible users
113
+ <a name="Panoramax.components.ui.Map+onceLayerReady"></a>
114
+
115
+ ### mapMore.onceLayerReady(layerId) ⇒ <code>Promise</code>
116
+ Wait for a given map layer to be really available.
117
+
118
+ **Kind**: instance method of [<code>MapMore</code>](#Panoramax.components.ui.MapMore)
119
+ **Fulfil**: <code>null</code> When layer is ready.
120
+
121
+ | Param | Type | Description |
122
+ | --- | --- | --- |
123
+ | layerId | <code>string</code> | the layer ID |
124
+
112
125
  <a name="Panoramax.components.ui.Map+setVisibleUsers"></a>
113
126
 
114
127
  ### mapMore.setVisibleUsers(visibleIds)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@panoramax/web-viewer",
3
- "version": "4.0.1-develop-676dfe51",
3
+ "version": "4.0.1-develop-35288366",
4
4
  "description": "Panoramax web viewer for geolocated pictures",
5
5
  "main": "build/index.js",
6
6
  "author": "Panoramax team",
@@ -108,8 +108,8 @@ export default class CoverageMap extends Basic {
108
108
  this.map.on("picture-click", e => this.select(e.seqId, e.picId));
109
109
  this.map.on("sequence-click", e => this.select(e.seqId));
110
110
 
111
- this.map.waitForEnoughMapLoaded().then(() => {
112
- alterMapState(this.map, this._initParams.getMapPostInit());
111
+ this.map.waitForEnoughMapLoaded().then(async () => {
112
+ await alterMapState(this.map, this._initParams.getMapPostInit());
113
113
  this.map.reloadLayersStyles();
114
114
  this.loader.dismiss();
115
115
  });
@@ -294,7 +294,7 @@ export default class Viewer extends PhotoViewer {
294
294
  });
295
295
  });
296
296
 
297
- alterMapState(this.map, this._initParams.getMapPostInit());
297
+ await alterMapState(this.map, this._initParams.getMapPostInit());
298
298
  initMapKeyboardHandler(this);
299
299
  linkMapAndPhoto(this);
300
300
  }
@@ -145,6 +145,9 @@ export default class PictureLegend extends LitElement {
145
145
  this._parent.psv.addEventListener("picture-loaded", () => {
146
146
  this._onPicChange(this._parent.psv.getPictureMetadata());
147
147
  });
148
+ this._parent.psv.addEventListener("sequence-stopped", () => {
149
+ this._onPicChange(this._parent.psv.getPictureMetadata());
150
+ });
148
151
  });
149
152
  }
150
153
 
@@ -154,12 +157,12 @@ export default class PictureLegend extends LitElement {
154
157
  this._caption = picMeta?.caption;
155
158
 
156
159
  if(picMeta) {
157
- const coordsHash = `${picMeta.gps[0]}/${picMeta.gps[1]}`;
160
+ const coordsHash = `${picMeta.gps[0].toFixed(4)}/${picMeta.gps[1].toFixed(4)}`;
158
161
  if(this._prevSearches[coordsHash]) {
159
162
  this._addr = this._prevSearches[coordsHash];
160
163
  }
161
- else {
162
- this._addrTimer2 = setTimeout(() => this._addr = "", 250);
164
+ else if(!this._parent.psv._sequencePlaying) {
165
+ this._addr = "";
163
166
  this._addrTimer1 = setTimeout(() => {
164
167
  reverseGeocodingNominatim(picMeta.gps[1], picMeta.gps[0])
165
168
  .then(addr => {
@@ -167,7 +170,7 @@ export default class PictureLegend extends LitElement {
167
170
  this._addr = addr;
168
171
  this._prevSearches[coordsHash] = addr;
169
172
  });
170
- }, 750);
173
+ }, 500);
171
174
  }
172
175
  }
173
176
  else {
@@ -326,10 +326,29 @@ export default class Map extends maplibregl.Map {
326
326
  */
327
327
  getVisibleUsers() {
328
328
  return [...this._userLayers].filter(l => (
329
- this.getLayoutProperty(getUserLayerId(l, "pictures"), "visibility") === "visible"
329
+ this.getLayer(getUserLayerId(l, "pictures"))
330
+ && this.getLayoutProperty(getUserLayerId(l, "pictures"), "visibility") === "visible"
330
331
  ));
331
332
  }
332
333
 
334
+ /**
335
+ * Wait for a given map layer to be really available.
336
+ * @param {string} layerId the layer ID
337
+ * @returns {Promise}
338
+ * @fulfil {null} When layer is ready.
339
+ * @memberof Panoramax.components.ui.Map#
340
+ */
341
+ onceLayerReady(layerId) {
342
+ if(this.getLayer(layerId)) {
343
+ return Promise.resolve();
344
+ }
345
+ else {
346
+ return new Promise(resolve => {
347
+ setTimeout(resolve, 250);
348
+ }).then(() => this.onceLayerReady(layerId));
349
+ }
350
+ }
351
+
333
352
  /**
334
353
  * Make given user layers visible on map, and hide all others (if any)
335
354
  * @memberof Panoramax.components.ui.Map#
@@ -343,7 +362,10 @@ export default class Map extends maplibregl.Map {
343
362
  await Promise.all(
344
363
  visibleIds
345
364
  .filter(id => id != "" && !this._userLayers.has(id))
346
- .map(id => this._createPicturesTilesLayer(id))
365
+ .map(id => {
366
+ this._createPicturesTilesLayer(id);
367
+ return this.onceLayerReady(getUserLayerId(id, "pictures"));
368
+ })
347
369
  );
348
370
 
349
371
  // Switch visibility
@@ -375,6 +397,10 @@ export default class Map extends maplibregl.Map {
375
397
  */
376
398
  filterUserLayersContent(dataType, filter) {
377
399
  [...this._userLayers].forEach(l => {
400
+ if(!this.getLayer(getUserLayerId(l, dataType))) {
401
+ console.warn("Layer", getUserLayerId(l, dataType), "not ready");
402
+ return;
403
+ }
378
404
  this.setFilter(getUserLayerId(l, dataType), filter);
379
405
  if(dataType === "sequences" && this.getLayer(getUserLayerId(l, "sequences_plus"))) {
380
406
  this.setFilter(getUserLayerId(l, "sequences_plus"), filter);
@@ -428,11 +454,16 @@ export default class Map extends maplibregl.Map {
428
454
  reloadLayersStyles() {
429
455
  const updateStyle = (layer, style) => {
430
456
  [...this._userLayers].forEach(l => {
457
+ const layerId = getUserLayerId(l, layer);
458
+ if(!this.getLayer(layerId)) {
459
+ console.warn("Layer", layerId, "not ready");
460
+ return;
461
+ }
431
462
  for(let p in style.layout) {
432
- this.setLayoutProperty(getUserLayerId(l, layer), p, style.layout[p]);
463
+ this.setLayoutProperty(layerId, p, style.layout[p]);
433
464
  }
434
465
  for(let p in style.paint) {
435
- this.setPaintProperty(getUserLayerId(l, layer), p, style.paint[p]);
466
+ this.setPaintProperty(layerId, p, style.paint[p]);
436
467
  }
437
468
  });
438
469
  };
@@ -323,7 +323,7 @@ export function alterPSVState(psv, params) {
323
323
  * @param {Map} map The MapLibre component to change.
324
324
  * @param {object} params The parameters to apply.
325
325
  */
326
- export function alterMapState(map, params) {
326
+ export async function alterMapState(map, params) {
327
327
  // Map position
328
328
  const mapOpts = getMapPositionFromString(params.map, map);
329
329
  if(mapOpts) {
@@ -333,7 +333,7 @@ export function alterMapState(map, params) {
333
333
  // Visible users
334
334
  let vu = Array.isArray(params.users) ? params.users : (params.users || "").split(",");
335
335
  if(vu.length === 0 || (vu.length === 1 && vu[0].trim() === "")) { vu = ["geovisio"]; }
336
- map.setVisibleUsers(vu);
336
+ await map.setVisibleUsers(vu);
337
337
 
338
338
  // Change map filters
339
339
  map.setFilters?.(paramsToMapFilters(params));
@@ -81,6 +81,7 @@ describe("getBackground", () => {
81
81
  const p = createParent();
82
82
  const c = document.createElement("div");
83
83
  const m = new Map(p, c);
84
+ m.getLayer = () => undefined;
84
85
  expect(m.getBackground()).toBe("streets");
85
86
  });
86
87
  });
@@ -99,7 +100,7 @@ describe("setBackground", () => {
99
100
  resolve();
100
101
  });
101
102
  m.setBackground("aerial");
102
- })
103
+ });
103
104
  });
104
105
 
105
106
  it("skips if setting streets and no raster available", () => {
@@ -107,6 +108,7 @@ describe("setBackground", () => {
107
108
  const c = document.createElement("div");
108
109
  const m = new Map(p, c);
109
110
  m.setLayoutProperty = jest.fn();
111
+ m.getLayer = () => undefined;
110
112
  m.setBackground("streets");
111
113
  expect(m.setLayoutProperty.mock.calls.length).toBe(0);
112
114
  });
@@ -115,6 +117,7 @@ describe("setBackground", () => {
115
117
  const p = createParent();
116
118
  const c = document.createElement("div");
117
119
  const m = new Map(p, c);
120
+ m.getLayer = () => undefined;
118
121
  expect(() => m.setBackground("aerial")).toThrowError("No aerial imagery available");
119
122
  });
120
123
  });
@@ -138,9 +141,10 @@ describe("setVisibleUsers", () => {
138
141
  const c = document.createElement("div");
139
142
  const m = new Map(p, c);
140
143
  m._createPicturesTilesLayer = (url, id) => m._userLayers.add(id);
141
- m.setLayoutProperty = jest.fn();
144
+ m._addedLayers = [];
145
+ m.addLayer = jest.fn();
142
146
  await m.setVisibleUsers(["blabla"]);
143
- expect(m.setLayoutProperty.mock.calls).toMatchSnapshot();
147
+ expect(m.addLayer.mock.calls).toMatchSnapshot();
144
148
  expect(p.dispatchEvent.mock.calls).toMatchSnapshot();
145
149
  });
146
150
 
@@ -372,47 +372,47 @@ describe("alterMapState", () => {
372
372
 
373
373
  afterEach(() => jest.clearAllMocks());
374
374
 
375
- it("should jump to map position when map param is provided", () => {
375
+ it("should jump to map position when map param is provided", async () => {
376
376
  const params = { map: "10/20/30" };
377
377
  const mapOpts = { center: [30,20], zoom: 10, pitch: 0 };
378
378
 
379
- alterMapState(map, params);
379
+ await alterMapState(map, params);
380
380
  expect(map.jumpTo).toHaveBeenCalledWith(mapOpts);
381
381
  });
382
382
 
383
- it("should set visible users when users param is provided", () => {
383
+ it("should set visible users when users param is provided", async () => {
384
384
  const params = { users: "user1,user2" };
385
- alterMapState(map, params);
385
+ await alterMapState(map, params);
386
386
  expect(map.setVisibleUsers).toHaveBeenCalledWith(["user1", "user2"]);
387
387
  });
388
388
 
389
- it("should set default visible user when users param is empty", () => {
389
+ it("should set default visible user when users param is empty", async () => {
390
390
  const params = { users: "" };
391
- alterMapState(map, params);
391
+ await alterMapState(map, params);
392
392
  expect(map.setVisibleUsers).toHaveBeenCalledWith(["geovisio"]);
393
393
  });
394
394
 
395
- it("should set map filters when params are provided", () => {
395
+ it("should set map filters when params are provided", async () => {
396
396
  const params = { "date_from": "2024-01-01", "pic_score": "ABC" };
397
397
  const filters = { "minDate": "2024-01-01", "qualityscore": [5,4,3] };
398
-
399
- alterMapState(map, params);
398
+ await alterMapState(map, params);
400
399
  expect(map.setFilters).toHaveBeenCalledWith(filters);
401
400
  });
402
401
 
403
- it("should set map background when background param is valid", () => {
402
+ it("should set map background when background param is valid", async () => {
404
403
  const params = { background: "aerial" };
405
- alterMapState(map, params);
404
+ map.setVisibleUsers = () => Promise.resolve();
405
+ await alterMapState(map, params);
406
406
  expect(map.setBackground).toHaveBeenCalledWith("aerial");
407
407
  });
408
408
 
409
- it("should not set map background when background param is invalid", () => {
409
+ it("should not set map background when background param is invalid", async () => {
410
410
  const params = { background: "invalid" };
411
- alterMapState(map, params);
411
+ await alterMapState(map, params);
412
412
  expect(map.setBackground).not.toHaveBeenCalled();
413
413
  });
414
414
 
415
- it("should handle multiple params correctly", () => {
415
+ it("should handle multiple params correctly", async () => {
416
416
  const params = {
417
417
  map: "15/7/6",
418
418
  users: "user1,user2",
@@ -422,7 +422,7 @@ describe("alterMapState", () => {
422
422
  const mapOpts = { center: [6, 7], zoom: 15, pitch: 0 };
423
423
  const filters = { camera: "value1" };
424
424
 
425
- alterMapState(map, params);
425
+ await alterMapState(map, params);
426
426
  expect(map.jumpTo).toHaveBeenCalledWith(mapOpts);
427
427
  expect(map.setVisibleUsers).toHaveBeenCalledWith(["user1", "user2"]);
428
428
  expect(map.setFilters).toHaveBeenCalledWith(filters);