From 8bda0bc0dc03d1626f7932fedd4a634a1f5b140a Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 16 Dec 2021 11:06:53 -0800 Subject: [PATCH 01/53] Removes check_all javascript that is no longer used --- bookwyrm/static/js/check_all.js | 34 -------------------- bookwyrm/templates/import/import_status.html | 4 --- 2 files changed, 38 deletions(-) delete mode 100644 bookwyrm/static/js/check_all.js diff --git a/bookwyrm/static/js/check_all.js b/bookwyrm/static/js/check_all.js deleted file mode 100644 index fd29f2cd..00000000 --- a/bookwyrm/static/js/check_all.js +++ /dev/null @@ -1,34 +0,0 @@ - -(function() { - 'use strict'; - - /** - * Toggle all descendant checkboxes of a target. - * - * Use `data-target="ID_OF_TARGET"` on the node on which the event is listened - * to (checkbox, button, link…), where_ID_OF_TARGET_ should be the ID of an - * ancestor for the checkboxes. - * - * @example - * - * @param {Event} event - * @return {undefined} - */ - function toggleAllCheckboxes(event) { - const mainCheckbox = event.target; - - document - .querySelectorAll(`#${mainCheckbox.dataset.target} [type="checkbox"]`) - .forEach(checkbox => checkbox.checked = mainCheckbox.checked); - } - - document - .querySelectorAll('[data-action="toggle-all"]') - .forEach(input => { - input.addEventListener('change', toggleAllCheckboxes); - }); -})(); diff --git a/bookwyrm/templates/import/import_status.html b/bookwyrm/templates/import/import_status.html index b3d20987..374ea22c 100644 --- a/bookwyrm/templates/import/import_status.html +++ b/bookwyrm/templates/import/import_status.html @@ -234,7 +234,3 @@ {% endif %} {% endspaceless %}{% endblock %} - -{% block scripts %} - -{% endblock %} From 8eb340945bd29ff55089912e2ce96e614d490214 Mon Sep 17 00:00:00 2001 From: Joel Bradshaw Date: Thu, 16 Dec 2021 08:47:03 +0000 Subject: [PATCH 02/53] Add sync_media_to_s3 command This is useful if the copy gets aborted, or to sync over remnants generated between the copy and the switchover to S3 --- bw-dev | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/bw-dev b/bw-dev index cfe8747f..0a06b5ed 100755 --- a/bw-dev +++ b/bw-dev @@ -146,7 +146,13 @@ case "$CMD" in awscommand "bookwyrm_media_volume:/images"\ "s3 cp /images s3://${AWS_STORAGE_BUCKET_NAME}/images\ --endpoint-url ${AWS_S3_ENDPOINT_URL}\ - --recursive --acl public-read" + --recursive --acl public-read" "$@" + ;; + sync_media_to_s3) + awscommand "bookwyrm_media_volume:/images"\ + "s3 sync /images s3://${AWS_STORAGE_BUCKET_NAME}/images\ + --endpoint-url ${AWS_S3_ENDPOINT_URL}\ + --acl public-read" "$@" ;; set_cors_to_s3) awscommand "$(pwd):/bw"\ @@ -184,6 +190,7 @@ case "$CMD" in echo " generate_thumbnails" echo " generate_preview_images [--all]" echo " copy_media_to_s3" + echo " sync_media_to_s3" echo " set_cors_to_s3 [cors file]" echo " runweb [command]" ;; From 37a7899f6f72f8b2e77a790ef7ff1222f302ac58 Mon Sep 17 00:00:00 2001 From: Joel Bradshaw Date: Thu, 16 Dec 2021 08:48:34 +0000 Subject: [PATCH 03/53] Consistently quote $@, check for argument Also add $@ to a couple commands, and add a check for the argument to the CORS command since it's required --- bw-dev | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/bw-dev b/bw-dev index 0a06b5ed..97a38834 100755 --- a/bw-dev +++ b/bw-dev @@ -131,7 +131,7 @@ case "$CMD" in makeitblack ;; populate_streams) - runweb python manage.py populate_streams $@ + runweb python manage.py populate_streams "$@" ;; populate_suggestions) runweb python manage.py populate_suggestions @@ -140,7 +140,7 @@ case "$CMD" in runweb python manage.py generateimages ;; generate_preview_images) - runweb python manage.py generate_preview_images $@ + runweb python manage.py generate_preview_images "$@" ;; copy_media_to_s3) awscommand "bookwyrm_media_volume:/images"\ @@ -155,11 +155,18 @@ case "$CMD" in --acl public-read" "$@" ;; set_cors_to_s3) + set +x + config_file=$1 + if [ -z "$config_file" ]; then + echo "This command requires a JSON file containing a CORS configuration as an argument" + exit 1 + fi + set -x awscommand "$(pwd):/bw"\ "s3api put-bucket-cors\ --bucket ${AWS_STORAGE_BUCKET_NAME}\ --endpoint-url ${AWS_S3_ENDPOINT_URL}\ - --cors-configuration file:///bw/$@" + --cors-configuration file:///bw/$config_file" "$@" ;; runweb) runweb "$@" From faffbdce21ae143205a7e8a40f1686d9cb6ed263 Mon Sep 17 00:00:00 2001 From: Joel Bradshaw Date: Thu, 16 Dec 2021 23:44:47 -0800 Subject: [PATCH 04/53] Fix spacing --- bw-dev | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bw-dev b/bw-dev index 97a38834..da36ae05 100755 --- a/bw-dev +++ b/bw-dev @@ -155,13 +155,13 @@ case "$CMD" in --acl public-read" "$@" ;; set_cors_to_s3) - set +x + set +x config_file=$1 if [ -z "$config_file" ]; then echo "This command requires a JSON file containing a CORS configuration as an argument" exit 1 fi - set -x + set -x awscommand "$(pwd):/bw"\ "s3api put-bucket-cors\ --bucket ${AWS_STORAGE_BUCKET_NAME}\ From 355405daa3296f20ebb5161002650a59fc195d9c Mon Sep 17 00:00:00 2001 From: Joachim Date: Fri, 17 Dec 2021 20:40:58 +0100 Subject: [PATCH 05/53] Front-end: Fix Safari details display and enhance dropdown on mobile --- bookwyrm/static/css/bookwyrm.css | 68 +++++++++++-- bookwyrm/static/js/bookwyrm.js | 100 ++++++++++++++++++++ bookwyrm/templates/components/dropdown.html | 2 +- 3 files changed, 159 insertions(+), 11 deletions(-) diff --git a/bookwyrm/static/css/bookwyrm.css b/bookwyrm/static/css/bookwyrm.css index f385e629..45d976e3 100644 --- a/bookwyrm/static/css/bookwyrm.css +++ b/bookwyrm/static/css/bookwyrm.css @@ -93,6 +93,10 @@ body { display: inline !important; } + +/** File input styles + ******************************************************************************/ + input[type=file]::file-selector-button { -moz-appearance: none; -webkit-appearance: none; @@ -119,17 +123,12 @@ input[type=file]::file-selector-button:hover { color: #363636; } -details .dropdown-menu { - display: block !important; -} -details.dropdown[open] summary.dropdown-trigger::before { - content: ""; - position: fixed; - top: 0; - bottom: 0; - left: 0; - right: 0; +/** General `details` element styles + ******************************************************************************/ + +summary::-webkit-details-marker { + display: none; } summary::marker { @@ -147,6 +146,55 @@ summary::marker { margin-top: 1em; } +/** Details dropdown + ******************************************************************************/ + +details.dropdown[open] summary.dropdown-trigger::before { + content: ""; + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; +} + +details .dropdown-menu { + display: block !important; +} + +details .dropdown-menu button { + /* Fix weird Safari defaults */ + box-sizing: border-box; +} + +details.dropdown .dropdown-menu button:focus-visible, +details.dropdown .dropdown-menu a:focus-visible { + outline-style: auto; + outline-offset: -2px; +} + +@media only screen and (max-width: 768px) { + details.dropdown[open] summary.dropdown-trigger::before { + background-color: rgba(0, 0, 0, 0.5); + z-index: 30; + } + details .dropdown-menu { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + display: flex !important; + align-items: center; + justify-content: center; + pointer-events: none; + z-index: 100; + } + details .dropdown-menu > * { + pointer-events: all; + } +} + /** Shelving ******************************************************************************/ diff --git a/bookwyrm/static/js/bookwyrm.js b/bookwyrm/static/js/bookwyrm.js index 2b78bf51..3e0b1ad8 100644 --- a/bookwyrm/static/js/bookwyrm.js +++ b/bookwyrm/static/js/bookwyrm.js @@ -51,6 +51,12 @@ let BookWyrm = new class { 'click', this.duplicateInput.bind(this) + )) + document.querySelectorAll('details.dropdown') + .forEach(node => node.addEventListener( + 'toggle', + this.handleDetailsDropdown.bind(this) + )) } @@ -482,4 +488,98 @@ let BookWyrm = new class { textareaEl.parentNode.appendChild(copyButtonEl) } + + /** + * Handle the details dropdown component. + * + * @param {Event} event - Event fired by a `details` element + * with the `dropdown` class name, on toggle. + * @return {undefined} + */ + handleDetailsDropdown(event) { + const detailsElement = event.target; + const summaryElement = detailsElement.querySelector('summary'); + const menuElement = detailsElement.querySelector('.dropdown-menu'); + const htmlElement = document.querySelector('html'); + + if (detailsElement.open) { + // Focus first menu element + menuElement.querySelectorAll( + 'a[href]:not([disabled]), button:not([disabled])' + )[0].focus(); + // Enable focus trap + menuElement.addEventListener('keydown', this.handleFocusTrap); + // Close on Esc + detailsElement.addEventListener('keydown', handleEscKey); + + // Clip page if Mobile + if (this.isMobile()) { + htmlElement.classList.add('is-clipped'); + } + } else { + summaryElement.focus(); + // Disable focus trap + menuElement.removeEventListener('keydown', this.handleFocusTrap); + + // Unclip page + if (this.isMobile()) { + htmlElement.classList.remove('is-clipped'); + } + } + + function handleEscKey(event) { + if (event.key !== 'Escape') { + return; + } + + summaryElement.click(); + } + } + + /** + * Check if windows matches mobile media query. + * + * @return {Boolean} + */ + isMobile() { + return window.matchMedia("(max-width: 768px)").matches; + } + + /** + * Focus trap handler + * + * @param {Event} event - Keydown event. + * @return {undefined} + */ + handleFocusTrap(event) { + if (event.key !== 'Tab') { + return; + } + + const focusableEls = event.currentTarget.querySelectorAll( + [ + 'a[href]:not([disabled])', + 'button:not([disabled])', + 'textarea:not([disabled])', + 'input:not([type="hidden"]):not([disabled])', + 'select:not([disabled])', + 'details:not([disabled])', + '[tabindex]:not([tabindex="-1"]):not([disabled])' + ].join(',') + ); + const firstFocusableEl = focusableEls[0]; + const lastFocusableEl = focusableEls[focusableEls.length - 1]; + + if (event.shiftKey ) /* Shift + tab */ { + if (document.activeElement === firstFocusableEl) { + lastFocusableEl.focus(); + event.preventDefault(); + } + } else /* Tab */ { + if (document.activeElement === lastFocusableEl) { + firstFocusableEl.focus(); + event.preventDefault(); + } + } + } }(); diff --git a/bookwyrm/templates/components/dropdown.html b/bookwyrm/templates/components/dropdown.html index b3710271..0e07bf99 100644 --- a/bookwyrm/templates/components/dropdown.html +++ b/bookwyrm/templates/components/dropdown.html @@ -15,7 +15,7 @@ {% block dropdown-trigger %}{% endblock %} -