@miso.ai/client-sdk-ui 1.11.0-beta.1 → 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 +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 +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 +1 -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
|
@@ -5,14 +5,9 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
var _commons = require("@miso.ai/commons");
|
|
8
|
-
var _base = _interopRequireDefault(require("./base.js"));
|
|
9
|
-
var _options = require("./options.js");
|
|
10
|
-
var sources = _interopRequireWildcard(require("../source.js"));
|
|
11
|
-
var _index = require("../actor/index.js");
|
|
12
8
|
var _constants = require("../constants.js");
|
|
13
|
-
var
|
|
14
|
-
|
|
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; }
|
|
9
|
+
var _searchBased = _interopRequireDefault(require("./search-based.js"));
|
|
10
|
+
var _autocompletable = require("./autocompletable.js");
|
|
16
11
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
17
12
|
const DEFAULT_API_OPTIONS = Object.freeze({
|
|
18
13
|
group: _commons.API.GROUP.SEARCH,
|
|
@@ -22,7 +17,6 @@ const DEFAULT_API_OPTIONS = Object.freeze({
|
|
|
22
17
|
}
|
|
23
18
|
});
|
|
24
19
|
const DEFAULT_AUTOCOMPLETE_OPTIONS = Object.freeze({
|
|
25
|
-
actor: false,
|
|
26
20
|
api: {
|
|
27
21
|
group: _commons.API.GROUP.SEARCH,
|
|
28
22
|
name: _commons.API.NAME.AUTOCOMPLETE,
|
|
@@ -30,45 +24,31 @@ const DEFAULT_AUTOCOMPLETE_OPTIONS = Object.freeze({
|
|
|
30
24
|
completion_fields: ['suggested_queries', 'title'],
|
|
31
25
|
fl: ['title', 'url', 'cover_image']
|
|
32
26
|
}
|
|
33
|
-
}
|
|
34
|
-
throttle: 300
|
|
35
|
-
});
|
|
36
|
-
const DEFAULT_LAYOUTS = Object.freeze({
|
|
37
|
-
[_constants.ROLE.QUERY]: _index2.SearchBoxLayout.type,
|
|
38
|
-
[_constants.ROLE.PRODUCTS]: _index2.ListLayout.type
|
|
39
|
-
});
|
|
40
|
-
const DEFAULT_TRACKERS = Object.freeze({
|
|
41
|
-
[_constants.ROLE.PRODUCTS]: {}
|
|
27
|
+
}
|
|
42
28
|
});
|
|
43
|
-
const
|
|
29
|
+
const DEFAULT_LAYOUTS = Object.freeze(Object.assign({}, _searchBased.default.DEFAULT_LAYOUTS));
|
|
30
|
+
const DEFAULT_TRACKERS = Object.freeze(Object.assign({}, _searchBased.default.DEFAULT_TRACKERS));
|
|
31
|
+
const DEFAULT_OPTIONS = Object.freeze(Object.assign({}, _searchBased.default.DEFAULT_OPTIONS, {
|
|
44
32
|
api: DEFAULT_API_OPTIONS,
|
|
45
33
|
autocomplete: DEFAULT_AUTOCOMPLETE_OPTIONS,
|
|
46
34
|
layouts: DEFAULT_LAYOUTS,
|
|
47
35
|
trackers: DEFAULT_TRACKERS
|
|
48
|
-
});
|
|
49
|
-
|
|
36
|
+
}));
|
|
37
|
+
const ROLES_OPTIONS = _searchBased.default.ROLES_OPTIONS;
|
|
38
|
+
class Search extends _searchBased.default {
|
|
50
39
|
constructor(plugin, client) {
|
|
51
40
|
super({
|
|
52
41
|
name: 'search',
|
|
53
42
|
plugin,
|
|
54
43
|
client,
|
|
55
|
-
roles:
|
|
44
|
+
roles: ROLES_OPTIONS,
|
|
56
45
|
defaults: DEFAULT_OPTIONS
|
|
57
46
|
});
|
|
58
47
|
}
|
|
59
|
-
|
|
60
|
-
super.
|
|
61
|
-
this.
|
|
62
|
-
source: sources.api(this._client),
|
|
63
|
-
options: this._options
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
_initSubscriptions(args) {
|
|
67
|
-
super._initSubscriptions(args);
|
|
68
|
-
this._unsubscribes = [...this._unsubscribes, this._hub.on(_index.fields.query(), args => this._query(args))];
|
|
48
|
+
_initProperties(args) {
|
|
49
|
+
super._initProperties(args);
|
|
50
|
+
this._initAutocomplete(args);
|
|
69
51
|
}
|
|
70
|
-
|
|
71
|
-
// lifecycle //
|
|
72
52
|
autoQuery() {
|
|
73
53
|
let {
|
|
74
54
|
setValue = true,
|
|
@@ -92,40 +72,6 @@ class Search extends _base.default {
|
|
|
92
72
|
});
|
|
93
73
|
}
|
|
94
74
|
}
|
|
95
|
-
query(args) {
|
|
96
|
-
if (!args.q) {
|
|
97
|
-
throw new Error(`q is required in query() call`);
|
|
98
|
-
}
|
|
99
|
-
this._hub.update(_index.fields.query(), args);
|
|
100
|
-
}
|
|
101
|
-
_query(args) {
|
|
102
|
-
// start a new session
|
|
103
|
-
this.restart();
|
|
104
|
-
const {
|
|
105
|
-
session
|
|
106
|
-
} = this;
|
|
107
|
-
|
|
108
|
-
// build payload and trigger request
|
|
109
|
-
const payload = this._buildPayload(args);
|
|
110
|
-
const event = (0, _options.mergeApiOptions)(this._options.resolved.api, {
|
|
111
|
-
payload,
|
|
112
|
-
session
|
|
113
|
-
});
|
|
114
|
-
this._request(event);
|
|
115
|
-
}
|
|
116
|
-
_buildPayload(args) {
|
|
117
|
-
return args;
|
|
118
|
-
}
|
|
119
|
-
_request(event) {
|
|
120
|
-
this._hub.update(_index.fields.request(), event);
|
|
121
|
-
}
|
|
122
|
-
updateCompletions(event) {
|
|
123
|
-
// TODO: verify
|
|
124
|
-
this._hub.update(_index.fields.data(_constants.DATA_ASPECT.AUTOCOMPLETE), Object.assign({}, event, {
|
|
125
|
-
source: 'manual'
|
|
126
|
-
}));
|
|
127
|
-
return this;
|
|
128
|
-
}
|
|
129
75
|
notifyViewUpdate() {
|
|
130
76
|
let role = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _constants.ROLE.PRODUCTS;
|
|
131
77
|
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
@@ -134,6 +80,13 @@ class Search extends _base.default {
|
|
|
134
80
|
super.notifyViewUpdate(role, ...args);
|
|
135
81
|
return this;
|
|
136
82
|
}
|
|
83
|
+
|
|
84
|
+
// destroy //
|
|
85
|
+
_destroy(options) {
|
|
86
|
+
this._feedback._destroy();
|
|
87
|
+
this._destroyAutocomplete();
|
|
88
|
+
super._destroy(options);
|
|
89
|
+
}
|
|
137
90
|
}
|
|
138
91
|
exports.default = Search;
|
|
139
|
-
(0,
|
|
92
|
+
(0, _autocompletable.makeAutocompletable)(Search.prototype);
|
package/package.json
CHANGED
package/src/actor/data.js
CHANGED
|
@@ -50,10 +50,8 @@ export default class DataActor {
|
|
|
50
50
|
const { session } = this._hub.states;
|
|
51
51
|
const { session: _, ...request } = event;
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
this._emitResponse({ session, request });
|
|
56
|
-
}
|
|
53
|
+
// emit response to update request
|
|
54
|
+
this._emitResponse({ session, request });
|
|
57
55
|
|
|
58
56
|
try {
|
|
59
57
|
const { signal } = this._ac || {};
|
package/src/actor/feedback.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as fields from './fields.js';
|
|
2
|
+
import { EVENT_TYPE } from '../constants.js';
|
|
2
3
|
|
|
3
4
|
export default class FeedbackActor {
|
|
4
5
|
|
|
@@ -10,29 +11,11 @@ export default class FeedbackActor {
|
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
_trigger(state) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
// TODO: ad-hoc
|
|
19
|
-
const { request } = data || {};
|
|
20
|
-
const { payload } = request || {};
|
|
21
|
-
const question_source = payload && payload._meta && payload._meta.question_source;
|
|
22
|
-
this._hub.trigger(fields.interaction(), this._buildInteraction(state, { question_source }));
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
_buildInteraction({ value, unselected }, { question_source }) {
|
|
26
|
-
return {
|
|
27
|
-
type: 'feedback',
|
|
28
|
-
context: {
|
|
29
|
-
custom_context: {
|
|
30
|
-
result_type: 'answer',
|
|
31
|
-
question_source,
|
|
32
|
-
value: unselected ? 'unselected' : value,
|
|
33
|
-
},
|
|
34
|
-
},
|
|
35
|
-
};
|
|
14
|
+
this._hub.trigger(fields.tracker(), {
|
|
15
|
+
type: EVENT_TYPE.FEEDBACK,
|
|
16
|
+
result_type: 'answer',
|
|
17
|
+
value: state.unselected ? 'unselected' : state.value,
|
|
18
|
+
});
|
|
36
19
|
}
|
|
37
20
|
|
|
38
21
|
_destroy() {
|
package/src/actor/fields.js
CHANGED
|
@@ -6,6 +6,10 @@ export function suggestions() {
|
|
|
6
6
|
return 'suggestions';
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
+
export function completions() {
|
|
10
|
+
return 'completions';
|
|
11
|
+
}
|
|
12
|
+
|
|
9
13
|
export function filters() {
|
|
10
14
|
return 'filters';
|
|
11
15
|
}
|
|
@@ -14,16 +18,16 @@ export function query() {
|
|
|
14
18
|
return 'query';
|
|
15
19
|
}
|
|
16
20
|
|
|
17
|
-
export function request(
|
|
18
|
-
return
|
|
21
|
+
export function request() {
|
|
22
|
+
return 'request';
|
|
19
23
|
}
|
|
20
24
|
|
|
21
|
-
export function response(
|
|
22
|
-
return
|
|
25
|
+
export function response() {
|
|
26
|
+
return 'response';
|
|
23
27
|
}
|
|
24
28
|
|
|
25
|
-
export function data(
|
|
26
|
-
return
|
|
29
|
+
export function data() {
|
|
30
|
+
return 'data';
|
|
27
31
|
}
|
|
28
32
|
|
|
29
33
|
export function view(role) {
|
|
@@ -49,3 +53,7 @@ export function feedback() {
|
|
|
49
53
|
export function input() {
|
|
50
54
|
return 'input';
|
|
51
55
|
}
|
|
56
|
+
|
|
57
|
+
export function more() {
|
|
58
|
+
return 'more';
|
|
59
|
+
}
|
package/src/actor/hub.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { defineValues, EventEmitter } from '@miso.ai/commons';
|
|
2
|
-
import { removeDataInstructions } from '../workflow/processors.js';
|
|
3
2
|
|
|
4
3
|
export default class Hub {
|
|
5
4
|
|
|
@@ -14,7 +13,7 @@ export default class Hub {
|
|
|
14
13
|
}
|
|
15
14
|
|
|
16
15
|
update(name, state, { silent = false } = {}) {
|
|
17
|
-
this._states[name] = Object.freeze(
|
|
16
|
+
this._states[name] = Object.freeze(state);
|
|
18
17
|
if (!silent) {
|
|
19
18
|
this._events.emit(name, state);
|
|
20
19
|
}
|
package/src/actor/index.js
CHANGED
|
@@ -6,5 +6,4 @@ export { default as SessionMaker } from './sessions.js';
|
|
|
6
6
|
export { default as DataActor } from './data.js';
|
|
7
7
|
export { default as ViewsActor } from './views.js';
|
|
8
8
|
export { default as FeedbackActor } from './feedback.js';
|
|
9
|
-
export { default as AutocompleteActor } from './autocomplete.js';
|
|
10
9
|
export { default as InteractionsActor } from './interactions.js';
|
|
@@ -12,20 +12,14 @@ export default class InteractionsActor {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
_handle(payload) {
|
|
15
|
+
// TODO: omit when option == false
|
|
15
16
|
payload = asArray(payload);
|
|
16
|
-
|
|
17
|
-
for (const p of preprocess) {
|
|
18
|
-
payload = payload.map(p);
|
|
19
|
-
}
|
|
20
|
-
// TODO: support filter?
|
|
17
|
+
|
|
21
18
|
if (payload.length === 0) {
|
|
22
19
|
return;
|
|
23
20
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
} else {
|
|
27
|
-
this._client.api.interactions.upload(payload, { merge: true });
|
|
28
|
-
}
|
|
21
|
+
|
|
22
|
+
this._client.api.interactions.upload(payload, { merge: true });
|
|
29
23
|
}
|
|
30
24
|
|
|
31
25
|
destroy() {
|
package/src/actor/sessions.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { uuidv4
|
|
1
|
+
import { uuidv4 } from '@miso.ai/commons';
|
|
2
2
|
import * as fields from './fields.js';
|
|
3
3
|
|
|
4
4
|
export default class SessionMaker {
|
|
@@ -6,42 +6,15 @@ export default class SessionMaker {
|
|
|
6
6
|
constructor(hub) {
|
|
7
7
|
this._hub = hub;
|
|
8
8
|
this._sessionIndex = 0;
|
|
9
|
-
delegateGetters(hub, this, ['active']);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
get active() {
|
|
13
|
-
const { session } = this._hub.states;
|
|
14
|
-
return !!(session && session.active);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
new({ force = false } = {}) {
|
|
18
|
-
const currentSession = this._hub.states.session;
|
|
19
|
-
if (currentSession && !currentSession.active && !force) {
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
const session = this._create();
|
|
23
|
-
this._hub.update(fields.session(), session);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
start() {
|
|
27
|
-
const session = this._hub.states.session || this._create();
|
|
28
|
-
if (session.active) {
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
this._hub.update(fields.session(), { ...session, active: true });
|
|
32
9
|
}
|
|
33
10
|
|
|
34
11
|
restart() {
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
_create(active = false) {
|
|
39
|
-
return Object.freeze({
|
|
40
|
-
active,
|
|
12
|
+
const session = Object.freeze({
|
|
41
13
|
uuid: uuidv4(),
|
|
42
14
|
index: this._sessionIndex++,
|
|
43
15
|
meta: {},
|
|
44
16
|
});
|
|
17
|
+
this._hub.update(fields.session(), session);
|
|
45
18
|
}
|
|
46
19
|
|
|
47
20
|
}
|
package/src/actor/tracker.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { asArray } from '@miso.ai/commons';
|
|
2
|
-
import {
|
|
1
|
+
import { asArray, trimObj } from '@miso.ai/commons';
|
|
2
|
+
import { PERFORMANCE_EVENT_TYPES, TRACKING_STATUS, EVENT_TYPE, validateEventType } from '../constants.js';
|
|
3
3
|
import * as fields from './fields.js';
|
|
4
4
|
import States from '../util/states.js';
|
|
5
|
-
import { toInteraction } from './utils.js';
|
|
6
5
|
|
|
7
6
|
const VALUELESS_ITEMS = [Symbol('valueless')];
|
|
8
7
|
|
|
@@ -26,29 +25,36 @@ export default class Tracker {
|
|
|
26
25
|
return this._states.getFullState(item);
|
|
27
26
|
}
|
|
28
27
|
|
|
29
|
-
_trigger(type, items
|
|
28
|
+
_trigger(type, items) {
|
|
29
|
+
validateEventType(type);
|
|
30
30
|
if (this._valueless) {
|
|
31
|
-
meta = items;
|
|
32
31
|
items = VALUELESS_ITEMS;
|
|
33
32
|
}
|
|
34
|
-
|
|
33
|
+
|
|
35
34
|
this._syncSession();
|
|
36
35
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
this._states.set(items, type, TRACKING_STATUS.TRIGGERED);
|
|
36
|
+
items = this._states.untriggered(asArray(items), type);
|
|
37
|
+
if (items.length === 0) {
|
|
38
|
+
return;
|
|
43
39
|
}
|
|
40
|
+
this._states.set(items, type, TRACKING_STATUS.TRIGGERED);
|
|
44
41
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
42
|
+
this._sendToHub({
|
|
43
|
+
type,
|
|
44
|
+
items: this._valueless ? undefined : items,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
submit({ value }) {
|
|
49
|
+
this._syncSession();
|
|
50
|
+
this._sendToHub({
|
|
51
|
+
type: EVENT_TYPE.SUBMIT,
|
|
52
|
+
value,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
49
55
|
|
|
50
|
-
|
|
51
|
-
this._hub.trigger(fields.
|
|
56
|
+
_sendToHub(args) {
|
|
57
|
+
this._hub.trigger(fields.tracker(), Object.freeze(trimObj({ role: this._role, ...args })));
|
|
52
58
|
}
|
|
53
59
|
|
|
54
60
|
_syncSession() {
|
|
@@ -82,7 +88,7 @@ export default class Tracker {
|
|
|
82
88
|
|
|
83
89
|
}
|
|
84
90
|
|
|
85
|
-
for (const type of
|
|
91
|
+
for (const type of PERFORMANCE_EVENT_TYPES) {
|
|
86
92
|
Tracker.prototype[type] = function(items, meta) {
|
|
87
93
|
this._trigger(type, items, meta);
|
|
88
94
|
};
|
package/src/actor/utils.js
CHANGED
|
@@ -1,50 +1,3 @@
|
|
|
1
|
-
import { trimObj } from '@miso.ai/commons';
|
|
2
|
-
import { ROLE, EVENT_TYPE } from '../constants.js';
|
|
3
|
-
|
|
4
|
-
const PRODUCT_TYPED_PROPERTIES = new Set([
|
|
5
|
-
ROLE.PRODUCTS,
|
|
6
|
-
ROLE.SOURCES,
|
|
7
|
-
ROLE.RELATED_RESOURCES,
|
|
8
|
-
]);
|
|
9
|
-
|
|
10
|
-
// TODO: move away
|
|
11
|
-
export function isProduct(property) {
|
|
12
|
-
return PRODUCT_TYPED_PROPERTIES.has(property);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function toInteraction({ property, misoId, request }, { event, values, manual }) {
|
|
16
|
-
// TODO: ad-hoc
|
|
17
|
-
const question_source = request && request._meta && request._meta.question_source;
|
|
18
|
-
const isProductType = isProduct(property);
|
|
19
|
-
const isSubmit = event === EVENT_TYPE.SUBMIT;
|
|
20
|
-
const isAffiliation = property === ROLE.AFFILIATION;
|
|
21
|
-
|
|
22
|
-
const product_ids = isProductType && values ? values.map(v => typeof v === 'string' ? v : v.product_id).filter(v => v) : !isSubmit ? [] : undefined;
|
|
23
|
-
const items = !isProductType && !isSubmit && values ? values.map(v => v.text || v.id || v) : undefined;
|
|
24
|
-
const value = isSubmit ? values : undefined;
|
|
25
|
-
|
|
26
|
-
const channel = isAffiliation ? values[0] && values[0].channel : undefined;
|
|
27
|
-
const positions = isAffiliation ? values.map(v => v.position) : undefined;
|
|
28
|
-
|
|
29
|
-
const payload = trimObj({
|
|
30
|
-
type: event === 'viewable' ? 'viewable_impression' : event,
|
|
31
|
-
product_ids,
|
|
32
|
-
miso_id: misoId,
|
|
33
|
-
context: {
|
|
34
|
-
custom_context: trimObj({
|
|
35
|
-
property,
|
|
36
|
-
channel,
|
|
37
|
-
items,
|
|
38
|
-
value,
|
|
39
|
-
positions,
|
|
40
|
-
trigger: manual ? 'manual' : 'auto',
|
|
41
|
-
question_source,
|
|
42
|
-
}),
|
|
43
|
-
},
|
|
44
|
-
});
|
|
45
|
-
return payload;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
1
|
export function isCurrentSession(hub, session) {
|
|
49
2
|
if (!session) {
|
|
50
3
|
return false;
|
package/src/actor/view.js
CHANGED
|
@@ -22,7 +22,7 @@ export default class ViewActor {
|
|
|
22
22
|
constructor(views, role) {
|
|
23
23
|
this._events = new EventEmitter({ target: this });
|
|
24
24
|
this._views = views;
|
|
25
|
-
this.
|
|
25
|
+
this._mapping = asMappingFunction((views._roles.mappings || {})[role] || role);
|
|
26
26
|
|
|
27
27
|
defineValues(this, {
|
|
28
28
|
role,
|
|
@@ -101,6 +101,10 @@ export default class ViewActor {
|
|
|
101
101
|
}
|
|
102
102
|
return this._tracker;
|
|
103
103
|
}
|
|
104
|
+
|
|
105
|
+
get workflowOptions() {
|
|
106
|
+
return this._views._getWorkflowOptions();
|
|
107
|
+
}
|
|
104
108
|
|
|
105
109
|
get filters() {
|
|
106
110
|
return this._views.filters;
|
|
@@ -122,21 +126,17 @@ export default class ViewActor {
|
|
|
122
126
|
const previousData = this._data;
|
|
123
127
|
this._data = data = this._sliceData(data || this._views._getData());
|
|
124
128
|
|
|
125
|
-
// protocol: no reaction until session starts
|
|
126
|
-
const { session, status, ongoing, request, meta } = data;
|
|
127
|
-
const active = session && session.active;
|
|
128
|
-
if (!force && !active) {
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
129
|
// if data is unchanged, skip unless forced
|
|
133
130
|
if (!force && statesEqual(data, previousData)) {
|
|
134
131
|
return;
|
|
135
132
|
}
|
|
136
133
|
|
|
134
|
+
const { session, status, ongoing, request, meta, value } = data;
|
|
135
|
+
const baseState = { session, status, ongoing, request, meta, data: value, ...getDataEmptyness(data) };
|
|
136
|
+
|
|
137
137
|
// render
|
|
138
138
|
const notifyUpdate = (state = {}, options) => {
|
|
139
|
-
state !== false && this.updateState({
|
|
139
|
+
state !== false && this.updateState({ ...baseState, ...state }, options);
|
|
140
140
|
};
|
|
141
141
|
try {
|
|
142
142
|
await this._layout.render(element, data, { notifyUpdate });
|
|
@@ -146,11 +146,10 @@ export default class ViewActor {
|
|
|
146
146
|
}
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
-
updateState(
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
}
|
|
153
|
-
const state = this._state = Object.freeze(trimObj({ session, status, ongoing, request, meta, error }));
|
|
149
|
+
updateState(state, { silent = false } = {}) {
|
|
150
|
+
// there might be error from notifyUpdate() call
|
|
151
|
+
const status = state.error ? STATUS.ERRONEOUS : state.status;
|
|
152
|
+
state = this._state = Object.freeze(trimObj({ ...state, status }));
|
|
154
153
|
const { role } = this;
|
|
155
154
|
this.hub.update(fields.view(role), state, { silent });
|
|
156
155
|
}
|
|
@@ -163,7 +162,7 @@ export default class ViewActor {
|
|
|
163
162
|
_sliceData(data) {
|
|
164
163
|
const { value, error, status, meta, ...rest } = data;
|
|
165
164
|
const sliced = {
|
|
166
|
-
value:
|
|
165
|
+
value: this._mapping(data),
|
|
167
166
|
status,
|
|
168
167
|
data: value,
|
|
169
168
|
meta,
|
|
@@ -247,3 +246,16 @@ function asMappingFunction(fn) {
|
|
|
247
246
|
throw new Error(`Invalid mapping function: ${fn}`);
|
|
248
247
|
}
|
|
249
248
|
}
|
|
249
|
+
|
|
250
|
+
function getDataEmptyness(data) {
|
|
251
|
+
return isDataStatusRelevantToEmptyness(data) ? { empty: !!isDateValueEmpty(data) } : {};
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function isDataStatusRelevantToEmptyness(data) {
|
|
255
|
+
return data.status === STATUS.READY && !data.ongoing;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
function isDateValueEmpty(data) {
|
|
259
|
+
const { value } = data;
|
|
260
|
+
return value === undefined || ((Array.isArray(value) || typeof value === 'string') && !value.length);
|
|
261
|
+
}
|
package/src/actor/views.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineValues, delegateGetters } from '@miso.ai/commons';
|
|
1
|
+
import { defineValues, delegateGetters, trimObj } from '@miso.ai/commons';
|
|
2
2
|
import { ROLE } from '../constants.js';
|
|
3
3
|
import * as fields from './fields.js';
|
|
4
4
|
import ViewActor from './view.js';
|
|
@@ -12,8 +12,7 @@ export default class ViewsActor {
|
|
|
12
12
|
workflow,
|
|
13
13
|
extensions,
|
|
14
14
|
layouts,
|
|
15
|
-
roles
|
|
16
|
-
rolesConfig = {},
|
|
15
|
+
roles,
|
|
17
16
|
options,
|
|
18
17
|
}) {
|
|
19
18
|
this._hub = hub;
|
|
@@ -21,14 +20,17 @@ export default class ViewsActor {
|
|
|
21
20
|
this._extensions = extensions;
|
|
22
21
|
this._layoutFactory = layouts;
|
|
23
22
|
this._options = options;
|
|
24
|
-
this.
|
|
23
|
+
this._roles = roles;
|
|
25
24
|
this._containers = new Map();
|
|
26
25
|
this._containerTracker = undefined;
|
|
27
26
|
this._views = {};
|
|
28
|
-
this._trackers = new Trackers(this, roles);
|
|
27
|
+
this._trackers = new Trackers(this, roles.members);
|
|
29
28
|
this._filters = new Filters(this);
|
|
30
29
|
|
|
31
|
-
for (const role of roles) {
|
|
30
|
+
for (const role of roles.members) {
|
|
31
|
+
if (role === ROLE.CONTAINER) {
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
32
34
|
this._views[role] = new ViewActor(this, role);
|
|
33
35
|
}
|
|
34
36
|
|
|
@@ -42,10 +44,14 @@ export default class ViewsActor {
|
|
|
42
44
|
this._unsubscribes = [
|
|
43
45
|
() => window.removeEventListener('resize', syncSize),
|
|
44
46
|
hub.on(fields.data(), data => this.refresh({ data })),
|
|
47
|
+
options.on('autocomplete', () => this._syncAutocompleteOptions()),
|
|
48
|
+
options.on('pagination', () => this._syncPaginationOptions()),
|
|
45
49
|
options.on('trackers', () => this._syncTrackers()),
|
|
46
50
|
options.on('layouts', () => this._syncLayouts()),
|
|
47
51
|
];
|
|
48
52
|
|
|
53
|
+
this._syncAutocompleteOptions();
|
|
54
|
+
this._syncPaginationOptions();
|
|
49
55
|
this._syncTrackers();
|
|
50
56
|
this._syncLayouts();
|
|
51
57
|
}
|
|
@@ -99,6 +105,10 @@ export default class ViewsActor {
|
|
|
99
105
|
// TODO
|
|
100
106
|
}
|
|
101
107
|
|
|
108
|
+
containsElement(element) {
|
|
109
|
+
return this._containers.has(element) || this._views[element.role];
|
|
110
|
+
}
|
|
111
|
+
|
|
102
112
|
refreshElement(element) {
|
|
103
113
|
const view = element.isContainer ? this._containers.get(element) : this._getViewByElement(element);
|
|
104
114
|
view && view.refresh({ force: true });
|
|
@@ -140,7 +150,7 @@ export default class ViewsActor {
|
|
|
140
150
|
} else {
|
|
141
151
|
for (let [role, [name, options]] of Object.entries(layouts)) {
|
|
142
152
|
// TODO: try to omit if unchanged
|
|
143
|
-
const fn = () => this._layoutFactory.create(name, { ...options, role, workflow: this._workflowName });
|
|
153
|
+
const fn = () => this._layoutFactory.create(name, { ...options, role, workflow: this._workflowName, workflowOptions: this._getWorkflowOptions() });
|
|
144
154
|
if (role === ROLE.CONTAINER) {
|
|
145
155
|
for (const view of this._containers.values()) {
|
|
146
156
|
view.layout = fn();
|
|
@@ -158,7 +168,7 @@ export default class ViewsActor {
|
|
|
158
168
|
return undefined;
|
|
159
169
|
}
|
|
160
170
|
const [name, options] = args;
|
|
161
|
-
return this._layoutFactory.create(name, { ...options, role, workflow: this._workflowName });
|
|
171
|
+
return this._layoutFactory.create(name, { ...options, role, workflow: this._workflowName, workflowOptions: this._getWorkflowOptions() });
|
|
162
172
|
}
|
|
163
173
|
|
|
164
174
|
get(role) {
|
|
@@ -225,6 +235,21 @@ export default class ViewsActor {
|
|
|
225
235
|
return this._containerTracker;
|
|
226
236
|
}
|
|
227
237
|
|
|
238
|
+
_syncAutocompleteOptions() {
|
|
239
|
+
this._autocompleteOptions = this._options.resolved.autocomplete;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
_syncPaginationOptions() {
|
|
243
|
+
this._paginationOptions = this._options.resolved.pagination;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
_getWorkflowOptions() {
|
|
247
|
+
return trimObj({
|
|
248
|
+
autocomplete: this._autocompleteOptions,
|
|
249
|
+
pagination: this._paginationOptions,
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
|
|
228
253
|
_error(e) {
|
|
229
254
|
// TODO: hub trigger error event
|
|
230
255
|
console.error(e);
|
|
@@ -267,6 +292,9 @@ class Trackers {
|
|
|
267
292
|
constructor(views, roles) {
|
|
268
293
|
this._views = views;
|
|
269
294
|
for (const role of roles) {
|
|
295
|
+
if (role === ROLE.CONTAINER) {
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
270
298
|
Object.defineProperty(this, role, {
|
|
271
299
|
get: () => views.get(role).tracker,
|
|
272
300
|
});
|