@if (data_get($setUp, 'detail.showCollapseIcon'))
|
@endif
@if ($checkbox)
|
@endif
@foreach ($this->visibleColumns as $column)
+ @php
+ $filterClass = str(data_get($column, 'filters.className'));
+ @endphp
-
- @foreach (data_get($column, 'filters') as $key => $filter)
-
- @if (str(data_get($filter, 'className'))->contains('FilterMultiSelect'))
-
- @endif
- @if (str(data_get($filter, 'className'))->contains(['FilterSelect', 'FilterEnumSelect']))
- @includeIf(data_get($theme, 'filterSelect.view'), [
- 'inline' => true,
- 'column' => $column,
- 'filter' => $filter,
- 'theme' => data_get($theme, 'filterSelect'),
- ])
- @endif
- @if (str(data_get($filter, 'className'))->contains('FilterInputText'))
- @includeIf(data_get($theme, 'filterInputText.view'), [
- 'inline' => true,
- 'filter' => $filter,
- 'theme' => data_get($theme, 'filterInputText'),
- ])
- @endif
- @if (str(data_get($filter, 'className'))->contains('FilterNumber'))
- @includeIf(data_get($theme, 'filterNumber.view'), [
- 'inline' => true,
- 'filter' => $filter,
- 'theme' => data_get($theme, 'filterNumber'),
- ])
- @endif
- @if (str(data_get($filter, 'className'))->contains('FilterDynamic'))
-
- @endif
- @if (str(data_get($filter, 'className'))->contains('FilterDateTimePicker'))
- @includeIf(data_get($theme, 'filterDatePicker.view'), [
- 'inline' => true,
- 'filter' => $filter,
- 'type' => 'datetime',
- 'tableName' => $tableName,
- 'classAttr' => 'w-full',
- 'theme' => data_get($theme, 'filterDatePicker'),
- ])
- @endif
- @if (str(data_get($filter, 'className'))->contains('FilterDatePicker'))
- @includeIf(data_get($theme, 'filterDatePicker.view'), [
- 'inline' => true,
- 'filter' => $filter,
- 'type' => 'date',
- 'tableName' => $tableName,
- 'classAttr' => 'w-full',
- 'theme' => data_get($theme, 'filterDatePicker'),
- ])
- @endif
- @if (str(data_get($filter, 'className'))->contains('FilterBoolean'))
- @includeIf(data_get($theme, 'filterBoolean.view'), [
- 'inline' => true,
- 'filter' => $filter,
- 'theme' => data_get($theme, 'filterBoolean'),
- ])
- @endif
-
- @endforeach
+
+ @if ($filterClass->contains('FilterMultiSelect'))
+
+ @elseif ($filterClass->contains(['FilterSelect', 'FilterEnumSelect']))
+ @includeIf(data_get($theme, 'filterSelect.view'), [
+ 'inline' => true,
+ 'filter' => (array) data_get($column, 'filters'),
+ 'theme' => data_get($theme, 'filterSelect'),
+ ])
+ @elseif ($filterClass->contains('FilterInputText'))
+ @includeIf(data_get($theme, 'filterInputText.view'), [
+ 'inline' => true,
+ 'filter' => (array) data_get($column, 'filters'),
+ 'theme' => data_get($theme, 'filterInputText'),
+ ])
+ @elseif ($filterClass->contains('FilterNumber'))
+ @includeIf(data_get($theme, 'filterNumber.view'), [
+ 'inline' => true,
+ 'filter' => (array) data_get($column, 'filters'),
+ 'theme' => data_get($theme, 'filterNumber'),
+ ])
+ @elseif ($filterClass->contains('FilterDateTimePicker'))
+ @includeIf(data_get($theme, 'filterDatePicker.view'), [
+ 'inline' => true,
+ 'filter' => (array) data_get($column, 'filters'),
+ 'type' => 'datetime',
+ 'tableName' => $tableName,
+ 'classAttr' => 'w-full',
+ 'theme' => data_get($theme, 'filterDatePicker'),
+ ])
+ @elseif ($filterClass->contains('FilterDatePicker'))
+ @includeIf(data_get($theme, 'filterDatePicker.view'), [
+ 'inline' => true,
+ 'filter' => (array) data_get($column, 'filters'),
+ 'type' => 'date',
+ 'classAttr' => 'w-full',
+ 'theme' => data_get($theme, 'filterDatePicker'),
+ ])
+ @elseif ($filterClass->contains('FilterBoolean'))
+ @includeIf(data_get($theme, 'filterBoolean.view'), [
+ 'inline' => true,
+ 'filter' => (array) data_get($column, 'filters'),
+ 'theme' => data_get($theme, 'filterBoolean'),
+ ])
+ @elseif ($filterClass->contains('FilterDynamic'))
+
+ @endif
+
|
@endforeach
@if (isset($actions) && count($actions))
diff --git a/src/Column.php b/src/Column.php
index 0f58bab3..23805a34 100644
--- a/src/Column.php
+++ b/src/Column.php
@@ -2,8 +2,6 @@
namespace PowerComponents\LivewirePowerGrid;
-use Illuminate\Support\Collection;
-
final class Column implements \Livewire\Wireable
{
public string $title = '';
@@ -72,7 +70,7 @@ final class Column implements \Livewire\Wireable
'label' => null,
];
- public ?Collection $filters = null;
+ public mixed $filters = null;
public bool $isAction = false;
diff --git a/src/Components/Filters/Builders/InputText.php b/src/Components/Filters/Builders/InputText.php
index 1083152e..7058e644 100644
--- a/src/Components/Filters/Builders/InputText.php
+++ b/src/Components/Filters/Builders/InputText.php
@@ -36,7 +36,7 @@ public function builder(EloquentBuilder|QueryBuilder $builder, string $field, in
$selected = $values['selected'];
$searchMorphs = $values['searchMorphs'];
- if (is_array($value) && blank($searchMorphs)) {
+ if (is_array($value) && count($value) > 0 && blank($searchMorphs)) {
$field = $field . '.' . key($value);
$value = $value[key($value)];
}
diff --git a/src/Components/Filters/FilterBoolean.php b/src/Components/Filters/FilterBoolean.php
index b75d9915..66ac7fbc 100644
--- a/src/Components/Filters/FilterBoolean.php
+++ b/src/Components/Filters/FilterBoolean.php
@@ -6,6 +6,8 @@
class FilterBoolean extends FilterBase
{
+ public string $key = 'boolean';
+
public string $trueLabel = 'Yes';
public string $falseLabel = 'No';
diff --git a/src/Components/Filters/FilterDatePicker.php b/src/Components/Filters/FilterDatePicker.php
index e4a75033..de08082f 100644
--- a/src/Components/Filters/FilterDatePicker.php
+++ b/src/Components/Filters/FilterDatePicker.php
@@ -5,6 +5,8 @@
/** @codeCoverageIgnore */
class FilterDatePicker extends FilterBase
{
+ public string $key = 'date';
+
public array $params = [];
public function params(array $params): FilterDatePicker
diff --git a/src/Components/Filters/FilterDateTimePicker.php b/src/Components/Filters/FilterDateTimePicker.php
index 7bdbf516..2e699ceb 100644
--- a/src/Components/Filters/FilterDateTimePicker.php
+++ b/src/Components/Filters/FilterDateTimePicker.php
@@ -5,6 +5,8 @@
/** @codeCoverageIgnore */
class FilterDateTimePicker extends FilterBase
{
+ public string $key = 'datetime';
+
public array $params = [];
public function params(array $params): FilterDateTimePicker
diff --git a/src/Components/Filters/FilterEnumSelect.php b/src/Components/Filters/FilterEnumSelect.php
index 82f97d18..2464dcea 100644
--- a/src/Components/Filters/FilterEnumSelect.php
+++ b/src/Components/Filters/FilterEnumSelect.php
@@ -6,6 +6,8 @@
class FilterEnumSelect extends FilterBase
{
+ public string $key = 'select';
+
public array|Collection $dataSource;
public string $optionValue = 'value';
diff --git a/src/Components/Filters/FilterInputText.php b/src/Components/Filters/FilterInputText.php
index d46701da..65e1d9de 100644
--- a/src/Components/Filters/FilterInputText.php
+++ b/src/Components/Filters/FilterInputText.php
@@ -6,6 +6,8 @@
class FilterInputText extends FilterBase
{
+ public string $key = 'input_text';
+
public array $operators = [];
public string $placeholder = '';
@@ -41,7 +43,7 @@ public static function getWireAttributes(string $field, string $title): array
return collect()
->put('selectAttributes', new ComponentAttributeBag([
'wire:model' => 'filters.input_text_options.' . $field,
- 'wire:input.live.debounce.600ms' => 'filterInputTextOptions(\'' . $field . '\', $event.target.value)',
+ 'wire:input.live.debounce.600ms' => 'filterInputTextOptions(\'' . $field . '\', $event.target.value, \'' . $title . '\')',
]))
->put('inputAttributes', new ComponentAttributeBag([
'wire:model' => 'filters.input_text.' . $field,
diff --git a/src/Components/Filters/FilterMultiSelect.php b/src/Components/Filters/FilterMultiSelect.php
index eda80f0b..5fc77ecc 100644
--- a/src/Components/Filters/FilterMultiSelect.php
+++ b/src/Components/Filters/FilterMultiSelect.php
@@ -6,6 +6,8 @@
class FilterMultiSelect extends FilterBase
{
+ public string $key = 'multi_select';
+
public array|Collection $dataSource;
public string $optionValue = '';
diff --git a/src/Components/Filters/FilterMultiSelectAsync.php b/src/Components/Filters/FilterMultiSelectAsync.php
index 924c504c..0eaed6fd 100644
--- a/src/Components/Filters/FilterMultiSelectAsync.php
+++ b/src/Components/Filters/FilterMultiSelectAsync.php
@@ -4,6 +4,8 @@
class FilterMultiSelectAsync extends FilterBase
{
+ public string $key = 'multi_select';
+
public string $url = '';
public string $method = 'get';
diff --git a/src/Components/Filters/FilterNumber.php b/src/Components/Filters/FilterNumber.php
index 4e6df160..574f71a9 100644
--- a/src/Components/Filters/FilterNumber.php
+++ b/src/Components/Filters/FilterNumber.php
@@ -7,6 +7,8 @@
class FilterNumber extends FilterBase
{
+ public string $key = 'number';
+
public string $thousands = '';
public string $decimal = '';
diff --git a/src/Components/Filters/FilterSelect.php b/src/Components/Filters/FilterSelect.php
index 4ec80fa3..495c4c98 100644
--- a/src/Components/Filters/FilterSelect.php
+++ b/src/Components/Filters/FilterSelect.php
@@ -7,6 +7,8 @@
class FilterSelect extends FilterBase
{
+ public string $key = 'select';
+
public array|Collection|\Closure $dataSource;
public string $optionValue = '';
diff --git a/src/Concerns/Filter.php b/src/Concerns/Filter.php
index b547e610..a585fbc1 100644
--- a/src/Concerns/Filter.php
+++ b/src/Concerns/Filter.php
@@ -8,12 +8,12 @@
use function Livewire\store;
-use PowerComponents\LivewirePowerGrid\Column;
-
trait Filter
{
public array $filters = [];
+ public array $test = [];
+
public array $filtered = [];
public array $enabledFilters = [];
@@ -24,16 +24,52 @@ trait Filter
public function clearFilter(string $field = '', bool $emit = true): void
{
- if (str_contains($field, '.')) {
- list($table, $column) = explode('.', $field);
- } else {
- $table = $field;
- $column = null;
- }
+ collect($this->filters())
+ ->each(function ($filter) use ($field) {
+ if (isset($this->filters['multi_select'][$field])) {
+ $this->dispatch('pg:clear_multi_select::' . $this->tableName . ':' . $field);
+ }
+
+ if (isset($this->filters['datetime'][$field]) || isset($this->filters['date'][$field])) {
+ $this->dispatch('pg:clear_flatpickr::' . $this->tableName . ':' . $field);
+ }
+
+ $unset = function ($filter, $field, $column) {
+ $key = data_get($filter, 'key');
+
+ if (str($field)->contains('.')) {
+ $explodeField = explode('.', $field);
+
+ $currentArray = &$this->filters[$key];
+ $lastIndex = array_pop($explodeField);
+
+ foreach ($explodeField as $index) {
+ if (isset($currentArray[$index]) && is_array($currentArray[$index])) {
+ $currentArray = &$currentArray[$index];
+ } else {
+ return;
+ }
+ }
+
+ unset($currentArray[$lastIndex]);
+ } else {
+ unset($this->filters[$key][$field]);
+ }
- $this->clearFilterByTableAndColumn($table, $column);
+ $this->enabledFilters = array_filter(
+ $this->enabledFilters,
+ fn ($filter) => $filter['field'] !== ($column ?? $field)
+ );
+ };
- unset($this->enabledFilters[$field]);
+ if ($field === data_get($filter, 'column')) {
+ $unset($filter, data_get($filter, 'field'), $field);
+ }
+
+ if ($field === data_get($filter, 'field')) {
+ $unset($filter, $field, null);
+ };
+ });
if ($emit) {
$this->dispatch('pg:events', ['event' => 'clearFilters', 'field' => $field, 'tableName' => $this->tableName]);
@@ -42,11 +78,6 @@ public function clearFilter(string $field = '', bool $emit = true): void
$this->persistState('filters');
}
- public function toggleFilters(): void
- {
- $this->showFilters = !$this->showFilters;
- }
-
public function clearAllFilters(): void
{
$this->enabledFilters = [];
@@ -58,6 +89,11 @@ public function clearAllFilters(): void
$this->dispatch('pg:clear_all_multi_select::' . $this->tableName);
}
+ public function toggleFilters(): void
+ {
+ $this->showFilters = !$this->showFilters;
+ }
+
#[On('pg:datePicker-{tableName}')]
public function datePickerChanged(
array $selectedDates,
@@ -91,8 +127,7 @@ public function datePickerChanged(
$endDate->endOfDay()->setTimeZone($appTimeZone);
}
- $this->enabledFilters[$field]['data-field'] = $field;
- $this->enabledFilters[$field]['label'] = $label;
+ $this->addEnabledFilters($field, $label);
$this->filters[$type][$field]['start'] = $startDate;
$this->filters[$type][$field]['end'] = $endDate;
@@ -112,8 +147,10 @@ public function multiSelectChanged(
data_set($this->filters, "multi_select.$field", $values);
- $this->enabledFilters[$field]['id'] = $field;
- $this->enabledFilters[$field]['label'] = $label;
+ $this->enabledFilters[] = [
+ 'field' => $field,
+ 'label' => $label,
+ ];
if (count($values) === 0) {
$this->clearFilter($field, emit: false);
@@ -128,8 +165,7 @@ public function filterSelect(string $field, string $label): void
{
$this->resetPage();
- $this->enabledFilters[$field]['id'] = $field;
- $this->enabledFilters[$field]['label'] = $label;
+ $this->addEnabledFilters($field, $label);
$value = data_get($this->filters, "select.$field");
@@ -151,8 +187,7 @@ public function filterNumberStart(string $field, array $params, string $value):
store($this)->set('filters.number.' . $field . '.thousands', $thousands);
store($this)->set('filters.number.' . $field . '.decimal', $decimal);
- $this->enabledFilters[$field]['id'] = $field;
- $this->enabledFilters[$field]['label'] = $title;
+ $this->addEnabledFilters($field, $title);
if (blank($value)) {
$this->clearFilter($field, emit: false);
@@ -172,8 +207,7 @@ public function filterNumberEnd(string $field, array $params, string $value): vo
store($this)->set('filters.number.' . $field . '.thousands', $thousands);
store($this)->set('filters.number.' . $field . '.decimal', $decimal);
- $this->enabledFilters[$field]['id'] = $field;
- $this->enabledFilters[$field]['label'] = $title;
+ $this->addEnabledFilters($field, $title);
if (blank($value)) {
$this->clearFilter($field, emit: false);
@@ -188,8 +222,7 @@ public function filterBoolean(string $field, string $value, string $label): void
{
$this->resetPage();
- $this->enabledFilters[$field]['id'] = $field;
- $this->enabledFilters[$field]['label'] = $label;
+ $this->addEnabledFilters($field, $label);
if ($value == 'all') {
$this->clearFilter($field, emit: false);
@@ -204,8 +237,7 @@ public function filterInputText(string $field, string $value, string $label = ''
{
$this->resetPage();
- $this->enabledFilters[$field]['id'] = $field;
- $this->enabledFilters[$field]['label'] = $label;
+ $this->addEnabledFilters($field, $label);
if (blank($value)) {
$this->clearFilter($field, emit: false);
@@ -216,18 +248,16 @@ public function filterInputText(string $field, string $value, string $label = ''
$this->persistState('filters');
}
- public function filterInputTextOptions(string $field, string $value): void
+ public function filterInputTextOptions(string $field, string $value, string $label = ''): void
{
data_set($this->filters, 'input_text_options.' . $field, $value);
- $this->enabledFilters[$field]['id'] = $field;
+ $disabled = false;
$this->resetPage();
- $this->enabledFilters[$field]['disabled'] = false;
-
if (in_array($value, ['is_empty', 'is_not_empty', 'is_null', 'is_not_null', 'is_blank', 'is_not_blank'])) {
- $this->enabledFilters[$field]['disabled'] = true;
+ $disabled = true;
if (str($field)->contains('.')) {
$this->filters['input_text'][str($field)->before('.')->toString()][str($field)->after('.')->toString()] = null;
@@ -236,6 +266,14 @@ public function filterInputTextOptions(string $field, string $value): void
}
}
+ if (!collect($this->enabledFilters)->where('field', $field)->count()) {
+ $this->enabledFilters[] = [
+ 'field' => $field,
+ 'label' => $label,
+ 'disabled' => $disabled,
+ ];
+ }
+
if (blank($value)) {
$this->clearFilter($field, emit: false);
}
@@ -243,42 +281,6 @@ public function filterInputTextOptions(string $field, string $value): void
$this->persistState('filters');
}
- private function clearFilterByTableAndColumn(string $table, ?string $column): void
- {
- $keys = [$table, $table . '.' . $column];
-
- foreach ($keys as $key) {
- $this->clearFilterByKey($key, $table, $column);
- }
- }
-
- private function clearFilterByKey(string $key, string $table, ?string $column): void
- {
- if (isset($this->filters['multi_select'][$key])) {
- $this->dispatch('pg:clear_multi_select::' . $this->tableName . ':' . $key);
- }
-
- if (isset($this->filters['datetime'][$key]) || isset($this->filters['date'][$key])) {
- $this->dispatch('pg:clear_flatpickr::' . $this->tableName . ':' . $key);
- }
-
- $filterTypes = ['input_text', 'input_text_options', 'number', 'boolean', 'datetime', 'date', 'select', 'multi_select'];
-
- foreach ($filterTypes as $type) {
- $this->unsetFilter($type, $key, $table, $column);
- }
- }
-
- private function unsetFilter(string $type, string $key, string $table, ?string $column): void
- {
- unset($this->filters[$type][$key]);
- unset($this->filters[$type][$table][$column]);
-
- if (empty($this->filters[$type][$table])) {
- unset($this->filters[$type][$table]);
- }
- }
-
private function resolveFilters(): void
{
$filters = collect($this->filters());
@@ -287,26 +289,9 @@ private function resolveFilters(): void
return;
}
- /** @var Column $column */
- foreach ($this->columns as $column) {
- if (str(strval(data_get($column, 'dataField')))->contains('.')) {
- $field = strval(data_get($column, 'field'));
- } else {
- $field = filled(data_get($column, 'dataField')) ? data_get($column, 'dataField') : data_get($column, 'field');
- }
-
- $filterForColumn = $filters->filter(
- fn ($filter) => data_get($filter, 'column') == $field
- );
-
- if ($filterForColumn->count() > 0) {
- $filterForColumn->transform(function ($filter) use ($column) {
- data_set($filter, 'title', data_get($column, 'title'));
-
- return $filter;
- });
-
- data_set($column, 'filters', $filterForColumn->map(function ($filter) {
+ $filters->each(function ($filter) {
+ $this->columns = collect($this->columns)->map(function ($column) use ($filter) {
+ if (data_get($column, 'field') === data_get($filter, 'column')) {
if (data_get($filter, 'dataSource') instanceof \Closure) {
$depends = (array) data_get($filter, 'depends');
$closure = data_get($filter, 'dataSource');
@@ -324,13 +309,20 @@ private function resolveFilters(): void
data_forget($filter, 'collection');
if (!is_array($filter) && method_exists($filter, 'execute')) {
- return (array) $filter->execute();
+ $filter = $filter->execute();
}
- return (array) $filter;
- }));
+ data_set($column, 'filters', (array) $filter);
+
+ if (isset($this->filters[data_get($filter, 'key')])
+ && in_array(data_get($filter, 'field'), array_keys($this->filters[data_get($filter, 'key')]))
+ && array_values($this->filters[data_get($filter, 'key')])) {
+ $this->enabledFilters[] = [
+ 'field' => data_get($filter, 'field'),
+ 'label' => data_get($column, 'title'),
+ ];
+ }
- $filterForColumn->each(function ($filter) {
if (data_get($filter, 'className') === 'PowerComponents\LivewirePowerGrid\Components\Filters\FilterDynamic' &&
filled(data_get($filter, 'attributes'))) {
$attributes = array_values((array) data_get($filter, 'attributes'));
@@ -341,12 +333,22 @@ private function resolveFilters(): void
}
}
}
- });
+ }
- continue;
- }
+ return $column;
+ })->toArray();
+ });
+ }
- data_set($column, 'filters', collect([]));
+ public function addEnabledFilters(string $field, ?string $label): void
+ {
+ if (!collect($this->enabledFilters)
+ ->where('field', $field)
+ ->count()) {
+ $this->enabledFilters[] = [
+ 'field' => $field,
+ 'label' => $label,
+ ];
}
}
}
diff --git a/src/PowerGridColumns.php b/src/PowerGridColumns.php
index 38aef819..361700c0 100644
--- a/src/PowerGridColumns.php
+++ b/src/PowerGridColumns.php
@@ -5,7 +5,7 @@
use Closure;
use Illuminate\Support\Traits\Macroable;
-/** @deprecated */
+/** @deprecated - Use 'PowerGridFields' instead of PowerGridColumns */
final class PowerGridColumns
{
use Macroable;
diff --git a/src/PowerGridComponent.php b/src/PowerGridComponent.php
index f90f8eba..682e1467 100644
--- a/src/PowerGridComponent.php
+++ b/src/PowerGridComponent.php
@@ -7,11 +7,12 @@
use Illuminate\Contracts\View\{Factory, View};
use Illuminate\Database\Eloquent\Relations\MorphToMany;
use Illuminate\Pagination\{LengthAwarePaginator, Paginator};
-use Illuminate\Support\{Collection as BaseCollection, Facades\Cache};
+use Illuminate\Support\{Arr, Collection as BaseCollection, Facades\Cache};
-use function Livewire\store;
+use Livewire\{Attributes\Computed, Component, Features\SupportQueryString\BaseUrl, WithPagination};
+
+use function Livewire\{invade, store};
-use Livewire\{Attributes\Computed, Component, WithPagination};
use PowerComponents\LivewirePowerGrid\Themes\ThemeBase;
use Throwable;
@@ -35,6 +36,55 @@ class PowerGridComponent extends Component
use Concerns\Summarize;
use Concerns\SoftDeletes;
+ protected function powerGridQueryString(): array
+ {
+ $queryString = [];
+
+ foreach (Arr::dot($this->filters()) as $filter) {
+ $as = str($filter->field)
+ ->replace('_id', '');
+
+ if ($as->contains('.')) {
+ $as = $as->afterLast('.');
+ }
+
+ if ($filter->key === 'input_text') {
+ $queryString['filters.input_text.' . $filter->field] = [
+ 'as' => $as->toString(),
+ 'except' => '',
+ ];
+
+ $queryString['filters.input_text_options.' . $filter->field] = [
+ 'as' => $as->append('_operator')->toString(),
+ 'except' => '',
+ ];
+
+ continue;
+ }
+
+ if ($filter->key === 'number') {
+ $queryString['filters.number.' . $filter->field . '.start'] = [
+ 'as' => $as->append('_start')->toString(),
+ 'except' => '',
+ ];
+
+ $queryString['filters.number.' . $filter->field . '.end'] = [
+ 'as' => $as->append('_end')->toString(),
+ 'except' => '',
+ ];
+
+ continue;
+ }
+
+ $queryString['filters.' . $filter->key . '.' . $filter->field] = [
+ 'as' => $as->toString(),
+ 'except' => '',
+ ];
+ }
+
+ return $queryString;
+ }
+
public function mount(): void
{
$this->readyToLoad = !$this->deferLoading;
@@ -50,6 +100,8 @@ public function mount(): void
$this->resolveTotalRow();
$this->restoreState();
+
+ $this->resolveFilters();
}
public function fetchDatasource(): void
@@ -199,8 +251,6 @@ public function getPublicPropertiesDefinedInComponent(): array
*/
public function render(): Application|Factory|View
{
- $this->resolveFilters();
-
/** @var ThemeBase $themeBase */
$themeBase = PowerGrid::theme($this->template() ?? powerGridTheme());
diff --git a/tests/Feature/ArchitectureTest.php b/tests/Feature/ArchitectureTest.php
deleted file mode 100644
index 6ed4c2a7..00000000
--- a/tests/Feature/ArchitectureTest.php
+++ /dev/null
@@ -1,9 +0,0 @@
-expect(['dump', 'dd', 'ddd', 'kint', 'ray', 'ds', 'var_dump', 'print_r', 'exit', 'die'])
- ->not->toBeUsed();
-
-arch('PowerGrid do not use to Strict Types')
- ->expect('\PowerComponents\LivewirePowerGrid')
- ->not->toUseStrictTypes();
diff --git a/tests/Feature/Filters/FilterInputOptionsCollectionTest.php b/tests/Feature/Filters/FilterInputOptionsCollectionTest.php
deleted file mode 100644
index ea14cd35..00000000
--- a/tests/Feature/Filters/FilterInputOptionsCollectionTest.php
+++ /dev/null
@@ -1,295 +0,0 @@
-operators();
- $livewire = livewire($component, [
- 'testFilters' => [$filter],
- ])
- ->call($theme)
- ->set('filters', filterInputText('Name 1', 'is'))
- ->assertSee('Name 1')
- ->assertDontSee('Name 2')
- ->call('clearFilter', 'name')
- ->assertSeeText('Name 1');
-
- expectColumnsFilterMatch($livewire, $filter);
- }
-)->group('filters', 'filterInputText')
- ->with('filter_input_text_options_themes_collection', 'filter_input_text_options_themes_array');
-
-it(
- 'properly filters by "name is" using nonexistent record using collection & array table',
- fn (string $component, string $theme) => livewire($component)
- ->call($theme)
- ->set('testFilters', [
- Filter::inputText('name')->operators(),
- ])
- ->set('filters', filterInputText('Name 6', 'is'))
- ->assertSee('No records found')
- ->assertDontSee('Name 1')
-)->group('filters', 'filterInputText')
- ->with('filter_input_text_options_themes_collection', 'filter_input_text_options_themes_array');
-
-it(
- 'properly filters by "name is not" using collection & array table',
- fn (string $component, string $theme) => livewire($component)
- ->call($theme)
- ->set('testFilters', [
- Filter::inputText('name')->operators(),
- ])
- ->set('filters', filterInputText('Name 2', 'is_not'))
- ->assertSee('Name 1')
- ->assertDontSee('NAme 2')
- ->call('clearFilter', 'name')
- ->assertSee('Name 2')
-)->group('filters', 'filterInputText')
- ->with('filter_input_text_options_themes_collection', 'filter_input_text_options_themes_array');
-
-it(
- 'properly filters by "name is not" using nonexistent record using collection & array table',
- fn (string $component, string $theme) => livewire($component)
- ->call($theme)
- ->set('testFilters', [
- Filter::inputText('name')->operators(),
- ])
- ->set('filters', filterInputText('Name 6', 'is_not'))
- ->assertSee('Name 5')
- ->assertSee('Name 4')
- ->call('clearFilter', 'name')
-)->group('filters', 'filterInputText')
- ->with('filter_input_text_options_themes_collection', 'filter_input_text_options_themes_array');
-
-it(
- 'properly filters by "name contains" using collection & array table',
- fn (string $component, string $theme) => livewire($component)
- ->call($theme)
- ->set('testFilters', [
- Filter::inputText('name')->operators(),
- ])
- ->set('filters', filterInputText('4', 'contains'))
- ->assertSee('Name 4')
- ->assertDontSee('Name 2')
-)->group('filters', 'filterInputText')
- ->with('filter_input_text_options_themes_collection', 'filter_input_text_options_themes_array');
-
-it(
- 'properly filters by "name contains" using nonexistent record using collection & array table',
- fn (string $component, string $theme) => livewire($component)
- ->call($theme)
- ->set('testFilters', [
- Filter::inputText('name')->operators(),
- ])
- ->set('filters', filterInputText('Name 6', 'contains'))
- ->assertSee('No records found')
- ->assertDontSee('Name 1')
- ->assertDontSee('Name 2')
-)->group('filters', 'filterInputText')
- ->with('filter_input_text_options_themes_collection', 'filter_input_text_options_themes_array');
-
-it(
- 'properly filters by "name contains not" using collection & array table',
- fn (string $component, string $theme) => livewire($component)
- ->call($theme)
- ->set('testFilters', [
- Filter::inputText('name')->operators(),
- ])
- ->set('filters', filterInputText('5', 'contains_not'))
- ->assertDontSee('Name 5')
- ->assertSee('Name 1')
-)->group('filters', 'filterInputText')
- ->with('filter_input_text_options_themes_collection', 'filter_input_text_options_themes_array');
-
-it(
- 'properly filters by "name contains not" using nonexistent record using collection & array table',
- fn (string $component, string $theme) => livewire($component)
- ->call($theme)
- ->set('testFilters', [
- Filter::inputText('name')->operators(),
- ])
- ->set('filters', filterInputText('Name 6', 'contains_not'))
- ->assertSee('Name 1')
- ->assertSee('Name 2')
-)->group('filters', 'filterInputText')
- ->with('filter_input_text_options_themes_collection', 'filter_input_text_options_themes_array');
-
-it(
- 'properly filters by "name starts with" using collection & array table',
- fn (string $component, string $theme) => livewire($component)
- ->call($theme)
- ->set('testFilters', [
- Filter::inputText('name')->operators(),
- ])
- ->set('filters', filterInputText('Na', 'starts_with'))
- ->assertSee('Name 1')
- ->assertSee('Name 2')
-)->group('filters', 'filterInputText')
- ->with('filter_input_text_options_themes_collection', 'filter_input_text_options_themes_array');
-
-it(
- 'properly filters by "name starts with" using nonexistent record using collection & array table',
- fn (string $component, string $theme) => livewire($component)
- ->call($theme)
- ->set('testFilters', [
- Filter::inputText('name')->operators(),
- ])
- ->set('filters', filterInputText('Nonexistent', 'starts_with'))
- ->assertSee('No records found')
- ->assertDontSee('Name 1')
- ->assertDontSee('Name 2')
-)->group('filters', 'filterInputText')
- ->with('filter_input_text_options_themes_collection', 'filter_input_text_options_themes_array');
-
-it(
- 'properly filters by "name ends with" using collection & array table',
- fn (string $component, string $theme) => livewire($component)
- ->call($theme)
- ->set('testFilters', [
- Filter::inputText('name')->operators(),
- ])
- ->set('filters', filterInputText('e 5', 'ends_with'))
- ->assertSee('Name 5')
- ->assertDontSee('Name 1')
-)->group('filters', 'filterInputText')
- ->with('filter_input_text_options_themes_collection', 'filter_input_text_options_themes_array');
-
-it(
- 'properly filters by "name ends with" using nonexistent record using collection & array table',
- fn (string $component, string $theme) => livewire($component)
- ->call($theme)
- ->set('testFilters', [
- Filter::inputText('name')->operators(),
- ])
- ->set('filters', filterInputText('Nonexistent', 'ends_with'))
- ->assertSee('No records found')
- ->assertDontSee('Name 1')
- ->assertDontSee('Name 2')
- ->assertDontSee('Name 3')
-)->group('filters', 'filterInputText')
- ->with('filter_input_text_options_themes_collection', 'filter_input_text_options_themes_array');
-
-it(
- 'properly filters by "chef name is blank"',
- fn (string $component, string $theme) => livewire($component)
- ->call($theme)
- ->set('testFilters', [
- Filter::inputText('name')->operators(),
- ])
- ->set('filters', filterInputText('', 'is_blank', 'chef_name'))
- ->assertSee('Name 1')
- ->assertDontSee('Name 2')
- ->assertDontSee('Name 3')
- ->set('setUp.footer.perPage', '50')
- ->assertSee('Name 1')
- ->assertDontSee('Name 2')
- ->assertDontSee('Name 3')
-)->group('filters', 'filterInputText')
- ->with('filter_input_text_options_themes_collection', 'filter_input_text_options_themes_array');
-
-it(
- 'properly filters by "chef name is NOT blank"',
- fn (string $component, string $theme) => livewire($component)
- ->call($theme)
- ->set('testFilters', [
- Filter::inputText('name')->operators(),
- ])
- ->set('filters', filterInputText('', 'is_not_blank', 'chef_name'))
- ->assertSee('Name 2')
- ->assertSee('Name 3')
- ->assertDontSee('Name 1')
- ->set('setUp.footer.perPage', '50')
- ->assertSee('Name 2')
- ->assertSee('Name 3')
- ->assertDontSee('Name 1')
-)->group('filters', 'filterInputText')
- ->with('filter_input_text_options_themes_collection', 'filter_input_text_options_themes_array');
-
-it(
- 'properly filters by "chef name is null"',
- fn (string $component, string $theme) => livewire($component)
- ->call($theme)
- ->set('testFilters', [
- Filter::inputText('name')->operators(),
- ])
- ->set('filters', filterInputText('', 'is_null', 'chef_name'))
- ->assertSee('Name 2')
- ->assertDontSee('Name 1')
- ->assertDontSee('Name 3')
- ->set('setUp.footer.perPage', '50')
- ->assertSee('Name 2')
- ->assertDontSee('Name 1')
- ->assertDontSee('Name 3')
-)->group('filters', 'filterInputText')
- ->with('filter_input_text_options_themes_collection', 'filter_input_text_options_themes_array');
-
-it(
- 'properly filters by "chef name is NOT null"',
- fn (string $component, string $theme) => livewire($component)
- ->call($theme)
- ->set('testFilters', [
- Filter::inputText('name')->operators(),
- ])
- ->set('filters', filterInputText('', 'is_not_null', 'chef_name'))
- ->assertDontSee('Name 1')
- ->assertSee('Name 3')
- ->assertDontSee('Name 2')
- ->set('setUp.footer.perPage', '50')
- ->assertDontSee('Name 1')
- ->assertSee('Name 3')
- ->assertDontSee('Name 2')
-)->group('filters', 'filterInputText')
- ->with('filter_input_text_options_themes_collection', 'filter_input_text_options_themes_array');
-
-it(
- 'properly filters by "chef name is empty"',
- fn (string $component, string $theme) => livewire($component)
- ->call($theme)
- ->set('testFilters', [
- Filter::inputText('name')->operators(),
- ])
- ->set('filters', filterInputText('', 'is_empty', 'chef_name'))
- ->assertSee('Name 1')
- ->assertSee('Name 2')
- ->assertDontSee('Name 3')
- ->set('setUp.footer.perPage', '50')
- ->assertSee('Name 1')
- ->assertSee('Name 2')
- ->assertDontSee('Name 3')
-)->group('filters', 'filterInputText')
- ->with('filter_input_text_options_themes_collection', 'filter_input_text_options_themes_array');
-
-it(
- 'properly filters by "chef name is NOT empty"',
- fn (string $component, string $theme) => livewire($component)
- ->call($theme)
- ->set('testFilters', [
- Filter::inputText('name')->operators(),
- ])
- ->set('filters', filterInputText('', 'is_not_empty', 'chef_name'))
- ->assertSee('Name 3')
- ->assertDontSee('Name 1')
- ->assertDontSee('Name 2')
- ->set('setUp.footer.perPage', '50')
- ->assertSee('Name 3')
- ->assertDontSee('Name 1')
- ->assertDontSee('Name 2')
-)->group('filters', 'filterInputText')
- ->with('filter_input_text_options_themes_collection', 'filter_input_text_options_themes_array');
-
-dataset('filter_input_text_options_themes_collection', [
- 'tailwind' => [DishesCollectionTable::class, 'tailwind'],
- 'bootstrap' => [DishesCollectionTable::class, 'bootstrap'],
-]);
-
-dataset('filter_input_text_options_themes_array', [
- 'tailwind' => [DishesArrayTable::class, 'tailwind'],
- 'bootstrap' => [DishesArrayTable::class, 'bootstrap'],
-]);
diff --git a/tests/Feature/Filters/FilterInputOptionsModelTest.php b/tests/Feature/Filters/FilterInputOptionsModelTest.php
deleted file mode 100644
index a6ef29cf..00000000
--- a/tests/Feature/Filters/FilterInputOptionsModelTest.php
+++ /dev/null
@@ -1,544 +0,0 @@
-field)->operators();
- $livewire = livewire($component, [
- 'join' => $params->join,
- 'testFilters' => [
- $filter,
- ],
- ])
- ->call($params->theme)
- ->set('filters', filterInputText('Francesinha', 'is', $params->field))
- ->assertSee('Francesinha')
- ->assertDontSee('Francesinha vegana')
- ->call('clearFilter', $params->field)
- ->assertSee('Francesinha vegana');
-
- expectColumnsFilterMatch($livewire, $filter);
-})->group('filters', 'filterInputText')
- ->with('filter_input_text_options_model_themes_with_join', 'filter_input_text_options_query_builder');
-
-it('properly filters by "name is" using nonexistent record', function (string $component, object $params) {
- $filter = Filter::inputText('name', $params->field)
- ->operators();
- $livewire = livewire($component, [
- 'join' => $params->join,
- 'testFilters' => [
- $filter,
- ],
- ])
- ->call($params->theme)
- ->set('filters', filterInputText('Nonexistent dish', 'is', $params->field))
- ->assertSee('No records found')
- ->assertDontSee('Francesinha');
-
- expectColumnsFilterMatch($livewire, $filter);
-})->group('filters', 'filterInputText')->with('filter_input_text_options_model_themes_with_join', 'filter_input_text_options_query_builder');
-
-it('properly show placeholder', function (string $component, object $params) {
- $filter = Filter::inputText('name', $params->field)
- ->placeholder('Test Placeholder');
-
- livewire($component, [
- 'join' => $params->join,
- 'testFilters' => [
- $filter,
- ],
- ])
- ->call($params->theme)
- ->assertSeeHtml('placeholder="Test Placeholder"');
-})->group('filters', 'filterInputText')->with('filter_input_text_options_model_themes_with_join', 'filter_input_text_options_query_builder');
-
-it('properly filters by "name is not"', function (string $component, object $params) {
- $component = livewire($component, [
- 'join' => $params->join,
- ])
- ->call($params->theme)
- ->set('testFilters', [
- Filter::inputText('name')->operators(),
- ])
- ->set('filters', filterInputText('Francesinha vegana', 'is_not', $params->field))
- ->assertSee('Francesinha')
- ->assertDontSee('Francesinha vegana');
-
- expectInputText($params, $component, 'Francesinha vegana', 'is_not');
-
- $component->call('clearFilter', $params->field)
- ->assertSee('Francesinha vegana');
-
- expect($component->filters)
- ->toMatchArray([
- 'input_text' => [],
- 'input_text_options' => [],
- ]);
-})->group('filters', 'filterInputText')->with('filter_input_text_options_model_themes_with_join', 'filter_input_text_options_query_builder');
-
-it('properly filters by "name is not" using nonexistent record', function (string $component, object $params) {
- $component = livewire($component, [
- 'join' => $params->join,
- ])
- ->call($params->theme)
- ->set('filters', filterInputText('Nonexistent dish', 'is_not', $params->field))
- ->assertSee('Francesinha')
- ->assertSee('Francesinha vegana');
-
- expectInputText($params, $component, 'Nonexistent dish', 'is_not');
-
- $component->call('clearFilter', $params->field);
-
- expect($component->filters)
- ->toMatchArray([
- 'input_text' => [],
- 'input_text_options' => [],
- ]);
-})->group('filters', 'filterInputText')->with('filter_input_text_options_model_themes_with_join', 'filter_input_text_options_query_builder');
-
-it('properly filters by "name contains"', function (string $component, object $params) {
- $component = livewire($component, [
- 'join' => $params->join,
- ])
- ->call($params->theme)
- ->set('filters', filterInputText('francesinha', 'contains', $params->field))
- ->assertSee('Francesinha')
- ->assertSee('Francesinha vegana');
-
- expectInputText($params, $component, 'francesinha', 'contains');
-
- $component->call('clearFilter', $params->field);
-
- expect($component->filters)
- ->toMatchArray([
- 'input_text' => [],
- 'input_text_options' => [],
- ]);
-})->group('filters', 'filterInputText')->with('filter_input_text_options_model_themes_with_join', 'filter_input_text_options_query_builder');
-
-it('properly filters by "name contains" using nonexistent record', function (string $component, object $params) {
- $component = livewire($component, [
- 'join' => $params->join,
- ])
- ->call($params->theme)
- ->set('testFilters', [
- Filter::inputText('name')->operators(),
- ])
- ->set('filters', filterInputText('Nonexistent dish', 'contains', $params->field))
- ->assertSee('No records found')
- ->assertDontSee('Francesinha')
- ->assertDontSee('Francesinha vegana');
-
- expectInputText($params, $component, 'Nonexistent dish', 'contains');
-
- $component->call('clearFilter', $params->field);
-
- expect($component->filters)
- ->toMatchArray([
- 'input_text' => [],
- 'input_text_options' => [],
- ]);
-})->group('filters', 'filterInputText')->with('filter_input_text_options_model_themes_with_join', 'filter_input_text_options_query_builder');
-
-it('properly filters by "name contains not"', function (string $component, object $params) {
- $component = livewire($component, [
- 'join' => $params->join,
- ])
- ->call($params->theme)
- ->set('testFilters', [
- Filter::inputText('name')->operators(),
- ])
- ->set('filters', filterInputText('francesinha', 'contains_not', $params->field))
- ->assertDontSee('Francesinha')
- ->assertDontSee('Francesinha vegana');
-
- expectInputText($params, $component, 'francesinha', 'contains_not');
-
- $component->call('clearFilter', $params->field);
-
- expect($component->filters)
- ->toMatchArray([
- 'input_text' => [],
- 'input_text_options' => [],
- ]);
-})->group('filters', 'filterInputText')->with('filter_input_text_options_model_themes_with_join', 'filter_input_text_options_query_builder');
-
-it('properly filters by "name contains not" using nonexistent record', function (string $component, object $params) {
- $component = livewire($component, [
- 'join' => $params->join,
- ])
- ->call($params->theme)
- ->set('testFilters', [
- Filter::inputText('name')->operators(),
- ])
- ->set('filters', filterInputText('Nonexistent dish', 'contains_not', $params->field))
- ->assertSee('Francesinha')
- ->assertSee('Francesinha vegana');
-
- expectInputText($params, $component, 'Nonexistent dish', 'contains_not');
-
- $component->call('clearFilter', $params->field);
-
- expect($component->filters)
- ->toMatchArray([
- 'input_text' => [],
- 'input_text_options' => [],
- ]);
-})->group('filters', 'filterInputText')->with('filter_input_text_options_model_themes_with_join', 'filter_input_text_options_query_builder');
-
-it('properly filters by "name starts with"', function (string $component, object $params) {
- $component = livewire($component, [
- 'join' => $params->join,
- ])
- ->call($params->theme)
- ->set('testFilters', [
- Filter::inputText('name')->operators(),
- ])
- ->set('filters', filterInputText('fran', 'starts_with', $params->field))
- ->assertSee('Francesinha')
- ->assertSee('Francesinha vegana')
- ->assertDontSee('Barco-Sushi da Sueli');
-
- expectInputText($params, $component, 'fran', 'starts_with');
-
- $component->call('clearFilter', $params->field);
-
- expect($component->filters)
- ->toMatchArray([
- 'input_text' => [],
- 'input_text_options' => [],
- ]);
-})->group('filters', 'filterInputText')->with('filter_input_text_options_model_themes_with_join', 'filter_input_text_options_query_builder');
-
-it('properly filters by "name starts with" using nonexistent record', function (string $component, object $params) {
- $component = livewire($component, [
- 'join' => $params->join,
- ])
- ->call($params->theme)
- ->set('testFilters', [
- Filter::inputText('name')->operators(),
- ])
- ->set('filters', filterInputText('Nonexistent', 'starts_with', $params->field))
- ->assertSee('No records found')
- ->assertDontSee('Francesinha')
- ->assertDontSee('Francesinha vegana')
- ->assertDontSee('Barco-Sushi da Sueli');
-
- expectInputText($params, $component, 'Nonexistent', 'starts_with');
-
- $component->call('clearFilter', $params->field);
-
- expect($component->filters)
- ->toMatchArray([
- 'input_text' => [],
- 'input_text_options' => [],
- ]);
-})->group('filters', 'filterInputText')->with('filter_input_text_options_model_themes_with_join', 'filter_input_text_options_query_builder');
-
-it('properly filters by "name ends with"', function (string $component, object $params) {
- $component = livewire($component, [
- 'join' => $params->join,
- ])
- ->call($params->theme)
- ->set('testFilters', [
- Filter::inputText('name')->operators(),
- ])
- ->set('filters', filterInputText('vegana', 'ends_with', $params->field))
- ->assertSee('Francesinha vegana')
- ->assertDontSee('Barco-Sushi da Sueli');
-
- expectInputText($params, $component, 'vegana', 'ends_with');
-
- $component->call('clearFilter', $params->field);
-
- expect($component->filters)
- ->toMatchArray([
- 'input_text' => [],
- 'input_text_options' => [],
- ]);
-})->group('filters', 'filterInputText')->with('filter_input_text_options_model_themes_with_join', 'filter_input_text_options_query_builder');
-
-it('properly filters by "name ends with" using nonexistent record', function (string $component, object $params) {
- $component = livewire($component, [
- 'join' => $params->join,
- ])
- ->call($params->theme)
- ->set('testFilters', [
- Filter::inputText('name')->operators(),
- ])
- ->set('filters', filterInputText('Nonexistent', 'ends_with', $params->field))
- ->assertSee('No records found')
- ->assertDontSee('Francesinha')
- ->assertDontSee('Francesinha vegana')
- ->assertDontSee('Barco-Sushi da Sueli');
-
- expectInputText($params, $component, 'Nonexistent', 'ends_with');
-
- $component->call('clearFilter', $params->field);
-
- expect($component->filters)
- ->toMatchArray([
- 'input_text' => [],
- 'input_text_options' => [],
- ]);
-})->group('filters', 'filterInputText')->with('filter_input_text_options_model_themes_with_join', 'filter_input_text_options_query_builder');
-
-it('properly filters by "chef name is blank"', function (string $component, object $params) {
- $component = livewire($component, [
- 'join' => $params->join,
- ])
- ->call($params->theme)
- ->set('testFilters', [
- Filter::inputText('name')->operators(),
- ])
- ->set('filters', filterInputText('', 'is_blank', 'chef_name'))
- ->assertSee('Carne Louca')
- ->assertDontSee('Pastel de Nata')
- ->assertDontSee('Francesinha vegana')
- ->set('setUp.footer.perPage', '50')
- ->assertSee('Carne Louca')
- ->assertDontSee('Pastel de Nata')
- ->assertDontSee('Francesinha vegana');
-
- expect($component->filters)
- ->toMatchArray([
- 'input_text' => [
- 'chef_name' => '',
- ],
- 'input_text_options' => [
- 'chef_name' => 'is_blank',
- ],
- ]);
-
- $component->call('clearFilter', 'chef_name');
-
- expect($component->filters)
- ->toMatchArray([
- 'input_text' => [],
- 'input_text_options' => [],
- ]);
-})->group('filters', 'filterInputText')->with('filter_input_text_options_model_themes_with_join', 'filter_input_text_options_query_builder');
-
-it('properly filters by "chef name is NOT blank"', function (string $component, object $params) {
- $component = livewire($component, [
- 'join' => $params->join,
- ])
- ->call($params->theme)
- ->set('testFilters', [
- Filter::inputText('name')->operators(),
- ])
- ->set('filters', filterInputText('', 'is_not_blank', 'chef_name'))
- ->assertSee('Pastel de Nata')
- ->assertSee('Francesinha vegana')
- ->assertDontSee('Carne Louca')
- ->set('setUp.footer.perPage', '50')
- ->assertSee('Pastel de Nata')
- ->assertSee('Francesinha vegana')
- ->assertDontSee('Carne Louca');
-
- expect($component->filters)
- ->toMatchArray([
- 'input_text' => [
- 'chef_name' => '',
- ],
- 'input_text_options' => [
- 'chef_name' => 'is_not_blank',
- ],
- ]);
-
- $component->call('clearFilter', 'chef_name');
-
- expect($component->filters)
- ->toMatchArray([
- 'input_text' => [],
- 'input_text_options' => [],
- ]);
-})->group('filters', 'filterInputText')->with('filter_input_text_options_model_themes_with_join', 'filter_input_text_options_query_builder');
-
-it('properly filters by "chef name is null"', function (string $component, object $params) {
- $component = livewire($component, [
- 'join' => $params->join,
- ])
- ->call($params->theme)
- ->set('testFilters', [
- Filter::inputText('name')->operators(),
- ])
- ->set('filters', filterInputText('', 'is_null', 'chef_name'))
- ->assertSee('Pastel de Nata')
- ->assertDontSee('Francesinha vegana')
- ->assertDontSee('Carne Louca')
- ->set('setUp.footer.perPage', '50')
- ->assertSee('Pastel de Nata')
- ->assertDontSee('Francesinha vegana')
- ->assertDontSee('Carne Louca');
-
- expect($component->filters)
- ->toMatchArray([
- 'input_text' => [
- 'chef_name' => '',
- ],
- 'input_text_options' => [
- 'chef_name' => 'is_null',
- ],
- ]);
-
- $component->call('clearFilter', 'chef_name');
-
- expect($component->filters)
- ->toMatchArray([
- 'input_text' => [],
- 'input_text_options' => [],
- ]);
-})->group('filters', 'filterInputText')->with('filter_input_text_options_model_themes_with_join', 'filter_input_text_options_query_builder');
-
-it('properly filters by "chef name is NOT null"', function (string $component, object $params) {
- $filter = Filter::inputText('name', 'chef_name')->operators();
- $livewire = livewire($component, [
- 'join' => $params->join,
- 'testFilters' => [
- $filter,
- ],
- ])
- ->call($params->theme)
- ->set('filters', filterInputText('', 'is_not_null', 'chef_name'))
- ->assertSee('Francesinha vegana')
- ->assertSee('Carne Louca')
- ->assertDontSee('Pastel de Nata')
- ->set('setUp.footer.perPage', '50')
- ->assertSee('Francesinha vegana')
- ->assertSee('Carne Louca')
- ->assertDontSee('Pastel de Nata');
-
- expect($livewire->filters)
- ->toMatchArray([
- 'input_text' => [
- 'chef_name' => '',
- ],
- 'input_text_options' => [
- 'chef_name' => 'is_not_null',
- ],
- ]);
-
- $livewire->call('clearFilter', 'is_not_null');
-
- expect($livewire->filters)
- ->toMatchArray([]);
-
- expectColumnsFilterMatch($livewire, $filter);
-})->group('filters', 'filterInputText')->with('filter_input_text_options_model_themes_with_join', 'filter_input_text_options_query_builder');
-
-it('properly filters by "chef name is empty"', function (string $component, object $params) {
- $filter = Filter::inputText('name', $params->field)->operators();
- $livewire = livewire($component, [
- 'join' => $params->join,
- 'testFilters' => [
- $filter,
- ],
- ])
- ->call($params->theme)
- ->set('filters', filterInputText('', 'is_empty', 'chef_name'))
- ->assertSee('Pastel de Nata')
- ->assertSee('Carne Louca')
- ->assertDontSee('Francesinha vegana')
- ->set('setUp.footer.perPage', '50')
- ->assertSee('Pastel de Nata')
- ->assertSee('Carne Louca')
- ->assertDontSee('Francesinha vegana');
-
- expect($livewire->filters)
- ->toMatchArray([
- 'input_text' => [
- 'chef_name' => '',
- ],
- 'input_text_options' => [
- 'chef_name' => 'is_empty',
- ],
- ]);
-
- $livewire->call('clearFilter', 'is_empty');
-
- expect($livewire->filters)
- ->toMatchArray([]);
-
- expectColumnsFilterMatch($livewire, $filter);
-})->group('filters', 'filterInputText')->with('filter_input_text_options_model_themes_with_join', 'filter_input_text_options_query_builder');
-
-it('properly filters by "chef name is NOT empty"', function (string $component, object $params) {
- $filter = Filter::inputText('name', $params->field)->operators();
- $livewire = livewire($component, [
- 'join' => $params->join,
- 'testFilters' => [
- $filter,
- ],
- ])
- ->call($params->theme)
- ->set('filters', filterInputText('', 'is_not_empty', 'chef_name'))
- ->assertSee('Francesinha vegana')
- ->assertDontSee('Pastel de Nata')
- ->assertDontSee('Carne Louca')
- ->assertSee('Francesinha vegana')
- ->assertDontSee('Pastel de Nata')
- ->assertDontSee('Carne Louca');
-
- expectColumnsFilterMatch($livewire, $filter);
-})->group('filters', 'filterInputText')->with('filter_input_text_options_model_themes_with_join', 'filter_input_text_options_query_builder');
-
-$component = new class () extends DishTableBase {
- public function filters(): array
- {
- return [
- Filter::inputText('id')
- ->builder(function ($builder, $values) {
- return $builder->where('dishes.id', 1);
- }),
- ];
- }
-};
-
-it('properly filters using custom builder', function (string $component, object $params) {
- $component = livewire($component, [
- 'join' => $params->join,
- ])
- ->call($params->theme);
-
- $component->set('filters', filterInputText('francesinha', 'contains', 'id'))
- ->assertSee('Pastel de Nata')
- ->assertDontSee('Francesinha')
- ->assertDontSee('Francesinha vegana');
-})->group('filters', 'filterInputText')
- ->with([
- 'tailwind' => [$component::class, (object) ['theme' => 'tailwind', 'join' => false]],
- 'bootstrap' => [$component::class, (object) ['theme' => 'bootstrap', 'join' => false]],
- ]);
-
-dataset('filter_input_text_options_model_themes_with_join', [
-
- 'tailwind join' => [DishesFiltersTable::class, (object) ['theme' => 'tailwind', 'field' => 'dishes.name', 'join' => true]],
- 'bootstrap join' => [DishesFiltersTable::class, (object) ['theme' => 'bootstrap', 'field' => 'dishes.name', 'join' => true]],
-]);
-
-dataset('filter_input_text_options_query_builder', [
- 'tailwind query builder -> id' => [DishesQueryBuilderTable::class, (object) ['theme' => 'tailwind', 'field' => 'id']],
- 'bootstrap query builder -> id' => [DishesQueryBuilderTable::class, (object) ['theme' => 'bootstrap', 'field' => 'id']],
-]);
-
-function expectColumnsFilterMatch($component, $filter, $field = 'name'): void
-{
- $column = collect($component->columns)
- ->filter(fn ($column) => $column->field === $field)->first();
-
- expect($column->filters->first())
- ->className->toBe(FilterInputText::class)
- ->operators->toBeArray()
- ->field->toBe($filter->field)
- ->title->toBe($column->title);
-}
diff --git a/tests/Feature/Filters/FilterMultiSelectTest.php b/tests/Feature/Filters/FilterMultiSelectTest.php
index 73c28939..0e33a5cd 100644
--- a/tests/Feature/Filters/FilterMultiSelectTest.php
+++ b/tests/Feature/Filters/FilterMultiSelectTest.php
@@ -1,7 +1,6 @@
id' => [$customCollection::class, (object) ['theme' => 'bootstrap']],
]);
-it('properly filter with category_id - Carnes and Peixe selected', function (string $component) {
- $multiSelect = Filter::multiSelect('category_name', 'category_id')
- ->dataSource(Category::all())
- ->optionValue('id')
- ->optionLabel('name');
-
- /** @var PowerGridComponent $livewire */
- $livewire = livewire($component, [
- 'testFilters' => [
- $multiSelect,
- ],
- ])
- ->set('setUp.footer.perPage', '20')
- ->assertSeeHtmlInOrder([
- 'x-data="pgTomSelect(JSON.parse('{\u0022tableName\u0022:\u0022default\u0022,\u0022label\u0022:\u0022Category\u0022,\u0022dataField\u0022:\u0022category_id\u0022,\u0022optionValue\u0022:\u0022id\u0022,\u0022optionLabel\u0022:\u0022name\u0022,\u0022initialValues\u0022:[],\u0022framework\u0022:{\u0022plugins\u0022:{\u0022clear_button\u0022:{\u0022title\u0022:\u0022Remove all selected options\u0022}}}}'))"',
- 'wire:model="filters.multi_select.category_id.values"',
- 'x-ref="select_picker_category_id_default"',
- ])
- ->set('filters', [
- 'multi_select' => [
- 'category_id' => [
- 1, // Carnes
- ],
- ],
- ])
- ->assertDontSee('Pastel de Nata')
- ->assertDontSee('борщ')
- ->assertDontSee('Francesinha vegana')
- ->assertSeeHtmlInOrder([
- 'Peixada da chef Nábia',
- 'Carne Louca',
- 'Bife à Rolê',
- ])
- ->set('filters', [
- 'multi_select' => [
- 'category_id' => [
- 3, // Tortas
- 7, // Sobremesas
- ],
- ],
- ])
- ->assertSee('борщ')
- ->assertDontSee('Peixada da chef Nábia');
-
- $column = collect($livewire->columns)
- ->filter(fn ($column) => $column->field === 'category_name')->first();
-
- $categories = Category::all();
-
- expect($column->filters->first())
- ->dataSource->toHaveLength($categories->count())
- ->optionValue->toBe($multiSelect->optionValue)
- ->optionLabel->toBe($multiSelect->optionLabel)
- ->className->toBe(FilterMultiSelect::class)
- ->field->toBe($multiSelect->field)
- ->title->toBe($column->title);
-})->group('filters')
- ->with('filter_multi_select_themes_with_join', 'filter_multi_select_query_builder');
-
it('properly filter with category_id - multiple select async', function (string $component) {
$multiSelect = Filter::multiSelectAsync('category_name', 'category_id')
->url('http://localhost/category')
@@ -229,15 +169,14 @@ public function filters(): array
$column = collect($livewire->columns)
->filter(fn ($column) => $column->field === 'category_name')->first();
- expect($column->filters->first())
+ expect((object) $column->filters)
->url->toBe('http://localhost/category')
->method->toBe('POST')
->parameters->toMatchArray([0 => 'Luan'])
->optionValue->toBe($multiSelect->optionValue)
->optionLabel->toBe($multiSelect->optionLabel)
->className->toBe(FilterMultiSelectAsync::class)
- ->field->toBe($multiSelect->field)
- ->title->toBe($column->title);
+ ->field->toBe($multiSelect->field);
})->group('filters')
->with('filter_multi_select_themes_with_join', 'filter_multi_select_query_builder');
diff --git a/tests/Feature/Filters/FilterMultipleTest.php b/tests/Feature/Filters/FilterMultipleTest.php
index 52ba300b..19cbbeac 100644
--- a/tests/Feature/Filters/FilterMultipleTest.php
+++ b/tests/Feature/Filters/FilterMultipleTest.php
@@ -115,18 +115,6 @@ public function filters(): array
$component->call('clearFilter', $params->field);
- $filters = array_merge(
- [
- 'input_text' => [],
- 'input_text_options' => [],
- ],
- filterNumber('price', '80.00', '100'),
- filterBoolean('in_stock', 'true')
- );
-
- expect($component->filters)
- ->toMatchArray($filters);
-
$component->assertDontSee('Polpetone Filé Mignon');
$component->call('clearAllFilters');
diff --git a/tests/cypress/cypress/e2e/action-rules/checkbox.cy.js b/tests/cypress/cypress/e2e/action-rules/checkbox.cy.js
index 0579544f..78edc46f 100644
--- a/tests/cypress/cypress/e2e/action-rules/checkbox.cy.js
+++ b/tests/cypress/cypress/e2e/action-rules/checkbox.cy.js
@@ -1,6 +1,6 @@
describe('Action Rules::checkbox', () => {
beforeEach(() => {
- cy.visit('/cypress?ruleType=checkbox');
+ cy.visit('/examples/cypress?ruleType=checkbox');
});
it('can visit page', () => {
diff --git a/tests/cypress/cypress/e2e/action-rules/radio.cy.js b/tests/cypress/cypress/e2e/action-rules/radio.cy.js
index 0e9773ed..b02997de 100644
--- a/tests/cypress/cypress/e2e/action-rules/radio.cy.js
+++ b/tests/cypress/cypress/e2e/action-rules/radio.cy.js
@@ -1,6 +1,6 @@
describe('Action Rules::radio', () => {
beforeEach(() => {
- cy.visit('/cypress?ruleType=radio');
+ cy.visit('/examples/cypress?ruleType=radio');
});
it('can visit page', () => {
diff --git a/tests/cypress/cypress/e2e/action-rules/rows.cy.js b/tests/cypress/cypress/e2e/action-rules/rows.cy.js
index 633308b6..3f139547 100644
--- a/tests/cypress/cypress/e2e/action-rules/rows.cy.js
+++ b/tests/cypress/cypress/e2e/action-rules/rows.cy.js
@@ -1,6 +1,6 @@
describe('Action Rules::rows', () => {
beforeEach(() => {
- cy.visit('/cypress?ruleType=rows');
+ cy.visit('/examples/cypress?ruleType=rows');
});
it('can visit page', () => {
diff --git a/tests/cypress/cypress/e2e/filters/input-text.cy.js b/tests/cypress/cypress/e2e/filters/input-text.cy.js
index 284c5a97..ab9d4789 100644
--- a/tests/cypress/cypress/e2e/filters/input-text.cy.js
+++ b/tests/cypress/cypress/e2e/filters/input-text.cy.js
@@ -1,27 +1,149 @@
describe('simple', () => {
beforeEach(() => {
- cy.visit('/cypress?testType=filters');
+ cy.visit('/examples/cypress?testType=filters');
});
- it('test', () => {
- const expectedFilter = '{"input_text":{"name":"d","email":"d"}}' // Daniel, Claudio
+ const inputField = '[data-cy="input_text_default_name"]';
+ const optionsField = '[data-cy="input_text_options_default_name"]';
+ const tableRows = '.power-grid-table tbody tr';
- cy.get('[wire\\:model="filters.input_text.name"]')
- .type('d').should('have.value', 'd');
+ const applyFilter = (filterType, filterValue) => {
+ cy.get(inputField).clear()
+ cy.get(inputField).type(filterValue).should('have.value', filterValue);
+ cy.get(optionsField).select(filterType);
+ };
- cy.get('[wire\\:model="filters.input_text.email"]')
- .type('d').should('have.value', 'd');
+ const clearFilter = () => {
+ cy.get('[data-cy="enabled-filters"]')
+ .should('contain.text', 'Name')
- cy.get('[data-cy="filters-log"]').should('contain.text', expectedFilter);
+ cy.wait(800) // wait livewire debounce
- cy.get('.power-grid-table tbody tr').then(($el) => {
- $el.each((index, row) => {
+ cy.get('[data-cy=enabled-filters-clear-name]')
+ .click()
- const name = Cypress.$(row).find('td').eq(1).text();
+ cy.get('[data-cy="enabled-filters"]')
+ .should('not.exist')
+ }
- expect(name).not.to.include('Luan');
- expect(name).not.to.include('Tio Jobs');
- });
- })
+ it('Filter - "contains" works properly', () => {
+ const filterValue = 'Dan';
+ applyFilter('contains', filterValue);
+
+ cy.get(tableRows).should('not.have.text', 'Luan');
+ cy.url().should('include', `name=${filterValue}`);
+ });
+
+ it('Filter - "is" works properly', () => {
+ const filterValue = 'John';
+ applyFilter('is', filterValue);
+ });
+
+ it('Filter - "contains_not" works properly', () => {
+ let filterValue = 'John';
+ applyFilter('contains_not', filterValue);
+
+ cy.get(tableRows).should('contain.text', 'Luan');
+ cy.get(tableRows).should('contain.text', 'Daniel');
+ cy.get(tableRows).should('contain.text', 'Claudio');
+ cy.get(tableRows).should('contain.text', 'Vitor');
+ cy.url().should('include', `name=${filterValue}`);
+
+ clearFilter()
+
+ cy.get(inputField).should('be.empty')
+
+ filterValue = 'Dan';
+ applyFilter('contains_not', filterValue);
+
+ cy.get(tableRows).should('not.contains.text', 'Dan')
+ cy.get(tableRows).should('contains.text', 'Luan')
+ cy.get(tableRows).should('contains.text', 'Claudio')
+ cy.get(tableRows).should('contains.text', 'Tio Jobs')
+ cy.get(tableRows).should('contains.text', 'Vitor')
+
+ cy.url().should('include', `name=${filterValue}`);
+
+ clearFilter()
+
+ cy.get(inputField).should('be.empty')
+
+ filterValue = 'Luan';
+ applyFilter('contains_not', filterValue);
+
+ cy.get(tableRows).should('contains.text', 'Dan')
+ cy.get(tableRows).should('not.contains.text', 'Luan')
+ cy.get(tableRows).should('contains.text', 'Claudio')
+ cy.get(tableRows).should('contains.text', 'Tio Jobs')
+ cy.get(tableRows).should('contains.text', 'Vitor')
+
+ cy.url().should('include', `name=${filterValue}`);
+
+ filterValue = 'an';
+ applyFilter('contains_not', filterValue);
+
+ cy.get(tableRows).should('not.contains.text', 'Dan')
+ cy.get(tableRows).should('not.contains.text', 'Luan')
+ cy.get(tableRows).should('contains.text', 'Claudio')
+ cy.get(tableRows).should('contains.text', 'Tio Jobs')
+ cy.get(tableRows).should('contains.text', 'Vitor')
+
+ cy.url().should('include', `name=${filterValue}`);
+ });
+
+ it('Filter - "starts_with" works properly', () => {
+ let filterValue = 'Lu';
+ applyFilter('starts_with', filterValue);
+
+ cy.get(tableRows).should('not.contains.text', 'Dan')
+ cy.get(tableRows).should('contains.text', 'Luan')
+ cy.get(tableRows).should('not.contains.text', 'Claudio')
+ cy.get(tableRows).should('not.contains.text', 'Tio Jobs')
+ cy.get(tableRows).should('not.contains.text', 'Vitor')
+
+ cy.url().should('include', `name=${filterValue}`);
+
+ clearFilter()
+
+ filterValue = 'Cl';
+ applyFilter('starts_with', filterValue);
+
+ cy.get(tableRows).should('not.contains.text', 'Dan')
+ cy.get(tableRows).should('not.contains.text', 'Luan')
+ cy.get(tableRows).should('contains.text', 'Claudio')
+ cy.get(tableRows).should('not.contains.text', 'Tio Jobs')
+ cy.get(tableRows).should('not.contains.text', 'Vitor')
+
+ cy.url().should('include', `name=${filterValue}`);
+
+ clearFilter()
+ });
+
+ it('Filter - "ends_with" works properly', () => {
+ let filterValue = 'obs';
+ applyFilter('ends_with', filterValue);
+
+ cy.get(tableRows).should('not.contains.text', 'Dan')
+ cy.get(tableRows).should('not.contains.text', 'Luan')
+ cy.get(tableRows).should('not.contains.text', 'Claudio')
+ cy.get(tableRows).should('contains.text', 'Tio Jobs')
+ cy.get(tableRows).should('not.contains.text', 'Vitor')
+
+ cy.url().should('include', `name=${filterValue}`);
+
+ clearFilter()
+
+ filterValue = 'an';
+ applyFilter('starts_with', filterValue);
+
+ cy.get(tableRows).should('contains.text', 'Dan')
+ cy.get(tableRows).should('contains.text', 'Luan')
+ cy.get(tableRows).should('not.contains.text', 'Claudio')
+ cy.get(tableRows).should('not.contains.text', 'Tio Jobs')
+ cy.get(tableRows).should('not.contains.text', 'Vitor')
+
+ cy.url().should('include', `name=${filterValue}`);
+
+ clearFilter()
});
})
diff --git a/tests/cypress/cypress/e2e/filters/number.cy.js b/tests/cypress/cypress/e2e/filters/number.cy.js
index 507faead..ee91e2bb 100644
--- a/tests/cypress/cypress/e2e/filters/number.cy.js
+++ b/tests/cypress/cypress/e2e/filters/number.cy.js
@@ -1,6 +1,6 @@
describe('simple', () => {
beforeEach(() => {
- cy.visit('/cypress?testType=filters');
+ cy.visit('/examples/cypress?testType=filters');
});
it('test', () => {
diff --git a/tests/cypress/cypress/e2e/simple.cy.js b/tests/cypress/cypress/e2e/simple.cy.js
index 1a2ea263..a64fc9ee 100644
--- a/tests/cypress/cypress/e2e/simple.cy.js
+++ b/tests/cypress/cypress/e2e/simple.cy.js
@@ -1,6 +1,6 @@
describe('simple', () => {
it('can visit simple page', () => {
- cy.visit('/simple')
+ cy.visit('/')
cy.contains('Simple')
})
})
diff --git a/yarn.lock b/yarn.lock
index 1f3f17e2..284caac1 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1333,7 +1333,7 @@
dependencies:
"@types/node" "*"
-"@types/node@*", "@types/node@^18.17.5":
+"@types/node@*":
version "18.18.9"
resolved "https://registry.npmjs.org/@types/node/-/node-18.18.9.tgz"
integrity sha512-0f5klcuImLnG4Qreu9hPj/rEfFq6YRc5n2mAjSsH+ec/mJL+3voBH0+8T7o8RpFjH7ovc+TRsL/c7OYIQsPTfQ==
@@ -1670,10 +1670,10 @@ ajv@^8.0.0, ajv@^8.9.0:
require-from-string "^2.0.2"
uri-js "^4.2.2"
-alpinejs@^3.12.2:
- version "3.13.2"
- resolved "https://registry.npmjs.org/alpinejs/-/alpinejs-3.13.2.tgz"
- integrity sha512-WzojeeN082kLZznGI1HAuP8yFJSWqJ1fGdz2mUjj45H4y0XwToE7fFqtI3mCPRR+BpcSbxT/NL+FyPnYAWSltw==
+alpinejs@^3.13.5:
+ version "3.13.5"
+ resolved "https://registry.yarnpkg.com/alpinejs/-/alpinejs-3.13.5.tgz#c06f067e847a295085b4c6f76c42a6a35499d953"
+ integrity sha512-1d2XeNGN+Zn7j4mUAKXtAgdc4/rLeadyTMWeJGXF5DzwawPBxwTiBhFFm6w/Ei8eJxUZeyNWWSD9zknfdz1kEw==
dependencies:
"@vue/reactivity" "~3.1.1"
@@ -1811,7 +1811,7 @@ at-least-node@^1.0.0:
resolved "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz"
integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==
-autoprefixer@^10.4.0, autoprefixer@^10.4.14:
+autoprefixer@^10.4.0:
version "10.4.16"
resolved "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.16.tgz"
integrity sha512-7vd3UC6xKp0HLfua5IjZlcXvGAGy7cBAXTg2lyQ/8WpNhd6SiZ8Be+xm3FyBSYJx5GKcpRCzBh7RH4/0dnY+uQ==
@@ -1823,6 +1823,18 @@ autoprefixer@^10.4.0, autoprefixer@^10.4.14:
picocolors "^1.0.0"
postcss-value-parser "^4.2.0"
+autoprefixer@^10.4.17:
+ version "10.4.17"
+ resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.17.tgz#35cd5695cbbe82f536a50fa025d561b01fdec8be"
+ integrity sha512-/cpVNRLSfhOtcGflT13P2794gVSgmPgTR+erw5ifnMLZb0UnSlkK4tquLmkd3BhA+nLo5tX8Cu0upUsGKvKbmg==
+ dependencies:
+ browserslist "^4.22.2"
+ caniuse-lite "^1.0.30001578"
+ fraction.js "^4.3.7"
+ normalize-range "^0.1.2"
+ picocolors "^1.0.0"
+ postcss-value-parser "^4.2.0"
+
aws-sign2@~0.7.0:
version "0.7.0"
resolved "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz"
@@ -1899,9 +1911,9 @@ binary-extensions@^2.0.0:
resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz"
integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
-blade-formatter@^1.37.1:
+blade-formatter@^1.38.6:
version "1.38.6"
- resolved "https://registry.npmjs.org/blade-formatter/-/blade-formatter-1.38.6.tgz"
+ resolved "https://registry.yarnpkg.com/blade-formatter/-/blade-formatter-1.38.6.tgz#d3ea21faefa4c03a6fb3ada20fd545f2f3c1e311"
integrity sha512-XwW1A4G7GPXjCG7oPKkvBp8UVb/YS/zoS8FbuuUbrnwzzmoVEe29oSqh1JpCVj9+SI2ye/qohRuXNkwHjcq/Ww==
dependencies:
"@prettier/plugin-php" "^0.19.7"
@@ -2076,6 +2088,16 @@ browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.21.10, browserslist@^
node-releases "^2.0.13"
update-browserslist-db "^1.0.13"
+browserslist@^4.22.2:
+ version "4.22.3"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.3.tgz#299d11b7e947a6b843981392721169e27d60c5a6"
+ integrity sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A==
+ dependencies:
+ caniuse-lite "^1.0.30001580"
+ electron-to-chromium "^1.4.648"
+ node-releases "^2.0.14"
+ update-browserslist-db "^1.0.13"
+
buffer-crc32@~0.2.3:
version "0.2.13"
resolved "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz"
@@ -2169,6 +2191,11 @@ caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001538, caniuse-lite@^1.0.30001541:
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001561.tgz"
integrity sha512-NTt0DNoKe958Q0BE0j0c1V9jbUzhBxHIEJy7asmGrpE0yG63KTV7PLHPnK2E1O9RsQrQ081I3NLuXGS6zht3cw==
+caniuse-lite@^1.0.30001578, caniuse-lite@^1.0.30001580:
+ version "1.0.30001580"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001580.tgz#e3c76bc6fe020d9007647044278954ff8cd17d1e"
+ integrity sha512-mtj5ur2FFPZcCEpXFy8ADXbDACuNFXg6mxVDqp7tqooX6l3zwm+d8EPoeOSIFRDvHs8qu7/SLFOGniULkcH2iA==
+
caseless@~0.12.0:
version "0.12.0"
resolved "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz"
@@ -2674,14 +2701,13 @@ csso@^4.2.0:
dependencies:
css-tree "^1.1.2"
-cypress@^13.3.0:
- version "13.5.0"
- resolved "https://registry.npmjs.org/cypress/-/cypress-13.5.0.tgz"
- integrity sha512-oh6U7h9w8wwHfzNDJQ6wVcAeXu31DlIYlNOBvfd6U4CcB8oe4akawQmH+QJVOMZlM42eBoCne015+svVqdwdRQ==
+cypress@^13.6.3:
+ version "13.6.3"
+ resolved "https://registry.yarnpkg.com/cypress/-/cypress-13.6.3.tgz#54f03ca07ee56b2bc18211e7bd32abd2533982ba"
+ integrity sha512-d/pZvgwjAyZsoyJ3FOsJT5lDsqnxQ/clMqnNc++rkHjbkkiF2h9s0JsZSyyH4QXhVFW3zPFg82jD25roFLOdZA==
dependencies:
"@cypress/request" "^3.0.0"
"@cypress/xvfb" "^1.2.4"
- "@types/node" "^18.17.5"
"@types/sinonjs__fake-timers" "8.1.1"
"@types/sizzle" "^2.3.2"
arch "^2.2.0"
@@ -2937,6 +2963,11 @@ electron-to-chromium@^1.4.535:
resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.580.tgz"
integrity sha512-T5q3pjQon853xxxHUq3ZP68ZpvJHuSMY2+BZaW3QzjS4HvNuvsMmZ/+lU+nCrftre1jFZ+OSlExynXWBihnXzw==
+electron-to-chromium@^1.4.648:
+ version "1.4.648"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.648.tgz#c7b46c9010752c37bb4322739d6d2dd82354fbe4"
+ integrity sha512-EmFMarXeqJp9cUKu/QEciEApn0S/xRcpZWuAm32U7NgoZCimjsilKXHRO9saeEW55eHZagIDg6XTUOv32w9pjg==
+
elliptic@^6.5.3, elliptic@^6.5.4:
version "6.5.4"
resolved "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz"
@@ -3336,7 +3367,7 @@ forwarded@0.2.0:
resolved "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz"
integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==
-fraction.js@^4.3.6:
+fraction.js@^4.3.6, fraction.js@^4.3.7:
version "4.3.7"
resolved "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz"
integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==
@@ -4504,6 +4535,11 @@ nanoid@^3.3.6:
resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz"
integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==
+nanoid@^3.3.7:
+ version "3.3.7"
+ resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8"
+ integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==
+
negotiator@0.6.3:
version "0.6.3"
resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz"
@@ -4573,6 +4609,11 @@ node-releases@^2.0.13:
resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz"
integrity sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==
+node-releases@^2.0.14:
+ version "2.0.14"
+ resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b"
+ integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==
+
nopt@^7.2.0:
version "7.2.0"
resolved "https://registry.npmjs.org/nopt/-/nopt-7.2.0.tgz"
@@ -5159,7 +5200,7 @@ postcss-value-parser@^4.0.0, postcss-value-parser@^4.1.0, postcss-value-parser@^
resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz"
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
-postcss@^8.2.14, postcss@^8.2.15, postcss@^8.4.23, postcss@^8.4.31:
+postcss@^8.2.14, postcss@^8.2.15, postcss@^8.4.23:
version "8.4.31"
resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz"
integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==
@@ -5168,6 +5209,15 @@ postcss@^8.2.14, postcss@^8.2.15, postcss@^8.4.23, postcss@^8.4.31:
picocolors "^1.0.0"
source-map-js "^1.0.2"
+postcss@^8.4.33:
+ version "8.4.33"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.33.tgz#1378e859c9f69bf6f638b990a0212f43e2aaa742"
+ integrity sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==
+ dependencies:
+ nanoid "^3.3.7"
+ picocolors "^1.0.0"
+ source-map-js "^1.0.2"
+
prettier@^2.2.0:
version "2.8.8"
resolved "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz"
@@ -5539,17 +5589,17 @@ safe-buffer@5.2.1, safe-buffer@^5.2.0, safe-buffer@^5.2.1:
resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
-sass-loader@^13.3.2:
- version "13.3.2"
- resolved "https://registry.npmjs.org/sass-loader/-/sass-loader-13.3.2.tgz"
- integrity sha512-CQbKl57kdEv+KDLquhC+gE3pXt74LEAzm+tzywcA0/aHZuub8wTErbjAoNI57rPUWRYRNC5WUnNl8eGJNbDdwg==
+sass-loader@^14.0.0:
+ version "14.0.0"
+ resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-14.0.0.tgz#fc8390f7cc16863622cd16f3ea07b36ba6ea8f91"
+ integrity sha512-oceP9wWbep/yRJ2+sMbCzk0UsXsDzdNis+N8nu9i5GwPXjy6v3DNB6TqfJLSpPO9k4+B8x8p/CEgjA9ZLkoLug==
dependencies:
neo-async "^2.6.2"
-sass@^1.66.1:
- version "1.69.5"
- resolved "https://registry.npmjs.org/sass/-/sass-1.69.5.tgz"
- integrity sha512-qg2+UCJibLr2LCVOt3OlPhr/dqVHWOa9XtZf2OjbLs/T4VPSJ00udtgJxH3neXZm+QqX8B+3cU7RaLqp1iVfcQ==
+sass@^1.70.0:
+ version "1.70.0"
+ resolved "https://registry.yarnpkg.com/sass/-/sass-1.70.0.tgz#761197419d97b5358cb25f9dd38c176a8a270a75"
+ integrity sha512-uUxNQ3zAHeAx5nRFskBnrWzDUJrrvpCPD5FNAoRvTi0WwremlheES3tg+56PaVtCs5QDRX5CBLxxKMDJMEa1WQ==
dependencies:
chokidar ">=3.0.0 <4.0.0"
immutable "^4.0.0"
@@ -5972,7 +6022,7 @@ svgo@^2.7.0:
picocolors "^1.0.0"
stable "^0.1.8"
-tailwindcss@^3.1.8, tailwindcss@^3.3.1, tailwindcss@^3.3.2:
+tailwindcss@^3.1.8, tailwindcss@^3.3.2:
version "3.3.5"
resolved "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.5.tgz"
integrity sha512-5SEZU4J7pxZgSkv7FP1zY8i2TIAOooNZ1e/OGtxIEv6GltpoiXUqWvLy89+a10qYTB1N5Ifkuw9lqQkN9sscvA==
@@ -6000,6 +6050,34 @@ tailwindcss@^3.1.8, tailwindcss@^3.3.1, tailwindcss@^3.3.2:
resolve "^1.22.2"
sucrase "^3.32.0"
+tailwindcss@^3.4.1:
+ version "3.4.1"
+ resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.4.1.tgz#f512ca5d1dd4c9503c7d3d28a968f1ad8f5c839d"
+ integrity sha512-qAYmXRfk3ENzuPBakNK0SRrUDipP8NQnEY6772uDhflcQz5EhRdD7JNZxyrFHVQNCwULPBn6FNPp9brpO7ctcA==
+ dependencies:
+ "@alloc/quick-lru" "^5.2.0"
+ arg "^5.0.2"
+ chokidar "^3.5.3"
+ didyoumean "^1.2.2"
+ dlv "^1.1.3"
+ fast-glob "^3.3.0"
+ glob-parent "^6.0.2"
+ is-glob "^4.0.3"
+ jiti "^1.19.1"
+ lilconfig "^2.1.0"
+ micromatch "^4.0.5"
+ normalize-path "^3.0.0"
+ object-hash "^3.0.0"
+ picocolors "^1.0.0"
+ postcss "^8.4.23"
+ postcss-import "^15.1.0"
+ postcss-js "^4.0.1"
+ postcss-load-config "^4.0.1"
+ postcss-nested "^6.0.1"
+ postcss-selector-parser "^6.0.11"
+ resolve "^1.22.2"
+ sucrase "^3.32.0"
+
tapable@^2.1.1, tapable@^2.2.0:
version "2.2.1"
resolved "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz"
@@ -6100,9 +6178,9 @@ toidentifier@1.0.1:
resolved "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz"
integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==
-tom-select@^2.2.2:
+tom-select@^2.3.1:
version "2.3.1"
- resolved "https://registry.npmjs.org/tom-select/-/tom-select-2.3.1.tgz"
+ resolved "https://registry.yarnpkg.com/tom-select/-/tom-select-2.3.1.tgz#df338d9082874cd0bceb3bee87ed0184447c47f1"
integrity sha512-QS4vnOcB6StNGqX4sGboGXL2fkhBF2gIBB+8Hwv30FZXYPn0CyYO8kkdATRvwfCTThxiR4WcXwKJZ3cOmtI9eg==
dependencies:
"@orchidjs/sifter" "^1.0.3"