diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 7d9c8c9d..7a082ae8 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -622,3 +622,33 @@ $bezier: cubic-bezier(0.75, 0, 0.25, 1); } } } + +// https://getbootstrap.com/docs/5.1/components/placeholders/ +.placeholder { + display: inline-block; + min-height: $spacer; + cursor: wait; + vertical-align: middle; + opacity: .5; + background-color: $grey; + animation: placeholder-glow 2s ease-in-out infinite; +} + +.placeholder-glow { + .placeholder { + -webkit-animation: placeholder-glow 2s ease-in-out infinite; + animation: placeholder-glow 2s ease-in-out infinite; + } + + @-webkit-keyframes placeholder-glow { + 50% { + opacity: .2; + } + } + + @keyframes placeholder-glow { + 50% { + opacity: .2; + } + } +} diff --git a/app/javascript/controllers/array_controller.js b/app/javascript/controllers/array_controller.js index 66cc2290..19d00ccd 100644 --- a/app/javascript/controllers/array_controller.js +++ b/app/javascript/controllers/array_controller.js @@ -1,7 +1,7 @@ import { Controller } from "stimulus"; export default class extends Controller { - static targets = ["item", "search", "current"]; + static targets = ["item", "search", "current", "placeholder"]; connect() { // TODO: Stimulus >1 @@ -104,12 +104,19 @@ export default class extends Controller { this.originalValue.push(itemTarget.dataset.value); this.newArrayValueURL.searchParams.set("value", itemTarget.dataset.value); + const placeholder = this.placeholderTarget.content.firstElementChild.cloneNode(true); + + this.currentTarget.appendChild(placeholder); + // TODO: Renderizarlas todas juntas fetch(this.newArrayValueURL) .then((response) => response.text()) - .then((body) => - this.currentTarget.insertAdjacentHTML("beforeend", body), - ); + .then((body) => { + const template = document.createElement("template"); + template.innerHTML = body; + + placeholder.replaceWith(template.content.firstElementChild); + }); } // TODO: Stimulus >1 diff --git a/app/views/posts/attributes/_new_array.haml b/app/views/posts/attributes/_new_array.haml index 8369f335..71c409a2 100644 --- a/app/views/posts/attributes/_new_array.haml +++ b/app/views/posts/attributes/_new_array.haml @@ -6,12 +6,15 @@ form_id = "form-#{Nanoid.generate}" %div{ data: { controller: 'modal array enter', 'array-original-value': metadata.value.to_json, 'array-new-array-value': site_posts_new_array_value_path(site) } } + %template{ data: { target: 'array.placeholder' } } + .col.mb-3{ 'aria-hidden': 'true' } + %span.placeholder.w-100 + .form-group = hidden_field_tag name, '' .d-flex.align-items-center.justify-content-between = label_tag id, post_label_t(attribute, post: post) = render 'bootstrap/btn', content: t('.edit'), action: 'modal#show' - .row.row-cols-1.row-cols-md-2{ data: { target: 'array.current' } } -# Mostramos la lista de valores actuales. Al aceptar el modal, se vacía el listado y se completa en base a @@ -23,6 +26,7 @@ Para poder cancelar, mantenemos el estado original y desactivamos o activamos los ítemes según estén incluidos en esa lista o no. + .row.row-cols-1.row-cols-md-2.no-gutters.placeholder-glow{ data: { target: 'array.current' } } - metadata.value.sort_by(&:remove_diacritics).each do |value| = render 'posts/new_array_value', value: value diff --git a/app/views/posts/attributes/_new_belongs_to.haml b/app/views/posts/attributes/_new_belongs_to.haml index 381b0e7b..afbc8bdd 100644 --- a/app/views/posts/attributes/_new_belongs_to.haml +++ b/app/views/posts/attributes/_new_belongs_to.haml @@ -19,6 +19,10 @@ value_list_id = "#{id}_body" %div{ id: modal_id, data: { controller: 'modal array', 'array-original-value': metadata.value.to_json, 'array-new-array-value': site_posts_new_related_post_path(site) } } + %template{ data: { target: 'array.placeholder' } } + .col.p-3{ 'aria-hidden': 'true' } + %span.placeholder.w-100 + .form-group = hidden_field_tag name, '' .d-flex.align-items-center.justify-content-between @@ -36,7 +40,7 @@ Para poder cancelar, mantenemos el estado original y desactivamos o activamos los ítemes según estén incluidos en esa lista o no. - .row.row-cols-3.row-cols-md-4{ data: { target: 'array.current' } } + .row.row-cols-3.row-cols-md-4.no-gutters.placeholder-glow{ data: { target: 'array.current' } } - metadata.values.slice(*metadata.value).each do |value| = render 'posts/new_array_value', value: value diff --git a/app/views/posts/attributes/_new_has_many.haml b/app/views/posts/attributes/_new_has_many.haml index 3aef2b86..143ad2d1 100644 --- a/app/views/posts/attributes/_new_has_many.haml +++ b/app/views/posts/attributes/_new_has_many.haml @@ -19,6 +19,10 @@ value_list_id = "#{id}_body" %div{ id: modal_id, data: { controller: 'modal array', 'array-original-value': metadata.value.to_json, 'array-new-array-value': site_posts_new_related_post_path(site) } } + %template{ data: { target: 'array.placeholder' } } + .col.p-3{ 'aria-hidden': 'true' } + %span.placeholder.w-100 + .form-group = hidden_field_tag name, '' .d-flex.align-items-center.justify-content-between @@ -35,7 +39,7 @@ Para poder cancelar, mantenemos el estado original y desactivamos o activamos los ítemes según estén incluidos en esa lista o no. - .row.row-cols-3.row-cols-md-4{ data: { target: 'array.current' } } + .row.row-cols-3.row-cols-md-4.no-gutters.placeholder-glow{ data: { target: 'array.current' } } - metadata.values.slice(*metadata.value).each do |value| = render 'posts/new_array_value', value: value diff --git a/app/views/posts/attributes/_new_predefined_array.haml b/app/views/posts/attributes/_new_predefined_array.haml index 09d8f7ce..ec251134 100644 --- a/app/views/posts/attributes/_new_predefined_array.haml +++ b/app/views/posts/attributes/_new_predefined_array.haml @@ -8,6 +8,10 @@ form_id = "form-#{Nanoid.generate}" %div{ data: { controller: 'modal array', 'array-original-value': metadata.value.to_json, 'array-new-array-value': site_posts_new_array_value_path(site) } } + %template{ data: { target: 'array.placeholder' } } + .col.mb-3{ 'aria-hidden': 'true' } + %span.placeholder.w-100 + .form-group = hidden_field_tag name, '' .d-flex.align-items-center.justify-content-between @@ -25,7 +29,7 @@ Para poder cancelar, mantenemos el estado original y desactivamos o activamos los ítemes según estén incluidos en esa lista o no. - .row.row-cols-1.row-cols-md-2{ data: { target: 'array.current' } } + .row.row-cols-1.row-cols-md-2.no-gutters.placeholder-glow{ data: { target: 'array.current' } } - metadata.values.slice(*metadata.value).each_key do |value| = render 'posts/new_array_value', value: value