Core UI updates for helpdesk

This commit is contained in:
Mark Gregory
2026-06-16 09:35:24 +01:00
parent dc86970b20
commit 6c5e2af806
7 changed files with 366 additions and 36 deletions
+82 -10
View File
@@ -87,6 +87,8 @@ final class KanbanBoard extends Component
'last_activity_at' => now(),
])->save();
$this->board_id = $board->id;
$fresh = $ticket->fresh(['owner', 'agent', 'status', 'priority', 'category', 'project', 'team', 'board']) ?? $ticket;
$workflow->dispatch($fresh, 'ticket.updated', Auth::user());
@@ -95,6 +97,17 @@ final class KanbanBoard extends Component
$this->dispatch('wms:toast', type: 'success', title: 'Board changed', message: $message);
}
/**
* Normalise the board selector value from Livewire/browser select events.
*
* @param int|string|null $value
* @return void
*/
public function updatedBoardId(int|string|null $value): void
{
$this->board_id = is_numeric($value) ? (int) $value : null;
}
/**
* Render the Kanban board.
*/
@@ -106,34 +119,43 @@ final class KanbanBoard extends Component
->orderBy('name')
->get();
$board = $boards->firstWhere('id', $this->board_id) ?? $boards->first();
$statuses = $board?->statuses ?? collect();
$board = $this->resolveSelectedBoard($boards);
$this->board_id = $board?->id;
if ($statuses->isEmpty()) {
$statuses = Status::query()->orderBy('sort_order')->orderBy('name')->get();
if ($board instanceof KanbanBoardModel && $board->statuses->isEmpty()) {
$this->ensureBoardHasStatuses($board);
$board->load(['statuses', 'owner:id,name,email']);
$boards = KanbanBoardModel::query()
->with(['statuses', 'owner:id,name,email'])
->orderBy('sort_order')
->orderBy('name')
->get();
}
return view('helpdesk::livewire.kanban-board', [
'boards' => $boards,
'board' => $board,
'statuses' => $statuses,
'ticketsByStatus' => $this->ticketsByStatus(),
'statuses' => $board?->statuses ?? collect(),
'ticketsByStatus' => $this->ticketsByStatus($board),
])->layout('layouts.app');
}
/**
* Get visible tickets grouped by status for the active board only.
* Get visible tickets grouped by status for the selected board only.
*
* @return array<int, Collection<int, Ticket>>
*/
private function ticketsByStatus(): array
private function ticketsByStatus(?KanbanBoardModel $board): array
{
$board = $this->activeBoard();
if ($board === null) {
return [];
}
return Ticket::query()
->with(['owner', 'agent', 'status', 'priority', 'category', 'project', 'team', 'product', 'tags', 'checklistItems', 'board'])
->visibleTo(Auth::user())
->when($board !== null, fn ($query) => $query->where('board_id', $board->id))
->where('board_id', $board->id)
->latest('last_activity_at')
->limit(300)
->get()
@@ -156,6 +178,30 @@ final class KanbanBoard extends Component
->first() ?: KanbanBoardModel::query()->orderBy('sort_order')->first();
}
/**
* Resolve the selected board from an already-loaded board collection.
*
* @param Collection<int, KanbanBoardModel> $boards
*/
private function resolveSelectedBoard(Collection $boards): ?KanbanBoardModel
{
if ($boards->isEmpty()) {
return null;
}
if ($this->board_id !== null) {
$selected = $boards->firstWhere('id', (int) $this->board_id);
if ($selected instanceof KanbanBoardModel) {
return $selected;
}
}
$default = $boards->firstWhere('is_default', true);
return $default instanceof KanbanBoardModel ? $default : $boards->first();
}
/**
* Attach a missing status to a board when a move requires it.
*/
@@ -166,4 +212,30 @@ final class KanbanBoard extends Component
['sort_order' => 999, 'updated_at' => now(), 'created_at' => now()]
);
}
/**
* Ensure a board has workflow columns. This keeps newly-created boards usable immediately.
*/
private function ensureBoardHasStatuses(KanbanBoardModel $board): void
{
if ($board->statuses()->exists()) {
return;
}
$statuses = Status::query()
->orderBy('sort_order')
->orderBy('name')
->get(['id']);
foreach ($statuses as $index => $status) {
DB::table('helpdesk_kanban_board_statuses')->updateOrInsert(
['board_id' => $board->id, 'status_id' => $status->id],
[
'sort_order' => ($index + 1) * 10,
'created_at' => now(),
'updated_at' => now(),
]
);
}
}
}