Merge pull request #9293 from filamentphp/new-table-filters-indicator-api

New table filters indicator API
This commit is contained in:
Dan Harrin
2023-10-29 18:10:09 +00:00
committed by GitHub
15 changed files with 202 additions and 56 deletions
+5 -2
View File
@@ -41,6 +41,7 @@ use Filament\Tables\Contracts\HasTable;
use Filament\Tables\Enums\ActionsPosition;
use Filament\Tables\Enums\FiltersLayout;
use Filament\Tables\Filters\Filter;
use Filament\Tables\Filters\Indicator;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Grouping\Group;
use Filament\Tables\Table;
@@ -709,8 +710,10 @@ class TablesDemo extends Component implements HasForms, HasTable
->filters([
Filter::make('dummy')
->indicateUsing(fn () => [
'one' => 'Posted by administrator',
'two' => 'Less than 1 year old',
Indicator::make('Posted by administrator')
->removeField('one'),
Indicator::make('Less than 1 year old')
->removeField('two'),
]),
]);
}
+5 -2
View File
@@ -345,6 +345,7 @@ You may even render multiple indicators at once, by returning an array. If you h
```php
use Filament\Forms\Components\DatePicker;
use Filament\Tables\Filters\Filter;
use Filament\Tables\Filters\Indicator;
Filter::make('created_at')
->form([
@@ -356,11 +357,13 @@ Filter::make('created_at')
$indicators = [];
if ($data['from'] ?? null) {
$indicators['from'] = 'Created from ' . Carbon::parse($data['from'])->toFormattedDateString();
$indicators[] = Indicator::make('Created from ' . Carbon::parse($data['from'])->toFormattedDateString())
->removeField('from');
}
if ($data['until'] ?? null) {
$indicators['until'] = 'Created until ' . Carbon::parse($data['until'])->toFormattedDateString();
$indicators[] = Indicator::make('Created until ' . Carbon::parse($data['until'])->toFormattedDateString())
->removeField('until');
}
return $indicators;
@@ -13,17 +13,19 @@
</span>
<div class="flex flex-wrap gap-1.5">
@foreach ($indicators as $wireClickHandler => $label)
<x-filament::badge>
{{ $label }}
@foreach ($indicators as $indicator)
<x-filament::badge :color="$indicator->getColor()">
{{ $indicator->getLabel() }}
<x-slot
name="deleteButton"
:label="__('filament-tables::table.filters.actions.remove.label')"
wire:click="{{ $wireClickHandler }}"
wire:loading.attr="disabled"
wire:target="removeTableFilter"
></x-slot>
@if ($indicator->isRemovable())
<x-slot
name="deleteButton"
:label="__('filament-tables::table.filters.actions.remove.label')"
wire:click="{{ $indicator->getRemoveLivewireClickHandler() }}"
wire:loading.attr="disabled"
wire:target="removeTableFilter"
></x-slot>
@endif
</x-filament::badge>
@endforeach
</div>
@@ -14,26 +14,7 @@
$content = $getContent();
$contentGrid = $getContentGrid();
$contentFooter = $getContentFooter();
$filterIndicators = [
...($hasSearch() ? ['resetTableSearch' => $getSearchIndicator()] : []),
...collect($getColumnSearchIndicators())
->mapWithKeys(fn (string $indicator, string $column): array => [
"resetTableColumnSearch('{$column}')" => $indicator,
])
->all(),
...array_reduce(
$getFilters(),
fn (array $carry, \Filament\Tables\Filters\BaseFilter $filter): array => [
...$carry,
...collect($filter->getIndicators())
->mapWithKeys(fn (string $label, int | string $field) => [
"removeTableFilter('{$filter->getName()}'" . (is_string($field) ? ' , \'' . $field . '\'' : null) . ')' => $label,
])
->all(),
],
[],
),
];
$filterIndicators = $getFilterIndicators();
$hasColumnsLayout = $hasColumnsLayout();
$hasSummary = $hasSummary();
$header = $getHeader();
@@ -2,6 +2,7 @@
namespace Filament\Tables\Concerns;
use Filament\Tables\Filters\Indicator;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Arr;
use RecursiveArrayIterator;
@@ -174,13 +175,14 @@ trait CanSearchRecords
$this->updatedTableColumnSearches();
}
public function getTableSearchIndicator(): string
public function getTableSearchIndicator(): Indicator
{
return __('filament-tables::table.fields.search.indicator') . ': ' . $this->getTableSearch();
return Indicator::make(__('filament-tables::table.fields.search.indicator') . ': ' . $this->getTableSearch())
->removeLivewireClickHandler('resetTableSearch');
}
/**
* @return array<string, string>
* @return array<Indicator>
*/
public function getTableColumnSearchIndicators(): array
{
@@ -203,7 +205,8 @@ trait CanSearchRecords
continue;
}
$indicators[$columnName] = "{$column->getLabel()}: {$search}";
$indicators[] = Indicator::make("{$column->getLabel()}: {$search}")
->removeLivewireClickHandler("resetTableColumnSearch('{$columnName}')");
}
return $indicators;
+3 -2
View File
@@ -6,6 +6,7 @@ use Filament\Forms\Form;
use Filament\Support\Contracts\TranslatableContentDriver;
use Filament\Tables\Actions\Action;
use Filament\Tables\Actions\BulkAction;
use Filament\Tables\Filters\Indicator;
use Filament\Tables\Grouping\Group;
use Filament\Tables\Table;
use Illuminate\Contracts\Pagination\Paginator;
@@ -93,10 +94,10 @@ interface HasTable
public function resetTableColumnSearch(string $column): void;
public function getTableSearchIndicator(): string;
public function getTableSearchIndicator(): Indicator;
/**
* @return array<string, string>
* @return array<Indicator>
*/
public function getTableColumnSearchIndicators(): array;
@@ -3,15 +3,16 @@
namespace Filament\Tables\Filters\Concerns;
use Closure;
use Filament\Tables\Filters\Indicator;
use Illuminate\Support\Arr;
trait HasIndicators
{
protected string | Closure | null $indicateUsing = null;
protected string | Closure | null $indicator = null;
protected Indicator | string | Closure | null $indicator = null;
public function indicator(string | Closure | null $indicator): static
public function indicator(Indicator | string | Closure | null $indicator): static
{
$this->indicator = $indicator;
@@ -26,7 +27,7 @@ trait HasIndicators
}
/**
* @return array<string>
* @return array<Indicator>
*/
public function getIndicators(): array
{
@@ -41,10 +42,24 @@ trait HasIndicators
return [];
}
return Arr::wrap($indicators);
$indicators = Arr::wrap($indicators);
foreach ($indicators as $field => $indicator) {
if (! $indicator instanceof Indicator) {
$indicator = Indicator::make($indicator);
}
if (is_string($field)) {
$indicator = $indicator->removeField($field);
}
$indicators[$field] = $indicator;
}
return $indicators;
}
public function getIndicator(): string
public function getIndicator(): Indicator | string
{
$state = $this->getState();
+7 -1
View File
@@ -19,7 +19,13 @@ class Filter extends BaseFilter
return [];
}
return [$this->getIndicator()];
$indicator = $this->getIndicator();
if (! $indicator instanceof Indicator) {
$indicator = Indicator::make($indicator);
}
return [$indicator];
});
}
+78
View File
@@ -0,0 +1,78 @@
<?php
namespace Filament\Tables\Filters;
use Closure;
use Filament\Support\Components\Component;
use Filament\Support\Concerns\HasColor;
class Indicator extends Component
{
use HasColor;
protected bool | Closure $isRemovable = true;
protected string | Closure | null $label = null;
protected string | Closure | null $removeField = null;
protected string | Closure | null $removeLivewireClickHandler = null;
public function __construct(string $label)
{
$this->label($label);
}
public static function make(string | Closure | null $label = null): static
{
return app(static::class, ['label' => $label]);
}
public function label(string $label): static
{
$this->label = $label;
return $this;
}
public function getLabel(): string
{
return $this->label;
}
public function removable(bool | Closure $condition = true): static
{
$this->isRemovable = $condition;
return $this;
}
public function isRemovable(): bool
{
return (bool) $this->evaluate($this->isRemovable);
}
public function removeField(string | Closure | null $name): static
{
$this->removeField = $name;
return $this;
}
public function getRemoveField(): ?string
{
return $this->evaluate($this->removeField);
}
public function removeLivewireClickHandler(string | Closure | null $handler): static
{
$this->removeLivewireClickHandler = $handler;
return $this;
}
public function getRemoveLivewireClickHandler(): ?string
{
return $this->evaluate($this->removeLivewireClickHandler);
}
}
+14 -2
View File
@@ -66,7 +66,13 @@ class SelectFilter extends BaseFilter
$labels = collect($labels)->join(', ', ' & ');
return ["{$filter->getIndicator()}: {$labels}"];
$indicator = $filter->getIndicator();
if (! $indicator instanceof Indicator) {
$indicator = Indicator::make("{$indicator}: {$labels}");
}
return [$indicator];
}
if (blank($state['value'] ?? null)) {
@@ -86,7 +92,13 @@ class SelectFilter extends BaseFilter
return [];
}
return ["{$filter->getIndicator()}: {$label}"];
$indicator = $filter->getIndicator();
if (! $indicator instanceof Indicator) {
$indicator = Indicator::make("{$indicator}: {$label}");
}
return [$indicator];
});
$this->resetState(['value' => null]);
+10 -4
View File
@@ -22,16 +22,22 @@ class TernaryFilter extends SelectFilter
$this->boolean();
$this->indicateUsing(function (array $state): array {
$this->indicateUsing(function (TernaryFilter $filter, array $state): array {
if (blank($state['value'] ?? null)) {
return [];
}
$stateLabel = $state['value'] ?
$this->getTrueLabel() :
$this->getFalseLabel();
$filter->getTrueLabel() :
$filter->getFalseLabel();
return ["{$this->getIndicator()}: {$stateLabel}"];
$indicator = $filter->getIndicator();
if (! $indicator instanceof Indicator) {
$indicator = Indicator::make("{$indicator}: {$stateLabel}");
}
return [$indicator];
});
}
@@ -36,14 +36,14 @@ class TrashedFilter extends TernaryFilter
$this->indicateUsing(function (array $state): array {
if ($state['value'] ?? null) {
return [$this->getTrueLabel()];
return [Indicator::make($this->getTrueLabel())];
}
if (blank($state['value'] ?? null)) {
return [];
}
return [$this->getFalseLabel()];
return [Indicator::make($this->getFalseLabel())];
});
}
}
+1
View File
@@ -23,6 +23,7 @@ class Table extends ViewComponent
use Table\Concerns\HasColumns;
use Table\Concerns\HasContent;
use Table\Concerns\HasEmptyState;
use Table\Concerns\HasFilterIndicators;
use Table\Concerns\HasFilters;
use Table\Concerns\HasHeader;
use Table\Concerns\HasHeaderActions;
@@ -3,6 +3,7 @@
namespace Filament\Tables\Table\Concerns;
use Closure;
use Filament\Tables\Filters\Indicator;
trait CanSearchRecords
{
@@ -79,13 +80,13 @@ trait CanSearchRecords
return $this->getLivewire()->hasTableSearch();
}
public function getSearchIndicator(): string
public function getSearchIndicator(): Indicator
{
return $this->getLivewire()->getTableSearchIndicator();
}
/**
* @return array<string, string>
* @return array<Indicator> | array<string, string>
*/
public function getColumnSearchIndicators(): array
{
@@ -0,0 +1,34 @@
<?php
namespace Filament\Tables\Table\Concerns;
use Filament\Tables\Filters\BaseFilter;
use Filament\Tables\Filters\Indicator;
trait HasFilterIndicators
{
/**
* @return array<Indicator>
*/
public function getFilterIndicators(): array
{
return [
...($this->hasSearch() ? [$this->getSearchIndicator()] : []),
...$this->getColumnSearchIndicators(),
...array_reduce(
$this->getFilters(),
fn (array $carry, BaseFilter $filter): array => [
...$carry,
...collect($filter->getIndicators())
->map(function (Indicator $indicator) use ($filter): Indicator {
$removeField = $indicator->getRemoveField();
return $indicator->removeLivewireClickHandler("removeTableFilter('{$filter->getName()}'" . (filled($removeField) ? ', \'' . $removeField . '\'' : null) . ')');
})
->all(),
],
[],
),
];
}
}