upload image by url in web ui

This commit is contained in:
Maxim Devaev 2021-08-01 21:25:26 +03:00
parent f5c1908657
commit 5933cc0b09
4 changed files with 154 additions and 84 deletions

View File

@ -324,7 +324,7 @@
<select disabled id="msd-image-selector"></select> <select disabled id="msd-image-selector"></select>
</td> </td>
<td> <td>
<button disabled id="msd-remove-image">Remove</button> <button disabled id="msd-remove-button">Remove</button>
</td> </td>
</tr> </tr>
</table> </table>
@ -348,11 +348,10 @@
</div> </div>
</div> </div>
<hr> <hr>
<input class="hidden" type="file" id="msd-select-new-image-file">
<div class="buttons buttons-row"> <div class="buttons buttons-row">
<button class="row50" disabled id="msd-select-new-image-button">Select image to upload</button> <button class="row50" disabled id="msd-select-new-button">Select image to upload</button>
<button class="row25" disabled id="msd-upload-new-image-button">Upload</button> <button class="row25" disabled id="msd-upload-new-button">Upload</button>
<button class="row25" disabled id="msd-abort-uploading-button">Abort</button> <button class="row25" disabled id="msd-abort-new-button">Abort</button>
</div> </div>
<div class="hidden" id="msd-message-another-user-uploads"> <div class="hidden" id="msd-message-another-user-uploads">
<hr> <hr>
@ -365,32 +364,38 @@
</table> </table>
</div> </div>
</div> </div>
<div class="hidden" id="msd-submenu-new-image"> <div class="hidden" id="msd-new-sub">
<hr>
<table class="kv">
<tr>
<td>Specify a local file:</td>
<td>
<input type="file" id="msd-new-file">
</td>
</tr>
<tr>
<td><b>Or</b> paste a URL:</td>
<td>
<input type="text" id="msd-new-url" style="width: 100%">
</td>
</tr>
</table>
</div>
<div class="hidden" id="msd-uploading-sub">
<hr> <hr>
<table class="kv"> <table class="kv">
<tr> <tr>
<td>New image:</td> <td>New image:</td>
<td class="value" id="msd-new-image-name"></td> <td class="value" id="msd-uploading-name"></td>
</tr> </tr>
<tr> <tr>
<td>Upload size:</td> <td>Upload size:</td>
<td class="value" id="msd-new-image-size"></td> <td class="value" id="msd-uploading-size"></td>
</tr> </tr>
</table> </table>
<div class="text"> <div class="text">
<div class="progress" id="msd-uploading-progress"><span class="progress-value" id="msd-uploading-progress-value"></span></div> <div class="progress" id="msd-uploading-progress"><span class="progress-value" id="msd-uploading-progress-value"></span></div>
</div> </div>
<hr>
<table class="kv">
<tr>
<td class="value">Tip:</td>
<td>To speed up uploading, close the Stream window.</td>
</tr>
<tr>
<td></td>
<td>This will save network bandwidth.</td>
</tr>
</table>
</div> </div>
<hr> <hr>
<div class="buttons buttons-row"> <div class="buttons buttons-row">

View File

@ -37,7 +37,7 @@ li(id="msd-dropdown" class="right feature-disabled")
tr tr
td Image: td Image:
td(width="100%") #[select(disabled id="msd-image-selector")] 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") table(class="kv msd-multi-storage feature-disabled")
tr(class="msd-cdrom-emulation 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]: 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") div(id="msd-storage-progress" class="progress")
span(id="msd-storage-progress-value" class="progress-value") span(id="msd-storage-progress-value" class="progress-value")
hr hr
input(type="file" id="msd-select-new-image-file" class="hidden")
div(class="buttons buttons-row") div(class="buttons buttons-row")
button(disabled id="msd-select-new-image-button" class="row50") Select image to upload button(disabled id="msd-select-new-button" class="row50") Select image to upload
button(disabled id="msd-upload-new-image-button" class="row25") Upload button(disabled id="msd-upload-new-button" class="row25") Upload
button(disabled id="msd-abort-uploading-button" class="row25") Abort button(disabled id="msd-abort-new-button" class="row25") Abort
div(id="msd-message-another-user-uploads" class="hidden") div(id="msd-message-another-user-uploads" class="hidden")
hr hr
+menu_message("info", "Another user uploads an image") +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 hr
table(class="kv") table(class="kv")
tr tr
td New image: td New image:
td(id="msd-new-image-name" class="value") td(id="msd-uploading-name" class="value")
tr tr
td Upload size: td Upload size:
td(id="msd-new-image-size" class="value") td(id="msd-uploading-size" class="value")
div(class="text") div(class="text")
div(id="msd-uploading-progress" class="progress") div(id="msd-uploading-progress" class="progress")
span(id="msd-uploading-progress-value" class="progress-value") 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 hr
div(class="buttons buttons-row") div(class="buttons buttons-row")
button(disabled id="msd-connect-button" class="row50") Connect drive to Server button(disabled id="msd-connect-button" class="row50") Connect drive to Server

View File

@ -33,22 +33,22 @@ export function Msd() {
/************************************************************************/ /************************************************************************/
var __state = null; var __state = null;
var __upload_http = null; var __http = null;
var __image_file = null;
var __init__ = function() { var __init__ = function() {
$("msd-led").title = "Unknown state"; $("msd-led").title = "Unknown state";
$("msd-image-selector").onchange = __selectImage; $("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); tools.radio.setOnClick("msd-mode-radio", __clickModeRadio);
$("msd-select-new-image-file").onchange = __selectNewImageFile; tools.el.setOnClick($("msd-select-new-button"), __toggleSelectSub);
tools.el.setOnClick($("msd-select-new-image-button"), () => $("msd-select-new-image-file").click()); $("msd-new-file").onchange = __selectNewFile;
$("msd-new-url").oninput = __selectNewUrl;
tools.el.setOnClick($("msd-upload-new-image-button"), __clickUploadNewImageButton); tools.el.setOnClick($("msd-upload-new-button"), __clickUploadNewButton);
tools.el.setOnClick($("msd-abort-uploading-button"), __clickAbortUploadingButton); tools.el.setOnClick($("msd-abort-new-button"), __clickAbortNewButton);
tools.el.setOnClick($("msd-connect-button"), () => __clickConnectButton(true)); tools.el.setOnClick($("msd-connect-button"), () => __clickConnectButton(true));
tools.el.setOnClick($("msd-disconnect-button"), () => __clickConnectButton(false)); tools.el.setOnClick($("msd-disconnect-button"), () => __clickConnectButton(false));
@ -65,11 +65,11 @@ export function Msd() {
var __selectImage = function() { var __selectImage = function() {
tools.el.setEnabled($("msd-image-selector"), false); 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); __sendParam("image", $("msd-image-selector").value);
}; };
var __clickRemoveImageButton = function() { var __clickRemoveButton = function() {
let name = $("msd-image-selector").value; 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) { wm.confirm(`Are you sure you want to remove the image<br><b>${name}</b> from Pi-KVM?`).then(function(ok) {
if (ok) { if (ok) {
@ -98,30 +98,61 @@ export function Msd() {
}); });
}; };
var __clickUploadNewImageButton = function() { var __clickUploadNewButton = function() {
__upload_http = new XMLHttpRequest(); let file = tools.input.getFile($("msd-new-file"));
__upload_http.open("POST", `/api/msd/write?image=${encodeURIComponent(__image_file.name)}`, true); __http = new XMLHttpRequest();
__upload_http.upload.timeout = 15000; if (file) {
__upload_http.onreadystatechange = __uploadStateChange; __http.open("POST", `/api/msd/write?image=${encodeURIComponent(file.name)}`, true);
__upload_http.send(__image_file); } 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() { var __httpStateChange = function() {
if (__upload_http.readyState === 4) { if (__http.readyState === 4) {
if (__upload_http.status !== 200) { if (__http.status !== 200) {
wm.error("Can't upload image to the Mass Storage Drive:<br>", __upload_http.responseText); 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 = ""; tools.hidden.setVisible($("msd-new-sub"), false);
__image_file = null; $("msd-new-file").value = "";
__upload_http = null; $("msd-new-url").value = "";
__http = null;
__applyState(); __applyState();
} }
}; };
var __clickAbortUploadingButton = function() { var __clickAbortNewButton = function() {
__upload_http.onreadystatechange = null; __http.onreadystatechange = null;
__upload_http.abort(); __http.abort();
__upload_http = null; __http = null;
tools.progress.setValue($("msd-uploading-progress"), "Aborted", 0); tools.progress.setValue($("msd-uploading-progress"), "Aborted", 0);
}; };
@ -138,18 +169,6 @@ export function Msd() {
tools.el.setEnabled($(`msd-${connected ? "connect" : "disconnect"}-button`), false); 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() { var __clickResetButton = function() {
wm.confirm("Are you sure you want to reset Mass Storage Drive?").then(function(ok) { wm.confirm("Are you sure you want to reset Mass Storage Drive?").then(function(ok) {
if (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() { var __applyState = function() {
__applyStateFeatures(); __applyStateFeatures();
__applyStateStatus(); __applyStateStatus();
@ -188,7 +238,7 @@ export function Msd() {
tools.el.setEnabled($("msd-image-selector"), (online && s.features.multi && !s.drive.connected && !s.busy)); tools.el.setEnabled($("msd-image-selector"), (online && s.features.multi && !s.drive.connected && !s.busy));
__applyStateImageSelector(); __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.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)}`); 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-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-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-select-new-button"), (online && !s.drive.connected && !__http && !s.busy));
tools.el.setEnabled($("msd-upload-new-image-button"), (online && !s.drive.connected && __image_file && !s.busy)); tools.el.setEnabled($("msd-upload-new-button"),
tools.el.setEnabled($("msd-abort-uploading-button"), (online && __upload_http)); (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)); tools.el.setEnabled($("msd-reset-button"), (s && s.enabled && !s.busy));
let uploading = (online ? (s.storage.uploading || __image_file) : null); tools.el.setEnabled($("msd-new-file"), (online && !s.drive.connected && !__http && !s.busy));
tools.hidden.setVisible($("msd-submenu-new-image"), uploading); tools.el.setEnabled($("msd-new-url"), (online && !s.drive.connected && !__http && !s.busy));
$("msd-new-image-name").innerHTML = (uploading ? uploading.name : "");
$("msd-new-image-size").innerHTML = (uploading ? tools.formatSize(uploading.size) : ""); 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 (online) {
if (s.storage.uploading) { if (s.storage.uploading) {
let percent = Math.round(s.storage.uploading.written * 100 / s.storage.uploading.size); let percent = Math.round(s.storage.uploading.written * 100 / s.storage.uploading.size);
tools.progress.setValue($("msd-uploading-progress"), `${percent}%`, percent); 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); tools.progress.setValue($("msd-uploading-progress"), "Waiting for upload (press UPLOAD button) ...", 0);
} }
} else { } else {
$("msd-select-new-image-file").value = ""; $("msd-new-file").value = "";
$("msd-new-url").value = "";
tools.progress.setValue($("msd-uploading-progress"), "", 0); tools.progress.setValue($("msd-uploading-progress"), "", 0);
} }
}; };
@ -245,7 +299,7 @@ export function Msd() {
tools.hidden.setVisible($("msd-message-out-of-storage"), tools.hidden.setVisible($("msd-message-out-of-storage"),
(online && s.features.multi && s.drive.image && !s.drive.image.in_storage)); (online && s.features.multi && s.drive.image && !s.drive.image.in_storage));
tools.hidden.setVisible($("msd-message-another-user-uploads"), tools.hidden.setVisible($("msd-message-another-user-uploads"),
(online && s.storage.uploading && !__upload_http)); (online && s.storage.uploading && !__http));
}; };
var __applyStateStatus = function() { var __applyStateStatus = function() {

View File

@ -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() { self.hidden = new function() {
return { return {
"setVisible": function(el, visible) { "setVisible": function(el, visible) {
el.classList.toggle("hidden", !visible); el.classList.toggle("hidden", !visible);
}, },
"isVisible": function(el) {
return !el.classList.contains("hidden");
},
}; };
}; };