@miso.ai/client-sdk-ui 1.11.0-beta.0 → 1.11.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/data.js +6 -7
- package/dist/cjs/actor/feedback.js +6 -39
- package/dist/cjs/actor/fields.js +14 -6
- package/dist/cjs/actor/hub.js +1 -2
- package/dist/cjs/actor/index.js +0 -7
- package/dist/cjs/actor/interactions.js +4 -15
- package/dist/cjs/actor/sessions.js +2 -33
- 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 +32 -8
- package/dist/cjs/asset/svgs.js +18 -8
- package/dist/cjs/constants.js +18 -19
- package/dist/cjs/defaults/hybrid-search/answer-box.js +19 -3
- package/dist/cjs/defaults/hybrid-search/phrases.js +5 -5
- package/dist/cjs/defaults/hybrid-search/templates.js +37 -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 +5 -5
- package/dist/cjs/layout/input/option-list.js +0 -4
- package/dist/cjs/layout/input/search-box.js +33 -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 +25 -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 +3 -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 +109 -111
- package/dist/cjs/workflow/ask.js +35 -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 +169 -102
- package/dist/cjs/workflow/explore.js +26 -19
- package/dist/cjs/workflow/hybrid-search-answer.js +99 -0
- package/dist/cjs/workflow/hybrid-search-results.js +70 -0
- package/dist/cjs/workflow/hybrid-search-views.js +122 -0
- package/dist/cjs/workflow/hybrid-search.js +98 -103
- package/dist/cjs/workflow/options.js +32 -17
- package/dist/cjs/workflow/processors.js +185 -17
- package/dist/cjs/workflow/recommendation.js +36 -49
- package/dist/cjs/workflow/search-based.js +186 -0
- package/dist/cjs/workflow/search.js +21 -68
- package/package.json +2 -2
- package/src/actor/data.js +2 -4
- package/src/actor/feedback.js +6 -23
- package/src/actor/fields.js +14 -6
- package/src/actor/hub.js +1 -2
- package/src/actor/index.js +0 -1
- package/src/actor/interactions.js +4 -10
- package/src/actor/sessions.js +3 -30
- 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 +36 -8
- package/src/asset/svgs.js +19 -7
- package/src/constants.js +25 -16
- package/src/defaults/hybrid-search/answer-box.js +17 -5
- package/src/defaults/hybrid-search/phrases.js +4 -4
- package/src/defaults/hybrid-search/templates.js +25 -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 +5 -6
- package/src/layout/input/option-list.js +0 -5
- package/src/layout/input/search-box.js +27 -14
- package/src/layout/list/cards.js +0 -4
- package/src/layout/list/carousel.js +0 -4
- package/src/layout/list/collection.js +22 -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 +4 -5
- package/src/layout/trackable.js +1 -1
- 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 +101 -77
- package/src/workflow/ask.js +33 -25
- 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 +147 -93
- package/src/workflow/explore.js +23 -8
- package/src/workflow/hybrid-search-answer.js +92 -0
- package/src/workflow/hybrid-search-results.js +63 -0
- package/src/workflow/hybrid-search-views.js +124 -0
- package/src/workflow/hybrid-search.js +102 -73
- package/src/workflow/options.js +26 -11
- package/src/workflow/processors.js +165 -14
- package/src/workflow/recommendation.js +32 -33
- package/src/workflow/search-based.js +183 -0
- package/src/workflow/search.js +21 -65
- 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/ask.js
CHANGED
|
@@ -2,7 +2,8 @@ import { defineValues, trimObj, API } from '@miso.ai/commons';
|
|
|
2
2
|
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
|
-
import { OptionListLayout, ListLayout,
|
|
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,
|
|
@@ -15,6 +16,7 @@ const DEFAULT_API_OPTIONS = Object.freeze({
|
|
|
15
16
|
|
|
16
17
|
const DEFAULT_LAYOUTS = Object.freeze({
|
|
17
18
|
...AnswerBasedWorkflow.DEFAULT_LAYOUTS,
|
|
19
|
+
[ROLE.QUERY]: [SearchBoxLayout.type, { templates: { buttonIcon: 'send' } }],
|
|
18
20
|
[ROLE.RELATED_RESOURCES]: [ListLayout.type, { incremental: true, itemType: 'article' }],
|
|
19
21
|
[ROLE.QUERY_SUGGESTIONS]: OptionListLayout.type,
|
|
20
22
|
});
|
|
@@ -36,13 +38,15 @@ const DEFAULT_OPTIONS = Object.freeze({
|
|
|
36
38
|
trackers: DEFAULT_TRACKERS,
|
|
37
39
|
});
|
|
38
40
|
|
|
41
|
+
const ROLES_OPTIONS = AnswerBasedWorkflow.ROLES_OPTIONS;
|
|
42
|
+
|
|
39
43
|
export default class Ask extends AnswerBasedWorkflow {
|
|
40
44
|
|
|
41
45
|
constructor(context, parentQuestionId) {
|
|
42
46
|
super({
|
|
43
47
|
name: 'ask',
|
|
44
48
|
context,
|
|
45
|
-
roles:
|
|
49
|
+
roles: ROLES_OPTIONS,
|
|
46
50
|
defaults: DEFAULT_OPTIONS,
|
|
47
51
|
parentQuestionId,
|
|
48
52
|
});
|
|
@@ -64,16 +68,17 @@ export default class Ask extends AnswerBasedWorkflow {
|
|
|
64
68
|
if (!previous) {
|
|
65
69
|
return;
|
|
66
70
|
}
|
|
71
|
+
// TODO: write question_source from payload._meta, so we don't need to write it to session.meta
|
|
67
72
|
const values = previous.states[fields.data()].value;
|
|
68
73
|
const value = values.suggested_followup_questions || values.followup_questions || [];
|
|
69
74
|
this._hub.update(fields.suggestions(), { value: value.map(text => ({ text })) });
|
|
70
75
|
}
|
|
71
76
|
|
|
72
|
-
|
|
77
|
+
_initSession(args) {
|
|
73
78
|
// register at context
|
|
74
79
|
args.parentQuestionId && this._context._byPqid.set(args.parentQuestionId, this);
|
|
75
80
|
this._context._events.emit('create', this);
|
|
76
|
-
super.
|
|
81
|
+
super._initSession(args);
|
|
77
82
|
}
|
|
78
83
|
|
|
79
84
|
// lifecycle //
|
|
@@ -119,30 +124,33 @@ export default class Ask extends AnswerBasedWorkflow {
|
|
|
119
124
|
}
|
|
120
125
|
|
|
121
126
|
// interactions //
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
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);
|
|
134
141
|
}
|
|
135
|
-
custom_context.question_id = questionId;
|
|
136
|
-
custom_context.root_question_id = rootQuestionId;
|
|
137
|
-
custom_context.parent_question_id = parentQuestionId;
|
|
138
142
|
|
|
139
|
-
return {
|
|
140
|
-
...payload,
|
|
143
|
+
return mergeInteraction(payload, {
|
|
141
144
|
context: {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
145
|
+
custom_context: {
|
|
146
|
+
property,
|
|
147
|
+
root_question_id,
|
|
148
|
+
parent_question_id,
|
|
149
|
+
question_id,
|
|
150
|
+
question_source,
|
|
151
|
+
},
|
|
152
|
+
}
|
|
153
|
+
});
|
|
146
154
|
}
|
|
147
155
|
|
|
148
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
|
+
}
|
package/src/workflow/base.js
CHANGED
|
@@ -3,42 +3,52 @@ 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
|
|
|
38
48
|
constructor(args) {
|
|
39
49
|
super(args.name || 'workflow', args.plugin);
|
|
40
50
|
|
|
41
|
-
let { context, plugin, client } = args;
|
|
51
|
+
let { context, plugin, client, options } = args;
|
|
42
52
|
this._context = context;
|
|
43
53
|
this._plugin = plugin = plugin || context._plugin;
|
|
44
54
|
this._client = client = client || context._client;
|
|
@@ -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() {
|
|
@@ -90,12 +102,7 @@ export default class Workflow extends Component {
|
|
|
90
102
|
}
|
|
91
103
|
|
|
92
104
|
get session() {
|
|
93
|
-
return this._hub.states.session;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
get active() {
|
|
97
|
-
const { session } = this;
|
|
98
|
-
return !!session && session.active;
|
|
105
|
+
return this._hub.states[fields.session()];
|
|
99
106
|
}
|
|
100
107
|
|
|
101
108
|
get states() {
|
|
@@ -112,23 +119,52 @@ 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);
|
|
157
|
+
}
|
|
158
|
+
|
|
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);
|
|
128
164
|
}
|
|
129
165
|
|
|
130
|
-
//
|
|
131
|
-
updateData(data
|
|
166
|
+
// data //
|
|
167
|
+
updateData(data) {
|
|
132
168
|
if (!data) {
|
|
133
169
|
throw new Error(`Data is required.`);
|
|
134
170
|
}
|
|
@@ -152,43 +188,33 @@ export default class Workflow extends Component {
|
|
|
152
188
|
}
|
|
153
189
|
}
|
|
154
190
|
|
|
155
|
-
this.
|
|
191
|
+
this._updateData(data);
|
|
156
192
|
|
|
157
|
-
|
|
193
|
+
return this;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
_updateData(data) {
|
|
158
197
|
data = this._defaultProcessData(data);
|
|
159
198
|
for (const process of this._options.resolved.dataProcessor) {
|
|
160
199
|
data = process(data);
|
|
161
200
|
}
|
|
162
201
|
|
|
163
|
-
|
|
164
|
-
data = addDataInstructions(data, instructions);
|
|
165
|
-
data = this._mergeDataIfNecessary(data);
|
|
166
|
-
|
|
167
|
-
this._hub.update(fields.data(), data);
|
|
168
|
-
|
|
169
|
-
return this;
|
|
202
|
+
this._updateDataInHub(data);
|
|
170
203
|
}
|
|
171
204
|
|
|
172
205
|
_defaultProcessData(data) {
|
|
173
|
-
|
|
206
|
+
data = writeDataStatus(data);
|
|
207
|
+
data = writeMisoIdToMeta(data);
|
|
208
|
+
return data;
|
|
174
209
|
}
|
|
175
210
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
return data;
|
|
179
|
-
}
|
|
180
|
-
return {
|
|
181
|
-
...this._hub.states[fields.data()],
|
|
182
|
-
...data,
|
|
183
|
-
};
|
|
211
|
+
_updateDataInHub(data) {
|
|
212
|
+
this._hub.update(fields.data(), data);
|
|
184
213
|
}
|
|
185
214
|
|
|
186
|
-
_handleResponseObject() {}
|
|
187
|
-
|
|
188
215
|
// TODO: notifyViewUpdateAll()
|
|
189
216
|
|
|
190
217
|
notifyViewUpdate(role, state) {
|
|
191
|
-
this._assertActive();
|
|
192
218
|
state = {
|
|
193
219
|
status: STATUS.READY,
|
|
194
220
|
session: this.session,
|
|
@@ -203,28 +229,54 @@ export default class Workflow extends Component {
|
|
|
203
229
|
return this._views.trackers;
|
|
204
230
|
}
|
|
205
231
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
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, {
|
|
219
257
|
context: {
|
|
220
|
-
...context,
|
|
221
258
|
custom_context: {
|
|
222
|
-
api_group,
|
|
223
|
-
api_name,
|
|
224
|
-
...custom_context,
|
|
259
|
+
api_group: group,
|
|
260
|
+
api_name: name,
|
|
225
261
|
},
|
|
226
262
|
},
|
|
227
|
-
};
|
|
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
|
+
}
|
|
228
280
|
}
|
|
229
281
|
|
|
230
282
|
// destroy //
|
|
@@ -255,12 +307,14 @@ export default class Workflow extends Component {
|
|
|
255
307
|
}
|
|
256
308
|
}
|
|
257
309
|
|
|
258
|
-
_assertActive() {
|
|
259
|
-
if (!this.active) {
|
|
260
|
-
throw new Error(`Unit is not active yet. Call unit.start() to activate it.`)
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
310
|
}
|
|
265
311
|
|
|
266
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
|
+
});
|