summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxim Devaev <[email protected]>2021-08-01 21:25:26 +0300
committerMaxim Devaev <[email protected]>2021-08-01 21:25:26 +0300
commit5933cc0b09b4f37e7e5f714b23ab5993e6fc0b2c (patch)
treec8bbbc7edf6813dccd0e2e0d740b00d398af9b4e
parentf5c1908657489d496e786f0d6aa579d1b5500542 (diff)
upload image by url in web ui
-rw-r--r--web/kvm/index.html39
-rw-r--r--web/kvm/navbar-msd.pug32
-rw-r--r--web/share/js/kvm/msd.js152
-rw-r--r--web/share/js/tools.js11
4 files changed, 152 insertions, 82 deletions
diff --git a/web/kvm/index.html b/web/kvm/index.html
index f6302516..5402303b 100644
--- a/web/kvm/index.html
+++ b/web/kvm/index.html
@@ -324,7 +324,7 @@
<select disabled id="msd-image-selector"></select>
</td>
<td>
- <button disabled id="msd-remove-image">Remove</button>
+ <button disabled id="msd-remove-button">Remove</button>
</td>
</tr>
</table>
@@ -348,11 +348,10 @@
</div>
</div>
<hr>
- <input class="hidden" type="file" id="msd-select-new-image-file">
<div class="buttons buttons-row">
- <button class="row50" disabled id="msd-select-new-image-button">Select image to upload</button>
- <button class="row25" disabled id="msd-upload-new-image-button">Upload</button>
- <button class="row25" disabled id="msd-abort-uploading-button">Abort</button>
+ <button class="row50" disabled id="msd-select-new-button">Select image to upload</button>
+ <button class="row25" disabled id="msd-upload-new-button">Upload</button>
+ <button class="row25" disabled id="msd-abort-new-button">Abort</button>
</div>
<div class="hidden" id="msd-message-another-user-uploads">
<hr>
@@ -365,32 +364,38 @@
</table>
</div>
</div>
- <div class="hidden" id="msd-submenu-new-image">
+ <div class="hidden" id="msd-new-sub">
<hr>
<table class="kv">
<tr>
- <td>New image:</td>
- <td class="value" id="msd-new-image-name"></td>
+ <td>Specify a local file:</td>
+ <td>
+ <input type="file" id="msd-new-file">
+ </td>
</tr>
<tr>
- <td>Upload size:</td>
- <td class="value" id="msd-new-image-size"></td>
+ <td><b>Or</b> paste a URL:</td>
+ <td>
+ <input type="text" id="msd-new-url" style="width: 100%">
+ </td>
</tr>
</table>
- <div class="text">
- <div class="progress" id="msd-uploading-progress"><span class="progress-value" id="msd-uploading-progress-value"></span></div>
- </div>
+ </div>
+ <div class="hidden" id="msd-uploading-sub">
<hr>
<table class="kv">
<tr>
- <td class="value">Tip:</td>
- <td>To speed up uploading, close the Stream window.</td>
+ <td>New image:</td>
+ <td class="value" id="msd-uploading-name"></td>
</tr>
<tr>
- <td></td>
- <td>This will save network bandwidth.</td>
+ <td>Upload size:</td>
+ <td class="value" id="msd-uploading-size"></td>
</tr>
</table>
+ <div class="text">
+ <div class="progress" id="msd-uploading-progress"><span class="progress-value" id="msd-uploading-progress-value"></span></div>
+ </div>
</div>
<hr>
<div class="buttons buttons-row">
diff --git a/web/kvm/navbar-msd.pug b/web/kvm/navbar-msd.pug
index 33a56845..dd671f71 100644
--- a/web/kvm/navbar-msd.pug
+++ b/web/kvm/navbar-msd.pug
@@ -37,7 +37,7 @@ li(id="msd-dropdown" class="right feature-disabled")
tr
td Image:
td(width="100%") #[select(disabled id="msd-image-selector")]
- td #[button(disabled id="msd-remove-image") Remove]
+ td #[button(disabled id="msd-remove-button") Remove]
table(class="kv msd-multi-storage feature-disabled")
tr(class="msd-cdrom-emulation feature-disabled")
td Drive #[a(target="_blank" href="https://github.com/pikvm/pikvm/blob/master/pages/msd.md") mode]:
@@ -53,34 +53,34 @@ li(id="msd-dropdown" class="right feature-disabled")
div(id="msd-storage-progress" class="progress")
span(id="msd-storage-progress-value" class="progress-value")
hr
- input(type="file" id="msd-select-new-image-file" class="hidden")
div(class="buttons buttons-row")
- button(disabled id="msd-select-new-image-button" class="row50") Select image to upload
- button(disabled id="msd-upload-new-image-button" class="row25") Upload
- button(disabled id="msd-abort-uploading-button" class="row25") Abort
+ button(disabled id="msd-select-new-button" class="row50") Select image to upload
+ button(disabled id="msd-upload-new-button" class="row25") Upload
+ button(disabled id="msd-abort-new-button" class="row25") Abort
div(id="msd-message-another-user-uploads" class="hidden")
hr
+menu_message("info", "Another user uploads an image")
- div(id="msd-submenu-new-image" class="hidden")
+ div(id="msd-new-sub" class="hidden")
+ hr
+ table(class="kv")
+ tr
+ td Specify a local file:
+ td #[input(type="file" id="msd-new-file")]
+ tr
+ td #[b Or] paste a URL:
+ td #[input(type="text" id="msd-new-url" style="width: 100%")]
+ div(id="msd-uploading-sub" class="hidden")
hr
table(class="kv")
tr
td New image:
- td(id="msd-new-image-name" class="value")
+ td(id="msd-uploading-name" class="value")
tr
td Upload size:
- td(id="msd-new-image-size" class="value")
+ td(id="msd-uploading-size" class="value")
div(class="text")
div(id="msd-uploading-progress" class="progress")
span(id="msd-uploading-progress-value" class="progress-value")
- hr
- table(class="kv")
- tr
- td(class="value") Tip:
- td To speed up uploading, close the Stream window.
- tr
- td
- td This will save network bandwidth.
hr
div(class="buttons buttons-row")
button(disabled id="msd-connect-button" class="row50") Connect drive to Server
diff --git a/web/share/js/kvm/msd.js b/web/share/js/kvm/msd.js
index eb9cacd9..93551c31 100644
--- a/web/share/js/kvm/msd.js
+++ b/web/share/js/kvm/msd.js
@@ -33,22 +33,22 @@ export function Msd() {
/************************************************************************/
var __state = null;
- var __upload_http = null;
- var __image_file = null;
+ var __http = null;
var __init__ = function() {
$("msd-led").title = "Unknown state";
$("msd-image-selector").onchange = __selectImage;
- tools.el.setOnClick($("msd-remove-image"), __clickRemoveImageButton);
+ tools.el.setOnClick($("msd-remove-button"), __clickRemoveButton);
tools.radio.setOnClick("msd-mode-radio", __clickModeRadio);
- $("msd-select-new-image-file").onchange = __selectNewImageFile;
- tools.el.setOnClick($("msd-select-new-image-button"), () => $("msd-select-new-image-file").click());
+ tools.el.setOnClick($("msd-select-new-button"), __toggleSelectSub);
+ $("msd-new-file").onchange = __selectNewFile;
+ $("msd-new-url").oninput = __selectNewUrl;
- tools.el.setOnClick($("msd-upload-new-image-button"), __clickUploadNewImageButton);
- tools.el.setOnClick($("msd-abort-uploading-button"), __clickAbortUploadingButton);
+ tools.el.setOnClick($("msd-upload-new-button"), __clickUploadNewButton);
+ tools.el.setOnClick($("msd-abort-new-button"), __clickAbortNewButton);
tools.el.setOnClick($("msd-connect-button"), () => __clickConnectButton(true));
tools.el.setOnClick($("msd-disconnect-button"), () => __clickConnectButton(false));
@@ -65,11 +65,11 @@ export function Msd() {
var __selectImage = function() {
tools.el.setEnabled($("msd-image-selector"), false);
- tools.el.setEnabled($("msd-remove-image"), false);
+ tools.el.setEnabled($("msd-remove-button"), false);
__sendParam("image", $("msd-image-selector").value);
};
- var __clickRemoveImageButton = function() {
+ var __clickRemoveButton = function() {
let name = $("msd-image-selector").value;
wm.confirm(`Are you sure you want to remove the image<br><b>${name}</b> from Pi-KVM?`).then(function(ok) {
if (ok) {
@@ -98,30 +98,61 @@ export function Msd() {
});
};
- var __clickUploadNewImageButton = function() {
- __upload_http = new XMLHttpRequest();
- __upload_http.open("POST", `/api/msd/write?image=${encodeURIComponent(__image_file.name)}`, true);
- __upload_http.upload.timeout = 15000;
- __upload_http.onreadystatechange = __uploadStateChange;
- __upload_http.send(__image_file);
+ var __clickUploadNewButton = function() {
+ let file = tools.input.getFile($("msd-new-file"));
+ __http = new XMLHttpRequest();
+ if (file) {
+ __http.open("POST", `/api/msd/write?image=${encodeURIComponent(file.name)}`, true);
+ } else {
+ let url = $("msd-new-url").value;
+ __http.open("POST", `/api/msd/write_remote?url=${encodeURIComponent(url)}`, true);
+ }
+ __http.upload.timeout = 7 * 24 * 3600;
+ __http.onreadystatechange = __httpStateChange;
+ __http.send(file);
+ __applyState();
};
- var __uploadStateChange = function() {
- if (__upload_http.readyState === 4) {
- if (__upload_http.status !== 200) {
- wm.error("Can't upload image to the Mass Storage Drive:<br>", __upload_http.responseText);
+ var __httpStateChange = function() {
+ if (__http.readyState === 4) {
+ if (__http.status !== 200) {
+ wm.error("Can't upload image to the Mass Storage Drive:<br>", __http.responseText);
+ } else if ($("msd-new-url").value.length > 0) {
+ let msg = "";
+ try {
+ let end = __http.responseText.lastIndexOf("\r\n");
+ if (end < 0) {
+ console.log(1);
+ end = __http.responseText.length;
+ }
+ let begin = __http.responseText.lastIndexOf("\r\n", end - 2);
+ if (begin < 0) {
+ end = 0;
+ }
+ let result_str = __http.responseText.slice(begin, end);
+ let result = JSON.parse(result_str);
+ if (!result.ok) {
+ msg = `Can't upload image to the Mass Storage Drive:<br>${result_str}`;
+ }
+ } catch (err) {
+ msg = `Can't parse upload result:<br>${err}`;
+ }
+ if (msg.length > 0) {
+ wm.error(msg);
+ }
}
- $("msd-select-new-image-file").value = "";
- __image_file = null;
- __upload_http = null;
+ tools.hidden.setVisible($("msd-new-sub"), false);
+ $("msd-new-file").value = "";
+ $("msd-new-url").value = "";
+ __http = null;
__applyState();
}
};
- var __clickAbortUploadingButton = function() {
- __upload_http.onreadystatechange = null;
- __upload_http.abort();
- __upload_http = null;
+ var __clickAbortNewButton = function() {
+ __http.onreadystatechange = null;
+ __http.abort();
+ __http = null;
tools.progress.setValue($("msd-uploading-progress"), "Aborted", 0);
};
@@ -138,18 +169,6 @@ export function Msd() {
tools.el.setEnabled($(`msd-${connected ? "connect" : "disconnect"}-button`), false);
};
- var __selectNewImageFile = function() {
- let el_input = $("msd-select-new-image-file");
- let image_file = (el_input.files.length ? el_input.files[0] : null);
- if (image_file && image_file.size > __state.storage.size) {
- wm.error("New image is too big for your Mass Storage Drive.<br>Maximum:", tools.formatSize(__state.storage.size));
- el_input.value = "";
- image_file = null;
- }
- __image_file = image_file;
- __applyState();
- };
-
var __clickResetButton = function() {
wm.confirm("Are you sure you want to reset Mass Storage Drive?").then(function(ok) {
if (ok) {
@@ -166,6 +185,37 @@ export function Msd() {
});
};
+ var __toggleSelectSub = function() {
+ let el_sub = $("msd-new-sub");
+ let visible = tools.hidden.isVisible(el_sub);
+ if (visible) {
+ $("msd-new-file").value = "";
+ $("msd-new-url").value = "";
+ }
+ tools.hidden.setVisible(el_sub, !visible);
+ __applyState();
+ };
+
+ var __selectNewFile = function() {
+ let el_input = $("msd-new-file");
+ let file = tools.input.getFile($("msd-new-file"));
+ if (file) {
+ $("msd-new-url").value = "";
+ if (file.size > __state.storage.size) {
+ wm.error("New image is too big for your Mass Storage Drive.<br>Maximum:", tools.formatSize(__state.storage.size));
+ el_input.value = "";
+ }
+ }
+ __applyState();
+ };
+
+ var __selectNewUrl = function() {
+ if ($("msd-new-url").value.length > 0) {
+ $("msd-new-file").value = "";
+ }
+ __applyState();
+ };
+
var __applyState = function() {
__applyStateFeatures();
__applyStateStatus();
@@ -188,7 +238,7 @@ export function Msd() {
tools.el.setEnabled($("msd-image-selector"), (online && s.features.multi && !s.drive.connected && !s.busy));
__applyStateImageSelector();
- tools.el.setEnabled($("msd-remove-image"), (online && s.features.multi && s.drive.image && !s.drive.connected && !s.busy));
+ tools.el.setEnabled($("msd-remove-button"), (online && s.features.multi && s.drive.image && !s.drive.connected && !s.busy));
tools.radio.setEnabled("msd-mode-radio", (online && s.features.cdrom && !s.drive.connected && !s.busy));
tools.radio.setValue("msd-mode-radio", `${Number(online && s.features.cdrom && s.drive.cdrom)}`);
@@ -196,25 +246,29 @@ export function Msd() {
tools.el.setEnabled($("msd-connect-button"), (online && (!s.features.multi || s.drive.image) && !s.drive.connected && !s.busy));
tools.el.setEnabled($("msd-disconnect-button"), (online && s.drive.connected && !s.busy));
- tools.el.setEnabled($("msd-select-new-image-button"), (online && !s.drive.connected && !__upload_http && !s.busy));
- tools.el.setEnabled($("msd-upload-new-image-button"), (online && !s.drive.connected && __image_file && !s.busy));
- tools.el.setEnabled($("msd-abort-uploading-button"), (online && __upload_http));
+ tools.el.setEnabled($("msd-select-new-button"), (online && !s.drive.connected && !__http && !s.busy));
+ tools.el.setEnabled($("msd-upload-new-button"),
+ (online && !s.drive.connected && (tools.input.getFile($("msd-new-file")) || $("msd-new-url").value.length > 0) && !s.busy));
+ tools.el.setEnabled($("msd-abort-new-button"), (online && __http));
tools.el.setEnabled($("msd-reset-button"), (s && s.enabled && !s.busy));
- let uploading = (online ? (s.storage.uploading || __image_file) : null);
- tools.hidden.setVisible($("msd-submenu-new-image"), uploading);
- $("msd-new-image-name").innerHTML = (uploading ? uploading.name : "");
- $("msd-new-image-size").innerHTML = (uploading ? tools.formatSize(uploading.size) : "");
+ tools.el.setEnabled($("msd-new-file"), (online && !s.drive.connected && !__http && !s.busy));
+ tools.el.setEnabled($("msd-new-url"), (online && !s.drive.connected && !__http && !s.busy));
+
+ tools.hidden.setVisible($("msd-uploading-sub"), (online && s.storage.uploading));
+ $("msd-uploading-name").innerHTML = ((online && s.storage.uploading) ? s.storage.uploading.name : "");
+ $("msd-uploading-size").innerHTML = ((online && s.storage.uploading) ? tools.formatSize(s.storage.uploading.size) : "");
if (online) {
if (s.storage.uploading) {
let percent = Math.round(s.storage.uploading.written * 100 / s.storage.uploading.size);
tools.progress.setValue($("msd-uploading-progress"), `${percent}%`, percent);
- } else if (!__upload_http) {
+ } else if (!__http) {
tools.progress.setValue($("msd-uploading-progress"), "Waiting for upload (press UPLOAD button) ...", 0);
}
} else {
- $("msd-select-new-image-file").value = "";
+ $("msd-new-file").value = "";
+ $("msd-new-url").value = "";
tools.progress.setValue($("msd-uploading-progress"), "", 0);
}
};
@@ -245,7 +299,7 @@ export function Msd() {
tools.hidden.setVisible($("msd-message-out-of-storage"),
(online && s.features.multi && s.drive.image && !s.drive.image.in_storage));
tools.hidden.setVisible($("msd-message-another-user-uploads"),
- (online && s.storage.uploading && !__upload_http));
+ (online && s.storage.uploading && !__http));
};
var __applyStateStatus = function() {
diff --git a/web/share/js/tools.js b/web/share/js/tools.js
index b24864e2..10013727 100644
--- a/web/share/js/tools.js
+++ b/web/share/js/tools.js
@@ -211,11 +211,22 @@ export var tools = new function() {
};
};
+ self.input = new function() {
+ return {
+ "getFile": function(el) {
+ return (el.files.length ? el.files[0] : null);
+ },
+ };
+ };
+
self.hidden = new function() {
return {
"setVisible": function(el, visible) {
el.classList.toggle("hidden", !visible);
},
+ "isVisible": function(el) {
+ return !el.classList.contains("hidden");
+ },
};
};