Adding rudimentary file browser.

This commit is contained in:
Marat Fayzullin 2023-02-21 20:30:39 -05:00
parent 753321ad1d
commit c05064e6e8
7 changed files with 149 additions and 2 deletions

29
htdocs/css/files.css Normal file
View File

@ -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;
}

18
htdocs/files.html Normal file
View File

@ -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>

17
htdocs/files.js Normal file
View File

@ -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);
}

View File

@ -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);
} }

62
owrx/controllers/file.py Normal file
View File

@ -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())

View File

@ -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),