summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Columns/Column.php34
-rw-r--r--src/Concerns/Makable.php11
-rw-r--r--src/TableComponent.php65
-rw-r--r--src/Toolbar.php9
-rw-r--r--src/Toolbar/ColumnSelect.php4
-rw-r--r--src/Toolbar/Filter.php26
-rw-r--r--src/Toolbar/Item.php3
-rw-r--r--src/Toolbar/SelectFilter.php35
8 files changed, 178 insertions, 9 deletions
diff --git a/src/Columns/Column.php b/src/Columns/Column.php
index 895708f..a8dc2e6 100644
--- a/src/Columns/Column.php
+++ b/src/Columns/Column.php
@@ -5,6 +5,7 @@ namespace Lightscale\LaralightTables\Columns;
use Lightscale\LaralightTables\TableComponent;
use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\Builder;
use Illuminate\View\ComponentAttributeBag;
use Illuminate\Support\HtmlString;
@@ -14,6 +15,7 @@ class Column {
private TableComponent $table;
private bool $showInSelect;
+ private bool $shouldEscape = true;
private ?Closure $slotFn = null;
private ?Closure $sortFn = null;
@@ -54,12 +56,24 @@ class Column {
return $this;
}
- public function sortable(callable $fn) : static
+ public function sortable(?callable $fn): static
{
- $this->sortFn = Closure::fromCallable($fn);
+ $this->sortFn = $fn;
return $this;
}
+ public function isSortable(): bool
+ {
+ return $this->sortFn !== null;
+ }
+
+ public function applySort(Builder $query, string $dir): void
+ {
+ if ($this->sortFn !== null) {
+ ($this->sortFn)($query, $dir);
+ }
+ }
+
public function colClass(string $v) : static
{
$this->colClass = $v;
@@ -88,9 +102,23 @@ class Column {
return $this->showInSelect;
}
+ public function shouldEscape(bool $v): static
+ {
+ $this->shouldEscape = $v;
+ return $this;
+ }
+
+ public function escape(string $content): string
+ {
+ return $this->shouldEscape ? e($content) : $content;
+ }
+
protected function getContent(Model $row): string
{
- return $this->slotFn?->call($this, $row, $this) ?? $this->defaultSlot($row);
+ return $this->escape(
+ $this->slotFn?->call($this, $row, $this) ??
+ $this->defaultSlot($row)
+ );
}
public function view(Model $row): HtmlString
diff --git a/src/Concerns/Makable.php b/src/Concerns/Makable.php
new file mode 100644
index 0000000..7562970
--- /dev/null
+++ b/src/Concerns/Makable.php
@@ -0,0 +1,11 @@
+<?php
+
+namespace Lightscale\LaralightTables\Concerns;
+
+trait Makable
+{
+ public static function make(mixed ...$args): static
+ {
+ return new static(...$args);
+ }
+}
diff --git a/src/TableComponent.php b/src/TableComponent.php
index 0a55d5e..266cdc3 100644
--- a/src/TableComponent.php
+++ b/src/TableComponent.php
@@ -2,6 +2,8 @@
namespace Lightscale\LaralightTables;
+use Lightscale\LaralightTables\Columns\Column;
+
use Livewire\Component;
use Livewire\WithPagination;
use Livewire\Attributes\Url;
@@ -28,9 +30,19 @@ abstract class TableComponent extends Component
#[Url]
public int $pageSize;
+
public array $activeColumns = [];
- public function mount()
+ #[Url]
+ public array $filters = [];
+
+ #[Url]
+ public ?string $order = null;
+
+ #[Url]
+ public ?string $orderDirection = null;
+
+ public function mount(): void
{
$this->setDefaultActiveColumns();
$this->setDefaultPageSize();
@@ -63,6 +75,28 @@ abstract class TableComponent extends Component
}
}
+ public function updatedFilters(): void
+ {
+ $this->resetPage();
+ }
+
+ public function orderBy(string $column): void
+ {
+ if ($column === $this->order) {
+ if ($this->orderDirection === 'desc') {
+ $this->order = null;
+ $this->orderDirection = null;
+ }
+ else {
+ $this->orderDirection = 'desc';
+ }
+ }
+ else {
+ $this->order = $column;
+ $this->orderDirection = 'asc';
+ }
+ }
+
protected function toolbar(): ?Toolbar
{
return null;
@@ -91,6 +125,25 @@ abstract class TableComponent extends Component
protected function search(Builder $builder, string $search) : void {}
+ protected function getFilters(): Collection
+ {
+ return $this->getToolbar()?->getFilters() ?? collect();
+ }
+
+
+ protected function getOrderColumn(): ?Column
+ {
+ return ($name = $this->order) === null ? null : $this->getColumns()[$name] ?? null;
+ }
+
+ protected function applyOrder(Builder $query): void
+ {
+ $column = $this->getOrderColumn();
+ if ($column) {
+ $column->applySort($query, $this->orderDirection);
+ }
+ }
+
protected function buildQuery() : Builder
{
$query = $this->query();
@@ -99,16 +152,22 @@ abstract class TableComponent extends Component
$this->search($query, $this->search);
}
+ foreach ($this->getFilters() as $filter) {
+ $filter->applyFilter($query);
+ }
+
+ $this->applyOrder($query);
+
return $query;
}
private ?Collection $columnsCache = null;
- public function getColumns()
+ public function getColumns(): Collection
{
if($this->columnsCache === null) {
$this->columnsCache = collect($this->columns())->each(
fn($c) => $c->setTable($this)
- );
+ )->keyBy('name');
}
return $this->columnsCache;
diff --git a/src/Toolbar.php b/src/Toolbar.php
index 2db39f5..8539e0e 100644
--- a/src/Toolbar.php
+++ b/src/Toolbar.php
@@ -5,7 +5,7 @@ namespace Lightscale\LaralightTables;
use Lightscale\LaralightTables\Toolbar\Item as ToolbarItem;
use Lightscale\LaralightTables\Toolbar\Search as SearchItem;
use Lightscale\LaralightTables\Toolbar\PageSize as PageSizeItem;
-use Lightscale\LaralightTables\Toolbar\Filter as FitlerItem;
+use Lightscale\LaralightTables\Toolbar\Filter as FilterItem;
use Illuminate\View\View;
use Illuminate\Support\Collection;
@@ -18,6 +18,7 @@ class Toolbar
protected Collection $startItems;
protected Collection $midItems;
protected Collection $endItems;
+ protected Collection $filterItems;
public function __construct(
private TableComponent $table
@@ -26,6 +27,7 @@ class Toolbar
$this->startItems = collect();
$this->midItems = collect();
$this->endItems = collect();
+ $this->filterItems = collect();
}
private function addItem(Collection $list, ToolbarItem $item): static
@@ -76,6 +78,11 @@ class Toolbar
return $this->pageSizeItem;
}
+ public function getFilters(): Collection
+ {
+ return $this->filterItems;
+ }
+
public function render(): View
{
return view('laralight-tables::toolbar', [
diff --git a/src/Toolbar/ColumnSelect.php b/src/Toolbar/ColumnSelect.php
index a70c49a..9380650 100644
--- a/src/Toolbar/ColumnSelect.php
+++ b/src/Toolbar/ColumnSelect.php
@@ -11,7 +11,9 @@ class ColumnSelect extends Item
public function render(): View
{
return view('laralight-tables::toolbar.column-select', [
- 'allColumns' => $this->getTable()->getColumns()
+ 'allColumns' => $this->getTable()
+ ->getColumns()
+ ->filter(fn($c) => $c->getShowInSelect())
]);
}
}
diff --git a/src/Toolbar/Filter.php b/src/Toolbar/Filter.php
index 19f29cc..51e0d9a 100644
--- a/src/Toolbar/Filter.php
+++ b/src/Toolbar/Filter.php
@@ -2,12 +2,30 @@
namespace Lightscale\LaralightTables\Toolbar;
+use Illuminate\Database\Eloquent\Builder;
+
use Closure;
abstract class Filter extends Item
{
protected ?Closure $filterCallback = null;
+ public function __construct(
+ protected string $key,
+ protected ?string $label = null,
+ ) {}
+
+ public function label(string $v): static
+ {
+ $this->label = $v;
+ return $this;
+ }
+
+ public function makeId(): string
+ {
+ return "filter_{$this->key}";
+ }
+
public function filter(callable $filterCB): static
{
$this->filterCallback = $filterCB;
@@ -16,7 +34,13 @@ abstract class Filter extends Item
public function applyFilter(Builder $query): void
{
- ($this->filterCallback)($query, $value);
+ if ($this->filterCallback !== null) {
+ $value = $this->getTable()->filters[$this->key] ?? null;
+
+ if (!empty($value)) {
+ ($this->filterCallback)($query, $value);
+ }
+ }
}
}
diff --git a/src/Toolbar/Item.php b/src/Toolbar/Item.php
index 168f877..e91698f 100644
--- a/src/Toolbar/Item.php
+++ b/src/Toolbar/Item.php
@@ -4,12 +4,15 @@ namespace Lightscale\LaralightTables\Toolbar;
use Lightscale\LaralightTables\TableComponent;
use Lightscale\LaralightTables\Toolbar;
+use Lightscale\LaralightTables\Concerns\Makable;
use Illuminate\View\View;
use Illuminate\Support\HtmlString;
abstract class Item
{
+ use Makable;
+
private Toolbar $toolbar;
public function setToolbar(Toolbar $toolbar): void
diff --git a/src/Toolbar/SelectFilter.php b/src/Toolbar/SelectFilter.php
new file mode 100644
index 0000000..0549885
--- /dev/null
+++ b/src/Toolbar/SelectFilter.php
@@ -0,0 +1,35 @@
+<?php
+
+namespace Lightscale\LaralightTables\Toolbar;
+
+use Illuminate\View\View;
+
+class SelectFilter extends Filter
+{
+ protected iterable $options;
+ protected ?string $placeholder = null;
+
+ public function placeholder(?string $v): static
+ {
+ $this->placeholder = $v;
+ return $this;
+ }
+
+ public function options(iterable $options): static
+ {
+ $this->options = $options;
+ return $this;
+ }
+
+ public function render(): View
+ {
+ return view('laralight-tables::toolbar.select-filter', [
+ 'id' => $this->makeId(),
+ 'key' => $this->key,
+ 'label' => $this->label,
+ 'options' => $this->options,
+ 'placeholder' => $this->placeholder,
+ ]);
+ }
+
+}