diff --git a/resources/views/editor.blade.php b/resources/views/editor.blade.php index 2df66a5..70c87aa 100644 --- a/resources/views/editor.blade.php +++ b/resources/views/editor.blade.php @@ -1,8 +1,7 @@
@if (! count($criteria)) -
+
Add a new condition diff --git a/resources/views/filters.blade.php b/resources/views/filters.blade.php new file mode 100644 index 0000000..33a94da --- /dev/null +++ b/resources/views/filters.blade.php @@ -0,0 +1,11 @@ +
+ @foreach($this->filters() as $filter) + @include('query-builder::filters.' . $filter->component()) + @endforeach +
+
+ +
\ No newline at end of file diff --git a/resources/views/filters/boolean.blade.php b/resources/views/filters/boolean.blade.php new file mode 100644 index 0000000..ddab435 --- /dev/null +++ b/resources/views/filters/boolean.blade.php @@ -0,0 +1,8 @@ +
+ + +
\ No newline at end of file diff --git a/resources/views/filters/date.blade.php b/resources/views/filters/date.blade.php new file mode 100644 index 0000000..9f0b91b --- /dev/null +++ b/resources/views/filters/date.blade.php @@ -0,0 +1,10 @@ +
+ + +
+ diff --git a/resources/views/filters/select.blade.php b/resources/views/filters/select.blade.php new file mode 100644 index 0000000..63ead61 --- /dev/null +++ b/resources/views/filters/select.blade.php @@ -0,0 +1,11 @@ +
+ + +
\ No newline at end of file diff --git a/resources/views/filters/text.blade.php b/resources/views/filters/text.blade.php new file mode 100644 index 0000000..0b1b73f --- /dev/null +++ b/resources/views/filters/text.blade.php @@ -0,0 +1,4 @@ +
+ + +
\ No newline at end of file diff --git a/resources/views/table.blade.php b/resources/views/table.blade.php new file mode 100644 index 0000000..079a5f6 --- /dev/null +++ b/resources/views/table.blade.php @@ -0,0 +1,92 @@ +
+ +
+ @if ($this->areFiltersAvailable()) +
+ @include('query-builder::filters') +
+ @endif +
+ +
+ @if($this->rows->count()) + +
+ + + + + @foreach ($this->columns() as $column) + + @endforeach + + + + + @foreach ($this->rows as $row) + isClickable()) + wire:click="rowClick('{{ $row->id }}')" + @endif + wire:key="row-{{ $row->id }}" + @class([ + 'bg-white border-b', + 'hover:bg-gray-50 cursor-pointer' => $this->isClickable(), + ])> + + @foreach ($this->columns() as $column) + + @endforeach + + @endforeach + +
isSortable()) wire:click="sort('{{ $column->key }}')" @endif> + @if ($column->showHeader) +
justify, + 'cursor-pointer' => $column->isSortable(), + ])> + {{ $column->label }} + + @if ($sortBy === $column->key) + @if ($sortDirection === 'asc') + + + + @else + + + + @endif + @endif + +
+ @endif +
+
+ + +
+
+
+ + @if($this->rows->hasPages()) +
+
{{ $this->rows->links() }}
+
+ @endif + @endif +
+
diff --git a/src/Http/Livewire/QueryBuilder/Concerns/WithFilters.php b/src/Http/Livewire/QueryBuilder/Concerns/WithFilters.php new file mode 100644 index 0000000..0e32984 --- /dev/null +++ b/src/Http/Livewire/QueryBuilder/Concerns/WithFilters.php @@ -0,0 +1,52 @@ +displayFilters && count($this->filters()) > 0; + } + + public function displayFilters(bool $displayFilters = true): static + { + $this->displayFilters = $displayFilters; + + return $this; + } + + public function filters(): array + { + return [ + TextFilter::make('Name', 'full_name')->useOperator('like'), + SelectFilter::make('Location', 'contract.location.name')->withOptions([ + 'ACT Skills Centre, Caerphilly' => 'ACT Skills Centre, Caerphilly', + 'Home Based' => 'Home Based', + ]), + BooleanFilter::make('Line Manager', 'contract.line_manager'), + DateFilter::make('Started on or after', 'contract.start_date')->useOperator('>='), + DateFilter::make('Started on or before', 'contract.start_date')->useOperator('<='), + ]; + } + + public function resetFilters(): void + { + $this->filterValues = []; + $this->resetPage(); + } + + public function updatedFilterValues(): void + { + $this->resetPage(); + } +} diff --git a/src/Http/Livewire/QueryBuilder/Concerns/WithPagination.php b/src/Http/Livewire/QueryBuilder/Concerns/WithPagination.php index d541310..0388ded 100644 --- a/src/Http/Livewire/QueryBuilder/Concerns/WithPagination.php +++ b/src/Http/Livewire/QueryBuilder/Concerns/WithPagination.php @@ -13,7 +13,7 @@ trait WithPagination public function applyPagination($query) { if ($this->paginate) { - return $query->paginate($this->perPage); + return $query->ray()->paginate($this->perPage); } else { return $query->get(); } diff --git a/src/Http/Livewire/QueryBuilder/Filters/BaseFilter.php b/src/Http/Livewire/QueryBuilder/Filters/BaseFilter.php new file mode 100644 index 0000000..ebcf556 --- /dev/null +++ b/src/Http/Livewire/QueryBuilder/Filters/BaseFilter.php @@ -0,0 +1,80 @@ +key = $key; + $this->label = $label; + $this->code = $label.':'.$this->operator; + } + + public static function make($label, $key = null): static + { + if (is_null($key)) { + $key = Str::snake($label); + } + + return new static($key, $label); + } + + public function label(): string + { + return $this->label; + } + + public function key(): string + { + return $this->key; + } + + public function operator(): string + { + return $this->operator; + } + + public function code(): string + { + return $this->code; + } + + public function component(): string + { + return $this->component; + } + + public function useOperator(string $operator): static + { + $this->operator = $operator; + $this->code = $this->label.':'.$this->operator; + + return $this; + } + + public function useComponent(string $component): static + { + $this->component = $component; + + return $this; + } + + public function parseValue($value) + { + return $value; + } +} diff --git a/src/Http/Livewire/QueryBuilder/Filters/BooleanFilter.php b/src/Http/Livewire/QueryBuilder/Filters/BooleanFilter.php new file mode 100644 index 0000000..b4b23c3 --- /dev/null +++ b/src/Http/Livewire/QueryBuilder/Filters/BooleanFilter.php @@ -0,0 +1,21 @@ +startOfDay(); + } +} diff --git a/src/Http/Livewire/QueryBuilder/Filters/NumberFilter.php b/src/Http/Livewire/QueryBuilder/Filters/NumberFilter.php new file mode 100644 index 0000000..1acaa4b --- /dev/null +++ b/src/Http/Livewire/QueryBuilder/Filters/NumberFilter.php @@ -0,0 +1,7 @@ +options; + } + + public function withOptions(array $options = []): static + { + $this->options = $options; + + return $this; + } +} diff --git a/src/Http/Livewire/QueryBuilder/Filters/TextFilter.php b/src/Http/Livewire/QueryBuilder/Filters/TextFilter.php new file mode 100644 index 0000000..72351ef --- /dev/null +++ b/src/Http/Livewire/QueryBuilder/Filters/TextFilter.php @@ -0,0 +1,15 @@ +operator() === 'like') { + return "%{$value}%"; + } + + return $value; + } +} diff --git a/src/QueryBuilder.php b/src/QueryBuilder.php index d91609d..3ed8281 100755 --- a/src/QueryBuilder.php +++ b/src/QueryBuilder.php @@ -8,6 +8,7 @@ use ACTTraining\QueryBuilder\Http\Livewire\QueryBuilder\Concerns\WithActions; use ACTTraining\QueryBuilder\Http\Livewire\QueryBuilder\Concerns\WithCaching; use ACTTraining\QueryBuilder\Http\Livewire\QueryBuilder\Concerns\WithColumns; +use ACTTraining\QueryBuilder\Http\Livewire\QueryBuilder\Concerns\WithFilters; use ACTTraining\QueryBuilder\Http\Livewire\QueryBuilder\Concerns\WithPagination; use ACTTraining\QueryBuilder\Http\Livewire\QueryBuilder\Concerns\WithQueryBuilder; use ACTTraining\QueryBuilder\Http\Livewire\QueryBuilder\Concerns\WithRowClick; @@ -28,6 +29,7 @@ abstract class QueryBuilder extends Component use WithActions; use WithCaching; use WithColumns; + use WithFilters; use WithPagination; use WithQueryBuilder; use WithRowClick; diff --git a/src/Table.php b/src/Table.php new file mode 100755 index 0000000..9cfc0b9 --- /dev/null +++ b/src/Table.php @@ -0,0 +1,98 @@ + '$refresh', + ]; + + abstract public function query(): Builder; + + public function booted(): void + { + $this->config(); + + } + + public function config(): void + { + // + } + + public function getRowsQueryProperty() + { + $query = $this->query()->when($this->sortBy !== '', function ($query) { + $query->orderBy($this->sortBy, $this->sortDirection); + }); + + $dottedFilterValue = Arr::dot($this->filterValues); + + foreach ($this->filters() as $filter) { + $value = $dottedFilterValue[$filter->code()] ?? null; + + $query->when($value !== null, function ($query) use ($filter, $value) { + $value = $filter->parseValue($value); + if (Str::contains($filter->key(), '.')) { + $relation = Str::beforeLast($filter->key(), '.'); + $column = Str::afterLast($filter->key(), '.'); + + $query->whereHas($relation, function ($query) use ($filter, $value, $column) { + $query->where($column, $filter->operator(), $value); + }); + } else { + $query->where($filter->key(), $filter->operator(), $value); + } + }); + } + + return $query; + } + + /** + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + public function getRowsProperty() + { + return $this->applyPagination($this->rowsQuery); + } + + protected function model(): Model + { + $model = $this->model; + + return app($model); + } + + public function render(): Factory|View + { + return view('query-builder::table'); + } +}