Tweak dropzone config and introduce dedicated Upload page (#1040)

- Introduce a dedicated Upload page and move the upload form there
- Style the utility hyperlinks on the index page with icons and bold text
- Display the cancel / dismiss downloads link, and tweak the link text to make more sense. Note: Cancelled downloads won't remove the partially uploaded file.
- Hide image preview thumbnails. Not relevant to our usecase, and mess up the layout when it happens.
- Turn on chunk retries and tweaks chunk size to be a full MiB (probably won't make a big difference)
This commit is contained in:
Daniel Markstedt 2022-12-19 17:21:01 -08:00 committed by GitHub
parent 4f13b0d795
commit 6b6a303986
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 149 additions and 83 deletions

View File

@ -140,6 +140,11 @@ select {
.dropzone {
display: flex;
flex-wrap: wrap;
align-items: center;
}
.dropzone label {
padding: 0 0.5rem;
}
.dropzone p,
@ -765,6 +770,27 @@ section#files p {
}
}
/*
------------------------------------------------------------------------------
Index > Section: Upload
------------------------------------------------------------------------------
*/
section#upload {
margin: 1rem 0;
}
section#upload a {
margin: auto;
display: block;
padding: 0.25rem 0 0.25rem 2rem;
background: url("icons/upload-in-progress.svg") no-repeat left center;
font-weight: bold;
}
section#upload a p {
margin: 0;
}
/*
------------------------------------------------------------------------------
Index > Section: Attach peripheral devices
@ -804,6 +830,27 @@ section#create-image > p a {
margin-top: 1rem;
}
/*
------------------------------------------------------------------------------
Index > Section: Create drive
------------------------------------------------------------------------------
*/
section#create-drive {
margin: 1rem 0;
}
section#create-drive a {
margin: auto;
display: block;
padding: 0.25rem 0 0.25rem 2rem;
background: url("icons/device-other.svg") no-repeat left center;
font-weight: bold;
}
section#create-drive a p {
margin: 0;
}
/*
------------------------------------------------------------------------------
Index > Section: Logging
@ -842,7 +889,7 @@ section#manual {
section#manual a {
margin: auto;
display: block;
padding: 0 0 0 2rem;
padding: 0.25rem 0 0.25rem 2rem;
background: url("icons/manual.svg") no-repeat left center;
font-weight: bold;
}

View File

@ -353,6 +353,35 @@
<hr/>
<section id="download-url">
<details>
<summary class="heading">
{{ _("Transfer Files to the PiSCSI") }}
</summary>
<ul>
<li>{{ _("Disk Images") }} = {{ env["image_dir"] }}</li>
<li>{{ _("Shared Files") }} = {{ FILE_SERVER_DIR }}</li>
<li>{{ _("To access shared files remotely, you may have to install one of the file servers first.") }}</li>
</ul>
</details>
<form action="/files/download_url" method="post">
<label for="download_url">{{ _("Download file from URL:") }}</label>
<input name="url" id="download_url" required="" type="url">
<label for="disk_images">{{ _("Disk Images") }}</label>
<input type="radio" name="destination" id="disk_images" value="disk_images" checked="checked">
<label for="shared_files">{{ _("Shared Files") }}</label>
<input type="radio" name="destination" id="shared_files" value="shared_files">
<input type="submit" value="{{ _("Download") }}" onclick="processNotify('{{ _("Downloading File...") }}')">
</form>
</section>
<section id="upload">
<a href="/upload" target="_blank"><p>{{ _("Upload Files (new tab)") }}</p></a>
</section>
<hr/>
<section id="attach-devices">
<details>
<summary class="heading">
@ -453,84 +482,6 @@
<hr/>
<section id="upload">
<details>
<summary class="heading">
{{ _("Upload File from Local Computer") }}
</summary>
<ul>
<li>{{ _("The largest file size accepted in this form is %(max_file_size)s MiB. Use other file transfer means for larger files.", max_file_size=max_file_size) }}</li>
<li>{{ _("File uploads will progress only if you stay on this page. If you navigate away before the transfer is completed, you will end up with an incomplete file.") }}</li>
<li>{{ _("To access shared files remotely, you may have to install one of the file servers first.") }}</li>
</ul>
</details>
<form name="dropper" action="/files/upload" method="post" class="dropzone dz-clickable" enctype="multipart/form-data" id="dropper">
<p>
<label for="upload_destination">{{ _("Target directory:") }}</label>
<select name="destination" id="upload_destination">
<option value="images">{{ _("Disk Images") }} - {{ env["image_dir"] }}</option>
<option value="file_server">{{ _("File Server") }} - {{ FILE_SERVER_DIR }}</option>
</select>
</p>
</form>
<script type="application/javascript">
Dropzone.options.dropper = {
paramName: 'file',
chunking: true,
forceChunking: true,
url: '/files/upload',
maxFilesize: {{ max_file_size }}, // MiB
chunkSize: 1000000, // bytes
dictDefaultMessage: "{{ _("Drop files here to upload") }}",
dictFallbackMessage: "{{ _("Your browser does not support drag'n'drop file uploads.") }}",
dictFallbackText: "{{ _("Please use the fallback form below to upload your files like in the olden days.") }}",
dictFileTooBig: "{{ _("File is too big: {{filesize}}MiB. Max filesize: {{maxFilesize}}MiB.") }}",
dictInvalidFileType: "{{ _("You can't upload files of this type.") }}",
dictResponseError: "{{ _("Server responded with code: {{statusCode}}") }}",
dictCancelUpload:" {{ _("Cancel upload") }}",
dictUploadCanceled: "{{ _("Upload canceled.") }}",
dictCancelUploadConfirmation: "{{ _("Are you sure you want to cancel this upload?") }}",
dictRemoveFile: "{{ _("Remove file") }}",
dictMaxFilesExceeded: "{{ _("You can not upload any more files.") }}",
dictFileSizeUnits: {
tb: "{{ _("TiB") }}",
gb: "{{ _("GiB") }}",
mb: "{{ _("MiB") }}",
kb: "{{ _("KiB") }}",
b: "{{ _("B") }}"
}
}
</script>
</section>
<hr/>
<section id="download-url">
<details>
<summary class="heading">
{{ _("Download File from the Web") }}
</summary>
<ul>
<li>{{ _("To access shared files remotely, you may have to install one of the file servers first.") }}</li>
</ul>
</details>
<form action="/files/download_url" method="post">
<label for="download_destination">{{ _("Target directory:") }}</label>
<select name="destination" id="download_destination">
<option value="images">{{ _("Disk Images") }} - {{ env["image_dir"] }}</option>
<option value="file_server">{{ _("File Server") }} - {{ FILE_SERVER_DIR }}</option>
</select>
<label for="download_url">{{ _("URL:") }}</label>
<input name="url" id="download_url" required="" type="url">
<input type="submit" value="{{ _("Download") }}" onclick="processNotify('{{ _("Downloading File...") }}')">
</form>
</section>
<hr/>
<section id="download-to-iso">
<details>
<summary class="heading">
@ -544,7 +495,7 @@
</details>
<form action="/files/download_to_iso" method="post">
<label for="iso_url">{{ _("URL:") }}</label>
<label for="iso_url">{{ _("Download file from URL:") }}</label>
<input name="url" id="iso_url" required="" type="url">
<label for="iso_type">{{ _("Type:") }}</label>
<select name="type" id="iso_type">
@ -636,8 +587,10 @@
</select>
<input type="submit" value="{{ _("Create") }}">
</form>
</section>
<p><a href="/drive/list">{{ _("Create a named disk image that mimics real-life drives") }}</a></p>
<section id="create-drive">
<a href="/drive/list"><p>{{ _("Create Disk Image With Properties") }}</p></a>
</section>
<hr/>

View File

@ -0,0 +1,54 @@
{% extends "base.html" %}
{% block content %}
<h2>{{ _("Upload File from Local Computer") }}</h2>
<ul>
<li>{{ _("The largest file size accepted in this form is %(max_file_size)s MiB. Use other file transfer means for larger files.", max_file_size=max_file_size) }}</li>
<li>{{ _("You have to manually clean up partially uploaded files, as a result of cancelling the upload or closing this page.") }}</li>
<li>{{ _("Disk Images") }} = {{ env["image_dir"] }}</li>
<li>{{ _("Shared Files") }} = {{ FILE_SERVER_DIR }}</li>
</ul>
<h3>{{ _("Destination") }}</h3>
<form name="dropper" action="/files/upload" method="post" class="dropzone dz-clickable" enctype="multipart/form-data" id="dropper">
<label for="disk_images">{{ _("Disk Images") }}</label>
<input type="radio" name="destination" id="disk_images" value="disk_images" checked="checked">
<label for="shared_files">{{ _("Shared Files") }}</label>
<input type="radio" name="destination" id="shared_files" value="shared_files">
</form>
<script type="application/javascript">
Dropzone.options.dropper = {
paramName: 'file',
url: '/files/upload',
maxFilesize: {{ max_file_size }}, // max allowed file size in MiB
chunking: true,
forceChunking: true,
parallelChunkUploads: false,
chunkSize: 1048576, // 1 MiB
retryChunks: true,
retryChunksLimit: 3,
createImageThumbnails: false,
addRemoveLinks: true,
dictDefaultMessage: "{{ _("Drop files here to upload") }}",
dictFallbackMessage: "{{ _("Your browser does not support drag'n'drop file uploads.") }}",
dictFallbackText: "{{ _("Please use the fallback form below to upload your files like in the olden days.") }}",
dictFileTooBig: "{{ _("File is too big: {{filesize}}MiB. Max filesize: {{maxFilesize}}MiB.") }}",
dictInvalidFileType: "{{ _("You can't upload files of this type.") }}",
dictResponseError: "{{ _("Server responded with code: {{statusCode}}") }}",
dictCancelUpload:" {{ _("Cancel upload") }}",
dictUploadCanceled: "{{ _("Upload canceled.") }}",
dictCancelUploadConfirmation: "{{ _("Are you sure you want to cancel this upload?") }}",
dictRemoveFile: "{{ _("Dismiss") }}",
dictMaxFilesExceeded: "{{ _("You can not upload any more files.") }}",
dictFileSizeUnits: {
tb: "{{ _("TiB") }}",
gb: "{{ _("GiB") }}",
mb: "{{ _("MiB") }}",
kb: "{{ _("KiB") }}",
b: "{{ _("B") }}"
}
}
</script>
{% endblock content %}

View File

@ -276,7 +276,6 @@ def index():
reserved_scsi_ids=reserved_scsi_ids,
image_suffixes_to_create=image_suffixes_to_create,
valid_image_suffixes=valid_image_suffixes,
max_file_size=int(int(MAX_FILE_SIZE) / 1024 / 1024),
drive_properties=format_drive_properties(APP.config["PISCSI_DRIVE_PROPERTIES"]),
RESERVATIONS=RESERVATIONS,
CFG_DIR=CFG_DIR,
@ -311,6 +310,19 @@ def drive_list():
)
@APP.route("/upload", methods=["GET"])
def upload_page():
"""
Sets up the data structures and kicks off the rendering of the file uploading page
"""
return response(
template="upload.html",
max_file_size=int(int(MAX_FILE_SIZE) / 1024 / 1024),
FILE_SERVER_DIR=FILE_SERVER_DIR,
)
@APP.route("/login", methods=["POST"])
def login():
"""
@ -943,7 +955,7 @@ def download_file():
"""
destination = request.form.get("destination")
url = request.form.get("url")
if destination == "file_server":
if destination == "shared_files":
destination_dir = FILE_SERVER_DIR
else:
server_info = piscsi_cmd.get_server_info()