Allow users to export their game list as CSV #47

Closed
opened 2024-01-14 14:45:21 -06:00 by jimmyb · 2 comments
Owner

Users should be able to download their own MyVideoGameList game-list data as a CSV file.

The current Laravel checkout has game_lists persistence, a GameList model, owner-only update/delete policies, profile/header links reserving /list/{username}, and controller stubs for list pages and list entry management. The public/user list surface itself is not fully rebuilt yet, and there is no CSV export route. This issue tracks adding an authenticated, owner-only CSV export that includes the user’s active game-list entries and useful related game/platform metadata.

Scope

  • Authenticated current-user CSV export.
  • Active, non-deleted game_lists rows only.
  • Game and platform metadata available through existing relationships/IDs.
  • Export action/link from the user’s own list page once rebuilt.
  • Safe CSV formatting for notes and user-entered fields.
  • Existing Laravel response/download patterns.

Acceptance Criteria

  • Signed-in users can download a CSV export of their own game list.
  • Guests are redirected to login and cannot export.
  • Users cannot export another user’s private list data.
  • Exported rows exclude soft-deleted game-list entries.
  • Exported rows include useful columns such as game title, platform, ownership, status, rating, priority, difficulty, hours played, replay value, started date, finished date, replaying flag, notes, and source game ID.
  • Status, ownership, hours-played, replay-value, and other coded values are exported as readable labels where practical.
  • CSV output handles commas, quotes, newlines, formulas, and other user-entered content safely.
  • Empty lists produce a valid CSV with headers and no data rows.
  • The response uses an appropriate text/csv content type and a clear filename such as myvideogamelist-{username}-list.csv.
  • Deleted or disabled games do not break the export; unavailable related game/platform data falls back safely.
  • User-facing export controls support light/dark mode and follow existing Laravel/Tailwind list patterns when the list page is rebuilt.

Test Coverage Required

  • Feature test confirming an authenticated user can export their own list as CSV.
  • Feature test confirming guests cannot export.
  • Authorization test confirming users cannot export another user’s list.
  • Feature test confirming soft-deleted list rows are excluded.
  • Regression test confirming empty lists return a valid header-only CSV.
  • CSV safety tests for commas, quotes, newlines, and formula-like notes or titles.
  • Regression test confirming readable labels for coded list fields.
  • Regression test confirming missing/deleted game or platform data does not crash export.
  • Tests should use Pest and focused list/export coverage.
  • Run the focused export tests, then run vendor/bin/pint --dirty before closing the issue.

Progress Checklist

  • game_lists table exists
  • GameList model exists
  • Profile/header links reserve user list pages
  • Game-list owner update/delete policy checks exist
  • Game-list rows store status, rating, notes, dates, and platform IDs
  • Add authenticated CSV export route/action
  • Authorize export for the current user only
  • Build query for active list rows with game/platform data
  • Map coded list values to readable CSV labels
  • Generate safe streamed CSV response and filename
  • Add export link/control to the owner’s list page when rebuilt
  • Add tests for export content, authorization, empty lists, soft deletes, CSV escaping, and missing related data
  • Confirm CSV export fits the rebuilt list-page workflow

Implementation and verification — 2026-10-27

Owner-only CSV and JSON downloads now stream the complete active list in bounded batches, with readable labels, safe CSV cells, null-safe related metadata, private cache headers, and owner-page export controls.

Local branch: codex/issue-47-853-game-list-export-search, based on refreshed origin/master. Changes are local and awaiting review; no PR, merge, push, or deployment has been performed.

Validation:

  • php artisan test --env=testing --compact tests/Feature/GameListPageTest.php tests/Feature/GameListExportTest.php tests/Feature/UserPrivacyTest.php — 224 tests passed, 2,670 assertions (SQLite).
  • vendor/bin/pint --dirty --format agent — passed.
  • composer stan — passed with zero errors.
  • npm run build — passed.
  • node_modules/.bin/playwright test tests/browser/game-list-sort.spec.js --workers=1 --output=/tmp/mvgl-list-browser-final — all 8 browser tests passed at 375px/1440px for owner/public views, with no application console errors. Light/dark screenshots inspected.

Browser checks use isolated in-memory SQLite fixtures and stub external assets. MariaDB CI and live-environment validation have not run. The issue remains open in progress pending review.

Acceptance re-review — 2026-10-27

All export acceptance criteria and required test categories are covered. The export includes every listed data field, keeps IDs, maps all six stored statuses, all four ownership codes and all thirteen hours-played bands, and safely handles missing/deleted related records. Replay value remains the numeric 1–5 scale displayed by the existing form; the replaying flag is Yes/No in CSV and boolean in JSON. Authorization regression fixtures now explicitly make both users’ lists private and confirm that target-user query parameters cannot change whose list is downloaded. Additional mapping tests cover every export field, ISO dates, false replaying flags and null values.

Verification after the search fix and expanded coverage:

  • Focused list/export/privacy suite: 230 tests passed, 3,078 assertions (SQLite).
  • Export suite rerun after making authorization fixtures explicitly private: all 19 tests passed, 440 assertions.
  • Pint and PHPStan passed; git diff --check passed.
  • All 8 game-list browser tests passed again at 375px/1440px for owner/public views.
  • The prior asset build remains valid; this re-review changed backend search and tests only.

All progress checkboxes are now complete. Implementation remains local and uncommitted on codex/issue-47-853-game-list-export-search, awaiting user review. No PR, push, merge, deployment or issue closure was performed. MariaDB CI and live-environment validation remain unrun.

Users should be able to download their own MyVideoGameList game-list data as a CSV file. The current Laravel checkout has `game_lists` persistence, a `GameList` model, owner-only update/delete policies, profile/header links reserving `/list/{username}`, and controller stubs for list pages and list entry management. The public/user list surface itself is not fully rebuilt yet, and there is no CSV export route. This issue tracks adding an authenticated, owner-only CSV export that includes the user’s active game-list entries and useful related game/platform metadata. ## Scope - Authenticated current-user CSV export. - Active, non-deleted `game_lists` rows only. - Game and platform metadata available through existing relationships/IDs. - Export action/link from the user’s own list page once rebuilt. - Safe CSV formatting for notes and user-entered fields. - Existing Laravel response/download patterns. ## Acceptance Criteria - Signed-in users can download a CSV export of their own game list. - Guests are redirected to login and cannot export. - Users cannot export another user’s private list data. - Exported rows exclude soft-deleted game-list entries. - Exported rows include useful columns such as game title, platform, ownership, status, rating, priority, difficulty, hours played, replay value, started date, finished date, replaying flag, notes, and source game ID. - Status, ownership, hours-played, replay-value, and other coded values are exported as readable labels where practical. - CSV output handles commas, quotes, newlines, formulas, and other user-entered content safely. - Empty lists produce a valid CSV with headers and no data rows. - The response uses an appropriate `text/csv` content type and a clear filename such as `myvideogamelist-{username}-list.csv`. - Deleted or disabled games do not break the export; unavailable related game/platform data falls back safely. - User-facing export controls support light/dark mode and follow existing Laravel/Tailwind list patterns when the list page is rebuilt. ## Test Coverage Required - Feature test confirming an authenticated user can export their own list as CSV. - Feature test confirming guests cannot export. - Authorization test confirming users cannot export another user’s list. - Feature test confirming soft-deleted list rows are excluded. - Regression test confirming empty lists return a valid header-only CSV. - CSV safety tests for commas, quotes, newlines, and formula-like notes or titles. - Regression test confirming readable labels for coded list fields. - Regression test confirming missing/deleted game or platform data does not crash export. - Tests should use Pest and focused list/export coverage. - Run the focused export tests, then run `vendor/bin/pint --dirty` before closing the issue. ## Progress Checklist - [x] `game_lists` table exists - [x] `GameList` model exists - [x] Profile/header links reserve user list pages - [x] Game-list owner update/delete policy checks exist - [x] Game-list rows store status, rating, notes, dates, and platform IDs - [x] Add authenticated CSV export route/action - [x] Authorize export for the current user only - [x] Build query for active list rows with game/platform data - [x] Map coded list values to readable CSV labels - [x] Generate safe streamed CSV response and filename - [x] Add export link/control to the owner’s list page when rebuilt - [x] Add tests for export content, authorization, empty lists, soft deletes, CSV escaping, and missing related data - [x] Confirm CSV export fits the rebuilt list-page workflow ## Implementation and verification — 2026-10-27 Owner-only CSV and JSON downloads now stream the complete active list in bounded batches, with readable labels, safe CSV cells, null-safe related metadata, private cache headers, and owner-page export controls. Local branch: `codex/issue-47-853-game-list-export-search`, based on refreshed `origin/master`. Changes are local and awaiting review; no PR, merge, push, or deployment has been performed. Validation: - `php artisan test --env=testing --compact tests/Feature/GameListPageTest.php tests/Feature/GameListExportTest.php tests/Feature/UserPrivacyTest.php` — 224 tests passed, 2,670 assertions (SQLite). - `vendor/bin/pint --dirty --format agent` — passed. - `composer stan` — passed with zero errors. - `npm run build` — passed. - `node_modules/.bin/playwright test tests/browser/game-list-sort.spec.js --workers=1 --output=/tmp/mvgl-list-browser-final` — all 8 browser tests passed at 375px/1440px for owner/public views, with no application console errors. Light/dark screenshots inspected. Browser checks use isolated in-memory SQLite fixtures and stub external assets. MariaDB CI and live-environment validation have not run. The issue remains open in progress pending review. ## Acceptance re-review — 2026-10-27 All export acceptance criteria and required test categories are covered. The export includes every listed data field, keeps IDs, maps all six stored statuses, all four ownership codes and all thirteen hours-played bands, and safely handles missing/deleted related records. Replay value remains the numeric 1–5 scale displayed by the existing form; the replaying flag is Yes/No in CSV and boolean in JSON. Authorization regression fixtures now explicitly make both users’ lists private and confirm that target-user query parameters cannot change whose list is downloaded. Additional mapping tests cover every export field, ISO dates, false replaying flags and null values. Verification after the search fix and expanded coverage: - Focused list/export/privacy suite: 230 tests passed, 3,078 assertions (SQLite). - Export suite rerun after making authorization fixtures explicitly private: all 19 tests passed, 440 assertions. - Pint and PHPStan passed; git diff --check passed. - All 8 game-list browser tests passed again at 375px/1440px for owner/public views. - The prior asset build remains valid; this re-review changed backend search and tests only. All progress checkboxes are now complete. Implementation remains local and uncommitted on codex/issue-47-853-game-list-export-search, awaiting user review. No PR, push, merge, deployment or issue closure was performed. MariaDB CI and live-environment validation remain unrun.
Codex changed title from Allow Users to Export List Data as CSV to Allow users to export their game list as CSV 2026-05-26 01:03:54 -05:00
Codex self-assigned this 2026-10-27 14:00:04 -05:00
Member

Merged in PR #1001 at 7d34d5ab.

  • Owners can download their complete active list as CSV or JSON from either their own list page or their public list URL. Search, status selection, sorting and loaded pages do not limit exports.
  • Exports are authenticated and always scoped to the signed-in user. CSV neutralizes formula-like cells and preserves quoted/multiline text; JSON retains original text. Missing/deleted game or platform metadata cannot prevent a download. Replay value stays on the existing numeric 1–5 scale.
  • Files stream in bounded batches. No database migrations or dependency changes are required for this feature.
  • Verification: 230 list/export/privacy tests (3,078 assertions), 8 desktop/mobile browser tests, Pint, PHPStan, asset build and diff checks passed. All issue checkboxes are complete.

Dev and production deployment is now being performed; deployment verification and rollback locations will follow.

Merged in PR #1001 at `7d34d5ab`. - Owners can download their complete active list as CSV or JSON from either their own list page or their public list URL. Search, status selection, sorting and loaded pages do not limit exports. - Exports are authenticated and always scoped to the signed-in user. CSV neutralizes formula-like cells and preserves quoted/multiline text; JSON retains original text. Missing/deleted game or platform metadata cannot prevent a download. Replay value stays on the existing numeric 1–5 scale. - Files stream in bounded batches. No database migrations or dependency changes are required for this feature. - Verification: 230 list/export/privacy tests (3,078 assertions), 8 desktop/mobile browser tests, Pint, PHPStan, asset build and diff checks passed. All issue checkboxes are complete. Dev and production deployment is now being performed; deployment verification and rollback locations will follow.
Member

PR #1001 is now deployed to development and production from merge revision 7d34d5ab62e2ff6e3fef4a0f2107f7f047737f8d.

  • Installed the 10 feature runtime/source files plus the Vite manifest and versioned JS/CSS assets. Rebuilt route and Blade caches, verified all deployed file checksums, and preserved 440 unrelated runtime/configuration/dependency files per environment. No migrations or dependency installations were needed.
  • Read-only MariaDB smoke tests passed on both hosts: owner-scoped CSV and JSON returned the expected 11 entries, all exported IDs belonged to the authenticated owner, the export route requires authentication, and searched All views rendered correctly for matching and empty queries. The smoke tests ran inside read-only transactions and did not alter user data.
  • Live HTTPS checks passed on both hosts: homepage and searched public lists returned 200, public lists remained read-only, guest CSV/JSON requests returned 302 to login, and publicly served asset checksums matched the package. Production's edge rejected an initial Python-default-header probe; normal HTML/browser-style requests passed without any edge configuration changes.
  • Release manifests record the scoped rollout as ee6b2847+issue992-3d129125+pr1000-c0341df2+pr1001-7d34d5ab, preserving the actual deployed baseline rather than claiming unrelated master dependency updates were installed.

Rollback backups (original files, checksums and deployment receipts):

  • Dev: /home/mvgldev/deploy-backups/pr1001-7d34d5ab-fa4rd7lv
  • Production: /home/mvgl/deploy-backups/pr1001-7d34d5ab-0opyeowo

Local checkout is clean on master at the merge revision. All progress checkboxes remain checked; this issue is closed with status/done.

PR #1001 is now deployed to development and production from merge revision `7d34d5ab62e2ff6e3fef4a0f2107f7f047737f8d`. - Installed the 10 feature runtime/source files plus the Vite manifest and versioned JS/CSS assets. Rebuilt route and Blade caches, verified all deployed file checksums, and preserved 440 unrelated runtime/configuration/dependency files per environment. No migrations or dependency installations were needed. - Read-only MariaDB smoke tests passed on both hosts: owner-scoped CSV and JSON returned the expected 11 entries, all exported IDs belonged to the authenticated owner, the export route requires authentication, and searched All views rendered correctly for matching and empty queries. The smoke tests ran inside read-only transactions and did not alter user data. - Live HTTPS checks passed on both hosts: homepage and searched public lists returned 200, public lists remained read-only, guest CSV/JSON requests returned 302 to login, and publicly served asset checksums matched the package. Production's edge rejected an initial Python-default-header probe; normal HTML/browser-style requests passed without any edge configuration changes. - Release manifests record the scoped rollout as `ee6b2847+issue992-3d129125+pr1000-c0341df2+pr1001-7d34d5ab`, preserving the actual deployed baseline rather than claiming unrelated master dependency updates were installed. Rollback backups (original files, checksums and deployment receipts): - Dev: `/home/mvgldev/deploy-backups/pr1001-7d34d5ab-fa4rd7lv` - Production: `/home/mvgl/deploy-backups/pr1001-7d34d5ab-0opyeowo` Local checkout is clean on `master` at the merge revision. All progress checkboxes remain checked; this issue is closed with `status/done`.
Sign in to join this conversation.
No milestone
No assignees
2 participants
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
MyVideoGameList/myvideogamelist.com#47
No description provided.