|
2 | 2 |
|
3 | 3 | namespace Backstage\Fields\Concerns; |
4 | 4 |
|
5 | | -use Filament\Forms; |
6 | | -use Filament\Forms\Components\Fieldset; |
7 | | -use Filament\Forms\Components\Grid; |
8 | | -use Filament\Forms\Components\Repeater; |
9 | | -use Illuminate\Support\Facades\Schema; |
10 | | -use Illuminate\Support\Str; |
| 5 | +use Filament\Forms\Components\KeyValue; |
11 | 6 |
|
12 | 7 | trait HasOptions |
13 | 8 | { |
| 9 | + use HasSelectableValues; |
| 10 | + |
14 | 11 | public static function addOptionsToInput(mixed $input, mixed $field): mixed |
15 | 12 | { |
16 | | - if (isset($field->config['optionType']) && $field->config['optionType'] === 'relationship') { |
17 | | - $options = []; |
18 | | - |
19 | | - foreach ($field->config['relations'] as $relation) { |
20 | | - $resources = config('backstage.fields.selectable_resources'); |
21 | | - $resourceClass = collect($resources)->first(function ($resource) use ($relation) { |
22 | | - $res = new $resource; |
23 | | - $model = $res->getModel(); |
24 | | - $model = new $model; |
25 | | - |
26 | | - if (! isset($relation['resource'])) { |
27 | | - return false; |
28 | | - } |
29 | | - |
30 | | - return $model->getTable() === $relation['resource']; |
31 | | - }); |
32 | | - |
33 | | - if (! $resourceClass) { |
34 | | - continue; |
35 | | - } |
36 | | - |
37 | | - $resource = new $resourceClass; |
38 | | - $model = $resource->getModel(); |
39 | | - $query = $model::query(); |
40 | | - |
41 | | - // Apply filters if they exist |
42 | | - if (isset($relation['relationValue_filters'])) { |
43 | | - foreach ($relation['relationValue_filters'] as $filter) { |
44 | | - if (isset($filter['column'], $filter['operator'], $filter['value'])) { |
45 | | - $query->where($filter['column'], $filter['operator'], $filter['value']); |
46 | | - } |
47 | | - } |
48 | | - } |
49 | | - |
50 | | - $results = $query->get(); |
51 | | - |
52 | | - if ($results->isEmpty()) { |
53 | | - continue; |
54 | | - } |
55 | | - |
56 | | - $opts = $results->pluck($relation['relationValue'] ?? 'name', $relation['relationKey'])->toArray(); |
57 | | - |
58 | | - if (count($opts) === 0) { |
59 | | - continue; |
60 | | - } |
61 | | - |
62 | | - $options[] = $opts; |
63 | | - } |
64 | | - |
65 | | - if (! empty($options)) { |
66 | | - $options = array_merge(...$options); |
67 | | - $input->options($options); |
68 | | - } |
69 | | - } |
70 | | - |
71 | | - if (isset($field->config['optionType']) && $field->config['optionType'] === 'array') { |
72 | | - $input->options($field->config['options']); |
73 | | - } |
74 | | - |
75 | | - return $input; |
| 13 | + return static::addValuesToInput( |
| 14 | + input: $input, |
| 15 | + field: $field, |
| 16 | + type: 'optionType', |
| 17 | + method: 'options' |
| 18 | + ); |
76 | 19 | } |
77 | 20 |
|
78 | 21 | public static function getOptionsConfig(): array |
79 | 22 | { |
80 | | - return [ |
| 23 | + return array_merge(static::getSelectableValuesConfig(), [ |
81 | 24 | 'optionType' => null, |
82 | | - 'options' => [], |
83 | | - 'descriptions' => [], |
84 | | - 'relations' => [], |
85 | | - 'contentType' => null, |
86 | | - 'relationKey' => null, |
87 | | - 'relationValue' => null, |
88 | | - ]; |
| 25 | + ]); |
89 | 26 | } |
90 | 27 |
|
91 | | - public function optionFormFields(): Fieldset |
| 28 | + public function optionFormFields(): \Filament\Forms\Components\Fieldset |
92 | 29 | { |
93 | | - return Forms\Components\Fieldset::make('Options') |
94 | | - ->columnSpanFull() |
95 | | - ->label(__('Options')) |
96 | | - ->schema([ |
97 | | - Forms\Components\Grid::make(2) |
98 | | - ->schema([ |
99 | | - Forms\Components\Select::make('config.optionType') |
100 | | - ->options([ |
101 | | - 'array' => __('Array'), |
102 | | - 'relationship' => __('Relationship'), |
103 | | - ]) |
104 | | - ->searchable() |
105 | | - ->live(onBlur: true) |
106 | | - ->reactive() |
107 | | - ->label(__('Type')), |
108 | | - // Array options |
109 | | - Forms\Components\KeyValue::make('config.options') |
110 | | - ->label(__('Options')) |
111 | | - ->columnSpanFull() |
112 | | - ->visible(fn (Forms\Get $get): bool => $get('config.optionType') == 'array') |
113 | | - ->required(fn (Forms\Get $get): bool => $get('config.optionType') == 'array'), |
114 | | - // Relationship options |
115 | | - Repeater::make('config.relations') |
116 | | - ->label(__('Relations')) |
117 | | - ->schema([ |
118 | | - Grid::make() |
119 | | - ->columns(2) |
120 | | - ->schema([ |
121 | | - Forms\Components\Select::make('resource') |
122 | | - ->label(__('Resource')) |
123 | | - ->searchable() |
124 | | - ->preload() |
125 | | - ->columnSpanFull() |
126 | | - ->live(debounce: 250) |
127 | | - ->afterStateUpdated(function (Forms\Set $set, ?string $state) { |
128 | | - $resources = config('backstage.fields.selectable_resources'); |
129 | | - $resourceClass = collect($resources)->first(function ($resource) use ($state) { |
130 | | - $res = new $resource; |
131 | | - $model = $res->getModel(); |
132 | | - $model = new $model; |
133 | | - |
134 | | - return $model->getTable() === $state; |
135 | | - }); |
136 | | - |
137 | | - if (! $resourceClass) { |
138 | | - return; |
139 | | - } |
140 | | - |
141 | | - $resource = new $resourceClass; |
142 | | - $model = $resource->getModel(); |
143 | | - $model = new $model; |
144 | | - |
145 | | - // Get all column names from the table |
146 | | - $columns = Schema::getColumnListing($model->getTable()); |
147 | | - |
148 | | - // Create options array with column names |
149 | | - $columnOptions = collect($columns)->mapWithKeys(function ($column) { |
150 | | - return [$column => Str::title($column)]; |
151 | | - })->toArray(); |
152 | | - |
153 | | - $set('relationValue', null); |
154 | | - $set('relationValue_options', $columnOptions); |
155 | | - }) |
156 | | - ->options(function () { |
157 | | - $resources = config('backstage.fields.selectable_resources'); |
158 | | - |
159 | | - return collect($resources)->map(function ($resource) { |
160 | | - $res = new $resource; |
161 | | - $model = $res->getModel(); |
162 | | - $model = new $model; |
163 | | - |
164 | | - return [ |
165 | | - $model->getTable() => Str::title($model->getTable()), |
166 | | - ]; |
167 | | - }) |
168 | | - ->collapse() |
169 | | - ->toArray(); |
170 | | - }) |
171 | | - ->noSearchResultsMessage(__('No types found')) |
172 | | - ->required(fn (Forms\Get $get): bool => $get('config.optionType') == 'relationship'), |
173 | | - Forms\Components\Hidden::make('relationKey') |
174 | | - ->default('ulid') |
175 | | - ->label(__('Key')) |
176 | | - ->required(fn (Forms\Get $get): bool => $get('config.optionType') == 'relationship'), |
177 | | - Forms\Components\Repeater::make('relationValue_filters') |
178 | | - ->label(__('Filters')) |
179 | | - ->visible(fn (Forms\Get $get): bool => ! empty($get('resource'))) |
180 | | - ->schema([ |
181 | | - Forms\Components\Grid::make(3) |
182 | | - ->schema([ |
183 | | - Forms\Components\Select::make('column') |
184 | | - ->options(fn (\Filament\Forms\Get $get) => $get('../../relationValue_options') ?? [ |
185 | | - 'slug' => __('Slug'), |
186 | | - 'name' => __('Name'), |
187 | | - ]) |
188 | | - ->live() |
189 | | - ->label(__('Column')), |
190 | | - Forms\Components\Select::make('operator') |
191 | | - ->options([ |
192 | | - '=' => __('Equal'), |
193 | | - '!=' => __('Not equal'), |
194 | | - '>' => __('Greater than'), |
195 | | - '<' => __('Less than'), |
196 | | - '>=' => __('Greater than or equal to'), |
197 | | - '<=' => __('Less than or equal to'), |
198 | | - 'LIKE' => __('Like'), |
199 | | - 'NOT LIKE' => __('Not like'), |
200 | | - ]) |
201 | | - ->label(__('Operator')), |
202 | | - Forms\Components\TextInput::make('value') |
203 | | - ->datalist(function (Forms\Get $get) { |
204 | | - $resource = $get('../../resource'); |
205 | | - $column = $get('column'); |
206 | | - |
207 | | - if (! $resource || ! $column) { |
208 | | - return []; |
209 | | - } |
210 | | - |
211 | | - $resources = config('backstage.fields.selectable_resources'); |
212 | | - $resourceClass = collect($resources)->first(function ($r) use ($resource) { |
213 | | - $res = new $r; |
214 | | - $model = $res->getModel(); |
215 | | - $model = new $model; |
216 | | - |
217 | | - return $model->getTable() === $resource; |
218 | | - }); |
219 | | - |
220 | | - if (! $resourceClass) { |
221 | | - return []; |
222 | | - } |
223 | | - |
224 | | - $resource = new $resourceClass; |
225 | | - $model = $resource->getModel(); |
226 | | - |
227 | | - return $model::query() |
228 | | - ->select($column) |
229 | | - ->distinct() |
230 | | - ->pluck($column) |
231 | | - ->toArray(); |
232 | | - }) |
233 | | - ->label(__('Value')), |
234 | | - ]), |
235 | | - ]) |
236 | | - ->columnSpanFull(), |
237 | | - ]), |
238 | | - ]) |
239 | | - ->visible(fn (Forms\Get $get): bool => $get('config.optionType') == 'relationship') |
240 | | - ->columnSpanFull(), |
241 | | - ]), |
242 | | - ]); |
| 30 | + return $this->selectableValuesFormFields( |
| 31 | + type: 'optionType', |
| 32 | + label: 'Options', |
| 33 | + arrayComponent: KeyValue::class |
| 34 | + ); |
243 | 35 | } |
244 | 36 | } |
0 commit comments