feat: add ticket numbers to cards with workspace prefix (#443)

* feat: add ticket numbers to cards with workspace prefix

- Add cardNumber to cards
- Add cardPrefix/cardCounter to workspace
- Populate initial prefixes and numbers via new migration
- Introduce generateWorkspacePrefix util and export it
- Include cardNumber in card-related API responses and search results
- Render and display tickets as PREFIX-NUMBER in UI
- Update Card component to accept ticketNumber
- Update CardModal and board cards to show number when available
- Add cardNumber to CommandPalette search results type

* feat: regen migration

* feat: enhance card and workspace schemas with cardNumber and indexing

- Updated the card repository to allocate card numbers atomically per workspace.
- Modified the card schema to include a cardNumber field and added an index on listId and cardNumber for improved query performance.
- Enhanced the workspace schema to include an index on cardPrefix for optimized lookups.
- Adjusted the migration journal to reflect the new schema changes and their timestamps.
- Updated the regex in workspace repository to allow alphanumeric prefixes in ticket IDs.

---------

Co-authored-by: Henry <henry_ball@hotmail.co.uk>
This commit is contained in:
Florent Azonnoudo
2026-04-28 21:29:41 +00:00
committed by GitHub
parent bc8b5463b3
commit 4658b2961c
21 changed files with 4302 additions and 91 deletions

View File

@@ -16,6 +16,7 @@ import { getAvatarUrl } from "~/utils/helpers";
const Card = ({
title,
ticketNumber,
labels,
members,
checklists,
@@ -25,6 +26,7 @@ const Card = ({
dueDate,
}: {
title: string;
ticketNumber?: string | null;
labels: { name: string; colourCode: string | null }[];
members: {
publicId: string;
@@ -67,6 +69,11 @@ const Card = ({
return (
<div className="flex flex-col overflow-hidden rounded-md border border-light-200 bg-light-50 px-3 py-2 text-sm text-neutral-900 dark:border-dark-200 dark:bg-dark-200 dark:text-dark-1000 dark:hover:bg-dark-300">
{ticketNumber && (
<span className="mb-1 text-xs text-light-700 dark:text-dark-800">
{ticketNumber}
</span>
)}
<span className="break-words">{title}</span>
{labels.length ||
members.length ||

View File

@@ -146,6 +146,10 @@ export function NewCardForm({
listId: 2,
description: "",
dueDate: args.dueDate ?? null,
cardNumber: null,
comments: [],
checklists: [],
attachments: [],
labels: oldBoard.labels.filter((label) =>
args.labelPublicIds.includes(label.publicId),
),

View File

@@ -757,6 +757,11 @@ export default function BoardPage({ isTemplate }: { isTemplate?: boolean }) {
>
<Card
title={card.title}
ticketNumber={
card.cardNumber != null
? `${boardData.workspace.cardPrefix}-${card.cardNumber}`
: null
}
labels={card.labels}
members={card.members}
checklists={card.checklists ?? []}