mirror of
https://github.com/Kozea/Radicale.git
synced 2025-06-26 16:45:52 +00:00
Merge pull request #1456 from MatthewHana/v3.2-devel
WEB UI: HREF for Upload, Refresh button, and CSS fixes
This commit is contained in:
commit
95cd6938d9
4 changed files with 280 additions and 153 deletions
|
@ -1,55 +1,72 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="margin: auto; display: block;" width="264px" height="264px" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid">
|
||||
<g transform="rotate(0 50 50)">
|
||||
<rect x="45.5" y="32" rx="0" ry="0" width="9" height="4" fill="#4e9a06">
|
||||
<animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="0.8695652173913042s" begin="-0.8026755852842808s" repeatCount="indefinite"></animate>
|
||||
</rect>
|
||||
</g><g transform="rotate(27.692307692307693 50 50)">
|
||||
<rect x="45.5" y="32" rx="0" ry="0" width="9" height="4" fill="#71cc1a">
|
||||
<animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="0.8695652173913042s" begin="-0.7357859531772575s" repeatCount="indefinite"></animate>
|
||||
</rect>
|
||||
</g><g transform="rotate(55.38461538461539 50 50)">
|
||||
<rect x="45.5" y="32" rx="0" ry="0" width="9" height="4" fill="#8ce139">
|
||||
<animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="0.8695652173913042s" begin="-0.6688963210702341s" repeatCount="indefinite"></animate>
|
||||
</rect>
|
||||
</g><g transform="rotate(83.07692307692308 50 50)">
|
||||
<rect x="45.5" y="32" rx="0" ry="0" width="9" height="4" fill="#cdff9c">
|
||||
<animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="0.8695652173913042s" begin="-0.6020066889632106s" repeatCount="indefinite"></animate>
|
||||
</rect>
|
||||
</g><g transform="rotate(110.76923076923077 50 50)">
|
||||
<rect x="45.5" y="32" rx="0" ry="0" width="9" height="4" fill="#cdf7a6">
|
||||
<animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="0.8695652173913042s" begin="-0.5351170568561873s" repeatCount="indefinite"></animate>
|
||||
</rect>
|
||||
</g><g transform="rotate(138.46153846153845 50 50)">
|
||||
<rect x="45.5" y="32" rx="0" ry="0" width="9" height="4" fill="#fcfcfc">
|
||||
<animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="0.8695652173913042s" begin="-0.46822742474916385s" repeatCount="indefinite"></animate>
|
||||
</rect>
|
||||
</g><g transform="rotate(166.15384615384616 50 50)">
|
||||
<rect x="45.5" y="32" rx="0" ry="0" width="9" height="4" fill="#fefefe">
|
||||
<animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="0.8695652173913042s" begin="-0.4013377926421404s" repeatCount="indefinite"></animate>
|
||||
</rect>
|
||||
</g><g transform="rotate(193.84615384615384 50 50)">
|
||||
<rect x="45.5" y="32" rx="0" ry="0" width="9" height="4" fill="#f4f4f4">
|
||||
<animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="0.8695652173913042s" begin="-0.33444816053511706s" repeatCount="indefinite"></animate>
|
||||
</rect>
|
||||
</g><g transform="rotate(221.53846153846155 50 50)">
|
||||
<rect x="45.5" y="32" rx="0" ry="0" width="9" height="4" fill="#ffd6d6">
|
||||
<animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="0.8695652173913042s" begin="-0.26755852842809363s" repeatCount="indefinite"></animate>
|
||||
</rect>
|
||||
</g><g transform="rotate(249.23076923076923 50 50)">
|
||||
<rect x="45.5" y="32" rx="0" ry="0" width="9" height="4" fill="#f86f6f">
|
||||
<animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="0.8695652173913042s" begin="-0.2006688963210702s" repeatCount="indefinite"></animate>
|
||||
</rect>
|
||||
</g><g transform="rotate(276.9230769230769 50 50)">
|
||||
<rect x="45.5" y="32" rx="0" ry="0" width="9" height="4" fill="#e73c3c">
|
||||
<animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="0.8695652173913042s" begin="-0.13377926421404682s" repeatCount="indefinite"></animate>
|
||||
</rect>
|
||||
</g><g transform="rotate(304.61538461538464 50 50)">
|
||||
<rect x="45.5" y="32" rx="0" ry="0" width="9" height="4" fill="#da2121">
|
||||
<animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="0.8695652173913042s" begin="-0.06688963210702341s" repeatCount="indefinite"></animate>
|
||||
</rect>
|
||||
</g><g transform="rotate(332.3076923076923 50 50)">
|
||||
<rect x="45.5" y="32" rx="0" ry="0" width="9" height="4" fill="#a40000">
|
||||
<animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="0.8695652173913042s" begin="0s" repeatCount="indefinite"></animate>
|
||||
</rect>
|
||||
</g>
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="1080" height="1080" viewBox="0 0 1080 1080" xml:space="preserve">
|
||||
<g transform="matrix(10.8 0 0 10.8 540 540)">
|
||||
<g style="">
|
||||
<g transform="matrix(2.64 0 0 2.64 0 -42.24)">
|
||||
<rect style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(78,154,6); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" x="-4.5" y="-2" rx="0" ry="0" width="9" height="4">
|
||||
<animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="0.8695652173913042s" begin="-0.8026755852842808s" repeatCount="indefinite"></animate>
|
||||
</rect>
|
||||
</g>
|
||||
<g transform="matrix(2.34 1.23 -1.23 2.34 19.63 -37.4)">
|
||||
<rect style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(113,204,26); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" x="-4.5" y="-2" rx="0" ry="0" width="9" height="4">
|
||||
<animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="0.8695652173913042s" begin="-0.7357859531772575s" repeatCount="indefinite"></animate>
|
||||
</rect>
|
||||
</g>
|
||||
<g transform="matrix(1.5 2.17 -2.17 1.5 34.76 -24)">
|
||||
<rect style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(140,225,57); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" x="-4.5" y="-2" rx="0" ry="0" width="9" height="4">
|
||||
<animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="0.8695652173913042s" begin="-0.6688963210702341s" repeatCount="indefinite"></animate>
|
||||
</rect>
|
||||
</g>
|
||||
<g transform="matrix(0.32 2.62 -2.62 0.32 41.93 -5.09)">
|
||||
<rect style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(205,255,156); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" x="-4.5" y="-2" rx="0" ry="0" width="9" height="4">
|
||||
<animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="0.8695652173913042s" begin="-0.6020066889632106s" repeatCount="indefinite"></animate>
|
||||
</rect>
|
||||
</g>
|
||||
<g transform="matrix(-0.94 2.47 -2.47 -0.94 39.5 14.98)">
|
||||
<rect style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(205,247,166); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" x="-4.5" y="-2" rx="0" ry="0" width="9" height="4">
|
||||
<animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="0.8695652173913042s" begin="-0.5351170568561873s" repeatCount="indefinite"></animate>
|
||||
</rect>
|
||||
</g>
|
||||
<g transform="matrix(-1.98 1.75 -1.75 -1.98 28.01 31.62)">
|
||||
<rect style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(252,252,252); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" x="-4.5" y="-2" rx="0" ry="0" width="9" height="4">
|
||||
<animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="0.8695652173913042s" begin="-0.46822742474916385s" repeatCount="indefinite"></animate>
|
||||
</rect>
|
||||
</g>
|
||||
<g transform="matrix(-2.56 0.63 -0.63 -2.56 10.11 41.01)">
|
||||
<rect style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(254,254,254); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" x="-4.5" y="-2" rx="0" ry="0" width="9" height="4">
|
||||
<animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="0.8695652173913042s" begin="-0.4013377926421404s" repeatCount="indefinite"></animate>
|
||||
</rect>
|
||||
</g>
|
||||
<g transform="matrix(-2.56 -0.63 0.63 -2.56 -10.11 41.01)">
|
||||
<rect style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(244,244,244); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" x="-4.5" y="-2" rx="0" ry="0" width="9" height="4">
|
||||
<animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="0.8695652173913042s" begin="-0.33444816053511706s" repeatCount="indefinite"></animate>
|
||||
</rect>
|
||||
</g>
|
||||
<g transform="matrix(-1.98 -1.75 1.75 -1.98 -28.01 31.62)">
|
||||
<rect style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(255,214,214); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" x="-4.5" y="-2" rx="0" ry="0" width="9" height="4">
|
||||
<animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="0.8695652173913042s" begin="-0.26755852842809363s" repeatCount="indefinite"></animate>
|
||||
</rect>
|
||||
</g>
|
||||
<g transform="matrix(-0.94 -2.47 2.47 -0.94 -39.5 14.98)">
|
||||
<rect style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(248,111,111); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" x="-4.5" y="-2" rx="0" ry="0" width="9" height="4">
|
||||
<animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="0.8695652173913042s" begin="-0.2006688963210702s" repeatCount="indefinite"></animate>
|
||||
</rect>
|
||||
</g>
|
||||
<g transform="matrix(0.32 -2.62 2.62 0.32 -41.93 -5.09)">
|
||||
<rect style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(231,60,60); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" x="-4.5" y="-2" rx="0" ry="0" width="9" height="4">
|
||||
<animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="0.8695652173913042s" begin="-0.13377926421404682s" repeatCount="indefinite"></animate>
|
||||
</rect>
|
||||
</g>
|
||||
<g transform="matrix(1.5 -2.17 2.17 1.5 -34.76 -24)">
|
||||
<rect style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(218,33,33); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" x="-4.5" y="-2" rx="0" ry="0" width="9" height="4">
|
||||
<animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="0.8695652173913042s" begin="-0.06688963210702341s" repeatCount="indefinite"></animate>
|
||||
</rect>
|
||||
</g>
|
||||
<g transform="matrix(2.34 -1.23 1.23 2.34 -19.63 -37.4)">
|
||||
<rect style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(164,0,0); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" x="-4.5" y="-2" rx="0" ry="0" width="9" height="4">
|
||||
<animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="0.8695652173913042s" begin="0s" repeatCount="indefinite"></animate>
|
||||
</rect>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 7.9 KiB |
|
@ -103,11 +103,20 @@ main{
|
|||
color: white;
|
||||
text-decoration: none;
|
||||
padding: 3px 10px;
|
||||
position: absolute;
|
||||
right: 25px;
|
||||
position: relative;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
#logoutview a[data-name=logout]{
|
||||
right: 25px;
|
||||
float: right;
|
||||
}
|
||||
|
||||
#logoutview a[data-name=refresh]{
|
||||
left: 25px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
#collectionsscene{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
@ -116,11 +125,11 @@ main{
|
|||
align-items: center;
|
||||
margin-top: 50px;
|
||||
width: 100%;
|
||||
height: calc(100vh - 50px);
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
#collectionsscene article{
|
||||
width: 250px;
|
||||
width: 275px;
|
||||
background: rgb(250, 250, 250);
|
||||
border-radius: 8px;
|
||||
box-shadow: 2px 2px 3px #0000001a;
|
||||
|
@ -129,7 +138,7 @@ main{
|
|||
padding-top: 0;
|
||||
margin: 10px;
|
||||
float: left;
|
||||
height: 350px;
|
||||
min-height: 375px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
@ -170,11 +179,12 @@ main{
|
|||
}
|
||||
|
||||
#collectionsscene article:hover ul{
|
||||
display: flex !important;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
#collectionsscene ul{
|
||||
display: none;
|
||||
visibility: hidden;
|
||||
display: flex;
|
||||
justify-content: space-evenly;
|
||||
width: 60%;
|
||||
margin: 0 20%;
|
||||
|
@ -216,7 +226,7 @@ main{
|
|||
#uploadcollectionscene ul{
|
||||
margin: 10px -30px;
|
||||
max-height: 600px;
|
||||
overflow: overlay;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
#uploadcollectionscene li{
|
||||
|
@ -225,6 +235,11 @@ main{
|
|||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
#uploadcollectionscene div[data-name=pending]{
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#uploadcollectionscene .successmessage{
|
||||
color: #4e9a06;
|
||||
width: 100%;
|
||||
|
@ -291,6 +306,11 @@ main{
|
|||
padding-top: 15px;
|
||||
}
|
||||
|
||||
img.loading{
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
}
|
||||
|
||||
.error::before{
|
||||
content: "!";
|
||||
height: 1em;
|
||||
|
@ -391,7 +411,7 @@ button.blue:active, a.blue:active{
|
|||
|
||||
#collectionsscene article{
|
||||
height: auto;
|
||||
min-height: 350px;
|
||||
min-height: 375px;
|
||||
}
|
||||
|
||||
.container{
|
||||
|
@ -399,10 +419,10 @@ button.blue:active, a.blue:active{
|
|||
}
|
||||
|
||||
#collectionsscene ul{
|
||||
display: flex !important;
|
||||
visibility: visible !important;
|
||||
}
|
||||
|
||||
#logoutview span{
|
||||
text-align: left;
|
||||
padding: 0 5px;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -542,7 +542,8 @@ function LoginScene() {
|
|||
let error_form = html_scene.querySelector("[data-name=error]");
|
||||
let logout_view = document.getElementById("logoutview");
|
||||
let logout_user_form = logout_view.querySelector("[data-name=user]");
|
||||
let logout_btn = logout_view.querySelector("[data-name=link]");
|
||||
let logout_btn = logout_view.querySelector("[data-name=logout]");
|
||||
let refresh_btn = logout_view.querySelector("[data-name=refresh]");
|
||||
|
||||
/** @type {?number} */ let scene_index = null;
|
||||
let user = "";
|
||||
|
@ -573,6 +574,7 @@ function LoginScene() {
|
|||
// setup logout
|
||||
logout_view.classList.remove("hidden");
|
||||
logout_btn.onclick = onlogout;
|
||||
refresh_btn.onclick = refresh;
|
||||
logout_user_form.textContent = user + "'s Collections";
|
||||
// Fetch principal
|
||||
let loading_scene = new LoadingScene();
|
||||
|
@ -623,9 +625,17 @@ function LoginScene() {
|
|||
function remove_logout() {
|
||||
logout_view.classList.add("hidden");
|
||||
logout_btn.onclick = null;
|
||||
refresh_btn.onclick = null;
|
||||
logout_user_form.textContent = "";
|
||||
}
|
||||
|
||||
function refresh(){
|
||||
//The easiest way to refresh is to push a LoadingScene onto the stack and then pop it
|
||||
//forcing the scene below it, the Collections Scene to refresh itself.
|
||||
push_scene(new LoadingScene(), false);
|
||||
pop_scene(scene_stack.length-2);
|
||||
}
|
||||
|
||||
this.show = function() {
|
||||
remove_logout();
|
||||
fill_form();
|
||||
|
@ -684,12 +694,6 @@ function CollectionsScene(user, password, collection, onerror) {
|
|||
/** @type {?XMLHttpRequest} */ let collections_req = null;
|
||||
/** @type {?Array<Collection>} */ let collections = null;
|
||||
/** @type {Array<Node>} */ let nodes = [];
|
||||
let filesInput = document.createElement("input");
|
||||
filesInput.setAttribute("type", "file");
|
||||
filesInput.setAttribute("accept", ".ics, .vcf");
|
||||
filesInput.setAttribute("multiple", "");
|
||||
let filesInputForm = document.createElement("form");
|
||||
filesInputForm.appendChild(filesInput);
|
||||
|
||||
function onnew() {
|
||||
try {
|
||||
|
@ -702,17 +706,9 @@ function CollectionsScene(user, password, collection, onerror) {
|
|||
}
|
||||
|
||||
function onupload() {
|
||||
filesInput.click();
|
||||
return false;
|
||||
}
|
||||
|
||||
function onfileschange() {
|
||||
try {
|
||||
let files = filesInput.files;
|
||||
if (files.length > 0) {
|
||||
let upload_scene = new UploadCollectionScene(user, password, collection, files);
|
||||
push_scene(upload_scene);
|
||||
}
|
||||
let upload_scene = new UploadCollectionScene(user, password, collection);
|
||||
push_scene(upload_scene);
|
||||
} catch(err) {
|
||||
console.error(err);
|
||||
}
|
||||
|
@ -740,6 +736,9 @@ function CollectionsScene(user, password, collection, onerror) {
|
|||
}
|
||||
|
||||
function show_collections(collections) {
|
||||
let heightOfNavBar = document.querySelector("#logoutview").offsetHeight + "px";
|
||||
html_scene.style.marginTop = heightOfNavBar;
|
||||
html_scene.style.height = "calc(100vh - " + heightOfNavBar +")";
|
||||
collections.forEach(function (collection) {
|
||||
let node = template.cloneNode(true);
|
||||
node.classList.remove("hidden");
|
||||
|
@ -820,8 +819,6 @@ function CollectionsScene(user, password, collection, onerror) {
|
|||
html_scene.classList.remove("hidden");
|
||||
new_btn.onclick = onnew;
|
||||
upload_btn.onclick = onupload;
|
||||
filesInputForm.reset();
|
||||
filesInput.onchange = onfileschange;
|
||||
if (collections === null) {
|
||||
update();
|
||||
} else {
|
||||
|
@ -834,7 +831,6 @@ function CollectionsScene(user, password, collection, onerror) {
|
|||
scene_index = scene_stack.length - 1;
|
||||
new_btn.onclick = null;
|
||||
upload_btn.onclick = null;
|
||||
filesInput.onchange = null;
|
||||
collections = null;
|
||||
// remove collection
|
||||
nodes.forEach(function(node) {
|
||||
|
@ -849,7 +845,6 @@ function CollectionsScene(user, password, collection, onerror) {
|
|||
collections_req = null;
|
||||
}
|
||||
collections = null;
|
||||
filesInputForm.reset();
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -861,43 +856,89 @@ function CollectionsScene(user, password, collection, onerror) {
|
|||
* @param {Collection} collection parent collection
|
||||
* @param {Array<File>} files
|
||||
*/
|
||||
function UploadCollectionScene(user, password, collection, files) {
|
||||
function UploadCollectionScene(user, password, collection) {
|
||||
let html_scene = document.getElementById("uploadcollectionscene");
|
||||
let template = html_scene.querySelector("[data-name=filetemplate]");
|
||||
let upload_btn = html_scene.querySelector("[data-name=submit]");
|
||||
let close_btn = html_scene.querySelector("[data-name=close]");
|
||||
let uploadfile_form = html_scene.querySelector("[data-name=uploadfile]");
|
||||
let uploadfile_lbl = html_scene.querySelector("label[for=uploadfile]");
|
||||
let href_form = html_scene.querySelector("[data-name=href]");
|
||||
let href_label = html_scene.querySelector("label[for=href]");
|
||||
let hreflimitmsg_html = html_scene.querySelector("[data-name=hreflimitmsg]");
|
||||
let pending_html = html_scene.querySelector("[data-name=pending]");
|
||||
|
||||
let files = uploadfile_form.files;
|
||||
href_form.addEventListener("keydown", cleanHREFinput);
|
||||
upload_btn.onclick = upload_start;
|
||||
uploadfile_form.onchange = onfileschange;
|
||||
|
||||
let href = random_uuid();
|
||||
href_form.value = href;
|
||||
|
||||
/** @type {?number} */ let scene_index = null;
|
||||
/** @type {?XMLHttpRequest} */ let upload_req = null;
|
||||
/** @type {Array<string>} */ let errors = [];
|
||||
/** @type {Array<string>} */ let results = [];
|
||||
/** @type {?Array<Node>} */ let nodes = null;
|
||||
|
||||
function upload_next() {
|
||||
function upload_start() {
|
||||
try {
|
||||
if (files.length === errors.length) {
|
||||
if (errors.every(error => error === null)) {
|
||||
pop_scene(scene_index - 1);
|
||||
} else {
|
||||
close_btn.classList.remove("hidden");
|
||||
}
|
||||
} else {
|
||||
let file = files[errors.length];
|
||||
let upload_href = collection.href + random_uuid() + "/";
|
||||
upload_req = upload_collection(user, password, upload_href, file, function(error) {
|
||||
if (scene_index === null) {
|
||||
return;
|
||||
}
|
||||
upload_req = null;
|
||||
errors.push(error);
|
||||
updateFileStatus(errors.length - 1);
|
||||
upload_next();
|
||||
});
|
||||
if(!read_form()){
|
||||
return false;
|
||||
}
|
||||
uploadfile_form.classList.add("hidden");
|
||||
uploadfile_lbl.classList.add("hidden");
|
||||
href_form.classList.add("hidden");
|
||||
href_label.classList.add("hidden");
|
||||
hreflimitmsg_html.classList.add("hidden");
|
||||
upload_btn.classList.add("hidden");
|
||||
close_btn.classList.add("hidden");
|
||||
|
||||
pending_html.classList.remove("hidden");
|
||||
|
||||
nodes = [];
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
let file = files[i];
|
||||
let node = template.cloneNode(true);
|
||||
node.classList.remove("hidden");
|
||||
let name_form = node.querySelector("[data-name=name]");
|
||||
name_form.textContent = file.name;
|
||||
node.classList.remove("hidden");
|
||||
nodes.push(node);
|
||||
updateFileStatus(i);
|
||||
template.parentNode.insertBefore(node, template);
|
||||
}
|
||||
upload_next();
|
||||
} catch(err) {
|
||||
console.error(err);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function upload_next(){
|
||||
try{
|
||||
if (files.length === results.length) {
|
||||
pending_html.classList.add("hidden");
|
||||
close_btn.classList.remove("hidden");
|
||||
return;
|
||||
} else {
|
||||
let file = files[results.length];
|
||||
if(files.length > 1 || href.length == 0){
|
||||
href = random_uuid();
|
||||
}
|
||||
let upload_href = collection.href + "/" + href + "/";
|
||||
upload_req = upload_collection(user, password, upload_href, file, function(result) {
|
||||
upload_req = null;
|
||||
results.push(result);
|
||||
updateFileStatus(results.length - 1);
|
||||
upload_next();
|
||||
});
|
||||
}
|
||||
}catch(err){
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
function onclose() {
|
||||
try {
|
||||
pop_scene(scene_index - 1);
|
||||
|
@ -911,54 +952,77 @@ function UploadCollectionScene(user, password, collection, files) {
|
|||
if (nodes === null) {
|
||||
return;
|
||||
}
|
||||
let pending_form = nodes[i].querySelector("[data-name=pending]");
|
||||
let success_form = nodes[i].querySelector("[data-name=success]");
|
||||
let error_form = nodes[i].querySelector("[data-name=error]");
|
||||
if (errors.length > i) {
|
||||
pending_form.classList.add("hidden");
|
||||
if (errors[i]) {
|
||||
if (results.length > i) {
|
||||
if (results[i]) {
|
||||
success_form.classList.add("hidden");
|
||||
error_form.textContent = "Error: " + errors[i];
|
||||
error_form.textContent = "Error: " + results[i];
|
||||
error_form.classList.remove("hidden");
|
||||
} else {
|
||||
success_form.classList.remove("hidden");
|
||||
error_form.classList.add("hidden");
|
||||
}
|
||||
} else {
|
||||
pending_form.classList.remove("hidden");
|
||||
success_form.classList.add("hidden");
|
||||
error_form.classList.add("hidden");
|
||||
}
|
||||
}
|
||||
|
||||
function read_form() {
|
||||
cleanHREFinput(href_form);
|
||||
let newhreftxtvalue = href_form.value.trim().toLowerCase();
|
||||
if(!isValidHREF(newhreftxtvalue)){
|
||||
alert("You must enter a valid HREF");
|
||||
return false;
|
||||
}
|
||||
href = newhreftxtvalue;
|
||||
|
||||
if(uploadfile_form.files.length == 0){
|
||||
alert("You must select at least one file to upload");
|
||||
return false;
|
||||
}
|
||||
files = uploadfile_form.files;
|
||||
return true;
|
||||
}
|
||||
|
||||
function onfileschange() {
|
||||
files = uploadfile_form.files;
|
||||
if(files.length > 1){
|
||||
hreflimitmsg_html.classList.remove("hidden");
|
||||
href_form.classList.add("hidden");
|
||||
href_label.classList.add("hidden");
|
||||
}else{
|
||||
hreflimitmsg_html.classList.add("hidden");
|
||||
href_form.classList.remove("hidden");
|
||||
href_label.classList.remove("hidden");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
this.show = function() {
|
||||
scene_index = scene_stack.length - 1;
|
||||
html_scene.classList.remove("hidden");
|
||||
if (errors.length < files.length) {
|
||||
close_btn.classList.add("hidden");
|
||||
}
|
||||
close_btn.onclick = onclose;
|
||||
nodes = [];
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
let file = files[i];
|
||||
let node = template.cloneNode(true);
|
||||
node.classList.remove("hidden");
|
||||
let name_form = node.querySelector("[data-name=name]");
|
||||
name_form.textContent = file.name;
|
||||
node.classList.remove("hidden");
|
||||
nodes.push(node);
|
||||
updateFileStatus(i);
|
||||
template.parentNode.insertBefore(node, template);
|
||||
}
|
||||
if (scene_index === null) {
|
||||
scene_index = scene_stack.length - 1;
|
||||
upload_next();
|
||||
}
|
||||
};
|
||||
|
||||
this.hide = function() {
|
||||
html_scene.classList.add("hidden");
|
||||
close_btn.classList.remove("hidden");
|
||||
upload_btn.classList.remove("hidden");
|
||||
uploadfile_form.classList.remove("hidden");
|
||||
uploadfile_lbl.classList.remove("hidden");
|
||||
href_form.classList.remove("hidden");
|
||||
href_label.classList.remove("hidden");
|
||||
hreflimitmsg_html.classList.add("hidden");
|
||||
pending_html.classList.add("hidden");
|
||||
close_btn.onclick = null;
|
||||
upload_btn.onclick = null;
|
||||
href_form.value = "";
|
||||
uploadfile_form.value = "";
|
||||
if(nodes == null){
|
||||
return;
|
||||
}
|
||||
nodes.forEach(function(node) {
|
||||
node.parentNode.removeChild(node);
|
||||
});
|
||||
|
@ -1142,7 +1206,7 @@ function CreateEditCollectionScene(user, password, collection) {
|
|||
|
||||
function read_form() {
|
||||
if(!edit){
|
||||
cleanHREFinput();
|
||||
cleanHREFinput(href_form);
|
||||
let newhreftxtvalue = href_form.value.trim().toLowerCase();
|
||||
if(!isValidHREF(newhreftxtvalue)){
|
||||
alert("You must enter a valid HREF");
|
||||
|
@ -1226,12 +1290,6 @@ function CreateEditCollectionScene(user, password, collection) {
|
|||
return false;
|
||||
}
|
||||
|
||||
function cleanHREFinput(event){
|
||||
let currentTxtVal = href_form.value.trim().toLowerCase();
|
||||
//Clean the HREF to remove non lowercase letters and dashes
|
||||
currentTxtVal = currentTxtVal.replace(/(?![0-9a-z\-\_])./g, '');
|
||||
href_form.value = currentTxtVal;
|
||||
}
|
||||
|
||||
function onTypeChange(e){
|
||||
if(type_form.value == CollectionType.WEBCAL){
|
||||
|
@ -1243,17 +1301,6 @@ function CreateEditCollectionScene(user, password, collection) {
|
|||
}
|
||||
}
|
||||
|
||||
function isValidHREF(href){
|
||||
if(href.length < 1){
|
||||
return false;
|
||||
}
|
||||
if(href.indexOf("/") != -1){
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
this.show = function() {
|
||||
this.release();
|
||||
scene_index = scene_stack.length - 1;
|
||||
|
@ -1289,6 +1336,40 @@ function CreateEditCollectionScene(user, password, collection) {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Removed invalid HREF characters for a collection HREF.
|
||||
*
|
||||
* @param a A valid Input element or an onchange Event of an Input element.
|
||||
*/
|
||||
function cleanHREFinput(a) {
|
||||
let href_form = a;
|
||||
if (a.target) {
|
||||
href_form = a.target;
|
||||
}
|
||||
let currentTxtVal = href_form.value.trim().toLowerCase();
|
||||
//Clean the HREF to remove non lowercase letters and dashes
|
||||
currentTxtVal = currentTxtVal.replace(/(?![0-9a-z\-\_])./g, '');
|
||||
href_form.value = currentTxtVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a proposed HREF for a collection has a valid format and syntax.
|
||||
*
|
||||
* @param href String of the porposed HREF.
|
||||
*
|
||||
* @return Boolean results if the HREF is valid.
|
||||
*/
|
||||
function isValidHREF(href) {
|
||||
if (href.length < 1) {
|
||||
return false;
|
||||
}
|
||||
if (href.indexOf("/") != -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format bytes to human-readable text.
|
||||
*
|
||||
|
|
|
@ -14,12 +14,13 @@
|
|||
<body>
|
||||
<nav id="logoutview" class="hidden">
|
||||
<span data-name="user" style="word-wrap:break-word;"></span>
|
||||
<a href="" class="red" data-name="link" title="Logout">Logout</a>
|
||||
<a href="#" class="green" data-name="refresh" title="Refresh">Refresh</a>
|
||||
<a href="#" class="red" data-name="logout" title="Logout">Logout</a>
|
||||
</nav>
|
||||
|
||||
<main>
|
||||
<section id="loadingscene">
|
||||
<img src="css/loading.svg" alt="Loading">
|
||||
<img src="css/loading.svg" alt="Loading..." class="loading">
|
||||
<h2>Loading</h2>
|
||||
<p>Please wait...</p>
|
||||
<noscript>JavaScript is required</noscript>
|
||||
|
@ -155,12 +156,20 @@
|
|||
<ul>
|
||||
<li data-name="filetemplate" class="hidden"> Uploading <span data-name="name">name</span>
|
||||
<br>
|
||||
<img data-name="pending" src="css/loading.svg" alt="Please wait...">
|
||||
<span class="successmessage" data-name="success">Uploaded Successfully!</span>
|
||||
<span class="error" data-name="error"></span>
|
||||
</li>
|
||||
</ul>
|
||||
<div data-name="pending" class="hidden">
|
||||
<img src="css/loading.svg" class="loading" alt="Please wait..."/>
|
||||
</div>
|
||||
<form>
|
||||
<label for="uploadfile">File:</label>
|
||||
<input data-name="uploadfile" type="file" accept=".ics, .vcf" multiple>
|
||||
<label for="href">HREF:</label>
|
||||
<input data-name="href" type="text">
|
||||
<small data-name="hreflimitmsg" class="hidden">You can only specify the HREF if you upload 1 file.</small>
|
||||
<button type="submit" class="green" data-name="submit">Upload</button>
|
||||
<button type="button" class="red" data-name="close">Close</button>
|
||||
</form>
|
||||
</section>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue