Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
4451644
Implement Flowforge integration in TasksBoard for task management
ManukMinasyan Aug 21, 2025
5b4134a
Refactor board components and update view references for improved str…
ManukMinasyan Aug 22, 2025
80f2e11
Add view data retrieval and column action methods to Board and Intera…
ManukMinasyan Aug 22, 2025
def3286
Enhance TasksBoard with action management and improved task display f…
ManukMinasyan Aug 22, 2025
50994de
Refactor BoardPage to prioritize action record retrieval and enhance …
ManukMinasyan Aug 22, 2025
30e3d41
Refactor TasksBoard and Board components to improve action and record…
ManukMinasyan Aug 22, 2025
caebb6e
Remove unused Eloquent query methods from TasksBoard and BoardPage fo…
ManukMinasyan Aug 22, 2025
6e989bb
Refactor TasksBoard and Board components to use record title and desc…
ManukMinasyan Aug 22, 2025
4d4e2bb
Refactor Board and HasBoardRecords components to allow nullable descr…
ManukMinasyan Aug 22, 2025
d5bc950
Refactor HasBoardRecords to improve attribute handling and clean up c…
ManukMinasyan Aug 22, 2025
1fa7e2a
Refactor TasksBoard and UserKanbanBoard to replace defaultSort with r…
ManukMinasyan Aug 22, 2025
41fc3d5
Enhance TasksBoard and ListProducts with searchable attributes and im…
ManukMinasyan Aug 22, 2025
b43451b
Refactor TasksBoard to implement card schema for enhanced display and…
ManukMinasyan Aug 22, 2025
35bf08a
Refactor card, column, and empty-column components for improved styli…
ManukMinasyan Aug 22, 2025
3e182c4
Remove unused Blade components from FlowforgeServiceProvider for clea…
ManukMinasyan Aug 22, 2025
b98dfd5
Refactor card component to adjust hover styles for improved visual fe…
ManukMinasyan Aug 22, 2025
fe816c3
Refactor TasksBoard to replace Flex with CardFlex for improved layout…
ManukMinasyan Aug 22, 2025
b48cb31
Refactor HasBoardRecords and InteractsWithBoard to implement configur…
ManukMinasyan Aug 22, 2025
cac6c85
Refactor TasksBoard and InteractsWithBoard to support descending orde…
ManukMinasyan Aug 22, 2025
3d6c5d8
Add comprehensive feature test suite and fix core API issues
ManukMinasyan Aug 22, 2025
44a3b73
Fix API documentation in README.md to use correct method names
ManukMinasyan Aug 22, 2025
1eed064
Use getKey() method instead of hardcoded id property in tests
ManukMinasyan Aug 22, 2025
f77ea69
Update documentation with accurate API methods and real-world examples
ManukMinasyan Aug 22, 2025
0ae21b6
Add BoardResourcePage and enhance InteractsWithKanbanQuery for improv…
ManukMinasyan Aug 22, 2025
7290bad
Fix styling
ManukMinasyan Aug 22, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
305 changes: 259 additions & 46 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ use Relaticle\Flowforge\Board;
use Relaticle\Flowforge\BoardPage;
use Relaticle\Flowforge\Column;

class TaskBoard extends BoardPage
class TaskBoardPage extends BoardPage
{
protected static ?string $navigationIcon = 'heroicon-o-view-columns';

Expand All @@ -62,8 +62,9 @@ class TaskBoard extends BoardPage
{
return $board
->query($this->getEloquentQuery())
->cardTitle('title')
->recordTitleAttribute('title')
->columnIdentifier('status')
->reorderBy('order_column')
->columns([
Column::make('todo')->label('To Do')->color('gray'),
Column::make('in_progress')->label('In Progress')->color('blue'),
Expand Down Expand Up @@ -135,7 +136,7 @@ php artisan flowforge:make-board TaskBoard --model=Task
```php
// app/Providers/Filament/AdminPanelProvider.php
->pages([
App\Filament\Pages\TaskBoard::class,
App\Filament\Pages\TaskBoardPage::class,
])
```

Expand All @@ -153,7 +154,7 @@ public function board(Board $board): Board
{
return $board
->query($this->getEloquentQuery())
->cardTitle('title')
->recordTitleAttribute('title')
->columnIdentifier('status')
->columns([
Column::make('backlog')->label('Backlog'),
Expand All @@ -169,41 +170,79 @@ Add create and edit capabilities:
```php
use Filament\Actions\CreateAction;
use Filament\Actions\EditAction;
use Filament\Actions\DeleteAction;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Select;

public function board(Board $board): Board
{
return $board
->query($this->getEloquentQuery())
->cardTitle('title')
->recordTitleAttribute('title')
->columnIdentifier('status')
->columns([...])
->reorderBy('order_column')
->columns([
Column::make('todo')->label('To Do')->color('gray'),
Column::make('in_progress')->label('In Progress')->color('blue'),
Column::make('completed')->label('Completed')->color('green'),
])
->columnActions([
CreateAction::make()
CreateAction::make('create')
->label('Add Task')
->iconButton()
->icon('heroicon-o-plus')
->model(Task::class)
->schema([
->form([
TextInput::make('title')->required(),
]),
Select::make('priority')
->options(['low' => 'Low', 'medium' => 'Medium', 'high' => 'High'])
->default('medium'),
])
->mutateFormDataUsing(function (array $data, string $columnId): array {
$data['status'] = $columnId;
return $data;
}),
])
->cardActions([
EditAction::make()->model(Task::class),
]);
EditAction::make('edit')->model(Task::class),
DeleteAction::make('delete')->model(Task::class),
])
->cardAction('edit'); // Make cards clickable
}
```

### Advanced Board with Properties
Display additional model attributes:
### Advanced Board with Schema
Use Filament's Schema system for rich card content:

```php
use Relaticle\Flowforge\Property;
use Filament\Infolists\Components\TextEntry;
use Filament\Schemas\Schema;

->cardProperties([
Property::make('description')->label('Description'),
Property::make('due_date')->label('Due')->color('red'),
Property::make('assignee.name')->label('Assigned')->icon('heroicon-o-user'),
])
public function board(Board $board): Board
{
return $board
->query($this->getEloquentQuery())
->recordTitleAttribute('title')
->columnIdentifier('status')
->cardSchema(fn (Schema $schema) => $schema
->components([
TextEntry::make('priority')
->badge()
->color(fn ($state) => match ($state) {
'high' => 'danger',
'medium' => 'warning',
'low' => 'success',
default => 'gray',
}),
TextEntry::make('due_date')
->date()
->icon('heroicon-o-calendar'),
TextEntry::make('assignee.name')
->icon('heroicon-o-user')
->placeholder('Unassigned'),
])
)
->columns([...]);
}
```

---
Expand All @@ -214,14 +253,26 @@ use Relaticle\Flowforge\Property;

| Method | Description | Required |
|--------|-------------|----------|
| `cardTitle(string)` | Field used for card titles | ✅ |
| `query(Builder\|Closure)` | Set the data source | ✅ |
| `recordTitleAttribute(string)` | Field used for card titles | ✅ |
| `columnIdentifier(string)` | Field that determines column placement | ✅ |
| `columns(array)` | Define board columns | ✅ |
| `query(Builder)` | Set the data source | ✅ |
| `defaultSort(string, ?string)` | Field and optional direction for drag & drop ordering | |
| `cardProperties(array)` | Additional fields to display | |
| `columnActions(array)` | Actions for column headers | |
| `reorderBy(string, string)` | Enable drag & drop with field and direction | |
| `cardSchema(Closure)` | Configure card content with Filament Schema | |
| `cardActions(array)` | Actions for individual cards | |
| `columnActions(array)` | Actions for column headers | |
| `cardAction(string)` | Default action when cards are clicked | |
| `searchable(array)` | Enable search across specified fields | |

### Livewire Methods (Available in your BoardPage)

| Method | Description | Usage |
|--------|-------------|-------|
| `updateRecordsOrderAndColumn(string, array)` | Handle drag & drop updates | Automatic |
| `loadMoreItems(string, ?int)` | Load more cards for pagination | Automatic |
| `getBoardRecord(int\|string)` | Get single record by ID | Manual |
| `getBoardColumnRecords(string)` | Get all records for a column | Manual |
| `getBoardColumnRecordCount(string)` | Count records in a column | Manual |

### Available Colors

Expand All @@ -231,39 +282,201 @@ use Relaticle\Flowforge\Property;

## Troubleshooting

<details>
<summary><strong>🔧 Cards not draggable</strong></summary>
### 🔧 Cards not draggable
**Cause:** Missing order column or reorderBy configuration
**Solution:**
1. Add integer column to your migration: `$table->integer('order_column')->nullable();`
2. Add `->reorderBy('order_column')` to your board configuration
3. Ensure your model's `$fillable` includes the order column

### 📭 Empty board showing
**Cause:** Query returns no results or status field mismatch
**Debug steps:**
1. Check query: `dd($this->getEloquentQuery()->get());`
2. Verify status values match column names exactly
3. Check database field type (string vs enum)

### ❌ Actions not working
**Cause:** Missing Filament traits or action configuration
**Solution:**
1. Ensure your BoardPage implements `HasActions`, `HasForms`
2. Use these traits in your class:
```php
use InteractsWithActions;
use InteractsWithForms;
use InteractsWithBoard;
```
3. Configure actions properly with `->model(YourModel::class)`

### 🔄 Drag & drop updates not saving
**Cause:** Missing primary key handling or invalid field names
**Solution:**
1. Add an integer `order_column` to your model
2. Configure `->defaultSort('order_column')` in your board
1. Ensure your model uses standard primary key or override `getKeyName()`
2. Check status field accepts the column identifier values
3. Verify order column exists and is fillable

### 💥 "No default Filament panel" error
**Cause:** Missing panel configuration in tests/development
**Solution:** Add to your panel provider:
```php
->defaultSort('order_column')
Panel::make()->default()->id('admin')
```
</details>

<details>
<summary><strong>📭 Empty board</strong></summary>

### 🎨 Styling not loading
**Cause:** Assets not built or registered
**Solution:**
1. Ensure your model has records
2. Check status field values match column keys
3. Debug with: `dd($this->getEloquentQuery()->get())`
</details>
1. Run `npm run build` to compile assets
2. Ensure Filament can load the assets with proper permissions

<details>
<summary><strong>❌ Create/Edit not working</strong></summary>
## Real-World Examples

**Solution:**
1. Implement `columnActions()` for create functionality
2. Implement `cardActions()` for edit functionality
3. Ensure proper action configuration
### Complete Task Management Board

```php
<?php

namespace App\Filament\Pages;

use App\Models\Task;
use Filament\Actions\CreateAction;
use Filament\Actions\EditAction;
use Filament\Actions\DeleteAction;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\DatePicker;
use Filament\Infolists\Components\TextEntry;
use Filament\Schemas\Schema;
use Illuminate\Database\Eloquent\Builder;
use Relaticle\Flowforge\Board;
use Relaticle\Flowforge\BoardPage;
use Relaticle\Flowforge\Column;

class TaskBoardPage extends BoardPage
{
protected static ?string $navigationIcon = 'heroicon-o-view-columns';
protected static ?string $navigationLabel = 'Task Board';

public function getEloquentQuery(): Builder
{
return Task::query()->with('assignee');
}

public function board(Board $board): Board
{
return $board
->query($this->getEloquentQuery())
->recordTitleAttribute('title')
->columnIdentifier('status')
->reorderBy('order_column', 'desc')
->searchable(['title', 'description', 'assignee.name'])
->columns([
Column::make('todo')->label('📋 To Do')->color('gray'),
Column::make('in_progress')->label('🔄 In Progress')->color('blue'),
Column::make('review')->label('👁️ Review')->color('purple'),
Column::make('completed')->label('✅ Completed')->color('green'),
])
->cardSchema(fn (Schema $schema) => $schema
->components([
TextEntry::make('priority')
->badge()
->color(fn ($state) => match ($state) {
'high' => 'danger',
'medium' => 'warning',
'low' => 'success',
default => 'gray',
}),
TextEntry::make('due_date')
->date()
->icon('heroicon-o-calendar')
->color('orange'),
TextEntry::make('assignee.name')
->icon('heroicon-o-user')
->placeholder('Unassigned'),
])
)
->columnActions([
CreateAction::make('create')
->label('Add Task')
->icon('heroicon-o-plus')
->model(Task::class)
->form([
TextInput::make('title')->required(),
Select::make('priority')
->options(['low' => 'Low', 'medium' => 'Medium', 'high' => 'High'])
->default('medium'),
DatePicker::make('due_date'),
])
->mutateFormDataUsing(function (array $data, string $columnId): array {
$data['status'] = $columnId;
return $data;
}),
])
->cardActions([
EditAction::make('edit')
->model(Task::class)
->form([
TextInput::make('title')->required(),
Select::make('status')
->options([
'todo' => 'To Do',
'in_progress' => 'In Progress',
'review' => 'Review',
'completed' => 'Completed',
]),
Select::make('priority')
->options(['low' => 'Low', 'medium' => 'Medium', 'high' => 'High']),
DatePicker::make('due_date'),
]),
DeleteAction::make('delete')
->model(Task::class)
->requiresConfirmation(),
])
->cardAction('edit'); // Make cards clickable to edit
}
}
```

### Required Database Schema

```sql
CREATE TABLE tasks (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(255) NOT NULL,
status VARCHAR(255) DEFAULT 'todo',
order_column INT NULL, -- Required for drag & drop
priority VARCHAR(255) DEFAULT 'medium',
due_date DATE NULL,
assignee_id BIGINT UNSIGNED NULL,
created_at TIMESTAMP NULL,
updated_at TIMESTAMP NULL
);
```

### Testing Your Board

```php
->columnActions([CreateAction::make()->model(Task::class)])
// tests/Feature/TaskBoardTest.php
use Livewire\Livewire;

test('task board renders successfully', function () {
Task::create(['title' => 'Test Task', 'status' => 'todo']);

Livewire::test(TaskBoardPage::class)
->assertSuccessful()
->assertSee('Test Task')
->assertSee('To Do');
});

test('can move tasks between columns', function () {
$task = Task::create(['title' => 'Test Task', 'status' => 'todo']);

Livewire::test(TaskBoardPage::class)
->call('updateRecordsOrderAndColumn', 'completed', [$task->getKey()])
->assertSuccessful();

expect($task->fresh()->status)->toBe('completed');
});
```
</details>

---

Expand Down
Loading