Conversation
…tabase migrations, API endpoints, and UI components. - Fixes issue of same prevId in snapshots
…ews and update trash to 'deleted cards'.
|
Hey @hjball. Were you able to review this PR? If there is some thing i need to change do let me know. |
|
Sorry for the delay @sai80082 - I plan on reviewing this one in the next couple days |
| boardPublicId: z.string().min(12), | ||
| }), | ||
| ) | ||
| .output(z.custom<Awaited<ReturnType<typeof cardRepo.getArchivedByBoardId>>>()) |
There was a problem hiding this comment.
We've deprecated this pattern now - all response types should be standard zod schemas (defined in the schemas dir)
| const card = await cardRepo.getWorkspaceAndCardIdByCardPublicId( | ||
| ctx.db, | ||
| input.cardPublicId, | ||
| { includeDeleted: true }, |
There was a problem hiding this comment.
We should guard against deletedAt being null - we only want to allow hard deleting card that have already been soft deleted, right?
| card.createdBy, | ||
| ); | ||
|
|
||
| await cardRepo.unarchive(ctx.db, { |
There was a problem hiding this comment.
How do we handle cases where the list has been archived?
| }; | ||
|
|
||
| const handleHardDelete = (cardPublicId: string) => { | ||
| if (confirm(t`Are you sure you want to permanently delete this card? This action cannot be undone.`)) { |
There was a problem hiding this comment.
Please use the modal confirmation pattern instead of browser native dialog
| ] | ||
| : []), | ||
| { | ||
| label: t`Archived cards`, |
There was a problem hiding this comment.
We'll only want to show these if the user has the correct permissions
| "card:delete", | ||
| card.createdBy, | ||
| ); | ||
|
|
There was a problem hiding this comment.
Would be good if hard deleting created an activity log for the audit trail
| export default function DeletedCardsView({ boardPublicId }: Props) { | ||
| const utils = api.useUtils(); | ||
|
|
||
| const { data: deletedcards, isLoading } = api.board.deletedCards.useQuery( |
There was a problem hiding this comment.
| const { data: deletedcards, isLoading } = api.board.deletedCards.useQuery( | |
| const { data: deletedCards, isLoading } = api.board.deletedCards.useQuery( |
| // We need to join with lists to filter by board | ||
| return db | ||
| .select({ | ||
| id: cards.id, |
There was a problem hiding this comment.
Can we exclude the internal ID from the response if it's not needed - the publicId should be sufficient
| ) => { | ||
| return db | ||
| .select({ | ||
| id: cards.id, |
| createdAt: timestamp("createdAt").defaultNow().notNull(), | ||
| updatedAt: timestamp("updatedAt"), | ||
| deletedAt: timestamp("deletedAt"), | ||
| archivedAt: timestamp("archivedAt"), |
There was a problem hiding this comment.
Would be good to add an index for archivedAt
|
Context: evaluating kan.bn as an audit-first system of record for human + AI-agent work (I also opened #611 on trail integrity — this comment is only about the trash/restore UX surface). Strong +1 — and thanks for the thorough patch (verified the migration + router changes). A few notes from an audit-focused reviewer, all minor:
None of these block the PR — 1 and 3 could be fast-follows. The archive/restore foundation here is exactly what audit-sensitive deployments need. |
This pull request implements the archive card functionality, allowing users to move cards to an archived state instead of deleting them permanently.
This closes #307.
Below are the UI changes that are done for this feature.





