CartoDB's positron basemap now renders an "API KEY REQUIRED" watermark. Use tiles="OpenStreetMap" via a new MAP_TILES constant instead. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
5.3 KiB
Overview – what the app does
The app is a single window: a DRK-red header bar, two tabs, and a
colour-coded status bar at the bottom (grey = neutral, green = success,
orange = warning, red = error; transient messages fade back to neutral after
~8 s). The window title shows the total entry count, and the window remembers
its size and position between sessions (data/window.json). The UI font is
enlarged for readability (UI_FONT_SIZE).
Tab 1 – "Neuer Eintrag" (new entry)
Workflow: build up a queue of entries, let them geocode in the background, then save the whole batch at once.
- Entry form – date (a calendar picker,
ttkbootstrap.DateEntry, pre-filled with today; typed input is accepted inJJJJ-MM-TTorTT.MM.JJJJand validated – an invalid date is rejected with a dialog), city (autocomplete combobox), postal code (optional). PressingReturnin any field, or the + Hinzufügen button, adds the row to the queue. The PLZ field only accepts digits. - Queue table – shows date, city, PLZ, and a live coordinate column that
updates from
⏳ wird gesucht…to eitherlat / lonor⚠ nicht gefundenas the background geocoder works through the queue.- Select a row and press Delete, use the "Auswahl entfernen"
button, or click the
✕cell. - Right-click a row for Löschen / Koordinaten erneut suchen.
- Select a row and press Delete, use the "Auswahl entfernen"
button, or click the
- Action bar
- Alle speichern – appends every queued row to
orte.csv. If any row looks like a duplicate (same date + city + PLZ), a modal lists them and asks whether to save anyway. - Warteschlange leeren – discards the queue (asks for confirmation).
- Karte öffnen – regenerates
karte.htmland opens it in the browser.
- Alle speichern – appends every queued row to
Tab 2 – "Einträge verwalten" (manage entries)
A table view of everything in orte.csv.
- Columns: Datum, Ort, PLZ, and Karte – a status column showing
✓when the row has coordinates or a redfehltwhen it doesn't (the whole row is red too). The raw lat/lon numbers live in the edit dialog, not this table. - Search box – live filter across date, city, and PLZ (substring match).
- Sortable columns – click a header to sort; clicking again reverses. The active column shows a ▲/▼ arrow. Default sort is by date, newest first. Sorting by Karte groups the rows without coordinates together.
- "Nur ohne Koordinaten" toggle – filters to entries that have no coordinates yet. The hint line always shows the total count, plus how many are missing coordinates.
- Edit – double-click a row (or Bearbeiten) opens a modal dialog to change date (calendar picker, validated) / city / PLZ. Two ways to fix coordinates: a "Koordinaten automatisch neu suchen" toggle re-runs geocoding after saving, or the Breitengrad / Längengrad fields let you type them in by hand (both empty = no map marker).
- Right-click → Koordinaten suchen – runs geocoding for that one row (handy for rows that failed the first time).
- Delete – Löschen removes the selected row(s) after a confirmation
dialog. This is irreversible, but a timestamped copy of the file is
written to
data/backups/before every change (see data-model.md). - Karte öffnen – same as on Tab 1.
The map (karte.html)
Generated by generate_map():
- Base layer: OpenStreetMap standard tiles (
MAP_TILES) – no API key. Initial view centred on[49.0, 9.0], zoom 8 (roughly Baden-Württemberg); the view auto-fits to the markers when there is more than one. - One
CircleMarkerper unique(city, lat, lon)group. Radius scales linearly with the visit count for that location (5 + count / max_count * 20px), colour is DRK red (#CC0000). - Popup shows the city and the visit count; tooltip shows the city.
- Rows with missing/blank coordinates are silently excluded.
- If there are no usable coordinates at all, a dialog says so (and the status bar shows a warning).
The generated HTML pulls Leaflet, jQuery and Bootstrap from CDNs, and the map tiles from
tile.openstreetmap.org, so the map needs an internet connection to render even though the data is local. To change the look, setMAP_TILESnear the top ofapp.pyto another no-key provider Folium knows ("OpenStreetMap","CartoDB positron"now needs a key, or a customfolium.TileLayerURL such as OSM Germany / OSM France).
Geocoding behaviour
geocode_city(city, postal_code) tries a series of queries in order and returns
the first hit:
"<PLZ> <city>, Germany"(only if a PLZ was given)"<city>, Baden-Württemberg, Germany""<city>, Hessen, Germany""<city>, Germany"
The regional bias is the GEOCODE_REGIONS constant (Baden-Württemberg,
Hessen) near the top of app.py. Results are rounded to five decimal places.
Nominatim's usage policy (max 1 req/s, identifying user_agent) is respected by
a manual time.sleep(1) in the worker loop.
If the geocoding service is unreachable (no internet), entries still save –
without coordinates – and after a few consecutive failures a one-time dialog
explains that the coordinates can be added later via Bearbeiten. The worker
thread logs failures to data/app.log and keeps running.