atriusmaps-node-sdk 3.3.196 → 3.3.226
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/_virtual/_empty_module_placeholder.js +2 -2
- package/dist/cjs/deploy/prepareSDKConfig.js +152 -2
- package/dist/cjs/nodesdk/nodeEntry.js +109 -0
- package/dist/cjs/package.json.js +190 -14
- package/dist/cjs/plugins/clientAPI/src/clientAPI.js +11 -2
- package/dist/cjs/plugins/dynamicPois/src/dynamicPois.js +218 -21
- package/dist/cjs/plugins/poiDataManager/src/poiDataManager.js +292 -21
- package/dist/cjs/plugins/sdkServer/src/sdkHeadless.js +99 -20
- package/dist/cjs/plugins/sdkServer/src/sdkServer.js +219 -2
- package/dist/cjs/plugins/sdkServer/src/util.js +16 -3
- package/dist/cjs/plugins/searchService/src/poiSearch.js +57 -19
- package/dist/cjs/plugins/searchService/src/searchService.js +246 -21
- package/dist/cjs/plugins/searchService/src/searchTypeahead.js +60 -3
- package/dist/cjs/plugins/searchService/src/utils.js +23 -4
- package/dist/cjs/plugins/venueDataLoader/src/venueDataLoader.js +472 -21
- package/dist/cjs/plugins/venueDataLoader/src/venueLoadingUtils.js +191 -23
- package/dist/cjs/plugins/wayfinder/src/findRoute.js +147 -19
- package/dist/cjs/plugins/wayfinder/src/minPriorityQueue.js +88 -2
- package/dist/cjs/plugins/wayfinder/src/navGraph.js +393 -5
- package/dist/cjs/plugins/wayfinder/src/navGraphDebug.js +110 -20
- package/dist/cjs/plugins/wayfinder/src/segmentBadges.js +28 -2
- package/dist/cjs/plugins/wayfinder/src/segmentBuilder.js +257 -19
- package/dist/cjs/plugins/wayfinder/src/segmentCategories.js +29 -2
- package/dist/cjs/plugins/wayfinder/src/stepBuilder.js +238 -3
- package/dist/cjs/plugins/wayfinder/src/wayfinder.js +597 -22
- package/dist/cjs/src/app.js +191 -25
- package/dist/cjs/src/configs/postproc-mol-url-parms.js +58 -2
- package/dist/cjs/src/configs/postproc-stateTracking.js +53 -19
- package/dist/cjs/src/controller.js +43 -4
- package/dist/cjs/src/debugTools.js +128 -23
- package/dist/cjs/src/env.js +17 -2
- package/dist/cjs/src/extModules/bustle.js +128 -4
- package/dist/cjs/src/extModules/flexapi/src/help.js +23 -4
- package/dist/cjs/src/extModules/flexapi/src/index.js +65 -4
- package/dist/cjs/src/extModules/flexapi/src/validate.js +133 -5
- package/dist/cjs/src/extModules/geohasher.js +90 -3
- package/dist/cjs/src/extModules/log.js +69 -2
- package/dist/cjs/src/historyManager.js +29 -2
- package/dist/cjs/src/utils/bounds.js +22 -4
- package/dist/cjs/src/utils/buildStructureLookup.js +31 -19
- package/dist/cjs/src/utils/configUtils.js +71 -3
- package/dist/cjs/src/utils/dom.js +48 -5
- package/dist/cjs/src/utils/funcs.js +30 -3
- package/dist/cjs/src/utils/geodesy.js +35 -3
- package/dist/cjs/src/utils/geom.js +209 -27
- package/dist/cjs/src/utils/i18n.js +69 -5
- package/dist/cjs/src/utils/observable.js +73 -2
- package/dist/cjs/src/utils/rand.js +82 -3
- package/dist/nodesdk/nodeEntry.js +1 -0
- package/dist/package.json.js +1 -0
- package/dist/plugins/searchService/src/searchService.js +1 -0
- package/dist/plugins/venueDataLoader/src/venueDataLoader.js +1 -0
- package/dist/plugins/venueDataLoader/src/venueLoadingUtils.js +1 -0
- package/dist/src/app.js +1 -0
- package/package.json +13 -9
- package/.yarnrc.yml +0 -1
- package/config/rollup.config.cjs.js +0 -31
- package/dist/cjs/deploy/nodeEntry.js +0 -20
- package/dist/cjs/src/auth/Auth.js +0 -23
- package/lib/deploy/nodeEntry.js +0 -1
- package/lib/package.json.js +0 -1
- package/lib/plugins/searchService/src/searchService.js +0 -1
- package/lib/plugins/venueDataLoader/src/venueDataLoader.js +0 -1
- package/lib/plugins/venueDataLoader/src/venueLoadingUtils.js +0 -1
- package/lib/src/app.js +0 -1
- package/lib/src/configs/sdkHeadless.json +0 -28
- /package/{lib → dist}/_virtual/_empty_module_placeholder.js +0 -0
- /package/{lib → dist}/deploy/prepareSDKConfig.js +0 -0
- /package/{lib → dist}/plugins/clientAPI/src/clientAPI.js +0 -0
- /package/{lib → dist}/plugins/dynamicPois/src/dynamicPois.js +0 -0
- /package/{lib → dist}/plugins/poiDataManager/src/poiDataManager.js +0 -0
- /package/{lib → dist}/plugins/sdkServer/src/sdkHeadless.js +0 -0
- /package/{lib → dist}/plugins/sdkServer/src/sdkServer.js +0 -0
- /package/{lib → dist}/plugins/sdkServer/src/util.js +0 -0
- /package/{lib → dist}/plugins/searchService/src/poiSearch.js +0 -0
- /package/{lib → dist}/plugins/searchService/src/searchTypeahead.js +0 -0
- /package/{lib → dist}/plugins/searchService/src/utils.js +0 -0
- /package/{lib → dist}/plugins/wayfinder/src/findRoute.js +0 -0
- /package/{lib → dist}/plugins/wayfinder/src/minPriorityQueue.js +0 -0
- /package/{lib → dist}/plugins/wayfinder/src/navGraph.js +0 -0
- /package/{lib → dist}/plugins/wayfinder/src/navGraphDebug.js +0 -0
- /package/{lib → dist}/plugins/wayfinder/src/segmentBadges.js +0 -0
- /package/{lib → dist}/plugins/wayfinder/src/segmentBuilder.js +0 -0
- /package/{lib → dist}/plugins/wayfinder/src/segmentCategories.js +0 -0
- /package/{lib → dist}/plugins/wayfinder/src/stepBuilder.js +0 -0
- /package/{lib → dist}/plugins/wayfinder/src/wayfinder.js +0 -0
- /package/{lib → dist}/src/configs/postproc-mol-url-parms.js +0 -0
- /package/{lib → dist}/src/configs/postproc-stateTracking.js +0 -0
- /package/{lib → dist}/src/configs/sdkHeadless.json.js +0 -0
- /package/{lib → dist}/src/controller.js +0 -0
- /package/{lib → dist}/src/debugTools.js +0 -0
- /package/{lib → dist}/src/env.js +0 -0
- /package/{lib → dist}/src/extModules/bustle.js +0 -0
- /package/{lib → dist}/src/extModules/flexapi/src/help.js +0 -0
- /package/{lib → dist}/src/extModules/flexapi/src/index.js +0 -0
- /package/{lib → dist}/src/extModules/flexapi/src/validate.js +0 -0
- /package/{lib → dist}/src/extModules/geohasher.js +0 -0
- /package/{lib → dist}/src/extModules/log.js +0 -0
- /package/{lib → dist}/src/historyManager.js +0 -0
- /package/{lib → dist}/src/utils/bounds.js +0 -0
- /package/{lib → dist}/src/utils/buildStructureLookup.js +0 -0
- /package/{lib → dist}/src/utils/configUtils.js +0 -0
- /package/{lib → dist}/src/utils/dom.js +0 -0
- /package/{lib → dist}/src/utils/funcs.js +0 -0
- /package/{lib → dist}/src/utils/geodesy.js +0 -0
- /package/{lib → dist}/src/utils/geom.js +0 -0
- /package/{lib → dist}/src/utils/i18n.js +0 -0
- /package/{lib → dist}/src/utils/observable.js +0 -0
- /package/{lib → dist}/src/utils/rand.js +0 -0
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
var
|
|
6
|
-
var
|
|
5
|
+
var R = require('ramda');
|
|
6
|
+
var Zousan = require('zousan');
|
|
7
7
|
var configUtils = require('../../../src/utils/configUtils.js');
|
|
8
8
|
var rand = require('../../../src/utils/rand.js');
|
|
9
9
|
var poiSearch = require('./poiSearch.js');
|
|
@@ -12,26 +12,251 @@ var searchTypeahead = require('./searchTypeahead.js');
|
|
|
12
12
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
13
13
|
|
|
14
14
|
function _interopNamespace(e) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
15
|
+
if (e && e.__esModule) return e;
|
|
16
|
+
var n = Object.create(null);
|
|
17
|
+
if (e) {
|
|
18
|
+
Object.keys(e).forEach(function (k) {
|
|
19
|
+
if (k !== 'default') {
|
|
20
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
21
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
22
|
+
enumerable: true,
|
|
23
|
+
get: function () { return e[k]; }
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
n["default"] = e;
|
|
29
|
+
return Object.freeze(n);
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
var
|
|
33
|
-
var
|
|
32
|
+
var R__namespace = /*#__PURE__*/_interopNamespace(R);
|
|
33
|
+
var Zousan__default = /*#__PURE__*/_interopDefaultLegacy(Zousan);
|
|
34
34
|
|
|
35
|
-
function
|
|
35
|
+
function create (app, config) {
|
|
36
|
+
const state = {
|
|
37
|
+
poiSearch: null,
|
|
38
|
+
typeahead: null,
|
|
39
|
+
indexesCreated: new Zousan__default["default"](), // re-initialize this when changing venues
|
|
40
|
+
defaultSearchTerms: null,
|
|
41
|
+
specialQueryTerms: {}
|
|
42
|
+
};
|
|
36
43
|
|
|
37
|
-
|
|
44
|
+
const init = async () => {
|
|
45
|
+
const pois = await app.bus.get('poi/getAll');
|
|
46
|
+
state.poiSearch = poiSearch(pois, app.i18n().language);
|
|
47
|
+
state.typeahead = searchTypeahead(pois, state.poiSearch.search, app.i18n().language);
|
|
48
|
+
state.defaultSearchTerms = configUtils.getLocalized(config, 'defaultSearchTerms', app.i18n().language);
|
|
49
|
+
state.indexesCreated.resolve();
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Prepares and send an event with up to 50 non-portal POIs sorted by distance to user location.
|
|
54
|
+
*/
|
|
55
|
+
// todo check if async events (events which send a new event as a result) are still needed
|
|
56
|
+
app.bus.on('search/queryNearby', async () => {
|
|
57
|
+
const pois = await searchNearby();
|
|
58
|
+
app.bus.send('search/showNearby', { pois, term: 'Nearby' });
|
|
59
|
+
return pois
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Returns max 50 non-portal POIs sorted by distance to user location.
|
|
64
|
+
* @returns Array.<POI>
|
|
65
|
+
*/
|
|
66
|
+
app.bus.on('search/queryNearbyAsync', searchNearby);
|
|
67
|
+
|
|
68
|
+
async function searchNearby () {
|
|
69
|
+
const startLocation = await app.bus.get('user/getPhysicalLocation');
|
|
70
|
+
if (!startLocation?.floorId) return []
|
|
71
|
+
const poisSameFloor = await app.bus.get('poi/getByFloorId', { floorId: startLocation?.floorId });
|
|
72
|
+
const isNotPortal = poi => poi.category.indexOf('portal') === -1 && poi.category !== 'element.door';
|
|
73
|
+
const noPortalPois = Object.values(R__namespace.pickBy(isNotPortal, poisSameFloor));
|
|
74
|
+
const poisWithDistance = await app.bus.get('wayfinder/addPathTimeMultiple', { pois: noPortalPois, startLocation });
|
|
75
|
+
return R__namespace.sortBy(R__namespace.prop('distance'), Object.values(poisWithDistance)).slice(0, 50)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Searches for POIs with search term or category name
|
|
80
|
+
* and sends a new event 'search/showCategory' with search result POIs.
|
|
81
|
+
*
|
|
82
|
+
* @param {string} searchTerm - term to search POIs
|
|
83
|
+
* @param {string} category - category name, fallback term to search POIs
|
|
84
|
+
* @param {string} categoryName - label to display in search results input view
|
|
85
|
+
*/
|
|
86
|
+
app.bus.on('search/queryCategory', async ({ category, categoryName, searchTerm }) => {
|
|
87
|
+
const pois = await state.indexesCreated.then(() =>
|
|
88
|
+
state.poiSearch.search({ query: searchTerm || category }));
|
|
89
|
+
app.bus.send('search/showCategory', { pois, category, categoryName });
|
|
90
|
+
return pois
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Searches for POIs with search term
|
|
95
|
+
* and sends a new event 'search/showCategory' with search result POIs.
|
|
96
|
+
*
|
|
97
|
+
* @param {string} term - search term
|
|
98
|
+
*/
|
|
99
|
+
// todo introduce consistent naming for parameters are return values (searchTem or term, pois or results, keywords or searchTerms)
|
|
100
|
+
app.bus.on('search/query', ({ term }) => {
|
|
101
|
+
return state.indexesCreated.then(() => {
|
|
102
|
+
const pois = state.poiSearch.search({ query: term });
|
|
103
|
+
app.bus.send('search/showSearchResults', { results: pois, term });
|
|
104
|
+
return pois
|
|
105
|
+
})
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Search for POIs with search term.
|
|
110
|
+
*
|
|
111
|
+
* @param {string} term - search term
|
|
112
|
+
* @returns Array.<POI>
|
|
113
|
+
*/
|
|
114
|
+
app.bus.on('search/queryAsync', ({ term }) =>
|
|
115
|
+
state.indexesCreated.then(() => state.poiSearch.search({ query: term }))
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* If search term matches any registered special query term,
|
|
120
|
+
* then send an event with params for this special query,
|
|
121
|
+
* otherwise search for POIs with term and send the event 'search/query' with search result POIs
|
|
122
|
+
*
|
|
123
|
+
* @param {string} term - search term or special query
|
|
124
|
+
*/
|
|
125
|
+
app.bus.on('search/queryWithSpecial', ({ term }) => {
|
|
126
|
+
if (state.specialQueryTerms[term]) {
|
|
127
|
+
const { event, params } = state.specialQueryTerms[term];
|
|
128
|
+
// use "send" as we can't gaurentee this event is a "get" or even returns POIs
|
|
129
|
+
return app.bus.send(event, params)
|
|
130
|
+
} else {
|
|
131
|
+
return app.bus.get('search/query', { term })
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Returns list of all localized default search terms declared in the configuration
|
|
137
|
+
* or list of up to 'limit' random unique POI categories as a fallback.
|
|
138
|
+
* Returns a list of keywords and sends an event 'search/showDefaultSearchKeywords' with same the list of keywords.
|
|
139
|
+
*
|
|
140
|
+
* @param {number} [limit=5] - Used to limit number of random unique categories list if default search terms are not defined in configuration.
|
|
141
|
+
* @returns Array.<string> - list of keywords
|
|
142
|
+
*/
|
|
143
|
+
app.bus.on('search/getDefaultSearchTerms', async ({ limit = 5 } = {}) => {
|
|
144
|
+
const defaultSearchTerms = state.defaultSearchTerms;
|
|
145
|
+
const hasDefaultSearchTerms = defaultSearchTerms && defaultSearchTerms.length;
|
|
146
|
+
const keywords = hasDefaultSearchTerms
|
|
147
|
+
? defaultSearchTerms
|
|
148
|
+
: await getUniqueRandomCategories(limit);
|
|
149
|
+
app.bus.send('search/showDefaultSearchKeywords', { keywords });
|
|
150
|
+
return keywords
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
async function getUniqueRandomCategories (limit) {
|
|
154
|
+
const allCategories = (await app.bus.send('poi/getAllCategories'))[0];
|
|
155
|
+
const uniqueCategories = Array.from(new Set(allCategories));
|
|
156
|
+
const shuffledUniqueCategories = shuffle(uniqueCategories);
|
|
157
|
+
return shuffledUniqueCategories.slice(0, limit)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function shuffle (a) {
|
|
161
|
+
for (let i = a.length - 1; i > 0; i--) {
|
|
162
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
163
|
+
[a[i], a[j]] = [a[j], a[i]];
|
|
164
|
+
}
|
|
165
|
+
return a
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Returns list of up to 'limit' unique random navigable POIs.
|
|
170
|
+
*
|
|
171
|
+
* @param {number} [limit=5]
|
|
172
|
+
* @returns Array.<POI>
|
|
173
|
+
*/
|
|
174
|
+
app.bus.on('search/getDefaultSearchPois', async ({ limit = 5 } = {}) => {
|
|
175
|
+
const allPois = await app.bus.get('poi/getAll');
|
|
176
|
+
const navigablePred = (val, key) => val.isNavigable;
|
|
177
|
+
const navigablePois = R__namespace.pickBy(navigablePred, allPois);
|
|
178
|
+
return rand.arrayPick(Object.values(navigablePois), limit)
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Registers an event and event params for special query term.
|
|
183
|
+
* Optionally adds passed special query term to keywords search index.
|
|
184
|
+
*
|
|
185
|
+
* @param {string} term - special query term
|
|
186
|
+
* @param {string} event - name of associated event
|
|
187
|
+
* @param {Object} params - parameters for associated event
|
|
188
|
+
* @param {boolean} addKeyword - indicates if term has to be added to keywords search index
|
|
189
|
+
*/
|
|
190
|
+
app.bus.on('search/registerSpecialQuery', ({ term, event, params, addKeyword = true }) => {
|
|
191
|
+
state.indexesCreated.then(() => {
|
|
192
|
+
if (addKeyword) {
|
|
193
|
+
state.typeahead.addKeyword(term);
|
|
194
|
+
}
|
|
195
|
+
state.specialQueryTerms[term] = { event, params };
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Adds list of keywords to keywords search index.
|
|
201
|
+
*
|
|
202
|
+
* @param {Array.<string>} keywords - list of new keywords
|
|
203
|
+
*/
|
|
204
|
+
app.bus.on('search/addKeywords', ({ keywords }) =>
|
|
205
|
+
state.indexesCreated.then(() =>
|
|
206
|
+
keywords.forEach(keyword => state.typeahead.addKeyword(keyword))));
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Returns lists of keywords and POIs matching search term.
|
|
210
|
+
*
|
|
211
|
+
* For term shorter than 3 characters only keywords index is queried.
|
|
212
|
+
* If no keywords are found or when term is longer,
|
|
213
|
+
* then POIs index is queried for the the remaining results.
|
|
214
|
+
*
|
|
215
|
+
* @param {string} term - search term
|
|
216
|
+
* @param {number} limit - maximum number of results
|
|
217
|
+
* @returns {{ pois: Array.<POI>, keywords: Array.<String>, term: string }} - list of keywords, list of POIs, search term
|
|
218
|
+
*/
|
|
219
|
+
app.bus.on('search/typeahead', ({ term, limit }) => state.indexesCreated.then(() => {
|
|
220
|
+
const { keywords, pois } = state.typeahead.query(term, limit);
|
|
221
|
+
return { keywords, pois, term }
|
|
222
|
+
}));
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Resets plugin state.
|
|
226
|
+
*/
|
|
227
|
+
app.bus.on('venueData/loadNewVenue', () => {
|
|
228
|
+
state.indexesCreated = new Zousan__default["default"]();
|
|
229
|
+
init();
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Updates POIs search index with dynamic Grab POIs.
|
|
234
|
+
*
|
|
235
|
+
* @param {string} plugin - type of dynamic data
|
|
236
|
+
* @param {Object<string, Object>} - dictionary of POI id to dynamic data object
|
|
237
|
+
*/
|
|
238
|
+
app.bus.on('poi/setDynamicData', async ({ plugin, idValuesMap }) => {
|
|
239
|
+
if (plugin !== 'grab') return
|
|
240
|
+
|
|
241
|
+
const dynamicPoisPromises = Object.keys(idValuesMap)
|
|
242
|
+
.map(id => app.bus.get('poi/getById', { id }));
|
|
243
|
+
|
|
244
|
+
return Promise.all(dynamicPoisPromises)
|
|
245
|
+
.then(pois =>
|
|
246
|
+
state.indexesCreated.then(() =>
|
|
247
|
+
state.poiSearch.updateMultiple(pois)))
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
const runTest = async (initialState, testRoutine) => {
|
|
251
|
+
// state = { ...initialState }
|
|
252
|
+
await testRoutine();
|
|
253
|
+
return state
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
return {
|
|
257
|
+
init,
|
|
258
|
+
runTest
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
exports.create = create;
|
|
@@ -1,8 +1,65 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var R = require('ramda');
|
|
4
4
|
var utils = require('./utils.js');
|
|
5
5
|
|
|
6
|
-
function
|
|
6
|
+
function createSearchTypeahead (pois, poiSearch, lang) {
|
|
7
|
+
const suggestedKeywordsSearch = createSuggestedKeywordsSearch(pois, lang);
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
function queryPois (query, limit) {
|
|
10
|
+
const matches = poiSearch({ query, limit });
|
|
11
|
+
const withSuggestions = poiSearch({ query, suggest: true, limit });
|
|
12
|
+
const matchedIds = matches.map(poi => poi.poiId);
|
|
13
|
+
const filteredSuggestions = withSuggestions.filter(poi => matchedIds.indexOf(poi.poiId) === -1);
|
|
14
|
+
return matches.concat(filteredSuggestions)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const query = (query, limit) => {
|
|
18
|
+
const suggestedKeywords = suggestedKeywordsSearch.search({ query, limit });
|
|
19
|
+
const queryLengthUnderLimit = query.length < 3;
|
|
20
|
+
const shouldQueryPois = !queryLengthUnderLimit && suggestedKeywords.length;
|
|
21
|
+
const poisLimit = limit - suggestedKeywords.length;
|
|
22
|
+
const pois = shouldQueryPois ? queryPois(query, poisLimit) : [];
|
|
23
|
+
return { keywords: suggestedKeywords, pois }
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const addKeyword = (keyword) => {
|
|
27
|
+
suggestedKeywordsSearch.add(keyword);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
return { query, addKeyword }
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function createSuggestedKeywordsSearch (pois, lang) {
|
|
34
|
+
const categories = extractParentCategories(pois);
|
|
35
|
+
const poisKeywords = R.pipe(
|
|
36
|
+
R.values,
|
|
37
|
+
R.chain(R.prop('keywords')),
|
|
38
|
+
R.filter(R.prop('isUserSearchable')),
|
|
39
|
+
R.pluck('name')
|
|
40
|
+
)(pois);
|
|
41
|
+
const allPotentialKeywords = [...categories, ...poisKeywords];
|
|
42
|
+
const keywords = Array.from(new Set([...allPotentialKeywords]));
|
|
43
|
+
const index = utils.getFlexSearchInstance({ lang, type: 'typeahead' });
|
|
44
|
+
|
|
45
|
+
keywords.forEach((keyword, i) => index.add(i, keyword));
|
|
46
|
+
|
|
47
|
+
const search = (queryParams) => {
|
|
48
|
+
const ids = index.search(queryParams);
|
|
49
|
+
return ids.map(index => keywords[index])
|
|
50
|
+
};
|
|
51
|
+
const add = (newKeyword) => {
|
|
52
|
+
keywords.push(newKeyword);
|
|
53
|
+
index.add(keywords.length - 1, newKeyword);
|
|
54
|
+
};
|
|
55
|
+
return { search, add }
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function extractParentCategories (pois) {
|
|
59
|
+
return Object.values(pois)
|
|
60
|
+
.map(poi => poi.category)
|
|
61
|
+
.map(fullCategory => fullCategory.split('.'))
|
|
62
|
+
.map(subcategories => subcategories[0])
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
module.exports = createSearchTypeahead;
|
|
@@ -2,12 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
var
|
|
5
|
+
var FlexSearch = require('flexsearch');
|
|
6
6
|
|
|
7
7
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
8
8
|
|
|
9
|
-
var
|
|
9
|
+
var FlexSearch__default = /*#__PURE__*/_interopDefaultLegacy(FlexSearch);
|
|
10
10
|
|
|
11
|
-
const
|
|
11
|
+
const NON_ASCII_LANGUAGES = ['ko', 'ja', 'zh-Hans', 'zh-Hant'];
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
const getFlexSearchInstance = ({ lang, type = 'standard' }) => {
|
|
14
|
+
const options = {
|
|
15
|
+
tokenize: 'forward',
|
|
16
|
+
rtl: lang === 'ar', // only for arabic
|
|
17
|
+
stemmer: {
|
|
18
|
+
s: '',
|
|
19
|
+
es: '',
|
|
20
|
+
ies: 'y'
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
// Use the full tokenizer for non-ASCII languages and for standard searching
|
|
25
|
+
// but use "forward" for typeahead
|
|
26
|
+
if (NON_ASCII_LANGUAGES.includes(lang))
|
|
27
|
+
options.tokenize = 'full';
|
|
28
|
+
|
|
29
|
+
return new FlexSearch__default["default"].Index(options)
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
exports.getFlexSearchInstance = getFlexSearchInstance;
|