@searchspring/snap-controller 0.39.2 → 0.40.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.
@@ -1,8 +1,8 @@
1
1
  import deepmerge from 'deepmerge';
2
- import { BeaconType, BeaconCategory } from '@searchspring/snap-tracker';
2
+ import { BeaconType, BeaconCategory, ProfilePlacement } from '@searchspring/snap-tracker';
3
+ import { ErrorType } from '@searchspring/snap-store-mobx';
3
4
  import { AbstractController } from '../Abstract/AbstractController';
4
5
  import { ControllerTypes } from '../types';
5
- import { ErrorType } from '@searchspring/snap-store-mobx';
6
6
  const defaultConfig = {
7
7
  id: 'recommend',
8
8
  tag: '',
@@ -20,13 +20,119 @@ export class RecommendationController extends AbstractController {
20
20
  render: undefined,
21
21
  product: {},
22
22
  };
23
- this.track = {
24
- product: {
25
- click: (e, result) => {
26
- if (!this.store.profile.tag || !result || !this.events.click)
23
+ this.track = (() => {
24
+ const getSeed = () => {
25
+ let skus = [];
26
+ switch (this.store.profile.placement) {
27
+ case ProfilePlacement.PRODUCTPAGE:
28
+ if (this.config.globals.product) {
29
+ skus = [this.config.globals.product];
30
+ }
31
+ break;
32
+ case ProfilePlacement.BASKETPAGE:
33
+ skus = this.tracker.cookies.cart.get(); // this is an array
34
+ break;
35
+ default:
36
+ return;
37
+ }
38
+ if (skus.length) {
39
+ return skus.map((sku) => ({
40
+ sku,
41
+ }));
42
+ }
43
+ };
44
+ return {
45
+ product: {
46
+ click: (e, result) => {
47
+ if (!this.store.profile.tag || !result || !this.events.click)
48
+ return;
49
+ const payload = {
50
+ type: BeaconType.PROFILE_PRODUCT_CLICK,
51
+ category: BeaconCategory.RECOMMENDATIONS,
52
+ context: this.config.globals.siteId ? { website: { trackingCode: this.config.globals.siteId } } : undefined,
53
+ event: {
54
+ context: {
55
+ action: 'navigate',
56
+ placement: this.store.profile.placement,
57
+ tag: this.store.profile.tag,
58
+ type: 'product-recommendation',
59
+ },
60
+ product: {
61
+ id: result.id,
62
+ mappings: {
63
+ core: result.mappings.core,
64
+ },
65
+ seed: getSeed(),
66
+ },
67
+ },
68
+ pid: this.events.click.id,
69
+ };
70
+ const event = this.tracker.track.event(payload);
71
+ this.eventManager.fire('track.product.click', { controller: this, event: e, result, trackEvent: event });
72
+ return event;
73
+ },
74
+ impression: (result) => {
75
+ if (!this.store.profile.tag || !result || !this.events.impression || (this.events.product && this.events.product[result.id]?.impression))
76
+ return;
77
+ const payload = {
78
+ type: BeaconType.PROFILE_PRODUCT_IMPRESSION,
79
+ category: BeaconCategory.RECOMMENDATIONS,
80
+ context: this.config.globals.siteId ? { website: { trackingCode: this.config.globals.siteId } } : undefined,
81
+ event: {
82
+ context: {
83
+ placement: this.store.profile.placement,
84
+ tag: this.store.profile.tag,
85
+ type: 'product-recommendation',
86
+ },
87
+ product: {
88
+ id: result.id,
89
+ mappings: {
90
+ core: result.mappings.core,
91
+ },
92
+ seed: getSeed(),
93
+ },
94
+ },
95
+ pid: this.events.impression.id,
96
+ };
97
+ this.events.product[result.id] = this.events.product[result.id] || {};
98
+ const event = (this.events.product[result.id].impression = this.tracker.track.event(payload));
99
+ this.eventManager.fire('track.product.impression', { controller: this, result, trackEvent: event });
100
+ return event;
101
+ },
102
+ render: (result) => {
103
+ if (!this.store.profile.tag || !result || !this.events.render || this.events.product[result.id]?.render)
104
+ return;
105
+ const payload = {
106
+ type: BeaconType.PROFILE_PRODUCT_RENDER,
107
+ category: BeaconCategory.RECOMMENDATIONS,
108
+ context: this.config.globals.siteId ? { website: { trackingCode: this.config.globals.siteId } } : undefined,
109
+ event: {
110
+ context: {
111
+ placement: this.store.profile.placement,
112
+ tag: this.store.profile.tag,
113
+ type: 'product-recommendation',
114
+ },
115
+ product: {
116
+ id: result.id,
117
+ mappings: {
118
+ core: result.mappings.core,
119
+ },
120
+ seed: getSeed(),
121
+ },
122
+ },
123
+ pid: this.events.render.id,
124
+ };
125
+ this.events.product[result.id] = this.events.product[result.id] || {};
126
+ const event = (this.events.product[result.id].render = this.tracker.track.event(payload));
127
+ this.eventManager.fire('track.product.render', { controller: this, result, trackEvent: event });
128
+ return event;
129
+ },
130
+ },
131
+ click: (e) => {
132
+ if (!this.store.profile.tag)
27
133
  return;
28
- const payload = {
29
- type: BeaconType.PROFILE_PRODUCT_CLICK,
134
+ const event = this.tracker.track.event({
135
+ type: BeaconType.PROFILE_CLICK,
30
136
  category: BeaconCategory.RECOMMENDATIONS,
31
137
  context: this.config.globals.siteId ? { website: { trackingCode: this.config.globals.siteId } } : undefined,
32
138
  event: {
@@ -36,25 +142,24 @@ export class RecommendationController extends AbstractController {
36
142
  tag: this.store.profile.tag,
37
143
  type: 'product-recommendation',
38
144
  },
39
- product: {
40
- id: result.id,
41
- mappings: {
42
- core: result.mappings.core,
43
- },
44
- seed: this.config.globals.seed,
145
+ profile: {
146
+ tag: this.store.profile.tag,
147
+ placement: this.store.profile.placement,
148
+ threshold: this.store.profile.display.threshold,
149
+ templateId: this.store.profile.display.template.uuid,
150
+ seed: getSeed(),
45
151
  },
46
152
  },
47
- pid: this.events.click.id,
48
- };
49
- const event = this.tracker.track.event(payload);
50
- this.eventManager.fire('track.product.click', { controller: this, event: e, result, trackEvent: event });
153
+ });
154
+ this.events.click = event;
155
+ this.eventManager.fire('track.click', { controller: this, event: e, trackEvent: event });
51
156
  return event;
52
157
  },
53
- impression: (result) => {
54
- if (!this.store.profile.tag || !result || !this.events.impression || (this.events.product && this.events.product[result.id]?.impression))
158
+ impression: () => {
159
+ if (!this.store.profile.tag || this.events.impression)
55
160
  return;
56
- const payload = {
57
- type: BeaconType.PROFILE_PRODUCT_IMPRESSION,
161
+ const event = this.tracker.track.event({
162
+ type: BeaconType.PROFILE_IMPRESSION,
58
163
  category: BeaconCategory.RECOMMENDATIONS,
59
164
  context: this.config.globals.siteId ? { website: { trackingCode: this.config.globals.siteId } } : undefined,
60
165
  event: {
@@ -63,26 +168,24 @@ export class RecommendationController extends AbstractController {
63
168
  tag: this.store.profile.tag,
64
169
  type: 'product-recommendation',
65
170
  },
66
- product: {
67
- id: result.id,
68
- mappings: {
69
- core: result.mappings.core,
70
- },
71
- seed: this.config.globals.seed,
171
+ profile: {
172
+ tag: this.store.profile.tag,
173
+ placement: this.store.profile.placement,
174
+ threshold: this.store.profile.display.threshold,
175
+ templateId: this.store.profile.display.template.uuid,
176
+ seed: getSeed(),
72
177
  },
73
178
  },
74
- pid: this.events.impression.id,
75
- };
76
- this.events.product[result.id] = this.events.product[result.id] || {};
77
- const event = (this.events.product[result.id].impression = this.tracker.track.event(payload));
78
- this.eventManager.fire('track.product.impression', { controller: this, result, trackEvent: event });
179
+ });
180
+ this.events.impression = event;
181
+ this.eventManager.fire('track.impression', { controller: this, trackEvent: event });
79
182
  return event;
80
183
  },
81
- render: (result) => {
82
- if (!this.store.profile.tag || !result || !this.events.render || this.events.product[result.id]?.render)
184
+ render: () => {
185
+ if (!this.store.profile.tag || this.events.render)
83
186
  return;
84
- const payload = {
85
- type: BeaconType.PROFILE_PRODUCT_RENDER,
187
+ const event = this.tracker.track.event({
188
+ type: BeaconType.PROFILE_RENDER,
86
189
  category: BeaconCategory.RECOMMENDATIONS,
87
190
  context: this.config.globals.siteId ? { website: { trackingCode: this.config.globals.siteId } } : undefined,
88
191
  event: {
@@ -91,101 +194,23 @@ export class RecommendationController extends AbstractController {
91
194
  tag: this.store.profile.tag,
92
195
  type: 'product-recommendation',
93
196
  },
94
- product: {
95
- id: result.id,
96
- mappings: {
97
- core: result.mappings.core,
98
- },
99
- seed: this.config.globals.seed,
197
+ profile: {
198
+ tag: this.store.profile.tag,
199
+ placement: this.store.profile.placement,
200
+ threshold: this.store.profile.display.threshold,
201
+ templateId: this.store.profile.display.template.uuid,
202
+ seed: getSeed(),
100
203
  },
101
204
  },
102
- pid: this.events.render.id,
103
- };
104
- this.events.product[result.id] = this.events.product[result.id] || {};
105
- const event = (this.events.product[result.id].render = this.tracker.track.event(payload));
106
- this.eventManager.fire('track.product.render', { controller: this, result, trackEvent: event });
205
+ });
206
+ this.events.render = event;
207
+ // track results render
208
+ this.store.results.forEach((result) => this.track.product.render(result));
209
+ this.eventManager.fire('track.render', { controller: this, trackEvent: event });
107
210
  return event;
108
211
  },
109
- },
110
- click: (e) => {
111
- if (!this.store.profile.tag)
112
- return;
113
- const event = this.tracker.track.event({
114
- type: BeaconType.PROFILE_CLICK,
115
- category: BeaconCategory.RECOMMENDATIONS,
116
- context: this.config.globals.siteId ? { website: { trackingCode: this.config.globals.siteId } } : undefined,
117
- event: {
118
- context: {
119
- action: 'navigate',
120
- placement: this.store.profile.placement,
121
- tag: this.store.profile.tag,
122
- type: 'product-recommendation',
123
- },
124
- profile: {
125
- tag: this.store.profile.tag,
126
- placement: this.store.profile.placement,
127
- threshold: this.store.profile.display.threshold,
128
- templateId: this.store.profile.display.template.uuid,
129
- },
130
- },
131
- });
132
- this.events.click = event;
133
- this.eventManager.fire('track.click', { controller: this, event: e, trackEvent: event });
134
- return event;
135
- },
136
- impression: () => {
137
- if (!this.store.profile.tag || this.events.impression)
138
- return;
139
- const event = this.tracker.track.event({
140
- type: BeaconType.PROFILE_IMPRESSION,
141
- category: BeaconCategory.RECOMMENDATIONS,
142
- context: this.config.globals.siteId ? { website: { trackingCode: this.config.globals.siteId } } : undefined,
143
- event: {
144
- context: {
145
- placement: this.store.profile.placement,
146
- tag: this.store.profile.tag,
147
- type: 'product-recommendation',
148
- },
149
- profile: {
150
- tag: this.store.profile.tag,
151
- placement: this.store.profile.placement,
152
- threshold: this.store.profile.display.threshold,
153
- templateId: this.store.profile.display.template.uuid,
154
- },
155
- },
156
- });
157
- this.events.impression = event;
158
- this.eventManager.fire('track.impression', { controller: this, trackEvent: event });
159
- return event;
160
- },
161
- render: () => {
162
- if (!this.store.profile.tag || this.events.render)
163
- return;
164
- const event = this.tracker.track.event({
165
- type: BeaconType.PROFILE_RENDER,
166
- category: BeaconCategory.RECOMMENDATIONS,
167
- context: this.config.globals.siteId ? { website: { trackingCode: this.config.globals.siteId } } : undefined,
168
- event: {
169
- context: {
170
- placement: this.store.profile.placement,
171
- tag: this.store.profile.tag,
172
- type: 'product-recommendation',
173
- },
174
- profile: {
175
- tag: this.store.profile.tag,
176
- placement: this.store.profile.placement,
177
- threshold: this.store.profile.display.threshold,
178
- templateId: this.store.profile.display.template.uuid,
179
- },
180
- },
181
- });
182
- this.events.render = event;
183
- // track results render
184
- this.store.results.forEach((result) => this.track.product.render(result));
185
- this.eventManager.fire('track.render', { controller: this, trackEvent: event });
186
- return event;
187
- },
188
- };
212
+ };
213
+ })();
189
214
  this.search = async () => {
190
215
  if (!this.initialized) {
191
216
  await this.init();
@@ -1 +1 @@
1
- {"version":3,"file":"SearchController.d.ts","sourceRoot":"","sources":["../../../src/Search/SearchController.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AACpE,OAAO,EAAE,YAAY,EAA0B,MAAM,+BAA+B,CAAC;AAErF,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,KAAK,EAAE,sBAAsB,EAAkD,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE7I,OAAO,KAAK,EAAE,kBAAkB,EAA2E,MAAM,2BAA2B,CAAC;AAqB7I,aAAK,kBAAkB,GAAG;IACzB,OAAO,EAAE;QACR,KAAK,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,KAAK,WAAW,GAAG,SAAS,CAAC;KAC/D,CAAC;CACF,CAAC;AAEF,qBAAa,gBAAiB,SAAQ,kBAAkB;IAChD,IAAI,kBAA0B;IAC7B,KAAK,EAAE,WAAW,CAAC;IACnB,MAAM,EAAE,sBAAsB,CAAC;IACvC,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,CAAC,eAAe,CAAwC;gBAG9D,MAAM,EAAE,sBAAsB,EAC9B,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,kBAAkB,EAC1F,OAAO,CAAC,EAAE,gBAAgB;IA2F3B,KAAK,EAAE,kBAAkB,CA+BvB;IAEF,IAAI,MAAM,IAAI,kBAAkB,CAgD/B;IAED,MAAM,QAAa,QAAQ,IAAI,CAAC,CAqO9B;CACF;AAED,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,kBAAkB,GAAG,kBAAkB,CAiBxF"}
1
+ {"version":3,"file":"SearchController.d.ts","sourceRoot":"","sources":["../../../src/Search/SearchController.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AACpE,OAAO,EAAE,YAAY,EAA0B,MAAM,+BAA+B,CAAC;AAErF,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,KAAK,EAAE,sBAAsB,EAAkD,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE7I,OAAO,KAAK,EAAE,kBAAkB,EAA2E,MAAM,2BAA2B,CAAC;AAsB7I,aAAK,kBAAkB,GAAG;IACzB,OAAO,EAAE;QACR,KAAK,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,KAAK,WAAW,GAAG,SAAS,CAAC;KAC/D,CAAC;CACF,CAAC;AAEF,qBAAa,gBAAiB,SAAQ,kBAAkB;IAChD,IAAI,kBAA0B;IAC7B,KAAK,EAAE,WAAW,CAAC;IACnB,MAAM,EAAE,sBAAsB,CAAC;IACvC,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,CAAC,eAAe,CAAwC;gBAG9D,MAAM,EAAE,sBAAsB,EAC9B,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,kBAAkB,EAC1F,OAAO,CAAC,EAAE,gBAAgB;IA6F3B,KAAK,EAAE,kBAAkB,CA+BvB;IAEF,IAAI,MAAM,IAAI,kBAAkB,CAgD/B;IAED,MAAM,QAAa,QAAQ,IAAI,CAAC,CAmO9B;CACF;AAED,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,kBAAkB,GAAG,kBAAkB,CAiBxF"}
@@ -4,6 +4,7 @@ import { StorageStore, StorageType, ErrorType } from '@searchspring/snap-store-m
4
4
  import { getSearchParams } from '../utils/getParams';
5
5
  import { ControllerTypes } from '../types';
6
6
  const HEIGHT_CHECK_INTERVAL = 50;
7
+ const API_LIMIT = 500;
7
8
  const defaultConfig = {
8
9
  id: 'search',
9
10
  globals: {},
@@ -57,6 +58,10 @@ export class SearchController extends AbstractController {
57
58
  await this.init();
58
59
  }
59
60
  const params = this.params;
61
+ if (this.params.search?.query?.string && this.params.search?.query?.string.length) {
62
+ // save it to the history store
63
+ this.store.history.save(this.params.search.query.string);
64
+ }
60
65
  try {
61
66
  try {
62
67
  await this.eventManager.fire('beforeSearch', {
@@ -85,65 +90,59 @@ export class SearchController extends AbstractController {
85
90
  let response;
86
91
  // infinite functionality
87
92
  // if params.page > 1 and infinite setting exists we should append results
88
- if (this.config.settings?.infinite && params.pagination?.page > 1) {
89
- const preventBackfill = this.config.settings.infinite?.backfill && !this.store.results.length && params.pagination?.page > this.config.settings.infinite.backfill;
90
- const dontBackfill = !this.config.settings.infinite?.backfill && !this.store.results.length && params.pagination?.page > 1;
91
- //if the page is higher than the backfill setting redirect back to page 1
93
+ if (this.config.settings?.infinite && params.pagination?.page && params.pagination.page > 1) {
94
+ const preventBackfill = this.config.settings.infinite?.backfill && !this.store.results.length && params.pagination.page > this.config.settings.infinite.backfill;
95
+ const dontBackfill = !this.config.settings.infinite?.backfill && !this.store.results.length;
96
+ // if the page is higher than the backfill setting redirect back to page 1
92
97
  if (preventBackfill || dontBackfill) {
93
98
  this.storage.set('scrollMap', {});
94
99
  this.urlManager.set('page', 1).go();
95
100
  return;
96
101
  }
97
- // if no results fetch results...
98
- let previousResults = this.previousResults;
99
102
  const backfills = [];
100
103
  let pageSize = params.pagination?.pageSize || this.store.pagination.pageSize || this.store.pagination.defaultPageSize;
101
- if (this.config.settings?.infinite.backfill && !previousResults.length) {
102
- // figure out how many pages of results to backfill and wait on all responses
104
+ // if no results fetch results...
105
+ if (this.config.settings?.infinite.backfill && !this.previousResults.length) {
103
106
  if (!pageSize) {
104
- //unfortunatly we need to fetch meta to know the default pagesize before we can continue.
107
+ // pageSize is unknown - need to fetch meta to know defaultPageSize before we can continue
105
108
  const meta = await this.client.meta();
106
109
  pageSize = meta.pagination?.defaultPageSize;
107
110
  }
108
- let pagesNeeded1 = params.pagination?.page && params.pagination?.page > this.config.settings?.infinite.backfill
111
+ // restricting pageSize to the limit
112
+ pageSize = pageSize > API_LIMIT ? API_LIMIT : pageSize;
113
+ const pagesNeeded = params.pagination?.page && params.pagination?.page > this.config.settings?.infinite.backfill
109
114
  ? this.config.settings?.infinite.backfill
110
115
  : params.pagination?.page;
111
- let totalResultsNeeded = pageSize * (pagesNeeded1 || 1);
112
- const apiLimit = 500;
113
- // our search api is limited to a certain amount per request.
114
- //so we will need to make more than one request if totalresultsneeded is greater.
115
- if (totalResultsNeeded < apiLimit) {
116
- const backfillParams = deepmerge({ ...params }, { pagination: { pageSize: totalResultsNeeded, page: 1 } });
116
+ // figure out how many pages of results to backfill and wait on all responses
117
+ const { size: backFillPageSize, pages: backFillPages } = backFillSize(pagesNeeded, pageSize);
118
+ for (let i = 1; i <= backFillPages; i++) {
119
+ const backfillParams = deepmerge({ ...params }, { pagination: { pageSize: backFillPageSize, page: i } });
117
120
  backfills.push(this.client.search(backfillParams));
118
121
  }
119
- else {
120
- //how many pages are needed?
121
- let pagesNeeded = Math.ceil(totalResultsNeeded / apiLimit);
122
- // we dont want to get the full apiLimit # of results on the last page, so lets find out how many are left.
123
- let lastPageCount = apiLimit - (pagesNeeded * apiLimit - totalResultsNeeded);
124
- for (let i = 1; i <= pagesNeeded; i++) {
125
- const backfillParams = deepmerge({ ...params }, { pagination: { pageSize: i < pagesNeeded ? apiLimit : lastPageCount, page: i } });
126
- backfills.push(this.client.search(backfillParams));
127
- }
128
- }
129
122
  }
130
- //infinite backfill and prev results
131
- // use the previous results and only make request for new result
123
+ // infinite backfill results
132
124
  if (backfills && backfills.length) {
125
+ // array to hold all results from backfill responses
133
126
  let backfillResults = [];
134
127
  const backfillResponses = await Promise.all(backfills);
135
- backfillResponses.map(([Bmeta, Bresponse]) => {
128
+ backfillResponses.map(([metaBackfill, responseBackfill]) => {
136
129
  if (!meta) {
137
- meta = Bmeta;
130
+ meta = metaBackfill;
138
131
  }
139
132
  if (!response) {
140
- response = Bresponse;
141
- backfillResults = response.results;
133
+ response = responseBackfill;
142
134
  }
143
- else {
144
- backfillResults = backfillResults.concat(Bresponse.results);
135
+ // push results to array
136
+ if (responseBackfill.results) {
137
+ backfillResults.push(...responseBackfill.results);
145
138
  }
146
139
  });
140
+ // overwrite pagination params to expected state
141
+ response.pagination.pageSize = pageSize;
142
+ response.pagination.totalPages = Math.ceil(response.pagination.totalResults / response.pagination.pageSize);
143
+ response.pagination.page = params.pagination?.page;
144
+ // set the response results with results from backfill responses
145
+ response.results = backfillResults;
147
146
  if (!response.meta) {
148
147
  /**
149
148
  * MockClient will overwrite the client search() method and use
@@ -152,12 +151,6 @@ export class SearchController extends AbstractController {
152
151
  // @ts-ignore
153
152
  response.meta = meta;
154
153
  }
155
- //we need to overwrite the pagination params so the ui doesnt get confused.
156
- response.pagination.pageSize = pageSize;
157
- response.pagination.totalPages = Math.ceil(response.pagination.totalResults / response.pagination.pageSize);
158
- response.pagination.page = params.pagination?.page;
159
- //set the response results after all backfill promises are resolved.
160
- response.results = backfillResults;
161
154
  }
162
155
  else {
163
156
  // infinite with no backfills.
@@ -172,7 +165,7 @@ export class SearchController extends AbstractController {
172
165
  response.meta = meta;
173
166
  }
174
167
  //append new results to previous results
175
- response.results = [...previousResults, ...(response.results || [])];
168
+ response.results = [...this.previousResults, ...(response.results || [])];
176
169
  }
177
170
  }
178
171
  else {
@@ -293,10 +286,12 @@ export class SearchController extends AbstractController {
293
286
  window.location.replace(redirectURL);
294
287
  return false;
295
288
  }
289
+ const nonBackgroundFilters = search?.request?.filters?.filter((filter) => !filter.background);
296
290
  if (config?.settings?.redirects?.singleResult &&
297
291
  search?.response?.search?.query &&
298
292
  search?.response?.pagination?.totalResults === 1 &&
299
- !search?.response?.filters?.length) {
293
+ !nonBackgroundFilters?.length &&
294
+ !search.controller.previousResults.length) {
300
295
  window.location.replace(search?.response.results[0].mappings.core.url);
301
296
  return false;
302
297
  }
@@ -392,3 +387,10 @@ export function getStorableRequestParams(request) {
392
387
  },
393
388
  };
394
389
  }
390
+ function backFillSize(pages, pageSize) {
391
+ const totalResults = pages * pageSize;
392
+ let numPages = Math.ceil(totalResults / API_LIMIT);
393
+ while (totalResults % numPages)
394
+ numPages++;
395
+ return { size: totalResults / numPages, pages: numPages };
396
+ }
@@ -6,6 +6,7 @@ import type { Tracker, ProductViewEvent } from '@searchspring/snap-tracker';
6
6
  import type { Profiler } from '@searchspring/snap-profiler';
7
7
  import type { UrlManager } from '@searchspring/snap-url-manager';
8
8
  import type { Logger } from '@searchspring/snap-logger';
9
+ import type { SearchRequestModel } from '@searchspring/snapi-types';
9
10
  export declare type PluginFunction = (cntrlr: AbstractController, ...args: any) => Promise<void> | void;
10
11
  export declare type PluginGrouping = [func: PluginFunction, ...args: unknown[]];
11
12
  export declare type BeforeSearchObj = {
@@ -15,6 +16,7 @@ export declare type BeforeSearchObj = {
15
16
  export declare type AfterSearchObj = {
16
17
  controller: AbstractController;
17
18
  response: any;
19
+ request: SearchRequestModel;
18
20
  };
19
21
  export declare type AfterStoreObj = {
20
22
  controller: AbstractController;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@searchspring/snap-controller",
3
- "version": "0.39.2",
3
+ "version": "0.40.0",
4
4
  "description": "Snap Controllers",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -20,21 +20,21 @@
20
20
  "test:watch": "jest --watch"
21
21
  },
22
22
  "dependencies": {
23
- "@searchspring/snap-toolbox": "^0.39.2",
23
+ "@searchspring/snap-toolbox": "^0.40.0",
24
24
  "deepmerge": "4.2.2"
25
25
  },
26
26
  "devDependencies": {
27
- "@searchspring/snap-client": "^0.39.2",
28
- "@searchspring/snap-event-manager": "^0.39.2",
29
- "@searchspring/snap-logger": "^0.39.2",
30
- "@searchspring/snap-profiler": "^0.39.2",
31
- "@searchspring/snap-store-mobx": "^0.39.2",
32
- "@searchspring/snap-tracker": "^0.39.2",
33
- "@searchspring/snap-url-manager": "^0.39.2"
27
+ "@searchspring/snap-client": "^0.40.0",
28
+ "@searchspring/snap-event-manager": "^0.40.0",
29
+ "@searchspring/snap-logger": "^0.40.0",
30
+ "@searchspring/snap-profiler": "^0.40.0",
31
+ "@searchspring/snap-store-mobx": "^0.40.0",
32
+ "@searchspring/snap-tracker": "^0.40.0",
33
+ "@searchspring/snap-url-manager": "^0.40.0"
34
34
  },
35
35
  "sideEffects": false,
36
36
  "files": [
37
37
  "dist/**/*"
38
38
  ],
39
- "gitHead": "2ca3741bc997a3d6a8f4dd5332c2c5e5731f0b01"
39
+ "gitHead": "ab543649e56e547374715ad0f018db29d72a0d8e"
40
40
  }