Skip to content

Commit

Permalink
Tidying Filters - Migrating Carbon usage into Trait, Adding Lifecycle…
Browse files Browse the repository at this point in the history
… Hooks (#1798)

* Tweaks to handle dates centrally

* Add localisation for DateFilter, DateTimeFilter, migrate DateRangeFilter to use Core Trait

* Add Filter Lifecycle Hooks

* Add Search Lifecycle Hook

* Adjust lifecycle hooks, adding docs

* Update DateFilter, DateTimeFilter validate returns

* Update DateRangeFilterTest

* Update ChangeLog

* Add Pills Locale Tests to DateTests

* Remove superfluous method

---------

Co-authored-by: lrljoe <[email protected]>
  • Loading branch information
lrljoe and lrljoe authored Jul 27, 2024
1 parent 8bc636a commit 5aaaded
Show file tree
Hide file tree
Showing 13 changed files with 356 additions and 205 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ All notable changes to `laravel-livewire-tables` will be documented in this file
### New Features
- Added capability to setFilterDefaultValue for a DateRangeFilter by @lrljoe in https://github.com/rappasoft/laravel-livewire-tables/pull/1796

### Tweaks
- Migrating Carbon usage into Trait, Adding Filter/Search Lifecycle Hooks by @lrljoe in https://github.com/rappasoft/laravel-livewire-tables/pull/1798

## [v3.3.3] - 2024-07-23
### New Features
- Add additional DateRangeFilter options by @lrljoe in https://github.com/rappasoft/laravel-livewire-tables/pull/1793
Expand Down
18 changes: 18 additions & 0 deletions docs/misc/lifecycle-hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,24 @@ This is called immediately after the Columns are set up
## rowsRetrieved
This is called immediately after the query is executed, and is passed the result from the executed query.

## searchUpdated
This is called whenever the search is updated, and is passed the value that has been searched for

## filterApplying
This is called whenever a Filter is applying

## filterReset
This is called whenever a Filter is reset

## filterSet
This is called whenever a Filter is set

## filterUpdated
This is called whenever a Filter is updated/used

## filterRemoved
This is called whenever a Filter is removed from the table

## Use in Traits
To use these in a trait, allowing you to easily set defaults across multiple tables, you should ensure that you append the Lifecycle Hook with your trait name, e.g.

Expand Down
6 changes: 6 additions & 0 deletions src/Traits/Helpers/FilterHelpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,10 @@ public function getFilterByKey(string $key)
public function setFilter(string $filterKey, mixed $value): void
{
$this->appliedFilters[$filterKey] = $this->filterComponents[$filterKey] = $value;

$this->callHook('filterSet', ['filter' => $filterKey, 'value' => $value]);
$this->callTraitHook('filterSet', ['filter' => $filterKey, 'value' => $value]);

}

public function selectAllFilterOptions(string $filterKey): void
Expand Down Expand Up @@ -238,6 +242,8 @@ public function resetFilter($filter): void
if (! $filter instanceof Filter) {
$filter = $this->getFilterByKey($filter);
}
$this->callHook('filterReset', ['filter' => $filter->getKey()]);
$this->callTraitHook('filterReset', ['filter' => $filter->getKey()]);

$this->setFilter($filter->getKey(), $filter->getDefaultValue());
}
Expand Down
10 changes: 10 additions & 0 deletions src/Traits/WithFilters.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ public function applyFilters(): Builder
continue;
}

$this->callHook('filterApplying', ['filter' => $filter->getKey(), 'value' => $value]);
$this->callTraitHook('filterApplying', ['filter' => $filter->getKey(), 'value' => $value]);

($filter->getFilterCallback())($this->getBuilder(), $value);
}
}
Expand All @@ -84,7 +87,14 @@ public function updatedFilterComponents(string|array|null $value, string $filter
$filter = $this->getFilterByKey($filterName);

if ($filter && $filter->isEmpty($value)) {
$this->callHook('filterRemoved', ['filter' => $filter->getKey()]);
$this->callTraitHook('filterRemoved', ['filter' => $filter->getKey()]);

$this->resetFilter($filterName);
} elseif ($filter) {
$this->callHook('filterUpdated', ['filter' => $filter->getKey(), 'value' => $value]);
$this->callTraitHook('filterUpdated', ['filter' => $filter->getKey(), 'value' => $value]);

}
}
}
3 changes: 3 additions & 0 deletions src/Traits/WithSearch.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ public function applySearch(): Builder
if ($this->searchIsEnabled() && $this->hasSearch()) {
$searchableColumns = $this->getSearchableColumns();

$this->callHook('searchUpdated', ['value' => $this->getSearch()]);
$this->callTraitHook('searchUpdated', ['value' => $this->getSearch()]);

if ($searchableColumns->count()) {
$this->setBuilder($this->getBuilder()->where(function ($query) use ($searchableColumns) {
foreach ($searchableColumns as $index => $column) {
Expand Down
15 changes: 7 additions & 8 deletions src/Views/Filters/DateFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

namespace Rappasoft\LaravelLivewireTables\Views\Filters;

use DateTime;
use Rappasoft\LaravelLivewireTables\Views\Filter;
use Rappasoft\LaravelLivewireTables\Views\Traits\Core\HasWireables;
use Rappasoft\LaravelLivewireTables\Views\Traits\Filters\{HasConfig, IsStringFilter};
use Rappasoft\LaravelLivewireTables\Views\Traits\Filters\{HandlesDates, HasConfig, IsStringFilter};

class DateFilter extends Filter
{
use HasConfig,
use HandlesDates,
HasConfig,
IsStringFilter;
use HasWireables;

Expand All @@ -21,17 +21,16 @@ class DateFilter extends Filter

public function validate(string $value): string|bool
{
if (DateTime::createFromFormat('Y-m-d', $value) === false) {
return false;
}
$this->setInputDateFormat('Y-m-d')->setOutputDateFormat($this->getConfig('pillFormat') ?? 'Y-m-d');
$carbonDate = $this->createCarbonDate($value);

return $value;
return ($carbonDate === false) ? false : $carbonDate->format('Y-m-d');
}

public function getFilterPillValue($value): string|array|null
{
if ($this->validate($value)) {
return DateTime::createFromFormat('Y-m-d', $value)->format($this->getConfig('pillFormat'));
return $this->outputTranslatedDate($this->createCarbonDate($value));
}

return null;
Expand Down
34 changes: 16 additions & 18 deletions src/Views/Filters/DateRangeFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
use Illuminate\Support\Facades\Validator;
use Rappasoft\LaravelLivewireTables\Views\Filter;
use Rappasoft\LaravelLivewireTables\Views\Traits\Core\HasWireables;
use Rappasoft\LaravelLivewireTables\Views\Traits\Filters\{HasConfig,HasOptions};
use Rappasoft\LaravelLivewireTables\Views\Traits\Filters\{HandlesDates, HasConfig,HasOptions};

class DateRangeFilter extends Filter
{
use HasOptions,
use HandlesDates,
HasOptions,
HasConfig;
use HasWireables;

Expand All @@ -31,6 +32,8 @@ public function validate(array|string $values): array|bool
{
$this->getOptions();
$this->getConfigs();
$this->setInputDateFormat($this->getConfig('dateFormat'))->setOutputDateFormat($this->getConfig('ariaDateFormat'));
$dateFormat = $this->getConfigs()['dateFormat'];

$returnedValues = ['minDate' => '', 'maxDate' => ''];
if (is_array($values)) {
Expand All @@ -57,17 +60,15 @@ public function validate(array|string $values): array|bool
return false;
}

$dateFormat = $this->getConfigs()['dateFormat'];

$validator = Validator::make($returnedValues, [
'minDate' => 'required|date_format:'.$dateFormat,
'maxDate' => 'required|date_format:'.$dateFormat,
]);
if ($validator->fails()) {
return false;
}
$startDate = Carbon::createFromFormat($dateFormat, $returnedValues['minDate']);
$endDate = Carbon::createFromFormat($dateFormat, $returnedValues['maxDate']);
$startDate = $this->createCarbonDate($returnedValues['minDate']);
$endDate = $this->createCarbonDate($returnedValues['maxDate']);

if (! ($startDate instanceof Carbon) || ! ($endDate instanceof Carbon)) {
return false;
Expand All @@ -86,8 +87,8 @@ public function validate(array|string $values): array|bool
'latest' => 'date_format:'.$dateFormat,
]);
if (! $earlyLateValidator->fails()) {
$earliestDate = Carbon::createFromFormat($dateFormat, $earliestDateString);
$latestDate = Carbon::createFromFormat($dateFormat, $latestDateString);
$earliestDate = $this->createCarbonDate($earliestDateString);
$latestDate = $this->createCarbonDate($latestDateString);

if ($earliestDate instanceof Carbon) {
if ($startDate->lt($earliestDate)) {
Expand Down Expand Up @@ -154,20 +155,17 @@ public function getFilterPillValue($value): string|array|null
$validatedValue = $this->validate($value);

if (is_array($validatedValue)) {
$dateFormat = $this->getConfig('dateFormat');
$ariaDateFormat = $this->getConfig('ariaDateFormat');
$locale = $this->getConfig('locale') ?? config('app.locale', 'en');

$carbon = new Carbon;
$carbon->setLocale($locale);
if ($this->hasConfig('locale')) {
$this->setPillsLocale($this->getConfig('locale'));
}

$minDate = $carbon->createFromFormat($dateFormat, $validatedValue['minDate']);
$maxDate = $carbon->createFromFormat($dateFormat, $validatedValue['maxDate']);
$minDate = $this->createCarbonDate($validatedValue['minDate']);
$maxDate = $this->createCarbonDate($validatedValue['maxDate']);

if (($minDate instanceof Carbon) && $maxDate instanceof Carbon) {
return $minDate->translatedFormat($ariaDateFormat)
return $this->outputTranslatedDate($minDate)
.' '.__('to').' '.
$maxDate->translatedFormat($ariaDateFormat);
$this->outputTranslatedDate($maxDate);
}
}

Expand Down
16 changes: 8 additions & 8 deletions src/Views/Filters/DateTimeFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

namespace Rappasoft\LaravelLivewireTables\Views\Filters;

use DateTime;
use Rappasoft\LaravelLivewireTables\Views\Filter;
use Rappasoft\LaravelLivewireTables\Views\Traits\Core\HasWireables;
use Rappasoft\LaravelLivewireTables\Views\Traits\Filters\{HasConfig, IsStringFilter};
use Rappasoft\LaravelLivewireTables\Views\Traits\Filters\{HandlesDates, HasConfig, IsStringFilter};

class DateTimeFilter extends Filter
{
use HasConfig,
use HandlesDates,
HasConfig,
IsStringFilter;
use HasWireables;

Expand All @@ -21,17 +21,17 @@ class DateTimeFilter extends Filter

public function validate(string $value): string|bool
{
if (DateTime::createFromFormat('Y-m-d\TH:i', $value) === false) {
return false;
}
$this->setInputDateFormat('Y-m-d\TH:i')->setOutputDateFormat($this->getConfig('pillFormat'));

$carbonDate = $this->createCarbonDate($value);

return $value;
return ($carbonDate === false) ? false : $carbonDate->format('Y-m-d\TH:i');
}

public function getFilterPillValue($value): string|array|null
{
if ($this->validate($value)) {
return DateTime::createFromFormat('Y-m-d\TH:i', $value)->format($this->getConfig('pillFormat'));
return $this->outputTranslatedDate($this->createCarbonDate($value));
}

return null;
Expand Down
59 changes: 59 additions & 0 deletions src/Views/Traits/Filters/HandlesDates.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

namespace Rappasoft\LaravelLivewireTables\Views\Traits\Filters;

use Carbon\Carbon;

trait HandlesDates
{
use HasPillsLocale;

protected string $inputDateFormat;

protected string $outputDateFormat;

protected Carbon $carbonInstance;

protected function createCarbon()
{
$this->carbonInstance = new Carbon;
$this->carbonInstance->setLocale($this->getPillsLocale());

}

protected function createCarbonDate(string $value): Carbon|bool
{
$this->createCarbon();
$fromFormat = false;
try {
$fromFormat = $this->carbonInstance->createFromFormat($this->inputDateFormat, $value);
} catch (\Exception $e) {
return false;
}

return $fromFormat;
}

protected function setInputDateFormat(string $inputDateFormat): self
{
$this->inputDateFormat = $inputDateFormat;

return $this;
}

protected function setOutputDateFormat(string $outputDateFormat): self
{
$this->outputDateFormat = $outputDateFormat;

return $this;
}

protected function outputTranslatedDate(?Carbon $carbon): string
{
if ($carbon instanceof Carbon) {
return $carbon->translatedFormat($this->outputDateFormat);
}

return '';
}
}
25 changes: 25 additions & 0 deletions src/Views/Traits/Filters/HasPillsLocale.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace Rappasoft\LaravelLivewireTables\Views\Traits\Filters;

trait HasPillsLocale
{
protected ?string $pillsLocale;

public function setPillsLocale(string $pillsLocale): self
{
$this->pillsLocale = $pillsLocale;

return $this;
}

public function hasPillsLocale(): bool
{
return isset($this->pillsLocale);
}

public function getPillsLocale(): string
{
return isset($this->pillsLocale) ? $this->pillsLocale : ($this->getConfig('locale') ?? config('app.locale', 'en'));
}
}
19 changes: 19 additions & 0 deletions tests/Views/Filters/DateFilterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -175,4 +175,23 @@ public function test_can_set_text_filter_wireable_live(): void
$this->assertSame('wire:model.live.debounce.500ms=filterComponents.active', self::$filterInstance->getWireMethod('filterComponents.'.self::$filterInstance->getKey()));

}

public function test_check_if_has_locale(): void
{
$this->assertFalse(self::$filterInstance->hasPillsLocale());
self::$filterInstance->setPillsLocale('fr');
$this->assertTrue(self::$filterInstance->hasPillsLocale());
}

public function test_check_if_can_get_locale(): void
{
$this->assertFalse(self::$filterInstance->hasPillsLocale());
$this->assertSame('en', self::$filterInstance->getPillsLocale());
self::$filterInstance->setPillsLocale('fr');
$this->assertTrue(self::$filterInstance->hasPillsLocale());
$this->assertSame('fr', self::$filterInstance->getPillsLocale());
self::$filterInstance->setPillsLocale('de');
$this->assertSame('de', self::$filterInstance->getPillsLocale());
$this->assertTrue(self::$filterInstance->hasPillsLocale());
}
}
Loading

0 comments on commit 5aaaded

Please sign in to comment.