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
@@ -57,7 +57,7 @@ const breadcrumbs: BreadcrumbItem[] = [
</Badge>
<Heading
:title="`${project.name} ticket settings`"
description="Configure project-specific ticket types, priorities, and custom field definitions."
description="Configure project-specific ticket types, priorities, custom field definitions, and ticket link labels."
/>
</div>
@@ -81,7 +81,7 @@ const breadcrumbs: BreadcrumbItem[] = [
{{ status }}
</div>
<div class="grid gap-6 xl:grid-cols-3">
<div class="grid gap-6 xl:grid-cols-2">
<Card class="gap-0 overflow-hidden">
<CardHeader class="border-b">
<CardTitle>Ticket types</CardTitle>
@@ -497,6 +497,124 @@ const breadcrumbs: BreadcrumbItem[] = [
</div>
</CardContent>
</Card>
<Card class="gap-0 overflow-hidden">
<CardHeader class="border-b">
<CardTitle>Link types</CardTitle>
<CardDescription>
Define project-specific labels for ticket-to-ticket
relationships.
</CardDescription>
</CardHeader>
<CardContent class="space-y-4 p-6">
<Form
v-bind="
ProjectTicketMetadataSettingsController.storeLinkType.form(
project.id,
)
"
class="space-y-4 rounded-xl border border-dashed border-border p-4"
v-slot="{ errors, processing }"
>
<div class="grid gap-2">
<Label for="link-type-name">
New link type name
</Label>
<Input
id="link-type-name"
name="name"
required
placeholder="Relates to"
/>
<InputError :message="errors.name" />
</div>
<Button type="submit" :disabled="processing">
Add link type
</Button>
</Form>
<div
v-for="ticketLinkType in ticketLinkTypes"
:key="ticketLinkType.id"
class="rounded-xl border border-border p-4"
>
<Form
v-bind="
ProjectTicketMetadataSettingsController.updateLinkType.form(
[project.id, ticketLinkType.id],
)
"
class="grid gap-4"
v-slot="{ errors, processing }"
>
<div class="grid gap-2">
<Label
:for="`link-type-name-${ticketLinkType.id}`"
>
Label
</Label>
<Input
:id="`link-type-name-${ticketLinkType.id}`"
name="name"
:value="ticketLinkType.label"
required
/>
<InputError :message="errors.name" />
</div>
<div class="grid gap-2">
<Label
:for="`link-type-position-${ticketLinkType.id}`"
>
Position
</Label>
<Input
:id="`link-type-position-${ticketLinkType.id}`"
name="position"
type="number"
min="1"
:max="ticketLinkTypes.length"
:value="ticketLinkType.position"
required
/>
<InputError :message="errors.position" />
</div>
<div
class="flex flex-wrap justify-between gap-3"
>
<Button
type="submit"
variant="outline"
:disabled="processing"
>
Save
</Button>
</div>
</Form>
<Form
v-bind="
ProjectTicketMetadataSettingsController.destroyLinkType.form(
[project.id, ticketLinkType.id],
)
"
class="mt-3 flex justify-end"
v-slot="{ processing: deleting }"
>
<Button
type="submit"
variant="destructive"
:disabled="deleting"
>
Delete
</Button>
</Form>
</div>
</CardContent>
</Card>
</div>
</div>
</AppLayout>