91 - Show the feed name on article activity entries

This commit is contained in:
myrmidex 2026-08-10 21:43:47 +02:00
parent d3e589c36c
commit 3b4200a0e5
5 changed files with 42 additions and 4 deletions

View file

@ -4,9 +4,12 @@
use App\Enums\ActivityTypeEnum; use App\Enums\ActivityTypeEnum;
use App\Models\ActivityLog; use App\Models\ActivityLog;
use App\Models\Article;
use App\Services\Activity\ActivitySummary; use App\Services\Activity\ActivitySummary;
use Illuminate\Contracts\View\View; use Illuminate\Contracts\View\View;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Database\Eloquent\Relations\Relation;
use Livewire\Component; use Livewire\Component;
use Livewire\WithPagination; use Livewire\WithPagination;
@ -34,7 +37,11 @@ public function updatedDays(): void
private function query(): Builder private function query(): Builder
{ {
return ActivityLog::query() return ActivityLog::query()
->with('subject') ->with(['subject' => function (Relation $morphTo): void {
if ($morphTo instanceof MorphTo) {
$morphTo->morphWith([Article::class => ['feed']]);
}
}])
->since(now()->subDays($this->days)) ->since(now()->subDays($this->days))
->when( ->when(
$this->type !== '', $this->type !== '',

View file

@ -40,7 +40,7 @@ public function loggedAt(Carbon $loggedAt): static
return $this->state(['logged_at' => $loggedAt]); return $this->state(['logged_at' => $loggedAt]);
} }
public function for_subject(Model $subject): static public function forSubject(Model $subject): static
{ {
return $this->state([ return $this->state([
'subject_type' => $subject->getMorphClass(), 'subject_type' => $subject->getMorphClass(),

View file

@ -44,6 +44,9 @@ class="w-44 shrink-0 pl-3 pr-10 py-2 border border-gray-300 rounded-md text-sm f
<div class="min-w-0 flex-1"> <div class="min-w-0 flex-1">
<p class="text-sm text-gray-900 dark:text-gray-100">{{ $entry->message }}</p> <p class="text-sm text-gray-900 dark:text-gray-100">{{ $entry->message }}</p>
@if ($entry->subject instanceof App\Models\Article)
<p class="mt-0.5 text-xs text-gray-500 dark:text-gray-400">{{ $entry->subject->feed?->name }}</p>
@endif
@if (($entry->context['reason'] ?? null) !== null) @if (($entry->context['reason'] ?? null) !== null)
<p class="mt-0.5 text-xs text-gray-500 dark:text-gray-400">{{ $entry->context['reason'] }}</p> <p class="mt-0.5 text-xs text-gray-500 dark:text-gray-400">{{ $entry->context['reason'] }}</p>
@endif @endif

View file

@ -6,7 +6,9 @@
use App\Livewire\Activity; use App\Livewire\Activity;
use App\Models\ActivityLog; use App\Models\ActivityLog;
use App\Models\Article; use App\Models\Article;
use App\Models\Feed;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\DB;
use Livewire\Livewire; use Livewire\Livewire;
use Tests\TestCase; use Tests\TestCase;
@ -70,7 +72,7 @@ public function test_entry_without_a_subject_renders(): void
public function test_entry_with_a_deleted_subject_renders(): void public function test_entry_with_a_deleted_subject_renders(): void
{ {
$article = Article::factory()->create(); $article = Article::factory()->create();
ActivityLog::factory()->for_subject($article)->create(['message' => 'Dangling subject']); ActivityLog::factory()->forSubject($article)->create(['message' => 'Dangling subject']);
$article->delete(); $article->delete();
Livewire::test(Activity::class) Livewire::test(Activity::class)
@ -83,6 +85,32 @@ public function test_empty_state_is_shown_when_there_is_no_activity(): void
Livewire::test(Activity::class)->assertSee('No activity in this period.'); Livewire::test(Activity::class)->assertSee('No activity in this period.');
} }
public function test_an_article_subject_shows_its_feed_name(): void
{
$feed = Feed::factory()->create(['name' => 'VRT News']);
$article = Article::factory()->create(['feed_id' => $feed->id]);
ActivityLog::factory()->forSubject($article)->create(['message' => 'Published something']);
Livewire::test(Activity::class)->assertSee('VRT News');
}
public function test_subjects_are_eager_loaded(): void
{
$feed = Feed::factory()->create();
foreach (range(1, 5) as $i) {
$article = Article::factory()->create(['feed_id' => $feed->id]);
ActivityLog::factory()->forSubject($article)->create();
}
DB::enableQueryLog();
Livewire::test(Activity::class);
$queries = count(DB::getQueryLog());
DB::disableQueryLog();
$this->assertLessThan(10, $queries);
}
public function test_a_reason_in_context_is_shown_under_the_message(): void public function test_a_reason_in_context_is_shown_under_the_message(): void
{ {
ActivityLog::factory()->create([ ActivityLog::factory()->create([

View file

@ -58,7 +58,7 @@ public function test_latest_first_breaks_ties_on_id(): void
public function test_subject_resolves_to_the_related_model(): void public function test_subject_resolves_to_the_related_model(): void
{ {
$article = Article::factory()->create(); $article = Article::factory()->create();
$log = ActivityLog::factory()->for_subject($article)->create(); $log = ActivityLog::factory()->forSubject($article)->create();
$this->assertInstanceOf(Article::class, $log->subject); $this->assertInstanceOf(Article::class, $log->subject);
$this->assertSame($article->id, $log->subject->id); $this->assertSame($article->id, $log->subject->id);