Files
pamietnik/backend/internal/api/templates/public.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

67 lines
1.9 KiB
HTML

{{define "title"}}Journal{{end}}
{{define "content"}}
<main class="container">
<div id="feed">
{{template "feed_items" .}}
</div>
</main>
{{end}}
{{define "feed_items"}}
{{range .Entries}}
<article class="pub-card">
{{if .Images}}
{{with (index .Images 0)}}
{{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 class="pub-cover" src="/uploads/{{.Filename}}" alt="">
</a>
{{end}}
{{end}}
{{end}}
<div class="pub-body">
<small class="pub-meta">{{.EntryDate}} · {{.EntryTime}}</small>
{{if .Title}}<strong class="pub-title">{{.Title}}</strong>{{end}}
{{if .Description}}<div class="pub-desc">{{markdown .Description}}</div>{{end}}
{{if .Hashtags}}<div class="pub-tags">{{range .Hashtags}}<span class="tag">#{{.}}</span> {{end}}</div>{{end}}
</div>
</article>
{{else}}
<p><small>// Noch keine öffentlichen Einträge</small></p>
{{end}}
{{if .HasMore}}
<div id="sentinel" data-offset="{{.Offset}}"></div>
{{end}}
{{end}}
{{define "scripts"}}
<script>
(function() {
const sentinel = document.getElementById('sentinel');
if (!sentinel) return;
const obs = new IntersectionObserver(function(entries) {
if (!entries[0].isIntersecting) return;
obs.disconnect();
fetch('/feed?offset=' + sentinel.dataset.offset)
.then(r => r.text())
.then(html => {
sentinel.remove();
const div = document.createElement('div');
div.innerHTML = html;
document.getElementById('feed').append(...div.childNodes);
const next = document.getElementById('sentinel');
if (next) obs.observe(next);
});
});
obs.observe(sentinel);
})();
</script>
{{end}}
{{template "base" .}}