atriusmaps-node-sdk 3.3.898 → 3.3.900
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/dist/cjs/nodesdk/nodeEntry.js +36 -58
- package/dist/cjs/package.json.js +8 -4
- package/dist/cjs/plugins/clientAPI/src/clientAPI.js +8 -6
- package/dist/cjs/plugins/dynamicPois/src/dynamicPois.js +50 -142
- package/dist/cjs/plugins/dynamicPois/src/processors.js +31 -53
- package/dist/cjs/plugins/flightStatus/src/flightDetailsMapper.js +47 -116
- package/dist/cjs/plugins/flightStatus/src/flightStatus.js +48 -82
- package/dist/cjs/plugins/flightStatus/src/utils.js +4 -14
- package/dist/cjs/plugins/poiDataManager/src/poiDataManager.js +77 -154
- package/dist/cjs/plugins/sdkServer/src/prepareSDKConfig.js +45 -76
- package/dist/cjs/plugins/sdkServer/src/sdkHeadless.js +70 -79
- package/dist/cjs/plugins/sdkServer/src/sdkServer.js +97 -147
- package/dist/cjs/plugins/searchService/src/flexsearchExports/lang.js +16 -190
- package/dist/cjs/plugins/searchService/src/flexsearchExports/simple.js +28 -35
- package/dist/cjs/plugins/searchService/src/poiSearch.js +10 -21
- package/dist/cjs/plugins/searchService/src/searchService.js +45 -147
- package/dist/cjs/plugins/searchService/src/searchTypeahead.js +17 -28
- package/dist/cjs/plugins/searchService/src/utils.js +9 -13
- package/dist/cjs/plugins/venueDataLoader/src/venueDataLoader.js +148 -304
- package/dist/cjs/plugins/venueDataLoader/src/venueLoadingUtils.js +47 -126
- package/dist/cjs/plugins/wayfinder/src/findRoute.js +6 -73
- package/dist/cjs/plugins/wayfinder/src/minPriorityQueue.js +7 -27
- package/dist/cjs/plugins/wayfinder/src/navGraph.js +78 -259
- package/dist/cjs/plugins/wayfinder/src/navGraphDebug.js +26 -57
- package/dist/cjs/plugins/wayfinder/src/segmentBadges.js +25 -25
- package/dist/cjs/plugins/wayfinder/src/segmentBuilder.js +50 -133
- package/dist/cjs/plugins/wayfinder/src/segmentCategories.js +29 -29
- package/dist/cjs/plugins/wayfinder/src/stepBuilder.js +53 -145
- package/dist/cjs/plugins/wayfinder/src/wayfinder.js +105 -349
- package/dist/cjs/src/app.js +53 -91
- package/dist/cjs/src/configs/postproc-mol-url-parms.js +34 -43
- package/dist/cjs/src/configs/postproc-stateTracking.js +1 -19
- package/dist/cjs/src/controller.js +4 -26
- package/dist/cjs/src/debugTools.js +55 -94
- package/dist/cjs/src/env.js +8 -19
- package/dist/cjs/src/extModules/bustle.js +15 -71
- package/dist/cjs/src/extModules/flexapi/src/help.js +7 -22
- package/dist/cjs/src/extModules/flexapi/src/index.js +15 -29
- package/dist/cjs/src/extModules/flexapi/src/validate.js +45 -93
- package/dist/cjs/src/extModules/geohasher.js +13 -31
- package/dist/cjs/src/extModules/log.js +18 -29
- package/dist/cjs/src/historyManager.js +4 -6
- package/dist/cjs/src/utils/bounds.js +2 -4
- package/dist/cjs/src/utils/buildStructureLookup.js +7 -7
- package/dist/cjs/src/utils/configUtils.js +7 -43
- package/dist/cjs/src/utils/date.js +5 -17
- package/dist/cjs/src/utils/distance.js +2 -2
- package/dist/cjs/src/utils/dom.js +9 -24
- package/dist/cjs/src/utils/funcs.js +15 -30
- package/dist/cjs/src/utils/geodesy.js +24 -39
- package/dist/cjs/src/utils/geom.js +32 -148
- package/dist/cjs/src/utils/i18n.js +39 -70
- package/dist/cjs/src/utils/isInitialState.js +7 -13
- package/dist/cjs/src/utils/location.js +10 -29
- package/dist/cjs/src/utils/observable.js +4 -29
- package/dist/cjs/src/utils/rand.js +9 -80
- package/dist/cjs/utils/constants.js +1 -1
- package/dist/package.json.js +1 -1
- package/dist/plugins/sdkServer/src/prepareSDKConfig.js +1 -1
- package/dist/src/utils/buildStructureLookup.js +1 -1
- package/dist/src/utils/date.js +1 -1
- package/package.json +1 -1
|
@@ -23,236 +23,153 @@ function _interopNamespaceDefault(e) {
|
|
|
23
23
|
|
|
24
24
|
var R__namespace = /*#__PURE__*/_interopNamespaceDefault(R);
|
|
25
25
|
|
|
26
|
-
const USE_AUTH_WHEN_NOT_PROD_STAGE = false;
|
|
27
|
-
|
|
26
|
+
const USE_AUTH_WHEN_NOT_PROD_STAGE = false;
|
|
28
27
|
async function create(app, config) {
|
|
29
|
-
const log = app.log.sublog(
|
|
28
|
+
const log = app.log.sublog("venueDataLoader");
|
|
30
29
|
let venueDataLoaded = new Zousan();
|
|
31
30
|
let mapDataLoaded = new Zousan();
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
R__namespace.pipe(R__namespace.prop('structures'), Object.values, R__namespace.path([0, 'id']))(venueData);
|
|
38
|
-
|
|
39
|
-
const mergeWithProp = (prop, toAdd, o) => R__namespace.over(R__namespace.lensProp(prop), old => R__namespace.mergeRight(old || {}, toAdd), o);
|
|
40
|
-
|
|
41
|
-
// This function counts the number of characters that match at the beginning of two strings.
|
|
42
|
-
const countMatchedPrefix = (a, b) =>
|
|
43
|
-
a.split('').reduce((max, _, i) => (a.substring(0, i + 1) === b.substring(0, i + 1) ? i : max), -1) + 1;
|
|
44
|
-
|
|
45
|
-
// This function returns the venue definition for a specific language. It does this by filtering the venueList for the specified language,
|
|
46
|
-
// sorting the results by how many characters match at the beginning of the venueId, and
|
|
47
|
-
// returning the first one. If no venues match, undefined is returned.
|
|
48
|
-
const getVenueDefForLang = (venueData, lang) =>
|
|
49
|
-
Object.values(venueData.venueList)
|
|
50
|
-
.filter(venueDef => venueDef.locale === lang) // select all the venues for the specified language
|
|
51
|
-
.sort((a, b) => countMatchedPrefix(b.id, venueData.id) - countMatchedPrefix(a.id, venueData.id)) // sort by how many characters match at the beginning of the venueId - most first
|
|
52
|
-
.at(0); // take the first one, which is the one that matches the most characters at the beginning of the venueId
|
|
53
|
-
|
|
54
|
-
// This function determines the "base venue ID", which currently is the venue ID of the Engilsh version of the venue.
|
|
55
|
-
// We can use the venueList to find the English version of the venue, and then return its ID.
|
|
56
|
-
const calculateBaseVenueId = venueData => getVenueDefForLang(venueData, 'en')?.id;
|
|
57
|
-
|
|
31
|
+
const getDefaultStructureId = (venueData) => venueData.defaultStructureId || R__namespace.path(["structureOrder", 0], venueData) || R__namespace.path(["selectorOrder", 0], venueData) || R__namespace.pipe(R__namespace.prop("structures"), Object.values, R__namespace.path([0, "id"]))(venueData);
|
|
32
|
+
const mergeWithProp = (prop, toAdd, o) => R__namespace.over(R__namespace.lensProp(prop), (old) => R__namespace.mergeRight(old || {}, toAdd), o);
|
|
33
|
+
const countMatchedPrefix = (a, b) => a.split("").reduce((max, _, i) => a.substring(0, i + 1) === b.substring(0, i + 1) ? i : max, -1) + 1;
|
|
34
|
+
const getVenueDefForLang = (venueData, lang) => Object.values(venueData.venueList).filter((venueDef) => venueDef.locale === lang).sort((a, b) => countMatchedPrefix(b.id, venueData.id) - countMatchedPrefix(a.id, venueData.id)).at(0);
|
|
35
|
+
const calculateBaseVenueId = (venueData) => getVenueDefForLang(venueData, "en")?.id;
|
|
58
36
|
async function loadVenueData(vConfig, languagesToTry) {
|
|
59
|
-
|
|
60
|
-
if (
|
|
61
|
-
vConfig.assetStage &&
|
|
62
|
-
vConfig.assetStage !== 'prod' &&
|
|
63
|
-
location.hostname !== 'localhost' &&
|
|
64
|
-
USE_AUTH_WHEN_NOT_PROD_STAGE
|
|
65
|
-
) ;
|
|
66
|
-
|
|
37
|
+
if (vConfig.assetStage && vConfig.assetStage !== "prod" && location.hostname !== "localhost" && USE_AUTH_WHEN_NOT_PROD_STAGE) ;
|
|
67
38
|
const fetchJson = venueLoadingUtils.createFetchJson();
|
|
68
39
|
const fetchText = venueLoadingUtils.createFetchText();
|
|
69
|
-
|
|
70
40
|
const venueData = await venueLoadingUtils.getVenueDataFromUrls(vConfig, fetchJson, languagesToTry);
|
|
71
|
-
|
|
72
41
|
const { accountId, venueId } = vConfig;
|
|
73
|
-
|
|
74
42
|
venueData.assetStage = vConfig.assetStage;
|
|
75
|
-
|
|
76
43
|
venueData.defaultOrdinal = venueData.defaultOrdinal || getDefaultOrdinal(venueData);
|
|
77
44
|
venueData.structures = venueLoadingUtils.buildStructures(venueData);
|
|
78
45
|
venueData.baseVenueId = calculateBaseVenueId(venueData);
|
|
79
|
-
venueData.getTranslatedContentPath = contentType =>
|
|
80
|
-
`https://content.locuslabs.com/${venueData.category}/${contentType}/${venueId}/${accountId}`;
|
|
46
|
+
venueData.getTranslatedContentPath = (contentType) => `https://content.locuslabs.com/${venueData.category}/${contentType}/${venueId}/${accountId}`;
|
|
81
47
|
venueData.fetchJson = fetchJson;
|
|
82
48
|
venueData.fetchText = fetchText;
|
|
83
49
|
if (app.config.debug && app.env.isBrowser) {
|
|
84
50
|
window._venueData = venueData;
|
|
85
51
|
}
|
|
86
|
-
|
|
87
52
|
if (venueData.queueTypes) {
|
|
88
53
|
venueData.securityQueueTypes = (() => {
|
|
89
|
-
const secLane = venueData.queueTypes.find(qt => qt.id ===
|
|
54
|
+
const secLane = venueData.queueTypes.find((qt) => qt.id === "SecurityLane");
|
|
90
55
|
if (secLane) {
|
|
91
|
-
return secLane.subtypes.map(t => t.id);
|
|
56
|
+
return secLane.subtypes.map((t) => t.id);
|
|
92
57
|
}
|
|
93
58
|
return [];
|
|
94
59
|
})();
|
|
95
60
|
}
|
|
96
|
-
|
|
97
|
-
app.bus.send('venueData/venueDataLoaded', { venueData });
|
|
98
|
-
|
|
61
|
+
app.bus.send("venueData/venueDataLoaded", { venueData });
|
|
99
62
|
venueDataLoaded.resolve(venueData);
|
|
100
63
|
return venueDataLoaded;
|
|
101
64
|
}
|
|
102
|
-
|
|
103
65
|
function getDefaultOrdinal(venueData) {
|
|
104
66
|
const defaultStructureId = getDefaultStructureId(venueData);
|
|
105
|
-
const defaultStructure = Object.values(venueData.structures).find(R__namespace.propEq(defaultStructureId,
|
|
67
|
+
const defaultStructure = Object.values(venueData.structures).find(R__namespace.propEq(defaultStructureId, "id"));
|
|
106
68
|
return defaultStructure.levels[defaultStructure.defaultLevelId].ordinal;
|
|
107
69
|
}
|
|
108
|
-
|
|
109
70
|
function notifyState(venueData) {
|
|
110
|
-
const state = { id:
|
|
71
|
+
const state = { id: "venueDataLoader" };
|
|
111
72
|
if (venueData.id !== config.venueId) {
|
|
112
73
|
state.vid = venueData.id;
|
|
113
74
|
}
|
|
114
|
-
|
|
115
75
|
state.lang = app.i18n().language;
|
|
116
|
-
|
|
117
|
-
if (venueData.assetStage !== 'prod') {
|
|
76
|
+
if (venueData.assetStage !== "prod") {
|
|
118
77
|
state.stage = venueData.assetStage;
|
|
119
78
|
}
|
|
120
|
-
app.bus.send(
|
|
79
|
+
app.bus.send("deepLinking/notifyState", state);
|
|
121
80
|
return venueData;
|
|
122
81
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
if (file.type === 'application/json') {
|
|
82
|
+
app.bus.on("debugTools/fileDrop", async ({ file, content }) => {
|
|
83
|
+
if (file.type === "application/json") {
|
|
126
84
|
const jsonOb = JSON.parse(content);
|
|
127
|
-
if (jsonOb.basemap && jsonOb[
|
|
85
|
+
if (jsonOb.basemap && jsonOb["basemap.venue"]) {
|
|
128
86
|
return replaceTheme(JSON.parse(content));
|
|
129
|
-
}
|
|
130
|
-
if (jsonOb.metadata && jsonOb.metadata[
|
|
87
|
+
}
|
|
88
|
+
if (jsonOb.metadata && jsonOb.metadata["mapbox:type"]) {
|
|
131
89
|
return replaceStyle(content);
|
|
132
|
-
}
|
|
90
|
+
}
|
|
133
91
|
}
|
|
134
92
|
});
|
|
135
|
-
|
|
136
|
-
// Returns true if category c1 is within category c2.
|
|
137
|
-
// "within" here means they either are the same category
|
|
138
|
-
// or c2 is a subcategory of c1
|
|
139
|
-
// i.e. withinCategory("eat", "eat") = true
|
|
140
|
-
// withinCategory("eat.coffee", "eat") = true
|
|
141
|
-
// withinCategory("eat", "eat.coffee") = false
|
|
142
|
-
const withinCategory = (c1, c2) => c1 === c2 || c1.indexOf(c2 + '.') === 0;
|
|
143
|
-
|
|
93
|
+
const withinCategory = (c1, c2) => c1 === c2 || c1.indexOf(c2 + ".") === 0;
|
|
144
94
|
function poiMapNameXForm(poi) {
|
|
145
95
|
let name = poi.name;
|
|
146
96
|
if (!config.poiMapNameXForm) {
|
|
147
97
|
return name;
|
|
148
|
-
}
|
|
149
|
-
Object.keys(config.poiMapNameXForm)
|
|
150
|
-
|
|
151
|
-
.forEach(
|
|
152
|
-
|
|
153
|
-
xforms.forEach(xform => (name = name.replace(new RegExp(xform.replace), xform.with)));
|
|
154
|
-
});
|
|
98
|
+
}
|
|
99
|
+
Object.keys(config.poiMapNameXForm).filter((c2) => withinCategory(poi.category, c2)).forEach((c2) => {
|
|
100
|
+
const xforms = config.poiMapNameXForm[c2];
|
|
101
|
+
xforms.forEach((xform) => name = name.replace(new RegExp(xform.replace), xform.with));
|
|
102
|
+
});
|
|
155
103
|
return name;
|
|
156
104
|
}
|
|
157
|
-
|
|
158
|
-
/*
|
|
159
|
-
This function replaces POI labels with the poi.mapLabel (if it exists).
|
|
160
|
-
If it does not exist and the config.copyPOINamesToMap is not explicitly set
|
|
161
|
-
to `false` - then we copy the name from poi.name (and then put it through a
|
|
162
|
-
set of transformations)
|
|
163
|
-
*/
|
|
164
105
|
async function copyPOINames(mapFeatures) {
|
|
165
106
|
const newMapFeatures = { ...mapFeatures };
|
|
166
|
-
const pois = await app.bus.get(
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
if (
|
|
174
|
-
|
|
175
|
-
} else {
|
|
176
|
-
|
|
177
|
-
f.properties.text = poi.mapLabel;
|
|
178
|
-
} else if (config.copyPOINamesToMap !== false) {
|
|
179
|
-
f.properties.text = poiMapNameXForm(poi);
|
|
180
|
-
}
|
|
107
|
+
const pois = await app.bus.get("poi/getAll");
|
|
108
|
+
Object.values(newMapFeatures).forEach(
|
|
109
|
+
(layerArray) => layerArray.filter((f) => f.properties.aiLayer === "poi" && f.geometry.type === "Point").forEach((f) => {
|
|
110
|
+
const poi = pois[f.properties.id];
|
|
111
|
+
if (!poi) {
|
|
112
|
+
log.warn(`Unknown poi in style: ${f.properties.id}`);
|
|
113
|
+
} else {
|
|
114
|
+
if (poi.mapLabel) {
|
|
115
|
+
f.properties.text = poi.mapLabel;
|
|
116
|
+
} else if (config.copyPOINamesToMap !== false) {
|
|
117
|
+
f.properties.text = poiMapNameXForm(poi);
|
|
181
118
|
}
|
|
182
|
-
}
|
|
119
|
+
}
|
|
120
|
+
})
|
|
183
121
|
);
|
|
184
|
-
|
|
185
122
|
return newMapFeatures;
|
|
186
123
|
}
|
|
187
|
-
|
|
188
|
-
// pass in theme object (parsed from theme file)
|
|
189
124
|
function replaceTheme(mapThemeSource) {
|
|
190
|
-
app.bus.send(
|
|
125
|
+
app.bus.send("map/replaceTheme", { theme: mapThemeSource });
|
|
191
126
|
}
|
|
192
|
-
|
|
193
127
|
function replaceStyle(mapStyleSource) {
|
|
194
|
-
app.bus.send(
|
|
128
|
+
app.bus.send("map/replaceStyle", { styleSrc: mapStyleSource });
|
|
195
129
|
}
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* Creates list of source ids from all floor ids and venue id and fetches GeoJSON features for each id.
|
|
199
|
-
* Returns dictionary of source id to list of GeoJson features
|
|
200
|
-
* @returns {Promise<Object<string, Array.<GeoJson>>>}
|
|
201
|
-
*/
|
|
202
130
|
async function getMapFeatures(venueData) {
|
|
203
131
|
return R__namespace.pipe(
|
|
204
|
-
R__namespace.prop(
|
|
205
|
-
R__namespace.map(R__namespace.prop(
|
|
132
|
+
R__namespace.prop("structures"),
|
|
133
|
+
R__namespace.map(R__namespace.prop("levels")),
|
|
206
134
|
R__namespace.chain(R__namespace.keys),
|
|
207
135
|
// Generate list of level IDs plus the venue ID to fetch feature JSON for each
|
|
208
136
|
R__namespace.prepend(venueData.id),
|
|
209
137
|
// eslint-disable-next-line no-template-curly-in-string
|
|
210
|
-
R__namespace.map(geoJsonId => venueData.files.geoJson.replace(
|
|
138
|
+
R__namespace.map((geoJsonId) => venueData.files.geoJson.replace("${geoJsonId}", geoJsonId)),
|
|
211
139
|
R__namespace.map(venueData.fetchJson),
|
|
212
140
|
R__namespace.map(
|
|
213
|
-
R__namespace.andThen(featureJSON => [
|
|
141
|
+
R__namespace.andThen((featureJSON) => [
|
|
214
142
|
featureJSON.id,
|
|
215
|
-
enrichFeaturesForLevel(featureJSON.id, featureJSON.features, venueData.id, venueData.structures)
|
|
216
|
-
])
|
|
143
|
+
enrichFeaturesForLevel(featureJSON.id, featureJSON.features, venueData.id, venueData.structures)
|
|
144
|
+
])
|
|
217
145
|
),
|
|
218
|
-
promises => Zousan.all(promises),
|
|
219
|
-
R__namespace.andThen(R__namespace.fromPairs)
|
|
146
|
+
(promises) => Zousan.all(promises),
|
|
147
|
+
R__namespace.andThen(R__namespace.fromPairs)
|
|
220
148
|
)(venueData);
|
|
221
149
|
}
|
|
222
|
-
|
|
223
150
|
const enrichFeaturesForLevel = (levelId, features, venueId, structures) => {
|
|
224
|
-
const structureId = levelId.replace(/-[^-]*$/,
|
|
225
|
-
const ordinalId =
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
const enrichFeature = feature => {
|
|
230
|
-
feature = mergeWithProp('properties', { venueId, structureId, ordinalId, levelId }, feature);
|
|
231
|
-
feature = R__namespace.assoc('id', feature.properties.subid, feature);
|
|
151
|
+
const structureId = levelId.replace(/-[^-]*$/, "");
|
|
152
|
+
const ordinalId = structureId === venueId ? "landscape-background" : `ordinal: ${structures.find(R__namespace.hasPath(["levels", levelId])).levels[levelId].ordinal}`;
|
|
153
|
+
const enrichFeature = (feature) => {
|
|
154
|
+
feature = mergeWithProp("properties", { venueId, structureId, ordinalId, levelId }, feature);
|
|
155
|
+
feature = R__namespace.assoc("id", feature.properties.subid, feature);
|
|
232
156
|
return feature;
|
|
233
157
|
};
|
|
234
158
|
return features.map(enrichFeature);
|
|
235
159
|
};
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
* Fetches map style, map theme, map GeoJson feature sources.
|
|
239
|
-
* Transforms data to convenient format and sends an event venueData/mapDataLoaded with map data.
|
|
240
|
-
*/
|
|
241
|
-
app.bus.on('venueData/loadMap', async () => {
|
|
242
|
-
venueDataLoaded.then(async venueData => {
|
|
160
|
+
app.bus.on("venueData/loadMap", async () => {
|
|
161
|
+
venueDataLoaded.then(async (venueData) => {
|
|
243
162
|
const mapStyleSource = await venueData.fetchText(venueData.files.style);
|
|
244
163
|
const mapTheme = await venueData.fetchJson(venueData.files.theme);
|
|
245
164
|
const badgesSpriteUrl = venueData.files.spritesheet;
|
|
246
165
|
const mapGlyphsUrl = venueData.files.glyphs;
|
|
247
166
|
const { id, bounds, structures, venueCenter, venueRadius, defaultOrdinal } = venueData;
|
|
248
|
-
const mapFeatures = venueData.venueList[id].mapTokens
|
|
249
|
-
? { [id]: [] }
|
|
250
|
-
: await getMapFeatures(venueData).then(copyPOINames);
|
|
167
|
+
const mapFeatures = venueData.venueList[id].mapTokens ? { [id]: [] } : await getMapFeatures(venueData).then(copyPOINames);
|
|
251
168
|
const venueBounds = {
|
|
252
169
|
n: bounds.ne.lat,
|
|
253
170
|
s: bounds.sw.lat,
|
|
254
171
|
e: bounds.ne.lng,
|
|
255
|
-
w: bounds.sw.lng
|
|
172
|
+
w: bounds.sw.lng
|
|
256
173
|
};
|
|
257
174
|
const mapData = {
|
|
258
175
|
mapFeatures,
|
|
@@ -267,218 +184,152 @@ async function create(app, config) {
|
|
|
267
184
|
venueCenter,
|
|
268
185
|
venueRadius,
|
|
269
186
|
accountId: config.accountId,
|
|
270
|
-
secure: config.auth !==
|
|
271
|
-
tileServerAuthInfo: venueData.tileServerAuthInfo
|
|
187
|
+
secure: config.auth !== void 0,
|
|
188
|
+
tileServerAuthInfo: venueData.tileServerAuthInfo
|
|
189
|
+
// only defined for tile maps
|
|
272
190
|
};
|
|
273
191
|
mapDataLoaded.resolve(mapData);
|
|
274
|
-
app.bus.send(
|
|
192
|
+
app.bus.send("venueData/mapDataLoaded", mapData);
|
|
275
193
|
});
|
|
276
194
|
});
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
// todo check if all async events are still needed (events that sends a new event as result, like 'venueData/buildingSelectorDataLoaded')
|
|
282
|
-
app.bus.on('venueData/loadBuildingSelectorData', () => {
|
|
283
|
-
return venueDataLoaded.then(async venueData => {
|
|
284
|
-
// displayable buildings with levels list ordered by ordinal desc.
|
|
195
|
+
const shouldDisplayPredicate = (building) => building.shouldDisplay == null || building.shouldDisplay;
|
|
196
|
+
app.bus.on("venueData/loadBuildingSelectorData", () => {
|
|
197
|
+
return venueDataLoaded.then(async (venueData) => {
|
|
285
198
|
const buildings = venueData.structures.filter(shouldDisplayPredicate).map(
|
|
286
199
|
R__namespace.evolve({
|
|
287
200
|
// creates copy of structure with modified levels
|
|
288
|
-
levels: R__namespace.pipe(R__namespace.values, R__namespace.sortWith([R__namespace.descend(R__namespace.prop(
|
|
289
|
-
})
|
|
201
|
+
levels: R__namespace.pipe(R__namespace.values, R__namespace.sortWith([R__namespace.descend(R__namespace.prop("ordinal"))]))
|
|
202
|
+
})
|
|
290
203
|
);
|
|
291
|
-
|
|
292
|
-
// todo order buildings using structureOrder and selectorOrder
|
|
293
|
-
// currently structures ordering is duplicated in level selectors handlers
|
|
294
|
-
// then we can remove structureOrder and selectorOrder from result
|
|
295
204
|
const result = {
|
|
296
205
|
buildings,
|
|
297
206
|
structureOrder: venueData.structureOrder,
|
|
298
|
-
selectorOrder: venueData.selectorOrder
|
|
207
|
+
selectorOrder: venueData.selectorOrder
|
|
299
208
|
};
|
|
300
|
-
app.bus.send(
|
|
209
|
+
app.bus.send("venueData/buildingSelectorDataLoaded", result);
|
|
301
210
|
return result;
|
|
302
211
|
});
|
|
303
212
|
});
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
venueDataLoaded.then(venueData => venueLoadingUtils.normalizeCoords(coords, venueData.bounds))
|
|
213
|
+
app.bus.on(
|
|
214
|
+
"venueData/normalizeCoords",
|
|
215
|
+
({ coords }) => venueDataLoaded.then((venueData) => venueLoadingUtils.normalizeCoords(coords, venueData.bounds))
|
|
307
216
|
);
|
|
308
|
-
|
|
309
217
|
const noNavInfo = { edges: [], nodes: [] };
|
|
310
|
-
app.bus.on(
|
|
311
|
-
return venueDataLoaded.then(async venueData => {
|
|
218
|
+
app.bus.on("venueData/loadNavGraph", async () => {
|
|
219
|
+
return venueDataLoaded.then(async (venueData) => {
|
|
312
220
|
const navGraphData = venueData.files.nav ? await venueData.fetchJson(venueData.files.nav) : noNavInfo;
|
|
313
221
|
const navGraphOb = { navGraphData, structures: venueData.structures };
|
|
314
|
-
app.bus.send(
|
|
222
|
+
app.bus.send("venueData/navGraphLoaded", navGraphOb);
|
|
315
223
|
return navGraphOb;
|
|
316
224
|
});
|
|
317
225
|
});
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
const poisUrl = config.useOldDataModel
|
|
322
|
-
? venueData.files.poisOld || venueData.files.pois
|
|
323
|
-
: venueData.files.pois || venueData.files.poisOld;
|
|
226
|
+
app.bus.on("venueData/loadPoiData", async () => {
|
|
227
|
+
return venueDataLoaded.then(async (venueData) => {
|
|
228
|
+
const poisUrl = config.useOldDataModel ? venueData.files.poisOld || venueData.files.pois : venueData.files.pois || venueData.files.poisOld;
|
|
324
229
|
if (poisUrl) {
|
|
325
230
|
const pois = await venueData.fetchJson(poisUrl);
|
|
326
|
-
app.bus.send(
|
|
231
|
+
app.bus.send("venueData/poiDataLoaded", {
|
|
327
232
|
pois,
|
|
328
|
-
structures: venueData.structures
|
|
233
|
+
structures: venueData.structures
|
|
329
234
|
});
|
|
330
235
|
}
|
|
331
236
|
});
|
|
332
237
|
});
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
venueDataLoaded.then(async venueData => ({
|
|
238
|
+
app.bus.on(
|
|
239
|
+
"venueData/getVenueCenter",
|
|
240
|
+
async () => venueDataLoaded.then(async (venueData) => ({
|
|
336
241
|
lat: venueData.venueCenter[0],
|
|
337
242
|
lng: venueData.venueCenter[1],
|
|
338
|
-
ordinal: 0
|
|
339
|
-
}))
|
|
243
|
+
ordinal: 0
|
|
244
|
+
}))
|
|
340
245
|
);
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
venueDataLoaded.then(venueData => venueData.files[type] + name)
|
|
246
|
+
app.bus.on(
|
|
247
|
+
"venueData/getContentUrl",
|
|
248
|
+
({ type, name = "" }) => venueDataLoaded.then((venueData) => venueData.files[type] + name)
|
|
344
249
|
);
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
venueDataLoaded.then(
|
|
250
|
+
app.bus.on(
|
|
251
|
+
"venueData/getFloorIdToNameMap",
|
|
252
|
+
() => venueDataLoaded.then(
|
|
348
253
|
R__namespace.pipe(
|
|
349
|
-
R__namespace.prop(
|
|
350
|
-
R__namespace.map(R__namespace.prop(
|
|
351
|
-
|
|
352
|
-
R__namespace.
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
254
|
+
R__namespace.prop("structures"),
|
|
255
|
+
R__namespace.map(R__namespace.prop("levels")),
|
|
256
|
+
// get levels for each structure
|
|
257
|
+
R__namespace.chain(R__namespace.values),
|
|
258
|
+
// flatten structures levels into single array
|
|
259
|
+
R__namespace.map(R__namespace.props(["id", "name"])),
|
|
260
|
+
// create pairs [id, name]
|
|
261
|
+
R__namespace.fromPairs
|
|
262
|
+
// create map of 'id' to 'name'
|
|
263
|
+
)
|
|
264
|
+
)
|
|
356
265
|
);
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
const structure = R__namespace.pipe(R__namespace.values, R__namespace.find(R__namespace.hasPath(['levels', floorId])))(venueData.structures);
|
|
266
|
+
app.bus.on("venueData/getFloorIdName", ({ floorId }) => {
|
|
267
|
+
return venueDataLoaded.then(async (venueData) => {
|
|
268
|
+
const structure = R__namespace.pipe(R__namespace.values, R__namespace.find(R__namespace.hasPath(["levels", floorId])))(venueData.structures);
|
|
361
269
|
if (!structure) {
|
|
362
270
|
return null;
|
|
363
271
|
}
|
|
364
272
|
return {
|
|
365
273
|
structureId: structure.id,
|
|
366
274
|
structureName: structure.name,
|
|
367
|
-
floorName: structure.levels[floorId].name
|
|
275
|
+
floorName: structure.levels[floorId].name
|
|
368
276
|
};
|
|
369
277
|
});
|
|
370
278
|
});
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
app.bus.on(
|
|
376
|
-
|
|
377
|
-
app.bus.on(
|
|
378
|
-
|
|
379
|
-
app.bus.on(
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
app.bus.on('venueData/getVenueId', getVenueDataProp('id'));
|
|
384
|
-
|
|
385
|
-
app.bus.on('venueData/getPositioningSupported', getVenueDataProp('positioningSupported'));
|
|
386
|
-
app.bus.on('venueData/getStructures', getVenueDataProp('structures'));
|
|
387
|
-
|
|
388
|
-
app.bus.on('venueData/loadNewVenue', async ({ venueId, accountId, assetStage = config.assetStage }) => {
|
|
389
|
-
venueDataLoaded.reject(new Error('loadNewVenue called - previous loading ignored'));
|
|
390
|
-
mapDataLoaded.reject(new Error('loadNewVenue called - previous loading ignored'));
|
|
279
|
+
const getVenueDataProp = (propName, defaultValue) => () => venueDataLoaded.then(R__namespace.pipe(R__namespace.prop(propName), R__namespace.defaultTo(defaultValue)));
|
|
280
|
+
app.bus.on("venueData/getVenueData", () => venueDataLoaded);
|
|
281
|
+
app.bus.on("venueData/getVenueName", getVenueDataProp("name"));
|
|
282
|
+
app.bus.on("venueData/getVenueCategory", getVenueDataProp("category"));
|
|
283
|
+
app.bus.on("venueData/getVenueTimezone", getVenueDataProp("tz"));
|
|
284
|
+
app.bus.on("venueData/getAccountId", () => config.accountId);
|
|
285
|
+
app.bus.on("venueData/getVenueId", getVenueDataProp("id"));
|
|
286
|
+
app.bus.on("venueData/getPositioningSupported", getVenueDataProp("positioningSupported"));
|
|
287
|
+
app.bus.on("venueData/getStructures", getVenueDataProp("structures"));
|
|
288
|
+
app.bus.on("venueData/loadNewVenue", async ({ venueId, accountId, assetStage = config.assetStage }) => {
|
|
289
|
+
venueDataLoaded.reject(new Error("loadNewVenue called - previous loading ignored"));
|
|
290
|
+
mapDataLoaded.reject(new Error("loadNewVenue called - previous loading ignored"));
|
|
391
291
|
venueDataLoaded = new Zousan();
|
|
392
292
|
mapDataLoaded = new Zousan();
|
|
393
293
|
loadVenueData({ ...config, venueId, accountId, assetStage }, []).then(notifyState);
|
|
394
294
|
});
|
|
395
|
-
|
|
396
|
-
// returns a full URL to an image hosted on img.locuslabs.com, size has to be a string of format ${width}x${height}
|
|
397
|
-
app.bus.on('venueData/getPoiImageUrl', ({ imageName, size }) => {
|
|
295
|
+
app.bus.on("venueData/getPoiImageUrl", ({ imageName, size }) => {
|
|
398
296
|
return `https://img.locuslabs.com/resize/${config.accountId}/png/transparent/${size}contain/poi/${imageName}`;
|
|
399
297
|
});
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
// for now it uses venueId and accountId and is used to fix collision when storing data in localStorage
|
|
403
|
-
app.bus.on('venueData/getDistributionId', () => {
|
|
404
|
-
return venueDataLoaded.then(venueData => {
|
|
298
|
+
app.bus.on("venueData/getDistributionId", () => {
|
|
299
|
+
return venueDataLoaded.then((venueData) => {
|
|
405
300
|
return `${venueData.baseVenueId}-${config.accountId}`;
|
|
406
301
|
});
|
|
407
302
|
});
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
venueDataLoaded.then(venueData => {
|
|
411
|
-
const searchUrl = config.useOldDataModel
|
|
412
|
-
? venueData.files.searchOld || venueData.files.search
|
|
413
|
-
: venueData.files.search;
|
|
303
|
+
app.bus.on(
|
|
304
|
+
"venueData/getCustomKeywords",
|
|
305
|
+
() => venueDataLoaded.then((venueData) => {
|
|
306
|
+
const searchUrl = config.useOldDataModel ? venueData.files.searchOld || venueData.files.search : venueData.files.search;
|
|
414
307
|
return venueData.fetchJson(searchUrl);
|
|
415
|
-
})
|
|
308
|
+
})
|
|
416
309
|
);
|
|
417
|
-
|
|
418
|
-
app.bus.on(
|
|
419
|
-
|
|
420
|
-
app.bus.on(
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
app.bus.on('venueData/getTranslatedFloorId', async ({ floorId }) =>
|
|
425
|
-
venueDataLoaded.then(venueData => getTranslatedFloorId(floorId, venueData)),
|
|
310
|
+
app.bus.on("venueData/isGrabEnabled", getVenueDataProp("enableGrab"));
|
|
311
|
+
app.bus.on("venueData/getGrabPoiIds", getVenueDataProp("grabPoiIds", []));
|
|
312
|
+
app.bus.on("venueData/getAssetsTimestamp", getVenueDataProp("version"));
|
|
313
|
+
app.bus.on(
|
|
314
|
+
"venueData/getTranslatedFloorId",
|
|
315
|
+
async ({ floorId }) => venueDataLoaded.then((venueData) => getTranslatedFloorId(floorId, venueData))
|
|
426
316
|
);
|
|
427
|
-
|
|
428
|
-
/**
|
|
429
|
-
* Takes a floorId that may be from the same venue but localized differently
|
|
430
|
-
* so it must be converted to this venue's floorId. FloorIds are of the form
|
|
431
|
-
* <venueId>-<buildingId>-<levelId> where <venueId> has a 2-letter suffice from
|
|
432
|
-
* its baseVenueId.
|
|
433
|
-
*
|
|
434
|
-
* e.g. dfw-building1-level1 -> dfwxx-building1-level1
|
|
435
|
-
* or dfwxx-building1-level1 -> dfw-building1-level1
|
|
436
|
-
* or dfwxx-building1-level1 -> dfwyy-building1-level1
|
|
437
|
-
*
|
|
438
|
-
* @param {string} floorId - The floor ID to translate.
|
|
439
|
-
* @param {Object} venueData - The venue data object containing the baseVenueId and structures.
|
|
440
|
-
* @returns {string} - The translated floor ID that matches the venue's baseVenue
|
|
441
|
-
*/
|
|
442
317
|
function getTranslatedFloorId(floorId, venueData) {
|
|
443
318
|
const allFloorIds = getAllFloorIds(venueData);
|
|
444
|
-
|
|
445
319
|
if (allFloorIds.includes(floorId)) {
|
|
446
320
|
return floorId;
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
// find a floor in the current venueData that matches the specified floorId with just an adjustment to the venueId portion in floorId string construct
|
|
452
|
-
return allFloorIds.find(fid => new RegExp(`${venueData.baseVenueId}.?.?-${buildingLevel}`).test(fid));
|
|
321
|
+
}
|
|
322
|
+
const buildingLevel = floorId.split("-").slice(1).join("-");
|
|
323
|
+
return allFloorIds.find((fid) => new RegExp(`${venueData.baseVenueId}.?.?-${buildingLevel}`).test(fid));
|
|
453
324
|
}
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
/**
|
|
460
|
-
* Returns object with queue types (security and immigration lanes) that are present in the venue defined in venue data.
|
|
461
|
-
* Also adds image id for lanes with images.
|
|
462
|
-
*
|
|
463
|
-
* @typedef QueueType
|
|
464
|
-
* @property {boolean} default
|
|
465
|
-
* @property {string} defaultText
|
|
466
|
-
* @property {string} id
|
|
467
|
-
* @property {string} imageId
|
|
468
|
-
*
|
|
469
|
-
* @typedef QueueTypes
|
|
470
|
-
* @property {QueueType[]} SecurityLane - list of security categories
|
|
471
|
-
* @property {QueueType[]} ImmigrationLane - list of immigration categories
|
|
472
|
-
*
|
|
473
|
-
* @return {QueueTypes} queueTypes
|
|
474
|
-
*/
|
|
475
|
-
app.bus.on('venueData/getQueueTypes', () => {
|
|
476
|
-
return venueDataLoaded.then(venueData => {
|
|
477
|
-
const lanesWithImages = ['tsapre', 'clear', 'globalEntry'];
|
|
325
|
+
const getAllFloorIds = (venueData) => venueData.structures.reduce((floors, s) => floors.concat(Object.keys(s.levels)), []);
|
|
326
|
+
app.bus.on("venueData/getQueueTypes", () => {
|
|
327
|
+
return venueDataLoaded.then((venueData) => {
|
|
328
|
+
const lanesWithImages = ["tsapre", "clear", "globalEntry"];
|
|
478
329
|
if (venueData.queueTypes) {
|
|
479
330
|
return venueData.queueTypes.reduce((obj, category) => {
|
|
480
331
|
const { id, subtypes } = category;
|
|
481
|
-
const typesWithImages = subtypes.map(type => {
|
|
332
|
+
const typesWithImages = subtypes.map((type) => {
|
|
482
333
|
const imageId = lanesWithImages.includes(type.id) && `security-logo-${type.id.toLowerCase()}`;
|
|
483
334
|
return { ...type, imageId };
|
|
484
335
|
});
|
|
@@ -490,7 +341,6 @@ async function create(app, config) {
|
|
|
490
341
|
}
|
|
491
342
|
});
|
|
492
343
|
});
|
|
493
|
-
|
|
494
344
|
const runTest = async ({ testRoutine, reset = false, venueData = null }) => {
|
|
495
345
|
if (reset || venueData) {
|
|
496
346
|
venueDataLoaded = new Zousan();
|
|
@@ -499,9 +349,7 @@ async function create(app, config) {
|
|
|
499
349
|
if (venueData) {
|
|
500
350
|
venueDataLoaded = Zousan.resolve(venueData);
|
|
501
351
|
}
|
|
502
|
-
|
|
503
352
|
await testRoutine();
|
|
504
|
-
|
|
505
353
|
let venueDataObj, mapDataObj;
|
|
506
354
|
if (venueDataLoaded.v) {
|
|
507
355
|
venueDataObj = await venueDataLoaded;
|
|
@@ -511,15 +359,12 @@ async function create(app, config) {
|
|
|
511
359
|
}
|
|
512
360
|
return { venueDataObj, mapDataObj };
|
|
513
361
|
};
|
|
514
|
-
|
|
515
362
|
const init = async () => {
|
|
516
|
-
const params = new URLSearchParams(typeof window ===
|
|
517
|
-
const lang = params.get(
|
|
518
|
-
// On first load there is no URL param for lang unless a customer has created one on purposed, in which case that languauge will be loaded in the UI and the map. If it is first load and no language is specified by the param, grab the browser's list of preferred languages. We will then try to display a map venue for their preferred languages in order if we have it.
|
|
363
|
+
const params = new URLSearchParams(typeof window === "undefined" ? "" : window.location.search);
|
|
364
|
+
const lang = params.get("lang");
|
|
519
365
|
let languagesToTry = [];
|
|
520
366
|
if (lang === null) {
|
|
521
|
-
|
|
522
|
-
languagesToTry = typeof window === 'undefined' ? [] : navigator.languages; // grab languages to use for alternate maps from the browser's list of preffered languages
|
|
367
|
+
languagesToTry = typeof window === "undefined" ? [] : navigator.languages;
|
|
523
368
|
}
|
|
524
369
|
const deepLinkProps = config.deepLinkProps || {};
|
|
525
370
|
if (deepLinkProps.lang) {
|
|
@@ -527,10 +372,9 @@ async function create(app, config) {
|
|
|
527
372
|
}
|
|
528
373
|
const venueId = deepLinkProps.vid || config.venueId;
|
|
529
374
|
const assetStage = config.useDynamicUrlParams && deepLinkProps.stage ? deepLinkProps.stage : config.assetStage;
|
|
530
|
-
const accountId = deepLinkProps.accountId || (assetStage ===
|
|
375
|
+
const accountId = deepLinkProps.accountId || (assetStage === "alpha" ? "A1VPTJKREFJWX5" : config.accountId);
|
|
531
376
|
loadVenueData({ ...config, venueId, accountId, assetStage }, languagesToTry).then(notifyState);
|
|
532
377
|
};
|
|
533
|
-
|
|
534
378
|
return {
|
|
535
379
|
init,
|
|
536
380
|
runTest,
|
|
@@ -540,8 +384,8 @@ async function create(app, config) {
|
|
|
540
384
|
getTranslatedFloorId,
|
|
541
385
|
setConfigProperty: (key, value) => {
|
|
542
386
|
config[key] = value;
|
|
543
|
-
}
|
|
544
|
-
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
545
389
|
};
|
|
546
390
|
}
|
|
547
391
|
|