Implement ticket links and blocker state

This commit is contained in:
2026-03-25 09:12:17 +01:00
parent 3b31e6bb7d
commit 70b90f32d4
34 changed files with 1722 additions and 10 deletions
@@ -10,6 +10,7 @@ use App\Http\Requests\UpdateProjectNamedSettingRequest;
use App\Http\Requests\UpdateTicketFieldDefinitionRequest;
use App\Models\Project;
use App\Models\TicketFieldDefinition;
use App\Models\TicketLinkType;
use App\Models\TicketPriority;
use App\Models\TicketType;
use Illuminate\Database\Eloquent\Model;
@@ -42,6 +43,7 @@ class ProjectTicketMetadataSettingsController extends Controller
'project' => $project,
'status' => session('status'),
'ticketFieldDefinitions' => $project->ticketFieldDefinitions()->get(),
'ticketLinkTypes' => $project->ticketLinkTypes()->get(),
'ticketPriorities' => $project->ticketPriorities()->get(),
'ticketTypes' => $project->ticketTypes()->get(),
]);
@@ -249,6 +251,71 @@ class ProjectTicketMetadataSettingsController extends Controller
->with('status', "{$deletedLabel} field was removed.");
}
public function storeLinkType(StoreProjectNamedSettingRequest $request, Project $project): RedirectResponse
{
$this->abortUnlessCanManage($request, $project);
$ticketLinkType = DB::transaction(function () use ($project, $request): TicketLinkType {
$ticketLinkType = $project->ticketLinkTypes()->create([
'label' => $request->validated('name'),
'position' => $project->ticketLinkTypes()->count() + 1,
]);
$this->reorderModels(
$project->ticketLinkTypes()->whereKeyNot($ticketLinkType->id)->get()->values(),
$ticketLinkType,
$request->position() ?? $project->ticketLinkTypes()->count(),
);
return $ticketLinkType;
});
return to_route('projects.settings.metadata', $project)
->with('status', "{$ticketLinkType->label} link type was added.");
}
public function updateLinkType(
UpdateProjectNamedSettingRequest $request,
Project $project,
TicketLinkType $ticketLinkType,
): RedirectResponse {
$this->abortUnlessCanManage($request, $project);
DB::transaction(function () use ($project, $request, $ticketLinkType): void {
$ticketLinkType->update([
'label' => $request->validated('name'),
]);
$this->reorderModels(
$project->ticketLinkTypes()->whereKeyNot($ticketLinkType->id)->get()->values(),
$ticketLinkType,
$request->position(),
);
});
return to_route('projects.settings.metadata', $project)
->with('status', "{$ticketLinkType->fresh()->label} link type was updated.");
}
public function destroyLinkType(
Request $request,
Project $project,
TicketLinkType $ticketLinkType,
): RedirectResponse {
$this->abortUnlessCanManage($request, $project);
$deletedLabel = $ticketLinkType->label;
DB::transaction(function () use ($project, $ticketLinkType): void {
$ticketLinkType->delete();
$this->persistOrderedModels($project->ticketLinkTypes()->get()->values());
});
return to_route('projects.settings.metadata', $project)
->with('status', "{$deletedLabel} link type was removed.");
}
private function abortUnlessCanManage(Request $request, Project $project): void
{
abort_unless(