-
-
Notifications
You must be signed in to change notification settings - Fork 45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Request]: Allow a Kanban board per resource record #33
Comments
I think I've managed to get it to work. I was using a protected property rather than a public property for my campaign and so it wasn't being available on subsequent requests. |
I have some source code implementing a kanban per resource, if you are interested we can work in a PR request to install either the board globally or in a resource |
Hi @ryanmortier i used your code to replicate same scenario. When i type an id for campaign, it works great but with query string there is a problem on subsequent requests. Query string return null. Did you find a way to solve query string problem ? |
@ahmetkocabiyik yes you'll need to change your query string variable from <?php
namespace App\Filament\Crm\Pages;
use App\Filament\Crm\Resources\CampaignResource;
use App\Models\Crm\Account;
use App\Models\Crm\AccountCampaign;
use App\Models\Crm\Campaign;
use App\Models\Crm\CampaignStage;
use Filament\Actions;
use Illuminate\Contracts\Support\Htmlable;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;
use Illuminate\Support\HtmlString;
use Mokhosh\FilamentKanban\Pages\KanbanBoard;
class CampaignKanbanBoard extends KanbanBoard
{
protected static ?string $slug = 'campaigns/board';
protected static string $model = Account::class;
protected static string $recordTitleAttribute = 'name';
protected static string $recordStatusAttribute = 'sort_order';
protected static bool $shouldRegisterNavigation = false;
public bool $disableEditModal = true;
public Campaign $campaign;
public function mount(): void
{
parent::mount();
$this->campaign = Campaign::findOrFail(request()->query('id'));
}
public function getBreadcrumbs(): array
{
return [
route('filament.crm.resources.campaigns.index') => 'Campaigns',
route('filament.crm.pages.campaigns.board', ['id' => $this->campaign->id]) => $this->campaign->name,
'Board',
];
}
public function getHeading(): string|Htmlable
{
return $this->campaign->name;
}
public function getSubheading(): string|Htmlable|null
{
$subheading = '<strong>'.e($this->campaign->start->format('M j, Y')).'</strong>';
$subheading .= ' to ';
$subheading .= '<strong>'.e($this->campaign->end->format('M j, Y')).'</strong>';
if ($this->campaign->description) {
$subheading .= '<br><p class="text-gray-600 dark:text-gray-400">'.nl2br(e($this->campaign->description)).'</p>';
}
return new HtmlString($subheading);
}
public function onStatusChanged(int $recordId, string $status, array $fromOrderedIds, array $toOrderedIds): void
{
$stage = CampaignStage::find($status);
$pivot = AccountCampaign::query()
->where('campaign_id', $this->campaign->id)
->where('account_id', $recordId)
->first();
if (! $pivot) {
return;
}
if ($stage) {
$pivot->stage()->associate($stage);
} else {
$pivot->stage()->dissociate();
}
$pivot->save();
$this->changeSortOrder($toOrderedIds);
}
protected function changeSortOrder(array $ids): void
{
AccountCampaign::setNewOrder(
$ids,
1,
'account_id',
function (Builder $query): Builder {
return $query->where('campaign_id', '=', $this->campaign->id);
}
);
}
public function onSortChanged(int $recordId, string $status, array $orderedIds): void
{
$this->changeSortOrder($orderedIds);
}
protected function records(): Collection
{
return $this->campaign
->accounts()
->orderByPivot('sort_order')
->orderBy('name')
->get();
}
protected function getHeaderActions(): array
{
return [
Actions\EditAction::make()
->url(fn (): string => CampaignResource::getUrl(
'edit',
['record' => $this->campaign]
)),
];
}
protected function statuses(): Collection
{
$new = ['id' => 0, 'title' => 'New'];
return $this->campaign->stages()->ordered()->get()->map(function ($stage) {
return ['id' => $stage->id, 'title' => $stage->name];
})->prepend($new);
}
protected function filterRecordsByStatus(Collection $records, array $status): array
{
return $records->where('pivot.campaign_stage_id', '=', $status['id'])->all();
}
} |
What happened?
I'm looking to be able to dynamically show a Kanban board per resource record. Take for instance the following example:
A
Campaign
model has abelongsToMany
relationship to anAccount
model.A
Campaign
also has ahasMany
relationship to aCampaignStage
model.The flow from a user would be that they create a campaign and attach accounts to the campaign. An account could potentially be added to many other campaigns. The user would also add a list of stages to each campaign and therefore each campaign may have a different set of stages (statuses).
On the API side, I would like to add a page to the
CampaignResource::class
and add the page to thegetPages()
method which would allow the page to receive the record via theInteractsWithRecords
trait. When a user clicks the table record on the list page, they would be linked to the kanban board with the record passed in the route.Also, since the campaigns and accounts are a many-to-many relationship, the status column cannot exist on the records (in this case the accounts table) and must instead be on the pivot table.
I tried my best to work around the package as it currently stands.
One suggestion you had made in #10 is to use a query string. The problem here is that Livewire can only get the request on mount, and not subsequent requests. Therefore the query string is null on subsequent requests.
This is my code:
Page
Models
Migrations
The text was updated successfully, but these errors were encountered: