feat: Bit of frontend changes

This commit is contained in:
2025-11-29 13:38:17 +01:00
parent 7711bcc220
commit 92187dc638
11 changed files with 87 additions and 89 deletions

1
.gitignore vendored
View File

@@ -3,5 +3,4 @@ config.json
/backend/target
/frontend/node_modules
/frontend/dist
/docker/privacy-policy.html
.idea/

View File

@@ -31,9 +31,6 @@ Configure by setting up _/docker/.env_ (copy [/docker/.env.example](docker/.env.
(Please note that the _bind\_url_ should be left unconfigured as it is used in the [/docker/docker-compose.yml](docker/docker-compose.yml) config file. Otherwise the proxy-pass may break.)
### Privacy policy
The website contains links to _privacy-policy.html_. You can (and should) set up this privacy policy page. Empty dummy files already exist in the [_docker/_](docker) and [_frontend/src/_](frontend/src) directories.
## API
API-Documentation: [openapi.yml](openapi.yml)

View File

@@ -1,8 +1,4 @@
use std::{
collections::HashMap,
io::Error,
};
use std::{collections::HashMap, io::Error};
use log::{debug, error};
use serde::Deserialize;
use tokio::io::{AsyncBufReadExt, BufReader, BufWriter};
@@ -113,6 +109,8 @@ pub async fn init<A: ToSocketAddrs>(
.await?;
tcp_stream_writer.flush().await?;
debug!("Sent login: '{}'", login_message.trim());
loop {
let mut line = String::new();
@@ -131,7 +129,7 @@ pub async fn init<A: ToSocketAddrs>(
let current_timestamp = get_current_timestamp();
debug!("Got line: '{line}'");
debug!("Got line: '{}'", line.trim());
line_received_tx
.send(current_timestamp)

View File

@@ -20,4 +20,3 @@ services:
- "127.0.0.1:9000:8080"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./privacy-policy.html:/usr/share/nginx/html/privacy-policy.html:ro

View File

@@ -16,7 +16,7 @@ http {
server_name _;
add_header Content-Security-Policy "default-src 'self' 'unsafe-inline' data:;";
add_header Permissions-Policy "geolocation=(), midi=(), camera=(), usb=(), payment=(), vr=(), speaker=(), ambient-light-sensor=(), gyroscope=(), microphone=(), usb=(), interest-cohort=()";
add_header Permissions-Policy "geolocation=(self), midi=(), camera=(), usb=(), payment=(), vr=(), speaker=(), ambient-light-sensor=(), gyroscope=(), microphone=(), usb=(), interest-cohort=()";
add_header Referer "no-referrer";
add_header Referrer-Policy "no-referrer";
add_header Strict-Transport-Security "max-age=63072000" always;
@@ -26,10 +26,10 @@ http {
client_max_body_size 1;
access_log off;
error_log /dev/null emerg;
location /r/ {
# Do not log location data
access_log off;
error_log /dev/null emerg;
proxy_pass http://backend:9000/r/;
}
@@ -41,11 +41,6 @@ http {
gzip_types *;
expires 1d;
location = /privacy-policy.html {
root /usr/share/nginx/html;
try_files /privacy-policy.html =404;
}
location / {
proxy_pass http://frontend:80/;
}

View File

@@ -1 +0,0 @@
<!-- Fill this privacy policy. -->

View File

@@ -13,7 +13,7 @@ WORKDIR /app
COPY src src
RUN mkdir dist
RUN npx handlebars src/table.handlebars -f dist/table.handlebars.compiled.js
RUN npx handlebars src/table.handlebars -f dist/table.handlebars.dist.js
COPY --from=install /app/node_modules/handlebars/dist/handlebars.min.js dist
COPY --from=install /app/node_modules/bootstrap/dist/js/bootstrap.min.js dist
@@ -21,7 +21,6 @@ COPY --from=install /app/node_modules/bootstrap/dist/js/bootstrap.min.js.map dis
COPY --from=install /app/node_modules/bootstrap/dist/css/bootstrap.min.css dist
COPY --from=install /app/node_modules/bootstrap/dist/css/bootstrap.min.css.map dist
COPY src/index.html dist
COPY src/privacy-policy.html dist
COPY src/main.js dist
COPY src/style.css dist

View File

@@ -6,7 +6,7 @@
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"copy-dependencies": "rm -rf dist && rsync -av --exclude='*.handlebars' src/ dist/ && cp node_modules/handlebars/dist/handlebars.min.js dist/ && cp node_modules/bootstrap/dist/js/bootstrap.min.js dist && cp node_modules/bootstrap/dist/js/bootstrap.min.js.map dist && cp node_modules/bootstrap/dist/css/bootstrap.min.css dist && cp node_modules/bootstrap/dist/css/bootstrap.min.css.map dist",
"compile": "handlebars src/table.handlebars -f dist/table.handlebars.compiled.js",
"compile": "handlebars src/table.handlebars -f dist/table.handlebars.dist.js",
"dev": "npm run copy-dependencies && npm run compile && cd dist && python3 -m http.server 8080"
},
"keywords": [

View File

@@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="en">
<html lang="de">
<head>
<meta charset="UTF-8">
@@ -13,90 +13,81 @@
</head>
<body>
<nav class="navbar navbar-dark bg-dark">
<div class="container">
<a class="navbar-brand" href="#">
above_me
</a>
<div class="links">
<a href="privacy-policy.html">
Privacy policy
</a>
</div>
</div>
</nav>
<div class="container">
<h3>See what's flying right above you!</h1>
<div class="intro">
<div>
<p>
Klicke auf <i>Was fliegt über mir?</i> oder gebe hier spezifische Koordinaten und einen Suchradius
ein, um zu sehen, was in deiner Nähe gerade fliegt.
</p>
<p>
Die Daten dieser Webseite basieren auf den Services des
<a href="http://wiki.glidernet.org/" target="_blank">Open Glider Network</a>.
(Vielen Dank für eure offenen APIs! 😊)
</p>
</div>
<div class="button-container">
<button type="button" class="btn btn-primary btn-lg" onclick="onClickWhatsAboveMe()"
aria-describedby="whats-above-me-hint">What's above
me?</button>
aria-describedby="whats-above-me-hint">Was fliegt über mir?</button>
<div id="whats-above-me-hint" class="form-text">
By clicking this button you accept our <a href="privacy-policy.html">privacy policy</a> and also
that
your current position is sent to the webserver.
Mit Klick auf den Button wird deine aktuelle Position vom Browser übermittelt und es werden die
Flugzeuge
in deiner Nähe abgefragt. Weder deine Position noch die Anfrage an den Server werden dabei geloggt
oder gespeichert.
</div>
</div>
<div class="alert alert-danger status-message" role="alert" id="no-position-available">
Error. Position for your device could not be loaded. Please check if you gave permission to this site to
access your position.
Es ist ein Fehler aufgetreten: Dein Browser erlaubt der Webseite nicht, den Standort zu ermitteln.<br>
Prüfe die Webseitenberechtigungen und versuche es dann erneut.
</div>
<div class="alert alert-danger status-message" role="alert" id="http-error">
Error. Could not fetch data. Open the developer console for more information.
Es ist ein Fehler aufgetreten: Die Daten konnten nicht geladen werden.<br>
(Öffne die Entwicklungskonsole für weitere Informationen.)
</div>
<div class="alert alert-info status-message" role="alert" id="loading-position">
Loading position...
Position wird vom Browser angefragt…
</div>
<div id="table-container" class="overflow-auto"></div>
</div>
<div id="table-container" class="overflow-auto"></div>
<p>
Either click <i>What's above me?</i> to automatically fetch your location
or enter specific coordinates and range and see whats flying above you right now.
</p>
<p>
This site works with data provided by the
<a href="http://wiki.glidernet.org/" target="_blank">Open Glider Network</a>.
(Thank you for your open data & APIs! 😊)
</p>
<form>
<div class="mb-3">
<label for="latitude" class="form-label">Latitude</label>
<input class="form-control" type="number" name="latitude" id="latitude" placeholder="48.858222"
min="-90" max="90" step=".000000001">
<form>
<div class="mb-3">
<label for="latitude" class="form-label">Breitengrad (Latitude)</label>
<input class="form-control" type="number" name="latitude" id="latitude" placeholder="48.858222"
min="-90" max="90" step=".000000001">
</div>
<div class="mb-3">
<label for="longitude" class="form-label">Längengrad (Longitude)</label>
<input class="form-control" type="number" name="longitude" id="longitude" placeholder="2.2945"
min="-180" max="180" step=".000000001">
</div>
<div class="mb-3">
<label for="range" class="form-label">Range</label>
<input class="form-control" type="number" name="range" id="range" min="1" max="20" value="20"
placeholder="1 - 20 km" aria-describedby="range-help" step="1">
<div id="range-help" class="form-text">
Suchradius (in <i>km</i>) um die angegebenen Koordinaten.
</div>
<div class="mb-3">
<label for="longitude" class="form-label">Longitude</label>
<input class="form-control" type="number" name="longitude" id="longitude" placeholder="2.2945"
min="-180" max="180" step=".000000001">
</div>
<div class="mb-3 button-container">
<button type="submit" class="btn btn-primary" aria-describedby="submit-hint">Was fliegt hier?</button>
<div id="submit-hint" class="form-text">
Mit Klick auf <i>Was fliegt hier?</i> werden die Flugzeuge für die angegebenen Koordinaten
abgefragt.
Weder die Koordinaten noch die Anfrage an den Server werden dabei geloggt oder gespeichert.
</div>
<div class="mb-3">
<label for="range" class="form-label">Range</label>
<input class="form-control" type="number" name="range" id="range" min="1" max="20" value="20"
placeholder="1 - 20 km" aria-describedby="range-help" step="1">
<div id="range-help" class="form-text">
Range (in <i>km</i>) around given coordinates that should be filtered for.
</div>
</div>
<div class="mb-3 button-container">
<button type="submit" class="btn btn-primary" aria-describedby="submit-hint">Submit</button>
<div id="submit-hint" class="form-text">
By clicking this button you accept our <a href="privacy-policy.html">privacy policy</a> and also
that the given position is sent to the webserver.
</div>
</div>
</form>
</div>
</form>
</div>
<script src="bootstrap.min.js"></script>
<script src="handlebars.min.js"></script>
<script src="table.handlebars.compiled.js"></script>
<script src="table.handlebars.dist.js"></script>
<script src="main.js"></script>
</body>

View File

@@ -1 +0,0 @@
<!-- Fill this privacy policy. -->

View File

@@ -1,5 +1,26 @@
nav {
margin-bottom: 3%;
html, body {
width: 100%;
height: 100%;
}
.container {
display: grid;
height: 100%;
width: 100%;
grid-template-columns: 100%;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"intro"
"table"
"form";
padding-top: 5%;
}
.intro {
grid-area: intro;
}
.button-container {
@@ -10,6 +31,7 @@ nav {
}
form {
grid-area: form;
margin-top: 12.5%;
}
@@ -32,7 +54,7 @@ form .button-container {
}
#table-container {
margin: 5% 0;
grid-area: table;
white-space: nowrap;
}