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

@@ -1,6 +1,7 @@
import { t } from "@lingui/core/macro";
import {
HiEllipsisHorizontal,
HiHashtag,
HiLink,
HiOutlineCheckCircle,
HiOutlineTrash,
@@ -18,11 +19,13 @@ export default function CardDropdown({
isTemplate,
boardPublicId,
cardCreatedBy,
ticketNumber,
}: {
cardPublicId: string;
isTemplate?: boolean;
boardPublicId?: string;
cardCreatedBy?: string | null;
ticketNumber?: string | null;
}) {
const { openModal } = useModal();
const { showPopup } = usePopup();
@@ -53,12 +56,40 @@ export default function CardDropdown({
}
};
const handleCopyTicketId = async () => {
if (!ticketNumber) return;
try {
await navigator.clipboard.writeText(ticketNumber);
showPopup({
header: t`ID copied`,
icon: "success",
message: t`Ticket ID copied to clipboard`,
});
} catch (error) {
console.error(error);
showPopup({
header: t`Unable to copy ID`,
icon: "error",
message: t`Please try again.`,
});
}
};
const items = [
{
label: t`Copy card link`,
action: handleCopyCardLink,
icon: <HiLink className="h-[16px] w-[16px] text-dark-900" />,
},
...(ticketNumber
? [
{
label: t`Copy ticket ID`,
action: handleCopyTicketId,
icon: <HiHashtag className="h-[16px] w-[16px] text-dark-900" />,
},
]
: []),
...(canEditCard
? [
{