Browse Source

引入 DND 实现拖拽

master
YuJian920 3 years ago
parent
commit
c51082a04a
  1. 4
      package.json
  2. 46
      src/components/DragAndDrop.tsx
  3. 14
      src/pages/Kanban/KanbanColumn/index.tsx
  4. 18
      src/pages/Kanban/index.tsx
  5. 1
      src/pages/Kanban/style.ts
  6. 21
      src/type/index.ts
  7. 92
      yarn.lock

4
package.json

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
"jira-dev-tool": "^1.6.59",
"qs": "^6.10.3",
"react": "^17.0.2",
"react-beautiful-dnd": "^13.1.0",
"react-dom": "^17.0.2",
"react-query": "^3.34.16",
"react-router": "6",
@ -53,5 +54,8 @@ @@ -53,5 +54,8 @@
},
"msw": {
"workerDirectory": "public"
},
"devDependencies": {
"@types/react-beautiful-dnd": "^13.1.2"
}
}

46
src/components/DragAndDrop.tsx

@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
import React from "react";
import { Draggable, Droppable } from "react-beautiful-dnd";
import { DragProps, DropChildrenProps, DropProps } from "../type";
export const Drop = ({ children, ...props }: DropProps) => {
return (
<Droppable {...props}>
{(provided) => {
if (React.isValidElement(children)) {
return React.cloneElement(children, {
...provided.droppableProps,
ref: provided.innerRef,
provided,
});
}
return <div />;
}}
</Droppable>
);
};
export const DropChild = React.forwardRef<HTMLDivElement, DropChildrenProps>(
({ children, ...props }, ref) => (
<div ref={ref} {...props}>
{children}
{props.provided?.placeholder}
</div>
)
);
export const Drag = ({ children, ...props }: DragProps) => {
return (
<Draggable {...props}>
{(provided) => {
if (React.isValidElement(children)) {
return React.cloneElement(children, {
...provided.draggableProps,
...provided.dragHandleProps,
ref: provided.innerRef,
});
}
return <div />;
}}
</Draggable>
);
};

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

@ -49,7 +49,7 @@ const TaskCard = ({ task }: { task: Task }) => { @@ -49,7 +49,7 @@ const TaskCard = ({ task }: { task: Task }) => {
};
const More = ({ kanban }: { kanban: Kanban }) => {
const { mutateAsync, isLoading } = useDeleteKanban();
const { mutateAsync } = useDeleteKanban();
const startEdit = () => {
Modal.confirm({
okText: "确定",
@ -76,24 +76,26 @@ const More = ({ kanban }: { kanban: Kanban }) => { @@ -76,24 +76,26 @@ const More = ({ kanban }: { kanban: Kanban }) => {
);
};
const KanbanColumn = ({ kanban }: { kanban: Kanban }) => {
const KanbanColumn = React.forwardRef<HTMLDivElement, { kanban: Kanban }>(
({ kanban, ...props }, ref) => {
const { data: allTasks } = useTasks(useTasksSearchParmas());
const tasks = allTasks?.filter((task) => task.kanbanId === kanban.id);
return (
<Container>
<Container {...props} ref={ref}>
<Row between={true}>
<h3>{kanban.name}</h3>
<More kanban={kanban} />
<More kanban={kanban} key={kanban.id} />
</Row>
<TasksContainer>
{tasks?.map((task) => (
<TaskCard task={task} />
<TaskCard key={task.id} task={task} />
))}
<CreateTask kanbanId={kanban.id} />
</TasksContainer>
</Container>
);
};
}
);
export default React.memo(KanbanColumn);

18
src/pages/Kanban/index.tsx

@ -1,5 +1,7 @@ @@ -1,5 +1,7 @@
import { Spin } from "antd";
import React from "react";
import { DragDropContext } from "react-beautiful-dnd";
import { Drag, Drop, DropChild } from "../../components/DragAndDrop";
import useDocumentTitle from "../../hook/useDocumentTitle";
import {
useKanbans,
@ -24,6 +26,7 @@ const Kanban = () => { @@ -24,6 +26,7 @@ const Kanban = () => {
const isLoading = taskIsLoading || kanbanIsLoading;
return (
<DragDropContext onDragEnd={() => {}}>
<ScreenContainer>
<h1>{currentProject?.name}</h1>
<SearchPanel />
@ -31,14 +34,25 @@ const Kanban = () => { @@ -31,14 +34,25 @@ const Kanban = () => {
<Spin size="large" />
) : (
<ColumnsContainer>
{kanbans?.map((kanban) => (
<KanbanColumn kanban={kanban} key={kanban.id} />
<Drop type="COLUMN" direction="horizontal" droppableId="kanban">
<DropChild style={{ display: "flex" }}>
{kanbans?.map((kanban, index) => (
<Drag
key={kanban.id}
draggableId={"kanban" + kanban.id}
index={index}
>
<KanbanColumn kanban={kanban} />
</Drag>
))}
</DropChild>
</Drop>
<CreateKanban />
</ColumnsContainer>
)}
<TaskModal />
</ScreenContainer>
</DragDropContext>
);
};

1
src/pages/Kanban/style.ts

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
import styled from "@emotion/styled";
import { DropChild } from "../../components/DragAndDrop";
export const ScreenContainer = styled.div`
padding: 3.2rem;

21
src/type/index.ts

@ -1,3 +1,11 @@ @@ -1,3 +1,11 @@
import React, { ReactNode } from "react";
import {
DraggableProps,
DroppableProps,
DroppableProvided,
DroppableProvidedProps,
} from "react-beautiful-dnd";
export interface User {
id: number;
name: string;
@ -37,3 +45,16 @@ export interface TaskType { @@ -37,3 +45,16 @@ export interface TaskType {
id: number;
name: string;
}
export type DropProps = Omit<DroppableProps, "children"> & {
children: ReactNode;
};
export type DropChildrenProps = Partial<
{ provided: DroppableProvided } & DroppableProvidedProps
> &
React.HtmlHTMLAttributes<HTMLDivElement>;
export type DragProps = Omit<DraggableProps, "children"> & {
children: ReactNode;
};

92
yarn.lock

@ -1058,7 +1058,7 @@ @@ -1058,7 +1058,7 @@
core-js-pure "^3.20.2"
regenerator-runtime "^0.13.4"
"@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.4", "@babel/runtime@^7.10.5", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.16.3", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2":
"@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.4", "@babel/runtime@^7.10.5", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.15.4", "@babel/runtime@^7.16.3", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2":
version "7.17.8"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.8.tgz#3e56e4aff81befa55ac3ac6a0967349fd1c5bca2"
integrity sha512-dQpEpK0O9o6lj6oPu0gRDbbnk+4LeHlNcBpspf6Olzt3GIX4P1lWF1gS+pHLDFlaJvbR6q7jCfQ08zA4QJBnmA==
@ -1947,6 +1947,14 @@ @@ -1947,6 +1947,14 @@
dependencies:
"@types/node" "*"
"@types/hoist-non-react-statics@^3.3.0":
version "3.3.1"
resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"
integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==
dependencies:
"@types/react" "*"
hoist-non-react-statics "^3.3.0"
"@types/html-minifier-terser@^6.0.0":
version "6.1.0"
resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35"
@ -2041,6 +2049,13 @@ @@ -2041,6 +2049,13 @@
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc"
integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==
"@types/react-beautiful-dnd@^13.1.2":
version "13.1.2"
resolved "https://registry.yarnpkg.com/@types/react-beautiful-dnd/-/react-beautiful-dnd-13.1.2.tgz#510405abb09f493afdfd898bf83995dc6385c130"
integrity sha512-+OvPkB8CdE/bGdXKyIhc/Lm2U7UAYCCJgsqmopFmh9gbAudmslkI8eOrPDjg4JhwSE6wytz4a3/wRjKtovHVJg==
dependencies:
"@types/react" "*"
"@types/react-dom@*", "@types/react-dom@^17.0.14":
version "17.0.14"
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.14.tgz#c8f917156b652ddf807711f5becbd2ab018dea9f"
@ -2048,6 +2063,16 @@ @@ -2048,6 +2063,16 @@
dependencies:
"@types/react" "*"
"@types/react-redux@^7.1.20":
version "7.1.23"
resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.23.tgz#3c2bb1bcc698ae69d70735f33c5a8e95f41ac528"
integrity sha512-D02o3FPfqQlfu2WeEYwh3x2otYd2Dk1o8wAfsA0B1C2AJEFxE663Ozu7JzuWbznGgW248NaOF6wsqCGNq9d3qw==
dependencies:
"@types/hoist-non-react-statics" "^3.3.0"
"@types/react" "*"
hoist-non-react-statics "^3.3.0"
redux "^4.0.0"
"@types/react@*", "@types/react@^17.0.41":
version "17.0.41"
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.41.tgz#6e179590d276394de1e357b3f89d05d7d3da8b85"
@ -3442,6 +3467,13 @@ css-blank-pseudo@^3.0.3: @@ -3442,6 +3467,13 @@ css-blank-pseudo@^3.0.3:
dependencies:
postcss-selector-parser "^6.0.9"
css-box-model@^1.2.0:
version "1.2.1"
resolved "https://registry.yarnpkg.com/css-box-model/-/css-box-model-1.2.1.tgz#59951d3b81fd6b2074a62d49444415b0d2b4d7c1"
integrity sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==
dependencies:
tiny-invariant "^1.0.6"
css-declaration-sorter@^6.0.3:
version "6.1.4"
resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.1.4.tgz#b9bfb4ed9a41f8dcca9bf7184d849ea94a8294b4"
@ -4883,7 +4915,7 @@ history@^5.2.0: @@ -4883,7 +4915,7 @@ history@^5.2.0:
dependencies:
"@babel/runtime" "^7.7.6"
hoist-non-react-statics@^3.3.1:
hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2:
version "3.3.2"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
@ -6262,6 +6294,11 @@ memfs@^3.1.2, memfs@^3.4.1: @@ -6262,6 +6294,11 @@ memfs@^3.1.2, memfs@^3.4.1:
dependencies:
fs-monkey "1.0.3"
memoize-one@^5.1.1:
version "5.2.1"
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e"
integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==
memoize-one@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-6.0.0.tgz#b2591b871ed82948aee4727dc6abceeeac8c1045"
@ -7481,7 +7518,7 @@ prompts@^2.0.1, prompts@^2.4.2: @@ -7481,7 +7518,7 @@ prompts@^2.0.1, prompts@^2.4.2:
kleur "^3.0.3"
sisteransi "^1.0.5"
prop-types@^15.8.1:
prop-types@^15.7.2, prop-types@^15.8.1:
version "15.8.1"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
@ -7540,6 +7577,11 @@ quick-lru@^5.1.1: @@ -7540,6 +7577,11 @@ quick-lru@^5.1.1:
resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932"
integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==
raf-schd@^4.0.2:
version "4.0.3"
resolved "https://registry.yarnpkg.com/raf-schd/-/raf-schd-4.0.3.tgz#5d6c34ef46f8b2a0e880a8fcdb743efc5bfdbc1a"
integrity sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==
raf@^3.4.1:
version "3.4.1"
resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39"
@ -7951,6 +7993,19 @@ react-app-polyfill@^3.0.0: @@ -7951,6 +7993,19 @@ react-app-polyfill@^3.0.0:
regenerator-runtime "^0.13.9"
whatwg-fetch "^3.6.2"
react-beautiful-dnd@^13.1.0:
version "13.1.0"
resolved "https://registry.yarnpkg.com/react-beautiful-dnd/-/react-beautiful-dnd-13.1.0.tgz#ec97c81093593526454b0de69852ae433783844d"
integrity sha512-aGvblPZTJowOWUNiwd6tNfEpgkX5OxmpqxHKNW/4VmvZTNTbeiq7bA3bn5T+QSF2uibXB0D1DmJsb1aC/+3cUA==
dependencies:
"@babel/runtime" "^7.9.2"
css-box-model "^1.2.0"
memoize-one "^5.1.1"
raf-schd "^4.0.2"
react-redux "^7.2.0"
redux "^4.0.4"
use-memo-one "^1.1.1"
react-dev-utils@^12.0.0:
version "12.0.0"
resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-12.0.0.tgz#4eab12cdb95692a077616770b5988f0adf806526"
@ -8000,7 +8055,7 @@ react-is@^16.12.0, react-is@^16.13.1, react-is@^16.7.0: @@ -8000,7 +8055,7 @@ react-is@^16.12.0, react-is@^16.13.1, react-is@^16.7.0:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
react-is@^17.0.1:
react-is@^17.0.1, react-is@^17.0.2:
version "17.0.2"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
@ -8028,6 +8083,18 @@ react-query@^3.34.16, react-query@^3.5.10: @@ -8028,6 +8083,18 @@ react-query@^3.34.16, react-query@^3.5.10:
broadcast-channel "^3.4.1"
match-sorter "^6.0.2"
react-redux@^7.2.0:
version "7.2.8"
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.8.tgz#a894068315e65de5b1b68899f9c6ee0923dd28de"
integrity sha512-6+uDjhs3PSIclqoCk0kd6iX74gzrGc3W5zcAjbrFgEdIjRSQObdIwfx80unTkVUYvbQ95Y8Av3OvFHq1w5EOUw==
dependencies:
"@babel/runtime" "^7.15.4"
"@types/react-redux" "^7.1.20"
hoist-non-react-statics "^3.3.2"
loose-envify "^1.4.0"
prop-types "^15.7.2"
react-is "^17.0.2"
react-refresh@^0.11.0:
version "0.11.0"
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.11.0.tgz#77198b944733f0f1f1a90e791de4541f9f074046"
@ -8155,6 +8222,13 @@ redent@^3.0.0: @@ -8155,6 +8222,13 @@ redent@^3.0.0:
indent-string "^4.0.0"
strip-indent "^3.0.0"
redux@^4.0.0, redux@^4.0.4:
version "4.1.2"
resolved "https://registry.yarnpkg.com/redux/-/redux-4.1.2.tgz#140f35426d99bb4729af760afcf79eaaac407104"
integrity sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw==
dependencies:
"@babel/runtime" "^7.9.2"
regenerate-unicode-properties@^10.0.1:
version "10.0.1"
resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz#7f442732aa7934a3740c779bb9b3340dccc1fb56"
@ -9060,6 +9134,11 @@ timsort@^0.3.0: @@ -9060,6 +9134,11 @@ timsort@^0.3.0:
resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4"
integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=
tiny-invariant@^1.0.6:
version "1.2.0"
resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.2.0.tgz#a1141f86b672a9148c72e978a19a73b9b94a15a9"
integrity sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg==
[email protected]:
version "1.0.5"
resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc"
@ -9300,6 +9379,11 @@ uri-js@^4.2.2: @@ -9300,6 +9379,11 @@ uri-js@^4.2.2:
dependencies:
punycode "^2.1.0"
use-memo-one@^1.1.1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/use-memo-one/-/use-memo-one-1.1.2.tgz#0c8203a329f76e040047a35a1197defe342fab20"
integrity sha512-u2qFKtxLsia/r8qG0ZKkbytbztzRb317XCkT7yP8wxL0tZ/CzK2G+WWie5vWvpyeP7+YoPIwbJoIHJ4Ba4k0oQ==
util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"

Loading…
Cancel
Save