mirror of
https://github.com/Steffo99/todocolors.git
synced 2024-11-25 17:54:18 +00:00
Implement task editor and other things
This commit is contained in:
parent
eee5904c08
commit
b73dc41b70
7 changed files with 119 additions and 28 deletions
19
todoblue/src/app/board/[board]/BoardTaskEditForm.tsx
Normal file
19
todoblue/src/app/board/[board]/BoardTaskEditForm.tsx
Normal file
|
@ -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 (
|
||||||
|
<form onSubmit={submitTask}>
|
||||||
|
<input type={"text"} placeholder={"What to do...?"} value={editedTaskText} onChange={(e) => setEditedTaskText(e.target.value)}/>
|
||||||
|
</form>
|
||||||
|
)
|
||||||
|
}
|
|
@ -3,7 +3,7 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
min-width: unset;
|
min-width: unset;
|
||||||
width: 240px;
|
width: 240px;
|
||||||
height: 44px;
|
min-height: 44px;
|
||||||
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
.taskDivBack {
|
.taskDivBack {
|
||||||
grid-template-areas:
|
grid-template-areas:
|
||||||
"buttons"
|
"id buttons"
|
||||||
;
|
;
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
|
@ -117,3 +117,10 @@
|
||||||
grid-area: buttons;
|
grid-area: buttons;
|
||||||
justify-self: end;
|
justify-self: end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.taskId {
|
||||||
|
grid-area: id;
|
||||||
|
|
||||||
|
font-size: xx-small;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
|
@ -27,11 +27,16 @@ export function TaskDisplay({task}: {task: TaskWithId}) {
|
||||||
|
|
||||||
let contents;
|
let contents;
|
||||||
if(isDisplayingActions) {
|
if(isDisplayingActions) {
|
||||||
contents = <div className={style.taskButtons}>
|
contents = <>
|
||||||
<button>
|
<small className={style.taskId}>
|
||||||
<FontAwesomeIcon icon={faTrashCanArrowUp}/> Ricrea
|
<code>
|
||||||
</button>
|
{task.id}
|
||||||
</div>
|
</code>
|
||||||
|
</small>
|
||||||
|
<div className={style.taskButtons}>
|
||||||
|
<RecreateButton task={task}/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
contents = <>
|
contents = <>
|
||||||
|
@ -71,3 +76,20 @@ export function TaskDisplay({task}: {task: TaskWithId}) {
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 (
|
||||||
|
<button onClick={recreateTask}>
|
||||||
|
<FontAwesomeIcon icon={faTrashCanArrowUp}/> Ricrea
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -60,6 +60,12 @@ export type TaskBoardAction = {
|
||||||
"Task": [
|
"Task": [
|
||||||
string,
|
string,
|
||||||
Task,
|
Task,
|
||||||
|
] | [
|
||||||
|
null,
|
||||||
|
Task,
|
||||||
|
] | [
|
||||||
|
string,
|
||||||
|
null,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
import {BoardMain} from "@/app/board/[board]/BoardMain"
|
import {BoardMain} from "@/app/board/[board]/BoardMain"
|
||||||
import {BoardManager} from "@/app/board/[board]/BoardManager"
|
import {BoardManager} from "@/app/board/[board]/BoardManager"
|
||||||
import {BoardHeader} from "@/app/board/[board]/BoardHeader"
|
import {BoardHeader} from "@/app/board/[board]/BoardHeader"
|
||||||
|
import {BoardTaskEditForm} from "@/app/board/[board]/BoardTaskEditForm"
|
||||||
|
|
||||||
|
|
||||||
export default function Page({params: {board}}: {params: {board: string}}) {
|
export default function Page({params: {board}}: {params: {board: string}}) {
|
||||||
|
@ -10,6 +11,7 @@ export default function Page({params: {board}}: {params: {board: string}}) {
|
||||||
<BoardManager name={board}>
|
<BoardManager name={board}>
|
||||||
<BoardHeader/>
|
<BoardHeader/>
|
||||||
<BoardMain/>
|
<BoardMain/>
|
||||||
|
<BoardTaskEditForm/>
|
||||||
</BoardManager>
|
</BoardManager>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
import {TASK_GROUPERS} from "@/app/board/[board]/doTaskGrouping"
|
import {TASK_GROUPERS} from "@/app/board/[board]/doTaskGrouping"
|
||||||
import {TASK_SORTERS} from "@/app/board/[board]/doTaskSorting"
|
import {TASK_SORTERS} from "@/app/board/[board]/doTaskSorting"
|
||||||
import {BoardAction, Task} from "@/app/board/[board]/Types"
|
import {BoardAction, Task} from "@/app/board/[board]/Types"
|
||||||
|
import {useBoardTaskEditor} from "@/app/board/[board]/useBoardTaskEditor"
|
||||||
import {useBoardWebSocket} from "@/app/board/[board]/useBoardWebSocket"
|
import {useBoardWebSocket} from "@/app/board/[board]/useBoardWebSocket"
|
||||||
import {TaskGroup, useBoardTaskArranger} from "@/app/board/[board]/useBoardTaskArranger"
|
import {TaskGroup, useBoardTaskArranger} from "@/app/board/[board]/useBoardTaskArranger"
|
||||||
import {useBoardTitleEditor} from "@/app/board/[board]/useBoardTitleEditor"
|
import {useBoardTitleEditor} from "@/app/board/[board]/useBoardTitleEditor"
|
||||||
|
@ -27,6 +28,10 @@ export interface UseBoardReturns {
|
||||||
editTitle: string,
|
editTitle: string,
|
||||||
setEditTitle: Dispatch<SetStateAction<string>>,
|
setEditTitle: Dispatch<SetStateAction<string>>,
|
||||||
send: (action: BoardAction) => void,
|
send: (action: BoardAction) => void,
|
||||||
|
editedTaskText: string,
|
||||||
|
setEditedTaskText: (text: string) => void,
|
||||||
|
editedTask: Task,
|
||||||
|
setEditedTask: (task: Task) => void,
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useBoard(name: string): UseBoardReturns {
|
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 {taskGroups} = useBoardTaskArranger(tasksById, taskGrouper, groupSorter, groupNamer, taskSorter);
|
||||||
const {isEditingTitle, stopEditingTitle, startEditingTitle, toggleEditingTitle, editTitle, setEditTitle} = useBoardTitleEditor(title, send);
|
const {isEditingTitle, stopEditingTitle, startEditingTitle, toggleEditingTitle, editTitle, setEditTitle} = useBoardTitleEditor(title, send);
|
||||||
|
|
||||||
|
const {editedTaskText, setEditedTaskText, editedTask, setEditedTask} = useBoardTaskEditor()
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title,
|
title,
|
||||||
tasksById,
|
tasksById,
|
||||||
|
@ -56,5 +63,9 @@ export function useBoard(name: string): UseBoardReturns {
|
||||||
editTitle,
|
editTitle,
|
||||||
setEditTitle,
|
setEditTitle,
|
||||||
send,
|
send,
|
||||||
|
editedTaskText,
|
||||||
|
setEditedTaskText,
|
||||||
|
editedTask,
|
||||||
|
setEditedTask,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"
|
import {useCallback, useMemo, useState} from "react"
|
||||||
|
|
||||||
|
|
||||||
const PRIORITY_RE = /[^][1-5]\b/
|
const PRIORITY_RE = /\^[1-5]\s?/
|
||||||
const IMPORTANCE_RE = /![1-5]\b/
|
const IMPORTANCE_RE = /![1-5]\s?/
|
||||||
const ICON_RE = /\[[A-Za-z]+]\b/
|
const ICON_RE = /\[([A-Za-z]+)]\s?/
|
||||||
|
|
||||||
const MATCH_TO_IMPORTANCE = {
|
const MATCH_TO_IMPORTANCE: {[key: string]: TaskImportance} = {
|
||||||
"!1": "Lowest",
|
"!1": "Lowest",
|
||||||
"!2": "Low",
|
"!2": "Low",
|
||||||
"!3": "Normal",
|
"!3": "Normal",
|
||||||
|
@ -14,7 +14,15 @@ const MATCH_TO_IMPORTANCE = {
|
||||||
"!5": "Highest",
|
"!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",
|
"^1": "Lowest",
|
||||||
"^2": "Low",
|
"^2": "Low",
|
||||||
"^3": "Normal",
|
"^3": "Normal",
|
||||||
|
@ -22,7 +30,15 @@ const MATCH_TO_PRIORITY = {
|
||||||
"^5": "Highest",
|
"^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",
|
"user": "User",
|
||||||
"image": "Image",
|
"image": "Image",
|
||||||
"envelope": "Envelope",
|
"envelope": "Envelope",
|
||||||
|
@ -46,19 +62,22 @@ const MATCH_TO_ICON = {
|
||||||
"moon": "Moon",
|
"moon": "Moon",
|
||||||
}
|
}
|
||||||
|
|
||||||
export function rawToEvent(raw: string): Task {
|
function rawToTask(raw: string): Task {
|
||||||
const priorityMatch = raw.match(PRIORITY_RE)
|
const priorityMatch = PRIORITY_RE.exec(raw)
|
||||||
const importanceMatch = raw.match(IMPORTANCE_RE)
|
const importanceMatch = IMPORTANCE_RE.exec(raw)
|
||||||
const iconMatch = raw.match(ICON_RE)
|
const iconMatch = ICON_RE.exec(raw)
|
||||||
|
|
||||||
const priority = MATCH_TO_PRIORITY[priorityMatch?.[0]];
|
// @ts-ignore TS2538
|
||||||
const importance = MATCH_TO_IMPORTANCE[importanceMatch?.[0]];
|
const priority = MATCH_TO_PRIORITY[priorityMatch?.[0]?.trim()] ?? "Normal";
|
||||||
const icon = MATCH_TO_ICON[iconMatch?.[0]?.toLowerCase()]
|
// @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
|
// TODO: Splice so the regex aren't executed twice
|
||||||
raw = raw.replace(PRIORITY_RE, "")
|
raw = raw?.replace(PRIORITY_RE, "")
|
||||||
raw = raw.replace(IMPORTANCE_RE, "")
|
raw = raw?.replace(IMPORTANCE_RE, "")
|
||||||
raw = raw.replace(ICON_RE, "")
|
raw = raw?.replace(ICON_RE, "")
|
||||||
|
|
||||||
raw = raw.trim()
|
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() {
|
export function useBoardTaskEditor() {
|
||||||
const [raw, setRaw] = useState<string>();
|
const [editedTaskText, setEditedTaskText] = useState<string>("");
|
||||||
|
|
||||||
const task = useMemo(() => rawToEvent(raw), [raw])
|
const editedTask = useMemo(() => rawToTask(editedTaskText), [editedTaskText])
|
||||||
|
|
||||||
const setTask = useCallback((t: Task) => {
|
const setEditedTask = useCallback((t: Task) => {
|
||||||
setRaw("") // TODO
|
setEditedTaskText(taskToRaw(t))
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
return {editedTaskText, setEditedTaskText, editedTask, setEditedTask}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue