@miso.ai/client-sdk-ui 1.11.4-beta.4 → 1.11.4-beta.5

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.
Files changed (64) hide show
  1. package/dist/cjs/actor/data.js +1 -1
  2. package/dist/cjs/actor/tracker.js +29 -13
  3. package/dist/cjs/actor/view.js +4 -2
  4. package/dist/cjs/actor/views.js +3 -6
  5. package/dist/cjs/affiliation/index.js +1 -1
  6. package/dist/cjs/combo/ask/options.js +1 -1
  7. package/dist/cjs/combo/base.js +1 -1
  8. package/dist/cjs/defaults/ask/controls.js +1 -1
  9. package/dist/cjs/defaults/common/templates.js +1 -1
  10. package/dist/cjs/layout/affiliation/affiliation.js +2 -2
  11. package/dist/cjs/layout/banner/banner.js +1 -1
  12. package/dist/cjs/layout/button/more-button.js +1 -1
  13. package/dist/cjs/layout/container/container.js +3 -3
  14. package/dist/cjs/layout/error/error.js +1 -1
  15. package/dist/cjs/layout/input/facets.js +1 -1
  16. package/dist/cjs/layout/input/option-list.js +1 -1
  17. package/dist/cjs/layout/input/search-box.js +2 -2
  18. package/dist/cjs/layout/input/select.js +1 -1
  19. package/dist/cjs/layout/list/cards.js +1 -1
  20. package/dist/cjs/layout/list/carousel.js +1 -1
  21. package/dist/cjs/layout/list/collection.js +1 -1
  22. package/dist/cjs/layout/list/list.js +1 -1
  23. package/dist/cjs/layout/radio/feedback.js +1 -1
  24. package/dist/cjs/layout/radio/radio.js +1 -1
  25. package/dist/cjs/layout/raf.js +1 -1
  26. package/dist/cjs/layout/template.js +1 -1
  27. package/dist/cjs/layout/templates.js +1 -1
  28. package/dist/cjs/layout/text/text.js +1 -1
  29. package/dist/cjs/layout/text/typewriter/index.js +56 -14
  30. package/dist/cjs/layout/trackable.js +3 -3
  31. package/dist/cjs/plugin.js +1 -1
  32. package/dist/cjs/util/trackers.js +3 -3
  33. package/dist/cjs/version.js +1 -1
  34. package/dist/cjs/workflow/answer-based.js +73 -19
  35. package/dist/cjs/workflow/ask.js +7 -7
  36. package/dist/cjs/workflow/asks.js +1 -1
  37. package/dist/cjs/workflow/autocomplete.js +1 -1
  38. package/dist/cjs/workflow/base.js +3 -2
  39. package/dist/cjs/workflow/explore.js +8 -4
  40. package/dist/cjs/workflow/hybrid-search-answer.js +1 -1
  41. package/dist/cjs/workflow/options/layouts.js +1 -1
  42. package/dist/cjs/workflow/options/trackers.js +67 -13
  43. package/dist/cjs/workflow/recommendation.js +1 -1
  44. package/dist/cjs/workflow/search-based.js +1 -1
  45. package/dist/cjs/workflow/search.js +4 -2
  46. package/package.json +2 -2
  47. package/src/actor/tracker.js +26 -11
  48. package/src/actor/view.js +2 -1
  49. package/src/actor/views.js +2 -6
  50. package/src/layout/affiliation/affiliation.js +1 -1
  51. package/src/layout/container/container.js +2 -2
  52. package/src/layout/input/search-box.js +1 -1
  53. package/src/layout/text/typewriter/index.js +40 -7
  54. package/src/layout/trackable.js +3 -3
  55. package/src/util/trackers.js +1 -1
  56. package/src/version.js +1 -1
  57. package/src/workflow/answer-based.js +47 -10
  58. package/src/workflow/ask.js +5 -3
  59. package/src/workflow/base.js +3 -3
  60. package/src/workflow/explore.js +9 -4
  61. package/src/workflow/options/trackers.js +63 -15
  62. package/src/workflow/recommendation.js +2 -2
  63. package/src/workflow/search-based.js +2 -2
  64. package/src/workflow/search.js +3 -2
@@ -13,7 +13,9 @@ var _index3 = require("../affiliation/index.js");
13
13
  var _index4 = require("./options/index.js");
14
14
  var _processors = require("./processors.js");
15
15
  var _useLink = require("./use-link.js");
16
+ const _excluded = ["setValue", "focus", "param", "sourceParam"];
16
17
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
18
+ function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
17
19
  const DEFAULT_API_OPTIONS = Object.freeze(Object.assign({}, _base.default.DEFAULT_API_OPTIONS, {
18
20
  group: _commons.API.GROUP.ASK,
19
21
  payload: Object.assign({}, _base.default.DEFAULT_API_OPTIONS.payload, {
@@ -55,9 +57,15 @@ const DEFAULT_LAYOUTS = Object.freeze(Object.assign({}, _base.default.DEFAULT_LA
55
57
  }]
56
58
  }));
57
59
  const DEFAULT_TRACKERS = Object.freeze(Object.assign({}, _base.default.DEFAULT_TRACKERS, {
58
- [_constants.ROLE.SOURCES]: {},
59
- [_constants.ROLE.AFFILIATION]: {},
60
- [_constants.ROLE.PRODUCTS]: {}
60
+ [_constants.ROLE.ANSWER]: {
61
+ active: true,
62
+ itemless: true,
63
+ deduplicated: false,
64
+ click: _index4.DEFAULT_TRACKER_OPTIONS.click // click only
65
+ },
66
+ [_constants.ROLE.SOURCES]: _index4.DEFAULT_TRACKER_OPTIONS,
67
+ [_constants.ROLE.AFFILIATION]: _index4.DEFAULT_TRACKER_OPTIONS,
68
+ [_constants.ROLE.PRODUCTS]: _index4.DEFAULT_TRACKER_OPTIONS
61
69
  }));
62
70
  const DEFAULT_OPTIONS = Object.freeze(Object.assign({}, _base.default.DEFAULT_OPTIONS, {
63
71
  api: DEFAULT_API_OPTIONS,
@@ -69,6 +77,22 @@ const ROLES_OPTIONS = (0, _index4.mergeRolesOptions)(_base.default.ROLES_OPTIONS
69
77
  main: _constants.ROLE.ANSWER,
70
78
  members: Object.keys(DEFAULT_LAYOUTS)
71
79
  });
80
+ function normalizeAutoQueryOptions() {
81
+ let _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
82
+ let {
83
+ setValue = true,
84
+ focus = true,
85
+ param = 'q',
86
+ sourceParam = 'qs'
87
+ } = _ref,
88
+ options = _objectWithoutPropertiesLoose(_ref, _excluded);
89
+ return Object.assign({
90
+ setValue,
91
+ focus,
92
+ param,
93
+ sourceParam
94
+ }, options);
95
+ }
72
96
  class AnswerBasedWorkflow extends _base.default {
73
97
  // constructor //
74
98
  _initProperties(args) {
@@ -82,7 +106,7 @@ class AnswerBasedWorkflow extends _base.default {
82
106
  }
83
107
  _initSubscriptions(args) {
84
108
  super._initSubscriptions(args);
85
- this._unsubscribes = [...this._unsubscribes, this._hub.on(_index.fields.query(), args => this._query(args)), this._views.get(_constants.ROLE.ANSWER).on('citation-click', event => this._onCitationClick(event))];
109
+ this._unsubscribes = [...this._unsubscribes, this._hub.on(_index.fields.query(), args => this._query(args)), this._views.get(_constants.ROLE.ANSWER).on('citation-click', event => this._onCitationClick(event)), this._views.get(_constants.ROLE.ANSWER).on('link-click', event => this._onAnswerLinkClick(event))];
86
110
  }
87
111
 
88
112
  // lifecycle //
@@ -140,12 +164,14 @@ class AnswerBasedWorkflow extends _base.default {
140
164
  autoQuery() {
141
165
  let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
142
166
  const {
143
- setValue = true,
144
- focus = true
145
- } = this._autoQuery = options;
167
+ setValue,
168
+ focus,
169
+ param,
170
+ sourceParam
171
+ } = this._autoQuery = normalizeAutoQueryOptions(options);
146
172
  const searchParams = new URLSearchParams(window.location.search);
147
- const q = searchParams.get('q');
148
- const qs = searchParams.get('qs');
173
+ const q = searchParams.get(param);
174
+ const qs = searchParams.get(sourceParam);
149
175
  const {
150
176
  layout
151
177
  } = this._views.get(_constants.ROLE.QUERY);
@@ -218,10 +244,10 @@ class AnswerBasedWorkflow extends _base.default {
218
244
  data = (0, _processors.writeAnswerStageToMeta)(data);
219
245
  return data;
220
246
  }
221
- _writeQuestionIdFromData(_ref) {
247
+ _writeQuestionIdFromData(_ref2) {
222
248
  let {
223
249
  value
224
- } = _ref;
250
+ } = _ref2;
225
251
  if (!value) {
226
252
  return;
227
253
  }
@@ -230,24 +256,27 @@ class AnswerBasedWorkflow extends _base.default {
230
256
  } = value;
231
257
  this._writeQuestionId(questionId);
232
258
  }
233
- _updateUrlIfNecessary(_ref2) {
259
+ _updateUrlIfNecessary(_ref3) {
234
260
  let {
235
261
  value,
236
262
  request
237
- } = _ref2;
263
+ } = _ref3;
238
264
  if (!value || !this._autoQuery || this._autoQuery.updateUrl === false) {
239
265
  // explicitly false
240
266
  return;
241
267
  }
268
+ const {
269
+ param
270
+ } = this._autoQuery;
242
271
  const {
243
272
  question
244
273
  } = value;
245
274
  const organic = request && request.payload && request.payload._meta && request.payload._meta.question_source === _constants.ORGANIC_QUESTION_SOURCE;
246
275
  const url = new URL(window.location);
247
- const currentQuestion = url.searchParams.get('q');
276
+ const currentQuestion = url.searchParams.get(param);
248
277
  // TODO: review this, handle &qs=
249
278
  if (question !== currentQuestion && (!organic || this._autoQuery.updateUrl === true)) {
250
- url.searchParams.set('q', question);
279
+ url.searchParams.set(param, question);
251
280
  window.history.replaceState({}, '', url);
252
281
  }
253
282
  }
@@ -256,6 +285,7 @@ class AnswerBasedWorkflow extends _base.default {
256
285
  _defaultProcessInteraction(payload, args) {
257
286
  payload = super._defaultProcessInteraction(payload, args);
258
287
  payload = this._writeAskPropertiesToInteraction(payload, args);
288
+ payload = this._writeAnswerClickInteraction(payload, args);
259
289
  return payload;
260
290
  }
261
291
  _writeAskPropertiesToInteraction() {
@@ -272,6 +302,25 @@ class AnswerBasedWorkflow extends _base.default {
272
302
  }
273
303
  });
274
304
  }
305
+ _writeAnswerClickInteraction(payload, args) {
306
+ if (args.role !== _constants.ROLE.ANSWER) {
307
+ return payload;
308
+ }
309
+ console.log('writeAnswerClickInteraction', payload, args);
310
+ const {
311
+ items = []
312
+ } = args;
313
+ return (0, _processors.mergeInteraction)(payload, {
314
+ context: {
315
+ custom_context: {
316
+ urls: items.map(item => item.url),
317
+ texts: items.map(item => item.text),
318
+ class_names: items.map(item => item.className),
319
+ attributes: items.map(item => item.attributes)
320
+ }
321
+ }
322
+ });
323
+ }
275
324
  _getQuestionSourceFromViewState(args) {
276
325
  const {
277
326
  request
@@ -283,10 +332,10 @@ class AnswerBasedWorkflow extends _base.default {
283
332
  }
284
333
 
285
334
  // handlers //
286
- _onCitationClick(_ref3) {
335
+ _onCitationClick(_ref4) {
287
336
  let {
288
337
  index
289
- } = _ref3;
338
+ } = _ref4;
290
339
  const {
291
340
  value
292
341
  } = this.states[_index.fields.data()] || {};
@@ -299,8 +348,13 @@ class AnswerBasedWorkflow extends _base.default {
299
348
  return;
300
349
  }
301
350
  // TODO: should we track impression as well?
302
- this._trackers.sources.click([source.product_id], {
303
- manual: false
351
+ this._views.trackers.sources.click([source.product_id]);
352
+ }
353
+ _onAnswerLinkClick(item) {
354
+ // put everything into args and let _defaultProcessInteraction() handles it
355
+ // for it's hard to make it a standard item
356
+ this._views.trackers.answer.click([], {
357
+ items: [item]
304
358
  });
305
359
  }
306
360
 
@@ -13,7 +13,7 @@ var _processors = require("./processors.js");
13
13
  var _index3 = require("./options/index.js");
14
14
  const _excluded = ["q", "qs"];
15
15
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
16
- function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.includes(n)) continue; t[n] = r[n]; } return t; }
16
+ function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
17
17
  const DEFAULT_API_OPTIONS = Object.freeze(Object.assign({}, _answerBased.default.DEFAULT_API_OPTIONS, {
18
18
  name: _commons.API.NAME.QUESTIONS,
19
19
  payload: Object.assign({}, _answerBased.default.DEFAULT_API_OPTIONS.payload, {
@@ -33,12 +33,12 @@ const DEFAULT_LAYOUTS = Object.freeze(Object.assign({}, _answerBased.default.DEF
33
33
  [_constants.ROLE.QUERY_SUGGESTIONS]: _index2.OptionListLayout.type
34
34
  }));
35
35
  const DEFAULT_TRACKERS = Object.freeze(Object.assign({}, _answerBased.default.DEFAULT_TRACKERS, {
36
- [_constants.ROLE.RELATED_RESOURCES]: {},
37
- [_constants.ROLE.QUERY_SUGGESTIONS]: {
38
- click: {
39
- validate: event => event.button === 0 // left click only
40
- }
41
- }
36
+ [_constants.ROLE.RELATED_RESOURCES]: _index3.DEFAULT_TRACKER_OPTIONS,
37
+ [_constants.ROLE.QUERY_SUGGESTIONS]: Object.assign({}, _index3.DEFAULT_TRACKER_OPTIONS, {
38
+ click: Object.assign({}, _index3.DEFAULT_TRACKER_OPTIONS.click, {
39
+ validate: event => event.button === 0 // loosen criteria, for it's not a hyperlink
40
+ })
41
+ })
42
42
  }));
43
43
  const DEFAULT_OPTIONS = Object.freeze(Object.assign({}, _answerBased.default.DEFAULT_OPTIONS, {
44
44
  api: DEFAULT_API_OPTIONS,
@@ -8,7 +8,7 @@ var _context = _interopRequireDefault(require("./context.js"));
8
8
  var _ask = _interopRequireDefault(require("./ask.js"));
9
9
  const _excluded = ["root", "events"];
10
10
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
- function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.includes(n)) continue; t[n] = r[n]; } return t; }
11
+ function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
12
12
  class Asks extends _context.default {
13
13
  constructor(plugin, client) {
14
14
  super('asks', plugin, client);
@@ -10,7 +10,7 @@ var _base = _interopRequireDefault(require("./base.js"));
10
10
  const _excluded = ["layouts", "trackers"],
11
11
  _excluded2 = ["defaults"];
12
12
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
13
- function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.includes(n)) continue; t[n] = r[n]; } return t; }
13
+ function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
14
14
  const ROLES_OPTIONS = Object.freeze({
15
15
  members: []
16
16
  });
@@ -59,6 +59,7 @@ class Workflow extends _commons.Component {
59
59
  context,
60
60
  plugin,
61
61
  client,
62
+ defaults,
62
63
  options
63
64
  } = args;
64
65
  this._context = context;
@@ -71,8 +72,8 @@ class Workflow extends _commons.Component {
71
72
  this._name = args.name;
72
73
  this._roles = args.roles;
73
74
  this._extensions = plugin._getExtensions(client);
74
- this._defaults = args.defaults;
75
- this._options = options || new _index3.WorkflowOptions(context && context._options, args.defaults);
75
+ this._defaults = defaults;
76
+ this._options = options || new _index3.WorkflowOptions(context && context._options, defaults);
76
77
  this._hub = injectLogger(new _index.Hub(), function () {
77
78
  return _this._log(...arguments);
78
79
  });
@@ -13,7 +13,7 @@ var _index3 = require("./options/index.js");
13
13
  var _useLink = require("./use-link.js");
14
14
  const _excluded = ["value"];
15
15
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
16
- function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.includes(n)) continue; t[n] = r[n]; } return t; }
16
+ function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
17
17
  const DEFAULT_API_OPTIONS = Object.freeze(Object.assign({}, _base.default.DEFAULT_API_OPTIONS, {
18
18
  group: _commons.API.GROUP.ASK,
19
19
  name: _commons.API.NAME.RELATED_QUESTIONS
@@ -30,10 +30,14 @@ const DEFAULT_LAYOUTS = Object.freeze(Object.assign({}, _base.default.DEFAULT_LA
30
30
  }]
31
31
  }));
32
32
  const DEFAULT_TRACKERS = Object.freeze(Object.assign({}, _base.default.DEFAULT_TRACKERS, {
33
- [_constants.ROLE.RELATED_QUESTIONS]: {},
34
- [_constants.ROLE.CONTAINER]: {},
33
+ [_constants.ROLE.RELATED_QUESTIONS]: _index3.DEFAULT_TRACKER_OPTIONS,
34
+ [_constants.ROLE.CONTAINER]: Object.assign({}, _index3.DEFAULT_TRACKER_OPTIONS, {
35
+ itemless: true
36
+ }),
35
37
  [_constants.ROLE.QUERY]: {
36
- [_constants.EVENT_TYPE.SUBMIT]: {}
38
+ [_constants.EVENT_TYPE.SUBMIT]: {
39
+ active: true
40
+ }
37
41
  }
38
42
  }));
39
43
  const DEFAULT_OPTIONS = Object.freeze(Object.assign({}, _base.default.DEFAULT_OPTIONS, {
@@ -11,7 +11,7 @@ var _processors = require("./processors.js");
11
11
  var _autocompletable = require("./autocompletable.js");
12
12
  const _excluded = ["qs"];
13
13
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
14
- function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.includes(n)) continue; t[n] = r[n]; } return t; }
14
+ function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
15
15
  const ROLES_OPTIONS = (0, _index.mergeRolesOptions)(_answerBased.default.ROLES_OPTIONS, {
16
16
  mappings: {
17
17
  [_constants.ROLE.QUESTION]: _constants.ROLE.KEYWORDS
@@ -9,7 +9,7 @@ var _commons = require("@miso.ai/commons");
9
9
  var _constants = require("../../constants.js");
10
10
  var _utils = require("./utils.js");
11
11
  const _excluded = ["results"];
12
- function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.includes(n)) continue; t[n] = r[n]; } return t; }
12
+ function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
13
13
  function normalizeLayoutsOptions() {
14
14
  let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
15
15
  if (options === false) {
@@ -3,37 +3,91 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
+ exports.DEFAULT_TRACKER_OPTIONS = void 0;
6
7
  exports.mergeTrackersOptions = mergeTrackersOptions;
7
8
  exports.normalizeTrackersOptions = normalizeTrackersOptions;
9
+ var _constants = require("../../constants.js");
8
10
  var _utils = require("./utils.js");
9
- function normalizeTrackersOptions(options) {
10
- if (options === undefined || options === false) {
11
- return options;
12
- }
11
+ const _excluded = ["active"],
12
+ _excluded2 = ["active"];
13
+ function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
14
+ const DEFAULT_TRACKER_OPTIONS = exports.DEFAULT_TRACKER_OPTIONS = Object.freeze({
15
+ active: true,
16
+ impression: Object.freeze({
17
+ active: true
18
+ }),
19
+ viewable: Object.freeze({
20
+ active: true,
21
+ area: 0.5,
22
+ duration: 1000
23
+ }),
24
+ click: Object.freeze({
25
+ active: true,
26
+ lenient: false
27
+ })
28
+ });
29
+ function normalizeTrackersOptions() {
30
+ let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
31
+ options = (0, _utils.normalizeOptions)(options);
32
+ const {
33
+ active
34
+ } = options,
35
+ rest = _objectWithoutPropertiesLoose(options, _excluded);
13
36
  const normalized = {};
14
- for (const [role, args] of Object.entries(options)) {
37
+ for (const [role, args] of Object.entries(rest)) {
15
38
  normalized[role] = normalizeTrackerOptions(args);
16
39
  }
17
- return normalized;
40
+ return Object.assign({
41
+ active
42
+ }, normalized);
43
+ }
44
+ function normalizeTrackerOptions() {
45
+ let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
46
+ options = (0, _utils.normalizeOptions)(options);
47
+ const rest = _objectWithoutPropertiesLoose(options, _excluded2);
48
+ const normalized = {};
49
+ for (const [role, args] of Object.entries(rest)) {
50
+ normalized[role] = normalizeTrackerEventOptions(args);
51
+ }
52
+ return options;
18
53
  }
19
- function normalizeTrackerOptions(options) {
54
+ function normalizeTrackerEventOptions() {
55
+ let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
56
+ options = (0, _utils.normalizeOptions)(options);
20
57
  return options;
21
58
  }
22
59
  function mergeTrackersOptions() {
23
60
  for (var _len = arguments.length, optionsList = new Array(_len), _key = 0; _key < _len; _key++) {
24
61
  optionsList[_key] = arguments[_key];
25
62
  }
63
+ // TODO: should be able to remove this
26
64
  if (optionsList[optionsList.length - 1] === false) {
27
65
  return false;
28
66
  }
29
- return (0, _utils.mergeOptions)(optionsList, (merged, options) => Object.assign(merged, Object.assign({}, options, {
30
- impression: mergeTrackerEventOptions(merged.impression, options.impression),
31
- viewable: mergeTrackerEventOptions(merged.viewable, options.viewable),
32
- click: mergeTrackerEventOptions(merged.click, options.click)
33
- })));
67
+ return (0, _utils.mergeOptions)(optionsList, (merged, options) => {
68
+ for (const [key, args] of Object.entries(options)) {
69
+ if (args === undefined) {
70
+ continue;
71
+ }
72
+ merged[key] = key === 'active' ? args : mergeTrackerOptions(merged[key], args);
73
+ }
74
+ return merged;
75
+ });
76
+ }
77
+ function mergeTrackerOptions() {
78
+ let base = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
79
+ let overrides = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
80
+ const merged = Object.assign({}, base);
81
+ for (const [key, args] of Object.entries(overrides)) {
82
+ if (args === undefined) {
83
+ continue;
84
+ }
85
+ merged[key] = _constants.TRACKING_EVENT_TYPES.includes(key) ? mergeTrackerEventOptions(base[key], args) : args;
86
+ }
87
+ return merged;
34
88
  }
35
89
  function mergeTrackerEventOptions() {
36
90
  let base = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
37
91
  let overrides = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
38
- return overrides === false || base === false ? overrides : Object.assign({}, base, overrides);
92
+ return Object.assign({}, base, overrides);
39
93
  }
@@ -22,7 +22,7 @@ const DEFAULT_LAYOUTS = Object.freeze(Object.assign({}, _base.default.DEFAULT_LA
22
22
  [_constants.ROLE.PRODUCTS]: _index.ListLayout.type
23
23
  }));
24
24
  const DEFAULT_TRACKERS = Object.freeze(Object.assign({}, _base.default.DEFAULT_TRACKERS, {
25
- [_constants.ROLE.PRODUCTS]: {}
25
+ [_constants.ROLE.PRODUCTS]: _index2.DEFAULT_TRACKER_OPTIONS
26
26
  }));
27
27
  const DEFAULT_OPTIONS = Object.freeze(Object.assign({}, _base.default.DEFAULT_OPTIONS, {
28
28
  api: DEFAULT_API_OPTIONS,
@@ -39,7 +39,7 @@ const DEFAULT_LAYOUTS = Object.freeze(Object.assign({}, _base.default.DEFAULT_LA
39
39
  [_constants.ROLE.MORE]: [_index2.MoreButtonLayout.type]
40
40
  }));
41
41
  const DEFAULT_TRACKERS = Object.freeze(Object.assign({}, _base.default.DEFAULT_TRACKERS, {
42
- [_constants.ROLE.PRODUCTS]: {}
42
+ [_constants.ROLE.PRODUCTS]: _index3.DEFAULT_TRACKER_OPTIONS
43
43
  }));
44
44
  const DEFAULT_PAGINATION = Object.freeze({
45
45
  active: false,
@@ -52,9 +52,11 @@ class Search extends _searchBased.default {
52
52
  autoQuery() {
53
53
  let {
54
54
  setValue = true,
55
- focus = true
55
+ focus = true,
56
+ param = 'q'
56
57
  } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
57
- const q = new URLSearchParams(window.location.search).get('q');
58
+ // TODO: align implementation with AnswerBasedWorkflow
59
+ const q = new URLSearchParams(window.location.search).get(param);
58
60
  const {
59
61
  layout
60
62
  } = this._views.get(_constants.ROLE.QUERY);
package/package.json CHANGED
@@ -26,7 +26,7 @@
26
26
  "url": "https://github.com/MisoAI/miso-client-js-sdk/issues"
27
27
  },
28
28
  "dependencies": {
29
- "@miso.ai/commons": "1.11.4-beta.4"
29
+ "@miso.ai/commons": "1.11.4-beta.5"
30
30
  },
31
- "version": "1.11.4-beta.4"
31
+ "version": "1.11.4-beta.5"
32
32
  }
@@ -3,40 +3,55 @@ import { PERFORMANCE_EVENT_TYPES, TRACKING_STATUS, EVENT_TYPE, validateEventType
3
3
  import * as fields from './fields.js';
4
4
  import States from '../util/states.js';
5
5
 
6
- const VALUELESS_ITEMS = [Symbol('valueless')];
6
+ // a dummy item array for manipulating deduplication
7
+ const ITEMLESS_DUMMY_ITEMS = [Symbol('itemless')];
7
8
 
8
9
  export default class Tracker {
9
10
 
10
- constructor({ hub, role, valueless = false }) {
11
+ constructor({ hub, role, options }) {
11
12
  this._hub = hub;
12
13
  this._role = role;
13
- this._valueless = !!valueless;
14
+ this._options = options;
14
15
  // TODO: know item type
15
16
 
16
17
  this._states = new States(this._getSessionId());
17
18
  }
18
19
 
20
+ get options() {
21
+ return typeof this._options === 'function' ? this._options() : this._options;
22
+ }
23
+
19
24
  getState(item) {
20
25
  return this._states.getFullState(item);
21
26
  }
22
27
 
23
- _trigger(type, items) {
28
+ _trigger(type, items, meta) {
24
29
  validateEventType(type);
25
- if (this._valueless) {
26
- items = VALUELESS_ITEMS;
30
+
31
+ const { options } = this;
32
+ if (!options) {
33
+ return;
27
34
  }
28
35
 
29
36
  this._syncSession();
30
37
 
31
- items = this._states.untriggered(asArray(items), type);
32
- if (items.length === 0) {
33
- return;
38
+ const { deduplicated = true, itemless = false } = options;
39
+
40
+ if (deduplicated) {
41
+ if (itemless) {
42
+ items = ITEMLESS_DUMMY_ITEMS;
43
+ }
44
+ items = this._states.untriggered(asArray(items), type);
45
+ if (items.length === 0) {
46
+ return;
47
+ }
48
+ this._states.set(items, type, TRACKING_STATUS.TRIGGERED);
34
49
  }
35
- this._states.set(items, type, TRACKING_STATUS.TRIGGERED);
36
50
 
37
51
  this._sendToHub({
38
52
  type,
39
- items: this._valueless ? undefined : items,
53
+ items: itemless ? undefined : items,
54
+ ...meta,
40
55
  });
41
56
  }
42
57
 
package/src/actor/view.js CHANGED
@@ -95,9 +95,10 @@ export default class ViewActor {
95
95
  if (role === ROLE.CONTAINER) {
96
96
  return this._views._getContainerTracker();
97
97
  }
98
+ // TODO: we should move this to workflow level, as there could be multiple view of the same role in the future
98
99
  if (!this._tracker) {
99
100
  const { hub } = this;
100
- this._tracker = new Tracker({ hub, role });
101
+ this._tracker = new Tracker({ hub, role, options: () => this.trackerOptions });
101
102
  }
102
103
  return this._tracker;
103
104
  }
@@ -24,7 +24,6 @@ export default class ViewsActor {
24
24
  this._containers = new Map();
25
25
  this._containerTracker = undefined;
26
26
  this._views = {};
27
- this._trackers = new Trackers(this, roles.members);
28
27
  this._filters = new Filters(this);
29
28
 
30
29
  for (const role of roles.members) {
@@ -36,6 +35,7 @@ export default class ViewsActor {
36
35
 
37
36
  defineValues(this, {
38
37
  interface: new Views(this),
38
+ trackers: new Trackers(this, roles.members),
39
39
  });
40
40
 
41
41
  const syncSize = () => this.syncSize();
@@ -50,10 +50,6 @@ export default class ViewsActor {
50
50
  this._syncLayouts();
51
51
  }
52
52
 
53
- get trackers() {
54
- return this._trackers;
55
- }
56
-
57
53
  get filters() {
58
54
  return this._filters;
59
55
  }
@@ -224,7 +220,7 @@ export default class ViewsActor {
224
220
  if (!this._containerTracker) {
225
221
  const hub = this._hub;
226
222
  const role = ROLE.CONTAINER;
227
- this._containerTracker = new Tracker({ hub, role, valueless: true, options: () => this._getTrackerOptions(role) });
223
+ this._containerTracker = new Tracker({ hub, role, itemless: true, options: () => this._getTrackerOptions(role) });
228
224
  }
229
225
  return this._containerTracker;
230
226
  }
@@ -165,7 +165,7 @@ export default class AffiliationLayout extends CollectionLayout {
165
165
 
166
166
  initialize(view) {
167
167
  super.initialize(view);
168
- const { viewable: options } = this._view.trackerOptions || {};
168
+ const { viewable: options } = this._view.tracker.options || {};
169
169
  this._viewable = new CarouselItemViewabilityObserver(this._onViewable.bind(this), options);
170
170
  }
171
171
 
@@ -82,7 +82,7 @@ export default class ContainerLayout extends RafLayout {
82
82
  }
83
83
 
84
84
  _trackImpression() {
85
- const { impression: options } = this._view.trackerOptions || {};
85
+ const { impression: options } = this._view.tracker.options || {};
86
86
  if (!options) {
87
87
  return;
88
88
  }
@@ -94,7 +94,7 @@ export default class ContainerLayout extends RafLayout {
94
94
  }
95
95
 
96
96
  async _trackViewable(element) {
97
- const { viewable: options } = this._view.trackerOptions || {};
97
+ const { viewable: options } = this._view.tracker.options || {};
98
98
  if (!options) {
99
99
  return;
100
100
  }
@@ -338,7 +338,7 @@ export default class SearchBoxLayout extends TemplateBasedLayout {
338
338
  }
339
339
 
340
340
  _trackSubmit(value) {
341
- const { [EVENT_TYPE.SUBMIT]: options } = this._view.trackerOptions || {};
341
+ const { [EVENT_TYPE.SUBMIT]: options } = this._view.tracker.options || {};
342
342
  if (!options) {
343
343
  return;
344
344
  }