340 lines
14 KiB
PHP
340 lines
14 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Modules\Helpdesk\Livewire;
|
|
|
|
use Illuminate\Contracts\View\View;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Schema;
|
|
use Illuminate\Support\Str;
|
|
use Livewire\Component;
|
|
use Modules\Helpdesk\Models\Category;
|
|
use Modules\Helpdesk\Models\GitRepository;
|
|
use Modules\Helpdesk\Models\Priority;
|
|
use Modules\Helpdesk\Models\Project;
|
|
use Modules\Helpdesk\Models\Status;
|
|
use Modules\Helpdesk\Models\Team;
|
|
use Modules\Helpdesk\Models\WorkflowTemplate;
|
|
|
|
final class SettingsManager extends Component
|
|
{
|
|
public string $section = 'statuses';
|
|
|
|
/** @var array<string, mixed> */
|
|
public array $statusForm = ['id' => null, 'name' => '', 'slug' => '', 'color' => 'zinc', 'sort_order' => 0, 'is_closed' => false];
|
|
|
|
/** @var array<string, mixed> */
|
|
public array $priorityForm = ['id' => null, 'name' => '', 'slug' => '', 'color' => 'zinc', 'sort_order' => 0];
|
|
|
|
/** @var array<string, mixed> */
|
|
public array $categoryForm = ['id' => null, 'company_id' => null, 'name' => '', 'slug' => '', 'color' => 'blue', 'description' => ''];
|
|
|
|
/** @var array<string, mixed> */
|
|
public array $teamForm = ['id' => null, 'company_id' => null, 'name' => '', 'slug' => '', 'color' => 'indigo', 'description' => '', 'archived_at' => null];
|
|
|
|
/** @var array<string, mixed> */
|
|
public array $projectForm = ['id' => null, 'company_id' => null, 'team_id' => null, 'title' => '', 'slug' => '', 'color' => 'blue', 'description' => '', 'archived_at' => null];
|
|
|
|
/** @var array<string, mixed> */
|
|
public array $repositoryForm = ['id' => null, 'company_id' => null, 'project_id' => null, 'name' => '', 'provider' => 'git', 'remote_url' => '', 'default_branch' => 'main', 'webhook_secret' => ''];
|
|
|
|
/** @var array<string, mixed> */
|
|
public array $workflowForm = ['id' => null, 'name' => '', 'event' => 'ticket.created', 'subject' => '', 'html_body' => '', 'text_body' => '', 'to_role' => 'requester', 'cc' => '', 'bcc' => '', 'is_active' => true];
|
|
|
|
/** @return void */
|
|
public function saveStatus(): void
|
|
{
|
|
$data = $this->validate([
|
|
'statusForm.name' => ['required', 'string', 'max:80'],
|
|
'statusForm.slug' => ['nullable', 'string', 'max:100'],
|
|
'statusForm.color' => ['required', 'string', 'max:30'],
|
|
'statusForm.sort_order' => ['required', 'integer', 'min:0'],
|
|
'statusForm.is_closed' => ['boolean'],
|
|
])['statusForm'];
|
|
|
|
$data['slug'] = $this->slug($data['slug'] ?: $data['name']);
|
|
Status::query()->updateOrCreate(['id' => $this->statusForm['id']], $data);
|
|
$this->resetStatusForm();
|
|
session()->flash('success', 'Status saved.');
|
|
}
|
|
|
|
/** @return void */
|
|
public function editStatus(int $id): void
|
|
{
|
|
$this->statusForm = Status::query()->findOrFail($id)->only(['id', 'name', 'slug', 'color', 'sort_order', 'is_closed']);
|
|
$this->section = 'statuses';
|
|
}
|
|
|
|
/** @return void */
|
|
public function deleteStatus(int $id): void
|
|
{
|
|
Status::query()->findOrFail($id)->delete();
|
|
session()->flash('success', 'Status deleted.');
|
|
}
|
|
|
|
/** @return void */
|
|
public function resetStatusForm(): void
|
|
{
|
|
$this->statusForm = ['id' => null, 'name' => '', 'slug' => '', 'color' => 'zinc', 'sort_order' => 0, 'is_closed' => false];
|
|
}
|
|
|
|
/** @return void */
|
|
public function savePriority(): void
|
|
{
|
|
$data = $this->validate([
|
|
'priorityForm.name' => ['required', 'string', 'max:80'],
|
|
'priorityForm.slug' => ['nullable', 'string', 'max:100'],
|
|
'priorityForm.color' => ['required', 'string', 'max:30'],
|
|
'priorityForm.sort_order' => ['required', 'integer', 'min:0'],
|
|
])['priorityForm'];
|
|
|
|
$data['slug'] = $this->slug($data['slug'] ?: $data['name']);
|
|
Priority::query()->updateOrCreate(['id' => $this->priorityForm['id']], $data);
|
|
$this->resetPriorityForm();
|
|
session()->flash('success', 'Priority saved.');
|
|
}
|
|
|
|
/** @return void */
|
|
public function editPriority(int $id): void
|
|
{
|
|
$this->priorityForm = Priority::query()->findOrFail($id)->only(['id', 'name', 'slug', 'color', 'sort_order']);
|
|
$this->section = 'priorities';
|
|
}
|
|
|
|
/** @return void */
|
|
public function deletePriority(int $id): void
|
|
{
|
|
Priority::query()->findOrFail($id)->delete();
|
|
session()->flash('success', 'Priority deleted.');
|
|
}
|
|
|
|
/** @return void */
|
|
public function resetPriorityForm(): void
|
|
{
|
|
$this->priorityForm = ['id' => null, 'name' => '', 'slug' => '', 'color' => 'zinc', 'sort_order' => 0];
|
|
}
|
|
|
|
/** @return void */
|
|
public function saveCategory(): void
|
|
{
|
|
$data = $this->validate([
|
|
'categoryForm.company_id' => ['nullable', 'integer'],
|
|
'categoryForm.name' => ['required', 'string', 'max:120'],
|
|
'categoryForm.slug' => ['nullable', 'string', 'max:140'],
|
|
'categoryForm.color' => ['required', 'string', 'max:30'],
|
|
'categoryForm.description' => ['nullable', 'string'],
|
|
])['categoryForm'];
|
|
|
|
$data['slug'] = $this->slug($data['slug'] ?: $data['name']);
|
|
Category::query()->updateOrCreate(['id' => $this->categoryForm['id']], $data);
|
|
$this->resetCategoryForm();
|
|
session()->flash('success', 'Category saved.');
|
|
}
|
|
|
|
/** @return void */
|
|
public function editCategory(int $id): void
|
|
{
|
|
$this->categoryForm = Category::query()->findOrFail($id)->only(['id', 'company_id', 'name', 'slug', 'color', 'description']);
|
|
$this->section = 'categories';
|
|
}
|
|
|
|
/** @return void */
|
|
public function deleteCategory(int $id): void
|
|
{
|
|
Category::query()->findOrFail($id)->delete();
|
|
session()->flash('success', 'Category deleted.');
|
|
}
|
|
|
|
/** @return void */
|
|
public function resetCategoryForm(): void
|
|
{
|
|
$this->categoryForm = ['id' => null, 'company_id' => null, 'name' => '', 'slug' => '', 'color' => 'blue', 'description' => ''];
|
|
}
|
|
|
|
/** @return void */
|
|
public function saveTeam(): void
|
|
{
|
|
$data = $this->validate([
|
|
'teamForm.company_id' => ['nullable', 'integer'],
|
|
'teamForm.name' => ['required', 'string', 'max:120'],
|
|
'teamForm.slug' => ['nullable', 'string', 'max:140'],
|
|
'teamForm.color' => ['required', 'string', 'max:30'],
|
|
'teamForm.description' => ['nullable', 'string'],
|
|
])['teamForm'];
|
|
|
|
$data['slug'] = $this->slug($data['slug'] ?: $data['name']);
|
|
Team::query()->updateOrCreate(['id' => $this->teamForm['id']], $data);
|
|
$this->resetTeamForm();
|
|
session()->flash('success', 'Team saved.');
|
|
}
|
|
|
|
/** @return void */
|
|
public function editTeam(int $id): void
|
|
{
|
|
$this->teamForm = Team::query()->findOrFail($id)->only(['id', 'company_id', 'name', 'slug', 'color', 'description', 'archived_at']);
|
|
$this->section = 'teams';
|
|
}
|
|
|
|
/** @return void */
|
|
public function deleteTeam(int $id): void
|
|
{
|
|
Team::query()->findOrFail($id)->delete();
|
|
session()->flash('success', 'Team deleted.');
|
|
}
|
|
|
|
/** @return void */
|
|
public function resetTeamForm(): void
|
|
{
|
|
$this->teamForm = ['id' => null, 'company_id' => null, 'name' => '', 'slug' => '', 'color' => 'indigo', 'description' => '', 'archived_at' => null];
|
|
}
|
|
|
|
/** @return void */
|
|
public function saveProject(): void
|
|
{
|
|
$data = $this->validate([
|
|
'projectForm.company_id' => ['nullable', 'integer'],
|
|
'projectForm.team_id' => ['nullable', 'integer', 'exists:helpdesk_teams,id'],
|
|
'projectForm.title' => ['required', 'string', 'max:160'],
|
|
'projectForm.slug' => ['nullable', 'string', 'max:180'],
|
|
'projectForm.color' => ['required', 'string', 'max:30'],
|
|
'projectForm.description' => ['nullable', 'string'],
|
|
])['projectForm'];
|
|
|
|
$data['slug'] = $this->slug($data['slug'] ?: $data['title']);
|
|
Project::query()->updateOrCreate(['id' => $this->projectForm['id']], $data);
|
|
$this->resetProjectForm();
|
|
session()->flash('success', 'Project saved.');
|
|
}
|
|
|
|
/** @return void */
|
|
public function editProject(int $id): void
|
|
{
|
|
$this->projectForm = Project::query()->findOrFail($id)->only(['id', 'company_id', 'team_id', 'title', 'slug', 'color', 'description', 'archived_at']);
|
|
$this->section = 'projects';
|
|
}
|
|
|
|
/** @return void */
|
|
public function deleteProject(int $id): void
|
|
{
|
|
Project::query()->findOrFail($id)->delete();
|
|
session()->flash('success', 'Project deleted.');
|
|
}
|
|
|
|
/** @return void */
|
|
public function resetProjectForm(): void
|
|
{
|
|
$this->projectForm = ['id' => null, 'company_id' => null, 'team_id' => null, 'title' => '', 'slug' => '', 'color' => 'blue', 'description' => '', 'archived_at' => null];
|
|
}
|
|
|
|
|
|
/** @return void */
|
|
public function saveRepository(): void
|
|
{
|
|
$data = $this->validate([
|
|
'repositoryForm.company_id' => ['nullable', 'integer'],
|
|
'repositoryForm.project_id' => ['nullable', 'integer', 'exists:helpdesk_projects,id'],
|
|
'repositoryForm.name' => ['required', 'string', 'max:160'],
|
|
'repositoryForm.provider' => ['required', 'string', 'max:40'],
|
|
'repositoryForm.remote_url' => ['required', 'string', 'max:500'],
|
|
'repositoryForm.default_branch' => ['required', 'string', 'max:120'],
|
|
'repositoryForm.webhook_secret' => ['nullable', 'string', 'max:120'],
|
|
])['repositoryForm'];
|
|
|
|
GitRepository::query()->updateOrCreate(['id' => $this->repositoryForm['id']], $data);
|
|
$this->resetRepositoryForm();
|
|
session()->flash('success', 'Git repository saved.');
|
|
}
|
|
|
|
/** @return void */
|
|
public function editRepository(int $id): void
|
|
{
|
|
$this->repositoryForm = GitRepository::query()->findOrFail($id)->only(['id', 'company_id', 'project_id', 'name', 'provider', 'remote_url', 'default_branch', 'webhook_secret']);
|
|
$this->section = 'git';
|
|
}
|
|
|
|
/** @return void */
|
|
public function deleteRepository(int $id): void
|
|
{
|
|
GitRepository::query()->findOrFail($id)->delete();
|
|
session()->flash('success', 'Git repository deleted.');
|
|
}
|
|
|
|
/** @return void */
|
|
public function resetRepositoryForm(): void
|
|
{
|
|
$this->repositoryForm = ['id' => null, 'company_id' => null, 'project_id' => null, 'name' => '', 'provider' => 'git', 'remote_url' => '', 'default_branch' => 'main', 'webhook_secret' => ''];
|
|
}
|
|
|
|
|
|
/** @return void */
|
|
public function saveWorkflowTemplate(): void
|
|
{
|
|
$data = $this->validate([
|
|
'workflowForm.name' => ['required', 'string', 'max:160'],
|
|
'workflowForm.event' => ['required', 'string', 'max:80'],
|
|
'workflowForm.subject' => ['required', 'string', 'max:220'],
|
|
'workflowForm.html_body' => ['required', 'string'],
|
|
'workflowForm.text_body' => ['nullable', 'string'],
|
|
'workflowForm.to_role' => ['required', 'string', 'max:40'],
|
|
'workflowForm.cc' => ['nullable', 'string', 'max:500'],
|
|
'workflowForm.bcc' => ['nullable', 'string', 'max:500'],
|
|
'workflowForm.is_active' => ['boolean'],
|
|
])['workflowForm'];
|
|
|
|
WorkflowTemplate::query()->updateOrCreate(['id' => $this->workflowForm['id']], $data);
|
|
$this->resetWorkflowTemplateForm();
|
|
session()->flash('success', 'Workflow message saved.');
|
|
}
|
|
|
|
/** @return void */
|
|
public function editWorkflowTemplate(int $id): void
|
|
{
|
|
$this->workflowForm = WorkflowTemplate::query()->findOrFail($id)->only(['id', 'name', 'event', 'subject', 'html_body', 'text_body', 'to_role', 'cc', 'bcc', 'is_active']);
|
|
$this->section = 'workflow';
|
|
}
|
|
|
|
/** @return void */
|
|
public function deleteWorkflowTemplate(int $id): void
|
|
{
|
|
WorkflowTemplate::query()->findOrFail($id)->delete();
|
|
session()->flash('success', 'Workflow message deleted.');
|
|
}
|
|
|
|
/** @return void */
|
|
public function resetWorkflowTemplateForm(): void
|
|
{
|
|
$this->workflowForm = ['id' => null, 'name' => '', 'event' => 'ticket.created', 'subject' => '', 'html_body' => '', 'text_body' => '', 'to_role' => 'requester', 'cc' => '', 'bcc' => '', 'is_active' => true];
|
|
}
|
|
|
|
/** @return View */
|
|
public function render(): View
|
|
{
|
|
return view('helpdesk::livewire.settings-manager', [
|
|
'companies' => $this->companies(),
|
|
'statuses' => Status::query()->withCount('tickets')->orderBy('sort_order')->orderBy('name')->get(),
|
|
'priorities' => Priority::query()->withCount('tickets')->orderBy('sort_order')->orderBy('name')->get(),
|
|
'categories' => Category::query()->withCount('tickets')->orderBy('name')->get(),
|
|
'teams' => Team::query()->withCount(['projects', 'tickets'])->orderBy('name')->get(),
|
|
'projects' => Project::query()->with(['team'])->withCount('tickets')->orderBy('title')->get(),
|
|
'repositories' => GitRepository::query()->with(['project'])->withCount('commits')->orderBy('name')->get(),
|
|
'workflowTemplates' => WorkflowTemplate::query()->orderBy('event')->orderBy('name')->get(),
|
|
])->layout('layouts.app');
|
|
}
|
|
|
|
/** @return array<int, object> */
|
|
private function companies(): array
|
|
{
|
|
if (! Schema::hasTable('companies')) {
|
|
return [];
|
|
}
|
|
|
|
return DB::table('companies')->select(['id', 'name'])->orderBy('name')->get()->all();
|
|
}
|
|
|
|
private function slug(string $value): string
|
|
{
|
|
return Str::slug($value);
|
|
}
|
|
}
|