@coveo/quantic 3.18.0-pre.f855ccdaab → 3.18.0

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.
@@ -38,6 +38,9 @@
38
38
  "c/quanticResultList": ["quanticResultList/quanticResultList.js"],
39
39
  "c/quanticResultLink": ["quanticResultLink/quanticResultLink.js"],
40
40
  "c/quanticSort": ["quanticSort/quanticSort.js"],
41
+ "c/quanticInsightInterface": [
42
+ "quanticInsightInterface/quanticInsightInterface.js"
43
+ ],
41
44
  "c/quanticSummary": ["quanticSummary/quanticSummary.js"],
42
45
  "c/quanticFacetValue": ["quanticFacetValue/quanticFacetValue.js"],
43
46
  "c/quanticNumericFacet": ["quanticNumericFacet/quanticNumericFacet.js"],
@@ -8,6 +8,7 @@
8
8
  tabindex="0"
9
9
  onkeydown={onKeyDown}
10
10
  aria-label={ariaLabelValue}
11
+ data-testid="facet__value"
11
12
  >
12
13
  <template if:false={displayAsLink}>
13
14
  <lightning-input
@@ -38,7 +39,6 @@
38
39
  <span
39
40
  class="slds-truncate slds-var-m-right_xx-small slds-var-m-top_xxx-small facet__value-text facet__value_idle"
40
41
  title={formattedFacetValue}
41
- data-testid="facet__value"
42
42
  >
43
43
  <lightning-formatted-rich-text value={item.highlightedResult} disable-linkify></lightning-formatted-rich-text>
44
44
  </span>
@@ -47,7 +47,6 @@
47
47
  <span
48
48
  class="slds-truncate slds-var-m-right_xx-small slds-var-m-top_xxx-small facet__value-text facet__value_idle"
49
49
  title={formattedFacetValue}
50
- data-testid="facet__value"
51
50
  >
52
51
  {formattedFacetValue}
53
52
  </span>
@@ -44,11 +44,14 @@ export default class QuanticInsightInterface extends LightningElement {
44
44
  hasRendered = false;
45
45
  /** @type {boolean} */
46
46
  ariaLiveEventsBound = false;
47
+ /** @type {function} */
48
+ unsubscribeInsightInterface;
47
49
 
48
50
  /** @type {string} */
49
51
  analyticsOriginContext = 'InsightPanel';
50
52
 
51
53
  disconnectedCallback() {
54
+ this.unsubscribeInsightInterface?.();
52
55
  destroyEngine(this.engineId);
53
56
  if (this.ariaLiveEventsBound) {
54
57
  this.removeEventListener(
@@ -133,19 +136,36 @@ export default class QuanticInsightInterface extends LightningElement {
133
136
  if (this.initialized) {
134
137
  return;
135
138
  }
136
- this.dispatchEvent(
137
- new CustomEvent(`quantic__insightinterfaceinitialized`, {
138
- detail: {
139
- engineId: this.engineId,
140
- insightId: this.insightId,
141
- },
142
- bubbles: true,
143
- composed: true,
144
- })
139
+ const engine = getHeadlessBindings(this.engineId).engine;
140
+ this.insightInterface = CoveoHeadlessInsight.buildInsightInterface(engine);
141
+ this.unsubscribeInsightInterface = this.insightInterface.subscribe(() =>
142
+ this.updateInsightInterfaceState()
145
143
  );
146
- this.initialized = true;
147
144
  };
148
145
 
146
+ updateInsightInterfaceState() {
147
+ if (this.initialized) {
148
+ return;
149
+ }
150
+ this.isInsightInterfaceReady =
151
+ !this.insightInterface.state.loading &&
152
+ !!this.insightInterface.state.config;
153
+
154
+ if (this.isInsightInterfaceReady) {
155
+ this.dispatchEvent(
156
+ new CustomEvent(`quantic__insightinterfaceinitialized`, {
157
+ detail: {
158
+ engineId: this.engineId,
159
+ insightId: this.insightId,
160
+ },
161
+ bubbles: true,
162
+ composed: true,
163
+ })
164
+ );
165
+ this.initialized = true;
166
+ }
167
+ }
168
+
149
169
  /**
150
170
  * @returns {HTMLInputElement}
151
171
  */
@@ -5,7 +5,7 @@
5
5
  </template>
6
6
  <template lwc:else>
7
7
  <template lwc:if={isFacetEnabled}>
8
- <div data-test="facet-content">
8
+ <div data-testid="facet-content">
9
9
  <template if:true={showPlaceholder}>
10
10
  <c-quantic-placeholder
11
11
  variant="card"
@@ -35,6 +35,7 @@
35
35
  </lightning-button-icon>
36
36
  <template if:true={hasActiveValues}>
37
37
  <button
38
+ data-testid="clear-selection-button"
38
39
  class="facet__clear-filter slds-button slds-grid slds-grid_vertical-align-center slds-var-p-horizontal_x-small slds-m-top_small"
39
40
  onclick={clearSelections}
40
41
  title={clearFilterLabel}
@@ -53,11 +54,13 @@
53
54
  </template>
54
55
  <template if:false={isCollapsed}>
55
56
  <div
57
+ data-testid="facet__body"
56
58
  class="slds-has-dividers_around-space slds-var-m-top_medium"
57
59
  >
58
60
  <template if:true={withInput}>
59
61
  <div class="slds-p-horizontal_x-small">
60
62
  <form
63
+ data-testid="facet__search-form"
61
64
  onsubmit={onApply}
62
65
  class="facet__search-form slds-grid slds-gutters slds-var-p-bottom_small"
63
66
  >
@@ -15,7 +15,6 @@ import numberInputMinimum from '@salesforce/label/c.quantic_NumberInputMinimum';
15
15
  import {
16
16
  registerComponentForInit,
17
17
  initializeWithHeadless,
18
- getHeadlessBindings,
19
18
  registerToStore,
20
19
  getHeadlessBundle,
21
20
  getBueno,
@@ -34,6 +33,7 @@ import {LightningElement, track, api} from 'lwc';
34
33
  /** @typedef {import("coveo").NumericFacetValue} NumericFacetValue */
35
34
  /** @typedef {import("coveo").SearchStatus} SearchStatus */
36
35
  /** @typedef {import("coveo").SearchEngine} SearchEngine */
36
+ /** @typedef {import("coveo").InsightEngine} InsightEngine */
37
37
  /** @typedef {import("coveo").FacetConditionsManager} FacetConditionsManager */
38
38
  /** @typedef {import('../quanticUtils/facetDependenciesUtils').DependsOn} DependsOn */
39
39
  /**
@@ -223,6 +223,8 @@ export default class QuanticNumericFacet extends LightningElement {
223
223
  numericFacetConditionsManager;
224
224
  /** @type {FacetConditionsManager} */
225
225
  numericFilterConditionsManager;
226
+ /** @type {SearchEngine | InsightEngine} */
227
+ engine;
226
228
 
227
229
  /** @type {string} */
228
230
  start;
@@ -262,9 +264,10 @@ export default class QuanticNumericFacet extends LightningElement {
262
264
  }
263
265
 
264
266
  /**
265
- * @param {SearchEngine} engine
267
+ * @param {SearchEngine | InsightEngine} engine
266
268
  */
267
269
  initialize = (engine) => {
270
+ this.engine = engine;
268
271
  this.validateDependsOnProperty();
269
272
  this.headless = getHeadlessBundle(this.engineId);
270
273
  this.searchStatus = this.headless.buildSearchStatus(engine);
@@ -273,15 +276,11 @@ export default class QuanticNumericFacet extends LightningElement {
273
276
  );
274
277
 
275
278
  if (this.numberOfValues > 0) {
276
- this.initializeFacet(engine);
279
+ this.initializeFacet();
277
280
  }
278
281
  if (this.withInput) {
279
- this.initializeFilter(engine);
282
+ this.initializeFilter();
280
283
  }
281
- this.searchStatus = this.headless.buildSearchStatus(engine);
282
- this.unsubscribeSearchStatus = this.searchStatus.subscribe(() =>
283
- this.updateState()
284
- );
285
284
  registerToStore(this.engineId, Store.facetTypes.NUMERICFACETS, {
286
285
  label: this.label,
287
286
  facetId: this.facet?.state.facetId ?? this.field,
@@ -310,11 +309,8 @@ export default class QuanticNumericFacet extends LightningElement {
310
309
  }
311
310
  }
312
311
 
313
- /**
314
- * @param {import("coveo").SearchEngine} engine
315
- */
316
- initializeFacet(engine) {
317
- this.facet = this.headless.buildNumericFacet(engine, {
312
+ initializeFacet() {
313
+ this.facet = this.headless.buildNumericFacet(this.engine, {
318
314
  options: {
319
315
  field: this.field,
320
316
  generateAutomaticRanges: true,
@@ -327,17 +323,14 @@ export default class QuanticNumericFacet extends LightningElement {
327
323
  this.unsubscribe = this.facet.subscribe(() => this.updateState());
328
324
  if (this.dependsOn) {
329
325
  this.numericFacetConditionsManager = this.initFacetConditionManager(
330
- engine,
326
+ this.engine,
331
327
  this.facet.state?.facetId
332
328
  );
333
329
  }
334
330
  }
335
331
 
336
- /**
337
- * @param {import("coveo").SearchEngine} engine
338
- */
339
- initializeFilter(engine) {
340
- this.numericFilter = this.headless.buildNumericFilter(engine, {
332
+ initializeFilter() {
333
+ this.numericFilter = this.headless.buildNumericFilter(this.engine, {
341
334
  options: {
342
335
  field: this.field,
343
336
  facetId: this.facet?.state.facetId
@@ -350,7 +343,7 @@ export default class QuanticNumericFacet extends LightningElement {
350
343
  );
351
344
  if (this.dependsOn) {
352
345
  this.numericFilterConditionsManager = this.initFacetConditionManager(
353
- engine,
346
+ this.engine,
354
347
  this.numericFilter.state?.facetId
355
348
  );
356
349
  }
@@ -580,10 +573,9 @@ export default class QuanticNumericFacet extends LightningElement {
580
573
  }
581
574
 
582
575
  if (this.numberOfValues > 0) {
583
- const engine = getHeadlessBindings(this.engineId).engine;
584
- engine.dispatch(
576
+ this.engine.dispatch(
585
577
  this.headless
586
- .loadNumericFacetSetActions(engine)
578
+ .loadNumericFacetSetActions(this.engine)
587
579
  .deselectAllNumericFacetValues(this.facet.state.facetId)
588
580
  );
589
581
  }
@@ -11,7 +11,7 @@
11
11
  </button>
12
12
  </template>
13
13
  <template if:false={loading}>
14
- <lightning-button-icon-stateful onclick={handleClick} aria-label={displayedLabel} variant="border-filled"
14
+ <lightning-button-icon-stateful data-testid="result-action-button" onclick={handleClick} aria-label={displayedLabel} variant="border-filled"
15
15
  class={resultActionOrderClasses} icon-name={displayedIcon} selected={_selected}>
16
16
  </lightning-button-icon-stateful>
17
17
  </template>
@@ -6,7 +6,7 @@
6
6
  <template lwc:else>
7
7
  <slot><!-- Timeframes --></slot>
8
8
  <template lwc:if={isFacetEnabled}>
9
- <div data-test="facet-content">
9
+ <div data-testid="facet-content">
10
10
  <template if:true={showPlaceholder}>
11
11
  <c-quantic-placeholder
12
12
  variant="card"
@@ -34,6 +34,7 @@
34
34
 
35
35
  <template if:true={hasActiveValues}>
36
36
  <button
37
+ data-testid="clear-selection-button"
37
38
  class="facet__clear-filter slds-button slds-grid slds-grid_vertical-align-center slds-p-horizontal_x-small slds-m-top_small"
38
39
  onclick={clearSelections}
39
40
  title={clearFilterLabel}
@@ -52,95 +53,97 @@
52
53
  </template>
53
54
 
54
55
  <template if:false={isCollapsed}>
55
- <template if:true={shouldDisplayDatePicker}>
56
- <div
57
- class="slds-grid slds-gutters slds-grid_vertical slds-p-around_x-small"
58
- >
59
- <form data-testid="facet__date-picker" onsubmit={handleApply}>
60
- <div class="slds-col slds-grid slds-gutters">
61
- <div
62
- class="slds-col slds-size_1-of-5 slds-var-p-top_xx-small slds-var-m-top_xxx-small"
63
- >
64
- <span class="timeframe-facet__input-label"
65
- >{labels.startLabel}</span
66
- >
67
- </div>
68
- <div class="slds-col slds-size_4-of-5">
69
- <lightning-input
70
- type="date"
71
- class="timeframe-facet__start-input"
72
- label="Start"
73
- variant="label-hidden"
74
- date-style="short"
75
- min="1401-01-01"
76
- placeholder={datepickerFormat}
77
- value={startDateNoTime}
78
- onchange={handleStartDateChange}
79
- onblur={handleStartDateBlur}
56
+ <div data-testid="facet__body">
57
+ <template if:true={shouldDisplayDatePicker}>
58
+ <div
59
+ class="slds-grid slds-gutters slds-grid_vertical slds-p-around_x-small"
60
+ >
61
+ <form data-testid="facet__date-picker" onsubmit={handleApply}>
62
+ <div class="slds-col slds-grid slds-gutters">
63
+ <div
64
+ class="slds-col slds-size_1-of-5 slds-var-p-top_xx-small slds-var-m-top_xxx-small"
80
65
  >
81
- </lightning-input>
66
+ <span class="timeframe-facet__input-label"
67
+ >{labels.startLabel}</span
68
+ >
69
+ </div>
70
+ <div class="slds-col slds-size_4-of-5">
71
+ <lightning-input
72
+ type="date"
73
+ class="timeframe-facet__start-input"
74
+ label="Start"
75
+ variant="label-hidden"
76
+ date-style="short"
77
+ min="1401-01-01"
78
+ placeholder={datepickerFormat}
79
+ value={startDateNoTime}
80
+ onchange={handleStartDateChange}
81
+ onblur={handleStartDateBlur}
82
+ >
83
+ </lightning-input>
84
+ </div>
82
85
  </div>
83
- </div>
84
- <div
85
- class="slds-col slds-grid slds-gutters slds-p-top_x-small"
86
- >
87
86
  <div
88
- class="slds-col slds-size_1-of-5 slds-var-p-top_xx-small slds-var-m-top_xxx-small"
87
+ class="slds-col slds-grid slds-gutters slds-p-top_x-small"
89
88
  >
90
- <span class="timeframe-facet__input-label"
91
- >{labels.endLabel}</span
89
+ <div
90
+ class="slds-col slds-size_1-of-5 slds-var-p-top_xx-small slds-var-m-top_xxx-small"
92
91
  >
92
+ <span class="timeframe-facet__input-label"
93
+ >{labels.endLabel}</span
94
+ >
95
+ </div>
96
+ <div class="slds-col slds-size_4-of-5">
97
+ <lightning-input
98
+ type="date"
99
+ class="timeframe-facet__end-input"
100
+ label="End"
101
+ variant="label-hidden"
102
+ date-style="short"
103
+ placeholder={datepickerFormat}
104
+ value={endDateNoTime}
105
+ onchange={handleEndDateChange}
106
+ onblur={handleEndDateBlur}
107
+ >
108
+ </lightning-input>
109
+ </div>
93
110
  </div>
94
- <div class="slds-col slds-size_4-of-5">
95
- <lightning-input
96
- type="date"
97
- class="timeframe-facet__end-input"
98
- label="End"
99
- variant="label-hidden"
100
- date-style="short"
101
- placeholder={datepickerFormat}
102
- value={endDateNoTime}
103
- onchange={handleEndDateChange}
104
- onblur={handleEndDateBlur}
111
+ <div class="slds-col slds-p-top_x-small">
112
+ <button
113
+ class="slds-button slds-button_neutral slds-button_stretch timeframe-facet__apply"
114
+ onblur={resetRangeValidation}
115
+ aria-label={ariaLabelValue}
105
116
  >
106
- </lightning-input>
117
+ {labels.apply}
118
+ </button>
107
119
  </div>
108
- </div>
109
- <div class="slds-col slds-p-top_x-small">
110
- <button
111
- class="slds-button slds-button_neutral slds-button_stretch timeframe-facet__apply"
112
- onblur={resetRangeValidation}
113
- aria-label={ariaLabelValue}
114
- >
115
- {labels.apply}
116
- </button>
117
- </div>
118
- </form>
119
- </div>
120
- </template>
121
-
122
- <template if:true={showValues}>
123
- <fieldset>
124
- <legend class="slds-assistive-text">{field}</legend>
125
- <ul
126
- class="slds-has-dividers_around-space slds-m-top_medium"
127
- >
128
- <template for:each={formattedValues} for:item="v">
129
- <li class="slds-grid" key={v.key}>
130
- <c-quantic-facet-value
131
- item={v}
132
- is-checked={v.selected}
133
- onquantic__selectvalue={onSelectValue}
134
- formatting-function={formatFacetValue}
135
- display-as-link
136
- is-range-facet
137
- >
138
- </c-quantic-facet-value>
139
- </li>
140
- </template>
141
- </ul>
142
- </fieldset>
143
- </template>
120
+ </form>
121
+ </div>
122
+ </template>
123
+
124
+ <template if:true={showValues}>
125
+ <fieldset>
126
+ <legend class="slds-assistive-text">{field}</legend>
127
+ <ul
128
+ class="slds-has-dividers_around-space slds-m-top_medium"
129
+ >
130
+ <template for:each={formattedValues} for:item="v">
131
+ <li class="slds-grid" key={v.key}>
132
+ <c-quantic-facet-value
133
+ item={v}
134
+ is-checked={v.selected}
135
+ onquantic__selectvalue={onSelectValue}
136
+ formatting-function={formatFacetValue}
137
+ display-as-link
138
+ is-range-facet
139
+ >
140
+ </c-quantic-facet-value>
141
+ </li>
142
+ </template>
143
+ </ul>
144
+ </fieldset>
145
+ </template>
146
+ </div>
144
147
  </template>
145
148
  </c-quantic-card-container>
146
149
  </div>
@@ -7,7 +7,6 @@ import expandFacet from '@salesforce/label/c.quantic_ExpandFacet';
7
7
  import startLabel from '@salesforce/label/c.quantic_StartLabel';
8
8
  import timeframeInputApply from '@salesforce/label/c.quantic_TimeframeInputApply';
9
9
  import {
10
- getHeadlessBindings,
11
10
  getHeadlessBundle,
12
11
  initializeWithHeadless,
13
12
  registerComponentForInit,
@@ -25,6 +24,7 @@ import {
25
24
  import {api, LightningElement, track} from 'lwc';
26
25
 
27
26
  /** @typedef {import("coveo").SearchEngine} SearchEngine */
27
+ /** @typedef {import("coveo").InsightEngine} InsightEngine */
28
28
  /** @typedef {import("coveo").SearchStatus} SearchStatus */
29
29
  /** @typedef {import("coveo").DateFacet} DateFacet */
30
30
  /** @typedef {import("coveo").DateFacetState} DateFacetState */
@@ -214,6 +214,8 @@ export default class QuanticTimeframeFacet extends LightningElement {
214
214
  dateFacetConditionsManager;
215
215
  /** @type {FacetConditionsManager} */
216
216
  dateFilterConditionsManager;
217
+ /** @type {SearchEngine | InsightEngine} */
218
+ engine;
217
219
 
218
220
  _isCollapsed = false;
219
221
  _showValues = true;
@@ -257,15 +259,14 @@ export default class QuanticTimeframeFacet extends LightningElement {
257
259
  * Gets whether to show the facet.
258
260
  */
259
261
  get showFacet() {
260
- const facetIsActivated =
261
- this.hasActiveValues || !!this.dateFilterState?.range;
262
262
  const canRefineWithCustomRange =
263
263
  this.hasResults && this.shouldDisplayDatePicker;
264
264
  const canRefineWithTimeframes =
265
265
  this.hasResults && this.formattedValues.length > 0;
266
-
267
266
  return (
268
- facetIsActivated || canRefineWithCustomRange || canRefineWithTimeframes
267
+ this.hasActiveValues ||
268
+ canRefineWithCustomRange ||
269
+ canRefineWithTimeframes
269
270
  );
270
271
  }
271
272
 
@@ -333,7 +334,7 @@ export default class QuanticTimeframeFacet extends LightningElement {
333
334
  get currentValues() {
334
335
  return this.timeframes.map((timeframe) => {
335
336
  return timeframe.period === 'past'
336
- ? getHeadlessBundle(this.engineId).buildDateRange({
337
+ ? this.headless.buildDateRange({
337
338
  start: {
338
339
  period: timeframe.period,
339
340
  unit: timeframe.unit,
@@ -341,7 +342,7 @@ export default class QuanticTimeframeFacet extends LightningElement {
341
342
  },
342
343
  end: {period: 'now'},
343
344
  })
344
- : getHeadlessBundle(this.engineId).buildDateRange({
345
+ : this.headless.buildDateRange({
345
346
  start: {period: 'now'},
346
347
  end: {
347
348
  period: timeframe.period,
@@ -386,10 +387,7 @@ export default class QuanticTimeframeFacet extends LightningElement {
386
387
  }
387
388
 
388
389
  get hasActiveValues() {
389
- return (
390
- this.formattedValues.some((v) => v.selected) ||
391
- !!this.dateFilterState?.range
392
- );
390
+ return this.facetState?.hasActiveValues || !!this.dateFilterState?.range;
393
391
  }
394
392
 
395
393
  get clearFilterLabel() {
@@ -435,11 +433,14 @@ export default class QuanticTimeframeFacet extends LightningElement {
435
433
  * @param {SearchEngine} engine
436
434
  */
437
435
  initialize = (engine) => {
436
+ this.engine = engine;
438
437
  this.validateDependsOnProperty();
439
438
  this.headless = getHeadlessBundle(this.engineId);
440
439
  this.initializeSearchStatusController(engine);
441
440
  this.initializeFacetController(engine);
442
- this.initializeDateFilterController(engine);
441
+ if (this.withDatePicker) {
442
+ this.initializeDateFilterController(engine);
443
+ }
443
444
  registerToStore(this.engineId, Store.facetTypes.DATEFACETS, {
444
445
  label: this.label,
445
446
  facetId: this.facet.state.facetId,
@@ -798,15 +799,14 @@ export default class QuanticTimeframeFacet extends LightningElement {
798
799
  }
799
800
 
800
801
  updateRangeInHeadless(startDate, endDate) {
801
- const engine = getHeadlessBindings(this.engineId).engine;
802
- engine.dispatch(
803
- getHeadlessBundle(this.engineId)
804
- .loadDateFacetSetActions(engine)
802
+ this.engine.dispatch(
803
+ this.headless
804
+ .loadDateFacetSetActions(this.engine)
805
805
  .deselectAllDateFacetValues(this.facet.state.facetId)
806
806
  );
807
807
 
808
808
  this.dateFilter.setRange(
809
- getHeadlessBundle(this.engineId).buildDateRange({
809
+ this.headless.buildDateRange({
810
810
  start: DateUtils.toLocalSearchApiDate(startDate),
811
811
  end: DateUtils.toLocalSearchApiDate(endDate),
812
812
  })