From 39d27ab9bb1bb228dc1a69afab3ea50ff65f52e2 Mon Sep 17 00:00:00 2001 From: Thomas Marstrander Date: Wed, 3 Apr 2019 09:43:09 +0200 Subject: [PATCH] JI-1059 Add offline request queue with retry dialog Add logic for adding extra class and hiding buttons in conf dialog Update font files with throbber --- fonts/h5p-core-20.eot | Bin 7764 -> 0 bytes fonts/h5p-core-20.ttf | Bin 7584 -> 0 bytes fonts/h5p-core-20.woff | Bin 7660 -> 0 bytes fonts/h5p-core-21.eot | Bin 0 -> 7784 bytes fonts/{h5p-core-20.svg => h5p-core-21.svg} | 12 +- fonts/h5p-core-21.ttf | Bin 0 -> 7604 bytes fonts/h5p-core-21.woff | Bin 0 -> 7680 bytes h5p.classes.php | 1 + js/h5p-confirmation-dialog.js | 34 ++- js/h5p.js | 15 +- js/request-queue.js | 233 ++++++++++++++++++--- styles/h5p-confirmation-dialog.css | 63 ++++++ styles/h5p.css | 10 +- 13 files changed, 314 insertions(+), 54 deletions(-) delete mode 100644 fonts/h5p-core-20.eot delete mode 100644 fonts/h5p-core-20.ttf delete mode 100644 fonts/h5p-core-20.woff create mode 100644 fonts/h5p-core-21.eot rename fonts/{h5p-core-20.svg => h5p-core-21.svg} (98%) create mode 100644 fonts/h5p-core-21.ttf create mode 100644 fonts/h5p-core-21.woff diff --git a/fonts/h5p-core-20.eot b/fonts/h5p-core-20.eot deleted file mode 100644 index a01133dd1ae453ce1ff12dd81caca1e08ce243fb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7764 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 Iaxv!r0K=bUb^rhX diff --git a/fonts/h5p-core-20.ttf b/fonts/h5p-core-20.ttf deleted file mode 100644 index 5103dc25bb75a94dfcb48c27bbcd99341c34f675..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7584 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 diff --git a/fonts/h5p-core-20.woff b/fonts/h5p-core-20.woff deleted file mode 100644 index 81982fcd3ef6ad42951ddbb71470b721145d35a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7660 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 f7LFa5KSH)b{Q^0LtK)fcOky<3 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 - + @@ -51,6 +51,6 @@ - + \ No newline at end of file diff --git a/fonts/h5p-core-21.ttf b/fonts/h5p-core-21.ttf new file mode 100644 index 0000000000000000000000000000000000000000..9c767365b4e4e7defadca9be4dc13b569b61e937 GIT binary patch literal 7604 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 KR~K?|&Hn)_cUHFm literal 0 HcmV?d00001 diff --git a/fonts/h5p-core-21.woff b/fonts/h5p-core-21.woff new file mode 100644 index 0000000000000000000000000000000000000000..32cc521e2a972a80fb3a5a9ff945c2c6a47173c0 GIT binary patch literal 7680 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 literal 0 HcmV?d00001 diff --git a/h5p.classes.php b/h5p.classes.php index 8e5f21f..52999cb 100644 --- a/h5p.classes.php +++ b/h5p.classes.php @@ -3489,6 +3489,7 @@ class H5PCore { 'offlineDialogBody' => $this->h5pF->t('We were unable to send information about your completion of this task. Please check your internet connection.'), 'offlineDialogRetryMessage' => $this->h5pF->t('Retrying in :num....'), 'offlineDialogRetryButtonLabel' => $this->h5pF->t('Retry now'), + 'offlineSuccessfulSubmit' => $this->h5pF->t('Successfully submitted results.'), ); } } diff --git a/js/h5p-confirmation-dialog.js b/js/h5p-confirmation-dialog.js index fa623c6..d082a35 100644 --- a/js/h5p-confirmation-dialog.js +++ b/js/h5p-confirmation-dialog.js @@ -11,6 +11,9 @@ H5P.ConfirmationDialog = (function (EventDispatcher) { * @param [options.dialogText] Dialog text * @param [options.cancelText] Cancel dialog button text * @param [options.confirmText] Confirm dialog button text + * @param [options.hideCancel] Hide cancel button + * @param [options.hideExit] Hide exit button + * @param [options.classes] Extra classes for popup * @constructor */ function ConfirmationDialog(options) { @@ -73,6 +76,12 @@ H5P.ConfirmationDialog = (function (EventDispatcher) { // Create outer popup var popup = document.createElement('div'); popup.classList.add('h5p-confirmation-dialog-popup', 'hidden'); + if (options.classes) { + options.classes.forEach(function (popupClass) { + popup.classList.add(popupClass); + }); + } + popup.setAttribute('role', 'dialog'); popup.setAttribute('aria-labelledby', 'h5p-confirmation-dialog-dialog-text-' + uniqueId); popupBackground.appendChild(popup); @@ -139,7 +148,14 @@ H5P.ConfirmationDialog = (function (EventDispatcher) { flowTo(confirmButton, e); } }); - buttons.appendChild(cancelButton); + + if (!options.hideCancel) { + buttons.appendChild(cancelButton); + } + else { + // Center buttons + buttons.classList.add('center'); + } // Confirm handler confirmButton.addEventListener('click', dialogConfirmed); @@ -148,7 +164,8 @@ H5P.ConfirmationDialog = (function (EventDispatcher) { dialogConfirmed(e); } else if (e.which === 9 && !e.shiftKey) { // Tab - flowTo(cancelButton, e); + const nextButton = !options.hideCancel ? cancelButton : confirmButton; + flowTo(nextButton, e); } }); buttons.appendChild(confirmButton); @@ -160,7 +177,9 @@ H5P.ConfirmationDialog = (function (EventDispatcher) { dialogCanceled(e); } }); - popup.appendChild(exitButton); + if (!options.hideExit) { + popup.appendChild(exitButton); + } // Wrapper element var wrapperElement; @@ -346,6 +365,15 @@ H5P.ConfirmationDialog = (function (EventDispatcher) { return this; }; + /** + * Retrieve element + * + * @return {HTMLElement} + */ + this.getElement = function () { + return popup; + }; + /** * Sets the minimum height of the view port * diff --git a/js/h5p.js b/js/h5p.js index cf1cac7..aed6375 100644 --- a/js/h5p.js +++ b/js/h5p.js @@ -66,20 +66,7 @@ H5P.init = function (target) { H5P.$body = H5P.jQuery(document.body); } - H5P.offlineRequestQueue = new H5P.RequestQueue(); - // We could handle previously failed requests here, instead we throw them away - // TODO: Add dialog - H5P.offlineRequestQueue.clear(); - H5P.offlineRequestQueue.on('requestQueued', function () { - }); - - H5P.offlineRequestQueue.on('processingQueue', function () { - }); - - H5P.offlineRequestQueue.on('queueEmptied', function () { - }); - - + H5P.offlineRequestQueue = new H5P.OfflineRequestQueue(); // Determine if we can use full screen if (H5P.fullscreenSupported === undefined) { diff --git a/js/request-queue.js b/js/request-queue.js index 3f1da2a..2459461 100644 --- a/js/request-queue.js +++ b/js/request-queue.js @@ -7,14 +7,15 @@ H5P.RequestQueue = (function ($, EventDispatcher) { /** * A queue for requests, will be automatically processed when regaining connection * - * @param {boolean} [options.showToast] Disable showing toast when losing or regaining connection + * @param {boolean} [options.showToast] Show toast when losing or regaining connection * @constructor */ const RequestQueue = function (options) { EventDispatcher.call(this); this.processingQueue = false; + options = options || {}; - this.showToast = options ? options.showToast : false; + this.showToast = options.showToast; this.itemName = 'requestQueue'; // Initialize listener for when requests are added to queue @@ -23,7 +24,7 @@ H5P.RequestQueue = (function ($, EventDispatcher) { }; /** - * Add request to queue + * Add request to queue. Only supports posts currently. * * @param {string} url * @param {Object} data @@ -46,7 +47,10 @@ H5P.RequestQueue = (function ($, EventDispatcher) { window.localStorage.setItem(this.itemName, JSON.stringify(storedStatements)); - this.trigger('requestQueued', storedStatements); + this.trigger('requestQueued', { + storedStatements: storedStatements, + processingQueue: this.processingQueue, + }); return true; }; @@ -73,7 +77,7 @@ H5P.RequestQueue = (function ($, EventDispatcher) { * * @returns {boolean} True if the storage was successfully cleared */ - RequestQueue.prototype.clear = function () { + RequestQueue.prototype.clearQueue = function () { if (!window.localStorage) { return false; } @@ -98,20 +102,16 @@ H5P.RequestQueue = (function ($, EventDispatcher) { return false; } - // Application is offline, re-send when we detect a connection - if (!window.navigator.onLine) { - return false; - } - - // We're online, attempt to send queued requests + // Attempt to send queued requests const queue = this.getStoredRequests(); const queueLength = queue.length; // Clear storage, failed requests will be re-added - this.clear(); + this.clearQueue(); // No items left in queue if (!queueLength) { + this.trigger('emptiedQueue', queue); return true; } @@ -169,28 +169,20 @@ H5P.RequestQueue = (function ($, EventDispatcher) { // Finished processing this queue this.processingQueue = false; - if (!window.navigator.onLine) { - return; - } - // Process next queue if items were added while processing current queue + // Run empty queue callback with next request queue const requestQueue = this.getStoredRequests(); - if (requestQueue.length) { - this.resumeQueue(); - return; - } - - // Run empty queue callback - this.trigger('queueEmptied'); + this.trigger('queueEmptied', requestQueue); }; /** * Display toast message on the first content of current page * * @param {string} msg Message to display + * @param {boolean} [forceShow] Force override showing the toast */ - RequestQueue.prototype.displayToastMessage = function (msg) { - if (!this.showToast) { + RequestQueue.prototype.displayToastMessage = function (msg, forceShow) { + if (!this.showToast && !forceShow) { return; } H5P.attachToastTo( @@ -228,4 +220,193 @@ H5P.RequestQueue = (function ($, EventDispatcher) { }; return RequestQueue; -})(H5P.jQuery, H5P.EventDispatcher); \ No newline at end of file +})(H5P.jQuery, H5P.EventDispatcher); + +/** + * Request queue for retrying failing requests, will automatically retry them when you come online + * + * @type {offlineRequestQueue} + */ +H5P.OfflineRequestQueue = (function (RequestQueue, Dialog) { + return function offlineRequestQueue() { + const requestQueue = new RequestQueue(); + + // We could handle requests from previous pages here, but instead we throw them away + requestQueue.clearQueue(); + + let startTime = null; + const retryIntervals = [10, 20, 40, 60, 120, 300, 600]; + let intervalIndex = -1; + let currentInterval = null; + let isAttached = false; + let isShowing = false; + let isLoading = false; + + const offlineDialog = new Dialog({ + headerText: H5P.t('offlineDialogHeader'), + dialogText: H5P.t('offlineDialogBody'), + confirmText: H5P.t('offlineDialogRetryButtonLabel'), + hideCancel: true, + hideExit: true, + classes: ['offline'], + }); + + + const dialog = offlineDialog.getElement(); + + // Add retry text to body + const countDownText = document.createElement('div'); + countDownText.classList.add('count-down'); + countDownText.innerHTML = H5P.t('offlineDialogRetryMessage') + .replace(':num', '0'); + + dialog.querySelector('.h5p-confirmation-dialog-text').appendChild(countDownText); + const countDownNum = countDownText.querySelector('.count-down-num'); + + // Create throbber + const throbberWrapper = document.createElement('div'); + throbberWrapper.classList.add('throbber-wrapper'); + const throbber = document.createElement('div'); + throbber.classList.add('sending-requests-throbber'); + throbberWrapper.appendChild(throbber); + + requestQueue.on('requestQueued', function (e) { + // Already processing queue, wait until queue has finished processing before showing dialog + if (e.data && e.data.processingQueue) { + return; + } + + if (!isAttached) { + const rootContent = document.body.querySelector('.h5p-content'); + if (!rootContent) { + return; + } + offlineDialog.appendTo(rootContent); + rootContent.appendChild(throbberWrapper); + isAttached = true; + } + + startCountDown(); + }.bind(this)); + + requestQueue.on('queueEmptied', function (e) { + if (e.data && e.data.length) { + // New requests were added while processing queue or requests failed again. Re-queue requests. + startCountDown(true); + return; + } + + // Successfully emptied queue + clearInterval(currentInterval); + toggleThrobber(false); + intervalIndex = -1; + if (isShowing) { + offlineDialog.hide(); + isShowing = false; + } + requestQueue.displayToastMessage(H5P.t('offlineSuccessfulSubmit'), true); + + }.bind(this)); + + offlineDialog.on('confirmed', function () { + // Show dialog on next render in case it is being hidden by the 'confirm' button + isShowing = false; + setTimeout(function () { + retryRequests(); + }, 100); + }.bind(this)); + + /** + * Toggle throbber visibility + * + * @param {boolean} [forceShow] Will force throbber visibility if set + */ + const toggleThrobber = function (forceShow) { + isLoading = !isLoading; + if (forceShow !== undefined) { + isLoading = forceShow; + } + + if (isLoading && isShowing) { + offlineDialog.hide(); + isShowing = false; + } + + if (isLoading) { + throbberWrapper.classList.add('show'); + } + else { + throbberWrapper.classList.remove('show'); + } + }; + + /** + * Retries the failed requests + */ + const retryRequests = function () { + clearInterval(currentInterval); + toggleThrobber(true); + requestQueue.resumeQueue(); + }; + + /** + * Increments retry interval + */ + const incrementRetryInterval = function () { + intervalIndex += 1; + if (intervalIndex >= retryIntervals.length) { + intervalIndex = retryIntervals.length - 1; + } + }; + + /** + * Starts counting down to retrying queued requests. + * + * @param forceDelayedShow + */ + const startCountDown = function (forceDelayedShow) { + toggleThrobber(false); + if (!isShowing) { + if (forceDelayedShow) { + // Must force delayed show since dialog may be hiding, and confirmation dialog does not + // support this. + setTimeout(function () { + offlineDialog.show(); + }, 100); + } + else { + offlineDialog.show(); + } + } + isShowing = true; + startTime = new Date().getTime(); + incrementRetryInterval(); + currentInterval = setInterval(updateCountDown, 100); + }; + + /** + * Updates the count down timer. Retries requests when time expires. + */ + const updateCountDown = function () { + const time = new Date().getTime(); + const timeElapsed = Math.floor((time - startTime) / 1000); + const timeLeft = retryIntervals[intervalIndex] - timeElapsed; + countDownNum.textContent = timeLeft.toString(); + + // Retry interval reached, retry requests + if (timeLeft <= 0) { + retryRequests(); + } + }; + + /** + * Add request to offline request queue. Only supports posts for now. + * + * @param {string} url The request url + * @param {Object} data The request data + */ + this.add = function (url, data) { + requestQueue.add(url, data); + }; + }; +})(H5P.RequestQueue, H5P.ConfirmationDialog); \ No newline at end of file diff --git a/styles/h5p-confirmation-dialog.css b/styles/h5p-confirmation-dialog.css index 5a8f597..3b13f68 100644 --- a/styles/h5p-confirmation-dialog.css +++ b/styles/h5p-confirmation-dialog.css @@ -116,3 +116,66 @@ button.h5p-confirmation-dialog-exit:hover { margin-top: -6px; display: inline-block; } + +.h5p-confirmation-dialog-popup.offline .h5p-confirmation-dialog-buttons { + float: none; + text-align: center; +} + +.h5p-confirmation-dialog-popup.offline .count-down { + font-family: Arial; + margin-top: 0.15em; + color: #000; +} + +.h5p-confirmation-dialog-popup.offline .h5p-confirmation-dialog-confirm-button:before { + content: "\e90b"; +} + +.throbber-wrapper { + display: none; + position: absolute; + height: 100%; + width: 100%; + top: 0; + left: 0; + z-index: 1; + background: rgba(44, 44, 44, 0.9); +} + +.throbber-wrapper.show { + display: block; +} + +.throbber-wrapper .throbber-container { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} + +.throbber-wrapper .sending-requests-throbber{ + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} + +.throbber-wrapper .sending-requests-throbber:before { + display: block; + font-family: 'H5P'; + content: "\e90b"; + color: white; + font-size: 10em; + animation: request-throbber 1.5s infinite linear; +} + +@keyframes request-throbber { + from { + transform: rotate(0); + } + + to { + transform: rotate(359deg); + } +} \ No newline at end of file diff --git a/styles/h5p.css b/styles/h5p.css index 1f81839..5a50326 100644 --- a/styles/h5p.css +++ b/styles/h5p.css @@ -3,11 +3,11 @@ /* Custom H5P font to use for icons. */ @font-face { font-family: 'h5p'; - src: url('../fonts/h5p-core-20.eot?cb8kvi'); - src: url('../fonts/h5p-core-20.eot?cb8kvi#iefix') format('embedded-opentype'), - url('../fonts/h5p-core-20.ttf?cb8kvi') format('truetype'), - url('../fonts/h5p-core-20.woff?cb8kvi') format('woff'), - url('../fonts/h5p-core-20.svg?cb8kvi#h5p') format('svg'); + src: url('../fonts/h5p-core-21.eot?mz1lkp'); + src: url('../fonts/h5p-core-21.eot?mz1lkp#iefix') format('embedded-opentype'), + url('../fonts/h5p-core-21.ttf?mz1lkp') format('truetype'), + url('../fonts/h5p-core-21.woff?mz1lkp') format('woff'), + url('../fonts/h5p-core-21.svg?mz1lkp#h5p') format('svg'); font-weight: normal; font-style: normal; }