mobility-toolbox-js 1.6.0-beta.7 → 1.6.0-beta.8
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/common/mixins/TrackerLayerMixin.js +99 -1
- package/common/mixins/TrajservLayerMixin.js +1 -141
- package/common/mixins/TralisLayerMixin.js +6 -0
- package/common/trackerConfig.js +16 -13
- package/common/trackerConfig.test.js +38 -0
- package/common/utils/createTrackerFilters.js +82 -0
- package/common/utils/createTrackerFilters.test.js +89 -0
- package/common/utils/trackerStyle.js +23 -21
- package/index.js +1 -1
- package/index.js.map +1 -1
- package/mapbox/layers/TralisLayer.js +0 -1
- package/ol/layers/TralisLayer.js +30 -20
- package/package.json +1 -1
|
@@ -3,8 +3,15 @@
|
|
|
3
3
|
import { buffer, containsCoordinate } from 'ol/extent';
|
|
4
4
|
import { unByKey } from 'ol/Observable';
|
|
5
5
|
import Feature from 'ol/Feature';
|
|
6
|
+
import qs from 'query-string';
|
|
6
7
|
import Tracker from '../Tracker';
|
|
7
8
|
import { timeSteps } from '../trackerConfig';
|
|
9
|
+
import createFilters from '../utils/createTrackerFilters';
|
|
10
|
+
|
|
11
|
+
/* Permalink parameter used to filters vehicles */
|
|
12
|
+
const LINE_FILTER = 'publishedlinename';
|
|
13
|
+
const ROUTE_FILTER = 'tripnumber';
|
|
14
|
+
const OPERATOR_FILTER = 'operator';
|
|
8
15
|
|
|
9
16
|
/**
|
|
10
17
|
* TrackerLayerInterface.
|
|
@@ -129,6 +136,13 @@ const TrackerLayerMixin = (Base) =>
|
|
|
129
136
|
live,
|
|
130
137
|
} = options;
|
|
131
138
|
|
|
139
|
+
let {
|
|
140
|
+
regexPublishedLineName,
|
|
141
|
+
publishedLineName,
|
|
142
|
+
tripNumber,
|
|
143
|
+
operator,
|
|
144
|
+
} = options;
|
|
145
|
+
|
|
132
146
|
const initTrackerOptions = {
|
|
133
147
|
pixelRatio: pixelRatio || window.devicePixelRatio || 1,
|
|
134
148
|
interpolate,
|
|
@@ -314,6 +328,74 @@ const TrackerLayerMixin = (Base) =>
|
|
|
314
328
|
default: false,
|
|
315
329
|
writable: true,
|
|
316
330
|
},
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Filter properties used in combination with permalink parameters.
|
|
334
|
+
*/
|
|
335
|
+
publishedLineName: {
|
|
336
|
+
get: () => {
|
|
337
|
+
return publishedLineName;
|
|
338
|
+
},
|
|
339
|
+
set: (newPublishedLineName) => {
|
|
340
|
+
publishedLineName = newPublishedLineName;
|
|
341
|
+
this.updateFilters();
|
|
342
|
+
},
|
|
343
|
+
},
|
|
344
|
+
tripNumber: {
|
|
345
|
+
get: () => {
|
|
346
|
+
return tripNumber;
|
|
347
|
+
},
|
|
348
|
+
set: (newTripNumber) => {
|
|
349
|
+
tripNumber = newTripNumber;
|
|
350
|
+
this.updateFilters();
|
|
351
|
+
},
|
|
352
|
+
},
|
|
353
|
+
operator: {
|
|
354
|
+
get: () => {
|
|
355
|
+
return operator;
|
|
356
|
+
},
|
|
357
|
+
set: (newOperator) => {
|
|
358
|
+
operator = newOperator;
|
|
359
|
+
this.updateFilters();
|
|
360
|
+
},
|
|
361
|
+
},
|
|
362
|
+
regexPublishedLineName: {
|
|
363
|
+
get: () => {
|
|
364
|
+
return regexPublishedLineName;
|
|
365
|
+
},
|
|
366
|
+
set: (newRegex) => {
|
|
367
|
+
regexPublishedLineName = newRegex;
|
|
368
|
+
this.updateFilters();
|
|
369
|
+
},
|
|
370
|
+
},
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Style properties.
|
|
374
|
+
*/
|
|
375
|
+
delayDisplay: {
|
|
376
|
+
value: options.delayDisplay || 300000,
|
|
377
|
+
writable: true,
|
|
378
|
+
},
|
|
379
|
+
delayOutlineColor: {
|
|
380
|
+
value: options.delayOutlineColor || '#000000',
|
|
381
|
+
writable: true,
|
|
382
|
+
},
|
|
383
|
+
useDelayStyle: {
|
|
384
|
+
value: options.useDelayStyle || false,
|
|
385
|
+
writable: true,
|
|
386
|
+
},
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Debug properties.
|
|
390
|
+
*/
|
|
391
|
+
// Not used anymore, but could be useful for debugging.
|
|
392
|
+
// showVehicleTraj: {
|
|
393
|
+
// value:
|
|
394
|
+
// options.showVehicleTraj !== undefined
|
|
395
|
+
// ? options.showVehicleTraj
|
|
396
|
+
// : true,
|
|
397
|
+
// writable: true,
|
|
398
|
+
// },
|
|
317
399
|
});
|
|
318
400
|
}
|
|
319
401
|
|
|
@@ -375,6 +457,7 @@ const TrackerLayerMixin = (Base) =>
|
|
|
375
457
|
*/
|
|
376
458
|
start() {
|
|
377
459
|
this.stop();
|
|
460
|
+
this.updateFilters();
|
|
378
461
|
this.tracker.setVisible(true);
|
|
379
462
|
this.renderTrajectories();
|
|
380
463
|
this.startUpdateTime();
|
|
@@ -587,10 +670,25 @@ const TrackerLayerMixin = (Base) =>
|
|
|
587
670
|
const roundedZoom = Math.round(zoom);
|
|
588
671
|
const timeStep = timeSteps[roundedZoom] || 25;
|
|
589
672
|
const nextTick = Math.max(25, timeStep / this.speed);
|
|
590
|
-
console.log(`Next render in ${nextTick} ms.`);
|
|
673
|
+
// console.log(`Next render in ${nextTick} ms.`);
|
|
591
674
|
return nextTick;
|
|
592
675
|
}
|
|
593
676
|
|
|
677
|
+
/**
|
|
678
|
+
* Update filter provided by properties or permalink.
|
|
679
|
+
*/
|
|
680
|
+
updateFilters() {
|
|
681
|
+
// Setting filters from the permalink if no values defined by the layer.
|
|
682
|
+
const parameters = qs.parse(window.location.search.toLowerCase());
|
|
683
|
+
// filter is the property in TrackerLayerMixin.
|
|
684
|
+
this.filter = createFilters(
|
|
685
|
+
this.publishedLineName || parameters[LINE_FILTER],
|
|
686
|
+
this.tripNumber || parameters[ROUTE_FILTER],
|
|
687
|
+
this.operator || parameters[OPERATOR_FILTER],
|
|
688
|
+
this.regexPublishedLineName,
|
|
689
|
+
);
|
|
690
|
+
}
|
|
691
|
+
|
|
594
692
|
/**
|
|
595
693
|
* @private
|
|
596
694
|
*/
|
|
@@ -101,74 +101,6 @@ export class TrajservLayerInterface {
|
|
|
101
101
|
defaultStyle(trajectory, viewState) {}
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
const LINE_FILTER = 'publishedlinename';
|
|
105
|
-
const ROUTE_FILTER = 'tripnumber';
|
|
106
|
-
const OPERATOR_FILTER = 'operator';
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Create a array of filter functions based on some parameters.
|
|
110
|
-
* @param {string} line
|
|
111
|
-
* @param {string} route
|
|
112
|
-
* @param {string} operator
|
|
113
|
-
* @param {string} regexLine
|
|
114
|
-
* @private
|
|
115
|
-
*/
|
|
116
|
-
const createFilters = (line, route, operator, regexLine) => {
|
|
117
|
-
const filterList = [];
|
|
118
|
-
|
|
119
|
-
if (!line && !route && !operator && !regexLine) {
|
|
120
|
-
return null;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
if (regexLine) {
|
|
124
|
-
const regexLineList =
|
|
125
|
-
typeof regexLine === 'string' ? [regexLine] : regexLine;
|
|
126
|
-
const lineFilter = (t) =>
|
|
127
|
-
regexLineList.some((tr) => new RegExp(tr, 'i').test(t.name));
|
|
128
|
-
filterList.push(lineFilter);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
if (line) {
|
|
132
|
-
const lineFiltersList = typeof line === 'string' ? line.split(',') : line;
|
|
133
|
-
const lineList = lineFiltersList.map((l) =>
|
|
134
|
-
l.replace(/\s+/g, '').toUpperCase(),
|
|
135
|
-
);
|
|
136
|
-
const lineFilter = (l) =>
|
|
137
|
-
lineList.some((filter) => filter === l.name.toUpperCase());
|
|
138
|
-
filterList.push(lineFilter);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
if (route) {
|
|
142
|
-
const routes = typeof route === 'string' ? route.split(',') : route;
|
|
143
|
-
const routeList = routes.map((item) => parseInt(item, 10));
|
|
144
|
-
const routeFilter = (item) => {
|
|
145
|
-
const routeId = parseInt(item.routeIdentifier.split('.')[0], 10);
|
|
146
|
-
return routeList.some((id) => id === routeId);
|
|
147
|
-
};
|
|
148
|
-
filterList.push(routeFilter);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
if (operator) {
|
|
152
|
-
const operatorList = typeof operator === 'string' ? [operator] : operator;
|
|
153
|
-
const operatorFilter = (t) =>
|
|
154
|
-
operatorList.some((op) => new RegExp(op, 'i').test(t.operator));
|
|
155
|
-
filterList.push(operatorFilter);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
if (!filterList.length) {
|
|
159
|
-
return null;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
return (t) => {
|
|
163
|
-
for (let i = 0; i < filterList.length; i += 1) {
|
|
164
|
-
if (!filterList[i](t)) {
|
|
165
|
-
return false;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
return true;
|
|
169
|
-
};
|
|
170
|
-
};
|
|
171
|
-
|
|
172
104
|
/**
|
|
173
105
|
* Mixin for TrajservLayerInterface.
|
|
174
106
|
*
|
|
@@ -185,12 +117,6 @@ const TrajservLayerMixin = (TrackerLayer) =>
|
|
|
185
117
|
*/
|
|
186
118
|
defineProperties(options) {
|
|
187
119
|
super.defineProperties(options);
|
|
188
|
-
let {
|
|
189
|
-
regexPublishedLineName,
|
|
190
|
-
publishedLineName,
|
|
191
|
-
tripNumber,
|
|
192
|
-
operator,
|
|
193
|
-
} = options;
|
|
194
120
|
|
|
195
121
|
let requestIntervalSeconds = 3;
|
|
196
122
|
let defaultApi;
|
|
@@ -205,25 +131,6 @@ const TrajservLayerMixin = (TrackerLayer) =>
|
|
|
205
131
|
defaultApi = new TrajservAPI(apiOptions);
|
|
206
132
|
}
|
|
207
133
|
Object.defineProperties(this, {
|
|
208
|
-
showVehicleTraj: {
|
|
209
|
-
value:
|
|
210
|
-
options.showVehicleTraj !== undefined
|
|
211
|
-
? options.showVehicleTraj
|
|
212
|
-
: true,
|
|
213
|
-
writable: true,
|
|
214
|
-
},
|
|
215
|
-
delayDisplay: {
|
|
216
|
-
value: options.delayDisplay || 300000,
|
|
217
|
-
writable: true,
|
|
218
|
-
},
|
|
219
|
-
delayOutlineColor: {
|
|
220
|
-
value: options.delayOutlineColor || '#000000',
|
|
221
|
-
writable: true,
|
|
222
|
-
},
|
|
223
|
-
useDelayStyle: {
|
|
224
|
-
value: options.useDelayStyle || false,
|
|
225
|
-
writable: true,
|
|
226
|
-
},
|
|
227
134
|
requestIntervalSeconds: {
|
|
228
135
|
get: () => {
|
|
229
136
|
return requestIntervalSeconds;
|
|
@@ -238,42 +145,7 @@ const TrajservLayerMixin = (TrackerLayer) =>
|
|
|
238
145
|
}
|
|
239
146
|
},
|
|
240
147
|
},
|
|
241
|
-
|
|
242
|
-
get: () => {
|
|
243
|
-
return publishedLineName;
|
|
244
|
-
},
|
|
245
|
-
set: (newPublishedLineName) => {
|
|
246
|
-
publishedLineName = newPublishedLineName;
|
|
247
|
-
this.updateFilters();
|
|
248
|
-
},
|
|
249
|
-
},
|
|
250
|
-
tripNumber: {
|
|
251
|
-
get: () => {
|
|
252
|
-
return tripNumber;
|
|
253
|
-
},
|
|
254
|
-
set: (newTripNumber) => {
|
|
255
|
-
tripNumber = newTripNumber;
|
|
256
|
-
this.updateFilters();
|
|
257
|
-
},
|
|
258
|
-
},
|
|
259
|
-
operator: {
|
|
260
|
-
get: () => {
|
|
261
|
-
return operator;
|
|
262
|
-
},
|
|
263
|
-
set: (newOperator) => {
|
|
264
|
-
operator = newOperator;
|
|
265
|
-
this.updateFilters();
|
|
266
|
-
},
|
|
267
|
-
},
|
|
268
|
-
regexPublishedLineName: {
|
|
269
|
-
get: () => {
|
|
270
|
-
return regexPublishedLineName;
|
|
271
|
-
},
|
|
272
|
-
set: (newRegex) => {
|
|
273
|
-
regexPublishedLineName = newRegex;
|
|
274
|
-
this.updateFilters();
|
|
275
|
-
},
|
|
276
|
-
},
|
|
148
|
+
|
|
277
149
|
api: {
|
|
278
150
|
value: options.api || defaultApi,
|
|
279
151
|
},
|
|
@@ -407,18 +279,6 @@ const TrajservLayerMixin = (TrackerLayer) =>
|
|
|
407
279
|
});
|
|
408
280
|
}
|
|
409
281
|
|
|
410
|
-
updateFilters() {
|
|
411
|
-
// Setting filters from the permalink if no values defined by the layer.
|
|
412
|
-
const parameters = qs.parse(window.location.search.toLowerCase());
|
|
413
|
-
// filter is the property in TrackerLayerMixin.
|
|
414
|
-
this.filter = createFilters(
|
|
415
|
-
this.publishedLineName || parameters[LINE_FILTER],
|
|
416
|
-
this.tripNumber || parameters[ROUTE_FILTER],
|
|
417
|
-
this.operator || parameters[OPERATOR_FILTER],
|
|
418
|
-
this.regexPublishedLineName,
|
|
419
|
-
);
|
|
420
|
-
}
|
|
421
|
-
|
|
422
282
|
abortFetchTrajectories() {
|
|
423
283
|
if (this.abortController) {
|
|
424
284
|
this.abortController.abort();
|
|
@@ -164,6 +164,12 @@ const TralisLayerMixin = (TrackerLayer) =>
|
|
|
164
164
|
if (!data.content) {
|
|
165
165
|
return;
|
|
166
166
|
}
|
|
167
|
+
|
|
168
|
+
// Temporary fix to avoid displaying old trains cached .
|
|
169
|
+
if (data.content.properties.mot) {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
|
|
167
173
|
const feat = this.format.readFeature(data.content);
|
|
168
174
|
|
|
169
175
|
feat.set('timeOffset', Date.now() - data.timestamp);
|
package/common/trackerConfig.js
CHANGED
|
@@ -12,19 +12,23 @@ const trackerRadiusMapping = {
|
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
+
* Trajserv value: 'Tram', 'Subway / Metro / S-Bahn', 'Train', 'Bus', 'Ferry', 'Cable Car', 'Gondola', 'Funicular', 'Long distance bus', 'Rail',
|
|
16
|
+
* New endpoint use Rail instead of Train.
|
|
17
|
+
* New tracker values: null, "tram", "subway", "rail", "bus", "ferry", "cablecar", "gondola", "funicular", "coach".
|
|
18
|
+
*
|
|
15
19
|
* @ignore
|
|
16
20
|
*/
|
|
17
21
|
export const types = [
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
/^Tram/i,
|
|
23
|
+
/^Subway( \/ Metro \/ S-Bahn)?/i,
|
|
24
|
+
/^Train/i,
|
|
25
|
+
/^Bus/i,
|
|
26
|
+
/^Ferry/i,
|
|
27
|
+
/^Cable ?Car/i,
|
|
28
|
+
/^Gondola/i,
|
|
29
|
+
/^Funicular/i,
|
|
30
|
+
/^(Long distance bus|coach)/i,
|
|
31
|
+
/^Rail/i, // New endpoint use Rail instead of Train.
|
|
28
32
|
];
|
|
29
33
|
|
|
30
34
|
/**
|
|
@@ -89,10 +93,9 @@ export const timeSteps = [
|
|
|
89
93
|
/**
|
|
90
94
|
* @ignore
|
|
91
95
|
*/
|
|
92
|
-
const getTypeIndex = (type) => {
|
|
96
|
+
export const getTypeIndex = (type) => {
|
|
93
97
|
if (typeof type === 'string') {
|
|
94
|
-
|
|
95
|
-
return types.indexOf(matched);
|
|
98
|
+
return types.findIndex((t) => t.test(type));
|
|
96
99
|
}
|
|
97
100
|
return type;
|
|
98
101
|
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { getTypeIndex } from './trackerConfig';
|
|
2
|
+
|
|
3
|
+
describe('trackerConfig', () => {
|
|
4
|
+
describe('#getTypeIndex()', () => {
|
|
5
|
+
test("retrurn the type is it's not a string", () => {
|
|
6
|
+
const obj = { foo: 'foo' };
|
|
7
|
+
expect(getTypeIndex(obj)).toBe(obj);
|
|
8
|
+
expect(getTypeIndex(0)).toBe(0);
|
|
9
|
+
expect(getTypeIndex(null)).toBe(null);
|
|
10
|
+
expect(getTypeIndex(undefined)).toBe(undefined);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
test('find good index for old trajserv values', () => {
|
|
14
|
+
expect(getTypeIndex('Tram')).toBe(0);
|
|
15
|
+
expect(getTypeIndex('Subway / Metro / S-Bahn')).toBe(1);
|
|
16
|
+
expect(getTypeIndex('Train')).toBe(2);
|
|
17
|
+
expect(getTypeIndex('Bus')).toBe(3);
|
|
18
|
+
expect(getTypeIndex('Ferry')).toBe(4);
|
|
19
|
+
expect(getTypeIndex('Cable Car')).toBe(5);
|
|
20
|
+
expect(getTypeIndex('Gondola')).toBe(6);
|
|
21
|
+
expect(getTypeIndex('Funicular')).toBe(7);
|
|
22
|
+
expect(getTypeIndex('Long distance bus')).toBe(8);
|
|
23
|
+
expect(getTypeIndex('Rail')).toBe(9);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test('find good index for new tracker values', () => {
|
|
27
|
+
expect(getTypeIndex('tram')).toBe(0);
|
|
28
|
+
expect(getTypeIndex('subway')).toBe(1);
|
|
29
|
+
expect(getTypeIndex('bus')).toBe(3);
|
|
30
|
+
expect(getTypeIndex('ferry')).toBe(4);
|
|
31
|
+
expect(getTypeIndex('cablecar')).toBe(5);
|
|
32
|
+
expect(getTypeIndex('gondola')).toBe(6);
|
|
33
|
+
expect(getTypeIndex('funicular')).toBe(7);
|
|
34
|
+
expect(getTypeIndex('coach')).toBe(8);
|
|
35
|
+
expect(getTypeIndex('rail')).toBe(9);
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
});
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Return a filter functions based on some parameters of a vehicle.
|
|
3
|
+
*
|
|
4
|
+
* @param {string|Array<string>} line - A list of vehicle's name to filter. Names can be separated by a comma. Ex: 'S1,S2,S3'
|
|
5
|
+
* @param {string|Array<string} route - A list of vehicle's route (contained in routeIdentifier property) to filter. Indentifiers can be separated by a comma. Ex: 'id1,id2,id3'
|
|
6
|
+
* @param {string|Array<string} operator A list of vehicle's operator to filter. Operators can be separated by a comma. Ex: 'SBB,DB'
|
|
7
|
+
* @param {Regexp} regexLine - A regex aplly of vehcile's name.
|
|
8
|
+
* @private
|
|
9
|
+
*/
|
|
10
|
+
const createFilters = (line, route, operator, regexLine) => {
|
|
11
|
+
const filterList = [];
|
|
12
|
+
|
|
13
|
+
if (!line && !route && !operator && !regexLine) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (regexLine) {
|
|
18
|
+
const regexLineList =
|
|
19
|
+
typeof regexLine === 'string' ? [regexLine] : regexLine;
|
|
20
|
+
const lineFilter = (item) => {
|
|
21
|
+
const name = item.name || (item.line && item.line.name) || '';
|
|
22
|
+
if (!name) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
return regexLineList.some((regexStr) =>
|
|
26
|
+
new RegExp(regexStr, 'i').test(name),
|
|
27
|
+
);
|
|
28
|
+
};
|
|
29
|
+
filterList.push(lineFilter);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (line) {
|
|
33
|
+
const lineFiltersList = typeof line === 'string' ? line.split(',') : line;
|
|
34
|
+
const lineList = lineFiltersList.map((l) =>
|
|
35
|
+
l.replace(/\s+/g, '').toUpperCase(),
|
|
36
|
+
);
|
|
37
|
+
const lineFilter = (item) => {
|
|
38
|
+
const name = (
|
|
39
|
+
item.name ||
|
|
40
|
+
(item.line && item.line.name) ||
|
|
41
|
+
''
|
|
42
|
+
).toUpperCase();
|
|
43
|
+
if (!name) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
return lineList.includes(name);
|
|
47
|
+
};
|
|
48
|
+
filterList.push(lineFilter);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (route) {
|
|
52
|
+
const routes = typeof route === 'string' ? route.split(',') : route;
|
|
53
|
+
const routeList = routes.map((item) => parseInt(item, 10));
|
|
54
|
+
const routeFilter = (item) => {
|
|
55
|
+
const routeId = parseInt(item.routeIdentifier.split('.')[0], 10);
|
|
56
|
+
return routeList.includes(routeId);
|
|
57
|
+
};
|
|
58
|
+
filterList.push(routeFilter);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (operator) {
|
|
62
|
+
const operatorList = typeof operator === 'string' ? [operator] : operator;
|
|
63
|
+
const operatorFilter = (item) =>
|
|
64
|
+
operatorList.some((op) => new RegExp(op, 'i').test(item.operator));
|
|
65
|
+
filterList.push(operatorFilter);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (!filterList.length) {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return (t) => {
|
|
73
|
+
for (let i = 0; i < filterList.length; i += 1) {
|
|
74
|
+
if (!filterList[i](t)) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return true;
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
export default createFilters;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import createTrackerFilters from './createTrackerFilters';
|
|
2
|
+
|
|
3
|
+
const u1 = {
|
|
4
|
+
routeIdentifier: '001.000827.004:7',
|
|
5
|
+
operator: 'FoO',
|
|
6
|
+
line: {
|
|
7
|
+
name: 'U1',
|
|
8
|
+
},
|
|
9
|
+
};
|
|
10
|
+
const ireta = {
|
|
11
|
+
routeIdentifier: '0022.000827.004:7',
|
|
12
|
+
operator: 'BAR',
|
|
13
|
+
line: {
|
|
14
|
+
name: 'IRETA',
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
const arb = {
|
|
18
|
+
routeIdentifier: '00333.000827.004:7',
|
|
19
|
+
operator: 'qux',
|
|
20
|
+
line: {
|
|
21
|
+
name: 'ARB',
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const trajectories = [u1, ireta, arb];
|
|
26
|
+
|
|
27
|
+
describe('#createTrackerFilter()', () => {
|
|
28
|
+
test('returns null', () => {
|
|
29
|
+
const filterFunc = createTrackerFilters();
|
|
30
|
+
expect(filterFunc).toBe(null);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
describe('using line', () => {
|
|
34
|
+
test('as string', () => {
|
|
35
|
+
const filterFunc = createTrackerFilters('u1,foo');
|
|
36
|
+
expect(trajectories.filter(filterFunc)).toEqual([u1]);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test('as array of string', () => {
|
|
40
|
+
const filterFunc = createTrackerFilters(['u1', 'foo', 'IRETA']);
|
|
41
|
+
expect(trajectories.filter(filterFunc)).toEqual([u1, ireta]);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
describe('using route identifier', () => {
|
|
46
|
+
test('as string', () => {
|
|
47
|
+
const filterFunc = createTrackerFilters(null, '1,foo');
|
|
48
|
+
expect(trajectories.filter(filterFunc)).toEqual([u1]);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test('as array of string', () => {
|
|
52
|
+
const filterFunc = createTrackerFilters(null, ['22', 'foo', '1']);
|
|
53
|
+
expect(trajectories.filter(filterFunc)).toEqual([u1, ireta]);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
describe('using operator', () => {
|
|
58
|
+
test('as string', () => {
|
|
59
|
+
const filterFunc = createTrackerFilters(null, null, 'foo');
|
|
60
|
+
expect(trajectories.filter(filterFunc)).toEqual([u1]);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test('as array of string', () => {
|
|
64
|
+
const filterFunc = createTrackerFilters(null, null, ['bar', 'foo', '1']);
|
|
65
|
+
expect(trajectories.filter(filterFunc)).toEqual([u1, ireta]);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe('using regexLine', () => {
|
|
70
|
+
test('as string', () => {
|
|
71
|
+
const filterFunc = createTrackerFilters(
|
|
72
|
+
null,
|
|
73
|
+
null,
|
|
74
|
+
null,
|
|
75
|
+
'^(S|R$|RE|PE|D|IRE|RB|TER)',
|
|
76
|
+
);
|
|
77
|
+
expect(trajectories.filter(filterFunc)).toEqual([ireta]);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test('as array of string', () => {
|
|
81
|
+
const filterFunc = createTrackerFilters(null, null, null, [
|
|
82
|
+
'^IR',
|
|
83
|
+
'^ARB$',
|
|
84
|
+
'foo',
|
|
85
|
+
]);
|
|
86
|
+
expect(trajectories.filter(filterFunc)).toEqual([ireta, arb]);
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
});
|
|
@@ -18,47 +18,43 @@ const style = (trajectory, viewState, trackerLayer) => {
|
|
|
18
18
|
delayDisplay,
|
|
19
19
|
} = trackerLayer;
|
|
20
20
|
|
|
21
|
-
const { zoom, pixelRatio } = viewState;
|
|
22
|
-
|
|
23
|
-
let { line = {} } = trajectory;
|
|
24
|
-
|
|
25
21
|
const {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
} = trajectory;
|
|
22
|
+
zoom,
|
|
23
|
+
pixelRatio,
|
|
24
|
+
operator_provides_realtime_journey: operatorProvidesRealtime,
|
|
25
|
+
} = viewState;
|
|
26
|
+
let { line, type } = trajectory;
|
|
27
|
+
const { id, delay, cancelled = false } = trajectory;
|
|
28
|
+
|
|
29
|
+
if (!type) {
|
|
30
|
+
type = 'Rail';
|
|
31
|
+
}
|
|
32
32
|
|
|
33
33
|
if (!line) {
|
|
34
34
|
line = {};
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
let { text_color: textColor, color } = line;
|
|
37
|
+
let { name, text_color: textColor, color } = line;
|
|
39
38
|
|
|
40
|
-
if (!
|
|
41
|
-
|
|
39
|
+
if (!name) {
|
|
40
|
+
name = 'I';
|
|
42
41
|
}
|
|
43
42
|
|
|
44
43
|
if (!textColor) {
|
|
45
|
-
textColor = '#
|
|
44
|
+
textColor = '#000000';
|
|
46
45
|
}
|
|
47
46
|
|
|
48
|
-
|
|
49
|
-
if (color[0] !== '#') {
|
|
47
|
+
if (color && color[0] !== '#') {
|
|
50
48
|
color = `#${color}`;
|
|
51
49
|
}
|
|
52
50
|
|
|
53
51
|
if (textColor[0] !== '#') {
|
|
54
52
|
textColor = `#${textColor}`;
|
|
55
53
|
}
|
|
56
|
-
console.log(color, textColor);
|
|
57
54
|
|
|
58
55
|
const z = Math.min(Math.floor(zoom || 1), 16);
|
|
59
56
|
const hover = hoverVehicleId === id;
|
|
60
57
|
const selected = selectedVehicleId === id;
|
|
61
|
-
let key = `${z}${type}${name}${color}${textColor}${operatorProvidesRealtime}${delay}${hover}${selected}${cancelled}`;
|
|
62
58
|
|
|
63
59
|
// Calcul the radius of the circle
|
|
64
60
|
let radius = getRadius(type, z) * pixelRatio;
|
|
@@ -71,8 +67,14 @@ const style = (trajectory, viewState, trackerLayer) => {
|
|
|
71
67
|
const mustDrawText = radius > 10 * pixelRatio;
|
|
72
68
|
|
|
73
69
|
// Optimize the cache key, very important in high zoom level
|
|
74
|
-
|
|
75
|
-
|
|
70
|
+
let key = `${z}${type}${color}${hover}${selected}${cancelled}${delay}`;
|
|
71
|
+
|
|
72
|
+
if (useDelayStyle) {
|
|
73
|
+
key += `${operatorProvidesRealtime}`;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (mustDrawText) {
|
|
77
|
+
key += `${name}${textColor}`;
|
|
76
78
|
}
|
|
77
79
|
|
|
78
80
|
if (!styleCache[key]) {
|