feat: full dashboard-ticketing scaffold with data model, controllers, Vue pages

This commit is contained in:
Joel Wedemire
2026-04-08 17:10:30 -07:00
parent 81d0d54f50
commit 391699220f
33 changed files with 1947 additions and 719 deletions

View File

@@ -0,0 +1,24 @@
<?php
namespace Dashboard\Ticketing\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class EmailConnection extends Model
{
protected $table = 'ticketing_email_connections';
protected $fillable = ['group_id', 'type', 'config', 'last_polled_at', 'active'];
protected $casts = [
'config' => 'array',
'active' => 'boolean',
'last_polled_at' => 'datetime',
];
public function group(): BelongsTo
{
return $this->belongsTo(TicketingGroup::class, 'group_id');
}
}

View File

@@ -0,0 +1,24 @@
<?php
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');
}
public function tickets(): HasMany
{
return $this->hasMany(Ticket::class, 'priority_id');
}
}

View File

@@ -9,27 +9,36 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
class Ticket extends Model
{
protected $fillable = [
'user_id',
'assigned_to',
'title',
'description',
'category',
'priority',
'status',
'number', 'group_id', 'submitter_id', 'assigned_to', 'project_id',
'title', 'description', 'status', 'priority_id', 'due_date',
];
public function submitter(): BelongsTo
protected $casts = [
'due_date' => 'date',
];
public function group(): BelongsTo
{
return $this->belongsTo(\App\Models\User::class, 'user_id');
return $this->belongsTo(TicketingGroup::class, 'group_id');
}
public function assignee(): BelongsTo
public function priority(): BelongsTo
{
return $this->belongsTo(\App\Models\User::class, 'assigned_to');
return $this->belongsTo(PriorityLevel::class, 'priority_id');
}
public function comments(): HasMany
public function project(): BelongsTo
{
return $this->hasMany(TicketComment::class);
return $this->belongsTo(TicketingProject::class, 'project_id');
}
public function messages(): HasMany
{
return $this->hasMany(TicketMessage::class, 'ticket_id')->orderBy('created_at');
}
public function attachments(): HasMany
{
return $this->hasMany(TicketAttachment::class, 'ticket_id');
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace Dashboard\Ticketing\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class TicketAttachment extends Model
{
protected $fillable = ['ticket_id', 'message_id', 'filename', 'path', 'mime_type', 'size'];
public function ticket(): BelongsTo
{
return $this->belongsTo(Ticket::class, 'ticket_id');
}
public function message(): BelongsTo
{
return $this->belongsTo(TicketMessage::class, 'message_id');
}
}

View File

@@ -1,30 +0,0 @@
<?php
namespace Dashboard\Ticketing\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class TicketComment extends Model
{
protected $fillable = [
'ticket_id',
'user_id',
'body',
'is_internal',
];
protected $casts = [
'is_internal' => 'boolean',
];
public function ticket(): BelongsTo
{
return $this->belongsTo(Ticket::class);
}
public function author(): BelongsTo
{
return $this->belongsTo(\App\Models\User::class, 'user_id');
}
}

View File

@@ -0,0 +1,29 @@
<?php
namespace Dashboard\Ticketing\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
class TicketMessage extends Model
{
protected $fillable = [
'ticket_id', 'user_id', 'author_email', 'body',
'is_internal', 'source', 'email_message_id',
];
protected $casts = [
'is_internal' => 'boolean',
];
public function ticket(): BelongsTo
{
return $this->belongsTo(Ticket::class, 'ticket_id');
}
public function attachments(): HasMany
{
return $this->hasMany(TicketAttachment::class, 'message_id');
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace Dashboard\Ticketing\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class TicketingAgentAccess extends Model
{
protected $table = 'ticketing_agent_access';
protected $fillable = ['user_id', 'group_id', 'role'];
public function group(): BelongsTo
{
return $this->belongsTo(TicketingGroup::class, 'group_id');
}
}

View File

@@ -0,0 +1,42 @@
<?php
namespace Dashboard\Ticketing\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
class TicketingGroup extends Model
{
protected $fillable = ['name', 'email_address', 'color', 'prefix'];
public function tickets(): HasMany
{
return $this->hasMany(Ticket::class, 'group_id');
}
public function priorityLevels(): HasMany
{
return $this->hasMany(PriorityLevel::class, 'group_id');
}
public function agentAccess(): HasMany
{
return $this->hasMany(TicketingAgentAccess::class, 'group_id');
}
public function projects(): HasMany
{
return $this->hasMany(TicketingProject::class, 'group_id');
}
public function emailConnections(): HasMany
{
return $this->hasMany(EmailConnection::class, 'group_id');
}
public function nextTicketNumber(): string
{
$count = $this->tickets()->count() + 1;
return $this->prefix . '-' . str_pad($count, 4, '0', STR_PAD_LEFT);
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace Dashboard\Ticketing\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
class TicketingProject extends Model
{
protected $fillable = ['group_id', 'name', 'description', 'status', 'created_by'];
public function group(): BelongsTo
{
return $this->belongsTo(TicketingGroup::class, 'group_id');
}
public function tickets(): HasMany
{
return $this->hasMany(Ticket::class, 'project_id');
}
}