From 5d569e89266d4d6b97134e6abc9ecb71986d9b3d Mon Sep 17 00:00:00 2001 From: Fabien Basmaison Date: Wed, 7 Apr 2021 09:24:34 +0200 Subject: [PATCH] [assets] Only update status if the promise is successful: - Use promises in `ajaxPost` and `interact`. - Add some animations in CSS. --- bookwyrm/static/css/bookwyrm.css | 28 ++++++++++++++++++ bookwyrm/static/js/bookwyrm.js | 51 ++++++++++++++++++++++++-------- 2 files changed, 67 insertions(+), 12 deletions(-) diff --git a/bookwyrm/static/css/bookwyrm.css b/bookwyrm/static/css/bookwyrm.css index a01aff827..980b4c4a2 100644 --- a/bookwyrm/static/css/bookwyrm.css +++ b/bookwyrm/static/css/bookwyrm.css @@ -224,3 +224,31 @@ html { content: "\e905"; right: 0; } + +/** Animations and transitions + ******************************************************************************/ + +@keyframes beating { + 0% { font-size: 100%; } + 25% { font-size: 125%; } + 100% { font-size: 75%; } +} + +@keyframes turning { + from { transform: rotateZ(0deg); } + to { transform: rotateZ(360deg); } +} + +.is-processing .icon-heart::before { + animation: beating 0.5s infinite alternate ease-in-out; +} + +.is-processing .icon-boost::before { + animation: turning 0.5s infinite ease-in-out; +} + +@media (prefers-reduced-motion: reduce) { + .is-processing .icon::before { + animation-duration: 1.5s; + } +} diff --git a/bookwyrm/static/js/bookwyrm.js b/bookwyrm/static/js/bookwyrm.js index f36df1094..0531b4d76 100644 --- a/bookwyrm/static/js/bookwyrm.js +++ b/bookwyrm/static/js/bookwyrm.js @@ -241,8 +241,6 @@ let BookWyrm = new class { * Make a request and update the UI accordingly. * This function is used for boosts and favourites. * - * @todo Only update status if the promise is successful. - * * @param {Event} event * * @return {undefined} @@ -250,15 +248,44 @@ let BookWyrm = new class { interact(event) { event.preventDefault(); - this.ajaxPost(event.target); + const bookwyrm = this; - // @todo This probably should be done with IDs. - document.querySelectorAll(`.${event.target.dataset.id}`) - .forEach(node => this.addRemoveClass( - node, - 'hidden', - node.className.indexOf('hidden') == -1 - )); + let allTriggers = document.querySelectorAll(`.${event.target.dataset.id}`); + + // Change icon to show ongoing activity on the current UI. + allTriggers.forEach(node => bookwyrm.addRemoveClass( + node, + 'is-processing', + true + )); + + this.ajaxPost(event.target) + .finally(() => { + // Change icon to remove ongoing activity on the current UI. + allTriggers.forEach(node => bookwyrm.addRemoveClass( + node, + 'is-processing', + false + )); + }) + .then(function() { + allTriggers.forEach(node => bookwyrm.addRemoveClass( + node, + 'hidden', + node.className.indexOf('hidden') == -1 + )); + }) + .catch(error => { + // @todo Display a notification in the UI instead. + // For now, the absence of change will be enough. + console.warn('Request failed:', error); + + allTriggers.forEach(node => bookwyrm.addRemoveClass( + node, + 'has-error', + node.className.indexOf('hidden') == -1 + )); + }); } /** @@ -266,10 +293,10 @@ let BookWyrm = new class { * * @param {object} form - Form to be submitted * - * @return {undefined} + * @return {Promise} */ ajaxPost(form) { - fetch(form.action, { + return fetch(form.action, { method : "POST", body: new FormData(form) });