Skip to content

Commit

Permalink
Merge pull request #454 from Power-Components/feature/searchable-raw
Browse files Browse the repository at this point in the history
add searchableRaw
  • Loading branch information
luanfreitasdev authored Jun 6, 2022
2 parents 8ccf07b + b8954f2 commit a9ea5c0
Show file tree
Hide file tree
Showing 5 changed files with 206 additions and 11 deletions.
16 changes: 15 additions & 1 deletion src/Column.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ final class Column

public bool $searchable = false;

public string $searchableRaw = '';

public bool $sortable = false;

public array $sum = [
Expand Down Expand Up @@ -118,7 +120,6 @@ public function placeholder(string $placeholder): Column
/**
* Makes the column searchable
*
* @return Column
*/
public function searchable(): Column
{
Expand All @@ -127,6 +128,19 @@ public function searchable(): Column
return $this;
}

/**
* Makes the column searchable with SQL Raw
*
*/
public function searchableRaw(string $sql): Column
{
$this->searchable();

$this->searchableRaw = $sql;

return $this;
}

/**
* Adds sort to the column header
*
Expand Down
10 changes: 6 additions & 4 deletions src/Helpers/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -263,10 +263,8 @@ public function filterContains(): Model

/** @var Column $column */
foreach ($this->columns as $column) {
/** @var string $searchable */
$searchable = data_get($column, 'searchable');
/** @var string $field */
$field = data_get($column, 'dataField') ?: data_get($column, 'field');
$searchable = strval(data_get($column, 'searchable'));
$field = strval(data_get($column, 'dataField')) ?: strval(data_get($column, 'field'));

if ($searchable && $field) {
if (str_contains($field, '.')) {
Expand All @@ -282,6 +280,10 @@ public function filterContains(): Model
if ($hasColumn) {
$query->orWhere($table . '.' . $field, SqlSupport::like(), '%' . $this->search . '%');
}

if ($sqlRaw = strval(data_get($column, 'searchableRaw'))) {
$query->orWhereRaw($sqlRaw . ' ' . SqlSupport::like() . ' \'%' . $this->search . '%\'');
}
}
}

Expand Down
97 changes: 97 additions & 0 deletions tests/DishesSearchableRawTable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?php

namespace PowerComponents\LivewirePowerGrid\Tests;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\DB;
use PowerComponents\LivewirePowerGrid\Tests\Models\Dish;
use PowerComponents\LivewirePowerGrid\Traits\ActionButton;
use PowerComponents\LivewirePowerGrid\{Column,
Footer,
Header,
PowerGrid,
PowerGridComponent,
PowerGridEloquent};

class DishesSearchableRawTable extends PowerGridComponent
{
use ActionButton;

public string $database = '';

public function setUp(): array
{
$this->showCheckBox();

return [
Header::make()
->showSearchInput(),

Footer::make()
->showPerPage()
->showRecordCount(),
];
}

public function datasource(): Builder
{
$searchableRaw = match ($this->database) {
'sqlite' => 'STRFTIME("%d/%m/%Y", dishes.produced_at) as produced_at_formatted',
'mysql' => 'DATE_FORMAT(dishes.produced_at, "%d/%m/%Y") as produced_at_formatted',
'pgsql' => 'to_char(dishes.produced_at, \'DD/MM/YYYY\')::text as produced_at_formatted',
default => ''
};

return Dish::query()
->join('categories', function ($categories) {
$categories->on('dishes.category_id', '=', 'categories.id');
})
->select('dishes.*', 'categories.name as category_name', DB::raw($searchableRaw));
}

public function addColumns(): PowerGridEloquent
{
return PowerGrid::eloquent()
->addColumn('id')
->addColumn('name')
->addColumn('produced_at_formatted');
}

public function columns(): array
{
$searchableRaw = match ($this->database) {
'sqlite' => 'STRFTIME("%d/%m/%Y", dishes.produced_at)',
'mysql' => 'DATE_FORMAT(dishes.produced_at, "%d/%m/%Y")',
'pgsql' => 'to_char(dishes.produced_at, \'DD/MM/YYYY\')::text',
default => ''
};

return [
Column::make('ID', 'id')
->searchable()
->sortable(),

Column::make('Prato', 'name')
->searchable()
->editOnClick()
->clickToCopy(true)
->makeInputText('name')
->placeholder('Prato placeholder')
->sortable(),

Column::make('Produced At Formatted', 'produced_at_formatted')
->searchableRaw($searchableRaw)
->sortable(),
];
}

public function bootstrap()
{
config(['livewire-powergrid.theme' => 'bootstrap']);
}

public function tailwind()
{
config(['livewire-powergrid.theme' => 'tailwind']);
}
}
52 changes: 52 additions & 0 deletions tests/Feature/SearchableRawTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

use function Pest\Livewire\livewire;

it('searches data using whereRaw on sqlite', function (string $component, object $params) {
livewire($component, ['database' => 'sqlite'])
->call($params->theme)
->set('search', '09/09/2021')
->assertSee('Polpetone Filé Mignon')
->assertDontSee('Barco-Sushi Simples')
->assertDontSee('No records found')
# 09/09/2022
->set('search', '09/09/2022')
->assertSee('No records found')
# 06/2026
->set('search', '06/2026')
->assertSee('Francesinha')
->assertDontSee('Polpetone Filé Mignon');
})->with('searchable-raw')->requiresSQLite();

it('searches data using whereRaw on mysql', function (string $component, object $params) {
livewire($component, ['database' => 'mysql'])
->call($params->theme)
->call($params->theme)
->set('search', '09/09/2021')
->assertSee('Polpetone Filé Mignon')
->assertDontSee('Barco-Sushi Simples')
->assertDontSee('No records found')
# 09/09/2022
->set('search', '09/09/2022')
->assertSee('No records found')
# 06/2026
->set('search', '06/2026')
->assertSee('Francesinha')
->assertDontSee('Polpetone Filé Mignon');
})->with('searchable-raw')->requiresMySQL();

it('searches data using whereRaw on pgsql', function (string $component, object $params) {
livewire($component, ['database' => 'pgsql'])
->call($params->theme)
->set('search', '09/09/2021')
->assertSee('Polpetone Filé Mignon')
->assertDontSee('Barco-Sushi Simples')
->assertDontSee('No records found')
# 09/09/2022
->set('search', '09/09/2022')
->assertSee('No records found')
# 06/2026
->set('search', '06/2026')
->assertSee('Francesinha')
->assertDontSee('Polpetone Filé Mignon');
})->with('searchable-raw')->requiresPostgreSQL();
42 changes: 36 additions & 6 deletions tests/Pest.php
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
<?php

use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Pest\PendingObjects\TestCall;
use PowerComponents\LivewirePowerGrid\Tests\Models\Dish;
use PowerComponents\LivewirePowerGrid\Tests\TestCase;
use PowerComponents\LivewirePowerGrid\{
Column,
use PowerComponents\LivewirePowerGrid\{Column,
PowerGridComponent,
Tests\DishesActionRulesTable,
Tests\DishesActionTable,
Tests\DishesCalculationsTable,
Tests\DishesCollectionTable,
Tests\DishesDetailRowTable,
Tests\DishesEnumTable,
Tests\DishesMakeTable,
Tests\DishesSearchableRawTable,
Tests\DishesTable,
Tests\DishesTableWithJoin
};
Tests\DishesTableWithJoin};

uses(TestCase::class)->in(__DIR__);

Expand Down Expand Up @@ -47,7 +46,6 @@ function powergrid(): PowerGridComponent
$component = new PowerGridComponent(1);
$component->datasource = Dish::query();
$component->columns = $columns;
$component->perPage = 10;

return $component;
}
Expand Down Expand Up @@ -163,6 +161,11 @@ function expectInputText(object $params, mixed $component, string $value, string
[DishesCollectionTable::class, 'bootstrap'],
]);

dataset('searchable-raw', [
'tailwind' => [DishesSearchableRawTable::class, (object) ['theme' => 'tailwind']],
'bootstrap' => [DishesSearchableRawTable::class, (object) ['theme' => 'bootstrap']],
]);

/**
* Skip tests based on minimum PHP Version
*
Expand All @@ -178,6 +181,33 @@ function onlyFromPhp(string $version): mixed
return test();
}

function requiresMySQL()
{
if (DB::getDriverName() !== 'mysql') {
test()->markTestSkipped('This test requires MySQL database');
}

return test();
}

function requiresSQLite()
{
if (DB::getDriverName() !== 'sqlite') {
test()->markTestSkipped('This test requires SQLite database');
}

return test();
}

function requiresPostgreSQL()
{
if (DB::getDriverName() !== 'pgsql') {
test()->markTestSkipped('This test requires PostgreSQL database');
}

return test();
}

expect()->extend('notToBeFileDownloaded', function ($component) {
$downloadEffect = data_get($component->lastResponse, 'original.effects.download');

Expand Down

0 comments on commit a9ea5c0

Please sign in to comment.