todo list
This commit is contained in:
parent
7426012154
commit
aec4d826b5
Binary file not shown.
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
@ -6,10 +6,7 @@ import timeLine from "../assets/process.png";
|
||||
import todo from "../assets/calendar.png";
|
||||
import { Tooltip, SideSheet } from "@douyinfe/semi-ui";
|
||||
import { UndoRedoContext } from "../pages/editor";
|
||||
// import {
|
||||
// IllustrationNoContent,
|
||||
// IllustrationNoContentDark,
|
||||
// } from "@douyinfe/semi-illustrations";
|
||||
import Todo from "./todo";
|
||||
|
||||
export default function Sidebar() {
|
||||
const SidesheetType = {
|
||||
@ -20,8 +17,8 @@ export default function Sidebar() {
|
||||
TIMELINE: 4,
|
||||
BOT: 5,
|
||||
};
|
||||
const [sidesheet, setSidesheet] = useState(SidesheetType.NONE);
|
||||
const { undoStack } = useContext(UndoRedoContext);
|
||||
const [sidesheet, setSidesheet] = useState(SidesheetType.NONE);
|
||||
|
||||
const getTitle = (type) => {
|
||||
switch (type) {
|
||||
@ -39,11 +36,11 @@ export default function Sidebar() {
|
||||
<div className="ms-3">Chat</div>
|
||||
</div>
|
||||
);
|
||||
case SidesheetType.TEAM:
|
||||
case SidesheetType.TODO:
|
||||
return (
|
||||
<div className="flex items-center">
|
||||
<img src={teamIcon} className="w-7" alt="chat icon" />
|
||||
<div className="ms-3">Your team</div>
|
||||
<img src={todo} className="w-7" alt="todo icon" />
|
||||
<div className="ms-3">To-do list</div>
|
||||
</div>
|
||||
);
|
||||
default:
|
||||
@ -54,7 +51,9 @@ export default function Sidebar() {
|
||||
const getContent = (type) => {
|
||||
switch (type) {
|
||||
case SidesheetType.TIMELINE:
|
||||
return getTimeline();
|
||||
return renderTimeline();
|
||||
case SidesheetType.TODO:
|
||||
return <Todo />;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -77,8 +76,11 @@ export default function Sidebar() {
|
||||
</button>
|
||||
</Tooltip>
|
||||
<Tooltip content="To-do">
|
||||
<button className="block">
|
||||
<img src={todo} className="w-8 mb-5" alt="chat icon" />
|
||||
<button
|
||||
className="block"
|
||||
onClick={() => setSidesheet(SidesheetType.TODO)}
|
||||
>
|
||||
<img src={todo} className="w-8 mb-5" alt="todo icon" />
|
||||
</button>
|
||||
</Tooltip>
|
||||
<Tooltip content="Timeline">
|
||||
@ -97,20 +99,23 @@ export default function Sidebar() {
|
||||
</div>
|
||||
<SideSheet
|
||||
visible={sidesheet !== SidesheetType.NONE}
|
||||
onCancel={() => setSidesheet(SidesheetType.NONE)}
|
||||
onCancel={() => {
|
||||
setSidesheet(SidesheetType.NONE);
|
||||
}}
|
||||
width={340}
|
||||
title={getTitle(sidesheet)}
|
||||
style={{ paddingBottom: "16px" }}
|
||||
bodyStyle={{ padding: "0px" }}
|
||||
>
|
||||
{getContent(sidesheet)}
|
||||
</SideSheet>
|
||||
</>
|
||||
);
|
||||
|
||||
function getTimeline() {
|
||||
function renderTimeline() {
|
||||
if (undoStack.length > 0) {
|
||||
return (
|
||||
<div>
|
||||
<div className="m-5">
|
||||
<hr />
|
||||
{[...undoStack].reverse().map((e) => (
|
||||
<>
|
||||
@ -125,18 +130,9 @@ export default function Sidebar() {
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<div className="mt-4">
|
||||
<div className="m-5">
|
||||
You havent added anything to your diagram yet.
|
||||
</div>
|
||||
// <Empty
|
||||
// className="mt-5"
|
||||
// image={<IllustrationNoContent style={{ width: 160, height: 160 }} />}
|
||||
// darkModeImage={
|
||||
// <IllustrationNoContentDark style={{ width: 160, height: 160 }} />
|
||||
// }
|
||||
// title="No activity"
|
||||
// description="You have not added anything to your diagram yet."
|
||||
// />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
254
src/components/todo.jsx
Normal file
254
src/components/todo.jsx
Normal file
@ -0,0 +1,254 @@
|
||||
import React, { useContext, useState } from "react";
|
||||
import {
|
||||
Checkbox,
|
||||
Input,
|
||||
TextArea,
|
||||
Row,
|
||||
Col,
|
||||
Dropdown,
|
||||
Button,
|
||||
Popover,
|
||||
Tag,
|
||||
List,
|
||||
RadioGroup,
|
||||
Radio,
|
||||
} from "@douyinfe/semi-ui";
|
||||
import {
|
||||
IconPlus,
|
||||
IconMore,
|
||||
IconDeleteStroked,
|
||||
IconCaretdown,
|
||||
} from "@douyinfe/semi-icons";
|
||||
import { TaskContext } from "../pages/editor";
|
||||
export default function Todo() {
|
||||
const Priority = {
|
||||
NONE: 0,
|
||||
LOW: 1,
|
||||
MEDIUM: 2,
|
||||
HIGH: 3,
|
||||
};
|
||||
const SortOrder = {
|
||||
ORIGINAL: "My order",
|
||||
PRIORITY: "Priority",
|
||||
COMPLETED: "Completed",
|
||||
ALPHABETICALLY: "Alphabetically",
|
||||
};
|
||||
const [activeTask, setActiveTask] = useState(-1);
|
||||
const [, setSortOrder] = useState(SortOrder.ORIGINAL);
|
||||
const { tasks, setTasks, updateTask } = useContext(TaskContext);
|
||||
|
||||
const priorityLabel = (p) => {
|
||||
switch (p) {
|
||||
case Priority.NONE:
|
||||
return "None";
|
||||
case Priority.LOW:
|
||||
return "Low";
|
||||
case Priority.MEDIUM:
|
||||
return "Medium";
|
||||
case Priority.HIGH:
|
||||
return "High";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
const priorityColor = (p) => {
|
||||
switch (p) {
|
||||
case Priority.NONE:
|
||||
return "blue";
|
||||
case Priority.LOW:
|
||||
return "green";
|
||||
case Priority.MEDIUM:
|
||||
return "yellow";
|
||||
case Priority.HIGH:
|
||||
return "red";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
const sort = (s) => {
|
||||
switch (s) {
|
||||
case SortOrder.ORIGINAL:
|
||||
setTasks((prev) => prev.sort((a, b) => a.order - b.order));
|
||||
return;
|
||||
case SortOrder.PRIORITY:
|
||||
setTasks((prev) => prev.sort((a, b) => b.priority - a.priority));
|
||||
return;
|
||||
case SortOrder.COMPLETED:
|
||||
setTasks((prev) =>
|
||||
prev.sort((a, b) => {
|
||||
if (a.complete && !b.complete) {
|
||||
return 1;
|
||||
} else if (!a.complete && b.complete) {
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
})
|
||||
);
|
||||
break;
|
||||
case SortOrder.ALPHABETICALLY:
|
||||
setTasks((prev) => prev.sort((a, b) => a.title.localeCompare(b.title)));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex justify-between items-center mx-5 mb-2">
|
||||
<Dropdown
|
||||
render={
|
||||
<Dropdown.Menu>
|
||||
{Object.values(SortOrder).map((order) => (
|
||||
<Dropdown.Item
|
||||
onClick={() => {
|
||||
setSortOrder(order);
|
||||
sort(order);
|
||||
}}
|
||||
>
|
||||
{order}
|
||||
</Dropdown.Item>
|
||||
))}
|
||||
</Dropdown.Menu>
|
||||
}
|
||||
trigger="click"
|
||||
>
|
||||
<Button
|
||||
style={{ marginRight: "10px" }}
|
||||
theme="borderless"
|
||||
type="tertiary"
|
||||
>
|
||||
Sort by <IconCaretdown />
|
||||
</Button>
|
||||
</Dropdown>
|
||||
<Button
|
||||
icon={<IconPlus />}
|
||||
block
|
||||
onClick={() => {
|
||||
setTasks((prev) => [
|
||||
{
|
||||
complete: false,
|
||||
details: "",
|
||||
title: "",
|
||||
priority: Priority.NONE,
|
||||
order: prev.length,
|
||||
},
|
||||
...prev,
|
||||
]);
|
||||
}}
|
||||
>
|
||||
Add task
|
||||
</Button>
|
||||
</div>
|
||||
<List>
|
||||
{tasks.map((t, i) => (
|
||||
<List.Item
|
||||
key={i}
|
||||
style={{ paddingLeft: "18px", paddingRight: "18px" }}
|
||||
className={`${t.complete ? "bg-emerald-50" : "hover:bg-slate-100"}`}
|
||||
onClick={() => setActiveTask(i)}
|
||||
>
|
||||
<div className="w-full">
|
||||
<Row gutter={6} align="middle" type="flex" className="mb-2">
|
||||
<Col span={2}>
|
||||
<Checkbox
|
||||
checked={t.complete}
|
||||
onChange={(e) =>
|
||||
updateTask(i, { complete: e.target.checked })
|
||||
}
|
||||
></Checkbox>
|
||||
</Col>
|
||||
<Col span={19}>
|
||||
<Input
|
||||
placeholder="Title"
|
||||
onChange={(v) => updateTask(i, { title: v })}
|
||||
value={t.title}
|
||||
></Input>
|
||||
</Col>
|
||||
<Col span={3}>
|
||||
<Popover
|
||||
content={
|
||||
<div className="p-2">
|
||||
<div className="mb-2 font-semibold">Set priority: </div>
|
||||
<RadioGroup
|
||||
onChange={(e) =>
|
||||
updateTask(i, { priority: e.target.value })
|
||||
}
|
||||
value={t.priority}
|
||||
direction="vertical"
|
||||
>
|
||||
<Radio value={Priority.NONE}>
|
||||
<Tag color={priorityColor(Priority.NONE)}>
|
||||
{priorityLabel(Priority.NONE)}
|
||||
</Tag>
|
||||
</Radio>
|
||||
<Radio value={Priority.LOW}>
|
||||
<Tag color={priorityColor(Priority.LOW)}>
|
||||
{priorityLabel(Priority.LOW)}
|
||||
</Tag>
|
||||
</Radio>
|
||||
<Radio value={Priority.MEDIUM}>
|
||||
<Tag color={priorityColor(Priority.MEDIUM)}>
|
||||
{priorityLabel(Priority.MEDIUM)}
|
||||
</Tag>
|
||||
</Radio>
|
||||
<Radio value={Priority.HIGH}>
|
||||
<Tag color={priorityColor(Priority.HIGH)}>
|
||||
{priorityLabel(Priority.HIGH)}
|
||||
</Tag>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
<Button
|
||||
icon={<IconDeleteStroked />}
|
||||
type="danger"
|
||||
block
|
||||
style={{ marginTop: "12px" }}
|
||||
onClick={() =>
|
||||
setTasks((prev) =>
|
||||
prev.filter((task, j) => i !== j)
|
||||
)
|
||||
}
|
||||
>
|
||||
Delete
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
trigger="click"
|
||||
showArrow
|
||||
className="w-[180px]"
|
||||
>
|
||||
<Button icon={<IconMore />} type="tertiary"></Button>
|
||||
</Popover>
|
||||
</Col>
|
||||
</Row>
|
||||
{activeTask === i && (
|
||||
<Row className="mb-2">
|
||||
<Col span={2}></Col>
|
||||
<Col span={22}>
|
||||
<TextArea
|
||||
placeholder="Details"
|
||||
onChange={(v) => updateTask(i, { details: v })}
|
||||
value={t.details}
|
||||
></TextArea>
|
||||
</Col>
|
||||
</Row>
|
||||
)}
|
||||
<Row>
|
||||
<Col span={2}></Col>
|
||||
<Col span={22}>
|
||||
Priority:{" "}
|
||||
<Tag color={priorityColor(t.priority)}>
|
||||
{priorityLabel(t.priority)}
|
||||
</Tag>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</List.Item>
|
||||
))}
|
||||
</List>
|
||||
</>
|
||||
);
|
||||
}
|
@ -19,6 +19,7 @@ export const NoteContext = createContext();
|
||||
export const SettingsContext = createContext();
|
||||
export const UndoRedoContext = createContext();
|
||||
export const SelectContext = createContext();
|
||||
export const TaskContext = createContext();
|
||||
|
||||
export default function Editor(props) {
|
||||
const [tables, setTables] = useState([]);
|
||||
@ -47,6 +48,7 @@ export default function Editor(props) {
|
||||
pan: { x: 0, y: 0 },
|
||||
showGrid: true,
|
||||
});
|
||||
const [tasks, setTasks] = useState([]);
|
||||
const [undoStack, setUndoStack] = useState([]);
|
||||
const [redoStack, setRedoStack] = useState([]);
|
||||
const [selectedElement, setSelectedElement] = useState({
|
||||
@ -386,6 +388,11 @@ export default function Editor(props) {
|
||||
);
|
||||
};
|
||||
|
||||
const updateTask = (id, values) =>
|
||||
setTasks((prev) =>
|
||||
prev.map((task, i) => (id === i ? { ...task, ...values } : task))
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
document.title = "Editor - drawDB";
|
||||
}, []);
|
||||
@ -419,6 +426,9 @@ export default function Editor(props) {
|
||||
>
|
||||
<SelectContext.Provider
|
||||
value={{ selectedElement, setSelectedElement }}
|
||||
>
|
||||
<TaskContext.Provider
|
||||
value={{ tasks, setTasks, updateTask }}
|
||||
>
|
||||
<div className="h-[100vh] overflow-hidden">
|
||||
<ControlPanel />
|
||||
@ -442,6 +452,7 @@ export default function Editor(props) {
|
||||
{layout.services && <Sidebar />}
|
||||
</div>
|
||||
</div>
|
||||
</TaskContext.Provider>
|
||||
</SelectContext.Provider>
|
||||
</UndoRedoContext.Provider>
|
||||
</SettingsContext.Provider>
|
||||
|
Loading…
Reference in New Issue
Block a user