Adding rudimentary file browser.
This commit is contained in:
parent
753321ad1d
commit
c05064e6e8
|
|
@ -0,0 +1,29 @@
|
||||||
|
@import url("openwebrx-header.css");
|
||||||
|
@import url("openwebrx-globals.css");
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
height: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin-bottom: 5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
background: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin: 1em 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-collapse: separate;
|
||||||
|
border-spacing: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
text-align: center;
|
||||||
|
border: 3px dotted;
|
||||||
|
}
|
||||||
|
|
@ -158,8 +158,8 @@ input[type=range]:disabled {
|
||||||
{
|
{
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
#openwebrx-scale-container
|
#openwebrx-scale-container
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
<HTML><HEAD>
|
||||||
|
<TITLE>OpenWebRX+ Received Files</TITLE>
|
||||||
|
<link rel="shortcut icon" type="image/x-icon" href="static/favicon.ico" />
|
||||||
|
<link rel="stylesheet" href="static/css/bootstrap.min.css" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="static/css/files.css" />
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/showdown/1.9.0/showdown.min.js"></script>
|
||||||
|
<script src="static/lib/jquery-3.2.1.min.js"></script>
|
||||||
|
<script src="static/lib/Header.js"></script>
|
||||||
|
<script src="static/files.js"></script>
|
||||||
|
</HEAD><BODY>
|
||||||
|
${header}
|
||||||
|
<div class="container">
|
||||||
|
<h1>OpenWebRX+ Received Files</h1>
|
||||||
|
<table>
|
||||||
|
${rows}
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</BODY></HTML>
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
function saveCanvas(canvas, name) {
|
||||||
|
var a = document.createElement('a');
|
||||||
|
|
||||||
|
canvas.toBlob(function(blob) {
|
||||||
|
a.href = window.URL.createObjectURL(blob);
|
||||||
|
}, 'image/png');
|
||||||
|
|
||||||
|
a.style = 'display: none';
|
||||||
|
a.download = name;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
document.body.removeChild(a);
|
||||||
|
window.URL.revokeObjectURL(a.href);
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
|
@ -93,6 +93,24 @@ function toggleRecording() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function saveCanvas(canvas, name) {
|
||||||
|
var a = document.createElement('a');
|
||||||
|
|
||||||
|
canvas.toBlob(function(blob) {
|
||||||
|
a.href = window.URL.createObjectURL(blob);
|
||||||
|
}, 'image/png');
|
||||||
|
|
||||||
|
a.style = 'display: none';
|
||||||
|
a.download = name;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
document.body.removeChild(a);
|
||||||
|
window.URL.revokeObjectURL(a.href);
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
function zoomInOneStep() {
|
function zoomInOneStep() {
|
||||||
zoom_set(zoom_level + 1);
|
zoom_set(zoom_level + 1);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
from owrx.controllers.template import WebpageController
|
||||||
|
from owrx.controllers.assets import ModificationAwareController
|
||||||
|
from owrx.breadcrumb import Breadcrumb, BreadcrumbItem, BreadcrumbMixin
|
||||||
|
from owrx.controllers.settings import SettingsBreadcrumb
|
||||||
|
from owrx.config.core import CoreConfig
|
||||||
|
|
||||||
|
from datetime import datetime, timezone
|
||||||
|
import mimetypes
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
|
class FileController(ModificationAwareController):
|
||||||
|
def getModified(self, file):
|
||||||
|
return datetime.fromtimestamp(os.path.getmtime(file), timezone.utc)
|
||||||
|
|
||||||
|
def openFile(self, file):
|
||||||
|
return open(file, "rb")
|
||||||
|
|
||||||
|
def serve_file(self, file, content_type=None):
|
||||||
|
try:
|
||||||
|
modified = self.getModified(file)
|
||||||
|
|
||||||
|
if not self.wasModified(file):
|
||||||
|
self.send_response("", code=304)
|
||||||
|
return
|
||||||
|
|
||||||
|
f = self.openFile(file)
|
||||||
|
data = f.read()
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
if content_type is None:
|
||||||
|
(content_type, encoding) = mimetypes.guess_type(file)
|
||||||
|
self.send_response(data, content_type=content_type, last_modified=modified, max_age=3600)
|
||||||
|
except FileNotFoundError:
|
||||||
|
self.send_response("file '%s' not found" % file, code=404)
|
||||||
|
|
||||||
|
def indexAction(self):
|
||||||
|
filename = self.request.matches.group(1)
|
||||||
|
self.serve_file("/tmp/" + filename)
|
||||||
|
|
||||||
|
|
||||||
|
class FilesController(WebpageController):
|
||||||
|
def template_variables(self):
|
||||||
|
files = [f for f in os.listdir('/tmp') if re.match(r'SSTV-[0-9]+-[0-9]+\.bmp', f)]
|
||||||
|
rows = ""
|
||||||
|
|
||||||
|
for i in range(len(files)):
|
||||||
|
# Start a row
|
||||||
|
if i % 3 == 0:
|
||||||
|
rows += '<tr>\n'
|
||||||
|
# Print out individual tiles
|
||||||
|
rows += ('<td class="file-tile"><img src="/files/%s" download="%s">' % (files[i], files[i])) + ('<p align="center">%s</p></td>\n' % files[i])
|
||||||
|
# Finish a row
|
||||||
|
if i % 3 == 2:
|
||||||
|
rows += '</tr>\n'
|
||||||
|
|
||||||
|
variables = super().template_variables()
|
||||||
|
variables["rows"] = rows
|
||||||
|
return variables
|
||||||
|
|
||||||
|
def indexAction(self):
|
||||||
|
self.serve_template("files.html", **self.template_variables())
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
from owrx.controllers.status import StatusController
|
from owrx.controllers.status import StatusController
|
||||||
from owrx.controllers.template import IndexController, MapController, PolicyController
|
from owrx.controllers.template import IndexController, MapController, PolicyController
|
||||||
from owrx.controllers.feature import FeatureController
|
from owrx.controllers.feature import FeatureController
|
||||||
|
from owrx.controllers.file import FilesController, FileController
|
||||||
from owrx.controllers.assets import OwrxAssetsController, AprsSymbolsController, CompiledAssetsController
|
from owrx.controllers.assets import OwrxAssetsController, AprsSymbolsController, CompiledAssetsController
|
||||||
from owrx.controllers.websocket import WebSocketController
|
from owrx.controllers.websocket import WebSocketController
|
||||||
from owrx.controllers.api import ApiController
|
from owrx.controllers.api import ApiController
|
||||||
|
|
@ -96,6 +97,8 @@ class Router(object):
|
||||||
StaticRoute("/map", MapController),
|
StaticRoute("/map", MapController),
|
||||||
StaticRoute("/policy", PolicyController),
|
StaticRoute("/policy", PolicyController),
|
||||||
StaticRoute("/features", FeatureController),
|
StaticRoute("/features", FeatureController),
|
||||||
|
StaticRoute("/files", FilesController),
|
||||||
|
RegexRoute("^/files/(SSTV-[0-9]+-[0-9]+\.bmp)$", FileController),
|
||||||
StaticRoute("/api/features", ApiController),
|
StaticRoute("/api/features", ApiController),
|
||||||
StaticRoute("/metrics", MetricsController, options={"action": "prometheusAction"}),
|
StaticRoute("/metrics", MetricsController, options={"action": "prometheusAction"}),
|
||||||
StaticRoute("/metrics.json", MetricsController),
|
StaticRoute("/metrics.json", MetricsController),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue