@miso.ai/client-sdk-ui 1.11.0-beta.9 → 1.11.1-beta.0
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/feedback.js +6 -39
- package/dist/cjs/actor/fields.js +14 -6
- package/dist/cjs/actor/index.js +0 -7
- package/dist/cjs/actor/interactions.js +4 -15
- package/dist/cjs/actor/sessions.js +2 -32
- package/dist/cjs/actor/tracker.js +25 -26
- package/dist/cjs/actor/utils.js +0 -49
- package/dist/cjs/actor/view.js +40 -40
- package/dist/cjs/actor/views.js +29 -8
- package/dist/cjs/constants.js +18 -19
- package/dist/cjs/defaults/hybrid-search/phrases.js +3 -3
- package/dist/cjs/defaults/hybrid-search/templates.js +22 -7
- package/dist/cjs/element/role/index.js +12 -5
- package/dist/cjs/element/role/{miso-hits.js → miso-more.js} +4 -4
- package/dist/cjs/element/role/miso-total.js +20 -0
- package/dist/cjs/layout/affiliation/affiliation.js +0 -3
- package/dist/cjs/layout/banner/banner.js +0 -4
- package/dist/cjs/layout/button/more-button.js +73 -0
- package/dist/cjs/layout/container/container.js +0 -3
- package/dist/cjs/layout/error/error.js +0 -4
- package/dist/cjs/layout/index.js +7 -0
- package/dist/cjs/layout/input/facets.js +0 -4
- package/dist/cjs/layout/input/option-list.js +0 -4
- package/dist/cjs/layout/input/search-box.js +13 -12
- package/dist/cjs/layout/list/cards.js +0 -3
- package/dist/cjs/layout/list/carousel.js +0 -3
- package/dist/cjs/layout/list/collection.js +22 -7
- package/dist/cjs/layout/list/list.js +0 -3
- package/dist/cjs/layout/radio/feedback.js +0 -3
- package/dist/cjs/layout/radio/radio.js +0 -4
- package/dist/cjs/layout/raf.js +4 -2
- package/dist/cjs/layout/text/text.js +0 -4
- package/dist/cjs/layout/text/typewriter/index.js +0 -3
- package/dist/cjs/layout/triggerable.js +79 -0
- package/dist/cjs/util/states.js +0 -15
- package/dist/cjs/version.js +1 -1
- package/dist/cjs/workflow/answer-based.js +70 -105
- package/dist/cjs/workflow/ask.js +29 -27
- package/dist/cjs/workflow/asks.js +1 -1
- package/dist/cjs/workflow/autocompletable.js +33 -0
- package/dist/cjs/workflow/autocomplete.js +122 -0
- package/dist/cjs/workflow/base.js +156 -98
- package/dist/cjs/workflow/explore.js +48 -46
- package/dist/cjs/workflow/hybrid-search-answer.js +17 -7
- package/dist/cjs/workflow/hybrid-search-results.js +17 -87
- package/dist/cjs/workflow/hybrid-search-views.js +122 -0
- package/dist/cjs/workflow/hybrid-search.js +47 -168
- package/dist/cjs/workflow/options.js +32 -17
- package/dist/cjs/workflow/processors.js +166 -2
- package/dist/cjs/workflow/recommendation.js +36 -49
- package/dist/cjs/workflow/search-based.js +228 -0
- package/dist/cjs/workflow/search.js +21 -68
- package/dist/cjs/workflow/use-link.js +44 -0
- package/package.json +2 -2
- package/src/actor/feedback.js +6 -23
- package/src/actor/fields.js +14 -6
- package/src/actor/index.js +0 -1
- package/src/actor/interactions.js +4 -10
- package/src/actor/sessions.js +3 -31
- package/src/actor/tracker.js +25 -19
- package/src/actor/utils.js +0 -47
- package/src/actor/view.js +27 -15
- package/src/actor/views.js +32 -8
- package/src/constants.js +25 -16
- package/src/defaults/hybrid-search/phrases.js +2 -2
- package/src/defaults/hybrid-search/templates.js +17 -5
- package/src/element/role/index.js +2 -1
- package/src/element/role/{miso-hits.js → miso-more.js} +3 -3
- package/src/element/role/miso-total.js +16 -0
- package/src/layout/affiliation/affiliation.js +1 -5
- package/src/layout/banner/banner.js +0 -5
- package/src/layout/button/more-button.js +69 -0
- package/src/layout/container/container.js +1 -5
- package/src/layout/error/error.js +0 -5
- package/src/layout/index.js +2 -1
- package/src/layout/input/facets.js +0 -5
- package/src/layout/input/option-list.js +0 -5
- package/src/layout/input/search-box.js +11 -14
- package/src/layout/list/cards.js +0 -4
- package/src/layout/list/carousel.js +0 -4
- package/src/layout/list/collection.js +21 -9
- package/src/layout/list/list.js +0 -4
- package/src/layout/radio/feedback.js +0 -4
- package/src/layout/radio/radio.js +0 -5
- package/src/layout/raf.js +2 -2
- package/src/layout/text/text.js +0 -5
- package/src/layout/text/typewriter/index.js +1 -5
- package/src/layout/triggerable.js +76 -0
- package/src/util/states.js +0 -14
- package/src/version.js +1 -1
- package/src/workflow/answer-based.js +61 -72
- package/src/workflow/ask.js +30 -24
- package/src/workflow/asks.js +1 -1
- package/src/workflow/autocompletable.js +29 -0
- package/src/workflow/autocomplete.js +113 -0
- package/src/workflow/base.js +133 -87
- package/src/workflow/explore.js +38 -30
- package/src/workflow/hybrid-search-answer.js +17 -6
- package/src/workflow/hybrid-search-results.js +17 -77
- package/src/workflow/hybrid-search-views.js +124 -0
- package/src/workflow/hybrid-search.js +47 -157
- package/src/workflow/options.js +26 -11
- package/src/workflow/processors.js +151 -3
- package/src/workflow/recommendation.js +32 -33
- package/src/workflow/search-based.js +222 -0
- package/src/workflow/search.js +21 -65
- package/src/workflow/use-link.js +40 -0
- package/dist/cjs/actor/autocomplete.js +0 -160
- package/dist/cjs/workflow/utils.js +0 -42
- package/src/actor/autocomplete.js +0 -133
- package/src/workflow/utils.js +0 -29
package/src/workflow/base.js
CHANGED
|
@@ -3,35 +3,45 @@ import { Hub, SessionMaker, DataActor, ViewsActor, InteractionsActor, fields } f
|
|
|
3
3
|
import * as sources from '../source.js';
|
|
4
4
|
import { STATUS, ROLE } from '../constants.js';
|
|
5
5
|
import { ContainerLayout, ErrorLayout } from '../layout/index.js';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
|
|
6
|
+
import { WorkflowOptions, mergeApiOptions, makeConfigurable } from './options.js';
|
|
7
|
+
import { getRevision, writeDataStatus, writeMisoIdToMeta, buildBaseInteraction, writeAffiliationInfoToInteraction, mergeInteraction } from './processors.js';
|
|
8
|
+
|
|
9
|
+
// TODO: just bury this into hub
|
|
10
|
+
function injectLogger(hub, callback) {
|
|
11
|
+
const { update, trigger } = hub;
|
|
12
|
+
hub.update = (name, state, options) => {
|
|
13
|
+
if (!options || !options.silent) {
|
|
14
|
+
callback('update', name, state, options);
|
|
15
|
+
}
|
|
16
|
+
return update.call(hub, name, state, options);
|
|
17
|
+
}
|
|
18
|
+
hub.trigger = (...args) => {
|
|
19
|
+
callback('trigger', ...args);
|
|
20
|
+
return trigger.apply(hub, args);
|
|
21
|
+
}
|
|
22
|
+
return hub;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const DEFAULT_API_OPTIONS = Object.freeze({});
|
|
9
26
|
|
|
10
27
|
const DEFAULT_LAYOUTS = Object.freeze({
|
|
11
28
|
[ROLE.CONTAINER]: ContainerLayout.type,
|
|
12
29
|
[ROLE.ERROR]: ErrorLayout.type,
|
|
13
30
|
});
|
|
14
31
|
|
|
15
|
-
const
|
|
16
|
-
[ROLE.ERROR]: {
|
|
17
|
-
mapping: data => data.error,
|
|
18
|
-
},
|
|
19
|
-
});
|
|
32
|
+
const DEFAULT_TRACKERS = Object.freeze({});
|
|
20
33
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
...defaults,
|
|
27
|
-
layouts: mergeLayoutsOptions(DEFAULT_LAYOUTS, layouts),
|
|
28
|
-
interactions: mergeInteractionsOptions(DEFAULT_INTERACTIONS, interactions),
|
|
29
|
-
};
|
|
30
|
-
}
|
|
34
|
+
const DEFAULT_OPTIONS = Object.freeze({
|
|
35
|
+
api: DEFAULT_API_OPTIONS,
|
|
36
|
+
layouts: DEFAULT_LAYOUTS,
|
|
37
|
+
trackers: DEFAULT_TRACKERS,
|
|
38
|
+
});
|
|
31
39
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
40
|
+
const ROLES_OPTIONS = Object.freeze({
|
|
41
|
+
mappings: {
|
|
42
|
+
[ROLE.ERROR]: data => data.error,
|
|
43
|
+
},
|
|
44
|
+
});
|
|
35
45
|
|
|
36
46
|
export default class Workflow extends Component {
|
|
37
47
|
|
|
@@ -46,43 +56,45 @@ export default class Workflow extends Component {
|
|
|
46
56
|
|
|
47
57
|
this._name = args.name;
|
|
48
58
|
this._roles = args.roles;
|
|
49
|
-
this._rolesConfig = { ...ROLES_CONFIG, ...args.rolesConfig };
|
|
50
59
|
|
|
51
60
|
this._extensions = plugin._getExtensions(client);
|
|
52
|
-
this.
|
|
61
|
+
this._defaults = args.defaults;
|
|
62
|
+
this._options = options || new WorkflowOptions(context && context._options, args.defaults);
|
|
53
63
|
this._hub = injectLogger(new Hub(), (...args) => this._log(...args));
|
|
54
64
|
|
|
55
65
|
this._initProperties(args);
|
|
56
66
|
this._initActors(args);
|
|
57
67
|
this._initSubscriptions(args);
|
|
58
|
-
this.
|
|
68
|
+
this._initSession(args);
|
|
59
69
|
}
|
|
60
70
|
|
|
61
71
|
_initProperties() {}
|
|
62
72
|
|
|
63
|
-
_initActors() {
|
|
73
|
+
_initActors({ name, roles }) {
|
|
64
74
|
const hub = this._hub;
|
|
65
75
|
const client = this._client;
|
|
66
|
-
const roles = this._roles;
|
|
67
|
-
const rolesConfig = this._rolesConfig;
|
|
68
76
|
const options = this._options;
|
|
69
77
|
const extensions = this._extensions;
|
|
70
78
|
const layouts = this._plugin.layouts;
|
|
71
79
|
|
|
72
80
|
this._sessions = new SessionMaker(hub);
|
|
73
81
|
this._data = new DataActor(hub, { source: sources.api(client), options });
|
|
74
|
-
this._views = new ViewsActor(hub, { extensions, layouts, roles,
|
|
82
|
+
this._views = new ViewsActor(hub, { extensions, layouts, roles, options, workflow: name });
|
|
75
83
|
this._interactions = new InteractionsActor(hub, { client, options });
|
|
76
84
|
}
|
|
77
85
|
|
|
78
|
-
_initSubscriptions() {
|
|
86
|
+
_initSubscriptions({ roles }) {
|
|
79
87
|
this._unsubscribes = [
|
|
80
88
|
this._hub.on(fields.response(), data => this.updateData(data)),
|
|
89
|
+
this._hub.on(fields.tracker(), args => this._onTracker(args)),
|
|
81
90
|
];
|
|
91
|
+
if (roles.main) {
|
|
92
|
+
this._unsubscribes.push(this._hub.on(fields.view(roles.main), state => this._onMainViewUpdate(state)));
|
|
93
|
+
}
|
|
82
94
|
}
|
|
83
95
|
|
|
84
|
-
|
|
85
|
-
this.
|
|
96
|
+
_initSession() {
|
|
97
|
+
this.restart();
|
|
86
98
|
}
|
|
87
99
|
|
|
88
100
|
get uuid() {
|
|
@@ -93,11 +105,6 @@ export default class Workflow extends Component {
|
|
|
93
105
|
return this._hub.states[fields.session()];
|
|
94
106
|
}
|
|
95
107
|
|
|
96
|
-
get active() {
|
|
97
|
-
const { session } = this;
|
|
98
|
-
return !!session && session.active;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
108
|
get states() {
|
|
102
109
|
return this._hub.states;
|
|
103
110
|
}
|
|
@@ -112,22 +119,51 @@ export default class Workflow extends Component {
|
|
|
112
119
|
}
|
|
113
120
|
|
|
114
121
|
// lifecycle //
|
|
115
|
-
|
|
116
|
-
this.
|
|
122
|
+
restart() {
|
|
123
|
+
this._emitInterruptEventIfNecessary();
|
|
124
|
+
this._sessions.restart();
|
|
117
125
|
return this;
|
|
118
126
|
}
|
|
119
127
|
|
|
120
|
-
|
|
121
|
-
this.
|
|
122
|
-
|
|
128
|
+
_emitInterruptEventIfNecessary() {
|
|
129
|
+
const { main } = this._roles;
|
|
130
|
+
if (!main) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const state = this._hub.states[fields.view(main)] || {};
|
|
134
|
+
if (state.session && state.status === STATUS.LOADING) {
|
|
135
|
+
// it's interrupted by a new question
|
|
136
|
+
this._emitLifecycleEvent('interrupt', state);
|
|
137
|
+
this._emitLifecycleEvent('finally', state);
|
|
138
|
+
}
|
|
123
139
|
}
|
|
124
140
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
141
|
+
_onMainViewUpdate(state) {
|
|
142
|
+
const { status } = state;
|
|
143
|
+
const done = status === STATUS.READY;
|
|
144
|
+
const erroneous = status === STATUS.ERRONEOUS;
|
|
145
|
+
const eventName = erroneous ? 'error' : status;
|
|
146
|
+
this._emitLifecycleEvent(eventName, state);
|
|
147
|
+
if (done) {
|
|
148
|
+
this._emitLifecycleEvent('done', state);
|
|
149
|
+
}
|
|
150
|
+
if (done || erroneous) {
|
|
151
|
+
this._emitLifecycleEvent('finally', state);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
_emitLifecycleEvent(name, event) {
|
|
156
|
+
this._emit(name, event);
|
|
128
157
|
}
|
|
129
158
|
|
|
130
|
-
//
|
|
159
|
+
// request //
|
|
160
|
+
_request(options = {}) {
|
|
161
|
+
const { session } = this;
|
|
162
|
+
const event = mergeApiOptions(this._options.resolved.api, { ...options, session });
|
|
163
|
+
this._hub.update(fields.request(), event);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// data //
|
|
131
167
|
updateData(data) {
|
|
132
168
|
if (!data) {
|
|
133
169
|
throw new Error(`Data is required.`);
|
|
@@ -158,8 +194,6 @@ export default class Workflow extends Component {
|
|
|
158
194
|
}
|
|
159
195
|
|
|
160
196
|
_updateData(data) {
|
|
161
|
-
this._sessions.start(); // in case session not started yet
|
|
162
|
-
|
|
163
197
|
data = this._defaultProcessData(data);
|
|
164
198
|
for (const process of this._options.resolved.dataProcessor) {
|
|
165
199
|
data = process(data);
|
|
@@ -178,24 +212,9 @@ export default class Workflow extends Component {
|
|
|
178
212
|
this._hub.update(fields.data(), data);
|
|
179
213
|
}
|
|
180
214
|
|
|
181
|
-
/*
|
|
182
|
-
_mergeDataIfNecessary(data) {
|
|
183
|
-
if (!data._inst || !data._inst.merge) {
|
|
184
|
-
return data;
|
|
185
|
-
}
|
|
186
|
-
return {
|
|
187
|
-
...this._hub.states[fields.data()],
|
|
188
|
-
...data,
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
_handleResponseObject() {}
|
|
193
|
-
*/
|
|
194
|
-
|
|
195
215
|
// TODO: notifyViewUpdateAll()
|
|
196
216
|
|
|
197
217
|
notifyViewUpdate(role, state) {
|
|
198
|
-
this._assertActive();
|
|
199
218
|
state = {
|
|
200
219
|
status: STATUS.READY,
|
|
201
220
|
session: this.session,
|
|
@@ -210,29 +229,54 @@ export default class Workflow extends Component {
|
|
|
210
229
|
return this._views.trackers;
|
|
211
230
|
}
|
|
212
231
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
const {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
}
|
|
225
|
-
return
|
|
226
|
-
|
|
232
|
+
_onTracker(args) {
|
|
233
|
+
const payload = this._buildInteraction(args);
|
|
234
|
+
this._sendInteraction(payload);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
_buildInteraction(args) {
|
|
238
|
+
let payload = buildBaseInteraction(args);
|
|
239
|
+
payload = this._defaultProcessInteraction(payload, args);
|
|
240
|
+
const { preprocess = [] } = this._options.resolved.interactions;
|
|
241
|
+
for (const p of preprocess) {
|
|
242
|
+
payload = p(payload, args);
|
|
243
|
+
}
|
|
244
|
+
return payload;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
_defaultProcessInteraction(payload, args) {
|
|
248
|
+
payload = this._writeApiInfoToInteraction(payload, args);
|
|
249
|
+
payload = this._writeMisoIdToInteraction(payload, args);
|
|
250
|
+
payload = writeAffiliationInfoToInteraction(payload, args);
|
|
251
|
+
return payload;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
_writeApiInfoToInteraction(payload) {
|
|
255
|
+
const { group, name } = this._options.resolved.api;
|
|
256
|
+
return mergeInteraction(payload, {
|
|
227
257
|
context: {
|
|
228
|
-
...context,
|
|
229
258
|
custom_context: {
|
|
230
|
-
api_group,
|
|
231
|
-
api_name,
|
|
232
|
-
...custom_context,
|
|
259
|
+
api_group: group,
|
|
260
|
+
api_name: name,
|
|
233
261
|
},
|
|
234
262
|
},
|
|
235
|
-
};
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
_writeMisoIdToInteraction(payload, args) {
|
|
267
|
+
// TODO: ad-hoc, try to pass info from tracker
|
|
268
|
+
const state = this._hub.states[fields.view(args.role)] || {};
|
|
269
|
+
const miso_id = (state.meta && state.meta.miso_id) || undefined;
|
|
270
|
+
return miso_id ? mergeInteraction(payload, { miso_id }) : payload;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
_sendInteraction(payload) {
|
|
274
|
+
const { handle } = this._options.resolved.interactions;
|
|
275
|
+
if (typeof handle === 'function') {
|
|
276
|
+
handle(payload);
|
|
277
|
+
} else {
|
|
278
|
+
this._hub.trigger(fields.interaction(), payload);
|
|
279
|
+
}
|
|
236
280
|
}
|
|
237
281
|
|
|
238
282
|
// destroy //
|
|
@@ -263,12 +307,14 @@ export default class Workflow extends Component {
|
|
|
263
307
|
}
|
|
264
308
|
}
|
|
265
309
|
|
|
266
|
-
_assertActive() {
|
|
267
|
-
if (!this.active) {
|
|
268
|
-
throw new Error(`Unit is not active yet. Call unit.start() to activate it.`)
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
|
|
272
310
|
}
|
|
273
311
|
|
|
274
312
|
makeConfigurable(Workflow.prototype);
|
|
313
|
+
|
|
314
|
+
Object.assign(Workflow, {
|
|
315
|
+
DEFAULT_API_OPTIONS,
|
|
316
|
+
DEFAULT_LAYOUTS,
|
|
317
|
+
DEFAULT_TRACKERS,
|
|
318
|
+
DEFAULT_OPTIONS,
|
|
319
|
+
ROLES_OPTIONS,
|
|
320
|
+
});
|
package/src/workflow/explore.js
CHANGED
|
@@ -1,21 +1,25 @@
|
|
|
1
1
|
import { API } from '@miso.ai/commons';
|
|
2
2
|
import Workflow from './base.js';
|
|
3
|
-
import { mergeApiOptions } from './options.js';
|
|
4
3
|
import { fields } from '../actor/index.js';
|
|
5
4
|
import { ROLE, EVENT_TYPE } from '../constants.js';
|
|
6
5
|
import { ListLayout, SearchBoxLayout } from '../layout/index.js';
|
|
6
|
+
import { mergeRolesOptions } from './options.js';
|
|
7
|
+
import { enableUseLink, UseLinkMixin } from './use-link.js';
|
|
7
8
|
|
|
8
9
|
const DEFAULT_API_OPTIONS = Object.freeze({
|
|
10
|
+
...Workflow.DEFAULT_API_OPTIONS,
|
|
9
11
|
group: API.GROUP.ASK,
|
|
10
12
|
name: API.NAME.RELATED_QUESTIONS,
|
|
11
13
|
});
|
|
12
14
|
|
|
13
15
|
const DEFAULT_LAYOUTS = Object.freeze({
|
|
16
|
+
...Workflow.DEFAULT_LAYOUTS,
|
|
14
17
|
[ROLE.RELATED_QUESTIONS]: [ListLayout.type, { itemType: 'question', link: { rel: 'noopener nofollow' } }],
|
|
15
18
|
[ROLE.QUERY]: [SearchBoxLayout.type, { placeholder: 'Ask a question' }],
|
|
16
19
|
});
|
|
17
20
|
|
|
18
21
|
const DEFAULT_TRACKERS = Object.freeze({
|
|
22
|
+
...Workflow.DEFAULT_TRACKERS,
|
|
19
23
|
[ROLE.RELATED_QUESTIONS]: {},
|
|
20
24
|
[ROLE.CONTAINER]: {},
|
|
21
25
|
[ROLE.QUERY]: {
|
|
@@ -24,11 +28,17 @@ const DEFAULT_TRACKERS = Object.freeze({
|
|
|
24
28
|
});
|
|
25
29
|
|
|
26
30
|
const DEFAULT_OPTIONS = Object.freeze({
|
|
31
|
+
...Workflow.DEFAULT_OPTIONS,
|
|
27
32
|
api: DEFAULT_API_OPTIONS,
|
|
28
33
|
layouts: DEFAULT_LAYOUTS,
|
|
29
34
|
trackers: DEFAULT_TRACKERS,
|
|
30
35
|
});
|
|
31
36
|
|
|
37
|
+
const ROLES_OPTIONS = mergeRolesOptions(Workflow.ROLES_OPTIONS, {
|
|
38
|
+
main: ROLE.RELATED_QUESTIONS,
|
|
39
|
+
members: Object.keys(DEFAULT_LAYOUTS),
|
|
40
|
+
});
|
|
41
|
+
|
|
32
42
|
export default class Explore extends Workflow {
|
|
33
43
|
|
|
34
44
|
constructor(plugin, client) {
|
|
@@ -36,7 +46,7 @@ export default class Explore extends Workflow {
|
|
|
36
46
|
name: 'explore',
|
|
37
47
|
plugin,
|
|
38
48
|
client,
|
|
39
|
-
roles:
|
|
49
|
+
roles: ROLES_OPTIONS,
|
|
40
50
|
defaults: DEFAULT_OPTIONS,
|
|
41
51
|
});
|
|
42
52
|
}
|
|
@@ -52,7 +62,7 @@ export default class Explore extends Workflow {
|
|
|
52
62
|
this._unsubscribes = [
|
|
53
63
|
...this._unsubscribes,
|
|
54
64
|
this._views.get(ROLE.RELATED_QUESTIONS).on('click', event => this._handleRelatedQuestionClick(event)),
|
|
55
|
-
this._hub.on(fields.query(),
|
|
65
|
+
this._hub.on(fields.query(), args => this._query(args)),
|
|
56
66
|
];
|
|
57
67
|
}
|
|
58
68
|
|
|
@@ -72,27 +82,18 @@ export default class Explore extends Workflow {
|
|
|
72
82
|
return super.useApi(options);
|
|
73
83
|
}
|
|
74
84
|
|
|
75
|
-
useLink(fn) {
|
|
76
|
-
if (typeof fn !== 'function' && fn !== false) {
|
|
77
|
-
throw new Error('useLink(fn) expects fn to be a function or false');
|
|
78
|
-
}
|
|
79
|
-
this._linkFn = fn;
|
|
80
|
-
return this;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
85
|
// lifecycle //
|
|
84
86
|
start({ relatedQuestions = true } = {}) {
|
|
85
|
-
if (
|
|
86
|
-
throw new Error('
|
|
87
|
+
if (this._linkFn === undefined) {
|
|
88
|
+
throw new Error('Must define link mapping function with useLink(fn) before calling start()');
|
|
87
89
|
}
|
|
88
|
-
this._sessions.start();
|
|
89
90
|
// in explore workflow, start() triggers query
|
|
90
91
|
// TODO: we should still make the query lifecycle
|
|
91
|
-
const { session } = this;
|
|
92
92
|
if (relatedQuestions) {
|
|
93
|
-
this.
|
|
93
|
+
this._request();
|
|
94
94
|
} else {
|
|
95
95
|
// TODO: ad-hoc
|
|
96
|
+
const { session } = this;
|
|
96
97
|
this.updateData({ session, request: {}, value: { related_questions: [] } });
|
|
97
98
|
}
|
|
98
99
|
return this;
|
|
@@ -105,12 +106,17 @@ export default class Explore extends Workflow {
|
|
|
105
106
|
|
|
106
107
|
_defaultProcessData(data) {
|
|
107
108
|
data = super._defaultProcessData(data);
|
|
108
|
-
|
|
109
|
-
|
|
109
|
+
data = this._addUrlToRelatedQuestions(data);
|
|
110
|
+
return data;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
_addUrlToRelatedQuestions(data) {
|
|
114
|
+
const { value } = data;
|
|
115
|
+
if (!value || !value.related_questions) {
|
|
110
116
|
return data;
|
|
111
117
|
}
|
|
112
|
-
|
|
113
|
-
const related_questions = value.related_questions.map(
|
|
118
|
+
const linkFn = this._linkFn && this._linkFn[0];
|
|
119
|
+
const related_questions = value.related_questions.map(linkFn ? (text => ({ text, url: this._getSubmitUrl({ q: text }, { generated: true }) })) : (text => ({ text })));
|
|
114
120
|
return {
|
|
115
121
|
...data,
|
|
116
122
|
value: {
|
|
@@ -124,19 +130,19 @@ export default class Explore extends Workflow {
|
|
|
124
130
|
this._events.emit('select', Object.freeze({ ...event, question }));
|
|
125
131
|
}
|
|
126
132
|
|
|
127
|
-
query(
|
|
128
|
-
if (!
|
|
129
|
-
|
|
133
|
+
query(args) {
|
|
134
|
+
if (!args.q) {
|
|
135
|
+
throw new Error(`q is required in query() call`);
|
|
130
136
|
}
|
|
131
|
-
|
|
132
|
-
window.open(url, '_blank');
|
|
137
|
+
this._hub.update(fields.query(), args);
|
|
133
138
|
}
|
|
134
139
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
+
_query(args) {
|
|
141
|
+
this._submitToPage(args);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
_getSubmitUrl(args, { generated = false } = {}) {
|
|
145
|
+
let url = UseLinkMixin.prototype._getSubmitUrl.call(this, args);
|
|
140
146
|
if (!generated || !this._productId) {
|
|
141
147
|
return url;
|
|
142
148
|
}
|
|
@@ -144,3 +150,5 @@ export default class Explore extends Workflow {
|
|
|
144
150
|
}
|
|
145
151
|
|
|
146
152
|
}
|
|
153
|
+
|
|
154
|
+
enableUseLink(Explore.prototype);
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import AnswerBasedWorkflow from './answer-based.js';
|
|
2
2
|
import { ROLE, STATUS, ORGANIC_QUESTION_SOURCE } from '../constants.js';
|
|
3
|
+
import { mergeRolesOptions } from './options.js';
|
|
3
4
|
import { writeKeywordsToData } from './processors.js';
|
|
5
|
+
import { makeAutocompletable } from './autocompletable.js';
|
|
4
6
|
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
const ROLES_OPTIONS = mergeRolesOptions(AnswerBasedWorkflow.ROLES_OPTIONS, {
|
|
8
|
+
mappings: {
|
|
9
|
+
[ROLE.QUESTION]: ROLE.KEYWORDS,
|
|
8
10
|
},
|
|
9
11
|
});
|
|
10
12
|
|
|
@@ -16,18 +18,19 @@ export default class HybridSearchAnswer extends AnswerBasedWorkflow {
|
|
|
16
18
|
plugin: superworkflow._plugin,
|
|
17
19
|
client: superworkflow._client,
|
|
18
20
|
options: superworkflow._options,
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
defaults: superworkflow._defaults,
|
|
22
|
+
roles: ROLES_OPTIONS,
|
|
21
23
|
superworkflow,
|
|
22
24
|
});
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
_initProperties(args) {
|
|
26
28
|
super._initProperties(args);
|
|
29
|
+
this._initAutocomplete(args);
|
|
27
30
|
this._superworkflow = args.superworkflow;
|
|
28
31
|
}
|
|
29
32
|
|
|
30
|
-
|
|
33
|
+
_initSession() {} // no reset here, will manually reset later
|
|
31
34
|
|
|
32
35
|
restart() {
|
|
33
36
|
super.restart();
|
|
@@ -78,4 +81,12 @@ export default class HybridSearchAnswer extends AnswerBasedWorkflow {
|
|
|
78
81
|
this._resultsSession && this._superworkflow._results.updateData({ ...data, session: this._resultsSession });
|
|
79
82
|
}
|
|
80
83
|
|
|
84
|
+
// destroy //
|
|
85
|
+
_destroy(options) {
|
|
86
|
+
this._destroyAutocomplete();
|
|
87
|
+
super._destroy(options);
|
|
88
|
+
}
|
|
89
|
+
|
|
81
90
|
}
|
|
91
|
+
|
|
92
|
+
makeAutocompletable(HybridSearchAnswer.prototype);
|
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
import { trimObj } from '@miso.ai/commons';
|
|
2
|
-
import
|
|
2
|
+
import SearchBasedWorkflow from './search-based.js';
|
|
3
3
|
import { fields } from '../actor/index.js';
|
|
4
|
-
import { ROLE
|
|
5
|
-
import {
|
|
6
|
-
import { writeKeywordsToData, composeFiltersPayload } from './processors.js';
|
|
4
|
+
import { ROLE } from '../constants.js';
|
|
5
|
+
import { mergeRolesOptions } from './options.js';
|
|
7
6
|
|
|
8
|
-
const
|
|
9
|
-
[ROLE.FACETS]
|
|
10
|
-
mapping: 'facet_counts',
|
|
11
|
-
},
|
|
7
|
+
const ROLES_OPTIONS = mergeRolesOptions(SearchBasedWorkflow.ROLES_OPTIONS, {
|
|
8
|
+
members: [ROLE.PRODUCTS, ROLE.KEYWORDS, ROLE.TOTAL, ROLE.FACETS, ROLE.MORE],
|
|
12
9
|
});
|
|
13
10
|
|
|
14
|
-
export default class HybridSearchResults extends
|
|
11
|
+
export default class HybridSearchResults extends SearchBasedWorkflow {
|
|
15
12
|
|
|
16
13
|
constructor(superworkflow) {
|
|
17
14
|
super({
|
|
@@ -19,8 +16,8 @@ export default class HybridSearchResults extends Workflow {
|
|
|
19
16
|
plugin: superworkflow._plugin,
|
|
20
17
|
client: superworkflow._client,
|
|
21
18
|
options: superworkflow._options,
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
defaults: superworkflow._defaults,
|
|
20
|
+
roles: ROLES_OPTIONS,
|
|
24
21
|
superworkflow,
|
|
25
22
|
});
|
|
26
23
|
}
|
|
@@ -30,49 +27,28 @@ export default class HybridSearchResults extends Workflow {
|
|
|
30
27
|
this._superworkflow = args.superworkflow;
|
|
31
28
|
}
|
|
32
29
|
|
|
33
|
-
|
|
34
|
-
super._initSubscriptions(args);
|
|
35
|
-
this._unsubscribes = [
|
|
36
|
-
...this._unsubscribes,
|
|
37
|
-
this._hub.on(fields.filters(), filters => this._refine(filters)),
|
|
38
|
-
];
|
|
39
|
-
}
|
|
30
|
+
_initSession() {} // no reset here, will manually reset later
|
|
40
31
|
|
|
41
|
-
|
|
32
|
+
// lifecycle //
|
|
33
|
+
_emitLifecycleEvent(name, event) {
|
|
34
|
+
super._emitLifecycleEvent(name, event);
|
|
35
|
+
this._superworkflow._emitLifecycleEvent(name, event);
|
|
36
|
+
}
|
|
42
37
|
|
|
43
38
|
// query //
|
|
44
|
-
|
|
45
|
-
// remember current facet_counts
|
|
46
|
-
const { facet_counts } = this._hub.states[fields.data()].value || {};
|
|
47
|
-
this._previousFacetCounts = facet_counts;
|
|
48
|
-
|
|
49
|
-
// start a new session
|
|
50
|
-
this.restart();
|
|
51
|
-
|
|
39
|
+
_getQuery() {
|
|
52
40
|
// get stored query from sibling
|
|
53
|
-
|
|
54
|
-
const payload = this._buildPayload({ ...query, filters });
|
|
55
|
-
const { session } = this;
|
|
56
|
-
const event = mergeApiOptions(this._options.resolved.api, { payload, session });
|
|
57
|
-
|
|
58
|
-
this._request(event);
|
|
41
|
+
return this._superworkflow._answer._hub.states[fields.query()];
|
|
59
42
|
}
|
|
60
43
|
|
|
61
44
|
_buildPayload({ filters, ...payload } = {}) {
|
|
62
45
|
// borrow the work from the sibling
|
|
63
46
|
payload = this._superworkflow._answer._buildPayload(payload);
|
|
64
|
-
payload =
|
|
47
|
+
payload = SearchBasedWorkflow.prototype._buildPayload.call(this, payload);
|
|
65
48
|
payload = this._writeQuestionIdToPayload(payload);
|
|
66
49
|
return { ...payload, answer: false };
|
|
67
50
|
}
|
|
68
51
|
|
|
69
|
-
_writeFiltersToPayload({ filters, ...payload } = {}) {
|
|
70
|
-
return trimObj({
|
|
71
|
-
...payload,
|
|
72
|
-
...composeFiltersPayload(filters),
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
|
|
76
52
|
_writeQuestionIdToPayload(payload) {
|
|
77
53
|
return {
|
|
78
54
|
...payload,
|
|
@@ -83,40 +59,4 @@ export default class HybridSearchResults extends Workflow {
|
|
|
83
59
|
};
|
|
84
60
|
}
|
|
85
61
|
|
|
86
|
-
_request(event) {
|
|
87
|
-
this._hub.update(fields.request(), event);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// data //
|
|
91
|
-
_defaultProcessData(data) {
|
|
92
|
-
data = super._defaultProcessData(data);
|
|
93
|
-
data = writeKeywordsToData(data);
|
|
94
|
-
data = this._retainFacetCounts(data);
|
|
95
|
-
return data;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
_retainFacetCounts(data) {
|
|
99
|
-
if (!this._previousFacetCounts) {
|
|
100
|
-
return data;
|
|
101
|
-
}
|
|
102
|
-
const { status, value } = data;
|
|
103
|
-
switch (status) {
|
|
104
|
-
case STATUS.INITIAL:
|
|
105
|
-
case STATUS.LOADING:
|
|
106
|
-
break;
|
|
107
|
-
default:
|
|
108
|
-
return data;
|
|
109
|
-
}
|
|
110
|
-
if (value && value.facet_counts) {
|
|
111
|
-
return data;
|
|
112
|
-
}
|
|
113
|
-
return {
|
|
114
|
-
...data,
|
|
115
|
-
value: {
|
|
116
|
-
...value,
|
|
117
|
-
facet_counts: this._previousFacetCounts,
|
|
118
|
-
},
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
|
|
122
62
|
}
|