atriusmaps-node-sdk 3.3.632 → 3.3.634
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/LICENSE.md +1 -2
- package/README.md +15 -16
- package/dist/cjs/deploy/prepareSDKConfig.js +73 -57
- package/dist/cjs/nodesdk/nodeEntry.js +51 -44
- package/dist/cjs/package.json.js +4 -1
- package/dist/cjs/plugins/clientAPI/src/clientAPI.js +6 -4
- package/dist/cjs/plugins/dynamicPois/src/dynamicPois.js +32 -26
- package/dist/cjs/plugins/dynamicPois/src/processors.js +41 -35
- package/dist/cjs/plugins/poiDataManager/src/poiDataManager.js +102 -95
- package/dist/cjs/plugins/sdkServer/src/sdkHeadless.js +52 -26
- package/dist/cjs/plugins/sdkServer/src/sdkServer.js +86 -66
- package/dist/cjs/plugins/searchService/src/flexsearchExports/lang.js +16 -16
- package/dist/cjs/plugins/searchService/src/flexsearchExports/simple.js +31 -8
- package/dist/cjs/plugins/searchService/src/poiSearch.js +14 -17
- package/dist/cjs/plugins/searchService/src/searchService.js +41 -39
- package/dist/cjs/plugins/searchService/src/searchTypeahead.js +14 -19
- package/dist/cjs/plugins/searchService/src/utils.js +4 -5
- package/dist/cjs/plugins/venueDataLoader/src/venueDataLoader.js +145 -127
- package/dist/cjs/plugins/venueDataLoader/src/venueLoadingUtils.js +37 -39
- package/dist/cjs/plugins/wayfinder/src/findRoute.js +11 -18
- package/dist/cjs/plugins/wayfinder/src/minPriorityQueue.js +18 -19
- package/dist/cjs/plugins/wayfinder/src/navGraph.js +111 -91
- package/dist/cjs/plugins/wayfinder/src/navGraphDebug.js +19 -16
- package/dist/cjs/plugins/wayfinder/src/segmentBadges.js +1 -1
- package/dist/cjs/plugins/wayfinder/src/segmentBuilder.js +79 -76
- package/dist/cjs/plugins/wayfinder/src/segmentCategories.js +1 -1
- package/dist/cjs/plugins/wayfinder/src/stepBuilder.js +147 -107
- package/dist/cjs/plugins/wayfinder/src/wayfinder.js +178 -148
- package/dist/cjs/src/app.js +64 -44
- package/dist/cjs/src/configs/postproc-mol-url-parms.js +22 -21
- package/dist/cjs/src/configs/postproc-stateTracking.js +5 -8
- package/dist/cjs/src/controller.js +11 -6
- package/dist/cjs/src/debugTools.js +61 -34
- package/dist/cjs/src/env.js +7 -4
- package/dist/cjs/src/extModules/bustle.js +35 -45
- package/dist/cjs/src/extModules/flexapi/src/help.js +16 -8
- package/dist/cjs/src/extModules/flexapi/src/index.js +39 -18
- package/dist/cjs/src/extModules/flexapi/src/validate.js +129 -87
- package/dist/cjs/src/extModules/geohasher.js +7 -7
- package/dist/cjs/src/extModules/log.js +20 -22
- package/dist/cjs/src/historyManager.js +2 -2
- package/dist/cjs/src/utils/bounds.js +6 -6
- package/dist/cjs/src/utils/buildStructureLookup.js +3 -3
- package/dist/cjs/src/utils/configUtils.js +14 -18
- package/dist/cjs/src/utils/dom.js +12 -18
- package/dist/cjs/src/utils/funcs.js +12 -15
- package/dist/cjs/src/utils/geodesy.js +7 -9
- package/dist/cjs/src/utils/geom.js +52 -40
- package/dist/cjs/src/utils/i18n.js +47 -36
- package/dist/cjs/src/utils/location.js +12 -13
- package/dist/cjs/src/utils/observable.js +27 -28
- package/dist/cjs/src/utils/rand.js +9 -10
- package/dist/package.json.js +1 -1
- package/package.json +1 -1
|
@@ -32,33 +32,39 @@ const mutateSecurityCheckpointLabel = (T, queueTimes, labels) => feature => {
|
|
|
32
32
|
const id = feature.properties.id;
|
|
33
33
|
const dynamicData = queueTimes[id];
|
|
34
34
|
const label = labels[id];
|
|
35
|
-
if (dynamicData) {
|
|
35
|
+
if (dynamicData) {
|
|
36
|
+
// should we only show this message when "timeIsReal" is true?
|
|
36
37
|
const { queueTime, isTemporarilyClosed } = dynamicData;
|
|
37
38
|
const secondaryText = isTemporarilyClosed ? T('ui:Closed') : T('ui:_xx_ minute wait', { count: queueTime });
|
|
38
39
|
feature.properties.text = `${label}\n${secondaryText}`;
|
|
39
40
|
}
|
|
40
|
-
return feature
|
|
41
|
+
return feature;
|
|
41
42
|
};
|
|
42
43
|
|
|
43
|
-
const processParkingPOIS =
|
|
44
|
-
const idValuesMap =
|
|
45
|
-
R__namespace.
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const props = (age < da['parking.timeToLive']) // if this update is recent enough, consider it "valid"
|
|
44
|
+
const processParkingPOIS = poiMap => {
|
|
45
|
+
const idValuesMap = R__namespace.pipe(
|
|
46
|
+
R__namespace.filter(poi => poi.category === 'parking'),
|
|
47
|
+
R__namespace.map(poi => {
|
|
48
|
+
const da = poi.dynamicAttributes;
|
|
49
|
+
if (!da) throw Error(`No dynamicAttributes defined for parking POI ${poi.poiId}`);
|
|
50
|
+
const age = (Date.now() - poi.timestamp) / 1000; // how long ago this was updated by backend (in seconds)
|
|
51
|
+
const props =
|
|
52
|
+
age < da['parking.timeToLive'] // if this update is recent enough, consider it "valid"
|
|
53
53
|
? R__namespace.pick(['lotStatus', 'rateDay', 'rateHour', 'timeIsReal', 'timeToTerminal1', 'timeToTerminal2'], poi)
|
|
54
|
-
: {
|
|
54
|
+
: {
|
|
55
|
+
lotStatus: da['parking.default'],
|
|
56
|
+
rateDay: '$ -',
|
|
57
|
+
rateHour: '$ -',
|
|
58
|
+
timeIsReal: false,
|
|
59
|
+
};
|
|
55
60
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
61
|
+
return { ...props, lastUpdated: poi.timestamp, lotName: poi.lotName };
|
|
62
|
+
}),
|
|
63
|
+
)(poiMap);
|
|
64
|
+
return idValuesMap;
|
|
59
65
|
};
|
|
60
66
|
|
|
61
|
-
const processOpenClosedPois =
|
|
67
|
+
const processOpenClosedPois = poiMap => {
|
|
62
68
|
const pathToOpenClosedData = ['dynamicData', 'openClosed'];
|
|
63
69
|
const openClosedPois = R__namespace.filter(R__namespace.hasPath(pathToOpenClosedData), poiMap);
|
|
64
70
|
const openClosedStatuses = R__namespace.map(R__namespace.path(pathToOpenClosedData), openClosedPois);
|
|
@@ -67,38 +73,38 @@ const processOpenClosedPois = (poiMap) => {
|
|
|
67
73
|
const isExpired = R__namespace.pipe(R__namespace.prop('expiration'), R__namespace.lt(Date.now()));
|
|
68
74
|
const idValuesMap = R__namespace.filter(isExpired, openClosedStatuses);
|
|
69
75
|
|
|
70
|
-
return idValuesMap
|
|
76
|
+
return idValuesMap;
|
|
71
77
|
} else {
|
|
72
|
-
throw Error('Open Closed poi status is malformed.')
|
|
78
|
+
throw Error('Open Closed poi status is malformed.');
|
|
73
79
|
}
|
|
74
80
|
};
|
|
75
81
|
|
|
76
82
|
/*
|
|
77
83
|
API response: https://gitlab.com/locuslabs/core-data-team/json-schemas/-/blob/develop/src/api-marketplace/dynamic-queue-data.json
|
|
78
84
|
*/
|
|
79
|
-
const processSecurityWaitTimes =
|
|
85
|
+
const processSecurityWaitTimes = poiMap => {
|
|
80
86
|
const queuePath = ['dynamicData', 'queue'];
|
|
81
87
|
const queuePois = R__namespace.filter(R__namespace.hasPath(queuePath), poiMap);
|
|
82
88
|
const queues = R__namespace.map(R__namespace.path(queuePath), queuePois);
|
|
83
|
-
return R__namespace.map(
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
+
return R__namespace.map(
|
|
90
|
+
queue => ({
|
|
91
|
+
isTemporarilyClosed: queue.isTemporarilyClosed,
|
|
92
|
+
queueTime: queue.queueTime,
|
|
93
|
+
timeIsReal: !queue.isQueueTimeDefault && queue.expiration > Date.now(),
|
|
94
|
+
lastUpdated: Date.now(),
|
|
95
|
+
}),
|
|
96
|
+
queues,
|
|
97
|
+
);
|
|
89
98
|
};
|
|
90
99
|
|
|
91
|
-
const processRoutingPois =
|
|
100
|
+
const processRoutingPois = poiMap => {
|
|
92
101
|
const now = Date.now();
|
|
93
102
|
|
|
94
|
-
return R__namespace.filter(
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
},
|
|
100
|
-
poiMap
|
|
101
|
-
)
|
|
103
|
+
return R__namespace.filter(poi => {
|
|
104
|
+
const navGraphHidden = R__namespace.path(['dynamicData', 'dynamic-routing', 'navGraphHidden'], poi);
|
|
105
|
+
const expiration = R__namespace.path(['dynamicData', 'dynamic-routing', 'expiration'], poi);
|
|
106
|
+
return navGraphHidden === true && expiration > now;
|
|
107
|
+
}, poiMap);
|
|
102
108
|
};
|
|
103
109
|
|
|
104
110
|
exports.mutateSecurityCheckpointLabel = mutateSecurityCheckpointLabel;
|
|
@@ -25,7 +25,7 @@ function _interopNamespaceDefault(e) {
|
|
|
25
25
|
|
|
26
26
|
var R__namespace = /*#__PURE__*/_interopNamespaceDefault(R);
|
|
27
27
|
|
|
28
|
-
async function create
|
|
28
|
+
async function create(app, config) {
|
|
29
29
|
const log = app.log.sublog('poiDataManager');
|
|
30
30
|
const init = () => {
|
|
31
31
|
app.bus.send('venueData/loadPoiData');
|
|
@@ -38,7 +38,7 @@ async function create (app, config) {
|
|
|
38
38
|
const structure = structuresLookup.floorIdToStructure(position.floorId);
|
|
39
39
|
if (!structure) {
|
|
40
40
|
log.error(`No structure found for floorId: ${position.floorId} for POI ${poi.poiId}`);
|
|
41
|
-
return { ...poi }
|
|
41
|
+
return { ...poi };
|
|
42
42
|
}
|
|
43
43
|
const floor = structuresLookup.floorIdToFloor(position.floorId);
|
|
44
44
|
const detailedPosition = {
|
|
@@ -46,9 +46,9 @@ async function create (app, config) {
|
|
|
46
46
|
structureName: structure.name,
|
|
47
47
|
buildingId: structure.id,
|
|
48
48
|
floorName: floor.name,
|
|
49
|
-
floorOrdinal: floor.ordinal
|
|
49
|
+
floorOrdinal: floor.ordinal,
|
|
50
50
|
};
|
|
51
|
-
return { ...poi, position: detailedPosition }
|
|
51
|
+
return { ...poi, position: detailedPosition };
|
|
52
52
|
};
|
|
53
53
|
|
|
54
54
|
// todo R.map may be enough to update dictionary values
|
|
@@ -60,18 +60,23 @@ async function create (app, config) {
|
|
|
60
60
|
poi.isNavigable = poi.isNavigable === undefined || poi.isNavigable === true; // isNavigable is true as default, and is optional in the POI data
|
|
61
61
|
// poi.isNavigable = /^[a-mA-M]+/.test(poi.name) // uncomment for easy testing of isNavigable
|
|
62
62
|
if (poi.capacity)
|
|
63
|
-
addToRoomInfo(poi, {
|
|
63
|
+
addToRoomInfo(poi, {
|
|
64
|
+
name: `Seats ${poi.capacity.join('-')}`,
|
|
65
|
+
svgId: 'number-of-seats',
|
|
66
|
+
});
|
|
64
67
|
if (poi.category.startsWith('meeting'))
|
|
65
|
-
addToRoomInfo(poi, {
|
|
68
|
+
addToRoomInfo(poi, {
|
|
69
|
+
name: app.gt()('poiView:Conference Room'),
|
|
70
|
+
svgId: 'conference-room',
|
|
71
|
+
});
|
|
66
72
|
|
|
67
73
|
const roomId = getRoomId(poi);
|
|
68
|
-
if (roomId)
|
|
69
|
-
poi.roomId = roomId;
|
|
74
|
+
if (roomId) poi.roomId = roomId;
|
|
70
75
|
|
|
71
|
-
return [poi.poiId, fixPositionInfo(poi, structuresLookup)]
|
|
76
|
+
return [poi.poiId, fixPositionInfo(poi, structuresLookup)];
|
|
72
77
|
}),
|
|
73
|
-
R__namespace.fromPairs
|
|
74
|
-
)(pois)
|
|
78
|
+
R__namespace.fromPairs,
|
|
79
|
+
)(pois);
|
|
75
80
|
};
|
|
76
81
|
|
|
77
82
|
const addToRoomInfo = (poi, value) => {
|
|
@@ -85,10 +90,10 @@ async function create (app, config) {
|
|
|
85
90
|
R__namespace.propOr([], 'externalIds'),
|
|
86
91
|
R__namespace.find(R__namespace.propEq('roomId', 'type')),
|
|
87
92
|
R__namespace.prop('id'),
|
|
88
|
-
R__namespace.unless(R__namespace.isNil, R__namespace.tail)
|
|
93
|
+
R__namespace.unless(R__namespace.isNil, R__namespace.tail),
|
|
89
94
|
);
|
|
90
95
|
|
|
91
|
-
async function checkNavgraph
|
|
96
|
+
async function checkNavgraph(pois) {
|
|
92
97
|
const start = Date.now();
|
|
93
98
|
const badPois = [];
|
|
94
99
|
const navGraph = await app.bus.get('wayfinder/_getNavGraph');
|
|
@@ -96,32 +101,34 @@ async function create (app, config) {
|
|
|
96
101
|
try {
|
|
97
102
|
const pos = poi.position;
|
|
98
103
|
const n = navGraph.findClosestNode(pos.floorId, pos.latitude, pos.longitude);
|
|
99
|
-
if (!n)
|
|
100
|
-
badPois.push({ id: poi.poiId, e: 'No closest Navgraph Node' });
|
|
104
|
+
if (!n) badPois.push({ id: poi.poiId, e: 'No closest Navgraph Node' });
|
|
101
105
|
} catch (e) {
|
|
102
106
|
log.error(e);
|
|
103
107
|
badPois.push({ id: poi.poiId, e: e.message });
|
|
104
108
|
}
|
|
105
109
|
});
|
|
106
110
|
|
|
107
|
-
if (badPois.length)
|
|
108
|
-
log.warn('badPois:', badPois);
|
|
111
|
+
if (badPois.length) log.warn('badPois:', badPois);
|
|
109
112
|
|
|
110
113
|
log(`Total time for navgraph POI check: ${Date.now() - start}ms`);
|
|
111
114
|
}
|
|
112
115
|
|
|
113
|
-
function filterBadPois
|
|
116
|
+
function filterBadPois(pois) {
|
|
114
117
|
const badPois = [];
|
|
115
118
|
Object.values(pois).forEach(poi => {
|
|
116
119
|
try {
|
|
117
120
|
const pos = poi.position;
|
|
118
|
-
if (!pos)
|
|
119
|
-
badPois.push({ poi, e: 'No position information' });
|
|
121
|
+
if (!pos) badPois.push({ poi, e: 'No position information' });
|
|
120
122
|
else {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
123
|
+
['buildingId', 'structureName', 'floorId', 'floorName', 'floorOrdinal', 'latitude', 'longitude'].forEach(
|
|
124
|
+
k => {
|
|
125
|
+
if (pos[k] === null || pos[k] === undefined)
|
|
126
|
+
badPois.push({
|
|
127
|
+
id: poi.poiId,
|
|
128
|
+
e: `invalid position property: ${k}: ${pos[k]}`,
|
|
129
|
+
});
|
|
130
|
+
},
|
|
131
|
+
);
|
|
125
132
|
}
|
|
126
133
|
} catch (e) {
|
|
127
134
|
log.error(e);
|
|
@@ -131,49 +138,48 @@ async function create (app, config) {
|
|
|
131
138
|
|
|
132
139
|
if (badPois.length) {
|
|
133
140
|
log.warn('badPois:', badPois);
|
|
134
|
-
badPois.forEach(ob => {
|
|
141
|
+
badPois.forEach(ob => {
|
|
142
|
+
delete pois[ob.id];
|
|
143
|
+
});
|
|
135
144
|
}
|
|
136
145
|
|
|
137
|
-
return pois
|
|
146
|
+
return pois;
|
|
138
147
|
}
|
|
139
148
|
|
|
140
|
-
async function enhanceImages
|
|
141
|
-
for (const poi of Object.values(pois))
|
|
142
|
-
await addImages(poi);
|
|
149
|
+
async function enhanceImages(pois) {
|
|
150
|
+
for (const poi of Object.values(pois)) await addImages(poi);
|
|
143
151
|
|
|
144
|
-
return pois
|
|
152
|
+
return pois;
|
|
145
153
|
}
|
|
146
154
|
|
|
147
155
|
app.bus.on('venueData/poiDataLoaded', async ({ pois, structures }) => {
|
|
148
156
|
const structuresLookup = buildStructureLookup.buildStructuresLookup(structures);
|
|
149
157
|
pois = formatPois(pois, structuresLookup);
|
|
150
158
|
if (configUtils.debugIsTrue(app, 'pseudoTransPois'))
|
|
151
|
-
for (const id in pois)
|
|
152
|
-
pois[id] = pseudoTransPoi(pois[id], app.i18n().language);
|
|
159
|
+
for (const id in pois) pois[id] = pseudoTransPoi(pois[id], app.i18n().language);
|
|
153
160
|
|
|
154
161
|
pois = filterBadPois(pois);
|
|
155
162
|
|
|
156
163
|
await enhanceImages(pois);
|
|
157
164
|
poisLoaded.resolve(pois);
|
|
158
165
|
|
|
159
|
-
if (app.config.debug && app.env.isBrowser)
|
|
160
|
-
window._pois = pois;
|
|
166
|
+
if (app.config.debug && app.env.isBrowser) window._pois = pois;
|
|
161
167
|
|
|
162
|
-
if (app.config.debug)
|
|
163
|
-
checkNavgraph(pois); // this doesn't change the pois, but warns in the console...
|
|
168
|
+
if (app.config.debug) checkNavgraph(pois); // this doesn't change the pois, but warns in the console...
|
|
164
169
|
});
|
|
165
170
|
|
|
166
171
|
app.bus.on('poi/getById', async ({ id }) => {
|
|
167
|
-
return poisLoaded.then(pois => pois[id])
|
|
172
|
+
return poisLoaded.then(pois => pois[id]);
|
|
168
173
|
});
|
|
169
174
|
|
|
170
|
-
app.bus.on('poi/getByFloorId', async ({ floorId }) =>
|
|
171
|
-
R__namespace.pickBy(R__namespace.pathEq(floorId, ['position', 'floorId'])))
|
|
175
|
+
app.bus.on('poi/getByFloorId', async ({ floorId }) =>
|
|
176
|
+
poisLoaded.then(R__namespace.pickBy(R__namespace.pathEq(floorId, ['position', 'floorId']))),
|
|
177
|
+
);
|
|
172
178
|
|
|
173
179
|
app.bus.on('poi/getByCategoryId', async ({ categoryId }) => {
|
|
174
180
|
// returns true for exact category matches or parent category matches
|
|
175
|
-
const categoryMatch =
|
|
176
|
-
return poisLoaded.then(R__namespace.pickBy(categoryMatch))
|
|
181
|
+
const categoryMatch = poi => poi.category === categoryId || poi.category.startsWith(categoryId + '.');
|
|
182
|
+
return poisLoaded.then(R__namespace.pickBy(categoryMatch));
|
|
177
183
|
});
|
|
178
184
|
|
|
179
185
|
app.bus.on('poi/getAll', async () => poisLoaded);
|
|
@@ -182,21 +188,22 @@ async function create (app, config) {
|
|
|
182
188
|
const addOtherSecurityLanesIfNeeded = async poi => {
|
|
183
189
|
const primaryCheckpointId = R__namespace.path(checkpointPath, poi);
|
|
184
190
|
|
|
185
|
-
if (!primaryCheckpointId) return poi
|
|
191
|
+
if (!primaryCheckpointId) return poi;
|
|
186
192
|
|
|
187
193
|
const queueTypes = await app.bus.get('venueData/getQueueTypes');
|
|
188
|
-
const securityPoisMap = await app.bus.get('poi/getByCategoryId', {
|
|
194
|
+
const securityPoisMap = await app.bus.get('poi/getByCategoryId', {
|
|
195
|
+
categoryId: 'security',
|
|
196
|
+
});
|
|
189
197
|
const securityPoisList = Object.values(securityPoisMap);
|
|
190
198
|
|
|
191
199
|
poi.queue.otherQueues = prepareOtherSecurityLanes(queueTypes, poi, securityPoisList);
|
|
192
|
-
return poi
|
|
200
|
+
return poi;
|
|
193
201
|
};
|
|
194
202
|
|
|
195
203
|
const prepareOtherSecurityLanes = (queueTypes, currentPoi, securityPois) => {
|
|
196
204
|
const queueTypePath = ['queue', 'queueType'];
|
|
197
205
|
const queueType = R__namespace.path(queueTypePath, currentPoi);
|
|
198
|
-
if (!queueType)
|
|
199
|
-
return null
|
|
206
|
+
if (!queueType) return null;
|
|
200
207
|
|
|
201
208
|
const queueSubtypes = queueTypes[queueType];
|
|
202
209
|
const primaryCheckpointId = R__namespace.path(checkpointPath, currentPoi);
|
|
@@ -206,56 +213,61 @@ async function create (app, config) {
|
|
|
206
213
|
.map(poi => {
|
|
207
214
|
const laneId = R__namespace.path(['queue', 'queueSubtype'], poi);
|
|
208
215
|
const lane = getLaneData(laneId)(queueSubtypes);
|
|
209
|
-
return { poiId: poi.poiId, ...lane }
|
|
210
|
-
})
|
|
216
|
+
return { poiId: poi.poiId, ...lane };
|
|
217
|
+
});
|
|
211
218
|
};
|
|
212
219
|
|
|
213
220
|
// if the value passed is non-null, simply return it. Else throw the error with the message specified.
|
|
214
221
|
// This is useful to insert into pipelines.
|
|
215
222
|
const ensureDefined = errorMsg => value => {
|
|
216
|
-
if (value != null)
|
|
217
|
-
|
|
218
|
-
throw Error(errorMsg)
|
|
223
|
+
if (value != null) return value;
|
|
224
|
+
throw Error(errorMsg);
|
|
219
225
|
};
|
|
220
226
|
|
|
221
|
-
const getLaneData = laneId =>
|
|
222
|
-
R__namespace.
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
227
|
+
const getLaneData = laneId =>
|
|
228
|
+
R__namespace.pipe(
|
|
229
|
+
R__namespace.find(R__namespace.propEq(laneId, 'id')),
|
|
230
|
+
ensureDefined(`No queue found with ID: ${laneId}`),
|
|
231
|
+
R__namespace.pick(['displayText', 'imageId']),
|
|
232
|
+
);
|
|
226
233
|
|
|
227
234
|
/**
|
|
228
235
|
* Updates security checkpoint POI with a list of related security checkpoints.
|
|
229
236
|
*/
|
|
230
237
|
app.bus.on('poi/addOtherSecurityLanes', ({ poi }) => addOtherSecurityLanesIfNeeded(poi));
|
|
231
238
|
|
|
232
|
-
const isFullUrl =
|
|
239
|
+
const isFullUrl = url => !!url?.startsWith('https:');
|
|
233
240
|
|
|
234
|
-
async function addImages
|
|
235
|
-
if (!poi) return
|
|
236
|
-
const dpr = typeof window === 'undefined' ? 1 :
|
|
241
|
+
async function addImages(poi) {
|
|
242
|
+
if (!poi) return;
|
|
243
|
+
const dpr = typeof window === 'undefined' ? 1 : window.devicePixelRatio || 1;
|
|
237
244
|
const size = `${Math.round(351 * dpr)}x${Math.round(197 * dpr)}`;
|
|
238
245
|
|
|
239
246
|
if (!R__namespace.length(poi.images)) {
|
|
240
247
|
poi.images = [];
|
|
241
|
-
} else if (!isFullUrl(poi.images[0])) {
|
|
248
|
+
} else if (!isFullUrl(poi.images[0])) {
|
|
249
|
+
// then images are not yet transformed
|
|
242
250
|
poi.images = await Zousan.all(
|
|
243
|
-
poi.images.map(imageName =>
|
|
244
|
-
|
|
251
|
+
poi.images.map(imageName => app.bus.get('venueData/getPoiImageUrl', { imageName, size })),
|
|
252
|
+
);
|
|
245
253
|
}
|
|
246
254
|
|
|
247
255
|
if (!R__namespace.length(poi.fullImages)) {
|
|
248
256
|
poi.fullImages = [];
|
|
249
|
-
} else if (!isFullUrl(poi.fullImages[0]?.url)) {
|
|
257
|
+
} else if (!isFullUrl(poi.fullImages[0]?.url)) {
|
|
258
|
+
// then images are not yet transformed
|
|
250
259
|
poi.fullImages = await Zousan.all(
|
|
251
260
|
poi.fullImages.map(async ({ url, ...rest }) => {
|
|
252
|
-
const fullUrl = await app.bus.get('venueData/getPoiImageUrl', {
|
|
253
|
-
|
|
254
|
-
|
|
261
|
+
const fullUrl = await app.bus.get('venueData/getPoiImageUrl', {
|
|
262
|
+
imageName: url,
|
|
263
|
+
size,
|
|
264
|
+
});
|
|
265
|
+
return { url: fullUrl, ...rest };
|
|
266
|
+
}),
|
|
255
267
|
);
|
|
256
268
|
}
|
|
257
269
|
|
|
258
|
-
return poi
|
|
270
|
+
return poi;
|
|
259
271
|
}
|
|
260
272
|
|
|
261
273
|
const getUniqueCategories = R__namespace.memoizeWith(R__namespace.identity, R__namespace.pipe(R__namespace.pluck('category'), R__namespace.values, R__namespace.uniq));
|
|
@@ -268,21 +280,20 @@ async function create (app, config) {
|
|
|
268
280
|
|
|
269
281
|
// See architectural document at https://docs.google.com/document/d/1NoBAboHR9BiX_vvLef-vp3ButrIQDWYofcTsdilEWvs/edit#
|
|
270
282
|
app.bus.on('poi/setDynamicData', ({ plugin, idValuesMap }) => {
|
|
271
|
-
poisLoaded
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
});
|
|
283
|
+
poisLoaded.then(pois => {
|
|
284
|
+
for (const poiId in idValuesMap) {
|
|
285
|
+
// const dd = { [plugin]: idValuesMap[poiId] }
|
|
286
|
+
const dynamicData = pois[poiId].dynamicData || {};
|
|
287
|
+
dynamicData[plugin] = { ...idValuesMap[poiId] };
|
|
288
|
+
const newPoi = R__namespace.mergeRight(pois[poiId], { dynamicData });
|
|
289
|
+
pois[poiId] = newPoi;
|
|
290
|
+
}
|
|
291
|
+
});
|
|
281
292
|
});
|
|
282
293
|
|
|
283
|
-
const runTest = async
|
|
294
|
+
const runTest = async testRoutine => {
|
|
284
295
|
await testRoutine();
|
|
285
|
-
return poisLoaded
|
|
296
|
+
return poisLoaded;
|
|
286
297
|
};
|
|
287
298
|
|
|
288
299
|
return {
|
|
@@ -290,27 +301,23 @@ async function create (app, config) {
|
|
|
290
301
|
runTest,
|
|
291
302
|
internal: {
|
|
292
303
|
addImages,
|
|
293
|
-
pseudoTransPoi
|
|
294
|
-
}
|
|
295
|
-
}
|
|
304
|
+
pseudoTransPoi,
|
|
305
|
+
},
|
|
306
|
+
};
|
|
296
307
|
}
|
|
297
308
|
|
|
298
|
-
function pseudoTransPoi
|
|
299
|
-
['description', 'nearbyLandmark', 'name', 'phone', 'operationHours']
|
|
300
|
-
.
|
|
301
|
-
|
|
302
|
-
poi[p] = i18n.toLang(poi[p], lang);
|
|
303
|
-
});
|
|
309
|
+
function pseudoTransPoi(poi, lang) {
|
|
310
|
+
['description', 'nearbyLandmark', 'name', 'phone', 'operationHours'].forEach(p => {
|
|
311
|
+
if (poi[p]) poi[p] = i18n.toLang(poi[p], lang);
|
|
312
|
+
});
|
|
304
313
|
if (poi.keywords)
|
|
305
314
|
poi.keywords = poi.keywords.map(keyword => {
|
|
306
315
|
keyword.name = i18n.toLang(keyword.name, lang);
|
|
307
|
-
return keyword
|
|
316
|
+
return keyword;
|
|
308
317
|
});
|
|
309
|
-
if (poi.position.floorName)
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
poi.position.structureName = i18n.toLang(poi.position.structureName, lang);
|
|
313
|
-
return poi
|
|
318
|
+
if (poi.position.floorName) poi.position.floorName = i18n.toLang(poi.position.floorName, lang);
|
|
319
|
+
if (poi.position.structureName) poi.position.structureName = i18n.toLang(poi.position.structureName, lang);
|
|
320
|
+
return poi;
|
|
314
321
|
}
|
|
315
322
|
|
|
316
323
|
exports.create = create;
|
|
@@ -30,18 +30,31 @@ const headlessCommands = [
|
|
|
30
30
|
{ name: 'from', type: 'location' },
|
|
31
31
|
{ name: 'to', type: 'location' },
|
|
32
32
|
{ name: 'accessible', type: 'boolean', optional: true },
|
|
33
|
-
{
|
|
34
|
-
|
|
33
|
+
{
|
|
34
|
+
name: 'queueTypes',
|
|
35
|
+
type: 'list',
|
|
36
|
+
itemType: { type: 'string' },
|
|
37
|
+
optional: true,
|
|
38
|
+
},
|
|
39
|
+
],
|
|
35
40
|
},
|
|
36
41
|
{
|
|
37
42
|
command: 'getDirectionsMultiple',
|
|
38
43
|
args: [
|
|
39
44
|
{ name: 'locations', type: 'list', itemType: { type: 'location' } },
|
|
40
45
|
{ name: 'accessible', type: 'boolean', optional: true },
|
|
41
|
-
{
|
|
42
|
-
|
|
46
|
+
{
|
|
47
|
+
name: 'queueTypes',
|
|
48
|
+
type: 'list',
|
|
49
|
+
itemType: { type: 'string' },
|
|
50
|
+
optional: true,
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
command: 'getPOIDetails',
|
|
56
|
+
args: [{ name: 'poiId', type: 'integer', min: 0 }],
|
|
43
57
|
},
|
|
44
|
-
{ command: 'getPOIDetails', args: [{ name: 'poiId', type: 'integer', min: 0 }] },
|
|
45
58
|
{ command: 'getAllPOIs' },
|
|
46
59
|
{ command: 'getStructures' },
|
|
47
60
|
{ command: 'getVenueData' },
|
|
@@ -49,39 +62,45 @@ const headlessCommands = [
|
|
|
49
62
|
command: 'search',
|
|
50
63
|
args: [
|
|
51
64
|
{ name: 'term', type: 'string', minLength: 2 },
|
|
52
|
-
{ name: 'details', type: 'boolean', optional: true }
|
|
53
|
-
]
|
|
54
|
-
}
|
|
65
|
+
{ name: 'details', type: 'boolean', optional: true },
|
|
66
|
+
],
|
|
67
|
+
},
|
|
55
68
|
];
|
|
56
69
|
|
|
57
|
-
function handleHeadless
|
|
70
|
+
function handleHeadless(app) {
|
|
58
71
|
app.bus.on('clientAPI/destroy', async () => app.destroy());
|
|
59
72
|
|
|
60
73
|
app.bus.on('clientAPI/getDirections', async ({ from, to, accessible, queueTypes }) => {
|
|
61
74
|
const fromEndpoint = await location.locationToEndpoint(app, from);
|
|
62
75
|
const toEndpoint = await location.locationToEndpoint(app, to);
|
|
63
76
|
const options = { requiresAccessibility: !!accessible };
|
|
64
|
-
if (queueTypes)
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
.then(R__namespace.pick(['distance', 'time', 'steps', 'navline', 'waypoints']))
|
|
77
|
+
if (queueTypes) options.selectedSecurityLanes = { SecurityLane: queueTypes };
|
|
78
|
+
return app.bus
|
|
79
|
+
.get('wayfinder/getRoute', { fromEndpoint, toEndpoint, options })
|
|
80
|
+
.then(R__namespace.pick(['distance', 'time', 'steps', 'navline', 'waypoints']));
|
|
68
81
|
});
|
|
69
82
|
|
|
70
83
|
app.bus.on('clientAPI/getDirectionsMultiple', async ({ locations, accessible, queueTypes }) => {
|
|
71
84
|
const endpoints = await Promise.all(locations.map(async l => location.locationToEndpoint(app, l)));
|
|
72
85
|
const options = { requiresAccessibility: !!accessible };
|
|
73
|
-
if (queueTypes)
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
86
|
+
if (queueTypes) options.selectedSecurityLanes = { SecurityLane: queueTypes };
|
|
87
|
+
const routes = await Promise.all(
|
|
88
|
+
R__namespace.aperture(2, endpoints).map(async a =>
|
|
89
|
+
app.bus.get('wayfinder/getRoute', {
|
|
90
|
+
fromEndpoint: a[0],
|
|
91
|
+
toEndpoint: a[1],
|
|
92
|
+
options,
|
|
93
|
+
}),
|
|
94
|
+
),
|
|
95
|
+
);
|
|
77
96
|
const directions = R__namespace.map(R__namespace.pick(['distance', 'time', 'steps', 'navline', 'waypoints']), routes);
|
|
78
97
|
return {
|
|
79
98
|
total: {
|
|
80
99
|
distance: R__namespace.sum(R__namespace.map(d => d.distance, directions)),
|
|
81
|
-
time: R__namespace.sum(R__namespace.map(d => d.time, directions))
|
|
100
|
+
time: R__namespace.sum(R__namespace.map(d => d.time, directions)),
|
|
82
101
|
},
|
|
83
|
-
directions
|
|
84
|
-
}
|
|
102
|
+
directions,
|
|
103
|
+
};
|
|
85
104
|
});
|
|
86
105
|
|
|
87
106
|
app.bus.on('clientAPI/getPOIDetails', async ({ poiId }) => app.bus.get('poi/getById', { id: poiId }));
|
|
@@ -93,14 +112,21 @@ function handleHeadless (app) {
|
|
|
93
112
|
const isNotFunction = o => typeof o !== 'function';
|
|
94
113
|
app.bus.on('clientAPI/getVenueData', async () => {
|
|
95
114
|
const vd = await app.bus.get('venueData/getVenueData');
|
|
96
|
-
return R__namespace.filter(isNotFunction, vd)
|
|
115
|
+
return R__namespace.filter(isNotFunction, vd);
|
|
97
116
|
});
|
|
98
117
|
|
|
99
|
-
app.bus.on('clientAPI/search', async ({ term, details }) =>
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
118
|
+
app.bus.on('clientAPI/search', async ({ term, details }) =>
|
|
119
|
+
app.bus.get('search/queryAsync', { term }).then(poiList => {
|
|
120
|
+
const poiIdList = poiList.map(poi => poi.poiId);
|
|
121
|
+
app.bus.send('event/search', {
|
|
122
|
+
referrer: 'prog',
|
|
123
|
+
searchMethod: null,
|
|
124
|
+
query: term,
|
|
125
|
+
entities: poiIdList,
|
|
126
|
+
});
|
|
127
|
+
return details ? poiList : poiIdList;
|
|
128
|
+
}),
|
|
129
|
+
);
|
|
104
130
|
}
|
|
105
131
|
|
|
106
132
|
exports.handleHeadless = handleHeadless;
|