feat: in-app feedback FAB #18

Merged
pyr0ball merged 1 commit from feature/feedback-button into main 2026-04-03 22:01:07 -07:00
Owner

Summary

  • GET /api/feedback/status — probed on mount; returns {enabled: bool}; hidden when FORGEJO_API_TOKEN unset or DEMO_MODE true
  • POST /api/feedback — creates Forgejo issue with type/title/description/repro steps + view, version, platform context; 503 without token, 403 in demo mode
  • FeedbackButton.vue — 2-step modal (type → review/attribution → submit); starts hidden, shows after status probe confirms enabled; Teleported to body to avoid z-index/overflow clipping
  • App.vue — mounts FeedbackButton with route.name as view context
  • .env.example — documents FORGEJO_API_TOKEN, FORGEJO_REPO, FORGEJO_API_URL

Ported from kiwi (Circuit-Forge/kiwi#14) with snipe adaptations:

  • Route prefix /api/ (not /api/v1/)
  • view field instead of tab in context
  • Route name via useRoute() (RouterView pattern vs kiwi tab state)

Test plan

  • Set FORGEJO_API_TOKEN in .env — confirm FAB appears on load
  • Leave token unset — confirm FAB stays hidden
  • Submit bug report → verify Forgejo issue created in Circuit-Forge/snipe with beta-feedback + needs-triage + bug labels
  • Submit in demo mode → confirm 403 response
  • Check FAB positioning on mobile (above bottom nav) and desktop (bottom-right corner)
## Summary - `GET /api/feedback/status` — probed on mount; returns `{enabled: bool}`; hidden when `FORGEJO_API_TOKEN` unset or `DEMO_MODE` true - `POST /api/feedback` — creates Forgejo issue with type/title/description/repro steps + view, version, platform context; 503 without token, 403 in demo mode - `FeedbackButton.vue` — 2-step modal (type → review/attribution → submit); starts hidden, shows after status probe confirms enabled; Teleported to body to avoid z-index/overflow clipping - `App.vue` — mounts `FeedbackButton` with `route.name` as view context - `.env.example` — documents `FORGEJO_API_TOKEN`, `FORGEJO_REPO`, `FORGEJO_API_URL` Ported from kiwi (Circuit-Forge/kiwi#14) with snipe adaptations: - Route prefix `/api/` (not `/api/v1/`) - `view` field instead of `tab` in context - Route name via `useRoute()` (RouterView pattern vs kiwi tab state) ## Test plan - [ ] Set `FORGEJO_API_TOKEN` in `.env` — confirm FAB appears on load - [ ] Leave token unset — confirm FAB stays hidden - [ ] Submit bug report → verify Forgejo issue created in Circuit-Forge/snipe with beta-feedback + needs-triage + bug labels - [ ] Submit in demo mode → confirm 403 response - [ ] Check FAB positioning on mobile (above bottom nav) and desktop (bottom-right corner)
pyr0ball added 3 commits 2026-04-03 19:06:05 -07:00
Wires circuitforge_core.tasks.scheduler into Snipe. Adds trust_photo_analysis
background task: downloads primary listing photo, calls LLMRouter with vision
capability, writes result to trust_scores.photo_analysis_json (Paid tier).
photo_analysis_json column already existed in 001_init.sql migration.
- Rename 002_background_tasks.sql → 007_background_tasks.sql to avoid
  collision with existing 002_add_listing_format.sql migration
- Add CREATE UNIQUE INDEX on trust_scores(listing_id) in same migration
  so save_trust_scores() can use ON CONFLICT upsert semantics
- Add Store.save_trust_scores() — upserts scores keyed by listing_id;
  preserves photo_analysis_json so runner writes are never clobbered
- runner.py: replace raw sqlite3.connect() with get_connection() throughout
  (timeout=30 + WAL mode); fix connection leak in insert_task via try/finally
- _run_trust_photo_analysis: read 'user_db' from params to write results to
  the correct per-user DB in cloud mode (was silently writing to wrong DB)
- main.py lifespan: use _shared_db_path() in cloud mode so background_tasks
  queue lives in shared DB, not _LOCAL_SNIPE_DB
- Add _enqueue_vision_tasks() and call it after score_batch() — this is the
  missing enqueue call site; gated by features.photo_analysis (Paid tier)
- Test fixture: add missing 'stage' column to background_tasks schema
- api/main.py: GET /api/feedback/status + POST /api/feedback — creates
  Forgejo issues; disabled (503) when FORGEJO_API_TOKEN unset, 403 in
  demo mode; includes view, version, platform context in issue body
- FeedbackButton.vue: 2-step modal (type → review → submit); probes
  /api/feedback/status on mount, stays hidden until confirmed enabled
- App.vue: mount FeedbackButton with current route name as view context;
  import useRoute for reactive route name tracking
- .env.example: document FORGEJO_API_TOKEN / FORGEJO_REPO / FORGEJO_API_URL
pyr0ball force-pushed feature/feedback-button from 1de9b43493 to 0617fc8256 2026-04-03 21:42:33 -07:00 Compare
pyr0ball merged commit 3f7c2b9135 into main 2026-04-03 22:01:07 -07:00
Sign in to join this conversation.
No reviewers
No labels
backlog
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: Circuit-Forge/snipe#18
No description provided.