feat(feedback): thread page_path through form + display in admin row + CSV export #106

Merged
YousifShkara merged 1 commit from feat/feedback-page-path-and-csv-export into main 2026-06-11 05:32:29 +02:00
Owner

Closes BUNYIP-84. First of a planned three-PR feedback parity series.

bunyip-api already supports page_path on submissions (handlers/feedback.rs:123, 204, 244) and ships a CSV export endpoint (handlers/feedback.rs:497-537 routed at routes/admin.rs:116). The SSR layer in bunyip-web simply did not surface either.

page_path threading:

  • bunyip-web/src/handlers/content.rs::feedback_get now accepts a Query<FeedbackQuery> with a single optional from field. When present and sane (starts with /, len <= 255 to match the API validation), it is rendered as a hidden page_path input on the form so the submit round-trips it to the API. Anything else (open-redirect-shaped, oversize) is silently dropped.
  • parse_feedback_form now reads the page_path field from the body and falls back to the existing /feedback default when absent. The same sanitize_page_path helper rejects malformed values.
  • feedback_post round-trips the captured path back into the rendered form on an error redraw so a typo on the message field does not strip context after the first failed submit.
  • The floating launcher's ?from= carry-through is a follow-up PR because it requires threading current_path: &str through dashboard_shell / public_shell and updating five call sites.

Admin row page_path display:

  • crates/bunyip-domain/src/models/feedback.rs::AdminFeedbackSummary gains a page_path: Option<String> field, populated by to_admin_summary from the existing Feedback.page_path column. Forward-compatible: serde defaults to None on rolling deploys.
  • bunyip-web/src/api/types.rs::AdminFeedbackSummary mirrors the field with #[serde(default)] so an older API still deserializes.
  • Admin feedback row template (bunyip-web/src/handlers/admin.rs::feedback) shows a small "From: " line under the identity row. The default /feedback value is suppressed (the form's own URL is noise); empty values are suppressed too.

CSV export:

  • New "Export CSV" button in the admin feedback page header.
  • New BFF proxy handler feedback_export at GET /admin/feedback/export that mirrors the existing download_asset pattern: re-auth via admin_guard, forward the session cookie to bunyip-api's /admin/feedback/export, stream the response body back with the upstream Content-Type / Content-Disposition so the browser drives the download. 401 forces re-auth; any other non-2xx bounces back to the feedback list so the browser never saves an error blob as feedback.csv.
  • Route registered in bunyip-web/src/main.rs next to the existing feedback routes.

just check-container clean (modulo the pre-existing test_config_defaults parallel-env-var flake on main, unrelated; 188 other tests pass; fmt + clippy + build clean).

#BUNYIP-84

Closes BUNYIP-84. First of a planned three-PR feedback parity series. bunyip-api already supports page_path on submissions (handlers/feedback.rs:123, 204, 244) and ships a CSV export endpoint (handlers/feedback.rs:497-537 routed at routes/admin.rs:116). The SSR layer in bunyip-web simply did not surface either. page_path threading: - `bunyip-web/src/handlers/content.rs::feedback_get` now accepts a `Query<FeedbackQuery>` with a single optional `from` field. When present and sane (starts with `/`, len <= 255 to match the API validation), it is rendered as a hidden `page_path` input on the form so the submit round-trips it to the API. Anything else (open-redirect-shaped, oversize) is silently dropped. - `parse_feedback_form` now reads the `page_path` field from the body and falls back to the existing `/feedback` default when absent. The same `sanitize_page_path` helper rejects malformed values. - `feedback_post` round-trips the captured path back into the rendered form on an error redraw so a typo on the message field does not strip context after the first failed submit. - The floating launcher's `?from=` carry-through is a follow-up PR because it requires threading `current_path: &str` through `dashboard_shell` / `public_shell` and updating five call sites. Admin row page_path display: - `crates/bunyip-domain/src/models/feedback.rs::AdminFeedbackSummary` gains a `page_path: Option<String>` field, populated by `to_admin_summary` from the existing `Feedback.page_path` column. Forward-compatible: serde defaults to `None` on rolling deploys. - `bunyip-web/src/api/types.rs::AdminFeedbackSummary` mirrors the field with `#[serde(default)]` so an older API still deserializes. - Admin feedback row template (`bunyip-web/src/handlers/admin.rs::feedback`) shows a small "From: <path>" line under the identity row. The default `/feedback` value is suppressed (the form's own URL is noise); empty values are suppressed too. CSV export: - New "Export CSV" button in the admin feedback page header. - New BFF proxy handler `feedback_export` at `GET /admin/feedback/export` that mirrors the existing `download_asset` pattern: re-auth via `admin_guard`, forward the session cookie to bunyip-api's `/admin/feedback/export`, stream the response body back with the upstream `Content-Type` / `Content-Disposition` so the browser drives the download. 401 forces re-auth; any other non-2xx bounces back to the feedback list so the browser never saves an error blob as `feedback.csv`. - Route registered in `bunyip-web/src/main.rs` next to the existing feedback routes. `just check-container` clean (modulo the pre-existing `test_config_defaults` parallel-env-var flake on `main`, unrelated; 188 other tests pass; fmt + clippy + build clean). #BUNYIP-84
feat(feedback): thread page_path through form + display in admin row + CSV export
All checks were successful
Create release / Create release from merged PR (pull_request) Has been skipped
Check / fmt / clippy / build / test (pull_request) Successful in 1m11s
dc541302c6
Closes BUNYIP-84. First of a planned three-PR feedback parity series.

bunyip-api already supports page_path on submissions (handlers/feedback.rs:123, 204, 244) and ships a CSV export endpoint (handlers/feedback.rs:497-537 routed at routes/admin.rs:116). The SSR layer in bunyip-web simply did not surface either.

page_path threading:

- `bunyip-web/src/handlers/content.rs::feedback_get` now accepts a `Query<FeedbackQuery>` with a single optional `from` field. When present and sane (starts with `/`, len <= 255 to match the API validation), it is rendered as a hidden `page_path` input on the form so the submit round-trips it to the API. Anything else (open-redirect-shaped, oversize) is silently dropped.
- `parse_feedback_form` now reads the `page_path` field from the body and falls back to the existing `/feedback` default when absent. The same `sanitize_page_path` helper rejects malformed values.
- `feedback_post` round-trips the captured path back into the rendered form on an error redraw so a typo on the message field does not strip context after the first failed submit.
- The floating launcher's `?from=` carry-through is a follow-up PR because it requires threading `current_path: &str` through `dashboard_shell` / `public_shell` and updating five call sites.

Admin row page_path display:

- `crates/bunyip-domain/src/models/feedback.rs::AdminFeedbackSummary` gains a `page_path: Option<String>` field, populated by `to_admin_summary` from the existing `Feedback.page_path` column. Forward-compatible: serde defaults to `None` on rolling deploys.
- `bunyip-web/src/api/types.rs::AdminFeedbackSummary` mirrors the field with `#[serde(default)]` so an older API still deserializes.
- Admin feedback row template (`bunyip-web/src/handlers/admin.rs::feedback`) shows a small "From: <path>" line under the identity row. The default `/feedback` value is suppressed (the form's own URL is noise); empty values are suppressed too.

CSV export:

- New "Export CSV" button in the admin feedback page header.
- New BFF proxy handler `feedback_export` at `GET /admin/feedback/export` that mirrors the existing `download_asset` pattern: re-auth via `admin_guard`, forward the session cookie to bunyip-api's `/admin/feedback/export`, stream the response body back with the upstream `Content-Type` / `Content-Disposition` so the browser drives the download. 401 forces re-auth; any other non-2xx bounces back to the feedback list so the browser never saves an error blob as `feedback.csv`.
- Route registered in `bunyip-web/src/main.rs` next to the existing feedback routes.

`just check-container` clean (modulo the pre-existing `test_config_defaults` parallel-env-var flake on `main`, unrelated; 188 other tests pass; fmt + clippy + build clean).

#BUNYIP-84
YousifShkara deleted branch feat/feedback-page-path-and-csv-export 2026-06-11 05:32:29 +02:00
Sign in to join this conversation.
No reviewers
No labels
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
psa-systems/bunyip!106
No description provided.