Phase 7: Search, filters, templates, and archive UI
Add full-text card search (PostgreSQL tsvector + GIN index) with navbar SearchBar, client-side board filters (label/assignee/due date), board templates (3 system templates + save-as-template API), and archive toggle for both board listing and board view. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,8 @@ import type { RequestHandler } from './$types.js';
|
||||
import { boardSchema } from '$lib/server/validation.js';
|
||||
import { withTenant } from '$lib/server/rls.js';
|
||||
import { requireAuth } from '$lib/server/guards.js';
|
||||
import { prisma } from '$lib/server/db.js';
|
||||
import { generatePositions } from '$lib/utils/fractional-index.js';
|
||||
|
||||
// List boards for current tenant
|
||||
export const GET: RequestHandler = async ({ locals }) => {
|
||||
@@ -50,10 +52,26 @@ export const POST: RequestHandler = async ({ request, locals }) => {
|
||||
return json({ error: result.error.issues[0].message }, { status: 400 });
|
||||
}
|
||||
|
||||
const { title, description, visibility, categoryId } = result.data;
|
||||
const { title, description, visibility, categoryId, templateId } = result.data;
|
||||
|
||||
// Load template columns if templateId provided
|
||||
let templateColumns: { title: string }[] = [];
|
||||
if (templateId) {
|
||||
// System templates have null tenantId, so query without RLS
|
||||
const template = await prisma.boardTemplate.findFirst({
|
||||
where: {
|
||||
id: templateId,
|
||||
OR: [{ tenantId: null }, { tenantId: tenant.id }]
|
||||
}
|
||||
});
|
||||
if (template) {
|
||||
const tpl = template.template as { columns?: { title: string }[] };
|
||||
templateColumns = tpl.columns || [];
|
||||
}
|
||||
}
|
||||
|
||||
const board = await withTenant(tenant.id, async (tx) => {
|
||||
return tx.board.create({
|
||||
const newBoard = await tx.board.create({
|
||||
data: {
|
||||
tenantId: tenant.id,
|
||||
title,
|
||||
@@ -73,6 +91,22 @@ export const POST: RequestHandler = async ({ request, locals }) => {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Create columns from template
|
||||
if (templateColumns.length > 0) {
|
||||
const positions = generatePositions(templateColumns.length);
|
||||
for (let i = 0; i < templateColumns.length; i++) {
|
||||
await tx.column.create({
|
||||
data: {
|
||||
boardId: newBoard.id,
|
||||
title: templateColumns[i].title,
|
||||
position: positions[i]
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return newBoard;
|
||||
});
|
||||
|
||||
return json({ board }, { status: 201 });
|
||||
|
||||
Reference in New Issue
Block a user