integrate edit button into astro site

This commit is contained in:
Davide Scaini
2026-03-29 15:39:11 +02:00
parent 1d3848f85e
commit b0ab7fbe3f
6 changed files with 409 additions and 55 deletions
+50 -42
View File
@@ -199,44 +199,46 @@ Sidecars work for *remote* activities too: if you include someone else's BAS fee
you can write local `.md` sidecars for their activity IDs. Your render stage applies
your overrides on top of their data. This is a natural extension of the local case.
### Editing UX: `bincio edit --serve`
### Editing UX: drawer in Astro + `bincio edit` write API
A separate FastAPI server (`bincio edit --serve`, default port 4041) handles all writes.
The static site and Astro are untouched — no hybrid mode, no dead-code API routes in prod.
The edit UI is a **slide-in drawer** (`EditDrawer.svelte`) in the Astro site.
The drawer fetches from and POSTs to the `bincio edit` FastAPI server (write API only —
the server no longer serves its own HTML UI).
**How it works:**
```
bincio edit --serve --data ~/bincio_data # starts on :4041
bincio render --serve # Astro dev server, port 4321
bincio edit --data-dir ~/… # write API only, port 4041
```
- Serves a bundled Svelte UI (single compiled HTML, reuses existing Svelte investment)
- `GET /api/activity/{id}` — returns merged BAS JSON + existing sidecar fields
- `POST /api/activity/{id}` — writes `edits/{id}.md` to the data dir
- Edit button appears on the activity detail page **only when `PUBLIC_EDIT_URL` is set** in `site/.env`
- Clicking Edit opens the drawer in the same page — no navigation, no copy-pasting IDs
- Drawer fetches `GET /api/activity/{id}` to pre-fill, `POST /api/activity/{id}` to save
- After save: server runs `merge_all()` automatically → Astro serves updated data immediately on refresh
- Closing the drawer applies `title` + `description` changes optimistically to the local page state
(no full reload required to see the text change)
**`PUBLIC_EDIT_URL` as feature flag:**
- **Unset** → no Edit button, no drawer. Works as a normal static site. Safe for public hosting.
- **Set** (e.g. `http://localhost:4041`) → editing enabled. Lives in `site/.env` (gitignored).
Each deployment opts in explicitly.
**Edit server API (`bincio edit --data-dir <dir>`):**
- `GET /api/activity/{id}` — current values (sidecar overrides layered on BAS JSON)
- `POST /api/activity/{id}` — write sidecar `.md`, trigger `merge_all()`
- `POST /api/activity/{id}/images` — multipart upload → `edits/images/{id}/{filename}`
- The Astro dev server's file watcher picks up `.md` writes → incremental rebuild
- `DELETE /api/activity/{id}/images/{filename}` — remove uploaded image
**Edit UI features:**
- Title text input (pre-filled from BAS JSON)
- Sport dropdown (pre-filled, shows all known sport types)
- Markdown textarea for description, with minimal toolbar (bold, italic, link, image insert)
- Live markdown preview panel
- `hide_stats` checkbox group: elevation, speed, heart_rate, cadence, power
- `highlight` toggle (feature in feed)
- `private` toggle (suppress from feed at render time)
- Image drag-and-drop zone → uploads to `edits/images/{id}/`, inserts `![]()` into textarea
- Save button → POST to API → success toast
**Edit drawer features:**
- Title, sport dropdown, gear
- Markdown textarea for description (images inserted as `![name](filename)` references)
- Image drag-and-drop zone with chip list + delete
- Hide stat panels (elevation, speed, heart_rate, cadence, power) — toggle buttons
- Highlight flag (★ — sorts to top of feed, visual badge)
- Private flag (⊘ — suppressed from index at render time)
**Workflow (typical):**
1. User browses the Astro dev server on :4040
2. Activity detail page has an "Edit" button (rendered only when `PUBLIC_EDIT_URL` env var is set)
3. Button links to `:4041/edit/{id}` — opens the FastAPI-served edit UI
4. User fills in form, saves → sidecar written → Astro rebuilds → refreshing :4040 shows changes
The `PUBLIC_EDIT_URL` env var in `.env` controls whether the Edit button appears;
leave it unset for production builds, set to `http://localhost:4041` for local dev.
### Image storage
### Image storage and serving
```
~/bincio_data/
@@ -249,17 +251,20 @@ leave it unset for production builds, set to `http://localhost:4041` for local d
```
Images are referenced in the markdown body with relative paths: `![Summit](col-summit.jpg)`.
The render stage resolves relative image paths against `edits/images/{id}/` and copies them
to `site/public/images/activities/{id}/` so they're served from the static site.
`merge_all()` symlinks `edits/images/{id}/``_merged/activities/images/{id}/` so images
are served at `data/activities/images/{id}/{filename}` by the Astro dev server.
`ActivityDetail.svelte` rewrites relative image paths to this URL when rendering markdown.
**Note:** browsers cannot display `.HEIC` files. Convert to JPEG/PNG first:
`sips -s format jpeg photo.HEIC --out photo.jpg` (macOS).
### Decided
- **Sidecar location**: `edits/` subdirectory (not co-located with JSON) — cleaner, easier to
backup/sync just your customisations independently of the extracted data
- **`private: true`**: suppresses from `index.json` at render time (not client-side hide)
safer for public hosting
- **`highlight`**: visual badge in feed + sorted before non-highlighted activities
- **Edit UI**: `bincio edit --serve` FastAPI server (Option B) — not integrated into Astro
- **Sidecar location**: `edits/` subdirectory — cleaner, easier to backup/sync independently
- **Merge output**: `data/_merged/` — extracted data stays pristine; `public/data``_merged/`
- **`private: true`**: suppressed from `index.json` at render time (not client-side hide)
- **`highlight`**: sorts to top of feed; visual badge TBD
- **Edit UI**: drawer in Astro site, `bincio edit` is a pure write API (no HTML serving)
## Known issues / next steps
@@ -282,9 +287,12 @@ to `site/public/images/activities/{id}/` so they're served from the static site.
- [ ] Map thumbnail in activity cards (SVG path from GeoJSON)
- [ ] GitHub Actions template for auto-publish
- [ ] Karoo/Garmin Connect importers beyond Strava
- [ ] `bincio.render.merge` module: walk `edits/`, parse sidecars, produce enriched data for Astro
- [ ] `bincio render --watch` incremental rebuild on sidecar changes
- [ ] Sidecar `.md` format: title, sport, description, hide_stats, highlight, private, images
- [ ] `bincio edit --serve` FastAPI server with Svelte edit UI (port 4041)
- [ ] Edit button on activity detail pages (visible when `PUBLIC_EDIT_URL` env var set)
- [ ] Image upload → `edits/images/{id}/`, render stage copies to `public/images/activities/{id}/`
- [x] `bincio.render.merge` — sidecar parser, `_merged/` output, private filter, highlight sort
- [x] `bincio edit` FastAPI write API (GET/POST activity, image upload/delete, triggers merge)
- [x] `EditDrawer.svelte` — slide-in edit UI in the Astro site (no separate HTML from server)
- [x] `PUBLIC_EDIT_URL` feature flag — unset = no edit UI, set = drawer enabled
- [x] Markdown rendering in activity description with image path rewriting
- [x] `hide_stats` support in activity detail stats panel
- [ ] `bincio render --watch` incremental rebuild on sidecar/data changes
- [ ] Highlight badge in activity feed cards
- [ ] Image format warning (HEIC → JPEG conversion hint in the upload UI)