Convert backend from submodule to regular directory
Some checks failed
Deploy to NAS / deploy (push) Failing after 4s

Remove submodule tracking; backend is now a plain directory in the repo.
Also update deploy workflow: remove --recurse-submodules.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Christoph K.
2026-04-07 16:59:50 +02:00
parent 0bb7758a2f
commit d0b0b4f8bd
35 changed files with 2271 additions and 8 deletions

View File

@@ -0,0 +1,15 @@
{{define "base"}}<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{block "title" .}}Reisejournal{{end}}</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.classless.slate.min.css">
<link rel="stylesheet" href="/static/style.css">
</head>
<body>
{{block "content" .}}{{end}}
{{block "scripts" .}}{{end}}
</body>
</html>
{{end}}

View File

@@ -0,0 +1,104 @@
{{define "title"}}{{.Date}} — Reisejournal{{end}}
{{define "content"}}
<main class="container">
<nav><a href="/days">← Alle Tage</a></nav>
<h1>{{.Date}}</h1>
<h2>Neuer Eintrag</h2>
<form method="post" action="/entries" enctype="multipart/form-data" class="entry-form">
<input type="hidden" name="date" value="{{.Date}}">
<div class="form-row">
<div class="form-col">
<label>Uhrzeit</label>
<input type="time" name="time" required id="entry-time">
</div>
<div class="form-col">
<label>GPS-Koordinaten <small>(optional)</small></label>
<div class="gps-row">
<input type="number" name="lat" id="entry-lat" step="any" placeholder="Breite">
<input type="number" name="lon" id="entry-lon" step="any" placeholder="Länge">
<button type="button" id="btn-gps" title="Aktuellen Standort ermitteln">&#9678; GPS</button>
</div>
<small id="gps-status"></small>
</div>
</div>
<label>Überschrift</label>
<input type="text" name="title" placeholder="Titel des Eintrags">
<label>Beschreibung</label>
<textarea name="description" rows="4" placeholder="Was ist passiert?"></textarea>
<label>Bilder <small>(optional, max. 10 MB pro Bild)</small></label>
<input type="file" name="images" multiple accept="image/*" id="image-input">
<div id="image-preview" class="image-preview"></div>
<button type="submit">Eintrag speichern</button>
</form>
<h2>Einträge <small>({{len .Entries}})</small></h2>
{{range .Entries}}
<div class="entry-card">
<div class="entry-meta">
<strong>{{.EntryTime}}</strong>
{{if .Lat}}<small> · &#9675; {{printf "%.5f" (deref .Lat)}}, {{printf "%.5f" (deref .Lon)}}</small>{{end}}
</div>
{{if .Title}}<div class="entry-title">{{.Title}}</div>{{end}}
{{if .Description}}<div class="entry-desc">{{.Description}}</div>{{end}}
{{if .Images}}
<div class="entry-images">
{{range .Images}}
<a href="/uploads/{{.Filename}}" target="_blank">
<img src="/uploads/{{.Filename}}" alt="{{.OriginalName}}" class="thumb">
</a>
{{end}}
</div>
{{end}}
</div>
{{else}}
<p><small>// Noch keine Einträge</small></p>
{{end}}
<h2>Trackpunkte <small>({{len .Points}})</small></h2>
<figure>
<table>
<thead><tr><th>Zeit</th><th>Lat</th><th>Lon</th><th>Quelle</th><th>Notiz</th></tr></thead>
<tbody>
{{range .Points}}
<tr>
<td>{{.Timestamp.Format "15:04:05"}}</td>
<td>{{printf "%.5f" .Lat}}</td>
<td>{{printf "%.5f" .Lon}}</td>
<td class="source-{{.Source}}">{{.Source}}</td>
<td><small>{{.Note}}</small></td>
</tr>
{{else}}
<tr><td colspan="5"><small>// Keine Punkte</small></td></tr>
{{end}}
</tbody>
</table>
</figure>
<h2>Aufenthalte <small>({{len .Stops}})</small></h2>
<figure>
<table>
<thead><tr><th>Von</th><th>Bis</th><th>Dauer</th><th>Ort</th></tr></thead>
<tbody>
{{range .Stops}}
<tr>
<td>{{.StartTS.Format "15:04"}}</td>
<td>{{.EndTS.Format "15:04"}}</td>
<td><small>{{divInt .DurationS 60}} min</small></td>
<td>{{if .PlaceLabel}}{{.PlaceLabel}}{{else}}<small></small>{{end}}</td>
</tr>
{{else}}
<tr><td colspan="4"><small>// Keine Aufenthalte</small></td></tr>
{{end}}
</tbody>
</table>
</figure>
</main>
{{end}}
{{define "scripts"}}
<script src="/static/day.js"></script>
{{end}}
{{template "base" .}}

View File

@@ -0,0 +1,46 @@
{{define "title"}}Tage — Reisejournal{{end}}
{{define "content"}}
<main class="container">
<div class="page-header">
<h1>REISEJOURNAL</h1>
<a href="/logout">[ Ausloggen ]</a>
</div>
<form method="get" action="/days/redirect">
<fieldset role="group">
<input type="date" name="date" id="nav-date" required>
<button type="submit">Tag öffnen</button>
</fieldset>
</form>
<h2>Reisetage</h2>
<figure>
<table>
<thead><tr><th>Datum</th><th>Punkte</th><th>Von</th><th>Bis</th></tr></thead>
<tbody>
{{range .Days}}
<tr>
<td><a href="/days/{{.Date}}">{{.Date}}</a></td>
<td>{{.Count}}</td>
<td><small>{{if .FirstTS}}{{.FirstTS.Format "15:04"}}{{end}}</small></td>
<td><small>{{if .LastTS}}{{.LastTS.Format "15:04"}}{{end}}</small></td>
</tr>
{{else}}
<tr><td colspan="4"><small>// Keine Daten vorhanden</small></td></tr>
{{end}}
</tbody>
</table>
</figure>
</main>
{{end}}
{{define "scripts"}}
<script>
var d = document.getElementById('nav-date');
if (d && !d.value) {
d.value = new Date().toISOString().slice(0, 10);
}
</script>
{{end}}
{{template "base" .}}

View File

@@ -0,0 +1,21 @@
{{define "title"}}Login — Reisejournal{{end}}
{{define "content"}}
<main class="container">
<article class="login-box">
<h1>REISEJOURNAL</h1>
{{if .Error}}<p class="err">// {{.Error}}</p>{{end}}
<form method="post" action="/login">
<label>Benutzername
<input name="username" autocomplete="username" value="{{.Username}}">
</label>
<label>Passwort
<input type="password" name="password" autocomplete="current-password">
</label>
<button type="submit">Einloggen</button>
</form>
</article>
</main>
{{end}}
{{template "base" .}}