From b73dc41b702871c91a04cef276bd2ba1728c071a Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Fri, 4 Aug 2023 13:06:16 +0200 Subject: [PATCH] Implement task editor and other things --- .../app/board/[board]/BoardTaskEditForm.tsx | 19 ++++++ .../app/board/[board]/TaskDisplay.module.css | 11 +++- .../src/app/board/[board]/TaskDisplay.tsx | 32 +++++++-- todoblue/src/app/board/[board]/Types.ts | 6 ++ todoblue/src/app/board/[board]/page.tsx | 2 + todoblue/src/app/board/[board]/useBoard.tsx | 11 ++++ .../app/board/[board]/useBoardTaskEditor.ts | 66 +++++++++++++------ 7 files changed, 119 insertions(+), 28 deletions(-) create mode 100644 todoblue/src/app/board/[board]/BoardTaskEditForm.tsx diff --git a/todoblue/src/app/board/[board]/BoardTaskEditForm.tsx b/todoblue/src/app/board/[board]/BoardTaskEditForm.tsx new file mode 100644 index 0000000..5fcaab3 --- /dev/null +++ b/todoblue/src/app/board/[board]/BoardTaskEditForm.tsx @@ -0,0 +1,19 @@ +import {useManagedBoard} from "@/app/board/[board]/BoardManager" +import {FormEvent, useCallback} from "react" + + +export function BoardTaskEditForm() { + const {editedTaskText, setEditedTaskText, editedTask, send} = useManagedBoard() + + const submitTask = useCallback((e: FormEvent) => { + e.preventDefault(); + send({"Task": [null, editedTask]}); + setEditedTaskText("") + }, [send, editedTask]) + + return ( +
+ setEditedTaskText(e.target.value)}/> +
+ ) +} diff --git a/todoblue/src/app/board/[board]/TaskDisplay.module.css b/todoblue/src/app/board/[board]/TaskDisplay.module.css index 0e11fcb..7a9c2e5 100644 --- a/todoblue/src/app/board/[board]/TaskDisplay.module.css +++ b/todoblue/src/app/board/[board]/TaskDisplay.module.css @@ -3,7 +3,7 @@ align-items: center; min-width: unset; width: 240px; - height: 44px; + min-height: 44px; cursor: pointer; } @@ -17,7 +17,7 @@ .taskDivBack { grid-template-areas: - "buttons" + "id buttons" ; grid-template-columns: 1fr; } @@ -117,3 +117,10 @@ grid-area: buttons; justify-self: end; } + +.taskId { + grid-area: id; + + font-size: xx-small; + word-break: break-all; +} diff --git a/todoblue/src/app/board/[board]/TaskDisplay.tsx b/todoblue/src/app/board/[board]/TaskDisplay.tsx index 08e6c47..7b17071 100644 --- a/todoblue/src/app/board/[board]/TaskDisplay.tsx +++ b/todoblue/src/app/board/[board]/TaskDisplay.tsx @@ -27,11 +27,16 @@ export function TaskDisplay({task}: {task: TaskWithId}) { let contents; if(isDisplayingActions) { - contents =
- -
+ contents = <> + + + {task.id} + + +
+ +
+ } else { contents = <> @@ -71,3 +76,20 @@ export function TaskDisplay({task}: {task: TaskWithId}) { ) } + +function RecreateButton({task}: {task: TaskWithId}) { + const {setEditedTask, send} = useManagedBoard() + + const id = task.id; + + const recreateTask = useCallback(() => { + setEditedTask(task) + send({"Task": [id, null]}) + }, [send, id]) + + return ( + + ) +} diff --git a/todoblue/src/app/board/[board]/Types.ts b/todoblue/src/app/board/[board]/Types.ts index b271c0c..f55fefa 100644 --- a/todoblue/src/app/board/[board]/Types.ts +++ b/todoblue/src/app/board/[board]/Types.ts @@ -60,6 +60,12 @@ export type TaskBoardAction = { "Task": [ string, Task, + ] | [ + null, + Task, + ] | [ + string, + null, ] } diff --git a/todoblue/src/app/board/[board]/page.tsx b/todoblue/src/app/board/[board]/page.tsx index d5fd891..31f9b21 100644 --- a/todoblue/src/app/board/[board]/page.tsx +++ b/todoblue/src/app/board/[board]/page.tsx @@ -3,6 +3,7 @@ import {BoardMain} from "@/app/board/[board]/BoardMain" import {BoardManager} from "@/app/board/[board]/BoardManager" import {BoardHeader} from "@/app/board/[board]/BoardHeader" +import {BoardTaskEditForm} from "@/app/board/[board]/BoardTaskEditForm" export default function Page({params: {board}}: {params: {board: string}}) { @@ -10,6 +11,7 @@ export default function Page({params: {board}}: {params: {board: string}}) { + ) } diff --git a/todoblue/src/app/board/[board]/useBoard.tsx b/todoblue/src/app/board/[board]/useBoard.tsx index f582fdf..2516c24 100644 --- a/todoblue/src/app/board/[board]/useBoard.tsx +++ b/todoblue/src/app/board/[board]/useBoard.tsx @@ -3,6 +3,7 @@ import {TASK_GROUPERS} from "@/app/board/[board]/doTaskGrouping" import {TASK_SORTERS} from "@/app/board/[board]/doTaskSorting" import {BoardAction, Task} from "@/app/board/[board]/Types" +import {useBoardTaskEditor} from "@/app/board/[board]/useBoardTaskEditor" import {useBoardWebSocket} from "@/app/board/[board]/useBoardWebSocket" import {TaskGroup, useBoardTaskArranger} from "@/app/board/[board]/useBoardTaskArranger" import {useBoardTitleEditor} from "@/app/board/[board]/useBoardTitleEditor" @@ -27,6 +28,10 @@ export interface UseBoardReturns { editTitle: string, setEditTitle: Dispatch>, send: (action: BoardAction) => void, + editedTaskText: string, + setEditedTaskText: (text: string) => void, + editedTask: Task, + setEditedTask: (task: Task) => void, } export function useBoard(name: string): UseBoardReturns { @@ -38,6 +43,8 @@ export function useBoard(name: string): UseBoardReturns { const {taskGroups} = useBoardTaskArranger(tasksById, taskGrouper, groupSorter, groupNamer, taskSorter); const {isEditingTitle, stopEditingTitle, startEditingTitle, toggleEditingTitle, editTitle, setEditTitle} = useBoardTitleEditor(title, send); + const {editedTaskText, setEditedTaskText, editedTask, setEditedTask} = useBoardTaskEditor() + return { title, tasksById, @@ -56,5 +63,9 @@ export function useBoard(name: string): UseBoardReturns { editTitle, setEditTitle, send, + editedTaskText, + setEditedTaskText, + editedTask, + setEditedTask, } } diff --git a/todoblue/src/app/board/[board]/useBoardTaskEditor.ts b/todoblue/src/app/board/[board]/useBoardTaskEditor.ts index bea2206..c40df17 100644 --- a/todoblue/src/app/board/[board]/useBoardTaskEditor.ts +++ b/todoblue/src/app/board/[board]/useBoardTaskEditor.ts @@ -1,12 +1,12 @@ -import {Task} from "@/app/board/[board]/Types" +import {Task, TaskIcon, TaskImportance, TaskPriority} from "@/app/board/[board]/Types" import {useCallback, useMemo, useState} from "react" -const PRIORITY_RE = /[^][1-5]\b/ -const IMPORTANCE_RE = /![1-5]\b/ -const ICON_RE = /\[[A-Za-z]+]\b/ +const PRIORITY_RE = /\^[1-5]\s?/ +const IMPORTANCE_RE = /![1-5]\s?/ +const ICON_RE = /\[([A-Za-z]+)]\s?/ -const MATCH_TO_IMPORTANCE = { +const MATCH_TO_IMPORTANCE: {[key: string]: TaskImportance} = { "!1": "Lowest", "!2": "Low", "!3": "Normal", @@ -14,7 +14,15 @@ const MATCH_TO_IMPORTANCE = { "!5": "Highest", } -const MATCH_TO_PRIORITY = { +const IMPORTANCE_TO_MATCH: {[key in TaskImportance]: string} = { + "Lowest": "!1", + "Low": "!2", + "Normal": "!3", + "High": "!4", + "Highest": "!5", +} + +const MATCH_TO_PRIORITY: {[key: string]: TaskPriority} = { "^1": "Lowest", "^2": "Low", "^3": "Normal", @@ -22,7 +30,15 @@ const MATCH_TO_PRIORITY = { "^5": "Highest", } -const MATCH_TO_ICON = { +const PRIORITY_TO_MATCH: {[key in TaskPriority]: string} = { + "Lowest": "^1", + "Low": "^2", + "Normal": "^3", + "High": "^4", + "Highest": "^5", +} + +const MATCH_TO_ICON: {[key: string]: TaskIcon} = { "user": "User", "image": "Image", "envelope": "Envelope", @@ -46,19 +62,22 @@ const MATCH_TO_ICON = { "moon": "Moon", } -export function rawToEvent(raw: string): Task { - const priorityMatch = raw.match(PRIORITY_RE) - const importanceMatch = raw.match(IMPORTANCE_RE) - const iconMatch = raw.match(ICON_RE) +function rawToTask(raw: string): Task { + const priorityMatch = PRIORITY_RE.exec(raw) + const importanceMatch = IMPORTANCE_RE.exec(raw) + const iconMatch = ICON_RE.exec(raw) - const priority = MATCH_TO_PRIORITY[priorityMatch?.[0]]; - const importance = MATCH_TO_IMPORTANCE[importanceMatch?.[0]]; - const icon = MATCH_TO_ICON[iconMatch?.[0]?.toLowerCase()] + // @ts-ignore TS2538 + const priority = MATCH_TO_PRIORITY[priorityMatch?.[0]?.trim()] ?? "Normal"; + // @ts-ignore TS2538 + const importance = MATCH_TO_IMPORTANCE[importanceMatch?.[0]?.trim()] ?? "Normal"; + // @ts-ignore TS2538 + const icon = MATCH_TO_ICON[iconMatch?.[1]?.trim()?.toLowerCase()] ?? "Circle"; // TODO: Splice so the regex aren't executed twice - raw = raw.replace(PRIORITY_RE, "") - raw = raw.replace(IMPORTANCE_RE, "") - raw = raw.replace(ICON_RE, "") + raw = raw?.replace(PRIORITY_RE, "") + raw = raw?.replace(IMPORTANCE_RE, "") + raw = raw?.replace(ICON_RE, "") raw = raw.trim() @@ -71,13 +90,18 @@ export function rawToEvent(raw: string): Task { } } +function taskToRaw(task: Task): string { + return `[${task.icon}] ${IMPORTANCE_TO_MATCH[task.importance]} ${PRIORITY_TO_MATCH[task.priority]} ${task.text}` +} export function useBoardTaskEditor() { - const [raw, setRaw] = useState(); + const [editedTaskText, setEditedTaskText] = useState(""); - const task = useMemo(() => rawToEvent(raw), [raw]) + const editedTask = useMemo(() => rawToTask(editedTaskText), [editedTaskText]) - const setTask = useCallback((t: Task) => { - setRaw("") // TODO + const setEditedTask = useCallback((t: Task) => { + setEditedTaskText(taskToRaw(t)) }, []) + + return {editedTaskText, setEditedTaskText, editedTask, setEditedTask} }