feat: ticket views, statuses, participants, merge; mobile layout fixes (#5)

- New migrations: ticket views, statuses, participants, merge support
- New models: TicketView, TicketStatus, TicketParticipant
- New seeder: EmailTemplatesSeeder
- Console commands for ticketing
- Mobile: sidebar min-w-0/overflow-hidden, tab nav overflow-x-auto

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Joel Wedemire
2026-04-19 22:22:45 -07:00
parent ffb64078d8
commit dd0a458250
17 changed files with 1399 additions and 260 deletions

View File

@@ -3,19 +3,13 @@
namespace Dashboard\Ticketing\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
class PriorityLevel extends Model
{
protected $table = 'ticketing_priority_levels';
protected $fillable = ['group_id', 'name', 'color', 'description', 'sort_order'];
public function group(): BelongsTo
{
return $this->belongsTo(TicketingGroup::class, 'group_id');
}
protected $fillable = ['name', 'color', 'description', 'sort_order'];
public function tickets(): HasMany
{

View File

@@ -10,7 +10,7 @@ class Ticket extends Model
{
protected $fillable = [
'number', 'group_id', 'submitter_id', 'assigned_to', 'project_id',
'title', 'description', 'status', 'priority_id', 'due_date',
'title', 'description', 'status', 'priority_id', 'due_date', 'merged_into_id',
];
protected $casts = [
@@ -41,4 +41,19 @@ class Ticket extends Model
{
return $this->hasMany(TicketAttachment::class, 'ticket_id');
}
public function views(): HasMany
{
return $this->hasMany(TicketView::class, 'ticket_id')->orderBy('viewed_at');
}
public function participants(): HasMany
{
return $this->hasMany(TicketParticipant::class, 'ticket_id');
}
public function mergedInto(): BelongsTo
{
return $this->belongsTo(Ticket::class, 'merged_into_id');
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace Dashboard\Ticketing\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class TicketParticipant extends Model
{
public $timestamps = false;
const CREATED_AT = 'created_at';
protected $fillable = ['ticket_id', 'user_id', 'added_by'];
public function ticket(): BelongsTo
{
return $this->belongsTo(Ticket::class, 'ticket_id');
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace Dashboard\Ticketing\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
class TicketStatus extends Model
{
protected $table = 'ticketing_statuses';
protected $fillable = ['slug', 'name', 'color', 'sort_order', 'is_closed', 'is_system'];
protected $casts = [
'is_closed' => 'boolean',
'is_system' => 'boolean',
];
public function tickets(): HasMany
{
return $this->hasMany(Ticket::class, 'status', 'slug');
}
}

20
src/Models/TicketView.php Normal file
View File

@@ -0,0 +1,20 @@
<?php
namespace Dashboard\Ticketing\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class TicketView extends Model
{
public $timestamps = false;
protected $table = 'ticket_views';
protected $fillable = ['ticket_id', 'user_id', 'viewed_at'];
protected $casts = ['viewed_at' => 'datetime'];
public function ticket(): BelongsTo
{
return $this->belongsTo(Ticket::class);
}
}