Skip to content

Commit fb8ba9f

Browse files
committed
wip
1 parent 9f5360c commit fb8ba9f

File tree

4 files changed

+129
-20
lines changed

4 files changed

+129
-20
lines changed

resources/views/fields/relation-option.blade.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<div class="file-list-item">
22
<div class="file-list-item__column">
3-
<span id="{{ $attrs->get('id') }}" class="file-list-item__name">{!! $label !!}</span>
3+
<span id="{{ $attrs->get('id') }}">{!! $label !!}</span>
44
<input type="hidden" name="{{ $attrs->get('name') }}" value="{{ $attrs->get('value') }}">
55
</div>
66
@unless($attrs->get('readonly') || $attrs->get('disabled'))

resources/views/fields/relation.blade.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class="btn btn--primary btn--lg btn--block"
5656
<template x-for="(item, index) in items" :key="item.value">
5757
<li class="file-list-item">
5858
<div class="file-list-item__column">
59-
<span class="file-list-item__name" x-html="item.label"></span>
59+
<span x-html="item.label"></span>
6060
</div>
6161
<div class="file-list-item__actions">
6262
<div class="form-group form-group--vertical-check">

src/Fields/MorphTo.php

Lines changed: 114 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
namespace Cone\Root\Fields;
66

7+
use Closure;
8+
use Cone\Root\Fields\Select as SelectField;
9+
use Cone\Root\Filters\Select;
710
use Illuminate\Database\Eloquent\Builder;
811
use Illuminate\Database\Eloquent\Model;
912
use Illuminate\Database\Eloquent\Relations\MorphTo as EloquentRelation;
@@ -20,6 +23,11 @@ class MorphTo extends BelongsTo
2023
*/
2124
protected string $template = 'root::fields.relation';
2225

26+
/**
27+
* Indicates whether the field is async.
28+
*/
29+
protected bool $async = true;
30+
2331
/**
2432
* The morph types.
2533
*/
@@ -36,24 +44,61 @@ public function getRelation(Model $model): EloquentRelation
3644
/**
3745
* {@inheritdoc}
3846
*/
39-
public function filters(Request $request): array
47+
public function async(bool $value = true): static
4048
{
41-
$filters = parent::filters($request);
49+
return $this;
50+
}
51+
52+
/**
53+
* Get the morph types.
54+
*/
55+
public function getTypes(): array
56+
{
57+
return $this->types;
58+
}
4259

43-
if ($this->isAsync()) {
44-
$typeFilter = Select::make(__('Type'), 'type')
45-
->options(array_map(
60+
/**
61+
* {@inheritdoc}
62+
*/
63+
public function filters(Request $request): array
64+
{
65+
$typeFilter = new class($this) extends Select
66+
{
67+
public function __construct(protected MorphTo $field)
68+
{
69+
parent::__construct('type');
70+
}
71+
72+
public function getName(): string
73+
{
74+
return __('Type');
75+
}
76+
77+
public function apply(Request $request, Builder $query, mixed $value): Builder
78+
{
79+
return $query;
80+
}
81+
82+
public function options(Request $request): array
83+
{
84+
return array_map(
4685
static function (string $type): string {
4786
return __(Str::of($type)->classBasename()->headline()->value());
4887
},
49-
array_combine($this->types, $this->types)
50-
))
51-
->toFilter();
52-
53-
array_unshift($filters, $typeFilter);
54-
}
88+
array_combine($this->field->getTypes(), $this->field->getTypes())
89+
);
90+
}
91+
92+
public function toField(): SelectField
93+
{
94+
return parent::toField()
95+
->value(function (Request $request, Model $model): ?string {
96+
return $model->getAttribute($this->field->getRelation($model)->getMorphType());
97+
});
98+
}
99+
};
55100

56-
return $filters;
101+
return array_merge([$typeFilter], parent::filters($request));
57102
}
58103

59104
/**
@@ -73,6 +118,59 @@ public function resolveRelatableQuery(Request $request, Model $model): Builder
73118
return parent::resolveRelatableQuery($request, $model);
74119
}
75120

121+
/**
122+
* Map the async searchable fields.
123+
*/
124+
protected function mapAsyncSearchableFields(Request $request): Fields
125+
{
126+
$fields = new Fields;
127+
128+
foreach ($this->getSearchableColumns() as $type => $columns) {
129+
foreach ($columns as $column) {
130+
$field = Hidden::make($this->getRelationName(), sprintf('%s:%s', $type, $column))
131+
->searchable(callback: function (Request $request, Builder $query, mixed $value, string $attribute): Builder {
132+
[$type, $column] = explode(':', $attribute);
133+
134+
return match ($query->getModel()::class) {
135+
$type => $query->where($query->qualifyColumn($column), 'like', "%{$value}%", 'or'),
136+
default => $query,
137+
};
138+
});
139+
140+
$fields->push($field);
141+
}
142+
}
143+
144+
return $fields;
145+
}
146+
147+
/**
148+
* {@inheritdoc}
149+
*/
150+
public function searchable(bool|Closure $value = true, ?Closure $callback = null, array $columns = ['id']): static
151+
{
152+
$columns = match (true) {
153+
array_is_list($columns) => array_fill_keys($this->types, $columns),
154+
default => $columns,
155+
};
156+
157+
return parent::searchable($value, $callback, $columns);
158+
}
159+
160+
/**
161+
* Resolve the filter query.
162+
*/
163+
public function resolveSearchQuery(Request $request, Builder $query, mixed $value): Builder
164+
{
165+
if (! $this->isSearchable()) {
166+
return parent::resolveSearchQuery($request, $query, $value);
167+
}
168+
169+
return call_user_func_array($this->searchQueryResolver, [
170+
$request, $query, $value, $this->getSearchableColumns(),
171+
]);
172+
}
173+
76174
/**
77175
* {@inheritdoc}
78176
*/
@@ -95,7 +193,10 @@ public function resolveHydrate(Request $request, Model $model, mixed $value): vo
95193
*/
96194
public function newOption(Model $related, string $label): Option
97195
{
98-
return new Option(sprintf('%s:%s', $related::class, $related->getKey()), $label);
196+
return new Option(
197+
sprintf('%s:%s', $related::class, $related->getKey()),
198+
sprintf('%s (%s)', $label, __(Str::of($related::class)->classBasename()->headline()->value()))
199+
);
99200
}
100201

101202
/**

src/Fields/Relation.php

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ abstract class Relation extends Field implements Form
9494
/**
9595
* Indicates whether the field is async.
9696
*/
97-
protected ?bool $async = false;
97+
protected bool $async = false;
9898

9999
/**
100100
* Determine if the field is computed.
@@ -492,10 +492,7 @@ public function filters(Request $request): array
492492
$fields = $this->resolveFields($request)->authorized($request);
493493

494494
$searchables = match (true) {
495-
$this->isAsync() => new Fields(array_map(
496-
fn (string $column): Hidden => Hidden::make($this->getRelationName(), $column)->searchable(),
497-
$this->getSearchableColumns()
498-
)),
495+
$this->isAsync() => $this->mapAsyncSearchableFields($request),
499496
default => $fields->searchable(),
500497
};
501498

@@ -510,6 +507,17 @@ public function filters(Request $request): array
510507
]));
511508
}
512509

510+
/**
511+
* Map the async searchable fields.
512+
*/
513+
protected function mapAsyncSearchableFields(Request $request): Fields
514+
{
515+
return new Fields(array_map(
516+
fn (string $column): Hidden => Hidden::make($this->getRelationName(), $column)->searchable(),
517+
$this->getSearchableColumns()
518+
));
519+
}
520+
513521
/**
514522
* Handle the callback for the field resolution.
515523
*/

0 commit comments

Comments
 (0)