mirror of
https://github.com/ae-utbm/sith.git
synced 2024-11-21 21:53:30 +00:00
improved feedback when loading ajax content
This commit is contained in:
parent
20c015c312
commit
7ea9a5ca2d
@ -93,6 +93,32 @@ a:not(.button) {
|
||||
}
|
||||
}
|
||||
|
||||
[aria-busy] {
|
||||
--loading-size: 50px;
|
||||
--loading-stroke: 5px;
|
||||
--loading-duration: 1s;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
[aria-busy]:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: var(--loading-size);
|
||||
height: var(--loading-size);
|
||||
margin-top: calc(var(--loading-size) / 2 * -1);
|
||||
margin-left: calc(var(--loading-size) / 2 * -1);
|
||||
border: var(--loading-stroke) solid rgba(0, 0, 0, .15);
|
||||
border-radius: 50%;
|
||||
border-top-color: rgba(0, 0, 0, 0.5);
|
||||
animation: rotate calc(var(--loading-duration)) linear infinite;
|
||||
}
|
||||
|
||||
@keyframes rotate {
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
.ib {
|
||||
display: inline-block;
|
||||
padding: 1px;
|
||||
|
@ -102,20 +102,10 @@ main {
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.paginator {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
width: -moz-fit-content;
|
||||
width: fit-content;
|
||||
background-color: rgba(0,0,0,.1);
|
||||
border-radius: 10px;
|
||||
padding: 10px;
|
||||
margin: 10px 0 10px auto;
|
||||
}
|
||||
|
||||
.photos,
|
||||
.albums {
|
||||
margin: 20px;
|
||||
min-height: 50px; // To contain the aria-busy loading wheel, even if empty
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
@ -96,7 +96,7 @@
|
||||
{% endif %}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="dynamic_view_content">
|
||||
<tbody id="dynamic_view_content" :aria-busy="loading">
|
||||
<template x-for="uv in uvs.results" :key="uv.id">
|
||||
<tr @click="window.location.href = `/pedagogy/uv/${uv.id}`" class="clickable">
|
||||
<td><a :href="`/pedagogy/uv/${uv.id}`" x-text="uv.code"></a></td>
|
||||
@ -140,6 +140,7 @@
|
||||
document.addEventListener("alpine:init", () => {
|
||||
Alpine.data("uv_search", () => ({
|
||||
uvs: [],
|
||||
loading: false,
|
||||
page: parseInt(initialUrlParams.get("page")) || page_default,
|
||||
page_size: parseInt(initialUrlParams.get("page_size")) || page_size_default,
|
||||
search: initialUrlParams.get("search") || "",
|
||||
@ -171,8 +172,10 @@
|
||||
},
|
||||
|
||||
async fetch_data() {
|
||||
this.loading = true;
|
||||
const url = "{{ url("api:fetch_uvs") }}" + window.location.search;
|
||||
this.uvs = await (await fetch(url)).json();
|
||||
this.loading = false;
|
||||
},
|
||||
|
||||
max_page() {
|
||||
|
@ -1,5 +1,4 @@
|
||||
{% extends "core/base.jinja" %}
|
||||
{% from "core/macros.jinja" import paginate %}
|
||||
|
||||
{%- block additional_css -%}
|
||||
<link rel="stylesheet" href="{{ scss('sas/album.scss') }}">
|
||||
@ -62,7 +61,7 @@
|
||||
|
||||
<div x-data="pictures">
|
||||
<h4>{% trans %}Pictures{% endtrans %}</h4>
|
||||
<div class="photos">
|
||||
<div class="photos" :aria-busy="loading">
|
||||
<template x-for="picture in pictures.results">
|
||||
<a :href="`/sas/picture/${picture.id}#pict`">
|
||||
<div class="photo" :style="`background-image: url(${picture.thumb_url})`">
|
||||
@ -81,13 +80,24 @@
|
||||
</template>
|
||||
</div>
|
||||
<nav class="pagination" x-show="nb_pages() > 1">
|
||||
<button @click="page--" :disabled="page <= 1">
|
||||
{# Adding the prevent here is important, because otherwise,
|
||||
clicking on the pagination buttons could submit the picture management form
|
||||
and reload the page #}
|
||||
<button
|
||||
@click.prevent="page--"
|
||||
:disabled="page <= 1"
|
||||
@keyup.right.window="page = Math.min(nb_pages(), page + 1)"
|
||||
>
|
||||
<i class="fa fa-caret-left"></i>
|
||||
</button>
|
||||
<template x-for="i in nb_pages()">
|
||||
<button x-text="i" @click="page = i":class="{active: page === i}"></button>
|
||||
<button x-text="i" @click.prevent="page = i" :class="{active: page === i}"></button>
|
||||
</template>
|
||||
<button @click="page++" :disabled="page >= nb_pages()">
|
||||
<button
|
||||
@click.prevent="page++"
|
||||
:disabled="page >= nb_pages()"
|
||||
@keyup.left.window="page = Math.max(1, page - 1)"
|
||||
>
|
||||
<i class="fa fa-caret-right"></i>
|
||||
</button>
|
||||
</nav>
|
||||
@ -95,9 +105,6 @@
|
||||
|
||||
{% if is_sas_admin %}
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
{% if user.is_in_group(pk=settings.SITH_GROUP_SAS_ADMIN_ID) %}
|
||||
<form class="add-files" id="upload_form" action="" method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
<div class="inputs">
|
||||
@ -122,18 +129,24 @@
|
||||
Alpine.data("pictures", () => ({
|
||||
pictures: {},
|
||||
page: parseInt(initialUrlParams.get("page")) || 1,
|
||||
loading: false,
|
||||
|
||||
async init() {
|
||||
await this.fetch_pictures();
|
||||
this.$watch("page", () => this.fetch_pictures());
|
||||
this.$watch("page", () => {
|
||||
update_query_string("page", this.page === 1 ? null : this.page);
|
||||
this.fetch_pictures()
|
||||
});
|
||||
},
|
||||
|
||||
async fetch_pictures() {
|
||||
update_query_string("page", this.page === 1 ? null : this.page);
|
||||
this.loading=true;
|
||||
const url = "{{ url("api:pictures") }}"
|
||||
+"?album_id={{ album.id }}"
|
||||
+`&page=${this.page}`
|
||||
+"&page_size={{ settings.SITH_SAS_IMAGES_PER_PAGE }}";
|
||||
this.pictures = await (await fetch(url)).json();
|
||||
this.loading=false;
|
||||
},
|
||||
|
||||
nb_pages() {
|
||||
@ -141,6 +154,7 @@
|
||||
}
|
||||
}))
|
||||
})
|
||||
|
||||
$("form#upload_form").submit(function (event) {
|
||||
let formData = new FormData($(this)[0]);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user