@miso.ai/client-sdk-ui 1.10.0-beta.0 → 1.10.0-beta.10
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/actor/autocomplete.js +157 -0
- package/dist/cjs/actor/data.js +4 -12
- package/dist/cjs/actor/fields.js +8 -0
- package/dist/cjs/actor/index.js +7 -0
- package/dist/cjs/actor/tracker.js +46 -70
- package/dist/cjs/actor/trackers.js +5 -1
- package/dist/cjs/actor/utils.js +16 -2
- package/dist/cjs/actor/view.js +14 -3
- package/dist/cjs/actor/views.js +9 -1
- package/dist/cjs/affiliation/index.js +126 -0
- package/dist/cjs/combo/ask/options.js +1 -1
- package/dist/cjs/combo/base.js +1 -1
- package/dist/cjs/constants.js +6 -3
- package/dist/cjs/defaults/ask/controls.js +1 -1
- package/dist/cjs/defaults/ask/phrases.js +1 -1
- package/dist/cjs/defaults/ask/templates.js +35 -4
- package/dist/cjs/element/role/index.js +7 -0
- package/dist/cjs/element/role/miso-affiliation.js +20 -0
- package/dist/cjs/layout/affiliation/affiliation.js +330 -0
- package/dist/cjs/layout/banner/banner.js +1 -1
- package/dist/cjs/layout/container/container.js +1 -1
- package/dist/cjs/layout/error/error.js +1 -1
- package/dist/cjs/layout/index.js +7 -0
- package/dist/cjs/layout/input/option-list.js +35 -50
- package/dist/cjs/layout/input/search-box.js +227 -129
- package/dist/cjs/layout/list/cards.js +1 -1
- package/dist/cjs/layout/list/carousel.js +5 -3
- package/dist/cjs/layout/list/collection.js +44 -49
- package/dist/cjs/layout/list/list.js +1 -1
- package/dist/cjs/layout/radio/feedback.js +1 -1
- package/dist/cjs/layout/radio/radio.js +1 -1
- package/dist/cjs/layout/raf.js +1 -1
- package/dist/cjs/layout/template.js +1 -1
- package/dist/cjs/layout/templates.js +172 -66
- package/dist/cjs/layout/text/text.js +1 -1
- package/dist/cjs/layout/text/typewriter/index.js +3 -3
- package/dist/cjs/layout/trackable.js +124 -0
- package/dist/cjs/plugin.js +1 -1
- package/dist/cjs/source/index.js +20 -8
- package/dist/cjs/util/bindings.js +58 -110
- package/dist/cjs/util/states.js +31 -24
- package/dist/cjs/util/trackers.js +75 -0
- package/dist/cjs/util/viewables.js +55 -0
- package/dist/cjs/version.js +1 -1
- package/dist/cjs/workflow/ask.js +60 -19
- package/dist/cjs/workflow/asks.js +1 -1
- package/dist/cjs/workflow/base.js +6 -7
- package/dist/cjs/workflow/explore.js +5 -2
- package/dist/cjs/workflow/options.js +60 -14
- package/dist/cjs/workflow/recommendation.js +2 -0
- package/dist/cjs/workflow/search.js +35 -7
- package/package.json +2 -2
- package/src/actor/autocomplete.js +131 -0
- package/src/actor/data.js +3 -10
- package/src/actor/fields.js +8 -0
- package/src/actor/index.js +1 -0
- package/src/actor/tracker.js +39 -62
- package/src/actor/trackers.js +3 -1
- package/src/actor/utils.js +14 -2
- package/src/actor/view.js +12 -1
- package/src/actor/views.js +11 -0
- package/src/affiliation/index.js +108 -0
- package/src/constants.js +10 -1
- package/src/defaults/ask/phrases.js +1 -1
- package/src/defaults/ask/templates.js +34 -2
- package/src/element/role/index.js +1 -0
- package/src/element/role/miso-affiliation.js +16 -0
- package/src/layout/affiliation/affiliation.js +295 -0
- package/src/layout/index.js +1 -0
- package/src/layout/input/option-list.js +35 -43
- package/src/layout/input/search-box.js +192 -95
- package/src/layout/list/carousel.js +4 -2
- package/src/layout/list/collection.js +42 -43
- package/src/layout/templates.js +127 -46
- package/src/layout/text/typewriter/index.js +2 -2
- package/src/layout/trackable.js +106 -0
- package/src/source/index.js +14 -1
- package/src/util/bindings.js +47 -103
- package/src/util/states.js +26 -20
- package/src/util/trackers.js +69 -0
- package/src/util/viewables.js +47 -0
- package/src/version.js +1 -1
- package/src/workflow/ask.js +37 -3
- package/src/workflow/base.js +2 -3
- package/src/workflow/explore.js +1 -1
- package/src/workflow/options.js +54 -13
- package/src/workflow/recommendation.js +1 -0
- package/src/workflow/search.js +33 -1
- package/dist/cjs/util/tracker.js +0 -348
- package/src/util/tracker.js +0 -318
package/dist/cjs/workflow/ask.js
CHANGED
|
@@ -7,12 +7,16 @@ exports.default = void 0;
|
|
|
7
7
|
var _commons = require("@miso.ai/commons");
|
|
8
8
|
var _base = _interopRequireDefault(require("./base.js"));
|
|
9
9
|
var _options = require("./options.js");
|
|
10
|
-
var
|
|
10
|
+
var sources = _interopRequireWildcard(require("../source/index.js"));
|
|
11
|
+
var _index2 = require("../actor/index.js");
|
|
11
12
|
var _constants = require("../constants.js");
|
|
12
|
-
var
|
|
13
|
+
var _index3 = require("../layout/index.js");
|
|
14
|
+
var _index4 = require("../affiliation/index.js");
|
|
13
15
|
const _excluded = ["q", "qs"];
|
|
16
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
17
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
14
18
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
15
|
-
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.
|
|
19
|
+
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.includes(n)) continue; t[n] = r[n]; } return t; }
|
|
16
20
|
const DEFAULT_API_OPTIONS = Object.freeze({
|
|
17
21
|
group: _commons.API.GROUP.ASK,
|
|
18
22
|
name: _commons.API.NAME.QUESTIONS,
|
|
@@ -24,34 +28,47 @@ const DEFAULT_API_OPTIONS = Object.freeze({
|
|
|
24
28
|
cite_end: ']'
|
|
25
29
|
}
|
|
26
30
|
});
|
|
31
|
+
const DEFAULT_AUTOCOMPLETE_OPTIONS = Object.freeze({
|
|
32
|
+
actor: false,
|
|
33
|
+
api: {
|
|
34
|
+
group: _commons.API.GROUP.ASK,
|
|
35
|
+
name: _commons.API.NAME.AUTOCOMPLETE
|
|
36
|
+
}
|
|
37
|
+
});
|
|
27
38
|
const DEFAULT_LAYOUTS = Object.freeze({
|
|
28
|
-
[_constants.ROLE.QUERY]: [
|
|
39
|
+
[_constants.ROLE.QUERY]: [_index3.SearchBoxLayout.type, {
|
|
29
40
|
placeholder: 'Ask a question'
|
|
30
41
|
}],
|
|
31
|
-
[_constants.ROLE.QUESTION]: [
|
|
42
|
+
[_constants.ROLE.QUESTION]: [_index3.TextLayout.type, {
|
|
32
43
|
tag: 'h2'
|
|
33
44
|
}],
|
|
34
|
-
[_constants.ROLE.ANSWER]:
|
|
35
|
-
[_constants.ROLE.FEEDBACK]:
|
|
36
|
-
[_constants.ROLE.SOURCES]: [
|
|
45
|
+
[_constants.ROLE.ANSWER]: _index3.TypewriterLayout.type,
|
|
46
|
+
[_constants.ROLE.FEEDBACK]: _index3.FeedbackLayout.type,
|
|
47
|
+
[_constants.ROLE.SOURCES]: [_index3.ListLayout.type, {
|
|
37
48
|
incremental: true,
|
|
38
49
|
itemType: 'article',
|
|
39
50
|
templates: {
|
|
40
51
|
ordered: true
|
|
41
52
|
}
|
|
42
53
|
}],
|
|
43
|
-
[_constants.ROLE.RELATED_RESOURCES]: [
|
|
54
|
+
[_constants.ROLE.RELATED_RESOURCES]: [_index3.ListLayout.type, {
|
|
44
55
|
incremental: true,
|
|
45
56
|
itemType: 'article'
|
|
46
57
|
}],
|
|
47
|
-
[_constants.ROLE.QUERY_SUGGESTIONS]:
|
|
58
|
+
[_constants.ROLE.QUERY_SUGGESTIONS]: _index3.OptionListLayout.type,
|
|
59
|
+
[_constants.ROLE.AFFILIATION]: [_index3.AffiliationLayout.type, {
|
|
60
|
+
incremental: true,
|
|
61
|
+
itemType: 'affiliation',
|
|
62
|
+
link: {
|
|
63
|
+
rel: 'noopener nofollow'
|
|
64
|
+
}
|
|
65
|
+
}]
|
|
48
66
|
});
|
|
49
67
|
const DEFAULT_TRACKERS = Object.freeze({
|
|
50
68
|
[_constants.ROLE.SOURCES]: {},
|
|
51
69
|
[_constants.ROLE.RELATED_RESOURCES]: {},
|
|
70
|
+
[_constants.ROLE.AFFILIATION]: {},
|
|
52
71
|
[_constants.ROLE.QUERY_SUGGESTIONS]: {
|
|
53
|
-
active: true,
|
|
54
|
-
// we are tracking events at initial stage, when session is not active yet
|
|
55
72
|
click: {
|
|
56
73
|
validate: event => event.button === 0 // left click only
|
|
57
74
|
}
|
|
@@ -59,6 +76,7 @@ const DEFAULT_TRACKERS = Object.freeze({
|
|
|
59
76
|
});
|
|
60
77
|
const DEFAULT_OPTIONS = Object.freeze({
|
|
61
78
|
api: DEFAULT_API_OPTIONS,
|
|
79
|
+
autocomplete: DEFAULT_AUTOCOMPLETE_OPTIONS,
|
|
62
80
|
layouts: DEFAULT_LAYOUTS,
|
|
63
81
|
trackers: DEFAULT_TRACKERS
|
|
64
82
|
});
|
|
@@ -75,9 +93,17 @@ class Ask extends _base.default {
|
|
|
75
93
|
(0, _commons.defineValues)(this, {
|
|
76
94
|
parentQuestionId
|
|
77
95
|
});
|
|
78
|
-
this._feedback = new
|
|
96
|
+
this._feedback = new _index2.FeedbackActor(this._hub);
|
|
79
97
|
this._setSuggestedQuestions();
|
|
80
|
-
|
|
98
|
+
|
|
99
|
+
/*
|
|
100
|
+
this._autocomplete = new AutocompleteActor(this._hub, {
|
|
101
|
+
source: sources.api(this._client),
|
|
102
|
+
options: this._options,
|
|
103
|
+
});
|
|
104
|
+
*/
|
|
105
|
+
|
|
106
|
+
this._unsubscribes = [...this._unsubscribes, this._hub.on(_index2.fields.query(), payload => this.query(payload)), this._hub.on(_index2.fields.view(_constants.ROLE.ANSWER), data => this._onAnswerViewUpdate(data)), this._views.get(_constants.ROLE.ANSWER).on('citation-click', event => this._onCitationClick(event))];
|
|
81
107
|
parentQuestionId && context._byPqid.set(parentQuestionId, this);
|
|
82
108
|
context._events.emit('create', this);
|
|
83
109
|
this.reset(); // create a session so query suggestions can be tracked
|
|
@@ -163,7 +189,7 @@ class Ask extends _base.default {
|
|
|
163
189
|
session
|
|
164
190
|
} = this;
|
|
165
191
|
session.meta.question_source = questionSource;
|
|
166
|
-
this._hub.update(
|
|
192
|
+
this._hub.update(_index2.fields.request(), (0, _options.mergeApiOptions)(this._options.resolved.api, {
|
|
167
193
|
payload,
|
|
168
194
|
session
|
|
169
195
|
}));
|
|
@@ -175,7 +201,7 @@ class Ask extends _base.default {
|
|
|
175
201
|
session,
|
|
176
202
|
status,
|
|
177
203
|
ongoing
|
|
178
|
-
} = this._hub.states[
|
|
204
|
+
} = this._hub.states[_index2.fields.view(_constants.ROLE.ANSWER)] || {};
|
|
179
205
|
if (session && status !== _constants.STATUS.INITIAL && (status !== _constants.STATUS.READY || ongoing)) {
|
|
180
206
|
// it's interrupted by a new question
|
|
181
207
|
const state = Object.freeze({
|
|
@@ -188,6 +214,18 @@ class Ask extends _base.default {
|
|
|
188
214
|
}
|
|
189
215
|
super.restart();
|
|
190
216
|
}
|
|
217
|
+
|
|
218
|
+
/*
|
|
219
|
+
updateCompletions(event) {
|
|
220
|
+
// TODO: verify
|
|
221
|
+
this._hub.update(fields.completions(), {
|
|
222
|
+
...event,
|
|
223
|
+
source: 'manual',
|
|
224
|
+
});
|
|
225
|
+
return this;
|
|
226
|
+
}
|
|
227
|
+
*/
|
|
228
|
+
|
|
191
229
|
_defaultProcessData(data) {
|
|
192
230
|
data = super._defaultProcessData(data);
|
|
193
231
|
const {
|
|
@@ -220,6 +258,9 @@ class Ask extends _base.default {
|
|
|
220
258
|
}
|
|
221
259
|
}
|
|
222
260
|
|
|
261
|
+
// affiliation
|
|
262
|
+
data = (0, _index4.processData)(data);
|
|
263
|
+
|
|
223
264
|
// 1. put answer_stage to meta
|
|
224
265
|
// 2. mark ongoing flag
|
|
225
266
|
return Object.assign({}, data, {
|
|
@@ -258,9 +299,9 @@ class Ask extends _base.default {
|
|
|
258
299
|
if (!previous) {
|
|
259
300
|
return;
|
|
260
301
|
}
|
|
261
|
-
const values = previous.states[
|
|
302
|
+
const values = previous.states[_index2.fields.data()].value;
|
|
262
303
|
const value = values.suggested_followup_questions || values.followup_questions || [];
|
|
263
|
-
this._hub.update(
|
|
304
|
+
this._hub.update(_index2.fields.suggestions(), {
|
|
264
305
|
value: value.map(text => ({
|
|
265
306
|
text
|
|
266
307
|
}))
|
|
@@ -272,7 +313,7 @@ class Ask extends _base.default {
|
|
|
272
313
|
} = _ref3;
|
|
273
314
|
const {
|
|
274
315
|
value
|
|
275
|
-
} = this.states[
|
|
316
|
+
} = this.states[_index2.fields.data()] || {};
|
|
276
317
|
const {
|
|
277
318
|
sources
|
|
278
319
|
} = value || {};
|
|
@@ -8,7 +8,7 @@ var _context = _interopRequireDefault(require("./context.js"));
|
|
|
8
8
|
var _ask = _interopRequireDefault(require("./ask.js"));
|
|
9
9
|
const _excluded = ["root", "events"];
|
|
10
10
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
11
|
-
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.
|
|
11
|
+
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.includes(n)) continue; t[n] = r[n]; } return t; }
|
|
12
12
|
class Asks extends _context.default {
|
|
13
13
|
constructor(plugin, client) {
|
|
14
14
|
super('asks', plugin, client);
|
|
@@ -16,7 +16,7 @@ const _excluded = ["layouts", "interactions"],
|
|
|
16
16
|
_excluded3 = ["context"];
|
|
17
17
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
18
18
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
19
|
-
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.
|
|
19
|
+
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.includes(n)) continue; t[n] = r[n]; } return t; }
|
|
20
20
|
const DEFAULT_LAYOUTS = Object.freeze({
|
|
21
21
|
[_constants.ROLE.CONTAINER]: _index3.ContainerLayout.type,
|
|
22
22
|
[_constants.ROLE.ERROR]: _index3.ErrorLayout.type
|
|
@@ -59,11 +59,10 @@ class Workflow extends _commons.Component {
|
|
|
59
59
|
const hub = this._hub = (0, _utils.injectLogger)(new _index.Hub(), function () {
|
|
60
60
|
return _this._log(...arguments);
|
|
61
61
|
});
|
|
62
|
-
const source = this._source = sources.api(client);
|
|
63
62
|
const layouts = plugin.layouts;
|
|
64
63
|
this._sessions = new _index.SessionMaker(hub);
|
|
65
64
|
this._data = new _index.DataActor(hub, {
|
|
66
|
-
source,
|
|
65
|
+
source: sources.api(client),
|
|
67
66
|
options
|
|
68
67
|
});
|
|
69
68
|
const views = this._views = new _index.ViewsActor(hub, {
|
|
@@ -73,14 +72,14 @@ class Workflow extends _commons.Component {
|
|
|
73
72
|
options,
|
|
74
73
|
workflow: name
|
|
75
74
|
});
|
|
76
|
-
this._interactions = new _index.InteractionsActor(hub, {
|
|
77
|
-
client,
|
|
78
|
-
options
|
|
79
|
-
});
|
|
80
75
|
this._trackers = new _index.Trackers(hub, {
|
|
81
76
|
views,
|
|
82
77
|
options
|
|
83
78
|
});
|
|
79
|
+
this._interactions = new _index.InteractionsActor(hub, {
|
|
80
|
+
client,
|
|
81
|
+
options
|
|
82
|
+
});
|
|
84
83
|
this._unsubscribes = [this._hub.on(_index.fields.response(), data => this.updateData(data))];
|
|
85
84
|
}
|
|
86
85
|
get uuid() {
|
|
@@ -12,14 +12,17 @@ var _constants = require("../constants.js");
|
|
|
12
12
|
var _index2 = require("../layout/index.js");
|
|
13
13
|
const _excluded = ["value"];
|
|
14
14
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
15
|
-
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.
|
|
15
|
+
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.includes(n)) continue; t[n] = r[n]; } return t; }
|
|
16
16
|
const DEFAULT_API_OPTIONS = Object.freeze({
|
|
17
17
|
group: _commons.API.GROUP.ASK,
|
|
18
18
|
name: _commons.API.NAME.RELATED_QUESTIONS
|
|
19
19
|
});
|
|
20
20
|
const DEFAULT_LAYOUTS = Object.freeze({
|
|
21
21
|
[_constants.ROLE.RELATED_QUESTIONS]: [_index2.ListLayout.type, {
|
|
22
|
-
itemType: 'question'
|
|
22
|
+
itemType: 'question',
|
|
23
|
+
link: {
|
|
24
|
+
rel: 'noopener nofollow'
|
|
25
|
+
}
|
|
23
26
|
}],
|
|
24
27
|
[_constants.ROLE.QUERY]: [_index2.SearchBoxLayout.type, {
|
|
25
28
|
placeholder: 'Ask a question'
|
|
@@ -6,23 +6,26 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.WorkflowOptions = exports.WorkflowContextOptions = void 0;
|
|
7
7
|
exports.makeConfigurable = makeConfigurable;
|
|
8
8
|
exports.mergeApiOptions = mergeApiOptions;
|
|
9
|
+
exports.mergeAutocompleteOptions = mergeAutocompleteOptions;
|
|
9
10
|
exports.mergeDataProcessorOptions = mergeDataProcessorOptions;
|
|
10
11
|
exports.mergeInteractionsOptions = mergeInteractionsOptions;
|
|
11
12
|
exports.mergeLayoutsOptions = mergeLayoutsOptions;
|
|
12
13
|
exports.mergeTrackersOptions = mergeTrackersOptions;
|
|
13
14
|
exports.normalizeApiOptions = normalizeApiOptions;
|
|
15
|
+
exports.normalizeAutocompleteOptions = normalizeAutocompleteOptions;
|
|
14
16
|
exports.normalizeDataProcessorOptions = normalizeDataProcessorOptions;
|
|
15
17
|
exports.normalizeInteractionsOptions = normalizeInteractionsOptions;
|
|
16
18
|
exports.normalizeLayoutsOptions = normalizeLayoutsOptions;
|
|
17
19
|
exports.normalizeTrackers = normalizeTrackers;
|
|
18
20
|
var _commons = require("@miso.ai/commons");
|
|
19
21
|
var _constants = require("../constants.js");
|
|
20
|
-
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.
|
|
22
|
+
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.includes(n)) continue; t[n] = r[n]; } return t; }
|
|
21
23
|
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
22
24
|
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
23
25
|
// normalize //
|
|
24
26
|
function normalizeApiOptions() {
|
|
25
27
|
let [name, payload] = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
|
|
28
|
+
// TODO: take object form as well
|
|
26
29
|
if (name === false) {
|
|
27
30
|
return {
|
|
28
31
|
actor: false
|
|
@@ -32,10 +35,15 @@ function normalizeApiOptions() {
|
|
|
32
35
|
payload = name;
|
|
33
36
|
name = undefined;
|
|
34
37
|
}
|
|
38
|
+
let group = undefined;
|
|
39
|
+
if (name && name.indexOf('/') !== -1) {
|
|
40
|
+
[group, name] = name.split('/');
|
|
41
|
+
}
|
|
35
42
|
if (name && typeof name !== 'string' || payload !== undefined && typeof payload !== 'object') {
|
|
36
43
|
throw new Error(`Invalid arguments for useApi(): ${name}, ${payload}`);
|
|
37
44
|
}
|
|
38
45
|
return (0, _commons.trimObj)({
|
|
46
|
+
group,
|
|
39
47
|
name,
|
|
40
48
|
payload
|
|
41
49
|
});
|
|
@@ -131,6 +139,20 @@ function normalizeInteractionsOptions(options) {
|
|
|
131
139
|
preprocess
|
|
132
140
|
});
|
|
133
141
|
}
|
|
142
|
+
function normalizeAutocompleteOptions(options) {
|
|
143
|
+
if (options === undefined) {
|
|
144
|
+
throw new Error(`Expect autocomplete options to be an object or a boolean value: ${options}`);
|
|
145
|
+
}
|
|
146
|
+
if (typeof options === 'boolean') {
|
|
147
|
+
options = {
|
|
148
|
+
actor: options
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
const processData = normalizeDataProcessorOptions(options.processData);
|
|
152
|
+
return Object.assign({}, options, {
|
|
153
|
+
processData
|
|
154
|
+
});
|
|
155
|
+
}
|
|
134
156
|
|
|
135
157
|
// merge //
|
|
136
158
|
function mergeApiOptions() {
|
|
@@ -217,6 +239,18 @@ function mergeInteractionsOptions() {
|
|
|
217
239
|
preprocess: concatArrays(merged.preprocess, options.preprocess)
|
|
218
240
|
})));
|
|
219
241
|
}
|
|
242
|
+
function mergeAutocompleteOptions() {
|
|
243
|
+
for (var _len6 = arguments.length, optionsList = new Array(_len6), _key7 = 0; _key7 < _len6; _key7++) {
|
|
244
|
+
optionsList[_key7] = arguments[_key7];
|
|
245
|
+
}
|
|
246
|
+
if (optionsList[optionsList.length - 1] === false) {
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
return mergeOptions(optionsList, (merged, options) => Object.assign(merged, Object.assign({}, options, {
|
|
250
|
+
api: mergeApiOptions(merged.api, options.api),
|
|
251
|
+
processData: mergeDataProcessorOptions(merged.processData, options.processData)
|
|
252
|
+
})));
|
|
253
|
+
}
|
|
220
254
|
|
|
221
255
|
// manifest //
|
|
222
256
|
const FEATURES = [{
|
|
@@ -239,6 +273,10 @@ const FEATURES = [{
|
|
|
239
273
|
key: 'interactions',
|
|
240
274
|
normalize: normalizeInteractionsOptions,
|
|
241
275
|
merge: mergeInteractionsOptions
|
|
276
|
+
}, {
|
|
277
|
+
key: 'autocomplete',
|
|
278
|
+
normalize: normalizeAutocompleteOptions,
|
|
279
|
+
merge: mergeAutocompleteOptions
|
|
242
280
|
}];
|
|
243
281
|
class WorkflowContextOptions {
|
|
244
282
|
constructor() {
|
|
@@ -339,21 +377,29 @@ for (const {
|
|
|
339
377
|
}
|
|
340
378
|
});
|
|
341
379
|
}
|
|
380
|
+
const DEFAULT_FEATURES = ['api', 'layouts', 'dataProcessor', 'trackers', 'interactions'];
|
|
342
381
|
function makeConfigurable(prototype) {
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
382
|
+
let features = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DEFAULT_FEATURES;
|
|
383
|
+
for (const feature of features) {
|
|
384
|
+
injectConfigurableFeature(prototype, feature);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
function injectConfigurableFeature(prototype, feature) {
|
|
388
|
+
if (feature === 'api') {
|
|
389
|
+
Object.assign(prototype, {
|
|
390
|
+
useApi() {
|
|
391
|
+
for (var _len7 = arguments.length, args = new Array(_len7), _key8 = 0; _key8 < _len7; _key8++) {
|
|
392
|
+
args[_key8] = arguments[_key8];
|
|
393
|
+
}
|
|
394
|
+
this._options.api.merge(args);
|
|
395
|
+
return this;
|
|
396
|
+
},
|
|
397
|
+
clearApi() {
|
|
398
|
+
this._options.api.set();
|
|
399
|
+
return this;
|
|
347
400
|
}
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
},
|
|
351
|
-
clearApi() {
|
|
352
|
-
this._options.api.set();
|
|
353
|
-
return this;
|
|
354
|
-
}
|
|
355
|
-
});
|
|
356
|
-
for (const feature of ['layouts', 'dataProcessor', 'trackers', 'interactions']) {
|
|
401
|
+
});
|
|
402
|
+
} else {
|
|
357
403
|
const upperCased = upperCase(feature);
|
|
358
404
|
Object.assign(prototype, {
|
|
359
405
|
[`use${upperCased}`](value) {
|
|
@@ -7,9 +7,12 @@ exports.default = void 0;
|
|
|
7
7
|
var _commons = require("@miso.ai/commons");
|
|
8
8
|
var _base = _interopRequireDefault(require("./base.js"));
|
|
9
9
|
var _options = require("./options.js");
|
|
10
|
-
var
|
|
10
|
+
var sources = _interopRequireWildcard(require("../source/index.js"));
|
|
11
|
+
var _index2 = require("../actor/index.js");
|
|
11
12
|
var _constants = require("../constants.js");
|
|
12
|
-
var
|
|
13
|
+
var _index3 = require("../layout/index.js");
|
|
14
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
15
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
13
16
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
14
17
|
const DEFAULT_API_OPTIONS = Object.freeze({
|
|
15
18
|
group: _commons.API.GROUP.SEARCH,
|
|
@@ -18,15 +21,28 @@ const DEFAULT_API_OPTIONS = Object.freeze({
|
|
|
18
21
|
fl: ['*']
|
|
19
22
|
}
|
|
20
23
|
});
|
|
24
|
+
const DEFAULT_AUTOCOMPLETE_OPTIONS = Object.freeze({
|
|
25
|
+
actor: false,
|
|
26
|
+
api: {
|
|
27
|
+
group: _commons.API.GROUP.SEARCH,
|
|
28
|
+
name: _commons.API.NAME.AUTOCOMPLETE,
|
|
29
|
+
payload: {
|
|
30
|
+
completion_fields: ['suggested_queries', 'title'],
|
|
31
|
+
fl: ['title', 'url', 'cover_image']
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
throttle: 300
|
|
35
|
+
});
|
|
21
36
|
const DEFAULT_LAYOUTS = Object.freeze({
|
|
22
|
-
[_constants.ROLE.QUERY]:
|
|
23
|
-
[_constants.ROLE.PRODUCTS]:
|
|
37
|
+
[_constants.ROLE.QUERY]: _index3.SearchBoxLayout.type,
|
|
38
|
+
[_constants.ROLE.PRODUCTS]: _index3.ListLayout.type
|
|
24
39
|
});
|
|
25
40
|
const DEFAULT_TRACKERS = Object.freeze({
|
|
26
41
|
[_constants.ROLE.PRODUCTS]: {}
|
|
27
42
|
});
|
|
28
43
|
const DEFAULT_OPTIONS = Object.freeze({
|
|
29
44
|
api: DEFAULT_API_OPTIONS,
|
|
45
|
+
autocomplete: DEFAULT_AUTOCOMPLETE_OPTIONS,
|
|
30
46
|
layouts: DEFAULT_LAYOUTS,
|
|
31
47
|
trackers: DEFAULT_TRACKERS
|
|
32
48
|
});
|
|
@@ -39,7 +55,11 @@ class Search extends _base.default {
|
|
|
39
55
|
roles: Object.keys(DEFAULT_LAYOUTS),
|
|
40
56
|
defaults: DEFAULT_OPTIONS
|
|
41
57
|
});
|
|
42
|
-
this.
|
|
58
|
+
this._autocomplete = new _index2.AutocompleteActor(this._hub, {
|
|
59
|
+
source: sources.api(this._client),
|
|
60
|
+
options: this._options
|
|
61
|
+
});
|
|
62
|
+
this._unsubscribes.push(this._hub.on(_index2.fields.query(), payload => this.query(payload)));
|
|
43
63
|
}
|
|
44
64
|
|
|
45
65
|
// lifecycle //
|
|
@@ -71,12 +91,19 @@ class Search extends _base.default {
|
|
|
71
91
|
const {
|
|
72
92
|
session
|
|
73
93
|
} = this;
|
|
74
|
-
this._hub.update(
|
|
94
|
+
this._hub.update(_index2.fields.request(), (0, _options.mergeApiOptions)(this._options.resolved.api, {
|
|
75
95
|
payload,
|
|
76
96
|
session
|
|
77
97
|
}));
|
|
78
98
|
return this;
|
|
79
99
|
}
|
|
100
|
+
updateCompletions(event) {
|
|
101
|
+
// TODO: verify
|
|
102
|
+
this._hub.update(_index2.fields.completions(), Object.assign({}, event, {
|
|
103
|
+
source: 'manual'
|
|
104
|
+
}));
|
|
105
|
+
return this;
|
|
106
|
+
}
|
|
80
107
|
notifyViewUpdate() {
|
|
81
108
|
let role = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _constants.ROLE.PRODUCTS;
|
|
82
109
|
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
@@ -86,4 +113,5 @@ class Search extends _base.default {
|
|
|
86
113
|
return this;
|
|
87
114
|
}
|
|
88
115
|
}
|
|
89
|
-
exports.default = Search;
|
|
116
|
+
exports.default = Search;
|
|
117
|
+
(0, _options.makeConfigurable)(Search.prototype, ['autocomplete']);
|
package/package.json
CHANGED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { STATUS } from '../constants.js';
|
|
2
|
+
import * as fields from './fields.js';
|
|
3
|
+
|
|
4
|
+
export default class AutocompleteActor {
|
|
5
|
+
|
|
6
|
+
constructor(hub, { source, options }) {
|
|
7
|
+
this._hub = hub;
|
|
8
|
+
this._source = source;
|
|
9
|
+
this._options = options;
|
|
10
|
+
this._index = -1;
|
|
11
|
+
|
|
12
|
+
this._unsubscribes = [
|
|
13
|
+
hub.on(fields.input(), () => this._sync()),
|
|
14
|
+
options.on('autocomplete', () => this._syncOptions()),
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
// sync right away
|
|
18
|
+
this._sync(true);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
get active() {
|
|
22
|
+
return this._options.resolved.autocomplete.actor !== false;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
get source() {
|
|
26
|
+
return this._source;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
_syncOptions() {
|
|
30
|
+
// TODO: explore scenarios where options.actor true -> false
|
|
31
|
+
this._sync(true);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async _sync(force = false) {
|
|
35
|
+
// protocol: inactive -> no reaction
|
|
36
|
+
if (!this.active) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const { input } = this._hub.states;
|
|
41
|
+
const value = input && input.value && input.value.trim() || undefined;
|
|
42
|
+
|
|
43
|
+
if (sameInput(this._input, input) && !force) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
this._input = input;
|
|
47
|
+
const index = ++this._index;
|
|
48
|
+
|
|
49
|
+
// new input, abort previous data fetch if any
|
|
50
|
+
this._clearTimeout();
|
|
51
|
+
this._abortPendingRequest({
|
|
52
|
+
type: 'new-input',
|
|
53
|
+
message: 'A new input renders previous autocomplete request obsolete.',
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// emit loading/initial state
|
|
57
|
+
this._emitCompletions({ index, input, status: value ? STATUS.LOADING : STATUS.INITIAL });
|
|
58
|
+
|
|
59
|
+
if (!value) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
try {
|
|
64
|
+
const response = await this._fetchCompletions(input);
|
|
65
|
+
if (this._index !== index) {
|
|
66
|
+
return; // new results loading, discard this one
|
|
67
|
+
}
|
|
68
|
+
this._emitCompletions({ index, input, status: STATUS.READY, value: response.completions });
|
|
69
|
+
} catch (error) {
|
|
70
|
+
this._error(error);
|
|
71
|
+
if (this._index !== index) {
|
|
72
|
+
return; // ignore
|
|
73
|
+
}
|
|
74
|
+
this._emitCompletions({ index, input, status: STATUS.ERRONEOUS, error });
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async _getCompletions(input) {
|
|
79
|
+
// TODO: cache
|
|
80
|
+
return await this._fetchCompletions(input);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async _fetchCompletions({ value }) {
|
|
84
|
+
// TODO: other options?
|
|
85
|
+
const { api } = this._options.resolved.autocomplete;
|
|
86
|
+
const { group, name } = api;
|
|
87
|
+
const { signal } = this._ac || {};
|
|
88
|
+
const options = { ...api.options, signal };
|
|
89
|
+
const payload = { ...api.payload, q: value };
|
|
90
|
+
return await this._source({ group, name, payload, options });
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
_clearTimeout() {
|
|
94
|
+
if (this._timeoutId) {
|
|
95
|
+
clearTimeout(this._timeoutId);
|
|
96
|
+
this._timeoutId = undefined;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
_abortPendingRequest(info) {
|
|
101
|
+
this._ac && this._ac.abort(info);
|
|
102
|
+
this._ac = new AbortController();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
_emitCompletions(event) {
|
|
106
|
+
event.source = 'actor';
|
|
107
|
+
this._hub.update(fields.completions(), event);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
_error(error) {
|
|
111
|
+
// TODO
|
|
112
|
+
console.error(error);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
_destroy() {
|
|
116
|
+
// abort ongoing data fetch if any
|
|
117
|
+
this._ac && this._ac.abort({
|
|
118
|
+
type: 'autocomplete-actor-destroy',
|
|
119
|
+
message: 'Autocomplete actor is destroyed.',
|
|
120
|
+
});
|
|
121
|
+
for (const unsubscribe of this._unsubscribes) {
|
|
122
|
+
unsubscribe();
|
|
123
|
+
}
|
|
124
|
+
this._unsubscribes = [];
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function sameInput(a, b) {
|
|
130
|
+
return (!a && !b) || (a && b && a.value === b.value);
|
|
131
|
+
}
|
package/src/actor/data.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as fields from './fields.js';
|
|
2
|
+
import { isCurrentSession } from './utils.js';
|
|
2
3
|
|
|
3
4
|
export default class DataActor {
|
|
4
5
|
|
|
@@ -61,7 +62,7 @@ export default class DataActor {
|
|
|
61
62
|
let value;
|
|
62
63
|
for await (value of response) {
|
|
63
64
|
// A new session invalidates ongoing data fetch for the old session, terminating the loop
|
|
64
|
-
if (!this.
|
|
65
|
+
if (!isCurrentSession(this._hub, session)) {
|
|
65
66
|
break;
|
|
66
67
|
}
|
|
67
68
|
this._emitResponse({ session, request, value });
|
|
@@ -77,15 +78,7 @@ export default class DataActor {
|
|
|
77
78
|
|
|
78
79
|
_emitResponseWithSessionCheck(response) {
|
|
79
80
|
// A new session invalidates ongoing data fetch
|
|
80
|
-
this.
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
_isCurrentSession(session) {
|
|
84
|
-
if (!session) {
|
|
85
|
-
return false;
|
|
86
|
-
}
|
|
87
|
-
const { session: currentSession } = this._hub.states;
|
|
88
|
-
return currentSession && currentSession.index === session.index;
|
|
81
|
+
isCurrentSession(this._hub, response.session) && this._emitResponse(response);
|
|
89
82
|
}
|
|
90
83
|
|
|
91
84
|
_emitResponse(response) {
|
package/src/actor/fields.js
CHANGED
package/src/actor/index.js
CHANGED
|
@@ -7,4 +7,5 @@ export { default as DataActor } from './data.js';
|
|
|
7
7
|
export { default as ViewsActor } from './views.js';
|
|
8
8
|
export { default as Trackers } from './trackers.js';
|
|
9
9
|
export { default as FeedbackActor } from './feedback.js';
|
|
10
|
+
export { default as AutocompleteActor } from './autocomplete.js';
|
|
10
11
|
export { default as InteractionsActor } from './interactions.js';
|