@miso.ai/client-sdk-ui 1.10.0-beta.1 → 1.10.0-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/actor/data.js +1 -1
- package/dist/cjs/actor/tracker.js +46 -70
- package/dist/cjs/actor/trackers.js +5 -1
- package/dist/cjs/actor/utils.js +6 -2
- package/dist/cjs/actor/view.js +14 -3
- package/dist/cjs/actor/views.js +9 -1
- package/dist/cjs/affiliation/index.js +126 -0
- package/dist/cjs/combo/ask/options.js +1 -1
- package/dist/cjs/combo/base.js +1 -1
- package/dist/cjs/constants.js +6 -3
- package/dist/cjs/defaults/ask/controls.js +1 -1
- package/dist/cjs/defaults/ask/phrases.js +1 -1
- package/dist/cjs/defaults/ask/templates.js +14 -4
- package/dist/cjs/element/role/index.js +7 -0
- package/dist/cjs/element/role/miso-affiliation.js +20 -0
- package/dist/cjs/layout/affiliation/affiliation.js +330 -0
- package/dist/cjs/layout/banner/banner.js +1 -1
- package/dist/cjs/layout/container/container.js +1 -1
- package/dist/cjs/layout/error/error.js +1 -1
- package/dist/cjs/layout/index.js +7 -0
- package/dist/cjs/layout/input/option-list.js +35 -50
- package/dist/cjs/layout/input/search-box.js +17 -5
- package/dist/cjs/layout/list/cards.js +1 -1
- package/dist/cjs/layout/list/carousel.js +5 -3
- package/dist/cjs/layout/list/collection.js +38 -48
- package/dist/cjs/layout/list/list.js +1 -1
- package/dist/cjs/layout/radio/feedback.js +1 -1
- package/dist/cjs/layout/radio/radio.js +1 -1
- package/dist/cjs/layout/raf.js +1 -1
- package/dist/cjs/layout/template.js +1 -1
- package/dist/cjs/layout/templates.js +135 -44
- package/dist/cjs/layout/text/text.js +1 -1
- package/dist/cjs/layout/text/typewriter/index.js +3 -3
- package/dist/cjs/layout/trackable.js +124 -0
- package/dist/cjs/plugin.js +1 -1
- package/dist/cjs/util/bindings.js +58 -110
- package/dist/cjs/util/states.js +31 -24
- package/dist/cjs/util/trackers.js +75 -0
- package/dist/cjs/util/viewables.js +55 -0
- package/dist/cjs/version.js +1 -1
- package/dist/cjs/workflow/ask.js +14 -5
- package/dist/cjs/workflow/asks.js +1 -1
- package/dist/cjs/workflow/base.js +5 -5
- package/dist/cjs/workflow/explore.js +1 -1
- package/dist/cjs/workflow/options.js +6 -1
- package/dist/cjs/workflow/recommendation.js +2 -0
- package/package.json +2 -2
- package/src/actor/tracker.js +39 -62
- package/src/actor/trackers.js +3 -1
- package/src/actor/utils.js +6 -2
- package/src/actor/view.js +12 -1
- package/src/actor/views.js +11 -0
- package/src/affiliation/index.js +108 -0
- package/src/constants.js +10 -1
- package/src/defaults/ask/phrases.js +1 -1
- package/src/defaults/ask/templates.js +13 -2
- package/src/element/role/index.js +1 -0
- package/src/element/role/miso-affiliation.js +16 -0
- package/src/layout/affiliation/affiliation.js +295 -0
- package/src/layout/index.js +1 -0
- package/src/layout/input/option-list.js +35 -43
- package/src/layout/input/search-box.js +7 -2
- package/src/layout/list/carousel.js +4 -2
- package/src/layout/list/collection.js +37 -43
- package/src/layout/templates.js +101 -26
- package/src/layout/text/typewriter/index.js +2 -2
- package/src/layout/trackable.js +106 -0
- package/src/util/bindings.js +47 -103
- package/src/util/states.js +26 -20
- package/src/util/trackers.js +69 -0
- package/src/util/viewables.js +47 -0
- package/src/version.js +1 -1
- package/src/workflow/ask.js +7 -3
- package/src/workflow/base.js +1 -1
- package/src/workflow/options.js +5 -1
- package/src/workflow/recommendation.js +1 -0
- package/dist/cjs/util/tracker.js +0 -348
- package/src/util/tracker.js +0 -318
package/src/actor/tracker.js
CHANGED
|
@@ -1,94 +1,63 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { asArray } from '@miso.ai/commons';
|
|
2
|
+
import { EVENT_TYPE, TRACKING_EVENT_TYPES, TRACKING_STATUS, validateEventType } from '../constants.js';
|
|
2
3
|
import * as fields from './fields.js';
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
4
|
+
import States from '../util/states.js';
|
|
5
|
+
import { normalizeTrackerOptions } from '../util/trackers.js';
|
|
5
6
|
import { toInteraction } from './utils.js';
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
return viewState && viewState.status === STATUS.READY;
|
|
9
|
-
}
|
|
8
|
+
const { IMPRESSION, VIEWABLE, CLICK } = EVENT_TYPE;
|
|
10
9
|
|
|
11
10
|
export default class Tracker {
|
|
12
11
|
|
|
13
12
|
constructor(hub, view, { active, bindings, ...options } = {}) {
|
|
14
13
|
this._hub = hub;
|
|
15
14
|
this._view = view;
|
|
16
|
-
this.
|
|
17
|
-
const role = this._role = view.role;
|
|
15
|
+
this._role = view.role;
|
|
18
16
|
// TODO: know item type
|
|
19
17
|
|
|
20
|
-
this.
|
|
21
|
-
|
|
22
|
-
list: element => this._listBindingsFn()(element),
|
|
23
|
-
},
|
|
24
|
-
proxyElement: view.proxyElement,
|
|
25
|
-
sessionId: () => this._getSessionId(),
|
|
26
|
-
active: active || (() => this._isViewReady()),
|
|
27
|
-
...options,
|
|
28
|
-
});
|
|
18
|
+
this._states = undefined;
|
|
19
|
+
this.config(options);
|
|
29
20
|
|
|
30
21
|
this._unsubscribes = [
|
|
31
|
-
this.
|
|
32
|
-
hub.on(fields.view(role), () => this.
|
|
22
|
+
...TRACKING_EVENT_TYPES.map(type => this._view.trackingEvents.on(type, values => this._trigger(type, values))),
|
|
23
|
+
hub.on(fields.view(view.role), () => this._syncSession()),
|
|
33
24
|
];
|
|
34
25
|
|
|
35
|
-
this.
|
|
26
|
+
this._syncSession();
|
|
36
27
|
}
|
|
37
28
|
|
|
38
29
|
config(options) {
|
|
39
|
-
this.
|
|
30
|
+
this._options = normalizeTrackerOptions(options);
|
|
40
31
|
}
|
|
41
32
|
|
|
42
33
|
start() {
|
|
43
34
|
throw new Error(`workflow.tracker.start() is deprecated. Use workflow.startTracker() instead.`);
|
|
44
35
|
}
|
|
45
36
|
|
|
46
|
-
|
|
47
|
-
this.
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
impression(productIds, options) {
|
|
51
|
-
this._assertViewReady();
|
|
52
|
-
this._tracker.impression(productIds.map(product_id => ({ product_id })), options);
|
|
37
|
+
impression(items, options) {
|
|
38
|
+
this._trigger(IMPRESSION, items, true);
|
|
53
39
|
}
|
|
54
40
|
|
|
55
|
-
viewable(
|
|
56
|
-
this.
|
|
57
|
-
this._tracker.viewable(productIds.map(product_id => ({ product_id })), options);
|
|
41
|
+
viewable(items, options) {
|
|
42
|
+
this._trigger(VIEWABLE, items, true);
|
|
58
43
|
}
|
|
59
44
|
|
|
60
|
-
click(
|
|
61
|
-
this.
|
|
62
|
-
this._tracker.click(productIds.map(product_id => ({ product_id })), options);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
_listBindingsFn() {
|
|
66
|
-
if (this._bindings && typeof this._bindings.list === 'function') {
|
|
67
|
-
return this._bindings.list;
|
|
68
|
-
}
|
|
69
|
-
const { layout } = this._view;
|
|
70
|
-
if (layout && layout.bindings && typeof layout.bindings.list === 'function') {
|
|
71
|
-
return layout.bindings.list;
|
|
72
|
-
}
|
|
73
|
-
// TODO: only if item is product typed
|
|
74
|
-
return fallbackListFunction(ATTR_DATA_MISO_PRODUCT_ID);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
_assertViewReady() {
|
|
78
|
-
if (!this._hub.active) {
|
|
79
|
-
throw new Error(`Workflow is not active. Call workflow.start() to activate it.`);
|
|
80
|
-
}
|
|
81
|
-
if (!isReady(this._getViewState())) {
|
|
82
|
-
throw new Error(`Workflow is not rendered yet. If you handle rendering by yourself, call workflow.notifyViewUpdate() when DOM is ready.`);
|
|
83
|
-
}
|
|
45
|
+
click(items, options) {
|
|
46
|
+
this._trigger(CLICK, items, true);
|
|
84
47
|
}
|
|
85
48
|
|
|
86
49
|
_getViewState() {
|
|
87
50
|
return this._hub.states[fields.view(this._role)];
|
|
88
51
|
}
|
|
89
52
|
|
|
90
|
-
|
|
91
|
-
|
|
53
|
+
_syncSession() {
|
|
54
|
+
const sessionId = this._getSessionId();
|
|
55
|
+
if (!sessionId) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (!this._states || sessionId !== this._states.sessionId) {
|
|
59
|
+
this._states = new States(sessionId);
|
|
60
|
+
}
|
|
92
61
|
}
|
|
93
62
|
|
|
94
63
|
_getSessionId() {
|
|
@@ -106,16 +75,25 @@ export default class Tracker {
|
|
|
106
75
|
return request && request.payload;
|
|
107
76
|
}
|
|
108
77
|
|
|
109
|
-
getState(
|
|
110
|
-
return this.
|
|
78
|
+
getState(item) {
|
|
79
|
+
return this._states.getFullState(item);
|
|
111
80
|
}
|
|
112
81
|
|
|
113
|
-
|
|
82
|
+
_trigger(type, items, manual = false) {
|
|
83
|
+
validateEventType(type);
|
|
84
|
+
|
|
85
|
+
items = this._states.untriggered(asArray(items), type);
|
|
86
|
+
if (items.length === 0) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
this._states.set(items, type, TRACKING_STATUS.TRIGGERED);
|
|
90
|
+
|
|
114
91
|
const property = this._role === 'results' ? 'products' : this._role; // TODO: ad-hoc, see #83
|
|
115
92
|
const misoId = this._getMisoId();
|
|
116
93
|
const request = this._getRequestPayload();
|
|
94
|
+
|
|
117
95
|
// TODO: should trigger 'tracker' and let workflow translate to interactions
|
|
118
|
-
this._hub.trigger(fields.interaction(), toInteraction({ property, misoId, request },
|
|
96
|
+
this._hub.trigger(fields.interaction(), toInteraction({ property, misoId, request }, { event: type, values: items, manual }));
|
|
119
97
|
}
|
|
120
98
|
|
|
121
99
|
_destroy() {
|
|
@@ -123,7 +101,6 @@ export default class Tracker {
|
|
|
123
101
|
unsubscribe();
|
|
124
102
|
}
|
|
125
103
|
this._unsubscribes = [];
|
|
126
|
-
this._tracker.destroy();
|
|
127
104
|
}
|
|
128
105
|
|
|
129
106
|
}
|
package/src/actor/trackers.js
CHANGED
|
@@ -12,7 +12,9 @@ export default class Trackers {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
_syncConfig() {
|
|
15
|
-
|
|
15
|
+
// TODO: trackers itself can be falsy
|
|
16
|
+
const { trackers } = this._options.resolved;
|
|
17
|
+
for (const [role, options] of Object.entries(trackers)) {
|
|
16
18
|
this._createOrConfigTracker(role, options);
|
|
17
19
|
}
|
|
18
20
|
}
|
package/src/actor/utils.js
CHANGED
|
@@ -22,8 +22,10 @@ export function toInteraction({ property, misoId, request }, { event, values, ma
|
|
|
22
22
|
// TODO: ad-hoc
|
|
23
23
|
const question_source = request && request._meta && request._meta.question_source;
|
|
24
24
|
const isProductType = isProduct(property);
|
|
25
|
-
const product_ids = isProductType ? values.map(v => v.product_id).filter(v => v) : [];
|
|
26
|
-
const items = isProductType ? undefined : values.map(v => v.text || v);
|
|
25
|
+
const product_ids = isProductType ? values.map(v => typeof v === 'string' ? v : v.product_id).filter(v => v) : [];
|
|
26
|
+
const items = isProductType ? undefined : values.map(v => v.text || v.id || v);
|
|
27
|
+
const channel = property === ROLE.AFFILIATION ? values[0] && values[0].channel : undefined;
|
|
28
|
+
const positions = property === ROLE.AFFILIATION ? values.map(v => v.position) : undefined;
|
|
27
29
|
const payload = trimObj({
|
|
28
30
|
type: event === 'viewable' ? 'viewable_impression' : event,
|
|
29
31
|
product_ids,
|
|
@@ -32,7 +34,9 @@ export function toInteraction({ property, misoId, request }, { event, values, ma
|
|
|
32
34
|
custom_context: trimObj({
|
|
33
35
|
api_ts,
|
|
34
36
|
property,
|
|
37
|
+
channel,
|
|
35
38
|
items,
|
|
39
|
+
positions,
|
|
36
40
|
trigger: manual ? 'manual' : 'auto',
|
|
37
41
|
question_source,
|
|
38
42
|
}),
|
package/src/actor/view.js
CHANGED
|
@@ -21,10 +21,13 @@ export default class ViewActor {
|
|
|
21
21
|
constructor(views, role) {
|
|
22
22
|
this._events = new EventEmitter({ target: this });
|
|
23
23
|
this._views = views;
|
|
24
|
+
const trackingEvents = {};
|
|
25
|
+
this._trackingEvents = new EventEmitter({ target: trackingEvents });
|
|
24
26
|
|
|
25
27
|
defineValues(this, {
|
|
26
28
|
role,
|
|
27
29
|
interface: new View(this),
|
|
30
|
+
trackingEvents,
|
|
28
31
|
});
|
|
29
32
|
}
|
|
30
33
|
|
|
@@ -134,6 +137,14 @@ export default class ViewActor {
|
|
|
134
137
|
this.hub.update(fields.view(role), state, { silent });
|
|
135
138
|
}
|
|
136
139
|
|
|
140
|
+
get trackerOptions() {
|
|
141
|
+
return this._views._getTrackerOptions(this.role);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
_track(type, items) {
|
|
145
|
+
this._trackingEvents.emit(type, items);
|
|
146
|
+
}
|
|
147
|
+
|
|
137
148
|
_sliceData({ value, error, status, meta, ...rest }) {
|
|
138
149
|
const sliced = {
|
|
139
150
|
value: this.role === ROLE.ERROR ? error : (value && value[this.role]),
|
|
@@ -205,7 +216,7 @@ export default class ViewActor {
|
|
|
205
216
|
class View {
|
|
206
217
|
|
|
207
218
|
constructor(actor) {
|
|
208
|
-
delegateGetters(this, actor, ['role', 'layout', 'element', 'proxyElement', 'refresh', 'on']);
|
|
219
|
+
delegateGetters(this, actor, ['role', 'layout', 'element', 'proxyElement', 'refresh', 'on', 'trackingEvents']);
|
|
209
220
|
}
|
|
210
221
|
|
|
211
222
|
}
|
package/src/actor/views.js
CHANGED
|
@@ -2,6 +2,7 @@ import { defineValues, delegateGetters } from '@miso.ai/commons';
|
|
|
2
2
|
import { STATUS, ROLE } from '../constants.js';
|
|
3
3
|
import * as fields from './fields.js';
|
|
4
4
|
import ViewActor from './view.js';
|
|
5
|
+
import { normalizeTrackerOptions } from '../util/trackers.js';
|
|
5
6
|
|
|
6
7
|
export default class ViewsActor {
|
|
7
8
|
|
|
@@ -34,9 +35,11 @@ export default class ViewsActor {
|
|
|
34
35
|
this._unsubscribes = [
|
|
35
36
|
() => window.removeEventListener('resize', syncSize),
|
|
36
37
|
hub.on(fields.data(), () => this.refresh()),
|
|
38
|
+
options.on('trackers', () => this._syncTrackers()),
|
|
37
39
|
options.on('layouts', () => this._syncLayouts()),
|
|
38
40
|
];
|
|
39
41
|
|
|
42
|
+
this._syncTrackers();
|
|
40
43
|
this._syncLayouts();
|
|
41
44
|
}
|
|
42
45
|
|
|
@@ -185,6 +188,14 @@ export default class ViewsActor {
|
|
|
185
188
|
return this._data;
|
|
186
189
|
}
|
|
187
190
|
|
|
191
|
+
_syncTrackers() {
|
|
192
|
+
this._trackerOptions = this._options.resolved.trackers;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
_getTrackerOptions(role) {
|
|
196
|
+
return normalizeTrackerOptions((this._trackerOptions && this._trackerOptions[role]) || false);
|
|
197
|
+
}
|
|
198
|
+
|
|
188
199
|
_error(e) {
|
|
189
200
|
// TODO: hub trigger error event
|
|
190
201
|
console.error(e);
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { trimObj } from '@miso.ai/commons';
|
|
2
|
+
|
|
3
|
+
export function processData(data) {
|
|
4
|
+
if (!data || !data.value) {
|
|
5
|
+
return data;
|
|
6
|
+
}
|
|
7
|
+
const { value } = data;
|
|
8
|
+
return {
|
|
9
|
+
...data,
|
|
10
|
+
value: processValue(value)
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function processValue(value) {
|
|
15
|
+
if (value.sovrn_aff) {
|
|
16
|
+
const { sovrn_aff, ...rest } = value;
|
|
17
|
+
value = {
|
|
18
|
+
...rest,
|
|
19
|
+
affiliation: processSovrnData(sovrn_aff),
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return postProcessValue(value);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function postProcessValue(value) {
|
|
26
|
+
const { affiliation } = value;
|
|
27
|
+
if (!affiliation) {
|
|
28
|
+
return value;
|
|
29
|
+
}
|
|
30
|
+
let { channel, products } = affiliation;
|
|
31
|
+
if (!products) {
|
|
32
|
+
return value;
|
|
33
|
+
}
|
|
34
|
+
products = products.map(product => ({ ...product }));
|
|
35
|
+
let i = 0;
|
|
36
|
+
for (const product of products) {
|
|
37
|
+
if (channel) {
|
|
38
|
+
product.channel = channel;
|
|
39
|
+
}
|
|
40
|
+
product.position = i++;
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
...value,
|
|
44
|
+
affiliation: {
|
|
45
|
+
...affiliation,
|
|
46
|
+
products,
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function processSovrnData({ products, ...sovrn_aff }) {
|
|
52
|
+
return {
|
|
53
|
+
channel: 'sovrn',
|
|
54
|
+
...sovrn_aff,
|
|
55
|
+
products: products.map(processSovrnProduct),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function processSovrnProduct({
|
|
60
|
+
id,
|
|
61
|
+
deeplink: url,
|
|
62
|
+
headline: title,
|
|
63
|
+
description,
|
|
64
|
+
currency,
|
|
65
|
+
retailPrice: original_price,
|
|
66
|
+
salePrice: sale_price,
|
|
67
|
+
discountRate: discount_rate_percent,
|
|
68
|
+
image: cover_image,
|
|
69
|
+
thumbnail,
|
|
70
|
+
merchant,
|
|
71
|
+
...product
|
|
72
|
+
}) {
|
|
73
|
+
const brand = merchant && merchant.name;
|
|
74
|
+
const brand_logo = merchant && merchant.logo;
|
|
75
|
+
return trimObj({
|
|
76
|
+
id: `sovrn-${id}`,
|
|
77
|
+
title,
|
|
78
|
+
description,
|
|
79
|
+
cover_image,
|
|
80
|
+
url,
|
|
81
|
+
currency,
|
|
82
|
+
original_price,
|
|
83
|
+
sale_price,
|
|
84
|
+
discount_rate_percent,
|
|
85
|
+
brand,
|
|
86
|
+
brand_logo,
|
|
87
|
+
custom_attributes: flatten({
|
|
88
|
+
sovrn_id: id,
|
|
89
|
+
thumbnail,
|
|
90
|
+
merchant,
|
|
91
|
+
...product,
|
|
92
|
+
}),
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function flatten(obj, prefix = '') {
|
|
97
|
+
return Object.keys(obj).reduce((acc, key) => {
|
|
98
|
+
const value = obj[key];
|
|
99
|
+
if (value === undefined) {
|
|
100
|
+
return acc;
|
|
101
|
+
}
|
|
102
|
+
const prefixedKey = prefix ? `${prefix}_${key}` : key;
|
|
103
|
+
if (typeof value === 'object') {
|
|
104
|
+
return { ...acc, ...flatten(value, prefixedKey) };
|
|
105
|
+
}
|
|
106
|
+
return { ...acc, [prefixedKey]: value };
|
|
107
|
+
}, {});
|
|
108
|
+
}
|
package/src/constants.js
CHANGED
|
@@ -19,6 +19,7 @@ export const ROLE = Object.freeze({
|
|
|
19
19
|
RELATED_RESOURCES: 'related_resources',
|
|
20
20
|
QUERY_SUGGESTIONS: 'query_suggestions',
|
|
21
21
|
RELATED_QUESTIONS: 'related_questions',
|
|
22
|
+
AFFILIATION: 'affiliation',
|
|
22
23
|
ERROR: 'error',
|
|
23
24
|
});
|
|
24
25
|
|
|
@@ -34,6 +35,7 @@ const DATA_ROLE_SET = new Set([
|
|
|
34
35
|
ROLE.RELATED_RESOURCES,
|
|
35
36
|
ROLE.QUERY_SUGGESTIONS,
|
|
36
37
|
ROLE.RELATED_QUESTIONS,
|
|
38
|
+
ROLE.AFFILIATION,
|
|
37
39
|
]);
|
|
38
40
|
|
|
39
41
|
export function isDataRole(role) {
|
|
@@ -47,6 +49,7 @@ export const LAYOUT_CATEGORY = Object.freeze({
|
|
|
47
49
|
QUERY: 'query',
|
|
48
50
|
RADIO: 'radio',
|
|
49
51
|
TEXT: 'text',
|
|
52
|
+
AFFILIATION: 'affiliation',
|
|
50
53
|
ERROR: 'error',
|
|
51
54
|
});
|
|
52
55
|
|
|
@@ -56,6 +59,12 @@ export const EVENT_TYPE = Object.freeze({
|
|
|
56
59
|
CLICK: 'click',
|
|
57
60
|
});
|
|
58
61
|
|
|
62
|
+
export const TRACKING_EVENT_TYPES = [
|
|
63
|
+
EVENT_TYPE.IMPRESSION,
|
|
64
|
+
EVENT_TYPE.VIEWABLE,
|
|
65
|
+
EVENT_TYPE.CLICK,
|
|
66
|
+
];
|
|
67
|
+
|
|
59
68
|
export const TRACKING_STATUS = Object.freeze({
|
|
60
69
|
UNTRACKED: 'untracked',
|
|
61
70
|
TRACKING: 'tracking',
|
|
@@ -74,7 +83,7 @@ export const STATUS = Object.freeze({
|
|
|
74
83
|
});
|
|
75
84
|
|
|
76
85
|
export function validateEventType(value) {
|
|
77
|
-
if (
|
|
86
|
+
if (TRACKING_EVENT_TYPES.indexOf(value) < 0) {
|
|
78
87
|
throw new Error(`Unrecognized event type: ${value}`);
|
|
79
88
|
}
|
|
80
89
|
}
|
|
@@ -6,7 +6,7 @@ export const question = 'You asked...';
|
|
|
6
6
|
/**
|
|
7
7
|
* The phrase displayed right before <miso-sources>
|
|
8
8
|
*/
|
|
9
|
-
export const sources = '
|
|
9
|
+
export const sources = 'This reply is based on the following articles';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* The phrase displayed right before <miso-query-suggestions>
|
|
@@ -106,6 +106,7 @@ function querySuggestions(options) {
|
|
|
106
106
|
function answerGroup(options) {
|
|
107
107
|
return [
|
|
108
108
|
answer(options),
|
|
109
|
+
affiliation(options),
|
|
109
110
|
sources(options),
|
|
110
111
|
container(options, { name: 'bottom-spacing', visibleWhen: 'ongoing' }),
|
|
111
112
|
];
|
|
@@ -119,7 +120,7 @@ function answer(options) {
|
|
|
119
120
|
'<miso-answer></miso-answer>',
|
|
120
121
|
'<miso-feedback></miso-feedback>',
|
|
121
122
|
]);
|
|
122
|
-
}
|
|
123
|
+
}
|
|
123
124
|
|
|
124
125
|
function sources(options) {
|
|
125
126
|
return container(options, { name: 'sources', visibleWhen: 'nonempty' }, [
|
|
@@ -127,7 +128,17 @@ function sources(options) {
|
|
|
127
128
|
phrase(options, { name: 'sources', tag: 'h3' }),
|
|
128
129
|
'<miso-sources></miso-sources>',
|
|
129
130
|
]);
|
|
130
|
-
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function affiliation(options) {
|
|
134
|
+
const { affiliation = true } = options || {};
|
|
135
|
+
if (!affiliation) {
|
|
136
|
+
return '';
|
|
137
|
+
}
|
|
138
|
+
return container(options, { name: 'affiliation', visibleWhen: 'nonempty' }, [
|
|
139
|
+
'<miso-affiliation></miso-affiliation>',
|
|
140
|
+
]);
|
|
141
|
+
}
|
|
131
142
|
|
|
132
143
|
function phrase(options, { name, tag = 'div' }) {
|
|
133
144
|
const { classPrefix } = options;
|
|
@@ -9,4 +9,5 @@ export { default as MisoAnswerElement } from './miso-answer.js';
|
|
|
9
9
|
export { default as MisoSourcesElement } from './miso-sources.js';
|
|
10
10
|
export { default as MisoRelatedResourcesElement } from './miso-related-resources.js';
|
|
11
11
|
export { default as MisoRelatedQuestionsElement } from './miso-related-questions.js';
|
|
12
|
+
export { default as MisoSovrnAffiliationElement } from './miso-affiliation.js';
|
|
12
13
|
export { default as MisoErrorElement } from './miso-error.js';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import MisoComponentElement from './miso-component.js';
|
|
2
|
+
import { ROLE } from '../../constants.js';
|
|
3
|
+
|
|
4
|
+
export default class MisoAffiliationElement extends MisoComponentElement {
|
|
5
|
+
|
|
6
|
+
constructor() {
|
|
7
|
+
super({
|
|
8
|
+
role: ROLE.AFFILIATION,
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
static get tagName() {
|
|
13
|
+
return 'miso-affiliation';
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
}
|