{"version":3,"sources":["webpack:///./cartridges/app_storefront_widgets/cartridge/client/default/js/widgets/global/SessionExpiration.js"],"names":["Modal","SessionExpiration","prefs","initialTimeout","countdownTimeout","countdown","countdownCircleAnimated","countdownIcon","countdownCircleBg","sessionTimeoutUrl","sessionContinueUrl","init","onDestroy","clearDisposableResources","eventBus","on","resetInitialTimeout","started","Date","now","focusListener","ev","handlePageFocus","window","forEach","disposable","undefined","onOKResponse","pageFocused","timePassed","passedMoreThanInitialTimeout","passedMoreThanCountdown","sessionExpired","countdownShown","startCountdown","then","adjustCountdown","actualTime","countdownAdjust","initCountdown","actualTimeout","timeout","showModal","ref","setText","countdownCircle","get","TAU","Math","PI","radius","circleLength","setAttributeNS","String","time","countdownTimeoutSeconds","SimpleCountdown","default","progress","minutes","seconds","passedTimePercent","duration","visibleCircleLength","round","location","assign","continueSession","submitFormJson","response","setCurrentToken","csrf","tokenName","token","closeModal","cancel","finally","destroy"],"mappings":"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","file":"account.widgets~cart.widgets~checkout.widgets.bundle.js","sourcesContent":["import { submitFormJson } from 'widgets/toolbox/ajax';\nimport { timeout } from 'widgets/toolbox/util';\nimport { setCurrentToken } from '../toolbox/ajax';\n\n/**\n * @typedef {ReturnType } Modal\n */\n\n/**\n * @description Base SessionExpiration implementation\n * @param {Modal} Modal Base widget for extending\n * @returns {typeof SessionExpiration} SessionExpiration class\n */\nexport default function (Modal) {\n /**\n * @category widgets\n * @subcategory global\n * @class SessionExpiration\n * @augments Modal\n * @classdesc Session expiration component. Used to notify customer via popup, that his/her session is about to expire.\n * 1. At page loads starts a background timeout with configured time.\n * 2. After timeout, popup with session expiration alert will be shown. Popup also contains countdown before session will be expired.\n * 3. Any customer interaction with popup will lead to backend ping and CSRF token re-newal, which prolongs customer session.\n * 4. If popup was not closed - redirect to session expiration page happens.\n * @property {string} data-widget - Widget name `sessionExpiration`\n * @property {string} data-disable-rendering - Can disable modal dynamic content rendering.\n * Should be set to `true` in order countdown to work correctly!\n * @property {string} data-session-timeout-url - URL to redirect customer once session timeout\n * @property {string} data-session-continue-url - URL to get updated token and prolong customer's session\n * @property {number} data-initial-timeout - Initial timeout in minutes prior to expiration popup\n * @property {number} data-countdown-timeout - Countdown time in minutes up to session expires\n * @example Example of Session Expiration DOM structure\n * \n * \n * \n *
\n * \n *
\n *
\n * \n *
\n * \n * \n * \n * \n * \n * \n * \n *
\n * \n * \n * \n */\n class SessionExpiration extends Modal {\n prefs() {\n return {\n initialTimeout: 24,\n countdownTimeout: 5,\n countdown: 'countdown',\n countdownCircleAnimated: 'countdownCircleAnimated',\n countdownIcon: 'countdownIcon',\n countdownCircleBg: 'countdownCircleBg',\n sessionTimeoutUrl: '',\n sessionContinueUrl: '',\n ...super.prefs()\n };\n }\n\n /**\n * @description Widget initialization logic\n * @listens module:ajax#responseok\n * @listens dom#focus\n * @returns {void}\n */\n init() {\n super.init();\n this.onDestroy(() => this.clearDisposableResources());\n this.eventBus().on('responseok', 'onOKResponse');\n this.resetInitialTimeout();\n this.started = Date.now();\n\n this.focusListener = this.ev('focus', () => this.handlePageFocus(), window);\n this.onDestroy(() => {\n if (this.focusListener) {\n this.focusListener.forEach((disposable) => disposable());\n this.focusListener = undefined;\n }\n });\n }\n\n /**\n * @description Evaluates actions needed after success AJAX responce\n * @returns {void}\n */\n onOKResponse() {\n this.started = Date.now();\n this.resetInitialTimeout();\n }\n\n /**\n * @description Method needed to properly handle mobile/tablet devices either\n * after application switch or after device turn on after sleep mode, because mobile/tablet\n * platforms will suspend `setTimeout`/`setInterval` operations, when tab is in background or device is in sleep mode\n * Methos adjusts timings in comparison to last active time.\n * @returns {void}\n */\n handlePageFocus() {\n if (!this.started) {\n return;\n }\n\n const pageFocused = Date.now();\n const timePassed = (pageFocused - this.started) / 1000 / 60;\n\n const passedMoreThanInitialTimeout = timePassed > this.prefs().initialTimeout;\n const passedMoreThanCountdown = timePassed > (this.prefs().initialTimeout + this.prefs().countdownTimeout);\n\n if (passedMoreThanCountdown) {\n this.sessionExpired();\n return;\n }\n\n if (passedMoreThanInitialTimeout && !passedMoreThanCountdown) {\n // adjust countdown\n if (!this.countdownShown) {\n this.startCountdown().then(() => this.adjustCountdown(timePassed));\n } else {\n this.adjustCountdown(timePassed);\n }\n\n return;\n }\n\n // adjust initial timeout\n this.resetInitialTimeout((this.prefs().initialTimeout - timePassed) * 60 * 1000);\n }\n\n /**\n * @description Executes started countdown adjustment\n * @param {number} actualTime - actual time for countdown\n * @returns {void}\n */\n adjustCountdown(actualTime) {\n const countdownAdjust = (this.prefs().initialTimeout + this.prefs().countdownTimeout) - actualTime;\n this.clearDisposableResources();\n this.initCountdown(countdownAdjust * 60);\n }\n\n /**\n * @description Resets initial timeout and starts new timeout. Usually is called once any ajax request finishes\n * @param {number|undefined} actualTimeout - actual time for initial timeout\n * @returns {void}\n */\n resetInitialTimeout(actualTimeout = undefined) {\n this.clearDisposableResources();\n this.initialTimeout = timeout(() => {\n this.startCountdown();\n }, actualTimeout || (this.prefs().initialTimeout * 60 * 1000));\n }\n\n /**\n * @description Shows \"Session expires in...\" modal and starts countdown.\n * Once countdown finishes, trigger session expiration logic\n * @returns {Promise} result\n */\n startCountdown() {\n this.showModal();\n this.countdownShown = true;\n this.ref('countdown').setText(`${this.prefs().countdownTimeout}:00`);\n const countdownCircle = this.ref('countdownCircle').get();\n const countdownCircleBg = this.ref('countdownCircleBg').get();\n const countdownCircleAnimated = this.ref('countdownCircleAnimated').get();\n if (countdownCircle && countdownCircleAnimated && countdownCircleBg) {\n const TAU = Math.PI * 2;\n const radius = 92;\n this.circleLength = TAU * radius;\n countdownCircleBg.setAttributeNS(null, 'r', String(radius));\n countdownCircleAnimated.setAttributeNS(null, 'r', String(radius));\n }\n\n return this.initCountdown();\n }\n\n /**\n * @description Initiates countdown with predefined starting time\n * @param {number|undefined} time - time to start countdown\n * @returns {Promise} result\n */\n initCountdown(time = undefined) {\n const countdownCircleAnimated = this.ref('countdownCircleAnimated').get();\n const circleLength = this.circleLength || 0;\n const countdownTimeoutSeconds = this.prefs().countdownTimeout * 60;\n\n return import(/* webpackChunkName: 'simplecountdown' */'widgets/toolbox/SimpleCountdown').then((SimpleCountdown) => {\n // eslint-disable-next-line new-cap\n this.countdown = new SimpleCountdown.default(progress => {\n this.ref('countdown').setText(`${progress.minutes}:${progress.seconds}`);\n\n const passedTimePercent = 1 - (progress.duration / countdownTimeoutSeconds);\n const visibleCircleLength = circleLength - Math.round(circleLength * passedTimePercent);\n\n if (countdownCircleAnimated) {\n countdownCircleAnimated.setAttributeNS(null, 'stroke-dasharray',\n (visibleCircleLength + ',' + circleLength));\n }\n }, () => this.sessionExpired(), {\n time: time || this.prefs().countdownTimeout * 60\n });\n });\n }\n\n /**\n * @description Session expired logic. Redirects customer to given URL.\n * @returns {void}\n */\n sessionExpired() {\n this.clearDisposableResources();\n window.location.assign(this.prefs().sessionTimeoutUrl);\n }\n\n /**\n * @description Continue session logic. Sends request to update csrf-token.\n * @returns {Promise} result\n */\n continueSession() {\n return submitFormJson(this.prefs().sessionContinueUrl, {}).then((response) => {\n setCurrentToken(response.csrf.tokenName, response.csrf.token);\n this.closeModal();\n this.countdownShown = false;\n });\n }\n\n /**\n * @description Method, which is called once customer closes modal\n * (i.e. press close button or clicked outside modal)\n * @returns {void}\n */\n cancel() {\n this.continueSession().finally(() => {\n super.cancel();\n });\n }\n\n /**\n * @description Clear disposable resources\n * @returns {void}\n */\n clearDisposableResources() {\n if (this.initialTimeout) {\n this.initialTimeout();\n this.initialTimeout = undefined;\n }\n if (this.countdown) {\n this.countdown.destroy();\n this.countdown = undefined;\n }\n }\n }\n\n return SessionExpiration;\n}\n"],"sourceRoot":""}