1
radicale/web/internal_data/css/icons/delete.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" viewBox="0 0 24 24" stroke-width="1.5" fill="none" xmlns="http://www.w3.org/2000/svg" color="#000000"><path d="M20 9l-1.995 11.346A2 2 0 0116.035 22h-8.07a2 2 0 01-1.97-1.654L4 9M21 6h-5.625M3 6h5.625m0 0V4a2 2 0 012-2h2.75a2 2 0 012 2v2m-6.75 0h6.75" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>
|
After Width: | Height: | Size: 418 B |
1
radicale/web/internal_data/css/icons/download.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="#000000"><path d="M6 20h12M12 4v12m0 0l3.5-3.5M12 16l-3.5-3.5" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>
|
After Width: | Height: | Size: 322 B |
1
radicale/web/internal_data/css/icons/edit.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" viewBox="0 0 24 24" stroke-width="1.5" fill="none" xmlns="http://www.w3.org/2000/svg" color="#000000"><path d="M14.363 5.652l1.48-1.48a2 2 0 012.829 0l1.414 1.414a2 2 0 010 2.828l-1.48 1.48m-4.243-4.242l-9.616 9.615a2 2 0 00-.578 1.238l-.242 2.74a1 1 0 001.084 1.085l2.74-.242a2 2 0 001.24-.578l9.615-9.616m-4.243-4.242l4.243 4.242" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>
|
After Width: | Height: | Size: 499 B |
1
radicale/web/internal_data/css/icons/new.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="#000000"><path d="M6 12h6m6 0h-6m0 0V6m0 6v6" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>
|
After Width: | Height: | Size: 305 B |
1
radicale/web/internal_data/css/icons/upload.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="#000000"><path d="M6 20h12M12 16V4m0 0l3.5 3.5M12 4L8.5 7.5" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>
|
After Width: | Height: | Size: 320 B |
55
radicale/web/internal_data/css/loading.svg
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
<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>
|
After Width: | Height: | Size: 3.9 KiB |
10
radicale/web/internal_data/css/logo.svg
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg width="200" height="300" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill="#a40000" d="M 186,188 C 184,98 34,105 47,192 C 59,279 130,296 130,296 C 130,296 189,277 186,188 z" />
|
||||||
|
<path fill="#ffffff" d="M 73,238 C 119,242 140,241 177,222 C 172,270 131,288 131,288 C 131,288 88,276 74,238 z" />
|
||||||
|
<g fill="none" stroke="#4e9a06" stroke-width="15">
|
||||||
|
<path d="M 103,137 C 77,69 13,62 13,62" />
|
||||||
|
<path d="M 105,136 C 105,86 37,20 37,20" />
|
||||||
|
<path d="M 105,135 C 112,73 83,17 83,17" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 564 B |
|
@ -1 +1,397 @@
|
||||||
body{background:#e4e9f6;color:#424247;display:flex;flex-direction:column;font-family:sans;font-size:14pt;line-height:1.4;margin:0;min-height:100vh}a{color:inherit}nav,footer{background:#a40000;color:#fff;padding:0 20%}nav ul,footer ul{display:flex;flex-wrap:wrap;margin:0;padding:0}nav ul li,footer ul li{display:block;padding:0 1em 0 0}nav ul li a,footer ul li a{color:inherit;display:block;padding:1em .5em 1em 0;text-decoration:inherit;transition:.2s}nav ul li a:hover,nav ul li a:focus,footer ul li a:hover,footer ul li a:focus{color:#000;outline:none}header{background:url(logo.svg),linear-gradient(to bottom right, #050a02, #000);background-position:22% 45%;background-repeat:no-repeat;color:#efdddd;font-size:1.5em;min-height:250px;overflow:auto;padding:3em 22%;text-shadow:.2em .2em .2em rgba(0,0,0,0.5)}header>*{padding-left:220px}header h1{font-size:2.5em;font-weight:lighter;margin:.5em 0}main{flex:1}section{padding:0 20% 2em}section:not(:last-child){border-bottom:1px dashed #ccc}section h1{background:linear-gradient(to bottom right, #050a02, #000);color:#e5dddd;font-size:2.5em;margin:0 -33.33% 1em;padding:1em 33.33%}section h2,section h3,section h4{font-weight:lighter;margin:1.5em 0 1em}article{border-top:1px solid transparent;position:relative;margin:3em 0}article aside{box-sizing:border-box;color:#aaa;font-size:.8em;right:-30%;top:.5em;position:absolute}article:before{border-top:1px dashed #ccc;content:"";display:block;left:-33.33%;position:absolute;right:-33.33%}pre{border-radius:3px;background:#000;color:#d3d5db;margin:0 -1em;overflow-x:auto;padding:1em}table{border-collapse:collapse;font-size:.8em;margin:auto}table td{border:1px solid #ccc;padding:.5em}dl dt{margin-bottom:.5em;margin-top:1em}p>code,li>code,dt>code{background:#d1daf0}@media (max-width: 800px){body{font-size:12pt}header,section{padding-left:2em;padding-right:2em}nav,footer{padding-left:0;padding-right:0}nav ul,footer ul{justify-content:center}nav ul li,footer ul li{padding:0 .5em}nav ul li a,footer ul li a{padding:1em 0}header{background-position:50% 30px,0 0;padding-bottom:0;padding-top:330px;text-align:center}header>*{margin:0;padding-left:0}section h1{margin:0 -.8em 1.3em;padding:.5em 0;text-align:center}article aside{top:.5em;right:-1.5em}article:before{left:-2em;right:-2em}}
|
body{
|
||||||
|
background: #ffffff;
|
||||||
|
color: #424247;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 14pt;
|
||||||
|
margin: 0;
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
flex-direction: row;
|
||||||
|
align-content: center;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: space-around;
|
||||||
|
}
|
||||||
|
|
||||||
|
main{
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container{
|
||||||
|
height: auto;
|
||||||
|
min-height: 450px;
|
||||||
|
width: 350px;
|
||||||
|
transition: .2s;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 20px 40px;
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid #dadce0;
|
||||||
|
border-radius: 8px;
|
||||||
|
display: block;
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container h1{
|
||||||
|
margin: 0;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
color: #484848;
|
||||||
|
}
|
||||||
|
|
||||||
|
#loginscene input{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#loginscene .logocontainer{
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#loginscene .logocontainer img{
|
||||||
|
width: 75px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#loginscene h1{
|
||||||
|
text-align: center;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
#loginscene button{
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
#loadingscene{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: rgb(237 237 237);
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
z-index: 999;
|
||||||
|
}
|
||||||
|
|
||||||
|
#loadingscene h2{
|
||||||
|
font-size: 2em;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
#logoutview{
|
||||||
|
width: 100%;
|
||||||
|
display: block;
|
||||||
|
background: white;
|
||||||
|
text-align: center;
|
||||||
|
padding: 10px 0px;
|
||||||
|
color: #666;
|
||||||
|
border-bottom: 2px solid #dadce0;
|
||||||
|
position: fixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
#logoutview span{
|
||||||
|
width: calc(100% - 60px);
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#logoutview a{
|
||||||
|
color: white;
|
||||||
|
text-decoration: none;
|
||||||
|
padding: 3px 10px;
|
||||||
|
position: absolute;
|
||||||
|
right: 25px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#collectionsscene{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-content: flex-start;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 50px;
|
||||||
|
width: 100%;
|
||||||
|
height: calc(100vh - 50px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#collectionsscene article{
|
||||||
|
width: 250px;
|
||||||
|
background: rgb(250, 250, 250);
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 2px 2px 3px #0000001a;
|
||||||
|
border: 1px solid #dadce0;
|
||||||
|
padding: 5px 10px;
|
||||||
|
padding-top: 0;
|
||||||
|
margin: 10px;
|
||||||
|
float: left;
|
||||||
|
height: 350px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#collectionsscene article .colorbar{
|
||||||
|
width: 500%;
|
||||||
|
height: 15px;
|
||||||
|
margin: 0px -100%;
|
||||||
|
background: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#collectionsscene article .title{
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 1.5em;
|
||||||
|
display: block;
|
||||||
|
padding: 10px 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#collectionsscene article small{
|
||||||
|
font-size: 15px;
|
||||||
|
float: left;
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: italic;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#collectionsscene article input[type=text]{
|
||||||
|
margin-bottom: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#collectionsscene article p{
|
||||||
|
font-size: 1em;
|
||||||
|
max-height: 130px;
|
||||||
|
overflow: overlay;
|
||||||
|
}
|
||||||
|
|
||||||
|
#collectionsscene article:hover ul{
|
||||||
|
display: flex !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#collectionsscene ul{
|
||||||
|
display: none;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
width: 60%;
|
||||||
|
margin: 0 20%;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#collectionsscene li{
|
||||||
|
list-style: none;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#collectionsscene li a{
|
||||||
|
text-decoration: none !important;
|
||||||
|
padding: 5px;
|
||||||
|
float: left;
|
||||||
|
border-radius: 5px;
|
||||||
|
width: 25px;
|
||||||
|
height: 25px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editcollectionscene p span{
|
||||||
|
word-wrap:break-word;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #4e9a06;
|
||||||
|
}
|
||||||
|
|
||||||
|
#deletecollectionscene p span{
|
||||||
|
word-wrap:break-word;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #a40000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#uploadcollectionscene ul{
|
||||||
|
margin: 10px -30px;
|
||||||
|
max-height: 600px;
|
||||||
|
overflow: overlay;
|
||||||
|
}
|
||||||
|
|
||||||
|
#uploadcollectionscene li{
|
||||||
|
border-bottom: 1px dashed #d5d5d5;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#uploadcollectionscene .successmessage{
|
||||||
|
color: #4e9a06;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
display: block;
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fabcontainer{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column-reverse;
|
||||||
|
position: fixed;
|
||||||
|
bottom: 5px;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fabcontainer a{
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
text-decoration: none;
|
||||||
|
color: white;
|
||||||
|
border: none !important;
|
||||||
|
border-radius: 100%;
|
||||||
|
margin: 5px 10px;
|
||||||
|
background: black;
|
||||||
|
text-align: center;
|
||||||
|
display: flex;
|
||||||
|
align-content: center;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 30px;
|
||||||
|
padding: 10px;
|
||||||
|
box-shadow: 2px 2px 7px #000000d6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title{
|
||||||
|
word-wrap: break-word;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
filter: invert(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.smalltext{
|
||||||
|
font-size: 75% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error{
|
||||||
|
width: 100%;
|
||||||
|
display: block;
|
||||||
|
text-align: center;
|
||||||
|
color: rgb(217,48,37);
|
||||||
|
font-family: sans-serif;
|
||||||
|
clear: both;
|
||||||
|
padding-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error::before{
|
||||||
|
content: "!";
|
||||||
|
height: 1em;
|
||||||
|
color: white;
|
||||||
|
background: rgb(217,48,37);
|
||||||
|
font-weight: bold;
|
||||||
|
border-radius: 100%;
|
||||||
|
display: inline-block;
|
||||||
|
width: 1.1em;
|
||||||
|
margin-right: 5px;
|
||||||
|
font-size: 1em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
button{
|
||||||
|
font-size: 1em;
|
||||||
|
padding: 7px 21px;
|
||||||
|
color: white;
|
||||||
|
border-radius: 4px;
|
||||||
|
float: right;
|
||||||
|
margin-left: 10px;
|
||||||
|
background: black;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
input, select{
|
||||||
|
width: 100%;
|
||||||
|
height: 3em;
|
||||||
|
border-style: solid;
|
||||||
|
border-color: #e6e6e6;
|
||||||
|
border-width: 1px;
|
||||||
|
border-radius: 7px;
|
||||||
|
margin-bottom: 25px;
|
||||||
|
padding-left: 15px;
|
||||||
|
padding-right: 15px;
|
||||||
|
outline: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=text], input[type=password]{
|
||||||
|
width: calc(100% - 30px);
|
||||||
|
}
|
||||||
|
|
||||||
|
input:active, input:focus, input:focus-visible{
|
||||||
|
border-color: #2494fe !important;
|
||||||
|
border-width: 1px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.red, span.red{
|
||||||
|
color: #b50202;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.red, a.red{
|
||||||
|
background: #b50202;
|
||||||
|
border: 1px solid #a40000;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.red:hover, a.red:hover{
|
||||||
|
background: #a40000;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.red:active, a.red:active{
|
||||||
|
background: #8f0000;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.green, a.green{
|
||||||
|
background: #4e9a06;
|
||||||
|
border: 1px solid #377200;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.green:hover, a.green:hover{
|
||||||
|
background: #377200;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.green:active, a.green:active{
|
||||||
|
background: #285200;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.blue, a.blue{
|
||||||
|
background: #2494fe;
|
||||||
|
border: 1px solid #055fb5;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.blue:hover, a.blue:hover{
|
||||||
|
background: #1578d6;
|
||||||
|
cursor: pointer !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.blue:active, a.blue:active{
|
||||||
|
background: #055fb5;
|
||||||
|
cursor: pointer !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 600px) {
|
||||||
|
#collectionsscene{
|
||||||
|
flex-direction: column !important;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
#collectionsscene article{
|
||||||
|
height: auto;
|
||||||
|
min-height: 350px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container{
|
||||||
|
max-width: 280px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#collectionsscene ul{
|
||||||
|
display: flex !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#logoutview span{
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* This file is part of Radicale Server - Calendar Server
|
* This file is part of Radicale Server - Calendar Server
|
||||||
* Copyright © 2017-2018 Unrud <unrud@outlook.com>
|
* Copyright © 2017-2024 Unrud <unrud@outlook.com>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -28,7 +28,7 @@ const SERVER = location.origin;
|
||||||
* @const
|
* @const
|
||||||
* @type {string}
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
const ROOT_PATH = (new URL("..", location.href)).pathname;
|
const ROOT_PATH = location.pathname.replace(new RegExp("/+[^/]+/*(/index\\.html?)?$"), "") + '/';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Regex to match and normalize color
|
* Regex to match and normalize color
|
||||||
|
@ -63,6 +63,7 @@ const CollectionType = {
|
||||||
CALENDAR: "CALENDAR",
|
CALENDAR: "CALENDAR",
|
||||||
JOURNAL: "JOURNAL",
|
JOURNAL: "JOURNAL",
|
||||||
TASKS: "TASKS",
|
TASKS: "TASKS",
|
||||||
|
WEBCAL: "WEBCAL",
|
||||||
is_subset: function(a, b) {
|
is_subset: function(a, b) {
|
||||||
let components = a.split("_");
|
let components = a.split("_");
|
||||||
for (let i = 0; i < components.length; i++) {
|
for (let i = 0; i < components.length; i++) {
|
||||||
|
@ -89,6 +90,9 @@ const CollectionType = {
|
||||||
if (a.search(this.TASKS) !== -1 || b.search(this.TASKS) !== -1) {
|
if (a.search(this.TASKS) !== -1 || b.search(this.TASKS) !== -1) {
|
||||||
union.push(this.TASKS);
|
union.push(this.TASKS);
|
||||||
}
|
}
|
||||||
|
if (a.search(this.WEBCAL) !== -1 || b.search(this.WEBCAL) !== -1) {
|
||||||
|
union.push(this.WEBCAL);
|
||||||
|
}
|
||||||
return union.join("_");
|
return union.join("_");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -102,12 +106,13 @@ const CollectionType = {
|
||||||
* @param {string} description
|
* @param {string} description
|
||||||
* @param {string} color
|
* @param {string} color
|
||||||
*/
|
*/
|
||||||
function Collection(href, type, displayname, description, color) {
|
function Collection(href, type, displayname, description, color, source) {
|
||||||
this.href = href;
|
this.href = href;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.displayname = displayname;
|
this.displayname = displayname;
|
||||||
this.color = color;
|
this.color = color;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
|
this.source = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -183,6 +188,7 @@ function get_collections(user, password, collection, callback) {
|
||||||
let addressbookcolor_element = response.querySelector(response_query + " > *|propstat > *|prop > *|addressbook-color");
|
let addressbookcolor_element = response.querySelector(response_query + " > *|propstat > *|prop > *|addressbook-color");
|
||||||
let calendardesc_element = response.querySelector(response_query + " > *|propstat > *|prop > *|calendar-description");
|
let calendardesc_element = response.querySelector(response_query + " > *|propstat > *|prop > *|calendar-description");
|
||||||
let addressbookdesc_element = response.querySelector(response_query + " > *|propstat > *|prop > *|addressbook-description");
|
let addressbookdesc_element = response.querySelector(response_query + " > *|propstat > *|prop > *|addressbook-description");
|
||||||
|
let webcalsource_element = response.querySelector(response_query + " > *|propstat > *|prop > *|source");
|
||||||
let components_query = response_query + " > *|propstat > *|prop > *|supported-calendar-component-set";
|
let components_query = response_query + " > *|propstat > *|prop > *|supported-calendar-component-set";
|
||||||
let components_element = response.querySelector(components_query);
|
let components_element = response.querySelector(components_query);
|
||||||
let href = href_element ? href_element.textContent : "";
|
let href = href_element ? href_element.textContent : "";
|
||||||
|
@ -190,11 +196,17 @@ function get_collections(user, password, collection, callback) {
|
||||||
let type = "";
|
let type = "";
|
||||||
let color = "";
|
let color = "";
|
||||||
let description = "";
|
let description = "";
|
||||||
|
let source = "";
|
||||||
if (resourcetype_element) {
|
if (resourcetype_element) {
|
||||||
if (resourcetype_element.querySelector(resourcetype_query + " > *|addressbook")) {
|
if (resourcetype_element.querySelector(resourcetype_query + " > *|addressbook")) {
|
||||||
type = CollectionType.ADDRESSBOOK;
|
type = CollectionType.ADDRESSBOOK;
|
||||||
color = addressbookcolor_element ? addressbookcolor_element.textContent : "";
|
color = addressbookcolor_element ? addressbookcolor_element.textContent : "";
|
||||||
description = addressbookdesc_element ? addressbookdesc_element.textContent : "";
|
description = addressbookdesc_element ? addressbookdesc_element.textContent : "";
|
||||||
|
} else if (resourcetype_element.querySelector(resourcetype_query + " > *|subscribed")) {
|
||||||
|
type = CollectionType.WEBCAL;
|
||||||
|
source = webcalsource_element ? webcalsource_element.textContent : "";
|
||||||
|
color = calendarcolor_element ? calendarcolor_element.textContent : "";
|
||||||
|
description = calendardesc_element ? calendardesc_element.textContent : "";
|
||||||
} else if (resourcetype_element.querySelector(resourcetype_query + " > *|calendar")) {
|
} else if (resourcetype_element.querySelector(resourcetype_query + " > *|calendar")) {
|
||||||
if (components_element) {
|
if (components_element) {
|
||||||
if (components_element.querySelector(components_query + " > *|comp[name=VEVENT]")) {
|
if (components_element.querySelector(components_query + " > *|comp[name=VEVENT]")) {
|
||||||
|
@ -221,7 +233,7 @@ function get_collections(user, password, collection, callback) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (href.substr(-1) === "/" && href !== collection.href && type) {
|
if (href.substr(-1) === "/" && href !== collection.href && type) {
|
||||||
collections.push(new Collection(href, type, displayname, description, sane_color));
|
collections.push(new Collection(href, type, displayname, description, sane_color, source));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
collections.sort(function(a, b) {
|
collections.sort(function(a, b) {
|
||||||
|
@ -235,11 +247,15 @@ function get_collections(user, password, collection, callback) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
request.send('<?xml version="1.0" encoding="utf-8" ?>' +
|
request.send('<?xml version="1.0" encoding="utf-8" ?>' +
|
||||||
'<propfind xmlns="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav" ' +
|
'<propfind ' +
|
||||||
|
'xmlns="DAV:" ' +
|
||||||
|
'xmlns:C="urn:ietf:params:xml:ns:caldav" ' +
|
||||||
'xmlns:CR="urn:ietf:params:xml:ns:carddav" ' +
|
'xmlns:CR="urn:ietf:params:xml:ns:carddav" ' +
|
||||||
|
'xmlns:CS="http://calendarserver.org/ns/" ' +
|
||||||
'xmlns:I="http://apple.com/ns/ical/" ' +
|
'xmlns:I="http://apple.com/ns/ical/" ' +
|
||||||
'xmlns:INF="http://inf-it.com/ns/ab/" ' +
|
'xmlns:INF="http://inf-it.com/ns/ab/" ' +
|
||||||
'xmlns:RADICALE="http://radicale.org/ns/">' +
|
'xmlns:RADICALE="http://radicale.org/ns/"' +
|
||||||
|
'>' +
|
||||||
'<prop>' +
|
'<prop>' +
|
||||||
'<resourcetype />' +
|
'<resourcetype />' +
|
||||||
'<RADICALE:displayname />' +
|
'<RADICALE:displayname />' +
|
||||||
|
@ -248,6 +264,7 @@ function get_collections(user, password, collection, callback) {
|
||||||
'<C:calendar-description />' +
|
'<C:calendar-description />' +
|
||||||
'<C:supported-calendar-component-set />' +
|
'<C:supported-calendar-component-set />' +
|
||||||
'<CR:addressbook-description />' +
|
'<CR:addressbook-description />' +
|
||||||
|
'<CS:source />' +
|
||||||
'</prop>' +
|
'</prop>' +
|
||||||
'</propfind>');
|
'</propfind>');
|
||||||
return request;
|
return request;
|
||||||
|
@ -329,12 +346,18 @@ function create_edit_collection(user, password, collection, create, callback) {
|
||||||
let addressbook_color = "";
|
let addressbook_color = "";
|
||||||
let calendar_description = "";
|
let calendar_description = "";
|
||||||
let addressbook_description = "";
|
let addressbook_description = "";
|
||||||
|
let calendar_source = "";
|
||||||
let resourcetype;
|
let resourcetype;
|
||||||
let components = "";
|
let components = "";
|
||||||
if (collection.type === CollectionType.ADDRESSBOOK) {
|
if (collection.type === CollectionType.ADDRESSBOOK) {
|
||||||
addressbook_color = escape_xml(collection.color + (collection.color ? "ff" : ""));
|
addressbook_color = escape_xml(collection.color + (collection.color ? "ff" : ""));
|
||||||
addressbook_description = escape_xml(collection.description);
|
addressbook_description = escape_xml(collection.description);
|
||||||
resourcetype = '<CR:addressbook />';
|
resourcetype = '<CR:addressbook />';
|
||||||
|
} else if (collection.type === CollectionType.WEBCAL) {
|
||||||
|
calendar_color = escape_xml(collection.color + (collection.color ? "ff" : ""));
|
||||||
|
calendar_description = escape_xml(collection.description);
|
||||||
|
resourcetype = '<CS:subscribed />';
|
||||||
|
calendar_source = collection.source;
|
||||||
} else {
|
} else {
|
||||||
calendar_color = escape_xml(collection.color + (collection.color ? "ff" : ""));
|
calendar_color = escape_xml(collection.color + (collection.color ? "ff" : ""));
|
||||||
calendar_description = escape_xml(collection.description);
|
calendar_description = escape_xml(collection.description);
|
||||||
|
@ -351,7 +374,7 @@ function create_edit_collection(user, password, collection, create, callback) {
|
||||||
}
|
}
|
||||||
let xml_request = create ? "mkcol" : "propertyupdate";
|
let xml_request = create ? "mkcol" : "propertyupdate";
|
||||||
request.send('<?xml version="1.0" encoding="UTF-8" ?>' +
|
request.send('<?xml version="1.0" encoding="UTF-8" ?>' +
|
||||||
'<' + xml_request + ' xmlns="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav" xmlns:CR="urn:ietf:params:xml:ns:carddav" xmlns:I="http://apple.com/ns/ical/" xmlns:INF="http://inf-it.com/ns/ab/">' +
|
'<' + xml_request + ' xmlns="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav" xmlns:CR="urn:ietf:params:xml:ns:carddav" xmlns:CS="http://calendarserver.org/ns/" xmlns:I="http://apple.com/ns/ical/" xmlns:INF="http://inf-it.com/ns/ab/">' +
|
||||||
'<set>' +
|
'<set>' +
|
||||||
'<prop>' +
|
'<prop>' +
|
||||||
(create ? '<resourcetype><collection />' + resourcetype + '</resourcetype>' : '') +
|
(create ? '<resourcetype><collection />' + resourcetype + '</resourcetype>' : '') +
|
||||||
|
@ -361,6 +384,7 @@ function create_edit_collection(user, password, collection, create, callback) {
|
||||||
(addressbook_color ? '<INF:addressbook-color>' + addressbook_color + '</INF:addressbook-color>' : '') +
|
(addressbook_color ? '<INF:addressbook-color>' + addressbook_color + '</INF:addressbook-color>' : '') +
|
||||||
(addressbook_description ? '<CR:addressbook-description>' + addressbook_description + '</CR:addressbook-description>' : '') +
|
(addressbook_description ? '<CR:addressbook-description>' + addressbook_description + '</CR:addressbook-description>' : '') +
|
||||||
(calendar_description ? '<C:calendar-description>' + calendar_description + '</C:calendar-description>' : '') +
|
(calendar_description ? '<C:calendar-description>' + calendar_description + '</C:calendar-description>' : '') +
|
||||||
|
(calendar_source ? '<CS:source>' + calendar_source + '</CS:source>' : '') +
|
||||||
'</prop>' +
|
'</prop>' +
|
||||||
'</set>' +
|
'</set>' +
|
||||||
(!create ? ('<remove>' +
|
(!create ? ('<remove>' +
|
||||||
|
@ -495,7 +519,12 @@ function LoginScene() {
|
||||||
function fill_form() {
|
function fill_form() {
|
||||||
user_form.value = user;
|
user_form.value = user;
|
||||||
password_form.value = "";
|
password_form.value = "";
|
||||||
error_form.textContent = error ? "Error: " + error : "";
|
if(error){
|
||||||
|
error_form.textContent = "Error: " + error;
|
||||||
|
error_form.classList.remove("hidden");
|
||||||
|
}else{
|
||||||
|
error_form.classList.add("hidden");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onlogin() {
|
function onlogin() {
|
||||||
|
@ -507,7 +536,7 @@ function LoginScene() {
|
||||||
// setup logout
|
// setup logout
|
||||||
logout_view.classList.remove("hidden");
|
logout_view.classList.remove("hidden");
|
||||||
logout_btn.onclick = onlogout;
|
logout_btn.onclick = onlogout;
|
||||||
logout_user_form.textContent = user;
|
logout_user_form.textContent = user + "'s Collections";
|
||||||
// Fetch principal
|
// Fetch principal
|
||||||
let loading_scene = new LoadingScene();
|
let loading_scene = new LoadingScene();
|
||||||
push_scene(loading_scene, false);
|
push_scene(loading_scene, false);
|
||||||
|
@ -683,12 +712,11 @@ function CollectionsScene(user, password, collection, onerror) {
|
||||||
let color_form = node.querySelector("[data-name=color]");
|
let color_form = node.querySelector("[data-name=color]");
|
||||||
let delete_btn = node.querySelector("[data-name=delete]");
|
let delete_btn = node.querySelector("[data-name=delete]");
|
||||||
let edit_btn = node.querySelector("[data-name=edit]");
|
let edit_btn = node.querySelector("[data-name=edit]");
|
||||||
|
let download_btn = node.querySelector("[data-name=download]");
|
||||||
if (collection.color) {
|
if (collection.color) {
|
||||||
color_form.style.color = collection.color;
|
color_form.style.background = collection.color;
|
||||||
} else {
|
|
||||||
color_form.classList.add("hidden");
|
|
||||||
}
|
}
|
||||||
let possible_types = [CollectionType.ADDRESSBOOK];
|
let possible_types = [CollectionType.ADDRESSBOOK, CollectionType.WEBCAL];
|
||||||
[CollectionType.CALENDAR, ""].forEach(function(e) {
|
[CollectionType.CALENDAR, ""].forEach(function(e) {
|
||||||
[CollectionType.union(e, CollectionType.JOURNAL), e].forEach(function(e) {
|
[CollectionType.union(e, CollectionType.JOURNAL), e].forEach(function(e) {
|
||||||
[CollectionType.union(e, CollectionType.TASKS), e].forEach(function(e) {
|
[CollectionType.union(e, CollectionType.TASKS), e].forEach(function(e) {
|
||||||
|
@ -704,10 +732,16 @@ function CollectionsScene(user, password, collection, onerror) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
title_form.textContent = collection.displayname || collection.href;
|
title_form.textContent = collection.displayname || collection.href;
|
||||||
|
if(title_form.textContent.length > 30){
|
||||||
|
title_form.classList.add("smalltext");
|
||||||
|
}
|
||||||
description_form.textContent = collection.description;
|
description_form.textContent = collection.description;
|
||||||
|
if(description_form.textContent.length > 150){
|
||||||
|
description_form.classList.add("smalltext");
|
||||||
|
}
|
||||||
let href = SERVER + collection.href;
|
let href = SERVER + collection.href;
|
||||||
url_form.href = href;
|
url_form.value = href;
|
||||||
url_form.textContent = href;
|
download_btn.href = href;
|
||||||
delete_btn.onclick = function() {return ondelete(collection);};
|
delete_btn.onclick = function() {return ondelete(collection);};
|
||||||
edit_btn.onclick = function() {return onedit(collection);};
|
edit_btn.onclick = function() {return onedit(collection);};
|
||||||
node.classList.remove("hidden");
|
node.classList.remove("hidden");
|
||||||
|
@ -945,9 +979,15 @@ function DeleteCollectionScene(user, password, collection) {
|
||||||
scene_index = scene_stack.length - 1;
|
scene_index = scene_stack.length - 1;
|
||||||
html_scene.classList.remove("hidden");
|
html_scene.classList.remove("hidden");
|
||||||
title_form.textContent = collection.displayname || collection.href;
|
title_form.textContent = collection.displayname || collection.href;
|
||||||
error_form.textContent = error ? "Error: " + error : "";
|
|
||||||
delete_btn.onclick = ondelete;
|
delete_btn.onclick = ondelete;
|
||||||
cancel_btn.onclick = oncancel;
|
cancel_btn.onclick = oncancel;
|
||||||
|
if(error){
|
||||||
|
error_form.textContent = "Error: " + error;
|
||||||
|
error_form.classList.remove("hidden");
|
||||||
|
}else{
|
||||||
|
error_form.classList.add("hidden");
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
this.hide = function() {
|
this.hide = function() {
|
||||||
html_scene.classList.add("hidden");
|
html_scene.classList.add("hidden");
|
||||||
|
@ -989,12 +1029,19 @@ function CreateEditCollectionScene(user, password, collection) {
|
||||||
let title_form = edit ? html_scene.querySelector("[data-name=title]") : null;
|
let title_form = edit ? html_scene.querySelector("[data-name=title]") : null;
|
||||||
let error_form = html_scene.querySelector("[data-name=error]");
|
let error_form = html_scene.querySelector("[data-name=error]");
|
||||||
let displayname_form = html_scene.querySelector("[data-name=displayname]");
|
let displayname_form = html_scene.querySelector("[data-name=displayname]");
|
||||||
|
let displayname_label = html_scene.querySelector("label[for=displayname]");
|
||||||
let description_form = html_scene.querySelector("[data-name=description]");
|
let description_form = html_scene.querySelector("[data-name=description]");
|
||||||
|
let description_label = html_scene.querySelector("label[for=description]");
|
||||||
|
let source_form = html_scene.querySelector("[data-name=source]");
|
||||||
|
let source_label = html_scene.querySelector("label[for=source]");
|
||||||
let type_form = html_scene.querySelector("[data-name=type]");
|
let type_form = html_scene.querySelector("[data-name=type]");
|
||||||
|
let type_label = html_scene.querySelector("label[for=type]");
|
||||||
let color_form = html_scene.querySelector("[data-name=color]");
|
let color_form = html_scene.querySelector("[data-name=color]");
|
||||||
|
let color_label = html_scene.querySelector("label[for=color]");
|
||||||
let submit_btn = html_scene.querySelector("[data-name=submit]");
|
let submit_btn = html_scene.querySelector("[data-name=submit]");
|
||||||
let cancel_btn = html_scene.querySelector("[data-name=cancel]");
|
let cancel_btn = html_scene.querySelector("[data-name=cancel]");
|
||||||
|
|
||||||
|
|
||||||
/** @type {?number} */ let scene_index = null;
|
/** @type {?number} */ let scene_index = null;
|
||||||
/** @type {?XMLHttpRequest} */ let create_edit_req = null;
|
/** @type {?XMLHttpRequest} */ let create_edit_req = null;
|
||||||
let error = "";
|
let error = "";
|
||||||
|
@ -1003,6 +1050,7 @@ function CreateEditCollectionScene(user, password, collection) {
|
||||||
let href = edit ? collection.href : collection.href + random_uuid() + "/";
|
let href = edit ? collection.href : collection.href + random_uuid() + "/";
|
||||||
let displayname = edit ? collection.displayname : "";
|
let displayname = edit ? collection.displayname : "";
|
||||||
let description = edit ? collection.description : "";
|
let description = edit ? collection.description : "";
|
||||||
|
let source = edit ? collection.source : "";
|
||||||
let type = edit ? collection.type : CollectionType.CALENDAR_JOURNAL_TASKS;
|
let type = edit ? collection.type : CollectionType.CALENDAR_JOURNAL_TASKS;
|
||||||
let color = edit && collection.color ? collection.color : "#" + random_hex(6);
|
let color = edit && collection.color ? collection.color : "#" + random_hex(6);
|
||||||
|
|
||||||
|
@ -1022,6 +1070,7 @@ function CreateEditCollectionScene(user, password, collection) {
|
||||||
function read_form() {
|
function read_form() {
|
||||||
displayname = displayname_form.value;
|
displayname = displayname_form.value;
|
||||||
description = description_form.value;
|
description = description_form.value;
|
||||||
|
source = source_form.value;
|
||||||
type = type_form.value;
|
type = type_form.value;
|
||||||
color = color_form.value;
|
color = color_form.value;
|
||||||
}
|
}
|
||||||
|
@ -1029,9 +1078,17 @@ function CreateEditCollectionScene(user, password, collection) {
|
||||||
function fill_form() {
|
function fill_form() {
|
||||||
displayname_form.value = displayname;
|
displayname_form.value = displayname;
|
||||||
description_form.value = description;
|
description_form.value = description;
|
||||||
|
source_form.value = source;
|
||||||
type_form.value = type;
|
type_form.value = type;
|
||||||
color_form.value = color;
|
color_form.value = color;
|
||||||
error_form.textContent = error ? "Error: " + error : "";
|
if(error){
|
||||||
|
error_form.textContent = "Error: " + error;
|
||||||
|
error_form.classList.remove("hidden");
|
||||||
|
}
|
||||||
|
error_form.classList.add("hidden");
|
||||||
|
|
||||||
|
onTypeChange();
|
||||||
|
type_form.addEventListener("change", onTypeChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onsubmit() {
|
function onsubmit() {
|
||||||
|
@ -1049,7 +1106,7 @@ function CreateEditCollectionScene(user, password, collection) {
|
||||||
}
|
}
|
||||||
let loading_scene = new LoadingScene();
|
let loading_scene = new LoadingScene();
|
||||||
push_scene(loading_scene);
|
push_scene(loading_scene);
|
||||||
let collection = new Collection(href, type, displayname, description, sane_color);
|
let collection = new Collection(href, type, displayname, description, sane_color, source);
|
||||||
let callback = function(error1) {
|
let callback = function(error1) {
|
||||||
if (scene_index === null) {
|
if (scene_index === null) {
|
||||||
return;
|
return;
|
||||||
|
@ -1082,6 +1139,16 @@ function CreateEditCollectionScene(user, password, collection) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onTypeChange(e){
|
||||||
|
if(type_form.value == CollectionType.WEBCAL){
|
||||||
|
source_label.classList.remove("hidden");
|
||||||
|
source_form.classList.remove("hidden");
|
||||||
|
}else{
|
||||||
|
source_label.classList.add("hidden");
|
||||||
|
source_form.classList.add("hidden");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.show = function() {
|
this.show = function() {
|
||||||
this.release();
|
this.release();
|
||||||
scene_index = scene_stack.length - 1;
|
scene_index = scene_stack.length - 1;
|
||||||
|
|
|
@ -1,138 +1,179 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
<head>
|
||||||
<head>
|
<meta charset="utf-8">
|
||||||
<meta charset="utf-8">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<title>Radicale Web Interface</title>
|
||||||
<script src="fn.js"></script>
|
<link href="css/main.css" type="text/css" media="screen" rel="stylesheet">
|
||||||
<title>Radicale Web Interface</title>
|
<link href="css/icon.png" type="image/png" rel="icon">
|
||||||
<link href="css/main.css" media="screen" rel="stylesheet">
|
<style>.hidden {display: none !important;}</style>
|
||||||
<link href="css/icon.png" type="image/png" rel="icon">
|
<script src="fn.js"></script>
|
||||||
<style>
|
</head>
|
||||||
.hidden {display:none;}
|
|
||||||
</style>
|
<body>
|
||||||
</head>
|
<nav id="logoutview" class="hidden">
|
||||||
|
<span data-name="user" style="word-wrap:break-word;"></span>
|
||||||
<body>
|
<a href="" class="red" data-name="link" title="Logout">Logout</a>
|
||||||
<nav>
|
</nav>
|
||||||
<ul>
|
|
||||||
<li id="logoutview" class="hidden"><a href="" data-name="link">Logout [<span data-name="user" style="word-wrap:break-word;"></span>]</a></li>
|
<main>
|
||||||
</ul>
|
<section id="loadingscene">
|
||||||
</nav>
|
<img src="css/loading.svg" alt="Loading">
|
||||||
|
<h2>Loading</h2>
|
||||||
<main>
|
<p>Please wait...</p>
|
||||||
<section id="loadingscene">
|
<noscript>JavaScript is required</noscript>
|
||||||
<h1>Loading</h1>
|
</section>
|
||||||
<p>Please wait...</p>
|
|
||||||
<noscript>JavaScript is required</noscript>
|
<section id="loginscene" class="container hidden">
|
||||||
</section>
|
<div class="logocontainer">
|
||||||
|
<img src="css/logo.svg" alt="Radicale">
|
||||||
<section id="loginscene" class="hidden">
|
</div>
|
||||||
<h1>Login</h1>
|
<h1>Sign in</h1>
|
||||||
<form data-name="form">
|
<br>
|
||||||
<input data-name="user" type="text" placeholder="Username"><br>
|
<form data-name="form">
|
||||||
<input data-name="password" type="password" placeholder="Password"><br>
|
<input data-name="user" type="text" placeholder="Username">
|
||||||
<span style="color: #A40000;" data-name="error"></span><br>
|
<input data-name="password" type="password" placeholder="Password">
|
||||||
<button type="submit">Next</button>
|
<button class="green" type="submit">Next</button>
|
||||||
</form>
|
<span class="error" data-name="error"></span>
|
||||||
</section>
|
</form>
|
||||||
|
</section>
|
||||||
<section id="collectionsscene" class="hidden">
|
|
||||||
<h1>Collections</h1>
|
<section id="collectionsscene" class="hidden">
|
||||||
<ul>
|
<div class="fabcontainer">
|
||||||
<li><a href="" data-name="new">Create new addressbook or calendar</a></li>
|
<a href="" class="green" data-name="new" title="Create a new addressbook or calendar">
|
||||||
<li><a href="" data-name="upload">Upload addressbook or calendar</a></li>
|
<img src="css/icons/new.svg" class="icon" alt="➕">
|
||||||
</ul>
|
</a>
|
||||||
<article data-name="collectiontemplate" class="hidden">
|
<a href="" class="blue" data-name="upload" title="Upload an addressbook or calendar">
|
||||||
<h2><span data-name="color">█ </span><span data-name="title" style="word-wrap:break-word;">Title</span> <small>[<span data-name="ADDRESSBOOK">addressbook</span><span data-name="CALENDAR_JOURNAL_TASKS">calendar, journal and tasks</span><span data-name="CALENDAR_JOURNAL">calendar and journal</span><span data-name="CALENDAR_TASKS">calendar and tasks</span><span data-name="JOURNAL_TASKS">journal and tasks</span><span data-name="CALENDAR">calendar</span><span data-name="JOURNAL">journal</span><span data-name="TASKS">tasks</span>]</small></h2>
|
<img src="css/icons/upload.svg" class="icon" alt="⬆️">
|
||||||
<span data-name="description" style="word-wrap:break-word;">Description</span>
|
</a>
|
||||||
|
</div>
|
||||||
|
<article data-name="collectiontemplate" class="hidden">
|
||||||
|
<div class="colorbar" data-name="color"></div>
|
||||||
|
<h3 class="title" data-name="title">Title</h3>
|
||||||
|
<small>
|
||||||
|
<span data-name="ADDRESSBOOK">Address book</span>
|
||||||
|
<span data-name="CALENDAR_JOURNAL_TASKS">Calendar, journal and tasks</span>
|
||||||
|
<span data-name="CALENDAR_JOURNAL">Calendar and journal</span>
|
||||||
|
<span data-name="CALENDAR_TASKS">Calendar and tasks</span>
|
||||||
|
<span data-name="JOURNAL_TASKS">Journal and tasks</span>
|
||||||
|
<span data-name="CALENDAR">Calendar</span>
|
||||||
|
<span data-name="JOURNAL">Journal</span>
|
||||||
|
<span data-name="TASKS">Tasks</span>
|
||||||
|
<span data-name="WEBCAL">Webcal</span>
|
||||||
|
</small>
|
||||||
|
<input type="text" data-name="url" value="" readonly="" onfocus="this.setSelectionRange(0, 99999);">
|
||||||
|
<p data-name="description" style="word-wrap:break-word;">Description</p>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<a href="" title="Download" class="green" data-name="download">
|
||||||
|
<img src="css/icons/download.svg" class="icon" alt="🔗">
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="" title="Edit" class="blue" data-name="edit">
|
||||||
|
<img src="css/icons/edit.svg" class="icon" alt="✏️">
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="" title="Delete" class="red" data-name="delete">
|
||||||
|
<img src="css/icons/delete.svg" class="icon" alt="❌">
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</article>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="editcollectionscene" class="container hidden">
|
||||||
|
<h1>Edit Collection</h1>
|
||||||
|
<p>Editing collection <span class="title" data-name="title">title</span>
|
||||||
|
</p>
|
||||||
|
<form> Type: <br>
|
||||||
|
<select data-name="type">
|
||||||
|
<option value="ADDRESSBOOK">addressbook</option>
|
||||||
|
<option value="CALENDAR_JOURNAL_TASKS">calendar, journal and tasks</option>
|
||||||
|
<option value="CALENDAR_JOURNAL">calendar and journal</option>
|
||||||
|
<option value="CALENDAR_TASKS">calendar and tasks</option>
|
||||||
|
<option value="JOURNAL_TASKS">journal and tasks</option>
|
||||||
|
<option value="CALENDAR">calendar</option>
|
||||||
|
<option value="JOURNAL">journal</option>
|
||||||
|
<option value="TASKS">tasks</option>
|
||||||
|
<option value="WEBCAL">webcal</option>
|
||||||
|
</select>
|
||||||
|
<label for="displayname">Title:</label>
|
||||||
|
<input data-name="displayname" type="text">
|
||||||
|
<label for="description">Description:</label>
|
||||||
|
<input data-name="description" type="text">
|
||||||
|
<label for="source">Source:</label>
|
||||||
|
<input data-name="source" type="url">
|
||||||
|
<label for="color">Color:</label>
|
||||||
|
<input data-name="color" type="color">
|
||||||
|
<br>
|
||||||
|
<span class="error hidden" data-name="error"></span>
|
||||||
|
<br>
|
||||||
|
<button type="submit" class="green" data-name="submit">Save</button>
|
||||||
|
<button type="button" class="red" data-name="cancel">Cancel</button>
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="createcollectionscene" class="container hidden">
|
||||||
|
<h1>Create a new Collection</h1>
|
||||||
|
<p>Enter the details of your new collection.</p>
|
||||||
|
<form> Type: <br>
|
||||||
|
<select data-name="type">
|
||||||
|
<option value="ADDRESSBOOK">Address book</option>
|
||||||
|
<option value="CALENDAR_JOURNAL_TASKS">Calendar, journal and tasks</option>
|
||||||
|
<option value="CALENDAR_JOURNAL">Calendar and journal</option>
|
||||||
|
<option value="CALENDAR_TASKS">Calendar and tasks</option>
|
||||||
|
<option value="JOURNAL_TASKS">Journal and tasks</option>
|
||||||
|
<option value="CALENDAR">Calendar</option>
|
||||||
|
<option value="JOURNAL">Journal</option>
|
||||||
|
<option value="TASKS">Tasks</option>
|
||||||
|
<option value="WEBCAL">Webcal</option>
|
||||||
|
</select>
|
||||||
|
<label for="displayname">Title:</label>
|
||||||
|
<input data-name="displayname" type="text">
|
||||||
|
<label for="description">Description:</label>
|
||||||
|
<input data-name="description" type="text">
|
||||||
|
<label for="source">Source:</label>
|
||||||
|
<input data-name="source" type="url">
|
||||||
|
<label for="color">Color:</label>
|
||||||
|
<input data-name="color" type="color">
|
||||||
|
<br>
|
||||||
|
<span class="error" data-name="error"></span>
|
||||||
|
<br>
|
||||||
|
<button type="submit" class="green" data-name="submit">Create</button>
|
||||||
|
<button type="button" class="red" data-name="cancel">Cancel</button>
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="uploadcollectionscene" class="container hidden">
|
||||||
|
<h1>Upload Collection</h1>
|
||||||
<ul>
|
<ul>
|
||||||
<li>URL: <a data-name="url" style="word-wrap:break-word;">url</a></li>
|
<li data-name="filetemplate" class="hidden"> Uploading <span data-name="name">name</span>
|
||||||
<li><a href="" data-name="edit">Edit</a></li>
|
<br>
|
||||||
<li><a href="" data-name="delete">Delete</a></li>
|
<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>
|
</ul>
|
||||||
</article>
|
<form>
|
||||||
</section>
|
<button type="button" class="red" data-name="close">Close</button>
|
||||||
|
</form>
|
||||||
<section id="editcollectionscene" class="hidden">
|
</section>
|
||||||
<h1>Edit collection</h1>
|
|
||||||
<h2>Edit <span data-name="title" style="word-wrap:break-word;font-weight:bold;">title</span>:</h2>
|
<section id="deletecollectionscene" class="container hidden">
|
||||||
<form>
|
<h1>Delete Collection</h1>
|
||||||
Title:<br>
|
<p>Do you want to delete the collection <span class="title" data-name="title">title</span>? </p>
|
||||||
<input data-name="displayname" type="text"><br>
|
<p class="red">WARNING: This action cannot be reversed.</p>
|
||||||
Description:<br>
|
<form>
|
||||||
<input data-name="description" type="text"><br>
|
<button type="button" class="red" data-name="delete">Delete</button>
|
||||||
Type:<br>
|
<button type="button" class="blue" data-name="cancel">Cancel</button>
|
||||||
<select data-name="type">
|
</form>
|
||||||
<option value="ADDRESSBOOK">addressbook</option>
|
<span class="error hidden" data-name="error"></span>
|
||||||
<option value="CALENDAR_JOURNAL_TASKS">calendar, journal and tasks</option>
|
<br>
|
||||||
<option value="CALENDAR_JOURNAL">calendar and journal</option>
|
</section>
|
||||||
<option value="CALENDAR_TASKS">calendar and tasks</option>
|
|
||||||
<option value="JOURNAL_TASKS">journal and tasks</option>
|
</main>
|
||||||
<option value="CALENDAR">calendar</option>
|
</body>
|
||||||
<option value="JOURNAL">journal</option>
|
</html>
|
||||||
<option value="TASKS">tasks</option>
|
|
||||||
</select><br>
|
|
||||||
Color:<br>
|
|
||||||
<input data-name="color" type="color"><br>
|
|
||||||
<span style="color: #A40000;" data-name="error"></span><br>
|
|
||||||
<button type="submit" data-name="submit">Save</button>
|
|
||||||
<button type="button" data-name="cancel">Cancel</button>
|
|
||||||
</form>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="createcollectionscene" class="hidden">
|
|
||||||
<h1>Create new collection</h1>
|
|
||||||
<form>
|
|
||||||
Title:<br>
|
|
||||||
<input data-name="displayname" type="text"><br>
|
|
||||||
Description:<br>
|
|
||||||
<input data-name="description" type="text"><br>
|
|
||||||
Type:<br>
|
|
||||||
<select data-name="type">
|
|
||||||
<option value="ADDRESSBOOK">addressbook</option>
|
|
||||||
<option value="CALENDAR_JOURNAL_TASKS">calendar, journal and tasks</option>
|
|
||||||
<option value="CALENDAR_JOURNAL">calendar and journal</option>
|
|
||||||
<option value="CALENDAR_TASKS">calendar and tasks</option>
|
|
||||||
<option value="JOURNAL_TASKS">journal and tasks</option>
|
|
||||||
<option value="CALENDAR">calendar</option>
|
|
||||||
<option value="JOURNAL">journal</option>
|
|
||||||
<option value="TASKS">tasks</option>
|
|
||||||
</select><br>
|
|
||||||
Color:<br>
|
|
||||||
<input data-name="color" type="color"><br>
|
|
||||||
<span style="color: #A40000;" data-name="error"></span><br>
|
|
||||||
<button type="submit" data-name="submit">Create</button>
|
|
||||||
<button type="button" data-name="cancel">Cancel</button>
|
|
||||||
</form>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="uploadcollectionscene" class="hidden">
|
|
||||||
<h1>Upload collection</h1>
|
|
||||||
<ul>
|
|
||||||
<li data-name="filetemplate" class="hidden">
|
|
||||||
Upload <span data-name="name" style="word-wrap:break-word;font-weight:bold;">name</span>:<br>
|
|
||||||
<span data-name="pending">Please wait...</span>
|
|
||||||
<span style="color: #00A400;" data-name="success">Finished</span>
|
|
||||||
<span style="color: #A40000;" data-name="error"></span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<form>
|
|
||||||
<button type="button" data-name="close">Close</button>
|
|
||||||
</form>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="deletecollectionscene" class="hidden">
|
|
||||||
<h1>Delete collection</h1>
|
|
||||||
<h2>Delete <span data-name="title" style="word-wrap:break-word;font-weight:bold;">title</span>?</h2>
|
|
||||||
<span style="color: #A40000;" data-name="error"></span><br>
|
|
||||||
<form>
|
|
||||||
<button type="button" data-name="delete">Yes</button>
|
|
||||||
<button type="button" data-name="cancel">No</button>
|
|
||||||
</form>
|
|
||||||
</section>
|
|
||||||
</main>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
|
@ -178,6 +178,9 @@ def props_from_request(xml_request: Optional[ET.Element]
|
||||||
if resource_type.tag == make_clark("C:calendar"):
|
if resource_type.tag == make_clark("C:calendar"):
|
||||||
value = "VCALENDAR"
|
value = "VCALENDAR"
|
||||||
break
|
break
|
||||||
|
if resource_type.tag == make_clark("CS:subscribed"):
|
||||||
|
value = "VSUBSCRIBED"
|
||||||
|
break
|
||||||
if resource_type.tag == make_clark("CR:addressbook"):
|
if resource_type.tag == make_clark("CR:addressbook"):
|
||||||
value = "VADDRESSBOOK"
|
value = "VADDRESSBOOK"
|
||||||
break
|
break
|
||||||
|
|