aboutsummaryrefslogtreecommitdiff
path: root/templates
diff options
context:
space:
mode:
authorB Stack <bgstack15@gmail.com>2021-01-07 20:52:38 -0500
committerB Stack <bgstack15@gmail.com>2021-01-07 20:56:10 -0500
commitbadcb48cd279f0e2a0ed7eae2661171f2411e647 (patch)
tree920d3319404ece4811fd7f8bea5ef96ba52021e1 /templates
downloadfuss-badcb48cd279f0e2a0ed7eae2661171f2411e647.tar.gz
fuss-badcb48cd279f0e2a0ed7eae2661171f2411e647.tar.bz2
fuss-badcb48cd279f0e2a0ed7eae2661171f2411e647.zip
initial commit
Diffstat (limited to 'templates')
-rw-r--r--templates/index.html.j283
-rw-r--r--templates/upload.html.j253
-rw-r--r--templates/upload.js.j2139
3 files changed, 275 insertions, 0 deletions
diff --git a/templates/index.html.j2 b/templates/index.html.j2
new file mode 100644
index 0000000..75f97ee
--- /dev/null
+++ b/templates/index.html.j2
@@ -0,0 +1,83 @@
+{% set prefix_s = prefix | trim('/') ~ '/' %}{% set s_prefix_s = ( '/' ~ prefix | trim('/') ~ '/' ) | replace ("//","/") %}{% set ulp_s = ulp | trim('/') ~ '/' %}{% set server_prefix = ( server | replace("//","##") ~ '/' ~ prefix ~ '/' ) | replace("///","/") | replace("//", "/") | replace("##","//") %}{% set prefix_ulp = ( '/' ~ prefix ~ '/' ~ ulp ~ '/' ) | replace("///","/") | replace("//", "/") %}{% set server_prefix_ulp = ( server | replace("//","##") ~ '/' ~ prefix ~ '/' ~ ulp ~ '/' ) | replace("///","/") | replace("//", "/") | replace("##","//") %}<!DOCTYPE html>
+<html>
+<head>
+<title>FUSS: File Upload and Storage Service</title>
+<link rel="stylesheet" href="{{ s_prefix_s }}static/index.css"/>
+<meta name="viewport" content="width=device-width, initial-scale=1">
+</head>
+<!--
+server = "{{ server }}"
+prefix = "{{ prefix }}"
+ulp = "{{ ulp }}"
+file_count = "{{ file_count }}"
+max_size = "{{ max_size }}"
+mimetype_blacklist = "{{ mimetype_blacklist }}"
+meta = "{{ meta }}"
+meta_visible = "{{ meta_visible }}"
+meta_headers = "{{ meta_headers }}"
+icons = "{{ icons }}"
+-->
+<body>
+<h1>FUSS</h1>
+<input id="intro" class="toggle" type="checkbox" checked><label for="intro" class="lbl-toggle" tabindex="0">Introduction</label>
+<div id="intro" class="content">
+<div class="content-inner">
+<a href="{{ server_prefix }}">FUSS</a> is a simple file upload and storage web app.
+Features include:
+<ul>
+<li>Maximum upload size</li>
+<li>Accept original file modification timestamp</li>
+<li>Filter out mimetypes</li>
+<li>Handle duplicate files gracefully</li>
+<li>Handle up to so many dissimilar files with same name</li>
+<li>Drag and drop upload</li>
+<li>Display mimetype icons</li>
+</ul>
+<p style="font-size: 66%;"><a href="https://gitlab.com/bgstack15/fuss/">source</a> (GPL-3.0)</p>
+</div> <!-- content-inner -->
+</div> <!-- content -->
+<input id="use" class="toggle" type="checkbox" checked><label for="use" class="lbl-toggle" tabindex="0">How to use</label>
+<div id="use" class="content">
+<div class="content-inner">
+{% if ulp != "" %}Visit the upload form at <a href="{{ prefix_ulp }}">{{ ulp_s }}</a>.
+Or f{% else %}F{% endif %}rom the command line:
+<pre>
+curl -F 'file=@/path/to/file' {{ server_prefix_ulp }}
+</pre>
+To save the original last modified timestamp from the command line, use script <a href="{{ s_prefix_s }}fuss-upload">fuss-upload</a>.
+<pre>
+./fuss-upload /path/to/file {{ server_prefix_ulp }}
+</pre>
+</div> <!-- content-inner -->
+</div> <!-- content -->
+<input id="stats" class="toggle" type="checkbox" checked><label for="stats" class="lbl-toggle" tabindex="0">Current status for this instance</label>
+<div id="stats" class="content">
+<div class="content-inner">
+<ul>
+<li>Max file size: {{ max_size }}</li>
+<li>Files stored: <a href="{{ s_prefix_s }}dump_files/">{{ file_count }}</a>
+(<a href="{{ s_prefix_s }}dump_files/json">json</a>
+<a href="{{ s_prefix_s }}dump_files/html">html</a>
+<a href="{{ s_prefix_s }}dump_files/html-long">html details</a>)
+</li>
+<li>Mimetype blacklist
+{% if mimetype_blacklist %}
+<ul>{% endif %}
+{% for m in mimetype_blacklist %}<li>{{ m }}</li>{% endfor %}
+{% if mimetype_blacklist %}</ul>{% endif %}
+<li>Max duplicate filenames: {{ max_dupe }}</li>
+<li>Metadata{% if not meta %} is disabled{% endif %}
+{% if meta %}
+<ul>
+<li>User queriable: {% if meta_visible %}yes{% else %}no{% endif %}</li>
+<li>Add to headers: {% if meta_visible and (meta_headers|length) > 0 %}yes{% else %}no{% endif %}</li>
+<li>Mimetype icons: {% if icons %}yes{% else %}no{% endif %}</li>
+{% endif %}
+</ul> <!-- metadata sublist -->
+</ul>
+<p style="font-size: 66%;"><a href="{{ s_prefix_s }}dump_config/">dump config</a> (<a href="{{ s_prefix_s }}dump_config/json">json</a>)
+</div> <!-- content-inner -->
+</div> <!-- content -->
+<script src="{{ s_prefix_s }}static/index.js"></script>
+</body>
+</html>
diff --git a/templates/upload.html.j2 b/templates/upload.html.j2
new file mode 100644
index 0000000..35673b7
--- /dev/null
+++ b/templates/upload.html.j2
@@ -0,0 +1,53 @@
+{% set prefix_s = prefix | trim('/') ~ '/' %}{% set s_prefix_s = ( '/' ~ prefix | trim('/') ~ '/' ) | replace ("//","/") %}{% set ulp_s = ulp | trim('/') ~ '/' %}{% set server_prefix = ( server | replace("//","##") ~ '/' ~ prefix ~ '/' ) | replace("///","/") | replace("//", "/") | replace("##","//") %}{% set prefix_ulp = ( '/' ~ prefix ~ '/' ~ ulp ~ '/' ) | replace("///","/") | replace("//", "/") %}{% set server_prefix_ulp = ( server | replace("//","##") ~ '/' ~ prefix ~ '/' ~ ulp ~ '/' ) | replace("///","/") | replace("//", "/") | replace("##","//") %}<!DOCTYPE html>
+<html>
+ <head>
+ <title>
+ FUSS upload page
+ </title>
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+
+ <!-- (A) CSS + JS -->
+ <link rel="stylesheet" href="{{ s_prefix_s }}static/upload.css"/>
+ <link rel="stylesheet" href="{{ s_prefix_s }}static/index.css"/>
+ <script src="{{ s_prefix_s }}template/upload.js"></script>
+ <script>
+ function lastmod(elem){
+ tc = "lastmod=";
+ for (var x=0; x < elem.files.length; x++) {
+ tc += `${Math.trunc(elem.files[x].lastModified / 1000)},`
+ }
+ document.cookie = tc;
+ // For a single file:
+ //document.cookie = `lastmod=${elem.files[0].lastModified}`
+ }
+ </script>
+ </head>
+<!--
+server = "{{ server }}"
+prefix = "{{ prefix }}"
+ulp = "{{ ulp }}"
+-->
+ <body>
+ <!-- (B) FILE DROP ZONE -->
+ <div id="upzone">
+ Drop Files Here
+ </div>
+
+ <!-- (D) FALLBACK -->
+ <form id="upform" action="{{ server_prefix_ulp }}" method="post" enctype="multipart/form-data">
+ <br/>
+ <input type="file" name="file" multiple accept="*" oninput="lastmod(this);" required>
+ <input type="submit" value="Upload File">
+ </form>
+
+ <!-- (C) UPLOAD STATUS -->
+ <div id="hiddenfirst">
+ <input id="upstatus" class="toggle" type="checkbox" checked><label for="upstatus" class="lbl-toggle" tabindex="0">Upload status</label>
+ <div id="upstatus" class="content">
+ <div class="content-inner" id="upstat">
+ </div> <!-- content-inner -->
+ </div> <!-- content -->
+ </div>
+ <script src="{{ s_prefix_s }}static/index.js"></script>
+ </body>
+</html>
diff --git a/templates/upload.js.j2 b/templates/upload.js.j2
new file mode 100644
index 0000000..28fe892
--- /dev/null
+++ b/templates/upload.js.j2
@@ -0,0 +1,139 @@
+{% set prefix_s = prefix | trim('/') ~ '/' %}{% set s_prefix_s = ( '/' ~ prefix | trim('/') ~ '/' ) | replace ("//","/") %}{% set ulp_s = ulp | trim('/') ~ '/' %}{% set server_prefix = ( server | replace("//","##") ~ '/' ~ prefix ~ '/' ) | replace("///","/") | replace("//", "/") | replace("##","//") %}{% set prefix_ulp = ( '/' ~ prefix ~ '/' ~ ulp ~ '/' ) | replace("///","/") | replace("//", "/") %}{% set server_prefix_ulp = ( server | replace("//","##") ~ '/' ~ prefix ~ '/' ~ ulp ~ '/' ) | replace("///","/") | replace("//", "/") | replace("##","//") %}
+/* vim:set syntax=javascript ts=2 sw=2 sts=2 et: */
+var ddup = {
+ // (A) ON PAGE LOAD
+ hzone: null, // HTML upload zone
+ hstat: null, // HTML upload status
+ hform: null, // HTML upload form
+ hiddenfirst: null,
+ init : function () {
+ // (A1) GET HTML ELEMENTS
+ ddup.hzone = document.getElementById("upzone");
+ ddup.hstat = document.getElementById("upstat");
+ ddup.hform = document.getElementById("upform");
+ ddup.hiddenfirst = document.getElementById("hiddenfirst");
+
+ // (A2) DRAG-DROP SUPPORTED
+ if (window.File && window.FileReader && window.FileList && window.Blob) {
+ // HIGHLIGHT DROPZONE ON FILE HOVER
+ ddup.hzone.addEventListener("dragenter", function (e) {
+ e.preventDefault();
+ e.stopPropagation();
+ ddup.hzone.classList.add('highlight');
+ ddup.hzone.innerHTML = "Release to upload";
+ });
+ ddup.hzone.addEventListener("dragleave", function (e) {
+ e.preventDefault();
+ e.stopPropagation();
+ ddup.hzone.classList.remove('highlight');
+ ddup.hzone.innerHTML = "Drop Files Here";
+ });
+
+ // DROP TO UPLOAD FILE
+ ddup.hzone.addEventListener("dragover", function (e) {
+ e.preventDefault();
+ e.stopPropagation();
+ });
+ ddup.hzone.addEventListener("drop", function (e) {
+ e.preventDefault();
+ e.stopPropagation();
+ ddup.hzone.classList.remove('highlight');
+ ddup.hiddenfirst.style.display = "block" ;
+ if (e.dataTransfer.files.length > 0) {
+ ddup.hzone.classList.add('processing');
+ ddup.hzone.innerHTML = "Uploading...";
+ ddup.queue(e.dataTransfer.files);
+ } else {
+ ddup.hzone.classList.add('invalid');
+ ddup.hzone.innerHTML = "Input is not recognized!";
+ ddup.reset_text_timer(1500);
+ }
+ });
+ }
+
+ // (A3) DRAG-DROP UPLOAD NOT SUPPORTED
+ else {
+ ddup.hzone.style.display = "none";
+ ddup.hform.style.display = "block";
+ }
+ },
+
+ // (B) UPLOAD QUEUE + HANDLER
+ // NOTE: AJAX IS ASYNCHRONOUS
+ // A QUEUE IS REQUIRED TO STOP SERVER FLOOD
+ upqueue : [], // upload queue
+ uplock : false, // currently uploading a file
+ queue : function (files) {
+ // FILE LIST INTO QUEUE
+ for (let f of files) {
+ // OPTIONAL - SHOW UPLOAD STATUS
+ ddup.thisdiv = document.getElementById(f.name);
+ if (!ddup.thisdiv) {
+ // add new div with filename as id
+ ddup.hstat.innerHTML += `<div id="${f.name}">${f.name} - Added to queue</div>`;
+ } else {
+ // change contents of existing div
+ ddup.thisdiv.innerHTML = `${f.name} - Added to queue`;
+ }
+ // ADD TO QUEUE
+ ddup.upqueue.push(f);
+ }
+ // GO!
+ ddup.go();
+ },
+
+ // (C) AJAX UPLOAD
+ go : function () { if (!ddup.uplock && ddup.upqueue.length!=0) {
+ // (C1) QUEUE STATUS UPDATE
+ ddup.uplock = true;
+
+ // (C2) PLUCK OUT FIRST FILE IN QUEUE
+ let thisfile = ddup.upqueue[0];
+ ddup.upqueue.shift();
+
+ // OPTIONAL - SHOW UPLOAD STATUS
+ ddup.thisdiv = document.getElementById(thisfile.name);
+ ddup.thisdiv.innerHTML = `${thisfile.name} - Upload started`;
+ // at start of queue, change color
+ ddup.hzone.classList.add('processing');
+ ddup.hzone.innerHTML = "Uploading...";
+
+ // (C3) UPLOAD DATA
+ let data = new FormData();
+ data.append('file', thisfile);
+ // ADD MORE POST DATA IF YOU WANT
+ // data.append("KEY", "VALUE");
+
+ // (C4) AJAX REQUEST
+ let xhr = new XMLHttpRequest();
+ xhr.open("POST", "{{ server_prefix_ulp }}");
+ xhr.setRequestHeader("lastModified", thisfile.lastModified/1000);
+ xhr.onload = function () {
+ // OPTIONAL - SHOW UPLOAD STATUS
+ ddup.thisdiv.innerHTML = `${thisfile.name} - ${this.response}`;
+ // NEXT BETTER PLAYER!
+ ddup.hzone.classList.remove('processing');
+ ddup.hzone.innerHTML = "Drop Files Here";
+ ddup.uplock = false;
+ ddup.go();
+ };
+ xhr.onerror = function(evt){
+ // OPTIONAL - SHOW UPLOAD STATUS
+ ddup.thisdiv.innerHTML = `${thisfile.name} - AJAX ERROR`;
+ // NEXT BETTER PLAYER!
+ ddup.hzone.classList.remove('processing');
+ ddup.hzone.innerHTML = "Drop Files Here";
+ ddup.uplock = false;
+ ddup.go();
+ };
+ xhr.send(data);
+ } },
+
+ reset_text_timer : function (delay_ms) {
+ setTimeout(function (){
+ ddup.hzone.classList.remove('invalid');
+ ddup.hzone.innerHTML = "Drop Files Here";
+ }, delay_ms);
+ }
+};
+window.addEventListener("DOMContentLoaded", ddup.init);
bgstack15