Update dependencies
This commit is contained in:
parent
12d685fd6e
commit
45f52c5459
|
@ -19,6 +19,7 @@ Its original purpose was to serve as a demo and test for the KD2 WebDAV library,
|
||||||
* MarkDown live preview
|
* MarkDown live preview
|
||||||
* Preview of images, text, MarkDown and PDF
|
* Preview of images, text, MarkDown and PDF
|
||||||
* Editing of Office files using Collabora or OnlyOffice
|
* Editing of Office files using Collabora or OnlyOffice
|
||||||
|
* Download all files from a directory
|
||||||
* WebDAV class 1, 2, 3 support, support for Etags
|
* WebDAV class 1, 2, 3 support, support for Etags
|
||||||
* No database server is required (SQLite3 is used)
|
* No database server is required (SQLite3 is used)
|
||||||
* Multiple user accounts
|
* Multiple user accounts
|
||||||
|
|
|
@ -789,7 +789,7 @@ class Server
|
||||||
$uri = trim(rtrim($this->base_uri, '/') . '/' . ltrim($uri, '/'), '/');
|
$uri = trim(rtrim($this->base_uri, '/') . '/' . ltrim($uri, '/'), '/');
|
||||||
$path = '/' . str_replace('%2F', '/', rawurlencode($uri));
|
$path = '/' . str_replace('%2F', '/', rawurlencode($uri));
|
||||||
|
|
||||||
if (($item['DAV::resourcetype'] ?? null) == 'collection') {
|
if (($item['DAV::resourcetype'] ?? null) == 'collection' && $path != '/') {
|
||||||
$path .= '/';
|
$path .= '/';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -309,11 +309,12 @@ input[name=rename], input[name=paste_name] {
|
||||||
width: 0;
|
width: 0;
|
||||||
height: 0;
|
height: 0;
|
||||||
border: none;
|
border: none;
|
||||||
display: flex;
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.loading .bg::after {
|
.loading .bg::after, .spinner span::after {
|
||||||
display: block;
|
display: block;
|
||||||
content: " ";
|
content: " ";
|
||||||
width: 70px;
|
width: 70px;
|
||||||
|
@ -336,6 +337,17 @@ input[name=rename], input[name=paste_name] {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.spinner {
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner span::after {
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
.loading .bg, .dragging .bg, .dialog .bg {
|
.loading .bg, .dragging .bg, .dialog .bg {
|
||||||
backdrop-filter: blur(5px);
|
backdrop-filter: blur(5px);
|
||||||
background: rgba(0, 0, 0, 0.5);
|
background: rgba(0, 0, 0, 0.5);
|
||||||
|
@ -348,6 +360,11 @@ dialog {
|
||||||
transition: all .3s;
|
transition: all .3s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
progress {
|
||||||
|
height: 2em;
|
||||||
|
width: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes spin { to { transform: rotate(360deg); } }
|
@keyframes spin { to { transform: rotate(360deg); } }
|
||||||
|
|
||||||
@media screen and (max-width: 800px) {
|
@media screen and (max-width: 800px) {
|
||||||
|
|
124
www/webdav.js
124
www/webdav.js
|
@ -38,6 +38,7 @@ const WebDAVNavigator = (url, options) => {
|
||||||
<option value="date">${_('Sort by date')}</option>
|
<option value="date">${_('Sort by date')}</option>
|
||||||
<option value="size">${_('Sort by size')}</option>
|
<option value="size">${_('Sort by size')}</option>
|
||||||
</select>
|
</select>
|
||||||
|
<input type="button" class="download_all" value="${_('Download all files')}" />
|
||||||
</div>
|
</div>
|
||||||
<table>%table%</table>`;
|
<table>%table%</table>`;
|
||||||
|
|
||||||
|
@ -47,7 +48,7 @@ const WebDAVNavigator = (url, options) => {
|
||||||
<input class="uploadfile" type="button" value="${_('Upload file')}" />`;
|
<input class="uploadfile" type="button" value="${_('Upload file')}" />`;
|
||||||
|
|
||||||
const dir_row_tpl = `<tr data-permissions="%permissions%"><td class="thumb"><span class="icon dir"><b>%icon%</b></span></td><th colspan="2"><a href="%uri%">%name%</a></th><td>%modified%</td><td class="buttons"><div></div></td></tr>`;
|
const dir_row_tpl = `<tr data-permissions="%permissions%"><td class="thumb"><span class="icon dir"><b>%icon%</b></span></td><th colspan="2"><a href="%uri%">%name%</a></th><td>%modified%</td><td class="buttons"><div></div></td></tr>`;
|
||||||
const file_row_tpl = `<tr data-permissions="%permissions%" data-mime="%mime%"><td class="thumb"><span class="icon %icon%"><b>%icon%</b></span></td><th><a href="%uri%">%name%</a></th><td class="size">%size%</td><td>%modified%</td><td class="buttons"><div><a href="%uri%" download class="btn">${_('Download')}</a></div></td></tr>`;
|
const file_row_tpl = `<tr data-permissions="%permissions%" data-mime="%mime%" data-size="%size%"><td class="thumb"><span class="icon %icon%"><b>%icon%</b></span></td><th><a href="%uri%">%name%</a></th><td class="size">%size_bytes%</td><td>%modified%</td><td class="buttons"><div><a href="%uri%" download class="btn">${_('Download')}</a></div></td></tr>`;
|
||||||
|
|
||||||
const propfind_tpl = `<?xml version="1.0" encoding="UTF-8"?>
|
const propfind_tpl = `<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<D:propfind xmlns:D="DAV:" xmlns:oc="http://owncloud.org/ns">
|
<D:propfind xmlns:D="DAV:" xmlns:oc="http://owncloud.org/ns">
|
||||||
|
@ -97,17 +98,6 @@ const WebDAVNavigator = (url, options) => {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const get_url = async (url) => {
|
|
||||||
if (temp_object_url) {
|
|
||||||
window.URL.revokeObjectURL(temp_object_url);
|
|
||||||
}
|
|
||||||
|
|
||||||
return req('GET', url).then(r => r.blob()).then(blob => {
|
|
||||||
temp_object_url = window.URL.createObjectURL(blob);
|
|
||||||
return temp_object_url;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const req = (method, url, body, headers) => {
|
const req = (method, url, body, headers) => {
|
||||||
if (!headers) {
|
if (!headers) {
|
||||||
headers = {};
|
headers = {};
|
||||||
|
@ -120,6 +110,52 @@ const WebDAVNavigator = (url, options) => {
|
||||||
return fetch(url, {method, body, headers});
|
return fetch(url, {method, body, headers});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const xhr = (method, url, progress_callback) => {
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
current_xhr = xhr;
|
||||||
|
xhr.responseType = 'blob';
|
||||||
|
var p = new Promise((resolve, reject) => {
|
||||||
|
xhr.open(method, url);
|
||||||
|
xhr.onload = function () {
|
||||||
|
if (this.status >= 200 && this.status < 300) {
|
||||||
|
resolve(xhr.response);
|
||||||
|
} else {
|
||||||
|
reject({
|
||||||
|
status: this.status,
|
||||||
|
statusText: xhr.statusText
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xhr.onerror = function () {
|
||||||
|
reject({
|
||||||
|
status: this.status,
|
||||||
|
statusText: xhr.statusText
|
||||||
|
});
|
||||||
|
};
|
||||||
|
xhr.onprogress = progress_callback;
|
||||||
|
xhr.send();
|
||||||
|
});
|
||||||
|
return p;
|
||||||
|
};
|
||||||
|
|
||||||
|
const get_url = async (url) => {
|
||||||
|
var progress = (e) => {
|
||||||
|
var p = $('progress');
|
||||||
|
if (!p || e.loaded <= 0) return;
|
||||||
|
p.value = e.loaded;
|
||||||
|
$('.progress_bytes').innerHTML = formatBytes(e.loaded);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (temp_object_url) {
|
||||||
|
window.URL.revokeObjectURL(temp_object_url);
|
||||||
|
}
|
||||||
|
|
||||||
|
return await xhr('GET', url, progress).then(blob => {
|
||||||
|
temp_object_url = window.URL.createObjectURL(blob);
|
||||||
|
return temp_object_url;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const wopi_init = async () => {
|
const wopi_init = async () => {
|
||||||
if (!wopi_discovery_url) {
|
if (!wopi_discovery_url) {
|
||||||
return;
|
return;
|
||||||
|
@ -221,6 +257,17 @@ const WebDAVNavigator = (url, options) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const closeDialog = (e) => {
|
const closeDialog = (e) => {
|
||||||
|
if (!$('body').classList.contains('dialog')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current_xhr) {
|
||||||
|
current_xhr.abort();
|
||||||
|
current_xhr = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.onbeforeunload = null;
|
||||||
|
|
||||||
$('body').classList.remove('dialog');
|
$('body').classList.remove('dialog');
|
||||||
if (!$('dialog')) return;
|
if (!$('dialog')) return;
|
||||||
$('dialog').remove();
|
$('dialog').remove();
|
||||||
|
@ -228,16 +275,43 @@ const WebDAVNavigator = (url, options) => {
|
||||||
evt = null;
|
evt = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const download = async (name, url) => {
|
const download = async (name, size, url) => {
|
||||||
var url = await get_url(url);
|
window.onbeforeunload = () => {
|
||||||
|
if (current_xhr) {
|
||||||
|
current_xhr.abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
openDialog(`<p class="spinner"><span></span></p>
|
||||||
|
<h3>${html(name)}</h3>
|
||||||
|
<progress max="${size}"></progress>
|
||||||
|
<p><span class="progress_bytes"></span> / ${formatBytes(size)}</p>`, false);
|
||||||
|
|
||||||
|
await get_url(url);
|
||||||
const a = document.createElement('a');
|
const a = document.createElement('a');
|
||||||
a.style.display = 'none';
|
a.style.display = 'none';
|
||||||
a.href = url;
|
a.href = temp_object_url;
|
||||||
a.download = name;
|
a.download = name;
|
||||||
document.body.appendChild(a);
|
document.body.appendChild(a);
|
||||||
a.click();
|
a.click();
|
||||||
window.URL.revokeObjectURL(url);
|
window.URL.revokeObjectURL(temp_object_url);
|
||||||
a.remove();
|
a.remove();
|
||||||
|
|
||||||
|
closeDialog();
|
||||||
|
window.onbeforeunload = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const download_all = async () => {
|
||||||
|
for (var i = 0; i < items.length; i++) {
|
||||||
|
var item = items[i];
|
||||||
|
if (item.is_dir) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
await download(item.name, item.size, item.uri)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const preview = (type, url) => {
|
const preview = (type, url) => {
|
||||||
|
@ -354,7 +428,7 @@ const WebDAVNavigator = (url, options) => {
|
||||||
const buildListing = (uri, xml) => {
|
const buildListing = (uri, xml) => {
|
||||||
uri = normalizeURL(uri);
|
uri = normalizeURL(uri);
|
||||||
|
|
||||||
var items = [[], []];
|
items = [[], []];
|
||||||
var title = null;
|
var title = null;
|
||||||
var root_permissions = null;
|
var root_permissions = null;
|
||||||
|
|
||||||
|
@ -442,7 +516,7 @@ const WebDAVNavigator = (url, options) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
var row = item.is_dir ? dir_row_tpl : file_row_tpl;
|
var row = item.is_dir ? dir_row_tpl : file_row_tpl;
|
||||||
item.size = item.size !== null ? formatBytes(item.size).replace(/ /g, ' ') : null;
|
item.size_bytes = item.size !== null ? formatBytes(item.size).replace(/ /g, ' ') : null;
|
||||||
item.icon = item.is_dir ? '📁' : (item.uri.indexOf('.') > 0 ? item.uri.replace(/^.*\.(\w+)$/, '$1').toUpperCase() : '');
|
item.icon = item.is_dir ? '📁' : (item.uri.indexOf('.') > 0 ? item.uri.replace(/^.*\.(\w+)$/, '$1').toUpperCase() : '');
|
||||||
item.modified = item.modified !== null ? formatDate(item.modified) : null;
|
item.modified = item.modified !== null ? formatDate(item.modified) : null;
|
||||||
item.name = html(item.name);
|
item.name = html(item.name);
|
||||||
|
@ -460,6 +534,13 @@ const WebDAVNavigator = (url, options) => {
|
||||||
reloadListing();
|
reloadListing();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!items.length) {
|
||||||
|
$('.download_all').disabled = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$('.download_all').onclick = download_all;
|
||||||
|
}
|
||||||
|
|
||||||
if (!root_permissions || root_permissions.indexOf('CK') != -1) {
|
if (!root_permissions || root_permissions.indexOf('CK') != -1) {
|
||||||
$('.upload').insertAdjacentHTML('afterbegin', create_buttons);
|
$('.upload').insertAdjacentHTML('afterbegin', create_buttons);
|
||||||
|
|
||||||
|
@ -518,6 +599,7 @@ const WebDAVNavigator = (url, options) => {
|
||||||
var mime = !dir ? tr.getAttribute('data-mime') : 'dir';
|
var mime = !dir ? tr.getAttribute('data-mime') : 'dir';
|
||||||
var buttons = $$('td.buttons div');
|
var buttons = $$('td.buttons div');
|
||||||
var permissions = tr.getAttribute('data-permissions');
|
var permissions = tr.getAttribute('data-permissions');
|
||||||
|
var size = tr.getAttribute('data-size');
|
||||||
|
|
||||||
if (permissions == 'null') {
|
if (permissions == 'null') {
|
||||||
permissions = null;
|
permissions = null;
|
||||||
|
@ -541,7 +623,7 @@ const WebDAVNavigator = (url, options) => {
|
||||||
// This is to get around CORS when not on the same domain
|
// This is to get around CORS when not on the same domain
|
||||||
if (user && password && (a = tr.querySelector('a[download]'))) {
|
if (user && password && (a = tr.querySelector('a[download]'))) {
|
||||||
a.onclick = () => {
|
a.onclick = () => {
|
||||||
download(file_name, url);
|
download(file_name, size, url);
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -615,7 +697,7 @@ const WebDAVNavigator = (url, options) => {
|
||||||
$$('a').onclick = () => { wopi_open(file_url, view_url); return false; };
|
$$('a').onclick = () => { wopi_open(file_url, view_url); return false; };
|
||||||
}
|
}
|
||||||
else if (user && password && !dir) {
|
else if (user && password && !dir) {
|
||||||
$$('a').onclick = () => { download(file_name, file_url); return false; };
|
$$('a').onclick = () => { download(file_name, size, file_url); return false; };
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$$('a').download = file_name;
|
$$('a').download = file_name;
|
||||||
|
@ -670,6 +752,8 @@ const WebDAVNavigator = (url, options) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var items = [[], []];
|
||||||
|
var current_xhr = null;
|
||||||
var current_url = url;
|
var current_url = url;
|
||||||
var base_url = url;
|
var base_url = url;
|
||||||
const user = options.user || null;
|
const user = options.user || null;
|
||||||
|
|
Loading…
Reference in a new issue