Save and load task notes

This commit is contained in:
2026-02-27 23:42:44 +01:00
parent deb8c86d0d
commit 13f6fe2c3f
5 changed files with 29 additions and 8 deletions
+5 -2
View File
@@ -33,13 +33,16 @@ export default function Router({
switch (entity.type) {
case "todo": {
const createTask = (statusId: string) => {
const now = new Date().getTime();
const task: Task = {
id: id("task"),
title: "New task",
statusId,
tagIds: [],
createdAt: new Date().getTime(),
updatedAt: new Date().getTime(),
// initialize empty rich document notes
doc: { version: "2.28.0", time: now, blocks: [] },
createdAt: now,
updatedAt: now,
};
updateEntity(entityId, (e) => ({
+11 -6
View File
@@ -26,11 +26,16 @@ export default function DocDialog({
tags: Record<TagId, Tag>;
children: React.ReactNode;
}) {
const [doc, setDoc] = useState<OutputData>({
version: "2.28.0",
time: Date.now(),
blocks: [],
});
// if there is an existing document on the task use it, otherwise start with a blank one
const doc = task.doc || { version: "2.28.0", time: Date.now(), blocks: [] };
const handleDocChange = (newDoc: OutputData) => {
setTask({
...task,
doc: newDoc,
updatedAt: Date.now(),
});
};
return (
<Dialog>
@@ -62,7 +67,7 @@ export default function DocDialog({
</DialogHeader>
<ScrollArea className="h-[60vh]">
<DocView key={0} doc={doc} setDoc={setDoc} />
<DocView key={task.id} doc={doc} setDoc={handleDocChange} />
</ScrollArea>
</DialogContent>
</Dialog>
+5
View File
@@ -168,6 +168,7 @@ export function exportTodoAsCsv(todo: TodoEntity): string {
const headers = [
"Title",
"Description",
"Doc",
"Status",
"Tags",
"Created",
@@ -176,6 +177,7 @@ export function exportTodoAsCsv(todo: TodoEntity): string {
const rows = Object.values(todo.tasks).map((task) => [
task.title,
task.description || "",
task.doc ? JSON.stringify(task.doc) : "",
todo.config.statuses.find((s) => s.id === task.statusId)?.name || "",
task.tagIds.map((id) => todo.tags[id]?.name || "").join(";"),
new Date(task.createdAt).toISOString(),
@@ -228,6 +230,9 @@ export function exportTodoAsMarkdown(todo: TodoEntity): string {
if (task.description) {
markdown += `\n - ${task.description}`;
}
if (task.doc) {
markdown += `\n\n${docToMarkdown(task.doc)}`;
}
markdown += "\n";
}
}
+5
View File
@@ -96,6 +96,7 @@ export function importTodoFromCsv(
const descriptionIndex = headers.indexOf("description");
const statusIndex = headers.indexOf("status");
const tagsIndex = headers.indexOf("tags");
const docIndex = headers.indexOf("doc");
if (titleIndex === -1) {
errors.push("CSV must have a 'Title' column");
@@ -145,6 +146,10 @@ export function importTodoFromCsv(
id: taskId,
title,
description: descriptionIndex !== -1 ? values[descriptionIndex] : "",
doc:
docIndex !== -1 && values[docIndex]
? JSON.parse(values[docIndex])
: undefined,
statusId,
tagIds,
createdAt: Date.now(),
+3
View File
@@ -70,6 +70,9 @@ export interface Task {
title: string;
description?: string;
/** rich notes/documentation for the task */
doc?: OutputData;
statusId: string;
tagIds: TagId[];