- Go 67.6%
- TypeScript 23.2%
- CSS 4.4%
- HTML 2.9%
- JavaScript 1.1%
- Other 0.8%
Notizen tragen jetzt eine Uhrzeit, nicht nur einen Tag:
tree_notes.observed_at wechselt von DATE auf TIMESTAMPTZ, im
API-Vertrag von `format: date` auf `format: date-time`. Ausgeliefert
wird RFC 3339 in Ortszeit des Bongerts; POST/PATCH nehmen weiterhin ein
blankes YYYY-MM-DD an, wenn nur der Tag bekannt ist. Mitternacht
Ortszeit ist die Konvention für "Uhrzeit unbekannt"
(internal/treestore/observedat.go, cmd/treedoc/ui/src/observedAt.ts),
deshalb kommt keine zweite Spalte dazu.
Damit ist auch die vorbestehende Vertragsverletzung erledigt:
observed_at lieferte RFC-3339-Zeitstempel gegen ein zugesagtes
`format: date`. Die OpenAPI-Middleware hatte das erkannt, aber
Response-Verstöße landen nur als Log-Warnung, nicht als Fehler.
Offline-Notizen aus TreePhoto behalten ihren Erfassungszeitpunkt statt
auf den Tag gekürzt zu werden. Fotos bleiben unverändert — deren
created_at war schon immer ein voller Zeitstempel.
Dazu: `position` (Bongert-Rasterkoordinate) fließt in die Antwort von
/api/tree/v1/around, und TreeDocsAround selektiert die Spalte. Ohne das
passende Scan-Ziel lief die Query in
"expected 13 destination arguments in Scan, not 12" — kein Test deckte
den Pfad ab.
Migration (bereits auf cleo und ruby gefahren):
ALTER TABLE tree_notes ALTER COLUMN observed_at TYPE TIMESTAMPTZ
USING (observed_at::timestamp AT TIME ZONE 'Europe/Berlin');
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|---|---|---|
| cmd | ||
| config | ||
| internal | ||
| schema | ||
| scripts | ||
| .gitignore | ||
| .golangci.yml | ||
| CHANGELOG.md | ||
| CLAUDE.md | ||
| config.sandbox.yaml.example | ||
| config.yaml.example | ||
| DEPLOY.md | ||
| go.mod | ||
| go.sum | ||
| INSTALL.md | ||
| Makefile | ||
| README.md | ||
treedoc / treelink
Werkzeuge zum Erfassen, Verwalten und Publizieren von Fotos und Stammdaten
von Obstbäumen. Das Go-Modul heißt forge.23.nu/md/treedoc.
Bäume werden mit treephoto.app (iPhone) fotografiert, in treedoc redaktionell bearbeitet und als statisches Archiv nach S3 ausgespielt. Zusätzliche Quelle ist der L&F-Obsidian-Vault.
Schnellstart
# Systemabhängigkeiten (Debian/Ubuntu)
apt install libimage-exiftool-perl imagemagick
make build # React-UI + alle cmd/-Binaries nach bin/
./bin/treedoc # → http://localhost:8767
Konfiguration: config.yaml (Vorlage: config.yaml.example; enthält Secrets
und ist gitignored). Die DB-DSN kommt aus db_dsn bzw. TREEDOC_DB_DSN.
make check # fmt, vet, lint, typecheck, tests
make sandbox-seed N=10 && make sandbox-treedoc # Spielwiese auf :8768
Architektur, Paketstruktur und Datenflüsse: CLAUDE.md.
Installation und Betrieb: INSTALL.md, DEPLOY.md. Änderungen: CHANGELOG.md.
Statische Archiv-Seite (store/{id}/index.html)
Pro Baum wird bei jedem Speichern eine statische, dependency-freie HTML-Seite nach S3 geschrieben (Langzeit-Archiv, oEmbed-konform). Die Vorlage ist:
internal/treestore/tree-static.html.tmpl
Das ist eine Go-html/template-Datei und wird per //go:embed fest ins Binary
gebacken. Zum Ändern des Aussehens diese Datei bearbeiten und neu bauen
(make build bzw. go build ./...). Die Seite muss ohne JavaScript und ohne
externe Abhängigkeiten auskommen.
Die zugehörige oEmbed-Antwort (store/{id}/oembed.json) wird in Go erzeugt:
Funktion RenderOEmbed in internal/treestore/render.go.
Alternativ lässt sich zur Laufzeit eine andere Vorlage per Flag übergeben
(treedoc --template pfad/zur/vorlage.tmpl, ebenso cmd/render --template …);
ist der Pfad leer oder unlesbar, greift die eingebettete Vorlage.
Bestehende Seiten neu rendern (z. B. nach einer Template-Änderung):
go run ./cmd/render --base https://treedoc.foxel.org --prefix store # alle Bäume
go run ./cmd/rerender --base https://treedoc.foxel.org abc123 def456 # nur diese IDs