mirror of
https://github.com/ae-utbm/sith.git
synced 2026-10-09 04:14:15 +00:00
Merge pull request #745 from ae-utbm/picture-zip
Add image download progress bar and fix output name of pictures
This commit is contained in:
12 files changed
+160
-115
No files matched your search
@@ -27,4 +27,6 @@ $twitblue: hsl(206, 82%, 63%);
|
||||
|
||||
$shadow-color: rgb(223, 223, 223);
|
||||
|
||||
$background-button-color: hsl(0, 0%, 95%);
|
||||
$background-button-color: hsl(0, 0%, 95%);
|
||||
|
||||
$deepblue: #354a5f;
|
||||
@@ -1,7 +1,8 @@
|
||||
@import "colors";
|
||||
|
||||
$hovered-text-color: #c2c2c2;
|
||||
$text-color: white;
|
||||
|
||||
$background-color: #354a5f;
|
||||
$background-color-hovered: #283747;
|
||||
|
||||
$red-text-color: #eb2f06;
|
||||
@@ -9,7 +10,7 @@ $hovered-red-text-color: #ff4d4d;
|
||||
|
||||
.header {
|
||||
box-sizing: border-box;
|
||||
background-color: $background-color;
|
||||
background-color: $deepblue;
|
||||
box-shadow: 3px 3px 3px 0 #dfdfdf;
|
||||
border-radius: 0;
|
||||
width: 100%;
|
||||
@@ -98,7 +99,7 @@ $hovered-red-text-color: #ff4d4d;
|
||||
border-radius: 0;
|
||||
margin: 0;
|
||||
box-sizing: border-box;
|
||||
background-color: $background-color;
|
||||
background-color: $deepblue;
|
||||
width: 45px;
|
||||
height: 25px;
|
||||
padding: 0;
|
||||
@@ -213,7 +214,7 @@ $hovered-red-text-color: #ff4d4d;
|
||||
background-position: center center;
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
background-color: $background-color;
|
||||
background-color: $deepblue;
|
||||
}
|
||||
|
||||
>.options {
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
!function(e){"object"==typeof exports?module.exports=e():"function"==typeof define&&define.amd?define(e):"undefined"!=typeof window?window.JSZipUtils=e():"undefined"!=typeof global?global.JSZipUtils=e():"undefined"!=typeof self&&(self.JSZipUtils=e())}(function(){return function o(i,f,u){function s(n,e){if(!f[n]){if(!i[n]){var t="function"==typeof require&&require;if(!e&&t)return t(n,!0);if(a)return a(n,!0);throw new Error("Cannot find module '"+n+"'")}var r=f[n]={exports:{}};i[n][0].call(r.exports,function(e){var t=i[n][1][e];return s(t||e)},r,r.exports,o,i,f,u)}return f[n].exports}for(var a="function"==typeof require&&require,e=0;e<u.length;e++)s(u[e]);return s}({1:[function(e,t,n){"use strict";var u={};function r(){try{return new window.XMLHttpRequest}catch(e){}}u._getBinaryFromXHR=function(e){return e.response||e.responseText};var s="undefined"!=typeof window&&window.ActiveXObject?function(){return r()||function(){try{return new window.ActiveXObject("Microsoft.XMLHTTP")}catch(e){}}()}:r;u.getBinaryContent=function(t,n){var e,r,o,i;"function"==typeof(n=n||{})?(i=n,n={}):"function"==typeof n.callback&&(i=n.callback),i||"undefined"==typeof Promise?(r=function(e){i(null,e)},o=function(e){i(e,null)}):e=new Promise(function(e,t){r=e,o=t});try{var f=s();f.open("GET",t,!0),"responseType"in f&&(f.responseType="arraybuffer"),f.overrideMimeType&&f.overrideMimeType("text/plain; charset=x-user-defined"),f.onreadystatechange=function(e){if(4===f.readyState)if(200===f.status||0===f.status)try{r(u._getBinaryFromXHR(f))}catch(e){o(new Error(e))}else o(new Error("Ajax error for "+t+" : "+this.status+" "+this.statusText))},n.progress&&(f.onprogress=function(e){n.progress({path:t,originalEvent:e,percent:e.loaded/e.total*100,loaded:e.loaded,total:e.total})}),f.send()}catch(e){o(new Error(e),null)}return e},t.exports=u},{}]},{},[1])(1)});
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
/*!
|
||||
|
||||
JSZip v3.10.1 - A JavaScript class for generating and reading zip files
|
||||
<http://stuartk.com/jszip>
|
||||
|
||||
(c) 2009-2016 Stuart Knightley <stuart [at] stuartk.com>
|
||||
Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip/main/LICENSE.markdown.
|
||||
|
||||
JSZip uses the library pako released under the MIT license :
|
||||
https://github.com/nodeca/pako/blob/main/LICENSE
|
||||
*/
|
||||
|
||||
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).JSZip=e()}}(function(){return function s(a,o,h){function u(r,e){if(!o[r]){if(!a[r]){var t="function"==typeof require&&require;if(!e&&t)return t(r,!0);if(l)return l(r,!0);var n=new Error("Cannot find module '"+r+"'");throw n.code="MODULE_NOT_FOUND",n}var i=o[r]={exports:{}};a[r][0].call(i.exports,function(e){var t=a[r][1][e];return u(t||e)},i,i.exports,s,a,o,h)}return o[r].exports}for(var l="function"==typeof require&&require,e=0;e<h.length;e++)u(h[e]);return u}({1:[function(e,t,r){"use strict";var d=e("./utils"),c=e("./support"),p="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";r.encode=function(e){for(var t,r,n,i,s,a,o,h=[],u=0,l=e.length,f=l,c="string"!==d.getTypeOf(e);u<e.length;)f=l-u,n=c?(t=e[u++],r=u<l?e[u++]:0,u<l?e[u++]:0):(t=e.charCodeAt(u++),r=u<l?e.charCodeAt(u++):0,u<l?e.charCodeAt(u++):0),i=t>>2,s=(3&t)<<4|r>>4,a=1<f?(15&r)<<2|n>>6:64,o=2<f?63&n:64,h.push(p.charAt(i)+p.charAt(s)+p.charAt(a)+p.charAt(o));return h.join("")},r.decode=function(e){var t,r,n,i,s,a,o=0,h=0,u="data:";if(e.substr(0,u.length)===u)throw new Error("Invalid base64 input, it looks like a data url.");var l,f=3*(e=e.replace(/[^A-Za-z0-9+/=]/g,"")).length/4;if(e.charAt(e.length-1)===p.charAt(64)&&f--,e.charAt(e.length-2)===p.charAt(64)&&f--,f%1!=0)throw new Error("Invalid base64 input, bad content length.");for(l=c.uint8array?new Uint8Array(0|f):new Array(0|f);o<e.length;)t=p.indexOf(e.charAt(o++))<<2|(i=p.indexOf(e.charAt(o++)))>>4,r=(15&i)<<4|(s=p.indexOf(e.charAt(o++)))>>2,n=(3&s)<<6|(a=p.indexOf(e.charAt(o++))),l[h++]=t,64!==s&&(l[h++]=r),64!==a&&(l[h++]=n);return l}},{"./support":30,"./utils":32}],2:[function(e,t,r){"use strict";var n=e("./external"),i=e("./stream/DataWorker"),s=e("./stream/Crc32Probe"),a=e("./stream/DataLengthProbe");function o(e,t,r,n,i){this.compressedSize=e,this.uncompressedSize=t,this.crc32=r,this.compression=n,this.compressedContent=i}o.prototype={getContentWorker:function(){var e=new i(n.Promise.resolve(this.compressedContent)).pipe(this.compression.uncompressWorker()).pipe(new a("data_length")),t=this;return e.on("end",function(){if(this.streamInfo.data_length!==t.uncompressedSize)throw new Error("Bug : uncompressed data size mismatch")}),e},getCompressedWorker:function(){return new i(n.Promise.resolve(this.compressedContent)).withStreamInfo("compressedSize",this.compressedSize).withStreamInfo("uncompressedSize",this.uncompressedSize).withStreamInfo("crc32",this.crc32).withStreamInfo("compression",this.compression)}},o.createWorkerFrom=function(e,t,r){return e.pipe(new s).pipe(new a("uncompressedSize")).pipe(t.compressWorker(r)).pipe(new a("compressedSize")).withStreamInfo("compression",t)},t.exports=o},{"./external":6,"./stream/Crc32Probe":25,"./stream/DataLengthProbe":26,"./stream/DataWorker":27}],3:[function(e,t,r){"use strict";var n=e("./stream/GenericWorker");r.STORE={magic:"\0\0",compressWorker:function(){return new n("STORE compression")},uncompressWorker:function(){return new n("STORE decompression")}},r.DEFLATE=e("./flate")},{"./flate":7,"./stream/GenericWorker":28}],4:[function(e,t,r){"use strict";var n=e("./utils");var o=function(){for(var e,t=[],r=0;r<256;r++){e=r;for(var n=0;n<8;n++)e=1&e?3988292384^e>>>1:e>>>1;t[r]=e}return t}();t.exports=function(e,t){return void 0!==e&&e.length?"string"!==n.getTypeOf(e)?function(e,t,r,n){var i=o,s=n+r;e^=-1;for(var a=n;a<s;a++)e=e>>>8^i[255&(e^t[a])];return-1^e}(0|t,e,e.length,0):function(e,t,r,n){var i=o,s=n+r;e^=-1;for(var a=n;a<s;a++)e=e>>>8^i[255&(e^t.charCodeAt(a))];return-1^e}(0|t,e,e.length,0):0}},{"./utils":32}],5:[function(e,t,r){"use strict";r.base64=!1,r.binary=!1,r.dir=!1,r.createFolders=!0,r.date=null,r.compression=null,r.compressionOptions=null,r.comment=null,r.unixPermissions=null,r.dosPermissions=null},{}],6:[function(e,t,r){"use strict";var n=null;n="undefined"!=typeof Promise?Promise:e("lie"),t.exports={Promise:n}},{lie:37}],7:[function(e,t,r){"use strict";var n="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Uint32Array,i=e("pako"),s=e("./utils"),a=e("./stream/GenericWorker"),o=n?"uint8array":"array";function h(e,t){a.call(this,"FlateWorker/"+e),this._pako=null,this._pakoAction=e,this._pakoOptions=t,this.meta={}}r.magic="\b\0",s.inherits(h,a),h.prototype.processChunk=function(e){this.meta=e.meta,null===this._pako&&this._createPako(),this._pako.push(s.transformTo(o,e.data),!1)},h.prototype.flush=function(){a.prototype.flush.call(this),null===this._pako&&this._createPako(),this._pako.push([],!0)},h.prototype.cleanUp=function(){a.prototype.cleanUp.call(this),this._pako=null},h.prototype._createPako=function(){this._pako=new i[this._pakoAction]({raw:!0,level:this._pakoOptions.level||-1});var t=this;this._pako.onData=function(Line truncated
|
||||
@@ -0,0 +1,28 @@
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2023, Gildas Lormeau
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -0,0 +1,28 @@
|
||||
# Built scripts of zip.js
|
||||
|
||||
**Warning**: These files are not compatible with ES modules, i.e. they cannot be imported with `import`. Instead, import `index.js` in the root folder of the project or one of the files prefixed with `zip-` in the [`/lib`](../lib) folder (e.g. `/lib/zip-no-worker-inflate.js`).
|
||||
|
||||
- for production (minified):
|
||||
|
||||
| | [`ZipReader`](https://gildas-lormeau.github.io/zip.js/api/classes/ZipReader.html) API | [`ZipWriter`](https://gildas-lormeau.github.io/zip.js/api/classes/ZipWriter.html) API | [`zip.fs`](https://gildas-lormeau.github.io/zip.js/api/classes/FS.html) API | Web Workers | No Web Workers | Usage |
|
||||
|--------------------------------|-----------------|-----------------|--------------|-------------|----------------|-------------------------------------------------------|
|
||||
| `zip.min.js` | x | x | | x | | compression/decompression with web workers |
|
||||
| `zip-no-worker.min.js` | x | x | | | x | compression/decompression without web workers |
|
||||
| `zip-no-worker-inflate.min.js` | x | | | | x | decompression without web workers |
|
||||
| `zip-no-worker-deflate.min.js` | | x | | | x | compression without web workers |
|
||||
| `zip-full.min.js` | x | x | | x | x | compression/decompression with or without web workers |
|
||||
| `zip-fs.min.js` | x | x | x | x | | compression/decompression with web workers |
|
||||
| `zip-fs-full.min.js` | x | x | x | x | x | compression/decompression with or without web workers |
|
||||
|
||||
- for development/debugging:
|
||||
|
||||
| | `zip` API | [`zip.fs`](https://gildas-lormeau.github.io/zip.js/api/classes/FS.html) API | Web Workers | No Web Workers |
|
||||
|-----------------------|-----------|--------------|-------------|----------------|
|
||||
| `zip.js` | x | | x | |
|
||||
| `zip-full.js` | x | | x | x |
|
||||
| `zip-fs.js` | x | x | x | |
|
||||
| `zip-fs-full.js` | x | x | x | x |
|
||||
|
||||
- `z-worker.js` can be used as a web worker script if the [Content Security Policy](https://developer.mozilla.org/docs/Web/HTTP/CSP) blocks scripts loaded with a `blob:` scheme
|
||||
- `z-worker-fflate.js` is the web worker script for using [fflate](https://gildas-lormeau.github.io/zip.js/core-api.html#alternative-codec-fflate)
|
||||
- `z-worker-pako.js` is the web worker script for using [pako](https://gildas-lormeau.github.io/zip.js/core-api.html#alternative-codec-pako)
|
||||
@@ -0,0 +1 @@
|
||||
((e,t)=>{"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).zip={})})(this,(function(e){"use strict";const{Array:t,Object:n,String:r,Number:i,BigInt:s,Math:a,Date:o,Map:l,Set:c,Response:d,URL:f,Error:u,Uint8Array:p,Uint16Array:m,Uint32Array:h,DataView:w,Blob:x,Promise:g,TextEncoder:v,TextDecoder:b,document:y,crypto:_,btoa:k,TransformStream:z,ReadableStream:S,WritableStream:D,CompressionStream:A,DecompressionStream:C,navigator:F,Worker:R}="undefined"!=typeof globalThis?globalThis:this||self;var E=void 0!==y?y.currentScript:null;const j=15,T=573,q=-2;function U(e){return I(e.map((([e,n])=>new t(e).fill(n,0,e))))}function I(e){return e.reduce(((e,n)=>e.concat(t.isArray(n)?I(n):n)),[])}const W=[0,1,2,3].concat(...U([[2,4],[2,5],[4,6],[4,7],[8,8],[8,9],[16,10],[16,11],[32,12],[32,13],[64,14],[64,15],[2,0],[1,16],[1,17],[2,18],[2,19],[4,20],[4,21],[8,22],[8,23],[16,24],[16,25],[32,26],[32,27],[64,28],[64,29]]));function N(){const e=this;function t(e,t){let n=0;do{n|=1&e,e>>>=1,n<<=1}while(--t>0);return n>>>1}e.build_tree=n=>{const r=e.dyn_tree,i=e.stat_desc.static_tree,s=e.stat_desc.elems;let o,l,c,d=-1;for(n.heap_len=0,n.heap_max=T,o=0;s>o;o++)0!==r[2*o]?(n.heap[++n.heap_len]=d=o,n.depth[o]=0):r[2*o+1]=0;for(;2>n.heap_len;)c=n.heap[++n.heap_len]=2>d?++d:0,r[2*c]=1,n.depth[c]=0,n.opt_len--,i&&(n.static_len-=i[2*c+1]);for(e.max_code=d,o=a.floor(n.heap_len/2);o>=1;o--)n.pqdownheap(r,o);c=s;do{o=n.heap[1],n.heap[1]=n.heap[n.heap_len--],n.pqdownheap(r,1),l=n.heap[1],n.heap[--n.heap_max]=o,n.heap[--n.heap_max]=l,r[2*c]=r[2*o]+r[2*l],n.depth[c]=a.max(n.depth[o],n.depth[l])+1,r[2*o+1]=r[2*l+1]=c,n.heap[1]=c++,n.pqdownheap(r,1)}while(n.heap_len>=2);n.heap[--n.heap_max]=n.heap[1],(t=>{const n=e.dyn_tree,r=e.stat_desc.static_tree,i=e.stat_desc.extra_bits,s=e.stat_desc.extra_base,a=e.stat_desc.max_length;let o,l,c,d,f,u,p=0;for(d=0;j>=d;d++)t.bl_count[d]=0;for(n[2*t.heap[t.heap_max]+1]=0,o=t.heap_max+1;T>o;o++)l=t.heap[o],d=n[2*n[2*l+1]+1]+1,d>a&&(d=a,p++),n[2*l+1]=d,l>e.max_code||(t.bl_count[d]++,f=0,s>l||(f=i[l-s]),u=n[2*l],t.opt_len+=u*(d+f),r&&(t.static_len+=u*(r[2*l+1]+f)));if(0!==p){do{for(d=a-1;0===t.bl_count[d];)d--;t.bl_count[d]--,t.bl_count[d+1]+=2,t.bl_count[a]--,p-=2}while(p>0);for(d=a;0!==d;d--)for(l=t.bl_count[d];0!==l;)c=t.heap[--o],c>e.max_code||(n[2*c+1]!=d&&(t.opt_len+=(d-n[2*c+1])*n[2*c],n[2*c+1]=d),l--)}})(n),((e,n,r)=>{const i=[];let s,a,o,l=0;for(s=1;j>=s;s++)i[s]=l=l+r[s-1]<<1;for(a=0;n>=a;a++)o=e[2*a+1],0!==o&&(e[2*a]=t(i[o]++,o))})(r,e.max_code,n.bl_count)}}function P(e,t,n,r,i){const s=this;s.static_tree=e,s.extra_bits=t,s.extra_base=n,s.elems=r,s.max_length=i}N._length_code=[0,1,2,3,4,5,6,7].concat(...U([[2,8],[2,9],[2,10],[2,11],[4,12],[4,13],[4,14],[4,15],[8,16],[8,17],[8,18],[8,19],[16,20],[16,21],[16,22],[16,23],[32,24],[32,25],[32,26],[31,27],[1,28]])),N.base_length=[0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224,0],N.base_dist=[0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,1536,2048,3072,4096,6144,8192,12288,16384,24576],N.d_code=e=>256>e?W[e]:W[256+(e>>>7)],N.extra_lbits=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0],N.extra_dbits=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],N.extra_blbits=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7],N.bl_order=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15];const L=U([[144,8],[112,9],[24,7],[8,8]]);P.static_ltree=I([12,140,76,204,44,172,108,236,28,156,92,220,60,188,124,252,2,130,66,194,34,162,98,226,18,146,82,210,50,178,114,242,10,138,74,202,42,170,106,234,26,154,90,218,58,186,122,250,6,134,70,198,38,166,102,230,22,150,86,214,54,182,118,246,14,142,78,206,46,174,110,238,30,158,94,222,62,190,126,254,1,129,65,193,33,161,97,225,17,145,81,209,49,177,113,241,9,137,73,201,41,169,105,233,25,153,89,217,57,185,121,249,5,133,69,197,37,165,101,229,21,149,85,213,53,181,117,245,13,141,77,205,45,173,109,237,29,157,93,221,61,189,125,253,19,275,147,403,83,339,211,467,51,307,179,435,115,371,243,499,11,267,139,395,75,331,203,459,43,299,171,427,107,363,235,491,27,283,155,411,91,347,219,475,59,315,187,443,123,379,251,507,7,263,135,391,71,327,199,455,39,295,167,423,103,359,231,487,23,279,151,407,87,343,215,471,55,311,183,439,119,375,247,503,15,271,143,399,79,335,207,463,47,303,175,431,111,367,239,495,31,287,159,415,95,351,223,479,63,319,191,447,127,383,255,511,0,64,32,96,16,80,48,112,8,72,40,104,24,88,56,120,4,68,36,100,20,84,52,116,3,131,67,195,35,163,99,227].map(((e,t)=>[e,L[t]])));const O=U([[30,5]]);function B(e,t,n,r,i){const s=this;s.good_length=e,s.max_lazy=t,s.nice_length=n,s.max_chain=r,s.func=i}P.static_dtree=I([0,16,8,24,4,20,12,28,2,18,10,26,6,22,14,30,1,17,9,25,5,21,13,29,3,19,11,27,7,23].map(((e,t)=>[e,O[t]]))),P.static_l_desc=new P(P.static_ltree,N.extra_lbits,257,286,j),P.static_d_desc=new P(P.static_dtree,N.extra_dbits,0,30,j),P.static_bl_desc=new P(Line truncated
|
||||
+18
-16
@@ -105,7 +105,7 @@ a:not(.button) {
|
||||
|
||||
.collapse-header {
|
||||
color: white;
|
||||
background-color: #354a5f;
|
||||
background-color: $deepblue;
|
||||
padding: 5px 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -206,34 +206,36 @@ a:not(.button) {
|
||||
width: 90%;
|
||||
margin: 20px auto 0;
|
||||
/*---------------------------------NAV---------------------------------*/
|
||||
|
||||
.btn {
|
||||
font-size: 15px;
|
||||
font-weight: normal;
|
||||
color: white;
|
||||
min-width: 60px;
|
||||
padding: 5px 10px;
|
||||
padding: 9px 13px;
|
||||
border: none;
|
||||
text-decoration: none;
|
||||
|
||||
&.btn-blue {
|
||||
background-color: #354a5f;
|
||||
}
|
||||
|
||||
&.btn-blue:disabled {
|
||||
background-color: rgba(70, 90, 126, 0.4);
|
||||
}
|
||||
|
||||
&.btn-blue.clickable:not(:disabled):hover {
|
||||
background-color: #2c3646;
|
||||
background-color: $deepblue;
|
||||
&:not(:disabled):hover {
|
||||
background-color: darken($deepblue, 10%);
|
||||
}
|
||||
&:disabled {
|
||||
background-color: rgba(70, 90, 126, 0.4);
|
||||
}
|
||||
}
|
||||
|
||||
&.btn-grey {
|
||||
background-color: grey;
|
||||
&:not(:disabled):hover {
|
||||
background-color: darken(gray, 15%);
|
||||
}
|
||||
&:disabled {
|
||||
background-color: lighten(gray, 15%);
|
||||
}
|
||||
}
|
||||
|
||||
&.btn-grey.clickable:not(:disabled):hover {
|
||||
background-color: hsl(210, 5%, 30%);
|
||||
i {
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -977,7 +979,7 @@ thead td {
|
||||
}
|
||||
|
||||
thead {
|
||||
background-color: #354a5f;
|
||||
background-color: $deepblue;
|
||||
color: white;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
{%- endblock -%}
|
||||
|
||||
{% block additional_js %}
|
||||
<script defer src="{{ static('core/js/jszip/jszip.min.js') }}"></script>
|
||||
<script defer src="{{ static('core/js/jszip/jszip-utils.min.js') }}"></script>
|
||||
<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>
|
||||
<script defer type="text/javascript" src="{{ static('core/js/zipjs/zip-fs-full.min.js') }}"></script>
|
||||
<script defer src="{{ static("core/js/alpinejs.min.js") }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block title %}
|
||||
@@ -19,11 +19,22 @@
|
||||
|
||||
{% block content %}
|
||||
<main>
|
||||
{% if can_edit(profile, user) %}
|
||||
<button disabled id="download" onclick="download('{{ url('api:pictures') }}?users_identified={{ object.id }}')">{% trans %}Download all my pictures{% endtrans %}</button>
|
||||
{% if user.id == object.id and albums|length > 0 %}
|
||||
<div x-data="picture_download" x-cloak>
|
||||
<button
|
||||
:disabled="in_progress"
|
||||
class="btn btn-blue"
|
||||
@click="download('{{ url("api:pictures") }}?users_identified={{ object.id }}')"
|
||||
>
|
||||
<i class="fa fa-download"></i>
|
||||
{% trans %}Download all my pictures{% endtrans %}
|
||||
</button>
|
||||
<progress x-ref="progress" x-show="in_progress"></progress>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% for album, pictures in albums|items %}
|
||||
<h4>{{ album }}</h4>
|
||||
<br />
|
||||
<div class="photos">
|
||||
{% for picture in pictures %}
|
||||
{% if picture.can_be_viewed_by(user) %}
|
||||
@@ -51,52 +62,61 @@
|
||||
</div>
|
||||
<br>
|
||||
{% endfor %}
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
/* Enable button once everything is loaded and if JSZip is supported */
|
||||
document.getElementById("download").disabled = !JSZip.support.blob;
|
||||
});
|
||||
async function download(url) {
|
||||
|
||||
let zip = new JSZip();
|
||||
let size = 0;
|
||||
let pictures = await (await fetch(url)).json();
|
||||
pictures.forEach(async (picture) => {
|
||||
size += picture.size;
|
||||
zip.file(
|
||||
"IMG_" + picture.date + picture.name.slice(picture.name.lastIndexOf(".")),
|
||||
new Promise(function (resolve, reject) {
|
||||
JSZipUtils.getBinaryContent(picture.full_size_url, (err, data) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
resolve(data);
|
||||
})
|
||||
}),
|
||||
{ binary: true }
|
||||
);
|
||||
});
|
||||
|
||||
let fileHandle = await window.showSaveFilePicker({
|
||||
_preferPolyfill: false,
|
||||
suggestedName: "{%- trans -%} pictures {%- endtrans -%}.zip",
|
||||
types: {},
|
||||
excludeAcceptAllOption: false,
|
||||
})
|
||||
let writeStream = await fileHandle.createWritable();
|
||||
|
||||
await zip.generateInternalStream({
|
||||
type: "uint8array",
|
||||
streamFiles: true,
|
||||
compression: "DEFLATE",
|
||||
compressionOptions: { level: 9 }
|
||||
})
|
||||
.on("data", (data) => writeStream.write(data))
|
||||
.on("error", (err) => console.error(err))
|
||||
.on("end", () => writeStream.close())
|
||||
.resume();
|
||||
}
|
||||
</script>
|
||||
</main>
|
||||
{% endblock %}
|
||||
{% endblock content %}
|
||||
|
||||
{% block script %}
|
||||
|
||||
{{ super() }}
|
||||
{% if user.id == object.id %}
|
||||
<script>
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
|
||||
document.addEventListener("alpine:init", () => {
|
||||
Alpine.data("picture_download", () => ({
|
||||
in_progress: false,
|
||||
|
||||
async download(url) {
|
||||
this.in_progress = true;
|
||||
const bar = this.$refs.progress;
|
||||
bar.value = 0;
|
||||
|
||||
/** @type Picture[] */
|
||||
const pictures = await (await fetch(url)).json();
|
||||
bar.max = 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(pictures.map(p => {
|
||||
const img_name = "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();
|
||||
this.in_progress = false;
|
||||
}
|
||||
}))
|
||||
});
|
||||
</script>
|
||||
{% endif %}
|
||||
{% endblock script %}
|
||||
@@ -136,7 +136,7 @@
|
||||
right: 5px;
|
||||
padding: 5px;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0px 0px 12px 2px rgb(0 0 0 / 14%);
|
||||
box-shadow: 0 0 12px 2px rgb(0 0 0 / 14%);
|
||||
background-color: white;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
@@ -186,29 +186,7 @@
|
||||
}
|
||||
|
||||
#eboutic .catalog-buttons button {
|
||||
font-size: 15px!important;
|
||||
font-weight: normal;
|
||||
color: white;
|
||||
min-width: 60px;
|
||||
padding: 10px 15px;
|
||||
}
|
||||
|
||||
#eboutic .catalog-buttons .validate {
|
||||
background-color: #354a5f;
|
||||
}
|
||||
#eboutic .catalog-buttons .clear {
|
||||
background-color: gray;
|
||||
}
|
||||
#eboutic .catalog-buttons button i {
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
#eboutic .catalog-buttons button.validate:hover {
|
||||
background-color: #2c3646;
|
||||
}
|
||||
|
||||
#eboutic .catalog-buttons button.clear:hover {
|
||||
background-color:hsl(210,5%,30%);
|
||||
}
|
||||
|
||||
#eboutic .catalog-buttons form {
|
||||
@@ -252,7 +230,7 @@
|
||||
}
|
||||
|
||||
#eboutic .product-image {
|
||||
margin-bottom: 0px;
|
||||
margin-bottom: 0;
|
||||
max-width: 70px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,13 +62,13 @@
|
||||
</li>
|
||||
</ul>
|
||||
<div class="catalog-buttons">
|
||||
<button @click="clear_basket()" class="clear">
|
||||
<button @click="clear_basket()" class="btn btn-grey">
|
||||
<i class="fa fa-trash"></i>
|
||||
{% trans %}Clear{% endtrans %}
|
||||
</button>
|
||||
<form method="get" action="{{ url('eboutic:command') }}">
|
||||
{% csrf_token %}
|
||||
<button class="validate">
|
||||
<button class="btn btn-blue">
|
||||
<i class="fa fa-check"></i>
|
||||
<input type="submit" value="{% trans %}Validate{% endtrans %}"/>
|
||||
</button>
|
||||
|
||||
+1
-2
@@ -724,8 +724,7 @@ if SENTRY_DSN:
|
||||
)
|
||||
|
||||
SITH_FRONT_DEP_VERSIONS = {
|
||||
"https://github.com/Stuk/jszip-utils": "0.1.0",
|
||||
"https://github.com/Stuk/jszip": "3.10.1",
|
||||
"https://github.com/gildas-lormeau/zip.js": "2.7.47",
|
||||
"https://github.com/jimmywarting/native-file-system-adapter": "3.0.1",
|
||||
"https://github.com/chartjs/Chart.js/": "2.6.0",
|
||||
"https://github.com/Ionaru/easy-markdown-editor/": "2.18.0",
|
||||
|
||||
Reference in new issue
Block a user