Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 48 additions & 20 deletions app/Filament/Resources/PluginResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use Filament\Schemas;
use Filament\Schemas\Schema;
use Filament\Tables;
use Filament\Tables\Contracts\HasTable;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\HtmlString;
Expand Down Expand Up @@ -259,36 +260,41 @@ public static function table(Table $table): Table
return $table
->columns([
Tables\Columns\ImageColumn::make('logo_path')
->label('')
->label('Logo')
->disk('public')
->circular()
->defaultImageUrl(fn () => 'https://ui-avatars.com/api/?name=P&color=7C3AED&background=EDE9FE')
->size(40),
->size(40)
->toggleable(),

Tables\Columns\TextColumn::make('name')
->label('Package Name')
->searchable()
->sortable()
->fontFamily('mono'),
->fontFamily('mono')
->toggleable(),

Tables\Columns\TextColumn::make('type')
->badge()
->color(fn (PluginType $state): string => match ($state) {
PluginType::Free => 'gray',
PluginType::Paid => 'success',
})
->sortable(),
->sortable()
->toggleable(),

Tables\Columns\TextColumn::make('tier')
->badge()
->color(fn (?PluginTier $state): string => $state?->color() ?? 'gray')
->sortable()
->placeholder('-'),
->placeholder('-')
->toggleable(),

Tables\Columns\TextColumn::make('user.email')
->label('Submitted By')
->searchable()
->sortable(),
->sortable()
->toggleable(),

Tables\Columns\TextColumn::make('status')
->badge()
Expand All @@ -298,7 +304,8 @@ public static function table(Table $table): Table
PluginStatus::Approved => 'success',
PluginStatus::Rejected => 'danger',
})
->sortable(),
->sortable()
->toggleable(),

Tables\Columns\TextColumn::make('mobile_min_version')
->label('Mobile SDK')
Expand All @@ -307,51 +314,67 @@ public static function table(Table $table): Table

Tables\Columns\ToggleColumn::make('is_official')
->label('Official')
->sortable(),
->sortable()
->toggleable(),

Tables\Columns\ToggleColumn::make('featured')
->sortable(),
->sortable()
->toggleable(),

Tables\Columns\ToggleColumn::make('is_active')
->label('Active')
->sortable(),
->sortable()
->toggleable(),

Tables\Columns\ToggleColumn::make('works_in_jump')
->label('Jump')
->sortable(),
->sortable()
->toggleable(),

Tables\Columns\IconColumn::make('reviewed_at')
->label('Reviewed')
->boolean()
->getStateUsing(fn (Plugin $record): bool => $record->reviewed_at !== null)
->tooltip(fn (Plugin $record): ?string => $record->reviewed_at?->diffForHumans())
->sortable(),
->sortable()
->toggleable(),

Tables\Columns\IconColumn::make('satis_synced_at')
->label('Satis')
->boolean()
->getStateUsing(fn (Plugin $record): bool => $record->isSatisSynced())
->tooltip(fn (Plugin $record): ?string => $record->satis_synced_at?->diffForHumans())
->visible(fn (): bool => true)
->sortable(),
->sortable()
->toggleable(),

Tables\Columns\TextColumn::make('created_at')
->label('Submitted')
->dateTime()
->sortable(),
->sortable()
->toggleable(),

Tables\Columns\TextColumn::make('approved_at')
->label('Approved')
->dateTime()
->placeholder('-')
->sortable(),
->sortable()
->toggleable(),
])
->reorderableColumns()
->filters([
Tables\Filters\SelectFilter::make('status')
->options(PluginStatus::class)
->query(fn (Builder $query, array $data): Builder => filled($data['value'])
? $query->where('status', $data['value'])
Tables\Filters\Filter::make('drafts')
->schema([
Forms\Components\Checkbox::make('show_drafts')
->label('Show drafts'),
])
->query(fn (Builder $query, array $data): Builder => ($data['show_drafts'] ?? false)
? $query
: $query->where('status', '!=', PluginStatus::Draft)
)
->indicateUsing(fn (array $data): array => ($data['show_drafts'] ?? false)
? ['show_drafts' => 'Showing drafts']
: []
),
Tables\Filters\SelectFilter::make('type')
->options(PluginType::class),
Expand Down Expand Up @@ -507,7 +530,12 @@ public static function table(Table $table): Table
->bulkActions([

])
->defaultSort('created_at', 'desc');
->defaultSort(
fn (HasTable $livewire): string => ($livewire instanceof Pages\ListPlugins && $livewire->getActiveTabStatus() === PluginStatus::Approved)
? 'approved_at'
: 'created_at',
'desc',
);
}

public static function getRelations(): array
Expand Down
27 changes: 27 additions & 0 deletions app/Filament/Resources/PluginResource/Pages/ListPlugins.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@

namespace App\Filament\Resources\PluginResource\Pages;

use App\Enums\PluginStatus;
use App\Filament\Resources\PluginResource;
use Filament\Actions;
use Filament\Resources\Pages\ListRecords;
use Filament\Schemas\Components\Tabs\Tab;
use Illuminate\Database\Eloquent\Builder;

class ListPlugins extends ListRecords
{
Expand All @@ -16,4 +19,28 @@ protected function getHeaderActions(): array
Actions\CreateAction::make(),
];
}

public function getTabs(): array
{
return [
PluginStatus::Pending->value => $this->makeStatusTab(PluginStatus::Pending, 'Pending'),
PluginStatus::Approved->value => $this->makeStatusTab(PluginStatus::Approved, 'Approved'),
PluginStatus::Rejected->value => $this->makeStatusTab(PluginStatus::Rejected, 'Rejected'),
'all' => Tab::make('All'),
];
}

/**
* The status the active tab is scoped to, or null when the tab lists every status.
*/
public function getActiveTabStatus(): ?PluginStatus
{
return PluginStatus::tryFrom($this->activeTab ?? '');
}

private function makeStatusTab(PluginStatus $status, string $label): Tab
{
return Tab::make($label)
->modifyQueryUsing(fn (Builder $query) => $query->where('status', $status));
}
}
3 changes: 3 additions & 0 deletions tests/Feature/Filament/GrantPluginToUserActionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public function test_grant_to_user_action_is_hidden_for_free_plugins_on_list():

Livewire::actingAs($this->admin)
->test(ListPlugins::class)
->set('activeTab', 'approved')
->assertTableActionHidden('grantToUser', $plugin);
}

Expand All @@ -40,6 +41,7 @@ public function test_grant_to_user_action_is_visible_for_paid_plugins_on_list():

Livewire::actingAs($this->admin)
->test(ListPlugins::class)
->set('activeTab', 'approved')
->assertTableActionVisible('grantToUser', $plugin);
}

Expand Down Expand Up @@ -68,6 +70,7 @@ public function test_grant_to_user_action_can_be_called_with_user_id_on_list():

Livewire::actingAs($this->admin)
->test(ListPlugins::class)
->set('activeTab', 'approved')
->callAction(
TestAction::make('grantToUser')->table($plugin),
data: ['user_id' => $recipient->id],
Expand Down
47 changes: 43 additions & 4 deletions tests/Feature/Filament/PluginListDraftFilterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

namespace Tests\Feature\Filament;

use App\Enums\PluginStatus;
use App\Filament\Resources\PluginResource\Pages\ListPlugins;
use App\Models\Plugin;
use App\Models\User;
Expand All @@ -24,26 +23,66 @@ protected function setUp(): void
config(['filament.users' => ['admin@test.com']]);
}

public function test_show_drafts_checkbox_renders_and_no_status_filter_remains(): void
{
Plugin::factory()->pending()->create();

$component = Livewire::actingAs($this->admin)
->test(ListPlugins::class)
->assertTableFilterExists('drafts')
->assertSee('Show drafts');

$this->assertNull($component->instance()->getTable()->getFilter('status'));
}

public function test_draft_plugins_are_hidden_by_default(): void
{
$draft = Plugin::factory()->draft()->create();
$approved = Plugin::factory()->approved()->create();

Livewire::actingAs($this->admin)
->test(ListPlugins::class)
->set('activeTab', 'all')
->assertCanNotSeeTableRecords([$draft])
->assertCanSeeTableRecords([$approved]);
}

public function test_draft_plugins_are_visible_when_filtering_by_draft_status(): void
public function test_draft_plugins_are_visible_when_show_drafts_is_checked(): void
{
$draft = Plugin::factory()->draft()->create();
$approved = Plugin::factory()->approved()->create();

Livewire::actingAs($this->admin)
->test(ListPlugins::class)
->filterTable('status', PluginStatus::Draft->value)
->set('activeTab', 'all')
->filterTable('drafts', ['show_drafts' => true])
->assertCanSeeTableRecords([$draft, $approved]);
}

public function test_drafts_are_hidden_again_when_show_drafts_is_unchecked(): void
{
$draft = Plugin::factory()->draft()->create();
$approved = Plugin::factory()->approved()->create();

Livewire::actingAs($this->admin)
->test(ListPlugins::class)
->set('activeTab', 'all')
->filterTable('drafts', ['show_drafts' => true])
->assertCanSeeTableRecords([$draft])
->assertCanNotSeeTableRecords([$approved]);
->filterTable('drafts', ['show_drafts' => false])
->assertCanNotSeeTableRecords([$draft])
->assertCanSeeTableRecords([$approved]);
}

public function test_show_drafts_does_not_leak_drafts_into_the_status_tabs(): void
{
$draft = Plugin::factory()->draft()->create();
$pending = Plugin::factory()->pending()->create();

Livewire::actingAs($this->admin)
->test(ListPlugins::class)
->filterTable('drafts', ['show_drafts' => true])
->assertCanSeeTableRecords([$pending])
->assertCanNotSeeTableRecords([$draft]);
}
}
Loading