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:
@@ -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)
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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; }
|
||||
|
||||
Reference in New Issue
Block a user