Browse Source

看板编辑和删除

master
YuJian920 3 years ago
parent
commit
be5abce3ed
  1. 21
      src/components/Mark.tsx
  2. 10
      src/hook/useKanban.ts
  3. 10
      src/hook/useTask.ts
  4. 67
      src/pages/Kanban/KanbanColumn/index.tsx
  5. 26
      src/pages/Kanban/TaskModal/index.tsx

21
src/components/Mark.tsx

@ -0,0 +1,21 @@
import React from "react";
const Mark = ({ name, keyword }: { name: string; keyword: string }) => {
const arr = name.split(keyword);
if (!keyword) return <>{name}</>;
else
return (
<>
{arr.map((str, index) => (
<span key={index}>
{str}
{index === arr.length - 1 ? null : (
<span style={{ color: "#257AFD" }}>{keyword}</span>
)}
</span>
))}
</>
);
};
export default React.memo(Mark);

10
src/hook/useKanban.ts

@ -35,3 +35,13 @@ export const useProjectInUrl = () => useProject(useProjectIdInUrl());
export const useKanbanSearchParams = () => ({ projectId: useProjectIdInUrl() }); export const useKanbanSearchParams = () => ({ projectId: useProjectIdInUrl() });
export const useKanbansQueryKey = () => ["kanbans", useKanbanSearchParams()]; export const useKanbansQueryKey = () => ["kanbans", useKanbanSearchParams()];
export const useDeleteKanban = () => {
const request = useRequest();
const queryClient = useQueryClient();
return useMutation(
({ id }: { id: number }) => request(`/kanbans/${id}`, { method: "DELETE" }),
{ onSuccess: () => queryClient.invalidateQueries("kanbans") }
);
};

10
src/hook/useTask.ts

@ -98,3 +98,13 @@ export const useEditTask = () => {
{ onSuccess: () => queryClient.invalidateQueries("tasks") } { onSuccess: () => queryClient.invalidateQueries("tasks") }
); );
}; };
export const useDeleteTask = () => {
const request = useRequest();
const queryClient = useQueryClient();
return useMutation(
({ id }: { id: number }) => request(`/tasks/${id}`, { method: "DELETE" }),
{ onSuccess: () => queryClient.invalidateQueries("tasks") }
);
};

67
src/pages/Kanban/KanbanColumn/index.tsx

@ -1,12 +1,15 @@
import { Card } from "antd"; import { Button, Card, Dropdown, Menu, Modal } from "antd";
import React from "react"; import React from "react";
import { Row } from "../../../components/lib";
import Mark from "../../../components/Mark";
import { useDeleteKanban } from "../../../hook/useKanban";
import { import {
useTaskModal, useTaskModal,
useTasks, useTasks,
useTasksSearchParmas, useTasksSearchParmas,
useTasksTypes, useTasksTypes,
} from "../../../hook/useTask"; } from "../../../hook/useTask";
import { Kanban } from "../../../type"; import { Kanban, Task } from "../../../type";
import CreateTask from "../CreateTask"; import CreateTask from "../CreateTask";
import { Container, TasksContainer } from "../style"; import { Container, TasksContainer } from "../style";
@ -28,24 +31,64 @@ const TaskTypeIcon = ({ id }: { id: number }) => {
); );
}; };
const TaskCard = ({ task }: { task: Task }) => {
const { startEdit } = useTaskModal();
const { name: keyword } = useTasksSearchParmas();
return (
<Card
onClick={() => startEdit(task.id)}
style={{ marginBottom: "0.5rem", cursor: "pointer" }}
key={task.id}
>
<p>
<Mark keyword={keyword} name={task.name} />
</p>
<TaskTypeIcon id={task.typeId} />
</Card>
);
};
const More = ({ kanban }: { kanban: Kanban }) => {
const { mutateAsync, isLoading } = useDeleteKanban();
const startEdit = () => {
Modal.confirm({
okText: "确定",
cancelText: "取消",
title: "确定删除看板吗?",
onOk: () => {
return mutateAsync({ id: kanban.id });
},
});
};
const overlay = (
<Menu>
<Menu.Item>
<Button type="link" onClick={startEdit}>
</Button>
</Menu.Item>
</Menu>
);
return (
<Dropdown overlay={overlay}>
<Button type="link">...</Button>
</Dropdown>
);
};
const KanbanColumn = ({ kanban }: { kanban: Kanban }) => { const KanbanColumn = ({ kanban }: { kanban: Kanban }) => {
const { data: allTasks } = useTasks(useTasksSearchParmas()); const { data: allTasks } = useTasks(useTasksSearchParmas());
const tasks = allTasks?.filter((task) => task.kanbanId === kanban.id); const tasks = allTasks?.filter((task) => task.kanbanId === kanban.id);
const { startEdit } = useTaskModal();
return ( return (
<Container> <Container>
<h3>{kanban.name}</h3> <Row between={true}>
<h3>{kanban.name}</h3>
<More kanban={kanban} />
</Row>
<TasksContainer> <TasksContainer>
{tasks?.map((task) => ( {tasks?.map((task) => (
<Card <TaskCard task={task} />
onClick={() => startEdit(task.id)}
style={{ marginBottom: "0.5rem", cursor: "pointer" }}
key={task.id}
>
<div>{task.name}</div>
<TaskTypeIcon id={task.typeId} />
</Card>
))} ))}
<CreateTask kanbanId={kanban.id} /> <CreateTask kanbanId={kanban.id} />
</TasksContainer> </TasksContainer>

26
src/pages/Kanban/TaskModal/index.tsx

@ -1,7 +1,11 @@
import React, { useEffect } from "react"; import React, { useEffect } from "react";
import { useForm } from "antd/es/form/Form"; import { useForm } from "antd/es/form/Form";
import { useEditTask, useTaskModal } from "../../../hook/useTask"; import {
import { Form, Input, Modal } from "antd"; useDeleteTask,
useEditTask,
useTaskModal,
} from "../../../hook/useTask";
import { Button, Form, Input, Modal } from "antd";
import UserSelect from "../../../components/UserSelect"; import UserSelect from "../../../components/UserSelect";
import TaskTypeSelect from "../../../components/TaskTypeSelect"; import TaskTypeSelect from "../../../components/TaskTypeSelect";
@ -14,6 +18,7 @@ const TaskModal = () => {
const [form] = useForm(); const [form] = useForm();
const { editingTaskId, editingTask, close } = useTaskModal(); const { editingTaskId, editingTask, close } = useTaskModal();
const { mutateAsync: editTask, isLoading: editLoading } = useEditTask(); const { mutateAsync: editTask, isLoading: editLoading } = useEditTask();
const { mutateAsync: deleteTask } = useDeleteTask();
const onCancel = () => { const onCancel = () => {
close(); close();
@ -29,6 +34,18 @@ const TaskModal = () => {
form.setFieldsValue(editingTask); form.setFieldsValue(editingTask);
}, [form, editingTask]); }, [form, editingTask]);
const startDelete = () => {
close();
Modal.confirm({
okText: "确定",
cancelText: "取消",
title: "确定删除任务吗?",
onOk() {
return deleteTask({ id: Number(editingTaskId) });
},
});
};
return ( return (
<Modal <Modal
forceRender={true} forceRender={true}
@ -55,6 +72,11 @@ const TaskModal = () => {
<TaskTypeSelect /> <TaskTypeSelect />
</Form.Item> </Form.Item>
</Form> </Form>
<div style={{ textAlign: "right" }}>
<Button style={{ fontSize: "14px" }} size="small" onClick={startDelete}>
</Button>
</div>
</Modal> </Modal>
); );
}; };

Loading…
Cancel
Save