Quick add task from the header (owner): modal, g t shortcut, auto_handle + Daisy webhook
Some checks failed
Deploy production / deploy (push) Has been cancelled
Some checks failed
Deploy production / deploy (push) Has been cancelled
- + button next to Dashboard (desktop and mobile sheet), lazy-loaded native <dialog>
- POST /trackers/tasks/quick inserts source 'quick-add', notes, due date, priority
- tasks.tasks.auto_handle (default false) with a Daisy badge in the tracker
- DAISY_TASK_WEBHOOK_URL/KEY/HEADER: fire-and-forget POST {task_id, title}, 3 s timeout
This commit is contained in:
@@ -276,6 +276,7 @@
|
||||
<p class="flex flex-wrap items-center gap-x-2 gap-y-1">
|
||||
<button type="button" class="title" onclick={() => openTask(t)}>{t.title}</button>
|
||||
{#if t.flagged}<Flag size={13} class="text-red-500" aria-label="Flagged" />{/if}
|
||||
{#if t.autoHandle}<span class="chip daisy" title="Daisy handles this">Daisy</span>{/if}
|
||||
{#if t.priority >= 2}<span class="chip prio-{t.priority}">{PRIORITY[t.priority]}</span>{/if}
|
||||
{#if t.dueDate}<span class="chip due-{isOpen(t) ? due : 'later'}">{dueLabel(t)}</span>{/if}
|
||||
{#if t.reminderAt && isOpen(t)}<span class="chip" title="Reminder"
|
||||
@@ -839,6 +840,11 @@
|
||||
color: var(--site-muted);
|
||||
white-space: nowrap;
|
||||
}
|
||||
.daisy {
|
||||
background: rgb(139 92 246 / 0.15);
|
||||
border-color: rgb(139 92 246 / 0.5);
|
||||
color: rgb(139 92 246);
|
||||
}
|
||||
.due-overdue {
|
||||
background: rgb(239 68 68 / 0.15);
|
||||
border-color: rgb(239 68 68 / 0.5);
|
||||
|
||||
45
src/routes/trackers/tasks/quick/+server.ts
Normal file
45
src/routes/trackers/tasks/quick/+server.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import * as z from 'zod';
|
||||
import { error, json } from '@sveltejs/kit';
|
||||
import { db } from '#lib/server/db/index.js';
|
||||
import { todoActivity, todoTasks } from '#lib/server/db/schema/index.js';
|
||||
import { requireOwner } from '#lib/server/owner.js';
|
||||
import { parseQuickTitle } from '#lib/server/tasks.js';
|
||||
import { notifyDaisy } from '#lib/server/daisy-hook.js';
|
||||
import type { RequestHandler } from './$types';
|
||||
|
||||
// Header "quick add task" modal (any page, owner only; hooks.server.ts also refuses
|
||||
// non-owner writes under /trackers/tasks). "!"/"!!!" in the title work as on the tracker.
|
||||
const input = z.object({
|
||||
title: z.string().trim().min(1, 'Give the task a title').max(500),
|
||||
notes: z.string().trim().max(10_000).optional().default(''),
|
||||
due: z
|
||||
.string()
|
||||
.regex(/^(\d{4}-\d{2}-\d{2})?$/, 'Invalid deadline')
|
||||
.optional()
|
||||
.default(''),
|
||||
priority: z.coerce.number().int().min(0).max(3).optional().default(0),
|
||||
autoHandle: z.boolean().optional().default(false)
|
||||
});
|
||||
|
||||
export const POST: RequestHandler = async (event) => {
|
||||
requireOwner(event);
|
||||
const parsed = input.safeParse(await event.request.json().catch(() => null));
|
||||
if (!parsed.success) error(400, parsed.error.issues[0]?.message ?? 'Invalid task');
|
||||
const quick = parseQuickTitle(parsed.data.title);
|
||||
if (!quick.title) error(400, 'Give the task a title');
|
||||
const [row] = await db
|
||||
.insert(todoTasks)
|
||||
.values({
|
||||
title: quick.title,
|
||||
notes: parsed.data.notes || null,
|
||||
dueDate: parsed.data.due || null,
|
||||
priority: parsed.data.priority || quick.priority,
|
||||
flagged: quick.flagged,
|
||||
autoHandle: parsed.data.autoHandle,
|
||||
source: 'quick-add'
|
||||
})
|
||||
.returning({ id: todoTasks.id, title: todoTasks.title });
|
||||
await db.insert(todoActivity).values({ taskId: row.id, kind: 'created', toStatus: 'todo' });
|
||||
const hook = parsed.data.autoHandle ? notifyDaisy(row) : 'off';
|
||||
return json({ id: row.id, title: row.title, hook });
|
||||
};
|
||||
Reference in New Issue
Block a user