@miso.ai/client-sdk-ui 1.11.0-beta.8 → 1.11.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 +28 -9
- 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 +20 -9
- 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/util/states.js
CHANGED
|
@@ -4,20 +4,6 @@ import { EVENT_TYPE, TRACKING_STATUS, validateEventType, validateTrackingStatus
|
|
|
4
4
|
const { IMPRESSION, VIEWABLE, CLICK } = EVENT_TYPE;
|
|
5
5
|
const { UNTRACKED, TRIGGERED } = TRACKING_STATUS;
|
|
6
6
|
|
|
7
|
-
/*
|
|
8
|
-
const STATES = {
|
|
9
|
-
NEW: Object.freeze({
|
|
10
|
-
[IMPRESSION]: UNTRACKED,
|
|
11
|
-
[VIEWABLE]: UNTRACKED,
|
|
12
|
-
}),
|
|
13
|
-
UNTRACKED: Object.freeze({
|
|
14
|
-
[IMPRESSION]: UNTRACKED,
|
|
15
|
-
[VIEWABLE]: UNTRACKED,
|
|
16
|
-
[CLICK]: UNTRACKED,
|
|
17
|
-
}),
|
|
18
|
-
};
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
7
|
const UNTRACKED_STATES = Object.freeze({
|
|
22
8
|
[IMPRESSION]: UNTRACKED,
|
|
23
9
|
[VIEWABLE]: UNTRACKED,
|
package/src/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export default '1.11.0
|
|
1
|
+
export default '1.11.0';
|
|
@@ -1,16 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { API } from '@miso.ai/commons';
|
|
2
2
|
import Workflow from './base.js';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
import { fields, FeedbackActor, AutocompleteActor } from '../actor/index.js';
|
|
6
|
-
import { ROLE, STATUS, ORGANIC_QUESTION_SOURCE, DATA_ASPECT } from '../constants.js';
|
|
3
|
+
import { fields, FeedbackActor } from '../actor/index.js';
|
|
4
|
+
import { ROLE, STATUS, ORGANIC_QUESTION_SOURCE } from '../constants.js';
|
|
7
5
|
import { SearchBoxLayout, TextLayout, ListLayout, TypewriterLayout, FeedbackLayout, AffiliationLayout } from '../layout/index.js';
|
|
8
6
|
import { processData as processAffiliationData } from '../affiliation/index.js';
|
|
9
|
-
import {
|
|
7
|
+
import { mergeRolesOptions } from './options.js';
|
|
8
|
+
import { writeAnswerStageToMeta, mergeInteraction } from './processors.js';
|
|
9
|
+
import { enableUseLink } from './use-link.js';
|
|
10
10
|
|
|
11
11
|
const DEFAULT_API_OPTIONS = Object.freeze({
|
|
12
|
+
...Workflow.DEFAULT_API_OPTIONS,
|
|
12
13
|
group: API.GROUP.ASK,
|
|
13
14
|
payload: {
|
|
15
|
+
...Workflow.DEFAULT_API_OPTIONS.payload,
|
|
14
16
|
source_fl: ['cover_image', 'url', 'created_at', 'updated_at', 'published_at'],
|
|
15
17
|
cite_link: 1,
|
|
16
18
|
cite_start: '[',
|
|
@@ -27,6 +29,7 @@ const DEFAULT_AUTOCOMPLETE_OPTIONS = Object.freeze({
|
|
|
27
29
|
});
|
|
28
30
|
|
|
29
31
|
const DEFAULT_LAYOUTS = Object.freeze({
|
|
32
|
+
...Workflow.DEFAULT_LAYOUTS,
|
|
30
33
|
[ROLE.QUERY]: [SearchBoxLayout.type, { placeholder: 'Ask a question' }],
|
|
31
34
|
[ROLE.QUESTION]: [TextLayout.type, { tag: 'h2' }],
|
|
32
35
|
[ROLE.ANSWER]: TypewriterLayout.type,
|
|
@@ -36,18 +39,25 @@ const DEFAULT_LAYOUTS = Object.freeze({
|
|
|
36
39
|
});
|
|
37
40
|
|
|
38
41
|
const DEFAULT_TRACKERS = Object.freeze({
|
|
42
|
+
...Workflow.DEFAULT_TRACKERS,
|
|
39
43
|
[ROLE.SOURCES]: {},
|
|
40
44
|
[ROLE.AFFILIATION]: {},
|
|
41
45
|
[ROLE.PRODUCTS]: {},
|
|
42
46
|
});
|
|
43
47
|
|
|
44
48
|
const DEFAULT_OPTIONS = Object.freeze({
|
|
49
|
+
...Workflow.DEFAULT_OPTIONS,
|
|
45
50
|
api: DEFAULT_API_OPTIONS,
|
|
46
51
|
autocomplete: DEFAULT_AUTOCOMPLETE_OPTIONS,
|
|
47
52
|
layouts: DEFAULT_LAYOUTS,
|
|
48
53
|
trackers: DEFAULT_TRACKERS,
|
|
49
54
|
});
|
|
50
55
|
|
|
56
|
+
const ROLES_OPTIONS = mergeRolesOptions(Workflow.ROLES_OPTIONS, {
|
|
57
|
+
main: ROLE.ANSWER,
|
|
58
|
+
members: Object.keys(DEFAULT_LAYOUTS),
|
|
59
|
+
});
|
|
60
|
+
|
|
51
61
|
export default class AnswerBasedWorkflow extends Workflow {
|
|
52
62
|
|
|
53
63
|
// constructor //
|
|
@@ -60,12 +70,6 @@ export default class AnswerBasedWorkflow extends Workflow {
|
|
|
60
70
|
_initActors(args) {
|
|
61
71
|
super._initActors(args);
|
|
62
72
|
this._feedback = new FeedbackActor(this._hub);
|
|
63
|
-
/*
|
|
64
|
-
this._autocomplete = new AutocompleteActor(this._hub, {
|
|
65
|
-
source: sources.api(this._client),
|
|
66
|
-
options: this._options,
|
|
67
|
-
});
|
|
68
|
-
*/
|
|
69
73
|
}
|
|
70
74
|
|
|
71
75
|
_initSubscriptions(args) {
|
|
@@ -73,7 +77,6 @@ export default class AnswerBasedWorkflow extends Workflow {
|
|
|
73
77
|
this._unsubscribes = [
|
|
74
78
|
...this._unsubscribes,
|
|
75
79
|
this._hub.on(fields.query(), args => this._query(args)),
|
|
76
|
-
this._hub.on(fields.view(ROLE.ANSWER), data => this._onAnswerViewUpdate(data)),
|
|
77
80
|
this._views.get(ROLE.ANSWER).on('citation-click', event => this._onCitationClick(event)),
|
|
78
81
|
];
|
|
79
82
|
}
|
|
@@ -84,19 +87,30 @@ export default class AnswerBasedWorkflow extends Workflow {
|
|
|
84
87
|
if (this._questionId) {
|
|
85
88
|
this._questionId = undefined;
|
|
86
89
|
}
|
|
87
|
-
// interrupt event
|
|
88
|
-
// TODO: move to workflow base
|
|
89
|
-
const { session, status, ongoing } = this._hub.states[fields.view(ROLE.ANSWER)] || {};
|
|
90
|
-
if (session && status !== STATUS.INITIAL && (status !== STATUS.READY || ongoing)) {
|
|
91
|
-
// it's interrupted by a new question
|
|
92
|
-
const state = Object.freeze({ session, status, ongoing });
|
|
93
|
-
this._emit('interrupt', state);
|
|
94
|
-
this._emit('finally', state);
|
|
95
|
-
}
|
|
96
90
|
// restart
|
|
97
91
|
super.restart();
|
|
98
92
|
}
|
|
99
93
|
|
|
94
|
+
_emitInterruptEventIfNecessary() {
|
|
95
|
+
const state = this._hub.states[fields.view(this._roles.main)] || {};
|
|
96
|
+
if (state.session && state.status !== STATUS.INITIAL && (state.status !== STATUS.READY || state.ongoing)) {
|
|
97
|
+
// it's interrupted by a new question
|
|
98
|
+
this._emitLifecycleEvent('interrupt', state);
|
|
99
|
+
this._emitLifecycleEvent('finally', state);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
_onMainViewUpdate(state) {
|
|
104
|
+
const { status } = state;
|
|
105
|
+
const done = status === STATUS.READY && !state.ongoing;
|
|
106
|
+
const erroneous = status === STATUS.ERRONEOUS;
|
|
107
|
+
const eventName = done ? 'done' : erroneous ? 'error' : status;
|
|
108
|
+
this._emitLifecycleEvent(eventName, state);
|
|
109
|
+
if (done || erroneous) {
|
|
110
|
+
this._emitLifecycleEvent('finally', state);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
100
114
|
// properties //
|
|
101
115
|
get questionId() {
|
|
102
116
|
return this._questionId;
|
|
@@ -131,44 +145,29 @@ export default class AnswerBasedWorkflow extends Workflow {
|
|
|
131
145
|
}
|
|
132
146
|
|
|
133
147
|
_query(args = {}) {
|
|
148
|
+
if (this._linkFn) {
|
|
149
|
+
this._submitToPage(args);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
134
152
|
// start a new session
|
|
135
153
|
this.restart();
|
|
136
154
|
|
|
137
|
-
// TODO: move to ask workflow
|
|
138
155
|
// keep track of question source on this session, for suggested questions interactions
|
|
139
156
|
this._writeQuestionSourceToSession(args);
|
|
140
157
|
|
|
141
158
|
// build payload and trigger request
|
|
142
|
-
const { session } = this;
|
|
143
159
|
const payload = this._buildPayload(args);
|
|
144
|
-
|
|
145
|
-
this._request(event);
|
|
160
|
+
this._request({ payload });
|
|
146
161
|
}
|
|
147
162
|
|
|
148
163
|
_writeQuestionSourceToSession(args) {
|
|
149
|
-
this.session.meta.question_source = args.
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
_request(event) {
|
|
153
|
-
this._hub.update(fields.request(), event);
|
|
164
|
+
this.session.meta.question_source = args.qs || ORGANIC_QUESTION_SOURCE; // might be null, not undefined
|
|
154
165
|
}
|
|
155
166
|
|
|
156
167
|
_buildPayload() {
|
|
157
168
|
throw new Error(`Not implemented`);
|
|
158
169
|
}
|
|
159
170
|
|
|
160
|
-
// autocomplete //
|
|
161
|
-
/*
|
|
162
|
-
updateCompletions(event) {
|
|
163
|
-
// TODO: verify
|
|
164
|
-
this._hub.update(fields.data(DATA_ASPECT.AUTOCOMPLETE), {
|
|
165
|
-
...event,
|
|
166
|
-
source: 'manual',
|
|
167
|
-
});
|
|
168
|
-
return this;
|
|
169
|
-
}
|
|
170
|
-
*/
|
|
171
|
-
|
|
172
171
|
// data //
|
|
173
172
|
_updateData(data) {
|
|
174
173
|
// if it's the head response, write question id and return
|
|
@@ -219,43 +218,32 @@ export default class AnswerBasedWorkflow extends Workflow {
|
|
|
219
218
|
}
|
|
220
219
|
|
|
221
220
|
// interactions //
|
|
222
|
-
|
|
223
|
-
payload = super.
|
|
224
|
-
payload = this.
|
|
221
|
+
_defaultProcessInteraction(payload, args) {
|
|
222
|
+
payload = super._defaultProcessInteraction(payload, args);
|
|
223
|
+
payload = this._writeAskPropertiesToInteraction(payload, args);
|
|
225
224
|
return payload;
|
|
226
225
|
}
|
|
227
226
|
|
|
228
|
-
|
|
229
|
-
const
|
|
230
|
-
const
|
|
231
|
-
|
|
232
|
-
return {
|
|
233
|
-
...payload,
|
|
227
|
+
_writeAskPropertiesToInteraction(payload = {}, args) {
|
|
228
|
+
const question_source = this._getQuestionSourceFromViewState(args);
|
|
229
|
+
const question_id = this.questionId;
|
|
230
|
+
return mergeInteraction(payload, {
|
|
234
231
|
context: {
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
question_id
|
|
238
|
-
|
|
239
|
-
}),
|
|
232
|
+
custom_context: {
|
|
233
|
+
question_source,
|
|
234
|
+
question_id,
|
|
235
|
+
},
|
|
240
236
|
},
|
|
241
|
-
};
|
|
237
|
+
});
|
|
242
238
|
}
|
|
243
239
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
}
|
|
249
|
-
const done = status === STATUS.READY && !ongoing;
|
|
250
|
-
const erroneous = status === STATUS.ERRONEOUS;
|
|
251
|
-
const eventName = done ? 'done' : erroneous ? 'error' : status;
|
|
252
|
-
const state = Object.freeze({ session, status, ongoing });
|
|
253
|
-
this._emit(eventName, state);
|
|
254
|
-
if (done || erroneous) {
|
|
255
|
-
this._emit('finally', state);
|
|
256
|
-
}
|
|
240
|
+
_getQuestionSourceFromViewState(args) {
|
|
241
|
+
const { request } = this._hub.states[fields.view(args.role)] || {};
|
|
242
|
+
const { payload } = request || {};
|
|
243
|
+
return (payload && payload._meta && payload._meta.question_source) || undefined;
|
|
257
244
|
}
|
|
258
245
|
|
|
246
|
+
// handlers //
|
|
259
247
|
_onCitationClick({ index }) {
|
|
260
248
|
const { value } = this.states[fields.data()] || {};
|
|
261
249
|
const { sources } = value || {};
|
|
@@ -289,7 +277,7 @@ export default class AnswerBasedWorkflow extends Workflow {
|
|
|
289
277
|
|
|
290
278
|
}
|
|
291
279
|
|
|
292
|
-
|
|
280
|
+
enableUseLink(AnswerBasedWorkflow.prototype);
|
|
293
281
|
|
|
294
282
|
Object.assign(AnswerBasedWorkflow, {
|
|
295
283
|
DEFAULT_API_OPTIONS,
|
|
@@ -297,4 +285,5 @@ Object.assign(AnswerBasedWorkflow, {
|
|
|
297
285
|
DEFAULT_LAYOUTS,
|
|
298
286
|
DEFAULT_TRACKERS,
|
|
299
287
|
DEFAULT_OPTIONS,
|
|
288
|
+
ROLES_OPTIONS,
|
|
300
289
|
});
|
package/src/workflow/ask.js
CHANGED
|
@@ -3,6 +3,7 @@ import AnswerBasedWorkflow from './answer-based.js';
|
|
|
3
3
|
import { fields } from '../actor/index.js';
|
|
4
4
|
import { ROLE, ORGANIC_QUESTION_SOURCE } from '../constants.js';
|
|
5
5
|
import { OptionListLayout, ListLayout, SearchBoxLayout } from '../layout/index.js';
|
|
6
|
+
import { mergeInteraction } from './processors.js';
|
|
6
7
|
|
|
7
8
|
const DEFAULT_API_OPTIONS = Object.freeze({
|
|
8
9
|
...AnswerBasedWorkflow.DEFAULT_API_OPTIONS,
|
|
@@ -37,13 +38,15 @@ const DEFAULT_OPTIONS = Object.freeze({
|
|
|
37
38
|
trackers: DEFAULT_TRACKERS,
|
|
38
39
|
});
|
|
39
40
|
|
|
41
|
+
const ROLES_OPTIONS = AnswerBasedWorkflow.ROLES_OPTIONS;
|
|
42
|
+
|
|
40
43
|
export default class Ask extends AnswerBasedWorkflow {
|
|
41
44
|
|
|
42
45
|
constructor(context, parentQuestionId) {
|
|
43
46
|
super({
|
|
44
47
|
name: 'ask',
|
|
45
48
|
context,
|
|
46
|
-
roles:
|
|
49
|
+
roles: ROLES_OPTIONS,
|
|
47
50
|
defaults: DEFAULT_OPTIONS,
|
|
48
51
|
parentQuestionId,
|
|
49
52
|
});
|
|
@@ -71,11 +74,11 @@ export default class Ask extends AnswerBasedWorkflow {
|
|
|
71
74
|
this._hub.update(fields.suggestions(), { value: value.map(text => ({ text })) });
|
|
72
75
|
}
|
|
73
76
|
|
|
74
|
-
|
|
77
|
+
_initSession(args) {
|
|
75
78
|
// register at context
|
|
76
79
|
args.parentQuestionId && this._context._byPqid.set(args.parentQuestionId, this);
|
|
77
80
|
this._context._events.emit('create', this);
|
|
78
|
-
super.
|
|
81
|
+
super._initSession(args);
|
|
79
82
|
}
|
|
80
83
|
|
|
81
84
|
// lifecycle //
|
|
@@ -121,30 +124,33 @@ export default class Ask extends AnswerBasedWorkflow {
|
|
|
121
124
|
}
|
|
122
125
|
|
|
123
126
|
// interactions //
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
127
|
+
_writeAskPropertiesToInteraction(payload, args) {
|
|
128
|
+
const root_question_id = this.rootQuestionId;
|
|
129
|
+
let { property } = (payload.context && payload.context.custom_context) || {};
|
|
130
|
+
let question_id, parent_question_id, question_source;
|
|
131
|
+
|
|
132
|
+
if (args.role === ROLE.QUERY_SUGGESTIONS) {
|
|
133
|
+
property = 'suggested_followup_questions';
|
|
134
|
+
parent_question_id = this.previous && this.previous.parentQuestionId;
|
|
135
|
+
question_id = this.parentQuestionId;
|
|
136
|
+
question_source = this.previous && this.previous.session.meta.question_source;
|
|
137
|
+
} else {
|
|
138
|
+
parent_question_id = this.parentQuestionId;
|
|
139
|
+
question_id = this.questionId;
|
|
140
|
+
question_source = this._getQuestionSourceFromViewState(args);
|
|
136
141
|
}
|
|
137
|
-
custom_context.question_id = questionId;
|
|
138
|
-
custom_context.root_question_id = rootQuestionId;
|
|
139
|
-
custom_context.parent_question_id = parentQuestionId;
|
|
140
142
|
|
|
141
|
-
return {
|
|
142
|
-
...payload,
|
|
143
|
+
return mergeInteraction(payload, {
|
|
143
144
|
context: {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
145
|
+
custom_context: {
|
|
146
|
+
property,
|
|
147
|
+
root_question_id,
|
|
148
|
+
parent_question_id,
|
|
149
|
+
question_id,
|
|
150
|
+
question_source,
|
|
151
|
+
},
|
|
152
|
+
}
|
|
153
|
+
});
|
|
148
154
|
}
|
|
149
155
|
|
|
150
156
|
// helpers //
|
package/src/workflow/asks.js
CHANGED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { mixin } from '@miso.ai/commons';
|
|
2
|
+
import { fields } from '../actor/index.js';
|
|
3
|
+
import Autocomplete from './autocomplete.js';
|
|
4
|
+
|
|
5
|
+
export function makeAutocompletable(prototype) {
|
|
6
|
+
mixin(prototype, AutocompletableMixin.prototype);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export class AutocompletableMixin {
|
|
10
|
+
|
|
11
|
+
_initAutocomplete(args) {
|
|
12
|
+
this._autocomplete = new Autocomplete(this, { defaults: args.defaults.autocomplete });
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
get autocomplete() {
|
|
16
|
+
return this._autocomplete;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
updateCompletions(data) {
|
|
20
|
+
this._hub.update(fields.completions(), data);
|
|
21
|
+
return this;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
_destroyAutocomplete() {
|
|
25
|
+
this._autocomplete && this._autocomplete._destroy();
|
|
26
|
+
this._autocomplete = undefined;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { STATUS } from '../constants.js';
|
|
2
|
+
import { fields } from '../actor/index.js';
|
|
3
|
+
import Workflow from './base.js';
|
|
4
|
+
|
|
5
|
+
const ROLES_OPTIONS = Object.freeze({
|
|
6
|
+
members: [],
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
function shimDefaults({ layouts, trackers, ...options } = {}) {
|
|
10
|
+
return {
|
|
11
|
+
active: false,
|
|
12
|
+
...options,
|
|
13
|
+
layouts: {},
|
|
14
|
+
trackers: {},
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function sameInputValue(a, b) {
|
|
19
|
+
return getInputValue(a) === getInputValue(b);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function getInputValue(args) {
|
|
23
|
+
return (args && args.value && args.value.trim()) || undefined;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default class Autocomplete extends Workflow {
|
|
27
|
+
|
|
28
|
+
constructor(superworkflow, { defaults, ...args } = {}) {
|
|
29
|
+
super({
|
|
30
|
+
name: 'autocomplete',
|
|
31
|
+
plugin: superworkflow._plugin,
|
|
32
|
+
client: superworkflow._client,
|
|
33
|
+
defaults: shimDefaults(defaults),
|
|
34
|
+
roles: ROLES_OPTIONS,
|
|
35
|
+
superworkflow,
|
|
36
|
+
...args,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
_initProperties(args) {
|
|
41
|
+
super._initProperties(args);
|
|
42
|
+
this._superworkflow = args.superworkflow;
|
|
43
|
+
this._active = args.defaults.active;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
_initSubscriptions(args) {
|
|
47
|
+
// TODO: how to sync options updates
|
|
48
|
+
super._initSubscriptions(args);
|
|
49
|
+
this._unsubscribes = [
|
|
50
|
+
...this._unsubscribes,
|
|
51
|
+
args.superworkflow._hub.on(fields.input(), args => this._query(args)),
|
|
52
|
+
];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// API //
|
|
56
|
+
get enabled() {
|
|
57
|
+
return this._active;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
enable() {
|
|
61
|
+
this._active = true;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
disable() {
|
|
65
|
+
this._active = false;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// query //
|
|
69
|
+
_query(args) {
|
|
70
|
+
if (!this._active || sameInputValue(args, this._args)) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
this._args = args;
|
|
74
|
+
|
|
75
|
+
// start a new session
|
|
76
|
+
this.restart();
|
|
77
|
+
const { session } = this;
|
|
78
|
+
session.meta.input = args;
|
|
79
|
+
|
|
80
|
+
// if input value is blank, emit empty response
|
|
81
|
+
if (!getInputValue(args)) {
|
|
82
|
+
this._updateCompletions({ session, status: STATUS.INITIAL });
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// payload
|
|
87
|
+
const payload = this._buildPayload(args);
|
|
88
|
+
|
|
89
|
+
// request
|
|
90
|
+
this._request({ payload });
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
_buildPayload(args) {
|
|
94
|
+
return { q: getInputValue(args) };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// data //
|
|
98
|
+
_updateDataInHub(data) {
|
|
99
|
+
if (data.value) {
|
|
100
|
+
data = {
|
|
101
|
+
...data,
|
|
102
|
+
value: data.value.completions,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
// update completion field in superworkflow hub
|
|
106
|
+
this._updateCompletions(data);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
_updateCompletions(data) {
|
|
110
|
+
this._superworkflow.updateCompletions(data);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
}
|