Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,121 @@
query: config.urlQuery,
};

// Custom URL routing: short, stable URL keys (q, category, brand, size, color, store, price, sort, page, etc.)
// instead of the default `simple` mapping's index-prefixed keys, with `arrayFormat: 'repeat'
// so `?brand=Apple&brand=Samsung` replaces `?brand[0]=Apple&brand[1]=Samsung`.
const isMaster = algoliaData.recordModel === 'master-level' || algoliaData.recordModel === 'attribute-sliced';
const sizeAttribute = isMaster ? 'variants.size' : 'size';
const colorAttribute = isMaster ? 'variants.color' : 'color';
const storeAttribute = isMaster ? 'variants.storeAvailability' : 'storeAvailability';
const priceAttribute = isMaster ? 'variants.price.' + algoliaData.currencyCode : 'price.' + algoliaData.currencyCode;

/**
* Compresses a hierarchicalMenu uiState slot (which stores cumulative paths at
* every level) into one segment per level so the URL reads as one value per level.
* Assumes category display names do not contain ' > '.
* @param {string[]} levels Cumulative paths, e.g. ['Womens', 'Womens > Clothing']
* @returns {string[]} One segment per level, e.g. ['Womens', 'Clothing']
*/
function compressBreadcrumb(levels) {
return levels.map(function (level, i) {
return i === 0 ? level : level.split(' > ').pop();
});
}

/**
* Rebuilds the cumulative-path form the hierarchicalMenu widget expects in uiState
* from the per-level segments carried in the URL. Inverse of compressBreadcrumb.
* @param {string[]} segments One segment per level, e.g. ['Womens', 'Clothing']
* @returns {string[]} Cumulative paths, e.g. ['Womens', 'Womens > Clothing']
*/
function expandBreadcrumb(segments) {
return segments.map(function (_, i) {
return segments.slice(0, i + 1).join(' > ');
});
}

// URL keys this mapping owns. Anything else already on the URL (lang, utm_*, ...) is
// preserved across refinements so locale and marketing parameters are not stripped.
const routeKeys = ['q', 'category', 'newArrivals', 'newArrival', 'brand', 'color', 'size', 'store', 'price', 'sort', 'page'];

const router = instantsearch.routers.history({
createURL: function (params) {
const qsModule = params.qsModule;
const url = new URL(params.location.href);
const current = qsModule.parse(url.search.slice(1));
routeKeys.forEach(function (key) { delete current[key]; });

Check warning on line 98 in cartridges/int_algolia_sfra/cartridge/static/default/js/algolia/instantsearch-config.js

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

cartridges/int_algolia_sfra/cartridge/static/default/js/algolia/instantsearch-config.js#L98

Generic Object Injection Sink
const merged = Object.assign({}, current, params.routeState);
url.search = qsModule.stringify(merged, { arrayFormat: 'repeat' });
return url.href;
}
});

const stateMapping = {
stateToRoute: function (uiState) {
var indexUiState = uiState[productsIndex] || {};

Check warning on line 107 in cartridges/int_algolia_sfra/cartridge/static/default/js/algolia/instantsearch-config.js

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

cartridges/int_algolia_sfra/cartridge/static/default/js/algolia/instantsearch-config.js#L107

Generic Object Injection Sink
var route = {};
if (indexUiState.query) route.q = indexUiState.query;
if (indexUiState.page) route.page = indexUiState.page;
if (indexUiState.sortBy === productsIndex) route.sort = 'best';
if (indexUiState.sortBy === productsIndexPriceAsc) route.sort = 'price-asc';
if (indexUiState.sortBy === productsIndexPriceDesc) route.sort = 'price-desc';
if (indexUiState.hierarchicalMenu && indexUiState.hierarchicalMenu['__primary_category.0']) {
route.category = compressBreadcrumb(indexUiState.hierarchicalMenu['__primary_category.0']);
}
if (indexUiState.hierarchicalMenu && indexUiState.hierarchicalMenu['newArrivalsCategory.0']) {
route.newArrivals = compressBreadcrumb(indexUiState.hierarchicalMenu['newArrivalsCategory.0']);
}
if (indexUiState.toggle && indexUiState.toggle.newArrival) route.newArrival = '1';
if (indexUiState.refinementList) {
if (indexUiState.refinementList.brand) route.brand = indexUiState.refinementList.brand;
if (indexUiState.refinementList[sizeAttribute]) route.size = indexUiState.refinementList[sizeAttribute];

Check warning on line 123 in cartridges/int_algolia_sfra/cartridge/static/default/js/algolia/instantsearch-config.js

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

cartridges/int_algolia_sfra/cartridge/static/default/js/algolia/instantsearch-config.js#L123

Generic Object Injection Sink
if (indexUiState.refinementList[colorAttribute]) route.color = indexUiState.refinementList[colorAttribute];

Check warning on line 124 in cartridges/int_algolia_sfra/cartridge/static/default/js/algolia/instantsearch-config.js

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

cartridges/int_algolia_sfra/cartridge/static/default/js/algolia/instantsearch-config.js#L124

Generic Object Injection Sink
if (indexUiState.refinementList[storeAttribute]) route.store = indexUiState.refinementList[storeAttribute];

Check warning on line 125 in cartridges/int_algolia_sfra/cartridge/static/default/js/algolia/instantsearch-config.js

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

cartridges/int_algolia_sfra/cartridge/static/default/js/algolia/instantsearch-config.js#L125

Generic Object Injection Sink
}
if (indexUiState.range && indexUiState.range[priceAttribute]) route.price = indexUiState.range[priceAttribute];

Check warning on line 127 in cartridges/int_algolia_sfra/cartridge/static/default/js/algolia/instantsearch-config.js

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

cartridges/int_algolia_sfra/cartridge/static/default/js/algolia/instantsearch-config.js#L127

Generic Object Injection Sink
return route;
},
routeToState: function (route) {
var indexUiState = {};
if (route.q) indexUiState.query = route.q;
if (route.page) indexUiState.page = Number(route.page);
if (route.sort === 'best') indexUiState.sortBy = productsIndex;
if (route.sort === 'price-asc') indexUiState.sortBy = productsIndexPriceAsc;
if (route.sort === 'price-desc') indexUiState.sortBy = productsIndexPriceDesc;
if (route.category) {
indexUiState.hierarchicalMenu = indexUiState.hierarchicalMenu || {};
indexUiState.hierarchicalMenu['__primary_category.0'] = expandBreadcrumb([].concat(route.category));
}
if (route.newArrivals) {
indexUiState.hierarchicalMenu = indexUiState.hierarchicalMenu || {};
indexUiState.hierarchicalMenu['newArrivalsCategory.0'] = expandBreadcrumb([].concat(route.newArrivals));
}
if (route.newArrival === '1') indexUiState.toggle = { newArrival: true };
var refinementList = {};
if (route.brand) refinementList.brand = [].concat(route.brand);
if (route.size) refinementList[sizeAttribute] = [].concat(route.size);

Check warning on line 148 in cartridges/int_algolia_sfra/cartridge/static/default/js/algolia/instantsearch-config.js

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

cartridges/int_algolia_sfra/cartridge/static/default/js/algolia/instantsearch-config.js#L148

Generic Object Injection Sink
if (route.color) refinementList[colorAttribute] = [].concat(route.color);

Check warning on line 149 in cartridges/int_algolia_sfra/cartridge/static/default/js/algolia/instantsearch-config.js

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

cartridges/int_algolia_sfra/cartridge/static/default/js/algolia/instantsearch-config.js#L149

Generic Object Injection Sink
if (route.store) refinementList[storeAttribute] = [].concat(route.store);

Check warning on line 150 in cartridges/int_algolia_sfra/cartridge/static/default/js/algolia/instantsearch-config.js

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

cartridges/int_algolia_sfra/cartridge/static/default/js/algolia/instantsearch-config.js#L150

Generic Object Injection Sink
if (Object.keys(refinementList).length) indexUiState.refinementList = refinementList;
if (route.price) {
indexUiState.range = {};
indexUiState.range[priceAttribute] = route.price;

Check warning on line 154 in cartridges/int_algolia_sfra/cartridge/static/default/js/algolia/instantsearch-config.js

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

cartridges/int_algolia_sfra/cartridge/static/default/js/algolia/instantsearch-config.js#L154

Generic Object Injection Sink
}
var ui = {};
ui[productsIndex] = indexUiState;

Check warning on line 157 in cartridges/int_algolia_sfra/cartridge/static/default/js/algolia/instantsearch-config.js

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

cartridges/int_algolia_sfra/cartridge/static/default/js/algolia/instantsearch-config.js#L157

Generic Object Injection Sink
if (route.q) {
ui[contentsIndex] = { query: route.q };

Check warning on line 159 in cartridges/int_algolia_sfra/cartridge/static/default/js/algolia/instantsearch-config.js

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

cartridges/int_algolia_sfra/cartridge/static/default/js/algolia/instantsearch-config.js#L159

Generic Object Injection Sink
}
return ui;
}
};

var search = instantsearch({
indexName: productsIndex,
searchClient: config.searchClient,
initialUiState: initialUiState,
routing: true,
routing: { router: router, stateMapping: stateMapping },
});

if (algoliaData.enableInsights) {
Expand Down
Loading