diff --git a/app/Actions/Tickets/StoreProjectTicketLink.php b/app/Actions/Tickets/StoreProjectTicketLink.php index 71d3719..1cf6422 100644 --- a/app/Actions/Tickets/StoreProjectTicketLink.php +++ b/app/Actions/Tickets/StoreProjectTicketLink.php @@ -17,18 +17,21 @@ class StoreProjectTicketLink ) {} /** - * @param array{linked_ticket_id: int, ticket_link_type_id: int} $validated + * @param array{linked_ticket_id: int, ticket_link_type_id: int, link_direction?: 'source'|'counterpart'} $validated */ public function handle(Project $project, Ticket $ticket, User $user, array $validated): TicketLink { $linkedTicketId = Arr::get($validated, 'linked_ticket_id'); $ticketLinkTypeId = Arr::get($validated, 'ticket_link_type_id'); + $isSourceTicket = Arr::get($validated, 'link_direction', 'source') === 'source'; $linkedTicket = Ticket::query() ->where('project_id', $project->id) ->findOrFail($linkedTicketId); + $sourceTicket = $isSourceTicket ? $ticket : $linkedTicket; + $targetTicket = $isSourceTicket ? $linkedTicket : $ticket; - return DB::transaction(function () use ($linkedTicket, $user, $ticketLinkTypeId, $ticket): TicketLink { + return DB::transaction(function () use ($linkedTicket, $user, $ticketLinkTypeId, $ticket, $sourceTicket, $targetTicket, $isSourceTicket): TicketLink { Ticket::query() ->whereKey([$ticket->id, $linkedTicket->id]) ->orderBy('id') @@ -50,31 +53,31 @@ class StoreProjectTicketLink if ($ticketLink === null) { $ticketLink = TicketLink::query()->create([ - 'source_ticket_id' => $ticket->id, - 'target_ticket_id' => $linkedTicket->id, + 'source_ticket_id' => $sourceTicket->id, + 'target_ticket_id' => $targetTicket->id, 'ticket_link_type_id' => $ticketLinkTypeId, ]); } else { $ticketLink->update([ - 'source_ticket_id' => $ticket->id, - 'target_ticket_id' => $linkedTicket->id, + 'source_ticket_id' => $sourceTicket->id, + 'target_ticket_id' => $targetTicket->id, 'ticket_link_type_id' => $ticketLinkTypeId, ]); } $ticketLink->load('ticketLinkType'); - $sourceLabel = $ticketLink->ticketLinkType->labelForSource(true); - $targetLabel = $ticketLink->ticketLinkType->labelForSource(false); + $ticketLabel = $ticketLink->ticketLinkType->labelForSource($isSourceTicket); + $linkedTicketLabel = $ticketLink->ticketLinkType->labelForSource(! $isSourceTicket); $this->createTicketWorklogEntry->handle( $ticket, $user, TicketWorklogEntryType::LinkUpdated, - "Linked {$linkedTicket->ticket_key} as {$sourceLabel}.", + "Linked {$linkedTicket->ticket_key} as {$ticketLabel}.", [ 'linked_ticket_key' => $linkedTicket->ticket_key, - 'ticket_link_type' => $sourceLabel, + 'ticket_link_type' => $ticketLabel, ], ); @@ -82,10 +85,10 @@ class StoreProjectTicketLink $linkedTicket, $user, TicketWorklogEntryType::LinkUpdated, - "Linked {$ticket->ticket_key} as {$targetLabel}.", + "Linked {$ticket->ticket_key} as {$linkedTicketLabel}.", [ 'linked_ticket_key' => $ticket->ticket_key, - 'ticket_link_type' => $targetLabel, + 'ticket_link_type' => $linkedTicketLabel, ], ); diff --git a/app/Http/Controllers/Api/ProjectTicketLinkController.php b/app/Http/Controllers/Api/ProjectTicketLinkController.php index 6555afd..1fa4eb4 100644 --- a/app/Http/Controllers/Api/ProjectTicketLinkController.php +++ b/app/Http/Controllers/Api/ProjectTicketLinkController.php @@ -36,11 +36,12 @@ class ProjectTicketLinkController extends ApiController $ticketLink = $this->storeProjectTicketLink->handle($project, $ticket, $user, $request->validated()); $ticketLink->setAttribute('current_ticket_id', $ticket->id); + $label = $ticketLink->ticketLinkType->labelForSource($ticketLink->source_ticket_id === $ticket->id); return TicketLinkResource::make($ticketLink->load(['sourceTicket', 'targetTicket', 'ticketLinkType'])) ->additional([ 'meta' => [ - 'message' => "{$ticketLink->ticketLinkType->label} link was saved.", + 'message' => "{$label} link was saved.", ], ]) ->response() diff --git a/app/Http/Controllers/ProjectTicketLinkController.php b/app/Http/Controllers/ProjectTicketLinkController.php index 208b98f..65b14e3 100644 --- a/app/Http/Controllers/ProjectTicketLinkController.php +++ b/app/Http/Controllers/ProjectTicketLinkController.php @@ -34,9 +34,10 @@ class ProjectTicketLinkController extends Controller ); $ticketLink = $this->storeProjectTicketLink->handle($project, $ticket, $user, $request->validated()); + $label = $ticketLink->ticketLinkType->labelForSource($ticketLink->source_ticket_id === $ticket->id); return to_route('projects.tickets.show', [$project, $ticket]) - ->with('status', "{$ticketLink->ticketLinkType->label} link was saved."); + ->with('status', "{$label} link was saved."); } public function destroy( diff --git a/app/Http/Requests/StoreTicketLinkRequest.php b/app/Http/Requests/StoreTicketLinkRequest.php index a4f2915..1bdc022 100644 --- a/app/Http/Requests/StoreTicketLinkRequest.php +++ b/app/Http/Requests/StoreTicketLinkRequest.php @@ -42,6 +42,7 @@ class StoreTicketLinkRequest extends FormRequest fn ($query) => $query->where('project_id', $project->id), ), ], + 'link_direction' => ['sometimes', 'required', Rule::in(['source', 'counterpart'])], ]; } diff --git a/resources/js/components/tickets/detail/TicketDetailRelationships.vue b/resources/js/components/tickets/detail/TicketDetailRelationships.vue index 10e88f3..4246a85 100644 --- a/resources/js/components/tickets/detail/TicketDetailRelationships.vue +++ b/resources/js/components/tickets/detail/TicketDetailRelationships.vue @@ -35,6 +35,7 @@ const canAddLink = computed( ); const form = useForm({ ticket_link_type_id: props.ticketLinkTypes[0]?.id ?? '', + link_direction: 'source', linked_ticket_id: '', }); const protection = useFormProtection(form, { @@ -220,7 +221,7 @@ function submit(): void { />
+ {{ ticket.ticket_key }}{{ selectedType.label }}{{ + form.link_direction === 'source' + ? selectedType.label + : selectedType.counterpart_label + }}