Skip to content

release/v0.1.12-phase12-recent-conversions-table#181

Merged
menvil merged 36 commits into
mainfrom
release/v0.1.12-phase12-recent-conversions-table
Jun 2, 2026
Merged

release/v0.1.12-phase12-recent-conversions-table#181
menvil merged 36 commits into
mainfrom
release/v0.1.12-phase12-recent-conversions-table

Conversation

@menvil

@menvil menvil commented Jun 2, 2026

Copy link
Copy Markdown
Owner

Phase 12 — Recent Conversions Table

Summary

Implements the RecentConversionsTable Livewire component on the dashboard (CONV-164–CONV-180).

What's included

  • CONV-164 RecentConversionsTable skeleton component + dashboard integration
  • CONV-165 Empty state ("No conversions yet")
  • CONV-166 File Name column with eager-loaded source file
  • CONV-167 From / To format columns (uppercase)
  • CONV-168 Size column (result file size, fallback to source)
  • CONV-169 Date column (M j, Y format)
  • CONV-170 Status badge column with color coding
  • CONV-171 Download row action (completed + result file only) + isCompleted() model helper
  • CONV-172 Search input (filename, source format, target format)
  • CONV-173 Status filter (All / Completed / Processing / Failed)
  • CONV-174 Pagination (10/page, page reset on filter/search change)
  • CONV-175 Convert again failing tests
  • CONV-176 Convert again action (dispatches conversion-repeat-requested event)
  • CONV-177 Star conversion failing tests
  • CONV-178 Star/unstar action + is_starred migration + model cast
  • CONV-179 Table authorization tests
  • CONV-180 Integration tests

Security

  • All queries scoped to auth()->id()
  • Actions (convertAgain, toggleStar) silently no-op on foreign jobs
  • Download links never rendered for other users' jobs

Stats

  • 328 tests / 848 assertions — all pass
  • composer lint — passes
  • npm run build — passes

🤖 Generated with Claude Code


Summary by cubic

Adds a Livewire Recent Conversions table to the dashboard so users can search, filter, and act on their latest conversion jobs. Meets CONV-164–CONV-180, scopes all data to the signed-in user, and guards the convert-again action to ignore queued/processing jobs.

  • New Features

    • RecentConversionsTable with columns: file name, from/to formats (uppercase), size (result or source), date, status badge.
    • Actions: Download (completed with result), Convert again (dispatches conversion-repeat-requested for completed/failed), Star/Unstar.
    • Search by filename/source/target formats; status filter (All, Completed, Processing, Failed); 10/page pagination with page reset on changes.
    • Security: queries/actions restricted to auth()->id(), actions no-op for other users’ jobs, download links hidden for non-owners.
    • Model/UX: is_starred boolean cast, isCompleted() helper, eager-load sourceFile/resultFile, extracted canDownload/canConvertAgain helpers.
  • Migration

    • Add is_starred to conversion_jobs (default false).

Written for commit 6788d2b. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features

    • "Recent Conversions" dashboard section with searchable, status-filterable, paginated conversions table
    • Star/unstar conversions, re-convert with one click, and download completed results
    • Human-readable file sizes, formatted dates, status badges, and empty-state messaging
  • Behavior

    • Pagination resets when search or status filter changes; table shows only the authenticated user’s conversions
  • Tests

    • Comprehensive feature, integration, and authorization tests added for the component

menvil and others added 30 commits June 2, 2026 10:30
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…nversions-table-skeleton

CONV-164: Create RecentConversionsTable skeleton
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…arget-format-columns

CONV-167: Add source and target format columns
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…-column

CONV-170: Add status badge column
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…-action

CONV-171: Add download row action
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…t-again-action

CONV-176: Implement convert again action
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ion-test

CONV-177: Add star conversion test
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…onversion-action

CONV-178: Implement star conversion action
menvil and others added 4 commits June 2, 2026 10:46
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ization-tests

CONV-179: Add table authorization tests
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…rsions-integration-test

CONV-180: Add recent conversions integration test
@coderabbitai

coderabbitai Bot commented Jun 2, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a "Recent Conversions" Livewire table: searchable, status-filtered, paginated, user-scoped, with actions to star jobs and request repeat conversions; adds an is_starred column and model flag; integrates the component into the dashboard and includes comprehensive tests.

Changes

Recent Conversions Feature

Layer / File(s) Summary
Data Model & Database Schema
app/Models/ConversionJob.php, database/migrations/2026_06_02_074426_add_is_starred_to_conversion_jobs_table.php
ConversionJob adds is_starred boolean property, boolean cast, fillable entry, and isCompleted() method. Migration creates is_starred column (default false) on conversion_jobs table.
Livewire Component Implementation
app/Livewire/RecentConversionsTable.php
Component exposes public search, statusFilter, perPage, resets pagination on updates, queries authenticated user's conversions with eager-loaded files, applies status and text filters, paginates, and provides toggleStar() and convertAgain() actions plus statusBadgeClasses() and formatBytes() helpers.
Component View & Rendering
resources/views/livewire/recent-conversions-table.blade.php
Blade template renders header, live-debounced search input, status dropdown, empty-state card, conversions table (file name, formats, size, created date, status badge), conditional actions (Download, Convert again, Star toggle), and pagination links.
Dashboard Integration
resources/views/dashboard.blade.php
Dashboard view mounts the livewire:recent-conversions-table component in a new container section positioned before footer help cards.
Feature Tests: Rendering, Filtering & Search
tests/Feature/Livewire/RecentConversionsTableTest.php
Tests verify component headings, dashboard embedding, empty-state behavior, pagination (10 per page), page reset on search/filter change, status filtering, search by filename/source/target formats, conditional Download visibility, status badge labels, date and size formatting, and display of formats and original filename.
Authorization Tests: User Scoping
tests/Feature/Livewire/RecentConversionsTableAuthorizationTest.php
Tests verify component displays only the authenticated user's conversions, scopes returned totals to the auth user, and renders download links only for the auth user's completed conversions.
Integration Tests: End-to-End Scenarios
tests/Feature/Livewire/RecentConversionsTableIntegrationTest.php
Integration tests assert completed conversions appear with expected column values and that the empty-state message is absent when conversions exist.
Action Tests: Events & State Mutations
tests/Feature/Livewire/RecentConversionsTableActionsTest.php
Tests verify convertAgain() dispatches conversion-repeat-requested only for the auth user's jobs, and toggleStar() updates is_starred only for the auth user's jobs.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • menvil/FileConverter#90: Directly conflicts as PR #90 removes the "recent conversions" table from the dashboard while this PR adds it back via Livewire.
  • menvil/FileConverter#123: Related prior changes that introduced ConversionJob foundations which this PR extends with is_starred/isCompleted().
  • menvil/FileConverter#162: The "Download" action in this table depends on the conversions.download route/controller introduced in PR #162.
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title is a release/version branch name that does not clearly summarize the main change; it uses a version tag format that lacks descriptive information about what was implemented. Consider using a descriptive title like 'Add RecentConversionsTable Livewire component with search, filtering, and actions' to clearly communicate the primary change.
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch release/v0.1.12-phase12-recent-conversions-table

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added the release Triggers AI code review (CodeRabbit, Cubic) label Jun 2, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 9 files

Re-trigger cubic

@menvil

menvil commented Jun 2, 2026

Copy link
Copy Markdown
Owner Author

@CodeRabbit review

@coderabbitai

coderabbitai Bot commented Jun 2, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/Feature/Livewire/RecentConversionsTableAuthorizationTest.php (1)

57-65: ⚡ Quick win

Store the other user's job in a variable for clarity.

The inline query ConversionJob::where('user_id', $other->id)->first() on line 65 works but reduces readability and adds an unnecessary database query in the assertion.

♻️ Proposed refactor
-    ConversionJob::factory()->for($other)->completed()->create([
+    $otherJob = ConversionJob::factory()->for($other)->completed()->create([
         'result_file_id' => $otherResult->id,
     ]);

     $this->actingAs($user);

     Livewire::test(RecentConversionsTable::class)
         ->assertSeeHtml(route('conversions.download', $ownJob))
-        ->assertDontSeeHtml(route('conversions.download', ConversionJob::where('user_id', $other->id)->first()));
+        ->assertDontSeeHtml(route('conversions.download', $otherJob));
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Feature/Livewire/RecentConversionsTableAuthorizationTest.php` around
lines 57 - 65, The assertion uses an inline query
ConversionJob::where('user_id', $other->id)->first() which hurts readability and
issues an extra DB call; instead, after creating the other user's job with
ConversionJob::factory()->for($other)->completed()->create([...]) assign that
returned model to a variable (e.g. $otherJob) and then use
route('conversions.download', $otherJob) in the Livewire::test assertions
alongside $ownJob and RecentConversionsTable::class to remove the inline query
and make the test clearer.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@resources/views/livewire/recent-conversions-table.blade.php`:
- Around line 68-81: Add two helper methods to the Livewire component
RecentConversionsTable: public function canDownload(ConversionJob $job): bool {
return $job->isCompleted() && $job->result_file_id !== null; } and public
function canConvertAgain(ConversionJob $job): bool { return $job->isCompleted()
|| $job->status === ConversionStatus::Failed; } (import ConversionStatus in the
component), then update recent-conversions-table.blade.php to replace the inline
conditionals ($job->isCompleted() && $job->result_file_id, $job->isCompleted()
|| $job->status === \App\Enums\ConversionStatus::Failed) with calls to
canDownload($job) and canConvertAgain($job) respectively so all business rules
live in the component.

---

Nitpick comments:
In `@tests/Feature/Livewire/RecentConversionsTableAuthorizationTest.php`:
- Around line 57-65: The assertion uses an inline query
ConversionJob::where('user_id', $other->id)->first() which hurts readability and
issues an extra DB call; instead, after creating the other user's job with
ConversionJob::factory()->for($other)->completed()->create([...]) assign that
returned model to a variable (e.g. $otherJob) and then use
route('conversions.download', $otherJob) in the Livewire::test assertions
alongside $ownJob and RecentConversionsTable::class to remove the inline query
and make the test clearer.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: de97c0d2-b55e-4bd5-8d50-7dc508c715fe

📥 Commits

Reviewing files that changed from the base of the PR and between 282ea85 and 540f55b.

📒 Files selected for processing (9)
  • app/Livewire/RecentConversionsTable.php
  • app/Models/ConversionJob.php
  • database/migrations/2026_06_02_074426_add_is_starred_to_conversion_jobs_table.php
  • resources/views/dashboard.blade.php
  • resources/views/livewire/recent-conversions-table.blade.php
  • tests/Feature/Livewire/RecentConversionsTableActionsTest.php
  • tests/Feature/Livewire/RecentConversionsTableAuthorizationTest.php
  • tests/Feature/Livewire/RecentConversionsTableIntegrationTest.php
  • tests/Feature/Livewire/RecentConversionsTableTest.php

Comment thread resources/views/livewire/recent-conversions-table.blade.php Outdated
…ine DB query in test

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
app/Livewire/RecentConversionsTable.php (1)

72-83: ⚡ Quick win

Consider gating convertAgain() with the new canConvertAgain() helper.

The new canConvertAgain() eligibility rule is only enforced in the view, while the convertAgain() action dispatches conversion-repeat-requested for any user-owned job regardless of status (e.g. a Queued/Processing job). Since Livewire actions are directly callable from the client, the UI gate can be bypassed. Aligning the action with the helper keeps the eligibility rule authoritative server-side.

♻️ Proposed change
         if (! $job) {
             return;
         }
 
+        if (! $this->canConvertAgain($job)) {
+            return;
+        }
+
         $this->dispatch('conversion-repeat-requested', conversionJobId: $job->id);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/Livewire/RecentConversionsTable.php` around lines 72 - 83, The
convertAgain() Livewire action currently dispatches conversion-repeat-requested
for any user-owned ConversionJob; update it to call the canConvertAgain() helper
and only dispatch when that helper returns true for the loaded $job. Locate the
convertAgain() method in RecentConversionsTable.php, after fetching the $job,
invoke canConvertAgain($job) (or the appropriate helper signature) and return
early if it’s false, so only eligible jobs (per the server-side rule) trigger
the dispatch('conversion-repeat-requested', conversionJobId: $job->id).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@app/Livewire/RecentConversionsTable.php`:
- Around line 72-83: The convertAgain() Livewire action currently dispatches
conversion-repeat-requested for any user-owned ConversionJob; update it to call
the canConvertAgain() helper and only dispatch when that helper returns true for
the loaded $job. Locate the convertAgain() method in RecentConversionsTable.php,
after fetching the $job, invoke canConvertAgain($job) (or the appropriate helper
signature) and return early if it’s false, so only eligible jobs (per the
server-side rule) trigger the dispatch('conversion-repeat-requested',
conversionJobId: $job->id).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6f9ca487-5e08-4ce6-a812-27bec5e4776b

📥 Commits

Reviewing files that changed from the base of the PR and between 540f55b and 1975edb.

📒 Files selected for processing (3)
  • app/Livewire/RecentConversionsTable.php
  • resources/views/livewire/recent-conversions-table.blade.php
  • tests/Feature/Livewire/RecentConversionsTableAuthorizationTest.php
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/Feature/Livewire/RecentConversionsTableAuthorizationTest.php
  • resources/views/livewire/recent-conversions-table.blade.php

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@menvil menvil merged commit 87690a3 into main Jun 2, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release Triggers AI code review (CodeRabbit, Cubic)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant