Core UI updates for helpdesk
This commit is contained in:
@@ -6,6 +6,7 @@ namespace Modules\Helpdesk\Livewire;
|
||||
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Livewire\Component;
|
||||
use Modules\Helpdesk\Models\KanbanBoard as KanbanBoardModel;
|
||||
@@ -26,16 +27,23 @@ final class KanbanBoard extends Component
|
||||
}
|
||||
|
||||
/**
|
||||
* Move a ticket to another workflow status.
|
||||
* Move a ticket to another workflow status on the active board.
|
||||
*/
|
||||
public function moveTicket(int|string $ticketId, int|string $statusId, WorkflowNotificationService $workflow): void
|
||||
{
|
||||
$ticket = Ticket::query()->visibleTo(Auth::user())->findOrFail((int) $ticketId);
|
||||
$status = Status::query()->findOrFail((int) $statusId);
|
||||
$board = $this->activeBoard();
|
||||
$oldStatusName = $ticket->status?->name ?? 'previous status';
|
||||
|
||||
$this->authorize('update', $ticket);
|
||||
|
||||
if ($board !== null && ! $board->statuses()->whereKey($status->id)->exists()) {
|
||||
$this->addStatusToBoard($board->id, $status->id);
|
||||
}
|
||||
|
||||
$ticket->forceFill([
|
||||
'board_id' => $board?->id,
|
||||
'status_id' => $status->id,
|
||||
'completed_at' => $status->is_closed ? now() : null,
|
||||
'last_activity_at' => now(),
|
||||
@@ -47,7 +55,44 @@ final class KanbanBoard extends Component
|
||||
Auth::user()
|
||||
);
|
||||
|
||||
session()->flash('success', 'Ticket moved to ' . $status->name . '.');
|
||||
$message = 'Ticket '.$ticket->reference.' moved from '.$oldStatusName.' to '.$status->name.'.';
|
||||
session()->flash('success', $message);
|
||||
$this->dispatch('wms:toast', type: 'success', title: 'Ticket moved', message: $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move a ticket from its current board to another board. A ticket can only belong to one board.
|
||||
*/
|
||||
public function moveTicketToBoard(int|string $ticketId, int|string|null $boardId, WorkflowNotificationService $workflow): void
|
||||
{
|
||||
$ticket = Ticket::query()->with('board')->visibleTo(Auth::user())->findOrFail((int) $ticketId);
|
||||
$board = KanbanBoardModel::query()->with(['statuses', 'owner:id,name,email'])->findOrFail((int) $boardId);
|
||||
$oldBoardName = $ticket->board?->name ?? 'No board';
|
||||
|
||||
$this->authorize('update', $ticket);
|
||||
|
||||
if (! $board->statuses->contains('id', $ticket->status_id)) {
|
||||
$firstStatus = $board->statuses->first();
|
||||
|
||||
if ($firstStatus !== null) {
|
||||
$ticket->status_id = $firstStatus->id;
|
||||
$ticket->completed_at = $firstStatus->is_closed ? now() : null;
|
||||
} else {
|
||||
$this->addStatusToBoard($board->id, (int) $ticket->status_id);
|
||||
}
|
||||
}
|
||||
|
||||
$ticket->forceFill([
|
||||
'board_id' => $board->id,
|
||||
'last_activity_at' => now(),
|
||||
])->save();
|
||||
|
||||
$fresh = $ticket->fresh(['owner', 'agent', 'status', 'priority', 'category', 'project', 'team', 'board']) ?? $ticket;
|
||||
$workflow->dispatch($fresh, 'ticket.updated', Auth::user());
|
||||
|
||||
$message = 'Ticket '.$fresh->reference.' moved from '.$oldBoardName.' to '.$board->name.'.';
|
||||
session()->flash('success', $message);
|
||||
$this->dispatch('wms:toast', type: 'success', title: 'Board changed', message: $message);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,7 +101,7 @@ final class KanbanBoard extends Component
|
||||
public function render(): View
|
||||
{
|
||||
$boards = KanbanBoardModel::query()
|
||||
->with('statuses')
|
||||
->with(['statuses', 'owner:id,name,email'])
|
||||
->orderBy('sort_order')
|
||||
->orderBy('name')
|
||||
->get();
|
||||
@@ -77,19 +122,48 @@ final class KanbanBoard extends Component
|
||||
}
|
||||
|
||||
/**
|
||||
* Get visible tickets grouped by status.
|
||||
* Get visible tickets grouped by status for the active board only.
|
||||
*
|
||||
* @return array<int, Collection<int, Ticket>>
|
||||
*/
|
||||
private function ticketsByStatus(): array
|
||||
{
|
||||
$board = $this->activeBoard();
|
||||
|
||||
return Ticket::query()
|
||||
->with(['owner', 'agent', 'status', 'priority', 'category', 'project', 'team', 'product', 'tags', 'checklistItems'])
|
||||
->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))
|
||||
->latest('last_activity_at')
|
||||
->limit(300)
|
||||
->get()
|
||||
->groupBy('status_id')
|
||||
->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the current board from the selected board ID.
|
||||
*/
|
||||
private function activeBoard(): ?KanbanBoardModel
|
||||
{
|
||||
if ($this->board_id !== null) {
|
||||
return KanbanBoardModel::query()->find((int) $this->board_id);
|
||||
}
|
||||
|
||||
return KanbanBoardModel::query()
|
||||
->where('is_default', true)
|
||||
->orderBy('sort_order')
|
||||
->first() ?: KanbanBoardModel::query()->orderBy('sort_order')->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach a missing status to a board when a move requires it.
|
||||
*/
|
||||
private function addStatusToBoard(int $boardId, int $statusId): void
|
||||
{
|
||||
DB::table('helpdesk_kanban_board_statuses')->updateOrInsert(
|
||||
['board_id' => $boardId, 'status_id' => $statusId],
|
||||
['sort_order' => 999, 'updated_at' => now(), 'created_at' => now()]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user