feat: custom board templates (#98) (#209)

* feat: add type and sourceId columns to board schema

* chore: update _journal and add snapshot

* feat: scaffold templates page

* feat: add template pages

* feat: add template card page

* feat: add template view indicator

* fix: ensure checklists default to empty array in board view

* feat: create template from board

* feat: show custom templates in new board form

* feat: create card activity from snapshot creation

* chore: update readme and features

* chore: add translations
This commit is contained in:
Henry
2025-10-10 20:19:42 +01:00
committed by GitHub
parent 362381f516
commit a7a27e7054
41 changed files with 8296 additions and 1357 deletions

View File

@@ -25,6 +25,10 @@ export const boardVisibilityEnum = pgEnum(
boardVisibilityStatuses,
);
export const boardTypes = ["regular", "template"] as const;
export type BoardType = (typeof boardTypes)[number];
export const boardTypeEnum = pgEnum("board_type", boardTypes);
export const boards = pgTable(
"board",
{
@@ -49,9 +53,13 @@ export const boards = pgTable(
.notNull()
.references(() => workspaces.id, { onDelete: "cascade" }),
visibility: boardVisibilityEnum("visibility").notNull().default("private"),
type: boardTypeEnum("type").notNull().default("regular"),
sourceBoardId: bigint("sourceBoardId", { mode: "number" }),
},
(table) => [
index("board_visibility_idx").on(table.visibility),
index("board_type_idx").on(table.type),
index("board_source_idx").on(table.sourceBoardId),
uniqueIndex("unique_slug_per_workspace")
.on(table.workspaceId, table.slug)
.where(sql`${table.deletedAt} IS NULL`),

View File

@@ -12,6 +12,7 @@ import {
varchar,
} from "drizzle-orm/pg-core";
import { boards } from "./boards";
import { checklists } from "./checklists";
import { imports } from "./imports";
import { labels } from "./labels";
@@ -133,6 +134,10 @@ export const cardActivities = pgTable("card_activity", {
),
fromComment: text("fromComment"),
toComment: text("toComment"),
sourceBoardId: bigint("sourceBoardId", { mode: "number" }).references(
() => boards.id,
{ onDelete: "set null" },
),
}).enableRLS();
export const cardActivitiesRelations = relations(cardActivities, ({ one }) => ({