Implement ticket statuses

This commit is contained in:
2026-04-14 03:09:12 +02:00
parent 2dc12c5d60
commit 8f4a8276ac
40 changed files with 1602 additions and 100 deletions
+59 -16
View File
@@ -18,6 +18,8 @@ import { board as boardSettings } from '@/routes/projects/settings';
import { index as boardIndex } from '@/routes/projects/board';
import { show as showTicket } from '@/routes/projects/tickets';
import type { BreadcrumbItem, ProjectBoardPageProps } from '@/types';
import type { TicketModel } from '@/types/models/ticket-model';
import type { TicketStatusModel } from '@/types/models/ticket-status-model';
const props = defineProps<ProjectBoardPageProps>();
@@ -36,16 +38,28 @@ const breadcrumbs: BreadcrumbItem[] = [
},
];
const statusOptions = [
{
label: 'Backlog',
value: '',
},
...props.boardColumns.map((boardColumn) => ({
label: boardColumn.name,
value: String(boardColumn.id),
})),
];
const ticketStatusLabel = (ticketStatus: TicketStatusModel | null): string => {
if (ticketStatus === null) {
return 'Unknown status';
}
if (
ticketStatus.board_column === null ||
ticketStatus.board_column === undefined
) {
return ticketStatus.name;
}
if (ticketStatus.board_column.name === ticketStatus.name) {
return ticketStatus.name;
}
return `${ticketStatus.board_column.name} / ${ticketStatus.name}`;
};
const allowedTargetStatuses = (ticket: TicketModel): TicketStatusModel[] => {
return ticket.ticket_status?.allowed_target_statuses ?? [];
};
</script>
<template>
@@ -116,6 +130,21 @@ const statusOptions = [
{{ boardColumn.tickets?.length ?? 0 }}
active ticket(s)
</CardDescription>
<div
v-if="
(boardColumn.ticket_statuses?.length ??
0) > 0
"
class="mt-3 flex flex-wrap gap-2"
>
<Badge
v-for="ticketStatus in boardColumn.ticket_statuses"
:key="ticketStatus.id"
variant="outline"
>
{{ ticketStatus.name }}
</Badge>
</div>
</div>
<Badge variant="secondary">
@@ -160,6 +189,13 @@ const statusOptions = [
<Badge variant="secondary">
{{ ticket.ticket_priority.name }}
</Badge>
<Badge variant="outline">
{{
ticketStatusLabel(
ticket.ticket_status,
)
}}
</Badge>
</div>
<CardTitle class="text-base">
<Link
@@ -218,18 +254,25 @@ const statusOptions = [
>
<select
:id="`ticket-status-${ticket.id}`"
name="board_column_id"
name="ticket_status_id"
:value="
ticket.board_column_id ?? ''
ticket.ticket_status_id ??
''
"
class="border-input bg-background shadow-xs focus-visible:border-ring focus-visible:ring-ring/50 min-w-44 rounded-md border px-3 py-2 text-sm outline-none transition-[color,box-shadow] focus-visible:ring-[3px]"
>
<option
v-for="statusOption in statusOptions"
:key="statusOption.label"
:value="statusOption.value"
v-for="ticketStatus in allowedTargetStatuses(
ticket,
)"
:key="ticketStatus.id"
:value="ticketStatus.id"
>
{{ statusOption.label }}
{{
ticketStatusLabel(
ticketStatus,
)
}}
</option>
</select>
<Button