Files
pamietnik/backend/internal/api/templates/day.html
Christoph K. 17186e7b64
All checks were successful
Deploy to NAS / deploy (push) Successful in 2m20s
Add TypeScript migration, image resizing, media upload UX, and multimedia support
- Migrate static JS to TypeScript (static-ts/ → compiled to internal/api/static/)
- Add image resizing on upload: JPEG/PNG/WebP scaled to max 1920px at quality 80
- Extract shared upload logic into upload.go (saveUpload, saveResizedImage, saveResizedWebP)
- Add POST /media endpoint for drag-drop/paste media uploads with markdown ref return
- Add background music player with video/audio coordination (autoplay.ts)
- Add global nav, public feed, hashtags, visibility, Markdown rendering for entries
- Add Dockerfile stage for TypeScript compilation (static-ts-builder)
- Add goldmark, disintegration/imaging, golang.org/x/image dependencies

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 23:03:04 +02:00

114 lines
4.0 KiB
HTML

{{define "title"}}{{.Date}} — Reisejournal{{end}}
{{define "content"}}
<main class="container">
<nav><a href="/days">← Alle Tage</a></nav>
<h1>{{.Date}}</h1>
<form method="post" action="/entries" enctype="multipart/form-data">
<input type="hidden" name="date" value="{{.Date}}">
<div class="gps-row">
<input type="time" name="time" required id="entry-time">
<select name="visibility">
<option value="private">Privat</option>
<option value="public">Öffentlich</option>
</select>
</div>
<input type="text" name="title" placeholder="Überschrift">
<div class="editor-wrap">
<textarea name="description" rows="6" placeholder="Beschreibung — Markdown unterstützt&#10;Medien: per Drag & Drop oder Einfügen (Strg+V)"></textarea>
<div class="editor-bar">
<button type="button" class="media-picker">&#128206; Datei anhängen</button>
<span class="upload-status"></span>
<input type="file" class="media-file-input" multiple accept="image/*,video/*,audio/*" style="display:none">
</div>
</div>
<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">&#9678; GPS</button>
</div>
<small id="gps-status"></small>
<input type="text" name="hashtags" placeholder="Hashtags (kommagetrennt)">
<button type="submit">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 eq .Visibility "public"}}<span class="badge-public">öffentlich</span>{{end}}
{{if .Lat}}<small> · &#9675; {{printf "%.5f" (deref .Lat)}}, {{printf "%.5f" (deref .Lon)}}</small>{{end}}
<a href="/entries/{{.EntryID}}/edit" class="entry-edit">bearbeiten</a>
</div>
{{if .Title}}<div class="entry-title">{{.Title}}</div>{{end}}
{{if .Description}}<div class="entry-desc">{{markdown .Description}}</div>{{end}}
{{if .Hashtags}}<div class="hashtags">{{range .Hashtags}}<span class="tag">#{{.}}</span> {{end}}</div>{{end}}
{{if .Images}}
<div class="entry-images">
{{range .Images}}
{{if isVideo .MimeType}}
<video src="/uploads/{{.Filename}}" controls class="media-embed"></video>
{{else if isAudio .MimeType}}
<audio src="/uploads/{{.Filename}}" controls class="media-audio"></audio>
{{else}}
<a href="/uploads/{{.Filename}}" target="_blank">
<img src="/uploads/{{.Filename}}" alt="{{.OriginalName}}" class="thumb">
</a>
{{end}}
{{end}}
</div>
{{end}}
</div>
{{else}}
<p><small>// Noch keine Einträge</small></p>
{{end}}
<h2>Aufenthalte <small>({{len .Stops}})</small></h2>
{{if .Stops}}
<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>
{{end}}
</tbody>
</table>
{{else}}
<p><small>// Keine Aufenthalte</small></p>
{{end}}
<details>
<summary><small>Trackpunkte ({{len .Points}})</small></summary>
<table>
<thead><tr><th>Zeit</th><th>Lat</th><th>Lon</th><th>Quelle</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>
</tr>
{{else}}
<tr><td colspan="4"><small>// Keine Punkte</small></td></tr>
{{end}}
</tbody>
</table>
</details>
</main>
{{end}}
{{define "scripts"}}
<script src="/static/day.js"></script>
<script src="/static/editor.js"></script>
{{end}}
{{template "base" .}}