var __extends = (this && this.__extends) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; /// <reference path="IProxy.ts" /> /// <reference path="../../util/Json.ts" /> /// <reference path="../../util/DateUtils.ts" /> /// <reference path="../../util/ZeroGapUtil.ts" /> /// <reference path="../../ajax/Ajax.ts" /> /// <reference path="../Request.ts" /> /// <reference path="../history/VisitorHistory.ts" /> /// <reference path="../event/ProductViewEvent.ts" /> /// <reference path="../response/Response.ts" /> var econda; (function (econda) { var recengine; (function (recengine) { var proxy; (function (proxy) { var Response = econda.recengine.response.Response; var ProductViewEvent = econda.recengine.event.ProductViewEvent; var DateUtils = econda.util.DateUtils; var ZeroGapUtil = econda.util.ZeroGapUtil; /** * Proxy to send requests to cross sell v1 recommendation service. This is an internal class an there's no reason * to use this class directly. * @class econda.recengine.proxy.AjaxProxy */ var AjaxProxy = (function (_super) { __extends(AjaxProxy, _super); function AjaxProxy(cfg) { if (cfg === void 0) { cfg = null; } _super.call(this); /** * Service uri. Used for unit tests only * @cfg {String} uri * @accessor */ this.uri = null; /** * Reference to request object * @cfg {econda.recengine.Request} request * @accessor */ this.request = null; /** * Last ajax request object. We use this for unit testing. * @private * @property {econda.ajax.Request} */ this._ajaxRequest = null; if (cfg instanceof AjaxProxy) { return cfg; } this.initConfig(cfg); } AjaxProxy.prototype.getUri = function () { return this.uri; }; AjaxProxy.prototype.setUri = function (uri) { this.uri = uri; }; AjaxProxy.prototype.setRequest = function (request) { this.request = request; }; AjaxProxy.prototype.getRequest = function () { return this.request; }; /** * Get instance of the ajax request class that was used to perform the request. * @returns {econda.ajax.Request} */ AjaxProxy.prototype.getAjaxRequest = function () { return this._ajaxRequest; }; /** * @private * @return {string} protocol to use */ AjaxProxy.detectProtocol = function () { return (typeof location.protocol === 'string' && location.protocol === 'https:') ? 'https' : 'http'; }; /** * Detects if cookies are required for current request. * @returns {Boolean} * @private */ AjaxProxy.prototype._isCookieRequired = function () { var cookieRequired = false; cookieRequired = cookieRequired || this.request.getAutoContext(); return cookieRequired; }; /** * Send request and call {@link #handleSuccess} when done. */ AjaxProxy.prototype.send = function () { var req = this.request; var cmp = this; var protocol = AjaxProxy.detectProtocol(); var uri = this.uri; if (!uri) { uri = [protocol, '://widgets.crosssell.info/eps/crosssell/recommendations/', req.getAccountId(), '.do'].join(''); } var params = this.getRecommendationServiceFormFieldParametersFromRequest(); var request = this._ajaxRequest = econda.ajax.Ajax.createRequest({ uri: uri, method: 'post', writer: 'form-encoded', reader: 'json', data: params, withCredentials: cmp._isCookieRequired(), timeoutMilliseconds: req.getTimeoutMilliseconds(), success: function (ajaxResponse) { cmp.handleSuccess(ajaxResponse); }, error: function () { cmp.handleError(); } }); request.init(); if (request.isSupportedRequest()) { request.send(); } else { var request = this._ajaxRequest = econda.ajax.Ajax.createRequest({ uri: uri, method: 'get', reader: 'json', params: params, withCredentials: cmp._isCookieRequired(), timeoutMilliseconds: req.getTimeoutMilliseconds(), success: function (ajaxResponse) { cmp.handleSuccess(ajaxResponse); }, error: function () { cmp.handleError(); } }); request.send(); } }; AjaxProxy.prototype.handleError = function () { var response = new Response({ isError: true }); this.request.handleResponse(response); }; /** * Handles ajax response data, creates Response object and calls callback on Request object * @private */ AjaxProxy.prototype.handleSuccess = function (responseData) { if (!responseData) { this.handleError(); return; } // modify response data to match expected property names if (typeof responseData.products === 'undefined') { responseData.products = responseData.items || []; delete responseData.items; } if (typeof responseData.widgetdetails !== 'undefined') { responseData.widgetDetails = responseData.widgetdetails; delete responseData.widgetdetails; } if (typeof responseData.start !== 'undefined') { responseData.startIndex = responseData.start; delete responseData.start; } if (typeof responseData.end !== 'undefined') { responseData.endIndex = responseData.end; delete responseData.end; } // remove unused data delete responseData.size; // create response object var response = new Response(responseData); response.setRequest(this.getRequest()); this.request.handleResponse(response); }; AjaxProxy.prototype.getRecommendationServiceFormFieldParametersFromRequest = function () { var request = this.request; var params = {}; // basics params['wid'] = request.getWidgetId(); params['aid'] = request.getAccountId(); params['type'] = request.getType(); params['start'] = request.getStartIndex(); params['widgetdetails'] = true; var csize = request.getChunkSize(); if (csize) { params['csize'] = csize; } var productIds = []; if (request.getAutoContext()) { productIds = this._getAutoContextParamValue(); } // manual context var context = request.getContext(); if (context) { var products = context.getProducts(); for (var n = 0; n < products.length; n++) { if (products[n].getSku()) { productIds.push('sku:' + products[n].getSku()); } else { productIds.push(products[n].getId()); } } context.addToRequest(params); // append history from profile ZeroGapUtil.appendHistoryFromProfile(params); // append current date (see MON-4036) params['timestamp'] = this._currentDateAsUtcIsoString(); // handle products excluded var productsExcluded = context.getProductsExcluded(); params['excl'] = this._convertProductReferencesListToParamValue(productsExcluded); } params['pid'] = productIds; return params; }; /** * legacy: send list of last viewed products if autoContext is set. * @private */ AjaxProxy.prototype._getAutoContextParamValue = function () { var productIds = []; var productViewedEvents = econda.data.visitor.getHistory() .getFilteredItems(function (e) { return e instanceof ProductViewEvent; }); var productReference; for (var n = 0; n < productViewedEvents.length; n++) { if (productReference = productViewedEvents[n].getProduct()) { if (productReference.getSku()) { productIds.push('sku:' + productReference.getSku()); } else { productIds.push(productReference.getId()); } } } return productIds.slice(-5).reverse(); }; AjaxProxy.prototype._currentDateAsUtcIsoString = function () { return DateUtils.toUtcIsoString(new Date()); }; AjaxProxy.prototype._convertProductReferencesListToParamValue = function (productReferences, readerFunction) { var productIds = []; var read = typeof readerFunction === 'function' ? readerFunction : function (item) { return item; }; for (var i = 0; i < productReferences.length; i++) { // noinspection TypeScriptValidateTypes var productReference = read(productReferences[i]); if (productReference.getSku() !== null) { productIds.push('sku:' + productReference.getSku()); } else { productIds.push(productReference.getId()); } } return productIds; }; return AjaxProxy; }(econda.base.BaseClass)); proxy.AjaxProxy = AjaxProxy; })(proxy = recengine.proxy || (recengine.proxy = {})); })(recengine = econda.recengine || (econda.recengine = {})); })(econda || (econda = {}));