Skip to content

Commit 182526a

Browse files
committed
wip
1 parent a1ab5b6 commit 182526a

File tree

5 files changed

+112
-8
lines changed

5 files changed

+112
-8
lines changed

resources/views/table/filters.blade.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<form method="GET" action="{{ $url }}" id="{{ $key }}" onchange="this.requestSubmit()">
1+
<form method="GET" action="{{ $url }}" id="{{ $key }}" onchange="this.requestSubmit()" autocomplete="off">
22
@if(! empty($filters))
33
<div class="data-table-filter" x-data="{ open: false }" x-on:click.outside="open = false">
44
<button

src/Fields/Date.php

Lines changed: 72 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33
namespace Cone\Root\Fields;
44

55
use Closure;
6+
use Cone\Root\Filters\Filter;
7+
use Cone\Root\Filters\RenderableFilter;
68
use Cone\Root\Root;
79
use DateTimeInterface;
810
use DateTimeZone;
11+
use Illuminate\Database\Eloquent\Builder;
912
use Illuminate\Database\Eloquent\Model;
1013
use Illuminate\Http\Request;
1114
use Illuminate\Support\Facades\Config;
@@ -118,12 +121,20 @@ public function getValue(Model $model): mixed
118121
{
119122
$value = parent::getValue($model);
120123

121-
if (! is_null($value)) {
122-
$value = DateFactory::parse($value, Config::get('app.timezone'))
123-
->setTimezone($this->timezone);
124+
return $this->parseValue($value);
125+
}
126+
127+
/**
128+
* Parse the given value.
129+
*/
130+
public function parseValue(mixed $value): ?DateTimeInterface
131+
{
132+
if (is_null($value)) {
133+
return $value;
124134
}
125135

126-
return $value;
136+
return DateFactory::parse($value, Config::get('app.timezone'))
137+
->setTimezone($this->timezone);
127138
}
128139

129140
/**
@@ -132,9 +143,65 @@ public function getValue(Model $model): mixed
132143
public function resolveFormat(Request $request, Model $model): ?string
133144
{
134145
if (is_null($this->formatResolver)) {
135-
$this->formatResolver = fn (Request $request, Model $model, mixed $value): ?string => is_null($value) ? $value : $value->format($this->format);
146+
$this->formatResolver = function (Request $request, Model $model, mixed $value): ?string {
147+
return is_null($value) ? $value : $value->format($this->format);
148+
};
136149
}
137150

138151
return parent::resolveFormat($request, $model);
139152
}
153+
154+
/**
155+
* Set the filterable attribute.
156+
*/
157+
public function filterable(?Closure $callback = null, bool|Closure $search = false): static
158+
{
159+
$callback ??= function (Request $request, Builder $query, mixed $value, string $attribute): Builder {
160+
return $query->whereDate($query->qualifyColumn($attribute), $value);
161+
};
162+
163+
return parent::filterable($callback, $search);
164+
}
165+
166+
/**
167+
* Get the form component data.
168+
*/
169+
public function toDisplay(Request $request, Model $model): array
170+
{
171+
return array_merge(parent::toDisplay($request, $model), [
172+
'value' => $this->resolveFormat($request, $model),
173+
]);
174+
}
175+
176+
/**
177+
* Get the filter representation of the field.
178+
*/
179+
public function toFilter(): Filter
180+
{
181+
return new class($this) extends RenderableFilter
182+
{
183+
protected Date $field;
184+
185+
public function __construct(Date $field)
186+
{
187+
parent::__construct($field->getModelAttribute());
188+
189+
$this->field = $field;
190+
}
191+
192+
public function apply(Request $request, Builder $query, mixed $value): Builder
193+
{
194+
return $this->field->resolveFilterQuery($request, $query, $value);
195+
}
196+
197+
public function toField(): Field
198+
{
199+
return Date::make($this->field->getLabel(), $this->getRequestKey())
200+
->value(function (Request $request): ?DateTimeInterface {
201+
return $this->field->parseValue($this->getValue($request));
202+
})
203+
->suffix('');
204+
}
205+
};
206+
}
140207
}

src/Fields/Field.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
namespace Cone\Root\Fields;
44

55
use Closure;
6+
use Cone\Root\Filters\Filter;
7+
use Cone\Root\Filters\RenderableFilter;
68
use Cone\Root\Traits\Authorizable;
79
use Cone\Root\Traits\HasAttributes;
810
use Cone\Root\Traits\Makeable;
@@ -682,6 +684,36 @@ public function toValidate(Request $request, Model $model): array
682684
return [$this->getValidationKey() => Arr::flatten($rules, 1)];
683685
}
684686

687+
/**
688+
* Get the filter representation of the field.
689+
*/
690+
public function toFilter(): Filter
691+
{
692+
return new class($this) extends RenderableFilter
693+
{
694+
protected Field $field;
695+
696+
public function __construct(Field $field)
697+
{
698+
parent::__construct($field->getModelAttribute());
699+
700+
$this->field = $field;
701+
}
702+
703+
public function apply(Request $request, Builder $query, mixed $value): Builder
704+
{
705+
return $this->field->resolveFilterQuery($request, $query, $value);
706+
}
707+
708+
public function toField(): Field
709+
{
710+
return Text::make($this->field->getLabel(), $this->getRequestKey())
711+
->value(fn (Request $request): mixed => $this->getValue($request))
712+
->suffix('');
713+
}
714+
};
715+
}
716+
685717
/**
686718
* Clone the field.
687719
*/

src/Filters/Filter.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ abstract class Filter
2121
/**
2222
* Create a new filter instance.
2323
*/
24-
public function __construct()
24+
public function __construct(?string $key = null)
2525
{
26-
$this->key = Str::of(static::class)->classBasename()->snake()->value();
26+
$this->key = $key ?: Str::of(static::class)->classBasename()->snake()->value();
2727
}
2828

2929
/**

src/Resources/Resource.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,10 +386,15 @@ public function filters(Request $request): array
386386

387387
$sortables = $fields->sortable();
388388

389+
$filterables = $fields->filter(static function (Field $field): bool {
390+
return $field->isFilterable() && ! $field->isSearchable();
391+
});
392+
389393
return array_values(array_filter([
390394
$searchables->isNotEmpty() ? new Search($searchables) : null,
391395
$sortables->isNotEmpty() ? new Sort($sortables) : null,
392396
$this->isSoftDeletable() ? new TrashStatus : null,
397+
...$filterables->map->toFilter()->all(),
393398
]));
394399
}
395400

0 commit comments

Comments
 (0)