diff --git a/Modules/Helpdesk/Config/config.php b/Modules/Helpdesk/Config/config.php index a629042b..fec8866d 100644 --- a/Modules/Helpdesk/Config/config.php +++ b/Modules/Helpdesk/Config/config.php @@ -7,7 +7,7 @@ return [ 'middleware' => ['web', 'auth'], 'disk' => env('HELPDESK_ATTACHMENTS_DISK', 'helpdesk'), 'max_upload_kb' => (int) env('HELPDESK_MAX_UPLOAD_KB', 10240), - 'allowed_mimes' => ['pdf', 'png', 'jpg', 'jpeg', 'webp', 'doc', 'docx', 'xls', 'xlsx', 'txt', 'csv', 'zip'], + 'allowed_mimes' => ['md','pdf', 'png', 'jpg', 'jpeg', 'webp', 'doc', 'docx', 'xls', 'xlsx', 'txt', 'csv', 'zip'], 'default_status_slug' => 'open', 'closed_status_slug' => 'closed', ]; diff --git a/Modules/Helpdesk/Database/Migrations/2026_04_24_000002_create_helpdesk_lookup_tables.php b/Modules/Helpdesk/Database/Migrations/2026_06_12_000010_create_helpdesk_lookup_tables.php similarity index 100% rename from Modules/Helpdesk/Database/Migrations/2026_04_24_000002_create_helpdesk_lookup_tables.php rename to Modules/Helpdesk/Database/Migrations/2026_06_12_000010_create_helpdesk_lookup_tables.php diff --git a/Modules/Helpdesk/Database/Migrations/2026_04_24_000003_create_helpdesk_tickets_table.php b/Modules/Helpdesk/Database/Migrations/2026_06_12_000020_create_helpdesk_tickets_table.php similarity index 100% rename from Modules/Helpdesk/Database/Migrations/2026_04_24_000003_create_helpdesk_tickets_table.php rename to Modules/Helpdesk/Database/Migrations/2026_06_12_000020_create_helpdesk_tickets_table.php diff --git a/Modules/Helpdesk/Database/Migrations/2026_04_24_000006_create_helpdesk_git_and_workflow_tables.php b/Modules/Helpdesk/Database/Migrations/2026_06_12_000030_create_helpdesk_git_and_workflow_tables.php similarity index 100% rename from Modules/Helpdesk/Database/Migrations/2026_04_24_000006_create_helpdesk_git_and_workflow_tables.php rename to Modules/Helpdesk/Database/Migrations/2026_06_12_000030_create_helpdesk_git_and_workflow_tables.php diff --git a/Modules/Helpdesk/Database/Migrations/2026_04_24_000004_create_helpdesk_comments_and_attachments_tables.php b/Modules/Helpdesk/Database/Migrations/2026_06_12_000040_create_helpdesk_comments_and_attachments_tables.php similarity index 100% rename from Modules/Helpdesk/Database/Migrations/2026_04_24_000004_create_helpdesk_comments_and_attachments_tables.php rename to Modules/Helpdesk/Database/Migrations/2026_06_12_000040_create_helpdesk_comments_and_attachments_tables.php diff --git a/Modules/Helpdesk/Database/Migrations/2026_04_24_000005_create_helpdesk_category_user_table.php b/Modules/Helpdesk/Database/Migrations/2026_06_12_000050_create_helpdesk_category_user_table.php similarity index 100% rename from Modules/Helpdesk/Database/Migrations/2026_04_24_000005_create_helpdesk_category_user_table.php rename to Modules/Helpdesk/Database/Migrations/2026_06_12_000050_create_helpdesk_category_user_table.php diff --git a/Modules/Helpdesk/Database/Seeders/HelpdeskDatabaseSeeder.php b/Modules/Helpdesk/Database/Seeders/HelpdeskDatabaseSeeder.php index ab50d524..a102f108 100644 --- a/Modules/Helpdesk/Database/Seeders/HelpdeskDatabaseSeeder.php +++ b/Modules/Helpdesk/Database/Seeders/HelpdeskDatabaseSeeder.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Modules\Helpdesk\database\seeders; +namespace Modules\Helpdesk\Database\Seeders; use Illuminate\Database\Seeder; use Illuminate\Support\Str; @@ -15,44 +15,113 @@ use Modules\Helpdesk\Models\WorkflowTemplate; final class HelpdeskDatabaseSeeder extends Seeder { - /** @return void */ + /** + * Seed the Helpdesk module lookup data and default workflow templates. + * + * @return void + */ public function run(): void + { + $this->seedStatuses(); + $this->seedPriorities(); + $this->seedCategories(); + $this->seedTeamsAndProjects(); + $this->seedWorkflowTemplates(); + } + + /** + * Seed ticket workflow statuses. + * + * @return void + */ + private function seedStatuses(): void { foreach ([ + ['name' => 'New', 'slug' => 'new', 'color' => 'sky', 'sort_order' => 5, 'is_closed' => false], ['name' => 'Open', 'slug' => 'open', 'color' => 'blue', 'sort_order' => 10, 'is_closed' => false], ['name' => 'In Progress', 'slug' => 'in-progress', 'color' => 'amber', 'sort_order' => 20, 'is_closed' => false], - ['name' => 'Waiting Customer', 'slug' => 'waiting-customer', 'color' => 'purple', 'sort_order' => 30, 'is_closed' => false], - ['name' => 'Closed', 'slug' => 'closed', 'color' => 'green', 'sort_order' => 90, 'is_closed' => true], + ['name' => 'Stalled', 'slug' => 'stalled', 'color' => 'rose', 'sort_order' => 30, 'is_closed' => false], + ['name' => 'On-Hold', 'slug' => 'on-hold', 'color' => 'violet', 'sort_order' => 40, 'is_closed' => false], + ['name' => 'Closed', 'slug' => 'closed', 'color' => 'emerald', 'sort_order' => 90, 'is_closed' => true], ] as $row) { Status::query()->updateOrCreate(['slug' => $row['slug']], $row); } + } + /** + * Seed ticket priorities. + * + * @return void + */ + private function seedPriorities(): void + { foreach ([ - ['name' => 'Low', 'slug' => 'low', 'color' => 'zinc', 'sort_order' => 10], - ['name' => 'Normal', 'slug' => 'normal', 'color' => 'blue', 'sort_order' => 20], - ['name' => 'High', 'slug' => 'high', 'color' => 'orange', 'sort_order' => 30], - ['name' => 'Critical', 'slug' => 'critical', 'color' => 'red', 'sort_order' => 40], + ['name' => 'High', 'slug' => 'high', 'color' => 'red', 'sort_order' => 10], + ['name' => 'Medium', 'slug' => 'medium', 'color' => 'amber', 'sort_order' => 20], + ['name' => 'Low', 'slug' => 'low', 'color' => 'emerald', 'sort_order' => 30], ] as $row) { Priority::query()->updateOrCreate(['slug' => $row['slug']], $row); } + } - foreach (['General Support', 'Software', 'Hardware', 'Access Request', 'Incident'] as $name) { - Category::query()->updateOrCreate(['slug' => Str::slug($name)], ['name' => $name, 'color' => 'blue']); + /** + * Seed ticket categories. + * + * @return void + */ + private function seedCategories(): void + { + foreach ([ + ['name' => 'Development', 'color' => 'indigo', 'description' => 'Software changes, enhancements and development work.'], + ['name' => 'Systems Deployment', 'color' => 'cyan', 'description' => 'Deployment, release, infrastructure and environment requests.'], + ['name' => 'Concepts', 'color' => 'purple', 'description' => 'Ideas, concepts, design discussion and future improvements.'], + ['name' => 'Bug', 'color' => 'rose', 'description' => 'Defects, regressions and incorrect behaviour.'], + ] as $row) { + Category::query()->updateOrCreate( + ['company_id' => null, 'slug' => Str::slug($row['name'])], + $row + ['company_id' => null, 'slug' => Str::slug($row['name'])] + ); } + } - $team = Team::query()->updateOrCreate(['slug' => 'support'], [ - 'name' => 'Support', - 'color' => 'indigo', - 'description' => 'Default support team for helpdesk tickets.', - ]); + /** + * Seed the default support team and a default project. + * + * @return void + */ + private function seedTeamsAndProjects(): void + { + $team = Team::query()->updateOrCreate( + ['company_id' => null, 'slug' => 'support'], + [ + 'company_id' => null, + 'name' => 'Support', + 'slug' => 'support', + 'color' => 'blue', + 'description' => 'Default support team for triage, ownership and ticket routing.', + ] + ); - Project::query()->updateOrCreate(['slug' => 'internal-helpdesk'], [ - 'team_id' => $team->id, - 'title' => 'Internal Helpdesk', - 'color' => 'blue', - 'description' => 'Default project for internal helpdesk tickets.', - ]); + Project::query()->updateOrCreate( + ['company_id' => null, 'slug' => 'support-desk'], + [ + 'company_id' => null, + 'team_id' => $team->id, + 'title' => 'Support Desk', + 'slug' => 'support-desk', + 'color' => 'indigo', + 'description' => 'Default project for operational helpdesk tickets.', + ] + ); + } + /** + * Seed default professional workflow email templates. + * + * @return void + */ + private function seedWorkflowTemplates(): void + { foreach ([ ['name' => 'Ticket raised requester notice', 'event' => 'ticket.created', 'subject' => 'Ticket {{ ticket.reference }} has been raised', 'html_body' => '
Hello {{ requester.name }},
Your ticket {{ ticket.reference }} has been raised successfully.
Subject: {{ ticket.subject }}
Priority: {{ ticket.priority }}
', 'to_role' => 'requester'], ['name' => 'Ticket updated requester notice', 'event' => 'ticket.updated', 'subject' => 'Ticket {{ ticket.reference }} has been updated', 'html_body' => 'Hello {{ requester.name }},
Your ticket {{ ticket.reference }} has been updated.
Status: {{ ticket.status }}
Priority: {{ ticket.priority }}
', 'to_role' => 'requester'], @@ -64,6 +133,5 @@ final class HelpdeskDatabaseSeeder extends Seeder $template + ['text_body' => null, 'cc' => null, 'bcc' => null, 'is_active' => true] ); } - } } diff --git a/Modules/Helpdesk/HelpdeskDatabaseSeeder.php b/Modules/Helpdesk/HelpdeskDatabaseSeeder.php new file mode 100644 index 00000000..a102f108 --- /dev/null +++ b/Modules/Helpdesk/HelpdeskDatabaseSeeder.php @@ -0,0 +1,137 @@ +seedStatuses(); + $this->seedPriorities(); + $this->seedCategories(); + $this->seedTeamsAndProjects(); + $this->seedWorkflowTemplates(); + } + + /** + * Seed ticket workflow statuses. + * + * @return void + */ + private function seedStatuses(): void + { + foreach ([ + ['name' => 'New', 'slug' => 'new', 'color' => 'sky', 'sort_order' => 5, 'is_closed' => false], + ['name' => 'Open', 'slug' => 'open', 'color' => 'blue', 'sort_order' => 10, 'is_closed' => false], + ['name' => 'In Progress', 'slug' => 'in-progress', 'color' => 'amber', 'sort_order' => 20, 'is_closed' => false], + ['name' => 'Stalled', 'slug' => 'stalled', 'color' => 'rose', 'sort_order' => 30, 'is_closed' => false], + ['name' => 'On-Hold', 'slug' => 'on-hold', 'color' => 'violet', 'sort_order' => 40, 'is_closed' => false], + ['name' => 'Closed', 'slug' => 'closed', 'color' => 'emerald', 'sort_order' => 90, 'is_closed' => true], + ] as $row) { + Status::query()->updateOrCreate(['slug' => $row['slug']], $row); + } + } + + /** + * Seed ticket priorities. + * + * @return void + */ + private function seedPriorities(): void + { + foreach ([ + ['name' => 'High', 'slug' => 'high', 'color' => 'red', 'sort_order' => 10], + ['name' => 'Medium', 'slug' => 'medium', 'color' => 'amber', 'sort_order' => 20], + ['name' => 'Low', 'slug' => 'low', 'color' => 'emerald', 'sort_order' => 30], + ] as $row) { + Priority::query()->updateOrCreate(['slug' => $row['slug']], $row); + } + } + + /** + * Seed ticket categories. + * + * @return void + */ + private function seedCategories(): void + { + foreach ([ + ['name' => 'Development', 'color' => 'indigo', 'description' => 'Software changes, enhancements and development work.'], + ['name' => 'Systems Deployment', 'color' => 'cyan', 'description' => 'Deployment, release, infrastructure and environment requests.'], + ['name' => 'Concepts', 'color' => 'purple', 'description' => 'Ideas, concepts, design discussion and future improvements.'], + ['name' => 'Bug', 'color' => 'rose', 'description' => 'Defects, regressions and incorrect behaviour.'], + ] as $row) { + Category::query()->updateOrCreate( + ['company_id' => null, 'slug' => Str::slug($row['name'])], + $row + ['company_id' => null, 'slug' => Str::slug($row['name'])] + ); + } + } + + /** + * Seed the default support team and a default project. + * + * @return void + */ + private function seedTeamsAndProjects(): void + { + $team = Team::query()->updateOrCreate( + ['company_id' => null, 'slug' => 'support'], + [ + 'company_id' => null, + 'name' => 'Support', + 'slug' => 'support', + 'color' => 'blue', + 'description' => 'Default support team for triage, ownership and ticket routing.', + ] + ); + + Project::query()->updateOrCreate( + ['company_id' => null, 'slug' => 'support-desk'], + [ + 'company_id' => null, + 'team_id' => $team->id, + 'title' => 'Support Desk', + 'slug' => 'support-desk', + 'color' => 'indigo', + 'description' => 'Default project for operational helpdesk tickets.', + ] + ); + } + + /** + * Seed default professional workflow email templates. + * + * @return void + */ + private function seedWorkflowTemplates(): void + { + foreach ([ + ['name' => 'Ticket raised requester notice', 'event' => 'ticket.created', 'subject' => 'Ticket {{ ticket.reference }} has been raised', 'html_body' => 'Hello {{ requester.name }},
Your ticket {{ ticket.reference }} has been raised successfully.
Subject: {{ ticket.subject }}
Priority: {{ ticket.priority }}
', 'to_role' => 'requester'], + ['name' => 'Ticket updated requester notice', 'event' => 'ticket.updated', 'subject' => 'Ticket {{ ticket.reference }} has been updated', 'html_body' => 'Hello {{ requester.name }},
Your ticket {{ ticket.reference }} has been updated.
Status: {{ ticket.status }}
Priority: {{ ticket.priority }}
', 'to_role' => 'requester'], + ['name' => 'Ticket response requester notice', 'event' => 'ticket.commented', 'subject' => 'New response on ticket {{ ticket.reference }}', 'html_body' => 'Hello {{ requester.name }},
A new response has been added to {{ ticket.reference }}.
Subject: {{ ticket.subject }}
', 'to_role' => 'requester'], + ['name' => 'Ticket closed requester notice', 'event' => 'ticket.closed', 'subject' => 'Ticket {{ ticket.reference }} has been closed', 'html_body' => 'Hello {{ requester.name }},
Your ticket {{ ticket.reference }} has been closed.
Thank you for using the support desk.
', 'to_role' => 'requester'], + ] as $template) { + WorkflowTemplate::query()->updateOrCreate( + ['name' => $template['name'], 'event' => $template['event']], + $template + ['text_body' => null, 'cc' => null, 'bcc' => null, 'is_active' => true] + ); + } + } +} diff --git a/Modules/Helpdesk/Livewire/TicketCreate.php b/Modules/Helpdesk/Livewire/TicketCreate.php index 7f0bcb94..e610c462 100644 --- a/Modules/Helpdesk/Livewire/TicketCreate.php +++ b/Modules/Helpdesk/Livewire/TicketCreate.php @@ -6,6 +6,8 @@ namespace Modules\Helpdesk\Livewire; use Illuminate\Contracts\View\View; use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Schema; use Livewire\Attributes\Validate; use Livewire\Component; use Livewire\Features\SupportFileUploads\TemporaryUploadedFile; @@ -14,8 +16,6 @@ use Modules\Helpdesk\Models\Category; use Modules\Helpdesk\Models\Priority; use Modules\Helpdesk\Models\Project; use Modules\Helpdesk\Models\Team; -use Illuminate\Support\Facades\DB; -use Illuminate\Support\Facades\Schema; use Modules\Helpdesk\Services\TicketService; final class TicketCreate extends Component @@ -52,16 +52,13 @@ final class TicketCreate extends Component /** * Store a new helpdesk ticket. - * - * @param TicketService $tickets - * @return mixed */ public function save(TicketService $tickets): mixed { $this->validate(); $this->validate([ - 'attachments.*' => 'file|max:' . config('helpdesk.max_upload_kb') . '|mimes:' . implode(',', config('helpdesk.allowed_mimes')), + 'attachments.*' => 'file|max:'.config('helpdesk.max_upload_kb').'|mimes:'.implode(',', config('helpdesk.allowed_mimes')), ]); $ticket = $tickets->create(Auth::user(), [ @@ -75,12 +72,11 @@ final class TicketCreate extends Component 'due_at' => $this->due_at, ], $this->attachments); - session()->flash('success', 'Ticket ' . $ticket->reference . ' has been created.'); + session()->flash('success', 'Ticket '.$ticket->reference.' has been created.'); return redirect()->route('helpdesk.tickets.index'); } - /** @return View */ public function render(): View { return view('helpdesk::livewire.ticket-create', [ diff --git a/Modules/Helpdesk/Resources/views/components/html-editor.blade.php b/Modules/Helpdesk/Resources/views/components/html-editor.blade.php index ea9af57b..ec6df4b7 100644 --- a/Modules/Helpdesk/Resources/views/components/html-editor.blade.php +++ b/Modules/Helpdesk/Resources/views/components/html-editor.blade.php @@ -33,6 +33,10 @@ > + @if($model) + + @endif +