mobility-toolbox-js 2.0.0 → 2.0.1-beta.13

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.
Files changed (102) hide show
  1. package/api/RoutingAPI.js +15 -0
  2. package/api/RoutingAPI.test.js +25 -0
  3. package/api/StopsAPI.js +12 -0
  4. package/api/StopsAPI.test.js +22 -0
  5. package/api/TralisAPI.js +359 -0
  6. package/api/TralisAPI.test.js +67 -0
  7. package/api/{tralis/TralisAPIUtils.js → TralisAPIUtils.js} +2 -32
  8. package/api/index.js +3 -3
  9. package/{ol/README.md → api/typedefs.js} +0 -0
  10. package/common/Tracker.js +14 -118
  11. package/common/api/HttpAPI.js +30 -0
  12. package/common/api/HttpAPI.test.js +50 -0
  13. package/common/api/WebSocketAPI.js +175 -0
  14. package/{api/tralis/WebSocketConnector.test.js → common/api/WebSocketAPI.test.js} +100 -145
  15. package/common/controls/Control.js +26 -91
  16. package/common/controls/Control.test.js +32 -43
  17. package/common/index.js +4 -0
  18. package/common/layers/Layer.js +53 -244
  19. package/common/layers/Layer.test.js +185 -244
  20. package/common/mixins/CopyrightMixin.js +20 -44
  21. package/common/mixins/SearchMixin.js +100 -166
  22. package/common/mixins/TralisLayerMixin.js +443 -894
  23. package/common/styles/index.js +4 -4
  24. package/common/styles/trackerDefaultStyle.js +39 -175
  25. package/common/styles/trackerDelayStyle.js +2 -11
  26. package/common/styles/trackerSimpleStyle.js +4 -8
  27. package/common/trackerConfig.js +61 -99
  28. package/common/trackerConfig.test.js +15 -17
  29. package/common/typedefs.js +0 -23
  30. package/common/utils/createTrackerFilters.js +10 -41
  31. package/common/utils/createTrackerFilters.test.js +40 -56
  32. package/common/utils/getMapboxMapCopyrights.js +3 -16
  33. package/common/utils/getMapboxMapCopyrights.test.js +32 -39
  34. package/common/utils/getMapboxStyleUrl.js +3 -13
  35. package/common/utils/getVehiclePosition.js +3 -33
  36. package/common/utils/index.js +5 -6
  37. package/common/utils/removeDuplicate.js +3 -17
  38. package/common/utils/removeDuplicate.test.js +17 -20
  39. package/common/utils/sortByDelay.js +2 -7
  40. package/common/utils/timeUtils.js +8 -32
  41. package/common/utils/timeUtils.test.js +7 -13
  42. package/index.js +8 -2
  43. package/mapbox/controls/CopyrightControl.js +9 -38
  44. package/mapbox/controls/index.js +1 -0
  45. package/mapbox/index.js +4 -3
  46. package/mapbox/layers/Layer.js +15 -76
  47. package/mapbox/layers/Layer.test.js +81 -101
  48. package/mapbox/layers/TralisLayer.js +46 -193
  49. package/mapbox/layers/TralisLayer.test.js +12 -14
  50. package/mapbox/layers/index.js +2 -0
  51. package/mapbox/utils.js +7 -21
  52. package/mbt.js +50444 -0
  53. package/mbt.js.map +7 -0
  54. package/mbt.min.js +1005 -0
  55. package/mbt.min.js.map +7 -0
  56. package/ol/controls/CopyrightControl.js +8 -46
  57. package/ol/controls/CopyrightControl.test.js +75 -121
  58. package/ol/controls/RoutingControl.js +167 -532
  59. package/ol/controls/RoutingControl.test.js +99 -164
  60. package/ol/controls/StopFinderControl.js +3 -31
  61. package/ol/controls/StopFinderControl.test.js +18 -29
  62. package/ol/controls/index.js +3 -0
  63. package/ol/index.js +5 -13
  64. package/ol/layers/Layer.js +23 -128
  65. package/ol/layers/Layer.test.js +79 -102
  66. package/ol/layers/MapboxLayer.js +62 -237
  67. package/ol/layers/MapboxLayer.test.js +58 -84
  68. package/ol/layers/MapboxStyleLayer.js +38 -268
  69. package/ol/layers/MapboxStyleLayer.test.js +97 -128
  70. package/ol/layers/MaplibreLayer.js +46 -187
  71. package/ol/layers/RoutingLayer.js +21 -51
  72. package/ol/layers/RoutingLayer.test.js +15 -24
  73. package/ol/layers/TralisLayer.js +102 -276
  74. package/ol/layers/TralisLayer.test.js +32 -50
  75. package/ol/layers/VectorLayer.js +3 -24
  76. package/ol/layers/VectorLayer.test.js +34 -45
  77. package/ol/layers/WMSLayer.js +15 -57
  78. package/ol/layers/WMSLayer.test.js +35 -43
  79. package/ol/layers/index.js +8 -0
  80. package/ol/styles/fullTrajectoryDelayStyle.js +11 -15
  81. package/ol/styles/fullTrajectoryStyle.js +17 -25
  82. package/ol/styles/index.js +2 -2
  83. package/package.json +35 -62
  84. package/api/routing/RoutingAPI.js +0 -44
  85. package/api/routing/RoutingAPI.test.js +0 -41
  86. package/api/stops/StopsAPI.js +0 -41
  87. package/api/stops/StopsAPI.test.js +0 -34
  88. package/api/tralis/TralisAPI.js +0 -731
  89. package/api/tralis/TralisAPI.test.js +0 -75
  90. package/api/tralis/WebSocketConnector.js +0 -338
  91. package/api/tralis/typedefs.js +0 -81
  92. package/common/api/api.js +0 -64
  93. package/common/api/api.test.js +0 -68
  94. package/index.js.map +0 -1
  95. package/module.js +0 -23
  96. package/ol/controls/snapshots/RoutingControlRouteGen10.json +0 -58
  97. package/ol/controls/snapshots/RoutingControlRouteGen100.json +0 -292
  98. package/ol/controls/snapshots/RoutingControlRouteGen30.json +0 -69
  99. package/ol/controls/snapshots/RoutingControlRouteGen5.json +0 -58
  100. package/ol/controls/snapshots/RoutingControlRouteOSM.json +0 -759
  101. package/ol/controls/snapshots/RoutingControlStation1.json +0 -60
  102. package/ol/controls/snapshots/RoutingControlStation2.json +0 -49
@@ -1,217 +1,106 @@
1
- /* eslint-disable no-underscore-dangle */
2
- import { toLonLat } from 'ol/proj';
3
- import { Map } from 'maplibre-gl';
4
- import Source from 'ol/source/Source';
5
- import OLLayer from 'ol/layer/Layer';
6
- import GeoJSON from 'ol/format/GeoJSON';
7
- import { toDegrees } from 'ol/math';
8
- import Layer from './Layer';
9
- import { getMapboxMapCopyrights, getMapboxStyleUrl } from '../../common/utils';
10
-
11
- /**
12
- * A class representing MaplibreLayer to display on BasicMap
13
- *
14
- * @example
15
- * import { MaplibreLayer } from 'mobility-toolbox-js/ol';
16
- *
17
- * const layer = new MaplibreLayer({
18
- * url: 'https://maps.geops.io/styles/travic_v2/style.json',
19
- * apikey: 'yourApiKey',
20
- * });
21
- *
22
- * @classproperty {ol/Map~Map} map - The map where the layer is displayed.
23
- * @extends {Layer}
24
- */
1
+ import { toLonLat } from "ol/proj";
2
+ import { Map } from "maplibre-gl";
3
+ import Source from "ol/source/Source";
4
+ import OLLayer from "ol/layer/Layer";
5
+ import GeoJSON from "ol/format/GeoJSON";
6
+ import { toDegrees } from "ol/math";
7
+ import Layer from "./Layer";
8
+ import { getMapboxMapCopyrights, getMapboxStyleUrl } from "../../common/utils";
25
9
  export default class MaplibreLayer extends Layer {
26
- /**
27
- * Constructor.
28
- *
29
- * @param {Object} options
30
- * @param {boolean} [options.preserveDrawingBuffer=false] If true able to export the canvas.
31
- * @param {number} [options.fadeDuration=300] Duration of the fade effect in ms.
32
- */
33
10
  constructor(options = {}) {
34
11
  const mbLayer = new OLLayer({
35
12
  source: new Source({}),
36
13
  render: (frameState) => {
37
14
  if (!this.mbMap) {
38
- // eslint-disable-next-line no-console
39
15
  console.warn("Mapbox map doesn't exist.");
40
16
  return null;
41
17
  }
42
-
43
18
  const canvas = this.mbMap.getCanvas();
44
19
  const { viewState } = frameState;
45
-
46
20
  const opacity = this.olLayer.getOpacity();
47
21
  canvas.style.opacity = opacity;
48
-
49
- // adjust view parameters in mapbox
50
22
  this.mbMap.jumpTo({
51
23
  center: toLonLat(viewState.center),
52
24
  zoom: viewState.zoom - 1,
53
25
  bearing: toDegrees(-viewState.rotation),
54
- animate: false,
26
+ animate: false
55
27
  });
56
-
57
28
  if (!canvas.isConnected) {
58
- // The canvas is not connected to the DOM, request a map rendering at the next animation frame
59
- // to set the canvas size.
60
29
  this.map.render();
61
- } else if (
62
- canvas.width !== frameState.size[0] ||
63
- canvas.height !== frameState.size[1]
64
- ) {
30
+ } else if (canvas.width !== frameState.size[0] || canvas.height !== frameState.size[1]) {
65
31
  this.mbMap.resize();
66
32
  }
67
-
68
33
  this.mbMap.redraw();
69
-
70
34
  return this.mbMap.getContainer();
71
- },
35
+ }
72
36
  });
73
-
74
37
  super({
75
38
  ...options,
76
- olLayer: mbLayer,
39
+ olLayer: mbLayer
77
40
  });
78
-
79
- /**
80
- * Url of the mapbox style.
81
- * @type {string}
82
- * @private
83
- */
84
41
  this.styleUrl = options.url;
85
-
86
- /**
87
- * Api key for the url of the mapbox style.
88
- * If set to false, the apiKey is not required.
89
- * @type {string}
90
- * @private
91
- */
92
42
  this.apiKey = options.apiKey;
93
-
94
- /**
95
- * Name of the apiKey to set in the url request.
96
- * Default is 'key'.
97
- * @type {string}
98
- * @private
99
- */
100
- this.apiKeyName = options.apiKeyName || 'key';
101
-
102
- /** @ignore */
43
+ this.apiKeyName = options.apiKeyName || "key";
103
44
  this.updateAttribution = this.updateAttribution.bind(this);
104
45
  }
105
-
106
- /**
107
- * Initialize the layer and listen to feature clicks.
108
- * @param {ol/Map~Map} map
109
- */
110
- init(map) {
111
- super.init(map);
112
-
46
+ attachToMap(map) {
47
+ super.attachToMap(map);
113
48
  if (!this.map) {
114
49
  return;
115
50
  }
116
-
117
- /**
118
- * The feature format.
119
- * @type {ol/format/GeoJSON}
120
- */
121
51
  this.format = new GeoJSON({
122
- featureProjection: this.map.getView().getProjection(),
52
+ featureProjection: this.map.getView().getProjection()
123
53
  });
124
-
125
54
  this.loadMbMap();
126
55
  }
127
-
128
- /**
129
- * Terminate what was initialized in init function. Remove layer, events...
130
- */
131
- terminate() {
56
+ detachFromMap() {
132
57
  if (this.mbMap) {
133
- this.mbMap.off('idle', this.updateAttribution);
134
- // Some asynchrone repaints are triggered even if the mbMap has been removed,
135
- // to avoid display of errors we set an empty function.
136
- this.mbMap.triggerRepaint = () => {};
58
+ this.mbMap.off("idle", this.updateAttribution);
59
+ this.mbMap.triggerRepaint = () => {
60
+ };
137
61
  this.mbMap.remove();
138
62
  this.mbMap = null;
139
63
  }
140
64
  this.loaded = false;
141
- super.terminate();
65
+ super.detachFromMap();
142
66
  }
143
-
144
- /**
145
- * Returns a style URL with apiKey & apiKeyName infos.
146
- * @private
147
- */
148
67
  createStyleUrl() {
149
68
  return getMapboxStyleUrl(this.apiKey, this.apiKeyName, this.styleUrl);
150
69
  }
151
-
152
- /**
153
- * Create the mapbox map.
154
- * @private
155
- */
156
70
  loadMbMap() {
157
- this.olListenersKeys.push(
158
- this.map.on('change:target', () => {
159
- this.loadMbMap();
160
- }),
161
- );
162
-
71
+ this.olListenersKeys.push(this.map.on("change:target", () => {
72
+ this.loadMbMap();
73
+ }));
163
74
  if (!this.map.getTargetElement()) {
164
75
  return;
165
76
  }
166
-
167
77
  if (!this.visible) {
168
- // On next change of visibility we load the map
169
- this.olListenersKeys.push(
170
- this.once('change:visible', () => {
171
- this.loadMbMap();
172
- }),
173
- );
78
+ this.olListenersKeys.push(this.once("change:visible", () => {
79
+ this.loadMbMap();
80
+ }));
174
81
  return;
175
82
  }
176
-
177
- const container = document.createElement('div');
178
- container.style.position = 'absolute';
179
- container.style.width = '100%';
180
- container.style.height = '100%';
181
-
182
- /**
183
- * A mapbox map
184
- * @type {mapboxgl.Map}
185
- */
83
+ const container = document.createElement("div");
84
+ container.style.position = "absolute";
85
+ container.style.width = "100%";
86
+ container.style.height = "100%";
186
87
  this.mbMap = new Map({
187
88
  style: this.createStyleUrl(),
188
89
  container,
189
90
  interactive: false,
190
91
  trackResize: false,
191
92
  attributionControl: false,
192
- ...(this.options.mapOptions || {}),
93
+ ...this.options.mapOptions || {}
193
94
  });
194
-
195
- this.mbMap.once('load', () => {
196
- /**
197
- * Is the map loaded.
198
- * @type {boolean}
199
- */
95
+ this.mbMap.once("load", () => {
200
96
  this.loaded = true;
201
-
202
97
  this.dispatchEvent({
203
- type: 'load',
204
- target: this,
98
+ type: "load",
99
+ target: this
205
100
  });
206
101
  });
207
-
208
- this.mbMap.on('idle', this.updateAttribution);
102
+ this.mbMap.on("idle", this.updateAttribution);
209
103
  }
210
-
211
- /**
212
- * Update attributions of the source.
213
- * @private
214
- */
215
104
  updateAttribution(evt) {
216
105
  const newAttributions = getMapboxMapCopyrights(evt.target) || [];
217
106
  if (this.copyrights?.toString() !== newAttributions.toString()) {
@@ -219,61 +108,31 @@ export default class MaplibreLayer extends Layer {
219
108
  this.olLayer.getSource().setAttributions(newAttributions);
220
109
  }
221
110
  }
222
-
223
- /**
224
- * Request feature information for a given coordinate.
225
- * @param {ol/coordinate~Coordinate} coordinate Coordinate to request the information at.
226
- * @param {Object} options A [mapboxgl.Map#queryrenderedfeatures](https://docs.mapbox.com/mapbox-gl-js/api/map/#map#queryrenderedfeatures) options parameter.
227
- * @return {Promise<FeatureInfo>} Promise with features, layer and coordinate. The original Mapbox feature is available as a property named 'mapboxFeature'.
228
- */
229
111
  getFeatureInfoAtCoordinate(coordinate, options) {
230
- // Ignore the getFeatureInfo until the mapbox map is loaded
231
- if (
232
- !options ||
233
- !this.format ||
234
- !this.mbMap ||
235
- !this.mbMap.isStyleLoaded()
236
- ) {
112
+ if (!options || !this.format || !this.mbMap || !this.mbMap.isStyleLoaded()) {
237
113
  return Promise.resolve({ coordinate, features: [], layer: this });
238
114
  }
239
-
240
115
  let pixel = coordinate && this.mbMap.project(toLonLat(coordinate));
241
-
242
116
  if (this.hitTolerance) {
243
117
  const { x, y } = pixel;
244
118
  pixel = [
245
119
  { x: x - this.hitTolerance, y: y - this.hitTolerance },
246
- { x: x + this.hitTolerance, y: y + this.hitTolerance },
120
+ { x: x + this.hitTolerance, y: y + this.hitTolerance }
247
121
  ];
248
122
  }
249
-
250
- // At this point we get GeoJSON Mapbox feature, we transform it to an OpenLayers
251
- // feature to be consistent with other layers.
252
- const features = this.mbMap
253
- .queryRenderedFeatures(pixel, options)
254
- .map((feature) => {
255
- const olFeature = this.format.readFeature(feature);
256
- if (olFeature) {
257
- // We save the original mapbox feature to avoid losing informations
258
- // potentially needed for other functionnality like highlighting
259
- // (id, layer id, source, sourceLayer ...)
260
- olFeature.set('mapboxFeature', feature);
261
- }
262
- return olFeature;
263
- });
264
-
123
+ const features = this.mbMap.queryRenderedFeatures(pixel, options).map((feature) => {
124
+ const olFeature = this.format.readFeature(feature);
125
+ if (olFeature) {
126
+ olFeature.set("mapboxFeature", feature);
127
+ }
128
+ return olFeature;
129
+ });
265
130
  return Promise.resolve({
266
131
  layer: this,
267
132
  features,
268
- coordinate,
133
+ coordinate
269
134
  });
270
135
  }
271
-
272
- /**
273
- * Create a copy of the MapboxLayer.
274
- * @param {Object} newOptions Options to override
275
- * @return {MapboxLayer} A MapboxLayer
276
- */
277
136
  clone(newOptions) {
278
137
  return new MaplibreLayer({ ...this.options, ...newOptions });
279
138
  }
@@ -1,91 +1,61 @@
1
- import { Circle, Fill, Stroke, Style } from 'ol/style';
2
- import { Vector as VectorSource } from 'ol/source';
3
- import { Vector } from 'ol/layer';
4
- import Layer from './Layer';
5
-
1
+ import { Circle, Fill, Stroke, Style } from "ol/style";
2
+ import { Vector as VectorSource } from "ol/source";
3
+ import { Vector } from "ol/layer";
4
+ import Layer from "./Layer";
6
5
  const circleStyle = new Circle({
7
6
  radius: 6,
8
7
  fill: new Fill({
9
- color: [255, 0, 0, 1],
8
+ color: [255, 0, 0, 1]
10
9
  }),
11
10
  stroke: new Stroke({
12
11
  color: [0, 0, 0, 1],
13
- width: 1,
14
- }),
12
+ width: 1
13
+ })
15
14
  });
16
-
17
15
  const blackBorder = new Style({
18
16
  stroke: new Stroke({
19
17
  color: [0, 0, 0, 1],
20
- width: 5,
21
- }),
18
+ width: 5
19
+ })
22
20
  });
23
-
24
21
  const redLine = new Style({
25
22
  image: circleStyle,
26
23
  stroke: new Stroke({
27
24
  color: [255, 0, 0, 1],
28
- width: 3,
29
- }),
25
+ width: 3
26
+ })
30
27
  });
31
-
32
28
  const dashedRedLine = new Style({
33
29
  image: circleStyle,
34
30
  stroke: new Stroke({
35
31
  color: [255, 0, 0, 1],
36
32
  width: 3,
37
- lineDash: [1, 10],
38
- }),
33
+ lineDash: [1, 10]
34
+ })
39
35
  });
40
-
41
36
  const defaultStyleFunction = (feature, resolution) => {
42
- const minResolution = feature.get('minResolution');
43
- const maxResolution = feature.get('maxResolution');
37
+ const minResolution = feature.get("minResolution");
38
+ const maxResolution = feature.get("maxResolution");
44
39
  const inRange = resolution <= minResolution && resolution > maxResolution;
45
-
46
40
  if (minResolution && maxResolution && !inRange) {
47
41
  return null;
48
42
  }
49
- const mot = feature.get('mot');
50
-
51
- if (mot !== 'foot') {
43
+ const mot = feature.get("mot");
44
+ if (mot !== "foot") {
52
45
  return [blackBorder, redLine];
53
46
  }
54
-
55
47
  return [dashedRedLine];
56
48
  };
57
-
58
- /**
59
- * A class use to display vector data.
60
- *
61
- * @classproperty {ol/Map~Map} map - The map where the layer is displayed.
62
- * @extends {Layer}
63
- */
64
49
  class RoutingLayer extends Layer {
65
- /**
66
- * Constructor.
67
- * @param {Object} [options]
68
- * @param {ol/style/Style~StyleLike} [options.style] Style to be used for routes, uses (ol/StyleLike) [https://openlayers.org/en/latest/apidoc/module-ol_style_Style.html#~StyleLike] instances
69
- */
70
50
  constructor(options = {}) {
71
51
  super(options);
72
-
73
- this.olLayer =
74
- options.olLayer ||
75
- new Vector({
76
- source: new VectorSource(),
77
- style: options.style || defaultStyleFunction,
78
- });
52
+ this.olLayer = options.olLayer || new Vector({
53
+ source: new VectorSource(),
54
+ style: options.style || defaultStyleFunction
55
+ });
79
56
  }
80
-
81
- /**
82
- * Create a copy of the RoutingLayer.
83
- * @param {Object} newOptions Options to override
84
- * @return {RoutingLayer} A RoutingLayer
85
- */
86
57
  clone(newOptions) {
87
58
  return new RoutingLayer({ ...this.options, ...newOptions });
88
59
  }
89
60
  }
90
-
91
61
  export default RoutingLayer;
@@ -1,49 +1,40 @@
1
- import fetch from 'jest-fetch-mock';
2
- import Map from 'ol/Map';
3
- import View from 'ol/View';
4
- import RoutingLayer from './RoutingLayer';
5
-
1
+ import fetch from "jest-fetch-mock";
2
+ import Map from "ol/Map";
3
+ import View from "ol/View";
4
+ import RoutingLayer from "./RoutingLayer";
6
5
  let layer;
7
6
  let onClick;
8
7
  let olMap;
9
-
10
- describe('RoutingLayer', () => {
8
+ describe("RoutingLayer", () => {
11
9
  beforeEach(() => {
12
10
  global.fetch = fetch;
13
11
  fetch.resetMocks();
14
-
15
12
  onClick = jest.fn();
16
13
  layer = new RoutingLayer({
17
14
  onClick,
18
- apiKey: 'apiKey',
15
+ apiKey: "apiKey"
19
16
  });
20
-
21
17
  olMap = new Map({
22
18
  view: new View({
23
19
  center: [831634, 5933959],
24
- zoom: 9,
25
- }),
20
+ zoom: 9
21
+ })
26
22
  });
27
23
  });
28
-
29
- test('should be instanced.', () => {
24
+ test("should be instanced.", () => {
30
25
  expect(layer).toBeInstanceOf(RoutingLayer);
31
26
  expect(layer.clickCallbacks[0]).toBe(onClick);
32
27
  });
33
-
34
- test('should called terminate on initalization.', () => {
35
- const spy = jest.spyOn(layer, 'terminate');
36
-
28
+ test("should called terminate on initalization.", () => {
29
+ const spy = jest.spyOn(layer, "detachFromMap");
37
30
  fetch.mockResponseOnce(JSON.stringify(global.fetchTrajectoriesResponse));
38
-
39
- layer.init(olMap);
31
+ layer.attachToMap(olMap);
40
32
  expect(spy).toHaveBeenCalledTimes(1);
41
33
  });
42
-
43
- test('should clone', () => {
44
- const clone = layer.clone({ name: 'clone' });
34
+ test("should clone", () => {
35
+ const clone = layer.clone({ name: "clone" });
45
36
  expect(clone).not.toBe(layer);
46
- expect(clone.name).toBe('clone');
37
+ expect(clone.name).toBe("clone");
47
38
  expect(clone).toBeInstanceOf(RoutingLayer);
48
39
  });
49
40
  });