@miso.ai/client-sdk-ui 1.11.0-beta.4 → 1.11.0-beta.6

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.
@@ -5,9 +5,9 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.sources = exports.showMore = exports.showLess = exports.question = exports.keywords = exports.hits = void 0;
7
7
  /**
8
- * The phrase displayed right before <miso-question>
8
+ * The phrase to display <miso-question>
9
9
  */
10
- const question = exports.question = 'You asked...';
10
+ const question = exports.question = 'You asked “${value}”';
11
11
 
12
12
  /**
13
13
  * The phrase displayed right before <miso-sources>
@@ -31,6 +31,15 @@ class Sections extends _templates.Sections {
31
31
  classes: [`${classPrefix}__answer-box-inner`]
32
32
  }, this.answerGroup(options)), this.answerBoxToggle(options)]);
33
33
  }
34
+ question(options) {
35
+ const {
36
+ phrase
37
+ } = this._helpers;
38
+ return phrase(options, {
39
+ name: 'question',
40
+ tag: 'h3'
41
+ }).replaceAll('${value}', '<miso-question></miso-question>');
42
+ }
34
43
  answerBoxToggle(options) {
35
44
  const {
36
45
  element
@@ -51,7 +60,7 @@ class Sections extends _templates.Sections {
51
60
  } = this._helpers;
52
61
  return container(options, {
53
62
  name: 'search-results',
54
- visibleWhen: 'ready'
63
+ visibleWhen: 'loading ready'
55
64
  }, [this.searchResultsInfoGroup(options), this.searchResultsFilters(options), '<miso-products></miso-products>']);
56
65
  }
57
66
  searchResultsInfoGroup(options) {
@@ -161,10 +161,10 @@ class FacetsLayout extends _template.default {
161
161
  }
162
162
  _render(element, data, controls) {
163
163
  super._render(element, data, controls);
164
- this._syncSelections();
165
164
  }
166
165
  _afterRender(element, state) {
167
166
  this._syncBindings(element, state);
167
+ this._syncSelections();
168
168
  }
169
169
  _unrender() {
170
170
  this._clearBindings();
@@ -270,6 +270,10 @@ class FacetsLayout extends _template.default {
270
270
  return Array.from(element.querySelectorAll(`[data-role="option"]`));
271
271
  }
272
272
  _handleClick(event) {
273
+ // only left click
274
+ if (event.button !== 0) {
275
+ return;
276
+ }
273
277
  const element = event.target.closest(`[data-role="option"]`);
274
278
  if (!element) {
275
279
  return;
@@ -4,4 +4,4 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
- var _default = exports.default = '1.11.0-beta.4';
7
+ var _default = exports.default = '1.11.0-beta.6';
@@ -204,6 +204,9 @@ class AnswerBasedWorkflow extends _base.default {
204
204
  return;
205
205
  }
206
206
  super._updateData(data);
207
+
208
+ // update URL if autoQuery.updateUrl is not false
209
+ this._updateUrlIfNecessary(data);
207
210
  }
208
211
  _handleHeadResponse(data) {
209
212
  // capture question ID and register at context
@@ -211,13 +214,9 @@ class AnswerBasedWorkflow extends _base.default {
211
214
  }
212
215
  _defaultProcessData(data) {
213
216
  data = super._defaultProcessData(data);
214
-
215
- // update URL if autoQuery.updateUrl is not false
216
- this._updateUrlIfNecessary(data);
217
-
218
- // affiliation
219
217
  data = (0, _index3.processData)(data);
220
- return (0, _processors.writeAnswerStageToMeta)(data);
218
+ data = (0, _processors.writeAnswerStageToMeta)(data);
219
+ return data;
221
220
  }
222
221
  _writeQuestionIdFromData(_ref) {
223
222
  let {
@@ -178,15 +178,19 @@ class Workflow extends _commons.Component {
178
178
  _updateData(data) {
179
179
  this._sessions.start(); // in case session not started yet
180
180
 
181
- data = (0, _processors.writeDataStatus)(data);
182
181
  data = this._defaultProcessData(data);
183
182
  for (const process of this._options.resolved.dataProcessor) {
184
183
  data = process(data);
185
184
  }
186
- this._hub.update(_index.fields.data(), data);
185
+ this._updateDataInHub(data);
187
186
  }
188
187
  _defaultProcessData(data) {
189
- return (0, _processors.writeMisoIdToMeta)(data);
188
+ data = (0, _processors.writeDataStatus)(data);
189
+ data = (0, _processors.writeMisoIdToMeta)(data);
190
+ return data;
191
+ }
192
+ _updateDataInHub(data) {
193
+ this._hub.update(_index.fields.data(), data);
190
194
  }
191
195
 
192
196
  /*
@@ -60,9 +60,12 @@ class HybridSearchAnswer extends _answerBased.default {
60
60
  }
61
61
 
62
62
  // data //
63
- _updateData(data) {
64
- // we want this to be available everywhere
63
+ _defaultProcessData(data) {
64
+ data = super._defaultProcessData(data);
65
65
  data = (0, _processors.writeKeywordsToData)(data);
66
+ return data;
67
+ }
68
+ _updateDataInHub(data) {
66
69
  switch (data.status) {
67
70
  case _constants.STATUS.INITIAL:
68
71
  case _constants.STATUS.LOADING:
@@ -70,7 +73,7 @@ class HybridSearchAnswer extends _answerBased.default {
70
73
  this._dispatchDataToSibling(data);
71
74
  break;
72
75
  }
73
- super._updateData(data);
76
+ super._updateDataInHub(data);
74
77
  }
75
78
  _handleHeadResponse(data) {
76
79
  super._handleHeadResponse(data);
@@ -78,7 +81,7 @@ class HybridSearchAnswer extends _answerBased.default {
78
81
  this._dispatchDataToSibling(data);
79
82
  }
80
83
  _dispatchDataToSibling(data) {
81
- this._superworkflow._results.updateData(Object.assign({}, data, {
84
+ this._resultsSession && this._superworkflow._results.updateData(Object.assign({}, data, {
82
85
  session: this._resultsSession
83
86
  }));
84
87
  }
@@ -10,7 +10,8 @@ var _index = require("../actor/index.js");
10
10
  var _constants = require("../constants.js");
11
11
  var _options = require("./options.js");
12
12
  var _processors = require("./processors.js");
13
- const _excluded = ["filters"];
13
+ const _excluded = ["filters"],
14
+ _excluded2 = ["filters"];
14
15
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
15
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
17
  const ROLES_CONFIG = Object.freeze({
@@ -43,14 +44,19 @@ class HybridSearchResults extends _base.default {
43
44
 
44
45
  // query //
45
46
  _refine(filters) {
47
+ // remember current facet_counts
48
+ const {
49
+ facet_counts
50
+ } = this._hub.states[_index.fields.data()].value || {};
51
+ this._previousFacetCounts = facet_counts;
52
+
46
53
  // start a new session
47
54
  this.restart();
48
55
 
49
56
  // get stored query from sibling
50
57
  const query = this._superworkflow._answer._hub.states[_index.fields.query()];
51
58
  const payload = this._buildPayload(Object.assign({}, query, {
52
- filters,
53
- answer: false
59
+ filters
54
60
  }));
55
61
  const {
56
62
  session
@@ -69,11 +75,32 @@ class HybridSearchResults extends _base.default {
69
75
  payload = _objectWithoutPropertiesLoose(_ref, _excluded);
70
76
  // borrow the work from the sibling
71
77
  payload = this._superworkflow._answer._buildPayload(payload);
78
+ payload = this._writeFqToPayload(Object.assign({}, payload, {
79
+ filters
80
+ }));
81
+ payload = this._writeQuestionIdToPayload(payload);
82
+ return Object.assign({}, payload, {
83
+ answer: false
84
+ });
85
+ }
86
+ _writeFqToPayload() {
87
+ let _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
88
+ let {
89
+ filters
90
+ } = _ref2,
91
+ payload = _objectWithoutPropertiesLoose(_ref2, _excluded2);
72
92
  const fq = (0, _processors.composeFq)(filters); // TODO: combine with fq in payload?
73
93
  return (0, _commons.trimObj)(Object.assign({}, payload, {
74
94
  fq
75
95
  }));
76
96
  }
97
+ _writeQuestionIdToPayload(payload) {
98
+ return Object.assign({}, payload, {
99
+ _meta: (0, _commons.trimObj)(Object.assign({}, payload._meta, {
100
+ question_id: this._superworkflow._answer.questionId
101
+ }))
102
+ });
103
+ }
77
104
  _request(event) {
78
105
  this._hub.update(_index.fields.request(), event);
79
106
  }
@@ -82,7 +109,32 @@ class HybridSearchResults extends _base.default {
82
109
  _defaultProcessData(data) {
83
110
  data = super._defaultProcessData(data);
84
111
  data = (0, _processors.writeKeywordsToData)(data);
112
+ data = this._retainFacetCounts(data);
85
113
  return data;
86
114
  }
115
+ _retainFacetCounts(data) {
116
+ if (!this._previousFacetCounts) {
117
+ return data;
118
+ }
119
+ const {
120
+ status,
121
+ value
122
+ } = data;
123
+ switch (status) {
124
+ case _constants.STATUS.INITIAL:
125
+ case _constants.STATUS.LOADING:
126
+ break;
127
+ default:
128
+ return data;
129
+ }
130
+ if (value && value.facet_counts) {
131
+ return data;
132
+ }
133
+ return Object.assign({}, data, {
134
+ value: Object.assign({}, value, {
135
+ facet_counts: this._previousFacetCounts
136
+ })
137
+ });
138
+ }
87
139
  }
88
140
  exports.default = HybridSearchResults;
@@ -20,6 +20,12 @@ const DEFAULT_API_OPTIONS = Object.freeze(Object.assign({}, _answerBased.default
20
20
  })
21
21
  }));
22
22
  const DEFAULT_LAYOUTS = Object.freeze(Object.assign({}, _answerBased.default.DEFAULT_LAYOUTS, {
23
+ [_constants.ROLE.QUERY]: [_index2.SearchBoxLayout.type, {
24
+ placeholder: ''
25
+ }],
26
+ [_constants.ROLE.QUESTION]: [_index2.TextLayout.type, {
27
+ raw: true
28
+ }],
23
29
  [_constants.ROLE.PRODUCTS]: [_index2.ListLayout.type, {
24
30
  itemType: 'article'
25
31
  }],
@@ -13,10 +13,10 @@ var _constants = require("../constants.js");
13
13
  function writeDataStatus(data) {
14
14
  const status = getStatus(data);
15
15
  const ongoing = status === _constants.STATUS.READY ? !!data.ongoing : undefined;
16
- return (0, _commons.trimObj)(Object.assign({}, data, {
16
+ return (0, _commons.trimObj)(Object.assign({
17
17
  status,
18
18
  ongoing
19
- }));
19
+ }, data)); // let orinigal data override status and ongoing
20
20
  }
21
21
  function getStatus(data) {
22
22
  if (!data) {
@@ -53,7 +53,8 @@ function writeKeywordsToData(data) {
53
53
  request,
54
54
  value
55
55
  } = data;
56
- if (!request || !value) {
56
+ // we still want the value in loading status
57
+ if (!request) {
57
58
  return data;
58
59
  }
59
60
  const {
@@ -106,7 +107,8 @@ function composeFq(filters) {
106
107
  if (!values || !values.length) {
107
108
  continue; // just in case
108
109
  }
109
- clauses.push(`${field}:(${values.map(v => `"${v}"`).join(' OR ')})`);
110
+ const vstr = values.length === 1 ? `"${values[0]}"` : `(${values.map(v => `"${v}"`).join(' OR ')})`;
111
+ clauses.push(`${field}:${vstr}`);
110
112
  }
111
- return clauses.map(c => `(${c})`).join(' AND ');
113
+ return clauses.map(c => `(${c})`).join(' AND ') || undefined;
112
114
  }
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.0-beta.4"
29
+ "@miso.ai/commons": "1.11.0-beta.6"
30
30
  },
31
- "version": "1.11.0-beta.4"
31
+ "version": "1.11.0-beta.6"
32
32
  }
@@ -1,7 +1,7 @@
1
1
  /**
2
- * The phrase displayed right before <miso-question>
2
+ * The phrase to display <miso-question>
3
3
  */
4
- export const question = 'You asked...';
4
+ export const question = 'You asked “${value}”';
5
5
 
6
6
  /**
7
7
  * The phrase displayed right before <miso-sources>
@@ -18,6 +18,11 @@ class Sections extends _Sections {
18
18
  ]);
19
19
  }
20
20
 
21
+ question(options) {
22
+ const { phrase } = this._helpers;
23
+ return phrase(options, { name: 'question', tag: 'h3' }).replaceAll('${value}', '<miso-question></miso-question>');
24
+ }
25
+
21
26
  answerBoxToggle(options) {
22
27
  const { element } = this._helpers;
23
28
  const { classPrefix } = options;
@@ -28,7 +33,7 @@ class Sections extends _Sections {
28
33
 
29
34
  searchResultsGroup(options) {
30
35
  const { container } = this._helpers;
31
- return container(options, { name: 'search-results', visibleWhen: 'ready' }, [
36
+ return container(options, { name: 'search-results', visibleWhen: 'loading ready' }, [
32
37
  this.searchResultsInfoGroup(options),
33
38
  this.searchResultsFilters(options),
34
39
  '<miso-products></miso-products>',
@@ -125,11 +125,11 @@ export default class FacetsLayout extends TemplateBasedLayout {
125
125
 
126
126
  _render(element, data, controls) {
127
127
  super._render(element, data, controls);
128
- this._syncSelections();
129
128
  }
130
129
 
131
130
  _afterRender(element, state) {
132
131
  this._syncBindings(element, state);
132
+ this._syncSelections();
133
133
  }
134
134
 
135
135
  _unrender() {
@@ -220,6 +220,10 @@ export default class FacetsLayout extends TemplateBasedLayout {
220
220
  }
221
221
 
222
222
  _handleClick(event) {
223
+ // only left click
224
+ if (event.button !== 0) {
225
+ return;
226
+ }
223
227
  const element = event.target.closest(`[data-role="option"]`);
224
228
  if (!element) {
225
229
  return;
package/src/version.js CHANGED
@@ -1 +1 @@
1
- export default '1.11.0-beta.4';
1
+ export default '1.11.0-beta.6';
@@ -176,6 +176,9 @@ export default class AnswerBasedWorkflow extends Workflow {
176
176
  return;
177
177
  }
178
178
  super._updateData(data);
179
+
180
+ // update URL if autoQuery.updateUrl is not false
181
+ this._updateUrlIfNecessary(data);
179
182
  }
180
183
 
181
184
  _handleHeadResponse(data) {
@@ -185,14 +188,9 @@ export default class AnswerBasedWorkflow extends Workflow {
185
188
 
186
189
  _defaultProcessData(data) {
187
190
  data = super._defaultProcessData(data);
188
-
189
- // update URL if autoQuery.updateUrl is not false
190
- this._updateUrlIfNecessary(data);
191
-
192
- // affiliation
193
191
  data = processAffiliationData(data);
194
-
195
- return writeAnswerStageToMeta(data);
192
+ data = writeAnswerStageToMeta(data);
193
+ return data;
196
194
  }
197
195
 
198
196
  _writeQuestionIdFromData({ value }) {
@@ -160,17 +160,22 @@ export default class Workflow extends Component {
160
160
  _updateData(data) {
161
161
  this._sessions.start(); // in case session not started yet
162
162
 
163
- data = writeDataStatus(data);
164
163
  data = this._defaultProcessData(data);
165
164
  for (const process of this._options.resolved.dataProcessor) {
166
165
  data = process(data);
167
166
  }
168
167
 
169
- this._hub.update(fields.data(), data);
168
+ this._updateDataInHub(data);
170
169
  }
171
170
 
172
171
  _defaultProcessData(data) {
173
- return writeMisoIdToMeta(data);
172
+ data = writeDataStatus(data);
173
+ data = writeMisoIdToMeta(data);
174
+ return data;
175
+ }
176
+
177
+ _updateDataInHub(data) {
178
+ this._hub.update(fields.data(), data);
174
179
  }
175
180
 
176
181
  /*
@@ -51,10 +51,13 @@ export default class HybridSearchAnswer extends AnswerBasedWorkflow {
51
51
  }
52
52
 
53
53
  // data //
54
- _updateData(data) {
55
- // we want this to be available everywhere
54
+ _defaultProcessData(data) {
55
+ data = super._defaultProcessData(data);
56
56
  data = writeKeywordsToData(data);
57
+ return data;
58
+ }
57
59
 
60
+ _updateDataInHub(data) {
58
61
  switch (data.status) {
59
62
  case STATUS.INITIAL:
60
63
  case STATUS.LOADING:
@@ -62,7 +65,7 @@ export default class HybridSearchAnswer extends AnswerBasedWorkflow {
62
65
  this._dispatchDataToSibling(data);
63
66
  break;
64
67
  }
65
- super._updateData(data);
68
+ super._updateDataInHub(data);
66
69
  }
67
70
 
68
71
  _handleHeadResponse(data) {
@@ -72,7 +75,7 @@ export default class HybridSearchAnswer extends AnswerBasedWorkflow {
72
75
  }
73
76
 
74
77
  _dispatchDataToSibling(data) {
75
- this._superworkflow._results.updateData({ ...data, session: this._resultsSession });
78
+ this._resultsSession && this._superworkflow._results.updateData({ ...data, session: this._resultsSession });
76
79
  }
77
80
 
78
81
  }
@@ -1,7 +1,7 @@
1
1
  import { trimObj } from '@miso.ai/commons';
2
2
  import Workflow from './base.js';
3
3
  import { fields } from '../actor/index.js';
4
- import { ROLE } from '../constants.js';
4
+ import { ROLE, STATUS } from '../constants.js';
5
5
  import { mergeApiOptions } from './options.js';
6
6
  import { writeKeywordsToData, composeFq } from './processors.js';
7
7
 
@@ -43,12 +43,16 @@ export default class HybridSearchResults extends Workflow {
43
43
 
44
44
  // query //
45
45
  _refine(filters) {
46
+ // remember current facet_counts
47
+ const { facet_counts } = this._hub.states[fields.data()].value || {};
48
+ this._previousFacetCounts = facet_counts;
49
+
46
50
  // start a new session
47
51
  this.restart();
48
52
 
49
53
  // get stored query from sibling
50
54
  const query = this._superworkflow._answer._hub.states[fields.query()];
51
- const payload = this._buildPayload({ ...query, filters, answer: false });
55
+ const payload = this._buildPayload({ ...query, filters });
52
56
  const { session } = this;
53
57
  const event = mergeApiOptions(this._options.resolved.api, { payload, session });
54
58
 
@@ -58,6 +62,12 @@ export default class HybridSearchResults extends Workflow {
58
62
  _buildPayload({ filters, ...payload } = {}) {
59
63
  // borrow the work from the sibling
60
64
  payload = this._superworkflow._answer._buildPayload(payload);
65
+ payload = this._writeFqToPayload({ ...payload, filters });
66
+ payload = this._writeQuestionIdToPayload(payload);
67
+ return { ...payload, answer: false };
68
+ }
69
+
70
+ _writeFqToPayload({ filters, ...payload } = {}) {
61
71
  const fq = composeFq(filters); // TODO: combine with fq in payload?
62
72
  return trimObj({
63
73
  ...payload,
@@ -65,6 +75,16 @@ export default class HybridSearchResults extends Workflow {
65
75
  });
66
76
  }
67
77
 
78
+ _writeQuestionIdToPayload(payload) {
79
+ return {
80
+ ...payload,
81
+ _meta: trimObj({
82
+ ...payload._meta,
83
+ question_id: this._superworkflow._answer.questionId,
84
+ }),
85
+ };
86
+ }
87
+
68
88
  _request(event) {
69
89
  this._hub.update(fields.request(), event);
70
90
  }
@@ -73,7 +93,32 @@ export default class HybridSearchResults extends Workflow {
73
93
  _defaultProcessData(data) {
74
94
  data = super._defaultProcessData(data);
75
95
  data = writeKeywordsToData(data);
96
+ data = this._retainFacetCounts(data);
76
97
  return data;
77
98
  }
78
99
 
100
+ _retainFacetCounts(data) {
101
+ if (!this._previousFacetCounts) {
102
+ return data;
103
+ }
104
+ const { status, value } = data;
105
+ switch (status) {
106
+ case STATUS.INITIAL:
107
+ case STATUS.LOADING:
108
+ break;
109
+ default:
110
+ return data;
111
+ }
112
+ if (value && value.facet_counts) {
113
+ return data;
114
+ }
115
+ return {
116
+ ...data,
117
+ value: {
118
+ ...value,
119
+ facet_counts: this._previousFacetCounts,
120
+ },
121
+ };
122
+ }
123
+
79
124
  }
@@ -3,7 +3,7 @@ import { InteractionsActor } from '../actor/index.js';
3
3
  import Workflow from './base.js';
4
4
  import AnswerBasedWorkflow from './answer-based.js';
5
5
  import { ROLE } from '../constants.js';
6
- import { ListLayout, TextLayout, FacetsLayout } from '../layout/index.js';
6
+ import { SearchBoxLayout, ListLayout, TextLayout, FacetsLayout } from '../layout/index.js';
7
7
  import HybridSearchAnswer from './hybrid-search-answer.js';
8
8
  import HybridSearchResults from './hybrid-search-results.js';
9
9
 
@@ -18,6 +18,8 @@ const DEFAULT_API_OPTIONS = Object.freeze({
18
18
 
19
19
  const DEFAULT_LAYOUTS = Object.freeze({
20
20
  ...AnswerBasedWorkflow.DEFAULT_LAYOUTS,
21
+ [ROLE.QUERY]: [SearchBoxLayout.type, { placeholder: '' }],
22
+ [ROLE.QUESTION]: [TextLayout.type, { raw: true }],
21
23
  [ROLE.PRODUCTS]: [ListLayout.type, { itemType: 'article' }],
22
24
  [ROLE.KEYWORDS]: [TextLayout.type, { raw: true }],
23
25
  [ROLE.HITS]: [TextLayout.type, { raw: true, format: 'number' }],
@@ -4,7 +4,7 @@ import { STATUS } from '../constants.js';
4
4
  export function writeDataStatus(data) {
5
5
  const status = getStatus(data);
6
6
  const ongoing = status === STATUS.READY ? !!data.ongoing : undefined;
7
- return trimObj({ ...data, status, ongoing });
7
+ return trimObj({ status, ongoing, ...data }); // let orinigal data override status and ongoing
8
8
  }
9
9
 
10
10
  function getStatus(data) {
@@ -35,7 +35,8 @@ export function writeMisoIdToMeta(data) {
35
35
 
36
36
  export function writeKeywordsToData(data) {
37
37
  const { request, value } = data;
38
- if (!request || !value) {
38
+ // we still want the value in loading status
39
+ if (!request) {
39
40
  return data;
40
41
  }
41
42
  const { payload } = request || {};
@@ -84,7 +85,8 @@ export function composeFq(filters) {
84
85
  if (!values || !values.length) {
85
86
  continue; // just in case
86
87
  }
87
- clauses.push(`${field}:(${values.map(v => `"${v}"`).join(' OR ')})`);
88
+ const vstr = values.length === 1 ? `"${values[0]}"` : `(${values.map(v => `"${v}"`).join(' OR ')})`;
89
+ clauses.push(`${field}:${vstr}`);
88
90
  }
89
- return clauses.map(c => `(${c})`).join(' AND ');
91
+ return clauses.map(c => `(${c})`).join(' AND ') || undefined;
90
92
  }