44
55namespace Relaticle \Flowforge \Adapters ;
66
7- use App \Models \Task ;
87use Filament \Forms \Form ;
8+ use Illuminate \Database \Eloquent \Builder ;
99use Illuminate \Database \Eloquent \Model ;
1010use Illuminate \Support \Collection ;
1111use Livewire \Wireable ;
1212use Relaticle \Flowforge \Config \KanbanConfig ;
1313use Relaticle \Flowforge \Contracts \KanbanAdapterInterface ;
1414
15- /**
16- * Abstract implementation of the Kanban adapter interface.
17- *
18- * This class provides shared functionality for all Eloquent-based Kanban adapters,
19- * including configuration management and common form building logic.
20- */
2115abstract class AbstractKanbanAdapter implements KanbanAdapterInterface, Wireable
2216{
17+ /**
18+ * The base Eloquent query builder.
19+ *
20+ * @var Builder
21+ */
22+ public Builder $ baseQuery ;
23+
2324 /**
2425 * Create a new abstract Kanban adapter instance.
2526 */
2627 public function __construct (
27- protected readonly KanbanConfig $ config
28+ Builder $ query ,
29+ public KanbanConfig $ config
2830 ) {
2931 }
3032
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 ();
157+ }
158+
31159 /**
32160 * Get the configuration for this adapter.
33161 */
@@ -44,17 +172,9 @@ public function getConfig(): KanbanConfig
44172 */
45173 public function getCreateForm (Form $ form , mixed $ activeColumn ): Form
46174 {
47- // Check for custom create form callback
48- $ createCallback = $ this ->config ->getCreateFormCallback ();
49-
50- if ($ createCallback !== null && is_callable ($ createCallback )) {
51- return $ createCallback ($ form , $ activeColumn );
52- }
53-
54175 // Fall back to default create form implementation
55176 $ titleField = $ this ->config ->getTitleField ();
56177 $ descriptionField = $ this ->config ->getDescriptionField ();
57- $ columnField = $ this ->config ->getColumnField ();
58178
59179 $ schema = KanbanConfig::getDefaultCreateFormSchema ($ titleField , $ descriptionField );
60180
@@ -74,20 +194,6 @@ public function getCreateForm(Form $form, mixed $activeColumn): Form
74194 */
75195 public function getEditForm (Form $ form ): Form
76196 {
77- // Check for custom edit form callback
78- $ editCallback = $ this ->config ->getEditFormCallback ();
79-
80- if ($ editCallback !== null && is_callable ($ editCallback )) {
81- return $ editCallback ($ form );
82- }
83-
84- // Check for custom create form callback as a fallback
85- $ createCallback = $ this ->config ->getCreateFormCallback ();
86-
87- if ($ createCallback !== null && is_callable ($ createCallback )) {
88- return $ createCallback ($ form , null );
89- }
90-
91197 // Fall back to default edit form implementation
92198 $ titleField = $ this ->config ->getTitleField ();
93199 $ descriptionField = $ this ->config ->getDescriptionField ();
@@ -182,4 +288,32 @@ public function updateCardsOrderAndColumn(string|int $columnId, array $cardIds):
182288
183289 return $ success ;
184290 }
291+
292+
293+ /**
294+ * Convert the adapter to a Livewire-compatible array.
295+ *
296+ * @return array<string, mixed>
297+ */
298+ public function toLivewire (): array
299+ {
300+ return [
301+ 'query ' => \EloquentSerialize::serialize ($ this ->baseQuery ),
302+ 'config ' => $ this ->config ->toArray (),
303+ ];
304+ }
305+
306+ /**
307+ * Create a new adapter instance from a Livewire-compatible array.
308+ *
309+ * @param array<string, mixed> $value The Livewire-compatible array
310+ * @return static
311+ */
312+ public static function fromLivewire ($ value ): static
313+ {
314+ $ query = \EloquentSerialize::unserialize ($ value ['query ' ]);
315+ $ config = new KanbanConfig (...$ value ['config ' ]);
316+
317+ return new static ($ query , $ config );
318+ }
185319}
0 commit comments