uploads: change loading indicator for upload widget.

Change the loading indicator from a progress bar to a spinner. Fixes
issue with the <progress> element having a different appearance on
different browsers.
This commit is contained in:
evazion
2022-02-18 02:52:24 -06:00
parent 093a808a36
commit 77515915a4
5 changed files with 40 additions and 8 deletions

View File

@@ -2,7 +2,7 @@
class ApplicationComponent < ViewComponent::Base
delegate :link_to_user, :time_ago_in_words_tagged, :format_text, :external_link_to, :tag_class, :current_page_path, to: :helpers
delegate :edit_icon, :delete_icon, :undelete_icon, :flag_icon, :upvote_icon, :downvote_icon, :link_icon, :sticky_icon, :unsticky_icon, :hashtag_icon, :caret_down_icon, :image_icon, to: :helpers
delegate :edit_icon, :delete_icon, :undelete_icon, :flag_icon, :upvote_icon, :downvote_icon, :link_icon, :sticky_icon, :unsticky_icon, :hashtag_icon, :caret_down_icon, :image_icon, :spinner_icon, to: :helpers
def policy(subject)
Pundit.policy!(current_user, subject)

View File

@@ -14,10 +14,10 @@
<%= f.input :source, label: false, as: :string, placeholder: "Paste URL here", input_html: { value: url, class: "text-center" }, wrapper_html: { class: "px-4 text-center" } %>
<%= f.input :referer_url, as: :hidden, input_html: { value: referer_url } %>
<%= f.submit "Upload", class: "button-primary text-center mx-auto hidden", "data-disable-with": false %>
<progress class="w-full hidden"></progress>
<% end %>
<%= spinner_icon(class: "hidden animate-spin absolute inset-0 m-auto h-12 link-color") %>
<template class="dropzone-preview-template">
<div class="dz-preview dz-file-preview flex flex-col text-center space-y-4">
<img class="object-contain px-8 max-h-360px max-w-full" data-dz-thumbnail>

View File

@@ -81,7 +81,7 @@ module IconHelper
end
def spinner_icon(**options)
icon_tag("fas fa-spinner fa-spin", **options)
svg_icon_tag("spinner-icon", "M304 48C304 74.51 282.5 96 256 96C229.5 96 208 74.51 208 48C208 21.49 229.5 0 256 0C282.5 0 304 21.49 304 48zM304 464C304 490.5 282.5 512 256 512C229.5 512 208 490.5 208 464C208 437.5 229.5 416 256 416C282.5 416 304 437.5 304 464zM0 256C0 229.5 21.49 208 48 208C74.51 208 96 229.5 96 256C96 282.5 74.51 304 48 304C21.49 304 0 282.5 0 256zM512 256C512 282.5 490.5 304 464 304C437.5 304 416 282.5 416 256C416 229.5 437.5 208 464 208C490.5 208 512 229.5 512 256zM74.98 437C56.23 418.3 56.23 387.9 74.98 369.1C93.73 350.4 124.1 350.4 142.9 369.1C161.6 387.9 161.6 418.3 142.9 437C124.1 455.8 93.73 455.8 74.98 437V437zM142.9 142.9C124.1 161.6 93.73 161.6 74.98 142.9C56.24 124.1 56.24 93.73 74.98 74.98C93.73 56.23 124.1 56.23 142.9 74.98C161.6 93.73 161.6 124.1 142.9 142.9zM369.1 369.1C387.9 350.4 418.3 350.4 437 369.1C455.8 387.9 455.8 418.3 437 437C418.3 455.8 387.9 455.8 369.1 437C350.4 418.3 350.4 387.9 369.1 369.1V369.1z", viewbox: "0 0 512 512", **options)
end
def external_link_icon(**options)

View File

@@ -92,11 +92,22 @@ export default class FileUploadComponent {
this.pollStatus(upload);
}
loadingStart() {
this.$component.find(".spinner-icon").removeClass("hidden");
this.$component.find("input").attr("disabled", "disabled");
this.$component.find("form").addClass("pointer-events-none cursor-wait opacity-50");
}
loadingStop() {
this.$component.find(".spinner-icon").addClass("hidden");
this.$component.find("input").removeAttr("disabled");
this.$component.find("form").removeClass("pointer-events-none cursor-wait opacity-50");
}
// Called after the upload is submitted via AJAX. Polls the upload until it
// is complete, then redirects to the upload page.
async pollStatus(upload) {
this.$component.find("progress").removeClass("hidden");
this.$component.find("input").attr("disabled", "disabled");
this.loadingStart();
while (upload.media_asset_count <= 1 && upload.status !== "completed" && upload.status !== "error") {
await Utility.delay(FileUploadComponent.POLL_DELAY);
@@ -105,8 +116,7 @@ export default class FileUploadComponent {
if (upload.status === "error") {
this.$dropzone.removeClass("success");
this.$component.find("progress").addClass("hidden");
this.$component.find("input").removeAttr("disabled");
this.loadingStop();
Utility.error(`Upload failed: ${upload.error}.`);
} else {

View File

@@ -16,6 +16,7 @@ $spacer: 0.25rem; /* 4px */
.cursor-pointer { cursor: pointer; }
.cursor-zoom-in { cursor: zoom-in; }
.cursor-zoom-out { cursor: zoom-out; }
.cursor-wait { cursor: wait; }
.hidden { display: none !important; }
.inline-block { display: inline-block; }
@@ -48,6 +49,8 @@ $spacer: 0.25rem; /* 4px */
.pointer-events-none { pointer-events: none; }
.select-none { user-select: none; }
.opacity-50 { opacity: 0.5; }
.leading-none { line-height: 1; }
.leading-normal { line-height: 1.5; }
@@ -59,6 +62,8 @@ $spacer: 0.25rem; /* 4px */
.left-0\.5 { left: 0.5 * $spacer; }
.right-0\.5 { right: 0.5 * $spacer; }
.inset-0 { top: 0; right: 0; bottom: 0; left: 0 }
.border, %border { border-width: 1px; }
.border-b { border-bottom-width: 1px; }
@@ -79,6 +84,7 @@ $spacer: 0.25rem; /* 4px */
.object-contain { object-fit: contain; }
.m-auto { margin: auto; }
.m-0 { margin: 0; }
.m-px { margin: 1px; }
.m-0\.5 { margin: 0.5 * $spacer; }
@@ -199,6 +205,8 @@ $spacer: 0.25rem; /* 4px */
.grid-cols-8 { grid-template-columns: repeat(8, minmax(0, 1fr)); }
.grid-cols-12 { grid-template-columns: repeat(12, minmax(0, 1fr)); }
.link-color { color: var(--link-color); }
.card {
@extend %border;
@extend %rounded-lg;
@@ -259,6 +267,20 @@ $spacer: 0.25rem; /* 4px */
}
}
.animate-spin {
animation: animate-spin 1s linear infinite;
}
@keyframes animate-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
@media screen and (min-width: 660px) {
.md\:inline-block { display: inline-block; }
.md\:block { display: block; }