"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var _a; /** * Contestants to keep inner configuration on one place */ class Constants { } Constants.URL_CHANGE_CHECKER_PERIOD_IN_SECONDS = 1; Constants.WEBSITE_SETTINGS_LOCAL_STORAGE_EXPIRATION_IN_SECONDS = 3 * 60 * 60; Constants.NOTIFICATIONS_CLOSED_BY_USER_DURATION_IN_SECONDS = 24 * 60 * 60; /** This defines for how long is activity information keep. It's important to let here 1 day bcs we are counting visitors per days */ Constants.DAILY_ACTIVITY_EXPIRATION_IN_SECONDS = 24 * 60 * 60; /** How often is checked if user still has its daily activity id */ Constants.DAILY_ACTIVITY_WATCH_PERIOD_IN_SECONDS = 60 * 5; Constants.ACTIVITY_ID_EXPIRATION_IN_SECONDS = 365 * 24 * 60 * 60; Constants.ACTIVITY_ID_WATCH_PERIOD_IN_SECONDS = 24 * 60 * 60; Constants.NOTIFICATION_INVALID_STATE_DURATION_IN_SECONDS = 15 * 60; Constants.NOTIFICATION_ALREADY_SEEN_STATE_DURATION_IN_SECONDS = 12 * 60 * 60; Constants.REVIEWS_STORAGE_EXPIRATION_IN_SECONDS = 60 * 60 * 24 * 3; /** @type {string} unique string used to create unique classes, ids and so on */ Constants.UNIQUE = 'xh1dse454'; //region App stability const AppStates = { Valid: 'valid', FatalError: 'fatal_error', Error: 'error', Unhealthy: 'unhealthy' }; let APP_STATE = AppStates.Valid; function IsAppRunning() { if (APP_STATE === AppStates.Valid || APP_STATE === AppStates.Unhealthy) { return true; } return false; } //endregion //region Initial run /** * Class ideally to be extended to provide all other parts of code one way to logging */ class Logger { /** * @param {Config} Configuration */ constructor(config) { /** * Classic information log * @param args just use like classing console.log */ this.log_info = (...args) => { if (this.config.debugMode) console.log(...args); }; /** * Classic error log * @param args just use like classing console.error */ this.log_error = (...args) => { if (this.config.debugMode) console.error(...args); }; this.config = config; } } /** * Main part of script, which is centre of all functionalities. Register, load and run all parts of pixel. */ class Main extends Logger { /** * @param {Configuration} config */ constructor(config) { super(config); // Create all important dependencies this.api = new ApiGate(this.config); this.urlChecker = new UrlChecker(location.href); this.notificationsManager = new NotificationsManager(this.api, this.config, this.urlChecker); // Check if debug mode is active if (!CookiesManager.checkCookie(CookiesManager.Name.DEBUG_MODE)) CookiesManager.setCookie(CookiesManager.Name.DEBUG_MODE, this.config.debugMode); else { this.config.debugMode = Utils.strToBool(CookiesManager.getCookie(CookiesManager.Name.DEBUG_MODE)); } // Print info about successful loading and show configuration into console for dev this.log_info('Pixel script loaded'); this.log_info(' - preview mode: ', this.config.previewMode); this.log_info(' - website id: ', this.config.websiteId); this.log_info(' - backend url: ', this.config.backendUrl); this.log_info(' - mobile mode: ', this.config.mobileMode); this.log_info(' - debug mode: ', this.config.debugMode); // Add callback which will be called with each url address change this.log_info('Registering callbacks...'); this.urlChecker.registerOnChangeCallback(this.api.decrease_credit); this.log_info('Callbacks registered'); } /** * This is core method to start all watchers load all important data and make everything functional * @returns {Promise} end when everything is started, app still should be in failed state but bcs of async it will be shown later */ run() { return __awaiter(this, void 0, void 0, function* () { let scriptBeginDateTime = new Date(); if (this.config.previewMode) { this.log_info('Pixel is in preview mode. Run method stopped here.'); return; } // Load notifications data, recalculate credit and run base watchers let notificationsStacks; try { yield this.api.decrease_credit(); yield this.runDailyUserActivityWatch(); yield this.runActivityIdWatch(); shoptetCouponCodeValidator(); notificationsStacks = yield this.notificationsManager.loadAndConvertNotificationsSettings(); if (!notificationsStacks) { this.log_error('No data were loaded for notifications'); APP_STATE = AppStates.FatalError; throw Error('Loading of notifications configuration failed'); } } catch (error) { this.log_error('Something failed while basic requests were sent (credits manipulation, daily user activity, activity id, notifications data): ', error); APP_STATE = AppStates.FatalError; throw Error('Any of core functionalities failed'); } // Register log notifications if (notificationsStacks.logNotifications.length > 0) { this.notificationsManager .registerLogNotifications(notificationsStacks.logNotifications) .then((r) => { this.log_info('Register log notifications success'); }) .catch((r) => { APP_STATE = AppStates.Unhealthy; this.log_error('Register log notifications failed ', r); }); } // Register and run show notifications // // Check if notifications are stopped by user const isNotificationLoopDisabled = CookiesManager.isNotificationLoopClosedByUser(); if (isNotificationLoopDisabled) { this.log_info('Notifications are stopped by customer bcs of close button click'); return; } // Check if there are any notifications if (notificationsStacks.showNotifications.length == 0) { this.log_info('There are no notifications to show'); return; } // Run notifications presenter - show notifications to user this.notificationsManager .runNotificationsPresenter(notificationsStacks.showNotifications, notificationsStacks.language, scriptBeginDateTime) .then((r) => { this.log_info('Notifications presenter loop success'); }) .catch((r) => { this.log_error('Notifications presenter failed ', r); APP_STATE = AppStates.Unhealthy; }); }); } /** * Run periodic job to check if user was in actual day active (for daily statistics) * @returns {Promise} */ runDailyUserActivityWatch() { return __awaiter(this, void 0, void 0, function* () { if (!IsAppRunning()) { return; } let visitId = CookiesManager.getCookie(CookiesManager.Name.DAILY_ACTIVITY); if (!visitId) { visitId = Utils.createUuid(); CookiesManager.setCookie(CookiesManager.Name.DAILY_ACTIVITY, visitId, Constants.DAILY_ACTIVITY_EXPIRATION_IN_SECONDS); const isSuccess = yield this.api.sendDailyActivity(visitId); const watcher = this.runDailyUserActivityWatch; const self = this; setTimeout(function () { return __awaiter(this, void 0, void 0, function* () { watcher() .then((r) => { self.log_info('Daily user activity success'); }) .catch((r) => { self.log_error('Daily user activity failed: ', r); APP_STATE = AppStates.Unhealthy; }); }); }, 1000 * Constants.DAILY_ACTIVITY_WATCH_PERIOD_IN_SECONDS); } }); } /** * Run periodic job to check if user is identified. Generate for each user (browser) id which defines them for purpose of orders and registrations stats. * @returns {Promise} */ runActivityIdWatch() { return __awaiter(this, void 0, void 0, function* () { if (!IsAppRunning()) { return; } CookiesManager.getOrCreateActivityId(); const watcher = this.runActivityIdWatch; const self = this; setTimeout(function () { return __awaiter(this, void 0, void 0, function* () { yield watcher() .then((r) => { self.log_info('Activity id watch success'); }) .catch((r) => { self.log_error('Activity id watch failed ', r); APP_STATE = AppStates.Error; }); }); }, 1000 * Constants.ACTIVITY_ID_WATCH_PERIOD_IN_SECONDS); }); } } //endregion function onCloseButtonClick() { CookiesManager.setNotificationLoopClosedByUser(); const mainNotificationDiv = document.getElementById(`${Constants.UNIQUE}-main-div-id`); if (mainNotificationDiv) { mainNotificationDiv.remove(); } } function getParamsFromPosition(_position) { if (_position === 'bottomLeft') { return { top: undefined, right: undefined, bottom: '10px', left: '10px' }; } if (_position === 'bottomRight') { return { top: undefined, right: '10px', bottom: '10px', left: undefined }; } if (_position === 'topLeft') { return { top: '10px', right: undefined, bottom: undefined, left: '10px' }; } if (_position === 'topRight') { return { top: '10px', right: '10px', bottom: undefined, left: undefined }; } if (_position === 'top') { return { top: '10px', right: '-10px', bottom: undefined, left: '-10px' }; } if (_position === 'bottom') { return { top: undefined, right: '-10px', bottom: '10px', left: '-10px' }; } } /** * The getSubmits function is used to obtain all form submit buttons or elements with specific on the page and determine if they are from UPgates forms or not. * The reason for this distinction is that UPgates forms have buttons that are not of the submit type, but have the attribute name="formSendButton". * @returns {Element[]} */ const getSubmits = () => { const idElements = document.querySelectorAll('#pixel_script_7102af82-6d23-4972-97f6-26f4481d9476'); if (idElements.length > 0) { return [...idElements]; } const metaElement = document.querySelector('meta[name="web_author"]'); // If there is a meta element with the attribute name="web_author" on the page and its value is "UPgates", then all buttons with the attribute name="formSendButton" are obtained. if (metaElement && metaElement.content === 'UPgates') { const formSendButtons = document.querySelectorAll('button[name="formSendButton"]'); return [...formSendButtons]; } // Else all buttons with the type attribute set to "submit" are obtained. const submits = document.querySelectorAll('input[type=submit]'); const buttonsSubmits = document.querySelectorAll('button[type="submit"]'); const withSubmits = [...submits, ...buttonsSubmits]; if (withSubmits.length > 0) { return withSubmits; } // Else all buttons are obtained. const anyButtons = document.querySelectorAll('button'); return [...anyButtons]; }; const callCustomFunction = (fun, att, language) => { fun(decodeURIComponent(att), language); }; function getNotificationPreview(notificationSettings, type, customerName, text, visitCount, language, summaryCount, maxLastDays, reviewText, rating, addLink, linkText, linkAsButton, animationSpeed, discountCouponName, discountCouponValue, discountCouponType, discountCouponAppliableTo, uniqueStyleIdentifier) { return __awaiter(this, void 0, void 0, function* () { let notificationsManager = new NotificationsManager(); const animation = animationSpeed !== undefined ? { animationSpeed: animationSpeed + 1, nextNotificationDelaySeconds: 1, position: 'bottomLeft', showAfterSeconds: 1, showDurationSeconds: 100000000 } : {}; const result = yield notificationsManager.showNotification(Object.assign(Object.assign({}, notificationSettings), { settings: Object.assign(Object.assign({ maxLastDays: maxLastDays, rating: rating, customerName: customerName, text: text }, notificationSettings.settings), { type: type }) }), { name: customerName, productName: text, imageURL: linkText, text: text, summary: reviewText, review: { positiveComment: reviewText }, addLink: addLink, discountCouponName: discountCouponName, discountCouponValue: discountCouponValue, discountCouponType: discountCouponType, discountCouponAppliableTo: discountCouponAppliableTo, linkAsButton: linkAsButton, openLinkInNewWindow: true, linkText: linkText, timestamp: new Date().getTime(), link: linkText, registrationCount: summaryCount, maxLastDays: maxLastDays, rating: rating, customerName: customerName, visitCount: visitCount || summaryCount, orderCount: summaryCount || visitCount }, animation, language, true, uniqueStyleIdentifier ? 'data-' + uniqueStyleIdentifier : undefined); return result; }); } //region Core modules class NotificationsManager extends Logger { /** * @param api {ApiGate} * @param config {Configuration} */ constructor(api, config, urlChecker) { super(config); this.api = api; this.urlChecker = urlChecker; } /** * Take log notifications and process them to register actions on buttons * @param {Array} logNotifications * @returns {Promise} */ registerLogNotifications(logNotifications) { return __awaiter(this, void 0, void 0, function* () { /** @type {Array.} */ let activeLogNotifications = []; logNotifications.forEach((logNotification) => { if (logNotification.isActiveForUrl(this.urlChecker.actualUrl)) { activeLogNotifications.push(logNotification); this.log_info('New active log notification registered: ', logNotification); } }); this.log_info(activeLogNotifications.length, ' active log notifications registered'); if (activeLogNotifications.length > 0) { this.log_info('Searching for buttons'); const allSubmits = getSubmits(); this.log_info('Found buttons: ', allSubmits); const api = this.api; const log_info = this.log_info; allSubmits.forEach((b) => { const onSubmitClick = (e) => __awaiter(this, void 0, void 0, function* () { e.preventDefault(); const inputs = Array.from(document.querySelectorAll('input[type=text]')); const allInputsValues = inputs.map((i) => { var _b; return (_b = i.value) !== null && _b !== void 0 ? _b : ''; }); log_info('All inputs values: ', allInputsValues); activeLogNotifications.forEach((logNotification) => { const notificationType = logNotification.settings.type === 'lastOrders' ? 'order' : 'registration'; log_info('Sending activity for notification: ', logNotification.settings.name); api.sendActivity(notificationType, logNotification.campaign.id, allInputsValues); log_info('Activity successfully sent'); }); b.removeEventListener('click', onSubmitClick, { once: true }); e.currentTarget.click(); }); b.addEventListener('click', onSubmitClick); }); } }); } /** * Loop over all notifications, take data for them and display them to user * @param {Array} showNotifications List of all notifications configured to be shown * @param {string} language configured language for texts * @param {Date} lastNotificationFinishedAt When the last notification was shown. First run = start of pixel script Main.run() * @returns {Promise} */ runNotificationsPresenter(showNotifications_1, language_1, lastNotificationFinishedAt_1) { return __awaiter(this, arguments, void 0, function* (showNotifications, language, lastNotificationFinishedAt, isFirstShow = true) { var _b, _c; this.log_info(showNotifications.length, ' total count of show notifications'); if (!IsAppRunning()) { return; // It stops the loop } let validShowNotifications = this.getValidNotifications(showNotifications); if (validShowNotifications.length == 0) { this.log_info('There are no valid notification to be shown'); yield Utils.sleep(4 * 60 * 1000); this.runNotificationsPresenter(showNotifications, language, lastNotificationFinishedAt, false) .then((r) => { this.log_info('Notifications presenter loop success'); }) .catch((r) => { this.log_error('Notifications presented loop failed: ', r); APP_STATE = AppStates.Error; }); return; } this.log_info(validShowNotifications.length, ' count of valid show notifications'); Utils.shuffleArray(validShowNotifications); let shownNotifications = 0; for (let notification of validShowNotifications) { this.log_info('Processing notification: ', notification); // IS notification visible for actual url? if (!this.urlChecker.isActualUrlInFilter(notification.campaign.urlFilter)) { this.log_info('- notification is not visible on that url'); continue; } try { let notificationData = yield this.getNotificationData(notification); if (!notificationData || notificationData === null) { throw new Error('Notification data is null (Server returned error response)'); } const visualSettingDependsOnDevice = this.config.mobileMode ? notification.campaign.visualPhoneSettings : notification.campaign.visualPcSettings; const showDelay = Math.abs((isFirstShow ? (_b = visualSettingDependsOnDevice.showAfterSeconds) !== null && _b !== void 0 ? _b : 0 : (_c = visualSettingDependsOnDevice.nextNotificationDelaySeconds) !== null && _c !== void 0 ? _c : 0) * 1000 - (new Date() - lastNotificationFinishedAt)); this.log_info('notification will be shown in ', showDelay, ' milliseconds'); shownNotifications++; if (showDelay > 0) yield Utils.sleep(showDelay); yield this.showNotification(notification, notificationData, visualSettingDependsOnDevice, language, false, undefined); lastNotificationFinishedAt = new Date(); isFirstShow = false; // Prevent repeat if notification is unrepeatable if (!notification.settings.repeatNotification) { CookiesManager.setNotificationIsAlreadySeen(notification.settings.id); } } catch (error) { CookiesManager.setNotificationAsInvalid(notification.settings.id); // TODO: should be great to identify if trouble is fatal or just missing enough data for notification. For fatal change state of app. this.log_error('Notification is invalid: ', error); } } if (shownNotifications == 0) { yield Utils.sleep(10 * 1000); } this.runNotificationsPresenter(showNotifications, language, new Date(), false) .then((r) => { this.log_info('Notifications presenter loop success'); }) .catch((r) => { this.log_error('Notifications presented loop failed: ', r); APP_STATE = AppStates.Error; }); }); } /** * It will convert non-general format of notifications data into general format which is ideal for rendering * @param {ShowNotification} notificationSettings * @param notificationData custom format from getNotificationData method (later maybe optimize) * @param {string} language * @returns {{note: string, iconSvg: string, header: any, message: string}|{iconSvg: string, header: string, message: string}|{note: string, iconSvg: string, header: string, message: string}|{iconSvg: string, link: ({linkAsButton: any, text: any, href, target: (string)}|null), message}|{iconSvg: string, rating: number, message: string}|{iconSvg: string, header: string, message: number}|{{imageURL: string, message: string, header: string, productURL: string}|{{imageURL: string, message: string, header: string}}|{iconSvg: string, link: ({linkAsButton: any, text: any, customButtonFunction: () => void}|null), message}} */ convertNotificationDataIntoSharedForm(notificationSettings, notificationData, language) { var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l; switch (notificationSettings.settings.type) { case 'lastRegistrations': return { header: notificationData.customerLocation ? notificationData.customerName + (notificationData.customerLocation.startsWith('z ') ? ` ${notificationData.customerLocation.trim()}` : ` (${notificationData.customerLocation.trim()})`) : notificationData.customerName, message: (_b = notificationSettings.settings.text) !== null && _b !== void 0 ? _b : LanguageManager.getTranslate('TextSingleRegistration', language), note: LanguageManager.describeAgeInMinutesMessage(notificationData.timestamp, language), iconSvg: IconsLibrary.getDefaultIconSvg(notificationSettings.settings.type) }; case 'lastOrders': return { header: notificationData.customerLocation ? notificationData.customerName + (notificationData.customerLocation.startsWith('z ') ? ` ${notificationData.customerLocation.trim()}` : ` (${notificationData.customerLocation.trim()})`) : notificationData.customerName, message: (_c = notificationSettings.settings.text) !== null && _c !== void 0 ? _c : LanguageManager.getTranslate('TextSingleOrder', language), note: LanguageManager.describeAgeInMinutesMessage(notificationData.timestamp, language), iconSvg: IconsLibrary.getDefaultIconSvg(notificationSettings.settings.type) }; case 'actualVisitors': return { header: `${notificationData.visitCount} ${(_d = notificationSettings.settings.text) !== null && _d !== void 0 ? _d : LanguageManager.getTranslate('TextVisitorsName', language)}`, message: LanguageManager.getTranslate('TextCurrentVisitors', language), iconSvg: IconsLibrary.getDefaultIconSvg(notificationSettings.settings.type) }; case 'visitorSummary': return { header: `${notificationData.visitCount} ${(_e = notificationSettings.settings.text) !== null && _e !== void 0 ? _e : LanguageManager.getTranslate('TextPeopleName', language)}`, message: LanguageManager.getTranslate('TextVisitorSummary', language), note: LanguageManager.getTimeWindowHumanForm(notificationSettings.settings.maxLastDays, language), iconSvg: IconsLibrary.getDefaultIconSvg(notificationSettings.settings.type) }; case 'registrationSummary': return { header: `${notificationData.registrationCount} ${(_f = notificationSettings.settings.text) !== null && _f !== void 0 ? _f : LanguageManager.getTranslate('TextPeopleName', language)}`, message: LanguageManager.getTranslate('TextRegistrationSummary', language), note: LanguageManager.getTimeWindowHumanForm(notificationSettings.settings.maxLastDays, language), iconSvg: IconsLibrary.getDefaultIconSvg(notificationSettings.settings.type) }; case 'orderSummary': return { header: `${notificationData.orderCount} ${(_g = notificationSettings.settings.text) !== null && _g !== void 0 ? _g : LanguageManager.getTranslate('TextPeopleName', language)}`, message: LanguageManager.getTranslate('TextOrderSummary', language), note: LanguageManager.getTimeWindowHumanForm(notificationSettings.settings.maxLastDays, language), iconSvg: IconsLibrary.getDefaultIconSvg(notificationSettings.settings.type) }; case 'heureka': return { message: LanguageManager.createReviewMessage(notificationData.summary, 90), rating: Number(notificationData.totalRating * 20), iconSvg: IconsLibrary.getDefaultIconSvg(notificationSettings.settings.type) }; case 'zboziCompanyRating': return { message: LanguageManager.createReviewMessage((_h = notificationData.review) === null || _h === void 0 ? void 0 : _h.positiveComment, 90), rating: Number(notificationData.rating), iconSvg: IconsLibrary.getDefaultIconSvg(notificationSettings.settings.type) }; case 'zboziProductRating': return { header: LanguageManager.createReviewMessage((_j = notificationData.review) === null || _j === void 0 ? void 0 : _j.positiveComments, 90), message: Number(notificationData.ratingStars * 20), iconSvg: IconsLibrary.getDefaultIconSvg(notificationSettings.settings.type) }; case 'spolehlivaRecenzeShopRating': return { message: LanguageManager.createReviewMessage((_k = notificationData.summary) !== null && _k !== void 0 ? _k : notificationData.review, 90), rating: Number(notificationData.rating * 20), iconSvg: IconsLibrary.getDefaultIconSvg(notificationSettings.settings.type) }; case 'spolehlivaRecenzeProductRating': return { message: LanguageManager.createReviewMessage((_l = notificationData.summary) !== null && _l !== void 0 ? _l : notificationData.review, 90), rating: Number(notificationData.rating * 20), iconSvg: IconsLibrary.getDefaultIconSvg(notificationSettings.settings.type) }; case 'individual': return { message: notificationData.text, link: notificationData.addLink ? { text: notificationData.linkText, href: notificationData.link, target: notificationData.openLinkInNewWindow ? '_blank' : '_self', linkAsButton: notificationData.linkAsButton } : null, iconSvg: IconsLibrary.getDefaultIconSvg(notificationSettings.settings.type) }; case 'shoptetLastOrders': return { header: notificationData.name, message: `${LanguageManager.getTranslate('ShoptetLastOrders', language)} ${notificationData.productName}`, imageURL: notificationData.imageURL, productURL: notificationData.productUrl }; case 'shoptetCouponCode': const isCouponActivated = CookiesManager.checkCookie(CookiesManager.Name.ACTIVATED_SHOPTET_COUPON); return { header: isCouponActivated ? LanguageManager.getOtherTranslations(language).SaleUsed : LanguageManager.getOtherTranslations(language).WeHaveSale, message: LanguageManager.createShoptetCouponMessage(language, notificationData.discountCouponName, notificationData.discountCouponValue, notificationData.discountCouponType, notificationData.discountCouponAppliableTo), iconSvg: isCouponActivated ? IconsLibrary.checkSvg : IconsLibrary.cardGiftcardSvg, link: { text: isCouponActivated ? LanguageManager.getOtherTranslations(language).SaleUsed : LanguageManager.getOtherTranslations(language).UseSale, linkAsButton: true, customButtonFunction: (couponName, language) => { CookiesManager.setCookie(CookiesManager.Name.ACTIVATED_SHOPTET_COUPON, couponName, 10000000); shoptetCouponCodeValidator(); const headerDiv = document.getElementsByClassName(`${Constants.UNIQUE}-header`)[0]; const button = document.getElementsByClassName(`${Constants.UNIQUE}-link-button`)[0]; const iconDiv = document.getElementsByClassName(`${Constants.UNIQUE}-icon-div`)[0]; const icon = document.getElementsByClassName(`${Constants.UNIQUE}-icon-img`)[0]; if (headerDiv) headerDiv.innerHTML = LanguageManager.getOtherTranslations(language).SaleUsed; if (button) { button.innerHTML = LanguageManager.getOtherTranslations(language).SaleUsed; button.classList.remove(`${Constants.UNIQUE}-link-button`); button.classList.add(`${Constants.UNIQUE}-link-button-disabled`); } if (iconDiv) { iconDiv.classList.remove(`${Constants.UNIQUE}-icon-div`); iconDiv.classList.add(`${Constants.UNIQUE}-icon-div-success`); } if (icon) { icon.innerHTML = IconsLibrary.checkSvg; icon.classList.remove(`${Constants.UNIQUE}-icon-img`); icon.classList.add(`${Constants.UNIQUE}-icon-img-success`); } } } }; } } /** * Returns random element from array */ getRandomElement(arr) { return arr[Math.floor(Math.random() * arr.length)]; } /** * * @param {string} notificationType */ setReviewsToLocalStorage(notificationType, reviews) { LocalStorageManager.setItem(`reviews-cache-${notificationType}`, reviews, Constants.REVIEWS_STORAGE_EXPIRATION_IN_SECONDS); } /** * * @param {string} notificationType */ getReviewsFromLocalStorage(notificationType) { return LocalStorageManager.getItem(`reviews-cache-${notificationType}`); } /** * Depends on type of notifications load its data * @param {ShowNotification} notification * @returns {Promise|{linkAsButton: any, name, link, linkText: any, text, addLink: any, openLinkInNewWindow: any, customButtonFunction: any, discountCouponName: any, discountCouponValue: any, discountCouponType: any, discountCouponAppliableTo: any}} */ getNotificationData(notification) { return __awaiter(this, void 0, void 0, function* () { let notificationData = undefined; if (notification.settings.type === 'individual' || notification.settings.type === 'shoptetCouponCode') { notificationData = this.createIndividualNotificationData(notification.settings); this.log_info('custom notification data: ', notificationData); } else if (notification.settings.type === 'heureka' || notification.settings.type === 'zboziCompanyRating' || notification.settings.type === 'zboziProductRating' || notification.settings.type === 'spolehlivaRecenzeShopRating' || notification.settings.type === 'spolehlivaRecenzeProductRating') { const localReviews = this.getReviewsFromLocalStorage(notification.settings.type); this.log_info('loaded reviews from local storage: ', localReviews); if (localReviews && localReviews.length) { const randomReview = this.getRandomElement(localReviews); this.log_info('notification data from local storage: ', randomReview); return randomReview; } notificationData = yield this.api.getNotificationData(notification); this.log_info('loaded reviews from server: ', notificationData); if (notificationData && (notificationData === null || notificationData === void 0 ? void 0 : notificationData.reviews) && (notificationData === null || notificationData === void 0 ? void 0 : notificationData.reviews.length)) { this.setReviewsToLocalStorage(notification.settings.type, notificationData.reviews); const randomReview = this.getRandomElement(notificationData.reviews); this.log_info('notification data: ', randomReview); return randomReview; } return null; } else { notificationData = yield this.api.getNotificationData(notification); this.log_info('notification data: ', notificationData); } return notificationData; }); } /** * Filter notifications to return just valid (it means it has no previous fails in defined period of time and its not one time notification displayed in defined period of time * @param {Array} showNotifications * @returns {Array|void} */ getValidNotifications(showNotifications) { let validShowNotifications = []; showNotifications.forEach((notification) => { const isValid = CookiesManager.getIsNotificationValid(notification.settings.id); if (!isValid) { this.log_info('Notification already set as invalid ', notification.settings); return; } if (!notification.settings.repeatNotification) { const isAlreadySeen = CookiesManager.getIsNotificationAlreadySeen(notification.settings.id); if (isAlreadySeen) { this.log_info('Notification already seen ', notification.settings); return; } } const visualSettingDependsOnDevice = this.config.mobileMode ? notification.campaign.visualPhoneSettings : notification.campaign.visualPcSettings; if (!visualSettingDependsOnDevice) { this.log_info('Notification is not enabled on this device ', notification.settings); return; } validShowNotifications.push(notification); }); return validShowNotifications; } /** * Return converted lists of notifications (log, show) * @returns {Promise} */ loadAndConvertNotificationsSettings() { return __awaiter(this, void 0, void 0, function* () { if (!IsAppRunning()) { return false; } let campaignSettings = yield this.loadCampaignSettings(); this.log_info('Raw campaign settings: ', campaignSettings); if (campaignSettings == null) { this.log_error('User has no remaining credits (and no trial mode). Cant start notification loop. Please, subscribe or start a trial mode '); return false; } return this.getNotificationsStacksFromCampaignSettings(campaignSettings); }); } /** * Load notification configuration from api * @returns {Promise} json data of notifications configuration */ loadCampaignSettings() { return __awaiter(this, void 0, void 0, function* () { let campaignSettings = LocalStorageManager.getItem(LocalStorageManager.Name.WEBSITE_SETTINGS); this.log_info('Campaign settings loaded from local storage', campaignSettings); if (campaignSettings == null) { campaignSettings = yield this.api.fetchCampaignSettings(); this.log_info('Campaign settings loaded from api', campaignSettings); if (campaignSettings == null) return null; LocalStorageManager.setItem(LocalStorageManager.Name.WEBSITE_SETTINGS, campaignSettings, Constants.WEBSITE_SETTINGS_LOCAL_STORAGE_EXPIRATION_IN_SECONDS); this.log_info('Campaign settings saved into local storage'); } return campaignSettings; }); } /** * Convert notifications configuration into object * @param campaignSettings * @returns {NotificationsStacks} */ getNotificationsStacksFromCampaignSettings(campaignSettings) { /** @type {Array.} */ let logNotifications = []; /** @type {Array.} */ let showNotifications = []; campaignSettings.campaigns.forEach((campaign) => { let campaignObj = convertJsonToCampaign(campaign); if (campaignObj.isActive) { campaignObj.notificationSettings.forEach((notification) => { if (notification.isActive) { if (notification.type === 'lastOrders' || notification.type === 'lastRegistrations') { let logNotification = new LogNotification(campaignObj, notification); logNotifications.push(logNotification); } let showNotification = new ShowNotification(campaignObj, notification); showNotifications.push(showNotification); } }); } }); return new NotificationsStacks(showNotifications, logNotifications, campaignSettings.language); } /** * Create result json data for custom notification * @param {DataNotificationSettings} notificationSettings * @returns {{linkAsButton: any, name, link, linkText: any, text, addLink: any, openLinkInNewWindow: any, customButtonFunction: any, discountCouponName: any, discountCouponValue: any, discountCouponType: any, discountCouponAppliableTo: any}} */ createIndividualNotificationData(notificationSettings) { return { name: notificationSettings.name, text: notificationSettings.text, addLink: notificationSettings.addLink, linkAsButton: notificationSettings.linkAsButton, openLinkInNewWindow: notificationSettings.openLinkInNewWindow, linkText: notificationSettings.linkText, link: notificationSettings.link, customButtonFunction: notificationSettings.customButtonFunction, discountCouponName: notificationSettings.discountCouponName, discountCouponValue: notificationSettings.discountCouponValue, discountCouponType: notificationSettings.discountCouponType, discountCouponAppliableTo: notificationSettings.discountCouponAppliableTo }; } /** * * @param {ShowNotification} notificationCompleteSettings * @param notificationData * @param {VisualPcPhoneSetting} visualSetting * @param language * @param forPreview */ showNotification(notificationCompleteSettings, notificationData, visualSetting, language, forPreview, uniqueStyleIdentifier) { return __awaiter(this, void 0, void 0, function* () { var _b, _c, _d, _e, _f; const isNotificationLoopDisabled = CookiesManager.isNotificationLoopClosedByUser(); if (isNotificationLoopDisabled) { this.log_info('Notifications are stopped by customer bcs of close button click'); return; } const notificationSettings = notificationCompleteSettings.settings; const campaignNotificationVisualSettings = ((_b = notificationCompleteSettings.campaign) === null || _b === void 0 ? void 0 : _b.notificationVisualSettings) || {}; const locationParams = getParamsFromPosition((_e = (_d = (_c = notificationCompleteSettings.campaign) === null || _c === void 0 ? void 0 : _c.visualPcSettings) === null || _d === void 0 ? void 0 : _d.position) !== null && _e !== void 0 ? _e : 'bottomLeft'); let animationType = 'slideInFromBottom'; if (visualSetting.position === 'top' || visualSetting.position === 'topLeft' || visualSetting.position === 'topRight') { animationType = 'slideInFromTop'; } const animationInSeconds = Math.round((2 - (2 * visualSetting.animationSpeed) / 100) * 100) / 100; const backAnimationDelay = visualSetting.showDurationSeconds + animationInSeconds; const animationFromTop = `slideInFromTop ${animationInSeconds}s ease-in 0s 1, slideInFromTopBack ${animationInSeconds}s ease-in ${backAnimationDelay}s 1`; const animationFromBottom = `slideInFromBottom ${animationInSeconds}s ease-in 0s 1, slideInFromBottomBack ${animationInSeconds}s ease-in ${backAnimationDelay}s 1`; const notificationDataSh = this.convertNotificationDataIntoSharedForm(notificationCompleteSettings, notificationData, language); const styleTagIdentifier = uniqueStyleIdentifier || Constants.UNIQUE; const myStyle = document.createElement('style'); myStyle.setAttribute(styleTagIdentifier, ''); myStyle.innerHTML = ` @keyframes slideInFromTop { 0% { transform: translateY(-100%); } 100% { transform: translateY(0); } } @keyframes slideInFromTopBack { 0% { transform: translateY(0); } 100% { transform: translateY(-200px); } } @keyframes slideInFromBottom { 0% { transform: translateY(100%); } 100% { transform: translateY(0); } } @keyframes slideInFromBottomBack { 0% { transform: translateY(0); } 100% { transform: translateY(200px); } } .${styleTagIdentifier}-main-div { visibility: visible; display: flex; flex-direction: column; font-family: Montserrat; color: ${notificationSettings.notificationVisualSettings.textColor || '#555770'}; z-index: 1000; position: ${forPreview ? 'relative' : 'fixed'}; width: 334px; height: 104px; padding: 12px; border-radius: ${notificationSettings.notificationVisualSettings.roundness ? notificationSettings.notificationVisualSettings.roundness + 'px' : (campaignNotificationVisualSettings === null || campaignNotificationVisualSettings === void 0 ? void 0 : campaignNotificationVisualSettings.roundness) ? campaignNotificationVisualSettings.roundness + 'px' : '5px'}; top: ${locationParams.top}; right: ${locationParams.right}; bottom: ${forPreview ? undefined : locationParams.bottom}; left: ${forPreview ? undefined : locationParams.left}; background-color: ${notificationSettings.notificationVisualSettings.backgroundColor || 'white'}; margin: 0 auto; box-shadow: 0px 1px 2px rgba(65, 32, 158, 0.06), 0px 0px 2px rgba(65, 32, 158, 0.04), 0px 4px 8px rgba(136, 100, 211, 0.16); box-sizing: content-box; animation: ${(visualSetting === null || visualSetting === void 0 ? void 0 : visualSetting.animationSpeed) !== undefined ? animationType === 'slideInFromTop' ? animationFromTop : animationFromBottom : 'none'}; } .${styleTagIdentifier}-icon-and-message { display: flex; flex-direction: row; } .${styleTagIdentifier}-icon-div, .${styleTagIdentifier}-icon-div-success, .${styleTagIdentifier}-icon-div-error { visibility: visible; display: flex; margin-right: 12px; height: 70px; align-items: center; justify-content: center; width: 70px; } .${styleTagIdentifier}-icon-div-success { background-color: ${'#eafced'}; } .${styleTagIdentifier}-icon-div-error { background-color: ${'#f9e8e8'}; } .${styleTagIdentifier}-icon-div { background-color: ${notificationSettings.notificationVisualSettings.iconBackgroundColor || '#FFF'}; } .${styleTagIdentifier}-icon-img img { object-fit: cover; } .${styleTagIdentifier}-icon-img svg { fill: ${notificationSettings.notificationVisualSettings.iconColor || '#7C76F7'}; } .${styleTagIdentifier}-icon-img-success svg { fill: ${'#67ce7f'}; } .${styleTagIdentifier}-icon-img-error svg { fill: ${'#cc6666'}; } .${styleTagIdentifier}-message { visibility: visible; display: flex; flex-direction: column; min-height: 60px; max-height: 78px; justify-content: ${notificationSettings.type === 'individual' && !notificationSettings.addLink ? 'start' : 'space-around'}; } .${styleTagIdentifier}-signature { font-size: 10px; font-weight: 400; display: flex; flex-direction: row; width: 95px; position: absolute; bottom: 12px; margin-top: 12px; justify-content: space-between; align-items: center; height: 16px; } .${styleTagIdentifier}-signature-image { height: 16px; width: 16px; display: flex; align-items: center; justify-content: center; } .${styleTagIdentifier}-message-span { margin-top: -5px; display: flex; align-items: center; font-weight: 400; font-size: 14px; } .${styleTagIdentifier}-message-container { flex-wrap: wrap; width: 256px; height: 100%; } .${styleTagIdentifier}-message-text { width: 100%; font-weight: 400; font-size: 14px; margin-top: 5px; text-align: left; } .${styleTagIdentifier}-message-text > p{ display: block; margin: 0; } .${styleTagIdentifier}-cross-mark { font-size: 14px; padding: 0px; color: #86879D; position: absolute; cursor: pointer; font-weight: bold; right: 16px; top: 8px; background: transparent; border: none; display: none; } .${styleTagIdentifier}-main-div:hover .${styleTagIdentifier}-cross-mark { display: block; } .${styleTagIdentifier}-header { font-size: 14px; color: #28293D; font-weight: 700; line-height: 1.5; text-align: left; } .${styleTagIdentifier}-note { font-size: 12px; color: #86879D; margin-top: 0px; line-height: 1.5; text-align: left; } .${styleTagIdentifier}-rating { font-size: 14px; margin-top: 8px; display: flex; align-items: center; font-weight: 700; color: #28293D; } .${styleTagIdentifier}-margin-right { margin-right: 10px; } .${styleTagIdentifier}-star-image { height: 16px; width: 16px; display: flex; align-items: center; justify-content: center; } .${styleTagIdentifier}-divider { width: 10px; color: #86879D; font-size: 12px; font-weight: 400; } .${styleTagIdentifier}-link-button, .${styleTagIdentifier}-link-button-disabled { color: ${notificationSettings.notificationVisualSettings.linkTextColor || '#FFFFFF'}; border-radius: 4px; border: 1px solid transparent; height: 28px; padding-left: 8px; padding-right: 8px; padding-top: 0px; padding-bottom: 0px; } .${styleTagIdentifier}-link-button { background-color: ${notificationSettings.notificationVisualSettings.linkButtonBackgroundColor || '#7075F3'}; cursor: pointer; } .${styleTagIdentifier}-link-button-disabled { background-color: ${Utils.hexToRGBA(notificationSettings.notificationVisualSettings.linkButtonBackgroundColor || '#7075F3', 0.5)}; } .${styleTagIdentifier}-link-text { cursor: pointer; color: ${notificationSettings.notificationVisualSettings.linkTextColor || '#7075F3'}; font-size: 14px; font-weight: 700; text-decoration: none; } .${styleTagIdentifier}-link-span { font-size: 12px; width: 100%; display: flex; justify-content: center; ${(notificationDataSh === null || notificationDataSh === void 0 ? void 0 : notificationDataSh.link) ? `margin-top: ${notificationDataSh.link.linkAsButton ? '9px' : '22px'}` : ``}; `; // if style tag not exists, create it else just change inner html if (!Utils.isStyleTagExists(styleTagIdentifier)) { Utils.appendStyleTag(myStyle); } else { const styleTag = document.querySelector(`style[${styleTagIdentifier}]`); styleTag.innerHTML = myStyle.innerHTML; } let icon; let iconError = false; if (notificationSettings.notificationVisualSettings.icon) { icon = IconsLibrary.getIconSvgByName(notificationSettings.notificationVisualSettings.icon); } else if ((notificationDataSh === null || notificationDataSh === void 0 ? void 0 : notificationDataSh.imageURL) && (notificationDataSh === null || notificationDataSh === void 0 ? void 0 : notificationDataSh.productURL)) { icon = ``; } else if (notificationDataSh === null || notificationDataSh === void 0 ? void 0 : notificationDataSh.imageURL) { icon = ``; } else if (notificationDataSh === null || notificationDataSh === void 0 ? void 0 : notificationDataSh.iconSvg) { icon = notificationDataSh.iconSvg; // TODO: what? || visualSetting } else { icon = IconsLibrary.errorSvg; iconError = true; } const iconColorType = notificationSettings.type === 'shoptetCouponCode' && CookiesManager.checkCookie(CookiesManager.Name.ACTIVATED_SHOPTET_COUPON) ? '-success' : !iconError ? '' : '-error'; const noteHtml = ` ${notificationDataSh === null || notificationDataSh === void 0 ? void 0 : notificationDataSh.note} `; const headerHtml = ` ${notificationDataSh === null || notificationDataSh === void 0 ? void 0 : notificationDataSh.header} `; const starHtml = `
${IconsLibrary.starSvg}
`; let ratingHtml; if (notificationDataSh === null || notificationDataSh === void 0 ? void 0 : notificationDataSh.rating) { let rating = Math.ceil(notificationDataSh.rating / 20); rating = rating === 0 ? 1 : rating; ratingHtml = `
${notificationDataSh.rating} %
${rating >= 5 ? starHtml : ''} ${rating >= 4 ? starHtml : ''} ${rating >= 3 ? starHtml : ''} ${rating >= 2 ? starHtml : ''} ${rating >= 1 ? starHtml : ''}
${LanguageManager.getOtherTranslations(language).Recommends}
`; } let linkHtml; if (notificationDataSh === null || notificationDataSh === void 0 ? void 0 : notificationDataSh.link) { if (notificationDataSh.link.linkAsButton === true) { const isButtonDisabled = notificationSettings.type === 'shoptetCouponCode' && CookiesManager.checkCookie(CookiesManager.Name.ACTIVATED_SHOPTET_COUPON); const onClickFunction = isButtonDisabled ? '' : notificationDataSh.link.customButtonFunction ? `callCustomFunction(${notificationDataSh.link.customButtonFunction}, "${encodeURIComponent(notificationData.discountCouponName)}", "${language}")` : `window.open("${notificationDataSh.link.href}", "${notificationDataSh.link.target ? '_blank' : ''}")`; linkHtml = ` `; } else if (notificationDataSh.link.linkAsButton === false) { linkHtml = ` `; } } const myHTML = `
${icon}
${(notificationDataSh === null || notificationDataSh === void 0 ? void 0 : notificationDataSh.header) ? headerHtml : ``}
${(notificationDataSh === null || notificationDataSh === void 0 ? void 0 : notificationDataSh.message) || ((_f = notificationSettings.text) === null || _f === void 0 ? void 0 : _f.replace(/(<\/p>\n

)/g, '
'))} ${linkHtml ? linkHtml : ``} ${(notificationDataSh === null || notificationDataSh === void 0 ? void 0 : notificationDataSh.rating) ? ratingHtml : ``} ${(notificationDataSh === null || notificationDataSh === void 0 ? void 0 : notificationDataSh.note) ? '
' + noteHtml : ``}

${IconsLibrary.signatureSvg} Overenyweb.cz
`; const myDiv = document.createElement('div'); myDiv.innerHTML = myHTML; if (forPreview) return myDiv; document.body.appendChild(myDiv); const reactAppRoot2 = document.getElementById('root'); if (reactAppRoot2) { reactAppRoot2.appendChild(myDiv); } else { document.body.appendChild(myDiv); } const nextNotificationShowAfter = (visualSetting.showDurationSeconds + (Math.round(animationInSeconds * 100) / 100) * 2) * 1000; yield Utils.sleep(nextNotificationShowAfter - 50); // delete popup after show duration const mainNotificationDiv = document.getElementById(`${styleTagIdentifier}-main-div-id`); if (mainNotificationDiv) { mainNotificationDiv.remove(); } }); } } /** * Class contains all api calls * TODO: implement better try catch of errors */ class ApiGate extends Logger { constructor(config) { super(config); } /** * Call method to decrease user credits * @returns {Promise} */ decrease_credit() { return __awaiter(this, void 0, void 0, function* () { if (!IsAppRunning()) { return; } const response = yield fetch(`${this.config.backendUrl}/credits/decrease`, { method: 'POST', headers: { 'Content-Type': 'application/json', Accept: 'application/json' }, body: JSON.stringify({ websiteId: this.config.websiteId }) }); if (response.status === 403) { APP_STATE = AppStates.FatalError; } }); } /** * Load all configuration for website * @returns {Promise} */ fetchCampaignSettings() { return __awaiter(this, void 0, void 0, function* () { const response = yield fetch(`${this.config.backendUrl}/campaign/verbose?websiteId=${this.config.websiteId}`, { method: 'GET', headers: { 'Content-Type': 'application/json', Accept: 'application/json' } }); if (response.status === 403) { return null; } else { this.log_info('fetchCampaignSettings response', response); const settings = yield response.json(); this.log_info('fetchCampaignSettings json', settings); return settings; } }); } /** * Send to api an information about user activity. If he registered or order something * @param {'order' | 'registration'} type defines kind of notification * @param {string} campaignId * @param {Array} inputsValues array of value which should be names or locations */ sendActivity(type, campaignId, inputsValues) { return __awaiter(this, void 0, void 0, function* () { const url = `${this.config.backendUrl}/activityStorage/${type}/create`; const activityId = CookiesManager.getOrCreateActivityId(); const body = { campaignId: campaignId, customerLocationShards: inputsValues, customerNameShards: inputsValues, userId: activityId }; const response = yield fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', Accept: 'application/json' }, body: JSON.stringify(body) }); if (response.status === 403) { return null; } else { this.log_info('sendActivity response', response); const settings = yield response.json(); this.log_info('sendActivity json', settings); return settings; } }); } /** * Load notification data depends on type of notification * @param {ShowNotification} showNotification * @returns {Promise} */ getNotificationData(showNotification) { return __awaiter(this, void 0, void 0, function* () { let url = yield this.generateGetNotificationDataUrl(showNotification); const response = yield fetch(url, { method: 'GET', headers: { 'Content-Type': 'application/json', Accept: 'application/json' } }); if (response.status === 403 || response.status === 500 || response.status === 404 || response.status === 400 || response.status === 401) { return null; } else { this.log_info('getNotificationData response', response); const settings = yield response.json(); this.log_info('getNotificationData json', settings); return settings; } }); } /** * Gets route info (url and query params) for fetching of notification data for requested notification settings / campaignId / websiteId * @param {ShowNotification} notificationSettings * @param {*} campaignId * @param {*} websiteId * @returns {URL} */ generateGetNotificationDataUrl(showNotification) { return __awaiter(this, void 0, void 0, function* () { const varToString = (varObj) => Object.keys(varObj)[0]; const activityId = CookiesManager.getOrCreateActivityId(); /** * * @param url {URL} * @param param * @param key */ function appendParamIntoUrlIfFilled(url, key, param) { if (param) url.searchParams.append(key || varToString(param), param); } const typeToUrlMap = { lastRegistrations: 'activityStorage/registration/random', lastOrders: 'activityStorage/order/random', actualVisitors: 'activityStorage/attendance/current', visitorSummary: 'activityStorage/attendance/summary', registrationSummary: 'activityStorage/registration/summary', orderSummary: 'activityStorage/order/summary', heureka: 'heureka/company/review/random', zboziCompanyRating: 'zbozi/company/review/random', zboziProductRating: 'zbozi/product/review/random', spolehlivaRecenzeShopRating: 'spolehlivaRecenze/shop/review/random', spolehlivaRecenzeProductRating: 'spolehlivaRecenze/product/review/random', shoptetLastOrders: 'shoptet/lastOrders' }; //TODO let notificationUrlPath = typeToUrlMap[showNotification.settings.type]; if (!notificationUrlPath) return false; let url = new URL(`${this.config.backendUrl}/${notificationUrlPath}`); appendParamIntoUrlIfFilled(url, 'campaignId', showNotification.campaign.id); appendParamIntoUrlIfFilled(url, 'userId', activityId); appendParamIntoUrlIfFilled(url, 'maxLastDays', showNotification.settings.maxLastDays); appendParamIntoUrlIfFilled(url, 'minRegistrations', showNotification.settings.minRegistrations); appendParamIntoUrlIfFilled(url, 'maxLastRegistrations', showNotification.settings.maxLastRegistrations); appendParamIntoUrlIfFilled(url, 'fallbackToGenericCustomer', showNotification.settings.fallbackToGenericCustomer); appendParamIntoUrlIfFilled(url, 'showCustomerOwnRegistrations', showNotification.settings.showCustomerOwnRegistrations); appendParamIntoUrlIfFilled(url, 'minOrders', showNotification.settings.minOrders); appendParamIntoUrlIfFilled(url, 'maxLastOrders', showNotification.settings.maxLastOrders); appendParamIntoUrlIfFilled(url, 'showCustomerOwnOrders', showNotification.settings.showCustomerOwnOrders); appendParamIntoUrlIfFilled(url, 'websiteId', this.config.websiteId); appendParamIntoUrlIfFilled(url, 'minVisitors', showNotification.settings.minVisitors); appendParamIntoUrlIfFilled(url, 'days', showNotification.settings.maxLastDays); appendParamIntoUrlIfFilled(url, 'minReviewStars', showNotification.settings.minReviewStars); appendParamIntoUrlIfFilled(url, 'minReviews', showNotification.settings.minReviews); return url; }); } sendDailyActivity(visitId) { return __awaiter(this, void 0, void 0, function* () { const url = `${this.config.backendUrl}/activityStorage/userAttendance/increase`; const requestBody = JSON.stringify({ websiteId: this.config.websiteId, visitorId: visitId }); const response = yield fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', Accept: 'application/json' }, body: requestBody }); if (response.status === 403) { return false; } else { return true; } }); } } const shoptetCouponCodeValidator = () => { if (!CookiesManager.checkCookie(CookiesManager.Name.ACTIVATED_SHOPTET_COUPON)) return; const couponCode = CookiesManager.getCookie(CookiesManager.Name.ACTIVATED_SHOPTET_COUPON); if (!couponCode) return; const couponCodeInput = document.getElementById('discountCouponCode'); if (!couponCodeInput) return; couponCodeInput.value = couponCode; couponCodeInput.parentElement.submit(); CookiesManager.removeCookie(CookiesManager.Name.ACTIVATED_SHOPTET_COUPON); }; /** * Class to control change of url and depends on that run registered callbacks */ class UrlChecker { /** * @param actualUrl {string} actual url which will be checked for change */ constructor(actualUrl) { /** * Actual url to check for change, against real actual url from location} * @type {string} */ this.actualUrl = actualUrl; /** * Array of methods which will be called if actual url will be changed * @type {Array} */ this.onChangeCallbacks = []; // Run periodic script for url change check this.runChangeUrlChecker(); } /** * Register method which will be called if url address will be changed * @param method {method} Method to call if url address is changed */ registerOnChangeCallback(method) { this.onChangeCallbacks.push(method); } /** * Begin periodic runner to control url address change */ runChangeUrlChecker() { if (this.onChangeCallbacks.length > 0 && this.actualUrl != location.href) { shoptetCouponCodeValidator(); this.onChangeCallbacks.forEach((callback) => { callback() .then((r) => { }) .catch((r) => { }); }); this.actualUrl = location.href; } var checker = this; setTimeout(checker.runChangeUrlChecker.bind(checker), Constants.URL_CHANGE_CHECKER_PERIOD_IN_SECONDS * 1000); } /** * * @param {UrlFilter} urlFilter * @param {string} url * @returns {boolean} */ isActualUrlInFilter(urlFilter) { const url = this.actualUrl; if ((urlFilter.includeUrlContains && urlFilter.includeUrlContains.some((subString) => url.includes(subString))) || (urlFilter.includeUrlBeginsWith && urlFilter.includeUrlBeginsWith.some((subString) => url.startsWith(subString))) || (urlFilter.includeUrlIsEqual && urlFilter.includeUrlIsEqual.some((subString) => url == subString))) { return !((urlFilter.excludeUrlContains && urlFilter.excludeUrlContains.some((subString) => url.includes(subString))) || (urlFilter.excludeUrlBeginsWith && urlFilter.excludeUrlBeginsWith.some((subString) => url.startsWith(subString))) || (urlFilter.excludeUrlIsEqual && urlFilter.excludeUrlIsEqual.some((subString) => url == subString))); } return false; } } //endregion //region Helpers class CookiesManager { static setCookie(cname, cvalue, expireSeconds) { const d = new Date(); d.setTime(d.getTime() + expireSeconds * 1000); let expires = 'expires=' + d.toUTCString(); let cookie_setting = cname + '=' + cvalue + ';' + expires + ';path=/'; console.log(cookie_setting); document.cookie = cookie_setting; } static getCookie(cname) { let name = cname + '='; let ca = document.cookie.split(';'); for (let i = 0; i < ca.length; i++) { let c = ca[i]; while (c.charAt(0) == ' ') { c = c.substring(1); } if (c.indexOf(name) == 0) { return c.substring(name.length, c.length); } } return undefined; } static checkCookie(cname) { let cookie_value = CookiesManager.getCookie(cname); if (cookie_value != undefined) return true; return false; } static isNotificationLoopClosedByUser() { // Check if notifications are stopped by user if (!this.checkCookie(this.Name.NOTIFICATIONS_CLOSED_BY_USER)) { this.setCookie(this.Name.NOTIFICATIONS_CLOSED_BY_USER, false); return false; } else { const notificationsClosedByUser = Utils.strToBool(this.getCookie(this.Name.NOTIFICATIONS_CLOSED_BY_USER)); if (notificationsClosedByUser) { return true; } return false; } } static setNotificationLoopClosedByUser(isEnables = false) { this.setCookie(this.Name.NOTIFICATIONS_CLOSED_BY_USER, true, Constants.NOTIFICATIONS_CLOSED_BY_USER_DURATION_IN_SECONDS); } static getOrCreateActivityId() { let activityId = CookiesManager.getCookie(CookiesManager.Name.ACTIVITY_ID); if (!activityId) { activityId = Utils.createUuid(); CookiesManager.setCookie(CookiesManager.Name.ACTIVITY_ID, activityId, Constants.ACTIVITY_ID_EXPIRATION_IN_SECONDS); } return activityId; } static getIsNotificationValid(notificationId) { let invalidationMarkExists = CookiesManager.getCookie(CookiesManager.Name.NOTIFICATION_IS_INVALID_PREFIX + '-' + notificationId); if (invalidationMarkExists) { return false; } return true; } static setNotificationAsInvalid(notificationId) { this.setCookie(CookiesManager.Name.NOTIFICATION_IS_INVALID_PREFIX + '-' + notificationId, true, Constants.NOTIFICATION_INVALID_STATE_DURATION_IN_SECONDS); } static getIsNotificationAlreadySeen(notificationId) { let alreadySeenMarkExists = CookiesManager.getCookie(CookiesManager.Name.NOTIFICATION_IS_ALREADY_SEEN + '-' + notificationId); if (alreadySeenMarkExists) { return true; } return false; } static setNotificationIsAlreadySeen(notificationId) { this.setCookie(CookiesManager.Name.NOTIFICATION_IS_ALREADY_SEEN + '-' + notificationId, true, Constants.NOTIFICATION_ALREADY_SEEN_STATE_DURATION_IN_SECONDS); } static removeCookie(cname) { CookiesManager.setCookie(cname, '', -1); } } CookiesManager.Name = { DEBUG_MODE: 'debug-mode-464s6544a4s54d', ACTIVITY_ID: 'activity-id-asre4qwgre6', NOTIFICATIONS_CLOSED_BY_USER: 'notifications_closed_by_user-s54g6s45', DAILY_ACTIVITY: 'daily-activity-4sr7t872s4', NOTIFICATION_IS_INVALID_PREFIX: 'invalid-notification-', NOTIFICATION_IS_ALREADY_SEEN: 'notification-seen-', ACTIVATED_SHOPTET_COUPON: 'activated-shoptet-coupon-235hnoi4h5' }; class LocalStorageManager { static getItem(sname) { let expiration = localStorage.getItem(sname + '_expiration'); if (expiration != null) { var expirationDate = new Date(JSON.parse(expiration)); if (expirationDate <= Date.now()) { localStorage.removeItem(sname); return null; } } var item = localStorage.getItem(sname); if (item == null) { return null; } return JSON.parse(item); } static setItem(sname, object, expireSeconds = null) { if (typeof object !== 'object' || object === null) { throw Error('Just objects are supported in local storage manager'); } localStorage.setItem(sname, JSON.stringify(object)); if (expireSeconds != null) { const d = new Date(); d.setTime(d.getTime() + expireSeconds * 1000); localStorage.setItem(sname + '_expiration', JSON.stringify(d)); } } } LocalStorageManager.Name = { WEBSITE_SETTINGS: 'website-settings-pixel-fsj5jlkj82827' }; class Utils { static createUuid() { return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) => (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16)); } static strToBool(value) { return value === 'true'; } static shuffleArray(array) { for (var i = array.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); var temp = array[i]; array[i] = array[j]; array[j] = temp; } } static sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } static isStyleTagExists(identifier) { return document.querySelector(`style[${identifier}]`) !== null; } static appendStyleTag(styleTag) { var link = document.createElement('link'); link.setAttribute('rel', 'stylesheet'); link.setAttribute('type', 'text/css'); link.setAttribute('href', 'https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap'); document.head.appendChild(link); document.head.appendChild(styleTag); } static hexToRGBA(hex, opacity) { let r = parseInt(hex.slice(1, 3), 16), g = parseInt(hex.slice(3, 5), 16), b = parseInt(hex.slice(5, 7), 16); if (opacity) { return `rgba(${r}, ${g}, ${b}, ${opacity})`; } else { return `rgb(${r}, ${g}, ${b})`; } } static isObjEmpty(obj) { return Object.keys(obj).length === 0; } } //endregion //region DataClasses class NotificationsStacks { /** * * @param showNotifications {Array.} * @param logNotifications {Array.} */ constructor(showNotifications, logNotifications, language) { this.showNotifications = showNotifications; this.logNotifications = logNotifications; this.language = language; } } class LogNotification { /** * @param campaign {Campaign} * @param notification {DataNotificationSettings} */ constructor(campaign, notification) { this.settings = notification; this.campaign = campaign; this.isValid = true; } isActiveForUrl(url) { if (!url) return false; const urlFilter = this.settings.urlFilter; return isUrlInFilter(urlFilter, url); } } const isUrlInFilter = (urlFilter, url) => { if (!urlFilter) return false; if ((urlFilter.includeUrlContains && urlFilter.includeUrlContains.some((subString) => url.includes(subString))) || (urlFilter.includeUrlBeginsWith && urlFilter.includeUrlBeginsWith.some((subString) => url.startsWith(subString))) || (urlFilter.includeUrlIsEqual && urlFilter.includeUrlIsEqual.some((subString) => url == subString))) { if ((urlFilter.excludeUrlContains && urlFilter.excludeUrlContains.some((subString) => url.includes(subString))) || (urlFilter.excludeUrlBeginsWith && urlFilter.excludeUrlBeginsWith.some((subString) => url.startsWith(subString))) || (urlFilter.excludeUrlIsEqual && urlFilter.excludeUrlIsEqual.some((subString) => url == subString))) { return false; } return true; } return false; }; class ShowNotification { /** * * @param campaign {Campaign} * @param notification {DataNotificationSettings} */ constructor(campaign, notification) { this.settings = notification; this.campaign = campaign; this.isValid = true; } } class Configuration { constructor(websiteId, backendUrl, isMobile, previewMode = false, debugMode = false) { /** * @type {boolean} */ this.previewMode = previewMode; /** * @type {string} */ this.websiteId = websiteId; this.backendUrl = backendUrl; this.mobileMode = isMobile; this.debugMode = debugMode; } } function convertJsonToCampaign(jsonData) { return new Campaign(jsonData.createdAt, jsonData.id, jsonData.isActive, jsonData.lastModifiedAt, jsonData.name, jsonData.notificationSettings, jsonData.notificationSettingsCount, jsonData.urlFilter, jsonData.visualPcSettings, jsonData.visualPhoneSettings, jsonData.notificationVisualSettings); } class Campaign { constructor(createdAt, id, isActive, lastModifiedAt, name, notificationSettings, notificationSettingsCount, urlFilter, visualPcSettings, visualPhoneSettings, notificationVisualSettings) { this.createdAt = createdAt; this.id = id; this.isActive = isActive; this.lastModifiedAt = lastModifiedAt; this.name = name; /** @type {Array.} */ this.notificationSettings = notificationSettings.map((notificationSetting) => convertJsonToNotificationSettings(notificationSetting)); this.notificationSettingsCount = notificationSettingsCount; this.urlFilter = convertJsonToUrlFilter(urlFilter); this.visualPcSettings = convertJsonToVisualPcMobileSetting(visualPcSettings); this.visualPhoneSettings = convertJsonToVisualPcMobileSetting(visualPhoneSettings); if (notificationVisualSettings) this.notificationVisualSettings = convertJsonToCampaingNotificationVisualSettings(notificationVisualSettings); else this.notificationVisualSettings = undefined; } } function convertJsonToNotificationSettings(jsonData) { return new DataNotificationSettings(jsonData.createdAt, jsonData.fallbackToGenericCustomer, jsonData.id, jsonData.isActive, jsonData.lastModifiedAt, jsonData.maxLastDays, jsonData.maxLastRegistrations, jsonData.minRegistrations, jsonData.notificationVisualSettings, jsonData.repeatNotification, jsonData.showCustomerOwnRegistrations, jsonData.text, jsonData.type, jsonData.urlFilter, jsonData.maxLastOrders, jsonData.minOrders, jsonData.showCustomerOwnOrders, jsonData.minVisitors, jsonData.minReviewStars, jsonData.minReviews, jsonData.name, jsonData.addLink, jsonData.linkAsButton, jsonData.openLinkInNewWindow, jsonData.linkText, jsonData.link, jsonData.discountCouponName, jsonData.discountCouponValue, jsonData.discountCouponType, jsonData.discountCouponAppliableTo); } class DataNotificationSettings { constructor(createdAt, fallbackToGenericCustomer, id, isActive, lastModifiedAt, maxLastDays, maxLastRegistrations, minRegistrations, notificationVisualSettings, repeatNotification, showCustomerOwnRegistrations, text, type, urlFilter, maxLastOrders, minOrders, showCustomerOwnOrders, minVisitors, minReviewStars, minReviews, name, addLink, linkAsButton, openLinkInNewWindow, linkText, link, discountCouponName, discountCouponValue, discountCouponType, discountCouponAppliableTo) { this.createdAt = createdAt; this.fallbackToGenericCustomer = fallbackToGenericCustomer; this.id = id; this.isActive = isActive; this.lastModifiedAt = lastModifiedAt; this.maxLastDays = maxLastDays; this.maxLastRegistrations = maxLastRegistrations; this.minRegistrations = minRegistrations; this.notificationVisualSettings = convertJsonToNotificationVisualSettings(notificationVisualSettings); this.repeatNotification = repeatNotification; this.showCustomerOwnRegistrations = showCustomerOwnRegistrations; this.text = text; this.type = type; this.urlFilter = convertJsonToUrlFilter(urlFilter); this.maxLastOrders = maxLastOrders; this.minOrders = minOrders; this.showCustomerOwnOrders = showCustomerOwnOrders; this.minVisitors = minVisitors; this.minReviewStars = minReviewStars; this.minReviews = minReviews; this.name = name; this.addLink = addLink; this.linkAsButton = linkAsButton; this.openLinkInNewWindow = openLinkInNewWindow; this.linkText = linkText; this.link = link; this.discountCouponName = discountCouponName; this.discountCouponValue = discountCouponValue; this.discountCouponType = discountCouponType; this.discountCouponAppliableTo = discountCouponAppliableTo; } } function convertJsonToNotificationVisualSettings(jsonData) { return new NotificationVisualSettings(jsonData === null || jsonData === void 0 ? void 0 : jsonData.backgroundColor, jsonData === null || jsonData === void 0 ? void 0 : jsonData.icon, jsonData === null || jsonData === void 0 ? void 0 : jsonData.iconBackgroundColor, jsonData === null || jsonData === void 0 ? void 0 : jsonData.iconColor, jsonData === null || jsonData === void 0 ? void 0 : jsonData.linkButtonBackgroundColor, jsonData === null || jsonData === void 0 ? void 0 : jsonData.linkButtonTextColor, jsonData === null || jsonData === void 0 ? void 0 : jsonData.linkTextColor, jsonData === null || jsonData === void 0 ? void 0 : jsonData.roundness, jsonData === null || jsonData === void 0 ? void 0 : jsonData.textColor); } class NotificationVisualSettings { constructor(backgroundColor, icon, iconBackgroundColor, iconColor, linkButtonBackgroundColor, linkButtonTextColor, linkTextColor, roundness, textColor) { this.backgroundColor = backgroundColor; this.icon = icon; this.iconBackgroundColor = iconBackgroundColor; this.iconColor = iconColor; this.linkButtonBackgroundColor = linkButtonBackgroundColor; this.linkButtonTextColor = linkButtonTextColor; this.linkTextColor = linkTextColor; this.roundness = roundness; this.textColor = textColor; } } function convertJsonToCampaingNotificationVisualSettings(jsonData) { return new CampaignNotificationVisualSettings(jsonData.roundness); } class CampaignNotificationVisualSettings { constructor(roundness) { this.roundness = roundness; } } function convertJsonToUrlFilter(jsonData) { return new UrlFilter(jsonData.excludeUrlBeginsWith, jsonData.excludeUrlContains, jsonData.excludeUrlIsEqual, jsonData.includeUrlBeginsWith, jsonData.includeUrlContains, jsonData.includeUrlIsEqual); } class UrlFilter { /** * * @param excludeUrlBeginsWith {Array.} * @param excludeUrlContains {Array.} * @param excludeUrlIsEqual {Array.} * @param includeUrlBeginsWith {Array.} * @param includeUrlContains {Array.} * @param includeUrlIsEqual {Array.} */ constructor(excludeUrlBeginsWith = [], excludeUrlContains = [], excludeUrlIsEqual = [], includeUrlBeginsWith = [], includeUrlContains = [], includeUrlIsEqual = []) { this.excludeUrlBeginsWith = excludeUrlBeginsWith; this.excludeUrlContains = excludeUrlContains; this.excludeUrlIsEqual = excludeUrlIsEqual; this.includeUrlBeginsWith = includeUrlBeginsWith; this.includeUrlContains = includeUrlContains; this.includeUrlIsEqual = includeUrlIsEqual; } } function convertJsonToVisualPcMobileSetting(jsonData) { const isEmpty = Utils.isObjEmpty(jsonData); if (isEmpty) { return undefined; } return new VisualPcPhoneSetting(jsonData.animationSpeed, jsonData.nextNotificationDelaySeconds, jsonData.position, jsonData.showAfterSeconds, jsonData.showDurationSeconds); } class VisualPcPhoneSetting { constructor(animationSpeed, nextNotificationDelaySeconds, position, showAfterSeconds, showDurationSeconds) { this.animationSpeed = animationSpeed; this.nextNotificationDelaySeconds = nextNotificationDelaySeconds; this.position = position; this.showAfterSeconds = showAfterSeconds; this.showDurationSeconds = showDurationSeconds; } } //endregion //region Sources class LanguageManager { /** * Describes given time window type * @param {*} masLastDays * @returns */ static getTimeWindowHumanForm(masLastDays, language) { let timeWindowDescription = ''; switch (masLastDays) { case 1: language === 'hu' ? (timeWindowDescription = '24 óra') : language === 'pl' ? (timeWindowDescription = '24 godziny') : language === 'sk' ? (timeWindowDescription = '24 hodín') : (timeWindowDescription = '24 hodin'); break; case 7: language === 'hu' ? (timeWindowDescription = '7 nap') : language === 'pl' ? (timeWindowDescription = '7 dni') : (timeWindowDescription = '7 dní'); break; case 30: language === 'hu' ? (timeWindowDescription = '30 nap') : language === 'pl' ? (timeWindowDescription = '30 dni') : (timeWindowDescription = '30 dní'); break; default: break; } const lastDays = language === 'hu' ? 'az utolsó' : language === 'pl' ? 'w ciągu ostatnich' : language === 'sk' ? 'za posledných' : 'za posledních'; return `${lastDays} ${timeWindowDescription}`; } static createReviewMessage(text, maxLength) { if (!text) return ' '; if (text.length > maxLength) text = text.substring(0, maxLength) + '...'; return `“${text}”`; } /** * Expect date in format Date (example: "2022-10-05T15:42:24.000Z") * @param {*} date * @returns */ static describeAgeInMinutesMessage(date, language) { const currentDate = new Date().getTime(); const timestamp = new Date(date).getTime(); const diffTime = Math.abs(currentDate - timestamp); const diffMinutes = Math.ceil(diffTime / (1000 * 60)); if (diffMinutes < 60) { // Minutes if (diffMinutes <= 1) { return language === 'hu' ? 'egy perce' : language === 'pl' ? 'minutę temu' : language === 'sk' ? 'pred minútou' : 'před minutou'; } return language === 'hu' ? `${diffMinutes} perccel ezelőtt` : language === 'pl' ? `${diffMinutes} minut temu` : language === 'sk' ? `pred ${diffMinutes} minútami` : `před ${diffMinutes} minutami`; } if (diffMinutes < 1440) { // Hours const hours = Math.floor(diffMinutes / 60); if (hours === 1) return language === 'hu' ? 'egy órája' : language === 'pl' ? 'godzinę temu' : language === 'sk' ? 'pred hodinou' : 'před hodinou'; return language === 'hu' ? `${hours} órával ezelőtt` : language === 'pl' ? `${hours} godzin temu` : language === 'sk' ? `pred ${hours} hodinami` : `před ${hours} hodinami`; } else { // Days const days = Math.floor(diffMinutes / 60 / 24); if (days === 1) return language === 'hu' ? 'tegnap' : language === 'pl' ? 'wczoraj' : 'včera'; return language === 'hu' ? ` ${days} nappal ezelőtt` : language === 'pl' ? `${days} dni temu` : language === 'sk' ? ` pred ${days} dňami` : ` před ${days} dny`; } } } _a = LanguageManager; LanguageManager.languageMap = { TextSingleOrder: { cs: 'má dokončenou objednávku', sk: 'má dokončenú objednávku', pl: 'złożył/a zamówienie', hu: 'befejezte a megrendelést' }, TextSingleRegistration: { cs: 'se přihlásil/a k odběru novinek', sk: 'sa prihlásil/a k odberu noviniek', pl: 'dokonał/a subskrypcji newslettera', hu: 'feliratkozott a hírlevélre' }, TextVisitorsName: { cs: 'návštěvníků', sk: 'návštevníkov', pl: 'użytkowników', hu: 'egyedi látogató' }, TextPeopleName: { cs: 'lidí', sk: 'ľudí', pl: 'osób', hu: 'személy' }, TextCurrentVisitors: { cs: 'si právě prohlíží tuto stránku', sk: 'si práve prezerá túto stránku', pl: 'właśnie ogląda tę stronę', hu: 'nézi jelenleg ezt az oldalt' }, TextVisitorSummary: { cs: 'navštívilo tuto stránku', sk: 'navštívilo túto stránku', pl: 'odwiedziło tę stronę', hu: 'látogatta meg ezt az oldalt' }, TextRegistrationSummary: { cs: 'se přihlásilo k odběru', sk: 'sa prihlásilo k odberu', pl: 'dokonało subskrypcji newslettera', hu: 'feliratkozott a hírlevélre' }, TextOrderSummary: { cs: 'si u nás nakoupilo', sk: 'si u nás nakúpilo', pl: 'zrobiło u nas zakupy', hu: 'vásárolt tőlünk' }, ShoptetLastOrders: { cs: 'právě objednal: ', sk: 'práve objednal: ', pl: 'właśnie zamówił: ', hu: 'most rendelt: ' } }; LanguageManager.getTranslate = (key, language) => { const translationNode = _a.languageMap[key]; if (!translationNode) { console.error('Translation failed for key: ', key); return 'not defined text'; } const translation = translationNode[language]; if (!translation) { console.error('Translation failed for key and lang: ', key, ' ', language); return 'not defined text'; } return translation; }; LanguageManager.createShoptetCouponMessage = (language, discountCouponName, discountCouponValue, discountCouponType, discountCouponAppliableTo) => { if (language === 'hu') { return `Aktiválja a "${discountCouponName}" kedvezménykódot, és kapjon ${discountCouponValue} ${discountCouponType} kedvezményt ${discountCouponAppliableTo}.`; } else if (language === 'sk') { return `Použite zľavový kód "${discountCouponName}" a získajte zľavu ${discountCouponValue} ${discountCouponType} na ${discountCouponAppliableTo}.`; } else if (language === 'pl') { return `Aktywuj kod rabatowy "${discountCouponName}", i uzyskaj ${discountCouponValue} ${discountCouponType} rabatu na ${discountCouponAppliableTo}.`; } else { return `Použijte slevový kód "${discountCouponName}" a získejte slevu ${discountCouponValue} ${discountCouponType} na ${discountCouponAppliableTo}.`; } }; LanguageManager.getOtherTranslations = (language) => { const otherTranslations = { cs: { Recommends: 'doporučuje', UseSale: 'Použít slevu', WeHaveSale: 'Máme pro vás slevu!', SaleUsed: 'Sleva použita' }, hu: { Recommends: 'ajánlott', UseSale: 'Kedvezmény aktiválása', WeHaveSale: 'Van egy kedvezmény!', SaleUsed: 'Kedvezmény aktiválva' }, sk: { Recommends: 'odporúča', UseSale: 'Uplatniť zľavu', WeHaveSale: 'Máme pre vás zľavu!', SaleUsed: 'Zľava uplatnená' }, pl: { Recommends: 'poleca', UseSale: 'Zastosuj zniżkę', WeHaveSale: 'Mamy dla Ciebie zniżkę!', SaleUsed: 'Zastosowano rabat' } }; return otherTranslations[language || 'cs']; }; class IconsLibrary { static getDefaultIconSvg(notificationType) { switch (notificationType) { case 'actualVisitors': return this.peopleSvg; case 'visitorSummary': return this.listAltSvg; case 'registrationSummary': return this.markMailReadSvg; case 'orderSummary': return this.addShoppingCartSvg; case 'heureka': return this.heurekaSvg; case 'zboziCompanyRating': return this.zboziSvg; case 'zboziProductRating': return this.zboziSvg; case 'individual': return this.notificationsActiveSvg; case 'lastRegistrations': return this.markMailReadSvg; case 'lastOrders': return this.addShoppingCartSvg; case 'spolehlivaRecenzeShopRating': return this.spolehlivaRecenzeSvg; case 'spolehlivaRecenzeProductRating': return this.spolehlivaRecenzeSvg; default: return null; } } static getIconSvgByName(iconName) { switch (iconName) { case 'Facebook': return this.facebookSvg; case 'Instagram': return this.instagramSvg; case 'Youtube': return this.youtubeSvg; case 'LocalShipping': return this.localShippingSvg; case 'Info': return this.infoSvg; case 'Mail': return this.mailSvg; case 'CardGiftcard': return this.cardGiftcardSvg; case 'Percent': return this.percentSvg; case 'NotificationsActive': return this.notificationsActiveSvg; case 'ProductionQuantityLimits': return this.productionQuantityLimitsSvg; case 'Favorite': return this.favoriteSvg; case 'EmojiEmotions': return this.emojiEmotionsSvg; case 'SentimentSatisfiedAlt': return this.sentimentSatisfiedAltSvg; case 'TouchApp': return this.touchAppSvg; case 'Alarm': return this.alarmSvg; case 'ChildFriendly': return this.childFriendlySvg; case 'StarIcon': return this.starIconSvg; case 'Visibility': return this.visibilitySvg; case 'Face': return this.faceSvg; case 'Face3': return this.face3Svg; case 'AddShoppingCart': return this.addShoppingCartSvg; case 'MarkMailRead': return this.markMailReadSvg; case 'ListAlt': return this.listAltSvg; case 'People': return this.peopleSvg; default: return null; } } } IconsLibrary.orderSvg = ` `; IconsLibrary.registrationSvg = ` `; IconsLibrary.visitorsSvg = ` `; IconsLibrary.summarySvg = ` `; IconsLibrary.heurekaSvg = ` `; IconsLibrary.zboziSvg = ` `; IconsLibrary.individualSvg = ` `; IconsLibrary.signatureSvg = ` `; IconsLibrary.starSvg = ` `; IconsLibrary.facebookSvg = ` `; IconsLibrary.instagramSvg = ` `; IconsLibrary.youtubeSvg = ` `; IconsLibrary.localShippingSvg = ` `; IconsLibrary.infoSvg = ` `; IconsLibrary.mailSvg = ` `; IconsLibrary.cardGiftcardSvg = ` `; IconsLibrary.percentSvg = ` `; IconsLibrary.notificationsActiveSvg = ` `; IconsLibrary.productionQuantityLimitsSvg = ` `; IconsLibrary.favoriteSvg = ` `; IconsLibrary.emojiEmotionsSvg = ` `; IconsLibrary.sentimentSatisfiedAltSvg = ` `; IconsLibrary.touchAppSvg = ` `; IconsLibrary.alarmSvg = ` `; IconsLibrary.childFriendlySvg = ` `; IconsLibrary.starIconSvg = ` `; IconsLibrary.visibilitySvg = ` `; IconsLibrary.faceSvg = ` `; IconsLibrary.face3Svg = ` `; IconsLibrary.addShoppingCartSvg = ` `; IconsLibrary.markMailReadSvg = ` `; IconsLibrary.listAltSvg = ` `; IconsLibrary.peopleSvg = ` `; IconsLibrary.checkSvg = ``; IconsLibrary.errorSvg = ``; IconsLibrary.spolehlivaRecenzeSvg = ``; //endregion //region Run script try { let previewMode = document.getElementById('notify-script').getAttribute('preview-mode') !== null ? true : false; let debugMode = document.getElementById('notify-script').getAttribute('debug-mode') !== null ? true : false; let isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent); let websiteId = document.getElementById('notify-script').getAttribute('website-id'); let backendUrl = document.getElementById('notify-script').getAttribute('backend-url'); const _config = new Configuration(websiteId, backendUrl, isMobile, previewMode, debugMode); const main = new Main(_config); main.run() .then((r) => { console.log('Script is successfuly running'); }) .catch((r) => { console.error('Při běhu pixel scriptu došlo k neočekávané chybě, kontaktujte prosím support ověřeného webu. Chyba: ', r); }); } catch (r) { console.error('Při běhu pixel scriptu došlo k neočekávané chybě, kontaktujte prosím support ověřeného webu. Chyba: ', r); // TODO: something terribly failed - maybe send slack bot message? } //endregion