Skip to content

Commit 6e103fc

Browse files
committed
UP
1 parent e38d0d4 commit 6e103fc

File tree

2 files changed

+23
-263
lines changed

2 files changed

+23
-263
lines changed

src/Adapters/AbstractKanbanAdapter.php

Lines changed: 22 additions & 262 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,31 @@
44

55
namespace Relaticle\Flowforge\Adapters;
66

7-
use Filament\Forms\Form;
87
use Illuminate\Database\Eloquent\Builder;
9-
use Illuminate\Database\Eloquent\Model;
10-
use Illuminate\Support\Collection;
118
use Livewire\Wireable;
129
use Relaticle\Flowforge\Config\KanbanConfig;
1310
use Relaticle\Flowforge\Contracts\KanbanAdapterInterface;
14-
11+
use Relaticle\Flowforge\Concerns\CardFormattingTrait;
12+
use Relaticle\Flowforge\Concerns\CrudOperationsTrait;
13+
use Relaticle\Flowforge\Concerns\FormHandlingTrait;
14+
use Relaticle\Flowforge\Concerns\QueryHandlingTrait;
15+
16+
/**
17+
* Abstract base class for Kanban adapters.
18+
*
19+
* This class has been refactored to use traits for better separation of concerns:
20+
* - QueryHandlingTrait: For database query operations
21+
* - CardFormattingTrait: For formatting models as cards
22+
* - CrudOperationsTrait: For card CRUD operations
23+
* - FormHandlingTrait: For form generation and handling
24+
*/
1525
abstract class AbstractKanbanAdapter implements KanbanAdapterInterface, Wireable
1626
{
27+
use QueryHandlingTrait;
28+
use CardFormattingTrait;
29+
use CrudOperationsTrait;
30+
use FormHandlingTrait;
31+
1732
/**
1833
* The base Eloquent query builder.
1934
*
@@ -28,132 +43,7 @@ public function __construct(
2843
Builder $query,
2944
public KanbanConfig $config
3045
) {
31-
}
32-
33-
/**
34-
* Get a new query builder, cloned from the base query.
35-
*/
36-
protected function newQuery(): Builder
37-
{
38-
return clone $this->baseQuery;
39-
}
40-
41-
/**
42-
* Find a model by its ID.
43-
*
44-
* @param mixed $id The model ID
45-
*/
46-
public function getModelById(mixed $id): ?Model
47-
{
48-
// Just find by ID without additional filters from the base query
49-
// This ensures we can find models by ID regardless of the base query filters
50-
return $this->baseQuery->getModel()::query()->find($id);
51-
}
52-
53-
/**
54-
* Get all items for the Kanban board.
55-
*/
56-
public function getItems(): Collection
57-
{
58-
$query = $this->newQuery();
59-
$orderField = $this->config->getOrderField();
60-
61-
if ($orderField !== null) {
62-
$query->orderBy($orderField);
63-
}
64-
65-
$models = $query->get();
66-
67-
return $this->formatCardsForDisplay($models);
68-
}
69-
70-
/**
71-
* Get items for a specific column with pagination.
72-
*
73-
* @param string|int $columnId The column ID
74-
* @param int $limit The number of items to return
75-
*/
76-
public function getItemsForColumn(string|int $columnId, int $limit = 10): Collection
77-
{
78-
$columnField = $this->config->getColumnField();
79-
$orderField = $this->config->getOrderField();
80-
81-
$query = $this->newQuery()->where($columnField, $columnId);
82-
83-
if ($orderField !== null) {
84-
$query->orderBy($orderField);
85-
}
86-
87-
$models = $query->limit($limit)->get();
88-
89-
return $this->formatCardsForDisplay($models);
90-
}
91-
92-
/**
93-
* Get the total count of items for a specific column.
94-
*
95-
* @param string|int $columnId The column ID
96-
*/
97-
public function getColumnItemsCount(string|int $columnId): int
98-
{
99-
$columnField = $this->config->getColumnField();
100-
101-
return $this->newQuery()
102-
->where($columnField, $columnId)
103-
->count();
104-
}
105-
106-
/**
107-
* Create a new card with the given attributes.
108-
*
109-
* @param array<string, mixed> $attributes The card attributes
110-
*/
111-
public function createCard(array $attributes): ?Model
112-
{
113-
$model = $this->baseQuery->getModel()->newInstance();
114-
115-
// Apply any scopes from the base query if applicable
116-
// For example, if the base query filters by user_id, we want to set that on the new model
117-
$wheres = $this->baseQuery->getQuery()->wheres;
118-
119-
foreach ($wheres as $where) {
120-
if (isset($where['column']) && isset($where['value']) && $where['type'] === 'Basic') {
121-
// If the filter is a basic where clause, apply it to the new model
122-
// This ensures models created through this adapter respect the base query conditions
123-
$model->{$where['column']} = $where['value'];
124-
}
125-
}
126-
127-
$model->fill($attributes);
128-
129-
if ($model->save()) {
130-
return $model;
131-
}
132-
133-
return null;
134-
}
135-
136-
/**
137-
* Update an existing card with the given attributes.
138-
*
139-
* @param Model $card The card to update
140-
* @param array<string, mixed> $attributes The card attributes to update
141-
*/
142-
public function updateCard(Model $card, array $attributes): bool
143-
{
144-
$card->fill($attributes);
145-
146-
return $card->save();
147-
}
148-
149-
/**
150-
* Delete an existing card.
151-
*
152-
* @param Model $card The card to delete
153-
*/
154-
public function deleteCard(Model $card): bool
155-
{
156-
return $card->delete();
46+
$this->baseQuery = $query;
15747
}
15848

15949
/**
@@ -165,135 +55,7 @@ public function getConfig(): KanbanConfig
16555
}
16656

16757
/**
168-
* Get the form for creating cards.
169-
*
170-
* @param Form $form The form instance
171-
* @param mixed $activeColumn The active column
172-
*/
173-
public function getCreateForm(Form $form, mixed $activeColumn): Form
174-
{
175-
// Fall back to default create form implementation
176-
$titleField = $this->config->getTitleField();
177-
$descriptionField = $this->config->getDescriptionField();
178-
179-
$schema = KanbanConfig::getDefaultCreateFormSchema($titleField, $descriptionField);
180-
181-
// For create form, set the column field value based on the active column
182-
// but hide it from the form as it's determined by where the user clicked
183-
if ($activeColumn) {
184-
$form->statePath(null);
185-
}
186-
187-
return $form->schema($schema);
188-
}
189-
190-
/**
191-
* Get the form for editing cards.
192-
*
193-
* @param Form $form The form instance
194-
*/
195-
public function getEditForm(Form $form): Form
196-
{
197-
// Fall back to default edit form implementation
198-
$titleField = $this->config->getTitleField();
199-
$descriptionField = $this->config->getDescriptionField();
200-
$columnField = $this->config->getColumnField();
201-
$columnValues = $this->config->getColumnValues();
202-
203-
$schema = KanbanConfig::getDefaultEditFormSchema(
204-
$titleField,
205-
$descriptionField,
206-
$columnField,
207-
$columnValues
208-
);
209-
210-
return $form->schema($schema);
211-
}
212-
213-
/**
214-
* Format a model as a card for display.
215-
*
216-
* @param Model $model The model to format
217-
* @return array<string, mixed> The formatted card
218-
*/
219-
protected function formatCardForDisplay(Model $model): array
220-
{
221-
$titleField = $this->config->getTitleField();
222-
$descriptionField = $this->config->getDescriptionField();
223-
$cardAttributes = $this->config->getCardAttributes();
224-
$columnField = $this->config->getColumnField();
225-
226-
$card = [
227-
'id' => $model->getKey(),
228-
'title' => $model->{$titleField},
229-
'column' => $model->{$columnField},
230-
];
231-
232-
if ($descriptionField !== null && isset($model->{$descriptionField})) {
233-
$card['description'] = $model->{$descriptionField};
234-
}
235-
236-
foreach ($cardAttributes as $key => $label) {
237-
$field = is_string($key) ? $key : $label;
238-
$card['attributes'][$field] = [
239-
'label' => is_string($key) ? $label : $field,
240-
'value' => $model->{$field},
241-
];
242-
}
243-
244-
return $card;
245-
}
246-
247-
/**
248-
* Format a collection of models as cards for display.
249-
*
250-
* @param Collection $models The models to format
251-
* @return Collection The formatted cards
252-
*/
253-
protected function formatCardsForDisplay(Collection $models): Collection
254-
{
255-
return $models->map(fn (Model $model) => $this->formatCardForDisplay($model));
256-
}
257-
258-
/**
259-
* Update the order of cards in a column.
260-
*
261-
* @param string|int $columnId The column ID
262-
* @param array<int, mixed> $cardIds The card IDs in their new order
263-
* @return bool Whether the operation was successful
264-
*/
265-
public function updateCardsOrderAndColumn(string|int $columnId, array $cardIds): bool
266-
{
267-
$orderField = $this->config->getOrderField();
268-
$columnField = $this->config->getColumnField();
269-
$success = true;
270-
271-
foreach ($cardIds as $index => $cardId) {
272-
$model = $this->getModelById($cardId);
273-
274-
if ($model === null) {
275-
$success = false;
276-
continue;
277-
}
278-
279-
if ($orderField !== null) {
280-
$model->{$orderField} = $index + 1;
281-
}
282-
$model->{$columnField} = $columnId;
283-
284-
if (!$model->save()) {
285-
$success = false;
286-
}
287-
}
288-
289-
return $success;
290-
}
291-
292-
293-
/**
294-
* Convert the adapter to a Livewire-compatible array.
295-
*
296-
* @return array<string, mixed>
58+
* @return array
29759
*/
29860
public function toLivewire(): array
29961
{
@@ -304,9 +66,7 @@ public function toLivewire(): array
30466
}
30567

30668
/**
307-
* Create a new adapter instance from a Livewire-compatible array.
308-
*
309-
* @param array<string, mixed> $value The Livewire-compatible array
69+
* @param $value
31070
* @return static
31171
*/
31272
public static function fromLivewire($value): static

tests/Feature/KanbanBoardTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use Livewire\Livewire;
88
use Relaticle\Flowforge\Livewire\KanbanBoard;
99
use Relaticle\Flowforge\Tests\TestCase;
10-
use Relaticle\Flowforge\Traits\HasKanbanBoard;
10+
use Relaticle\Flowforge\Concerns\HasKanbanBoard;
1111

1212
// Mock Task model for testing
1313
class MockTask extends Model

0 commit comments

Comments
 (0)