2016-11-20 09:40:49 +00:00
|
|
|
{% extends "core/base.jinja" %}
|
|
|
|
|
2023-03-30 12:38:40 +00:00
|
|
|
{%- block additional_css -%}
|
2024-07-23 10:11:19 +00:00
|
|
|
<link rel="stylesheet" href="{{ scss('sas/album.scss') }}">
|
2023-03-30 12:38:40 +00:00
|
|
|
{%- endblock -%}
|
|
|
|
|
2024-07-23 10:11:19 +00:00
|
|
|
{% block additional_js %}
|
|
|
|
<script defer type="module">
|
|
|
|
import { showSaveFilePicker } from "{{ static('core/js/native-file-system-adapter/mod.js') }}";
|
|
|
|
window.showSaveFilePicker = showSaveFilePicker; /* Export function to normal javascript */
|
|
|
|
</script>
|
2024-07-30 09:11:31 +00:00
|
|
|
<script defer type="text/javascript" src="{{ static('core/js/zipjs/zip-fs-full.min.js') }}"></script>
|
2024-08-10 12:49:02 +00:00
|
|
|
<script defer type="text/javascript" src="{{ static('core/js/alpine/intersect.min.js') }}"></script>
|
2024-07-23 10:11:19 +00:00
|
|
|
{% endblock %}
|
|
|
|
|
2016-11-20 09:40:49 +00:00
|
|
|
{% block title %}
|
2024-07-23 10:11:19 +00:00
|
|
|
{% trans user_name=profile.get_display_name() %}{{ user_name }}'s pictures{% endtrans %}
|
2016-11-20 09:40:49 +00:00
|
|
|
{% endblock %}
|
|
|
|
|
|
|
|
{% block content %}
|
2024-08-10 12:49:02 +00:00
|
|
|
<main x-data="user_pictures">
|
2024-08-09 15:33:07 +00:00
|
|
|
{% if user.id == object.id %}
|
|
|
|
<div x-show="pictures.length > 0" x-cloak>
|
2024-07-30 17:23:48 +00:00
|
|
|
<button
|
2024-08-10 12:49:02 +00:00
|
|
|
:disabled="is_downloading"
|
2024-07-30 17:57:56 +00:00
|
|
|
class="btn btn-blue"
|
2024-08-05 17:25:30 +00:00
|
|
|
@click="download_zip()"
|
2024-07-30 17:23:48 +00:00
|
|
|
>
|
2024-07-30 17:57:56 +00:00
|
|
|
<i class="fa fa-download"></i>
|
2024-07-30 17:23:48 +00:00
|
|
|
{% trans %}Download all my pictures{% endtrans %}
|
|
|
|
</button>
|
2024-08-10 12:49:02 +00:00
|
|
|
<progress x-ref="progress" x-show="is_downloading"></progress>
|
2024-07-30 17:23:48 +00:00
|
|
|
</div>
|
2022-08-09 16:11:20 +00:00
|
|
|
{% endif %}
|
2024-08-09 15:33:07 +00:00
|
|
|
|
2024-08-10 12:49:02 +00:00
|
|
|
<template x-for="[album, pictures] in Object.entries(albums)">
|
|
|
|
<section x-data="{ shown: false }" x-intersect:enter="shown = true">
|
|
|
|
<hgroup x-show="shown" x-transition x-cloak>
|
|
|
|
<br />
|
|
|
|
<h4 x-text="album"></h4>
|
|
|
|
<div class="photos">
|
|
|
|
<template x-for="picture in pictures">
|
|
|
|
<a :href="`/sas/picture/${picture.id}#pict`">
|
|
|
|
<div
|
|
|
|
class="photo"
|
|
|
|
:class="{not_moderated: !picture.is_moderated}"
|
|
|
|
:style="`background-image: url(${picture.thumb_url})`"
|
|
|
|
>
|
|
|
|
<template x-if="!picture.is_moderated">
|
|
|
|
<div class="overlay"> </div>
|
|
|
|
<div class="text">{% trans %}To be moderated{% endtrans %}</div>
|
|
|
|
</template>
|
|
|
|
<template x-if="picture.is_moderated">
|
|
|
|
<div class="text"> </div>
|
|
|
|
</template>
|
|
|
|
</div>
|
2024-08-10 13:16:37 +00:00
|
|
|
</a>
|
|
|
|
</template>
|
|
|
|
</div>
|
2024-08-10 12:49:02 +00:00
|
|
|
</hgroup>
|
2024-08-10 13:16:37 +00:00
|
|
|
</section>
|
|
|
|
</template>
|
|
|
|
<div class="photos" :aria-busy="loading"></div>
|
2024-07-30 17:23:48 +00:00
|
|
|
</main>
|
2024-07-30 17:57:56 +00:00
|
|
|
{% endblock content %}
|
|
|
|
|
2024-07-30 17:23:48 +00:00
|
|
|
{% block script %}
|
2024-07-30 09:11:31 +00:00
|
|
|
|
2024-07-30 17:23:48 +00:00
|
|
|
{{ super() }}
|
2024-08-09 15:33:07 +00:00
|
|
|
<script>
|
2024-07-30 17:23:48 +00:00
|
|
|
/**
|
|
|
|
* @typedef Picture
|
|
|
|
* @property {number} id
|
|
|
|
* @property {string} name
|
|
|
|
* @property {number} size
|
|
|
|
* @property {string} date
|
|
|
|
* @property {Object} author
|
|
|
|
* @property {string} full_size_url
|
|
|
|
* @property {string} compressed_url
|
|
|
|
* @property {string} thumb_url
|
2024-07-31 09:56:38 +00:00
|
|
|
* @property {string} album
|
2024-07-30 17:23:48 +00:00
|
|
|
*/
|
2024-07-28 21:53:18 +00:00
|
|
|
|
2024-08-09 15:33:07 +00:00
|
|
|
document.addEventListener("alpine:init", () => {
|
|
|
|
Alpine.data("user_pictures", () => ({
|
2024-08-10 12:49:02 +00:00
|
|
|
is_downloading: false,
|
2024-08-09 15:33:07 +00:00
|
|
|
loading: true,
|
|
|
|
pictures: [],
|
|
|
|
albums: {},
|
|
|
|
|
|
|
|
async init() {
|
|
|
|
this.pictures = await this.get_pictures();
|
|
|
|
this.albums = Object.groupBy(this.pictures, ({album}) => album);
|
|
|
|
this.loading = false;
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return {Promise<Picture[]>}
|
|
|
|
*/
|
|
|
|
async get_pictures() {
|
|
|
|
{# The API forbids to get more than 199 items at once
|
|
|
|
from paginated routes.
|
|
|
|
In order to download all the user pictures, it may be needed
|
|
|
|
to performs multiple requests #}
|
|
|
|
const max_per_page = 199;
|
|
|
|
const url = "{{ url("api:pictures") }}"
|
|
|
|
+ "?users_identified={{ object.id }}"
|
|
|
|
+ `&page_size=${max_per_page}`;
|
|
|
|
|
|
|
|
let first_page = (await ( await fetch(url)).json());
|
|
|
|
let promises = [first_page.results];
|
|
|
|
|
|
|
|
const nb_pictures = first_page.count
|
|
|
|
const nb_pages = Math.ceil(nb_pictures / max_per_page);
|
|
|
|
|
|
|
|
for (let i = 2; i <= nb_pages; i++) {
|
|
|
|
promises.push(
|
|
|
|
fetch(url + `&page=${i}`).then(res => res.json().then(json => json.results))
|
|
|
|
);
|
2024-07-30 17:57:56 +00:00
|
|
|
}
|
2024-08-09 15:33:07 +00:00
|
|
|
return (await Promise.all(promises)).flat()
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
async download_zip(){
|
2024-08-10 12:49:02 +00:00
|
|
|
this.is_downloading = true;
|
2024-08-09 15:33:07 +00:00
|
|
|
const bar = this.$refs.progress;
|
|
|
|
bar.value = 0;
|
|
|
|
bar.max = this.pictures.length;
|
|
|
|
|
|
|
|
const fileHandle = await window.showSaveFilePicker({
|
|
|
|
_preferPolyfill: false,
|
|
|
|
suggestedName: "{%- trans -%} pictures {%- endtrans -%}.zip",
|
|
|
|
types: {},
|
|
|
|
excludeAcceptAllOption: false,
|
|
|
|
})
|
|
|
|
const zipWriter = new zip.ZipWriter(await fileHandle.createWritable());
|
|
|
|
|
|
|
|
await Promise.all(this.pictures.map(p => {
|
|
|
|
const img_name = p.album + "/IMG_" + p.date.replaceAll(/[:\-]/g, "_") + p.name.slice(p.name.lastIndexOf("."));
|
|
|
|
return zipWriter.add(
|
|
|
|
img_name,
|
|
|
|
new zip.HttpReader(p.full_size_url),
|
|
|
|
{level: 9, lastModDate: new Date(p.date), onstart: () => bar.value += 1}
|
|
|
|
);
|
|
|
|
}));
|
|
|
|
|
|
|
|
await zipWriter.close();
|
2024-08-10 12:49:02 +00:00
|
|
|
this.is_downloading = false;
|
2024-08-09 15:33:07 +00:00
|
|
|
}
|
|
|
|
}))
|
|
|
|
});
|
|
|
|
</script>
|
2024-07-30 17:57:56 +00:00
|
|
|
{% endblock script %}
|