mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
fix: drag and drop function (#815)
* fix: kanban drag and drop * fix: kanban board issue dnd mutation
This commit is contained in:
parent
6de94efc7d
commit
3fa6185b63
@ -108,7 +108,9 @@ export const SingleBoard: React.FC<Props> = ({
|
||||
key={issue.id}
|
||||
draggableId={issue.id}
|
||||
index={index}
|
||||
isDragDisabled={isNotAllowed || selectedGroup === "created_by"}
|
||||
isDragDisabled={
|
||||
isNotAllowed || selectedGroup === "created_by" || selectedGroup === "labels"
|
||||
}
|
||||
>
|
||||
{(provided, snapshot) => (
|
||||
<SingleBoardIssue
|
||||
|
@ -50,7 +50,6 @@ import {
|
||||
MODULE_ISSUES_WITH_PARAMS,
|
||||
PROJECT_ISSUES_LIST_WITH_PARAMS,
|
||||
} from "constants/fetch-keys";
|
||||
import useEstimateOption from "hooks/use-estimate-option";
|
||||
|
||||
type Props = {
|
||||
type?: string;
|
||||
@ -93,8 +92,6 @@ export const SingleBoardIssue: React.FC<Props> = ({
|
||||
|
||||
const { orderBy, params } = useIssuesView();
|
||||
|
||||
const { estimateValue } = useEstimateOption(issue.estimate_point);
|
||||
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId, cycleId, moduleId } = router.query;
|
||||
|
||||
@ -113,7 +110,14 @@ export const SingleBoardIssue: React.FC<Props> = ({
|
||||
>(
|
||||
CYCLE_ISSUES_WITH_PARAMS(cycleId as string, params),
|
||||
(prevData) =>
|
||||
handleIssuesMutation(formData, groupTitle ?? "", selectedGroup, index, prevData),
|
||||
handleIssuesMutation(
|
||||
formData,
|
||||
groupTitle ?? "",
|
||||
selectedGroup,
|
||||
index,
|
||||
orderBy,
|
||||
prevData
|
||||
),
|
||||
false
|
||||
);
|
||||
else if (moduleId)
|
||||
@ -125,10 +129,17 @@ export const SingleBoardIssue: React.FC<Props> = ({
|
||||
>(
|
||||
MODULE_ISSUES_WITH_PARAMS(moduleId as string),
|
||||
(prevData) =>
|
||||
handleIssuesMutation(formData, groupTitle ?? "", selectedGroup, index, prevData),
|
||||
handleIssuesMutation(
|
||||
formData,
|
||||
groupTitle ?? "",
|
||||
selectedGroup,
|
||||
index,
|
||||
orderBy,
|
||||
prevData
|
||||
),
|
||||
false
|
||||
);
|
||||
else
|
||||
else {
|
||||
mutate<
|
||||
| {
|
||||
[key: string]: IIssue[];
|
||||
@ -136,10 +147,21 @@ export const SingleBoardIssue: React.FC<Props> = ({
|
||||
| IIssue[]
|
||||
>(
|
||||
PROJECT_ISSUES_LIST_WITH_PARAMS(projectId as string, params),
|
||||
(prevData) =>
|
||||
handleIssuesMutation(formData, groupTitle ?? "", selectedGroup, index, prevData),
|
||||
(prevData) => {
|
||||
if (!prevData) return prevData;
|
||||
|
||||
return handleIssuesMutation(
|
||||
formData,
|
||||
groupTitle ?? "",
|
||||
selectedGroup,
|
||||
index,
|
||||
orderBy,
|
||||
prevData
|
||||
);
|
||||
},
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
issuesService
|
||||
.patchIssue(workspaceSlug as string, projectId as string, issue.id, formData)
|
||||
@ -156,7 +178,18 @@ export const SingleBoardIssue: React.FC<Props> = ({
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
[workspaceSlug, projectId, cycleId, moduleId, issue, groupTitle, index, selectedGroup, params]
|
||||
[
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
cycleId,
|
||||
moduleId,
|
||||
issue,
|
||||
groupTitle,
|
||||
index,
|
||||
selectedGroup,
|
||||
orderBy,
|
||||
params,
|
||||
]
|
||||
);
|
||||
|
||||
const getStyle = (
|
||||
|
@ -48,6 +48,7 @@ import {
|
||||
} from "constants/fetch-keys";
|
||||
// image
|
||||
import emptyCycle from "public/empty-state/empty-cycle.svg";
|
||||
import { orderArrayBy } from "helpers/array.helper";
|
||||
|
||||
type Props = {
|
||||
type?: "issue" | "cycle" | "module";
|
||||
@ -208,8 +209,8 @@ export const IssuesView: React.FC<Props> = ({
|
||||
|
||||
return {
|
||||
...prevData,
|
||||
[sourceGroup]: sourceGroupArray,
|
||||
[destinationGroup]: destinationGroupArray,
|
||||
[sourceGroup]: orderArrayBy(sourceGroupArray, orderBy),
|
||||
[destinationGroup]: orderArrayBy(destinationGroupArray, orderBy),
|
||||
};
|
||||
},
|
||||
false
|
||||
@ -230,8 +231,8 @@ export const IssuesView: React.FC<Props> = ({
|
||||
|
||||
return {
|
||||
...prevData,
|
||||
[sourceGroup]: sourceGroupArray,
|
||||
[destinationGroup]: destinationGroupArray,
|
||||
[sourceGroup]: orderArrayBy(sourceGroupArray, orderBy),
|
||||
[destinationGroup]: orderArrayBy(destinationGroupArray, orderBy),
|
||||
};
|
||||
},
|
||||
false
|
||||
@ -250,8 +251,8 @@ export const IssuesView: React.FC<Props> = ({
|
||||
|
||||
return {
|
||||
...prevData,
|
||||
[sourceGroup]: sourceGroupArray,
|
||||
[destinationGroup]: destinationGroupArray,
|
||||
[sourceGroup]: orderArrayBy(sourceGroupArray, orderBy),
|
||||
[destinationGroup]: orderArrayBy(destinationGroupArray, orderBy),
|
||||
};
|
||||
},
|
||||
false
|
||||
|
@ -29,7 +29,7 @@ import {
|
||||
TrashIcon,
|
||||
XMarkIcon,
|
||||
ArrowTopRightOnSquareIcon,
|
||||
PaperClipIcon
|
||||
PaperClipIcon,
|
||||
} from "@heroicons/react/24/outline";
|
||||
// helpers
|
||||
import { copyTextToClipboard, truncateText } from "helpers/string.helper";
|
||||
@ -82,7 +82,7 @@ export const SingleListIssue: React.FC<Props> = ({
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const { groupByProperty: selectedGroup, params } = useIssueView();
|
||||
const { groupByProperty: selectedGroup, orderBy, params } = useIssueView();
|
||||
|
||||
const partialUpdateIssue = useCallback(
|
||||
(formData: Partial<IIssue>) => {
|
||||
@ -97,7 +97,14 @@ export const SingleListIssue: React.FC<Props> = ({
|
||||
>(
|
||||
CYCLE_ISSUES_WITH_PARAMS(cycleId as string, params),
|
||||
(prevData) =>
|
||||
handleIssuesMutation(formData, groupTitle ?? "", selectedGroup, index, prevData),
|
||||
handleIssuesMutation(
|
||||
formData,
|
||||
groupTitle ?? "",
|
||||
selectedGroup,
|
||||
index,
|
||||
orderBy,
|
||||
prevData
|
||||
),
|
||||
false
|
||||
);
|
||||
|
||||
@ -110,7 +117,14 @@ export const SingleListIssue: React.FC<Props> = ({
|
||||
>(
|
||||
MODULE_ISSUES_WITH_PARAMS(moduleId as string, params),
|
||||
(prevData) =>
|
||||
handleIssuesMutation(formData, groupTitle ?? "", selectedGroup, index, prevData),
|
||||
handleIssuesMutation(
|
||||
formData,
|
||||
groupTitle ?? "",
|
||||
selectedGroup,
|
||||
index,
|
||||
orderBy,
|
||||
prevData
|
||||
),
|
||||
false
|
||||
);
|
||||
|
||||
@ -122,7 +136,7 @@ export const SingleListIssue: React.FC<Props> = ({
|
||||
>(
|
||||
PROJECT_ISSUES_LIST_WITH_PARAMS(projectId as string, params),
|
||||
(prevData) =>
|
||||
handleIssuesMutation(formData, groupTitle ?? "", selectedGroup, index, prevData),
|
||||
handleIssuesMutation(formData, groupTitle ?? "", selectedGroup, index, orderBy, prevData),
|
||||
false
|
||||
);
|
||||
|
||||
@ -138,7 +152,18 @@ export const SingleListIssue: React.FC<Props> = ({
|
||||
} else mutate(PROJECT_ISSUES_LIST_WITH_PARAMS(projectId as string, params));
|
||||
});
|
||||
},
|
||||
[workspaceSlug, projectId, cycleId, moduleId, issue, groupTitle, index, selectedGroup, params]
|
||||
[
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
cycleId,
|
||||
moduleId,
|
||||
issue,
|
||||
groupTitle,
|
||||
index,
|
||||
selectedGroup,
|
||||
orderBy,
|
||||
params,
|
||||
]
|
||||
);
|
||||
|
||||
const handleCopyText = () => {
|
||||
|
@ -37,6 +37,7 @@ export const FILTER_ISSUE_OPTIONS: Array<{
|
||||
},
|
||||
];
|
||||
|
||||
import { orderArrayBy } from "helpers/array.helper";
|
||||
import { IIssue, TIssueGroupByOptions, TIssueOrderByOptions } from "types";
|
||||
|
||||
type THandleIssuesMutation = (
|
||||
@ -44,6 +45,7 @@ type THandleIssuesMutation = (
|
||||
oldGroupTitle: string,
|
||||
selectedGroupBy: TIssueGroupByOptions,
|
||||
issueIndex: number,
|
||||
orderBy: TIssueOrderByOptions,
|
||||
prevData?:
|
||||
| {
|
||||
[key: string]: IIssue[];
|
||||
@ -61,6 +63,7 @@ export const handleIssuesMutation: THandleIssuesMutation = (
|
||||
oldGroupTitle,
|
||||
selectedGroupBy,
|
||||
issueIndex,
|
||||
orderBy,
|
||||
prevData
|
||||
) => {
|
||||
if (!prevData) return prevData;
|
||||
@ -89,15 +92,24 @@ export const handleIssuesMutation: THandleIssuesMutation = (
|
||||
assignees: formData?.assignees_list ?? oldGroup[issueIndex]?.assignees_list,
|
||||
};
|
||||
|
||||
oldGroup.splice(issueIndex, 1);
|
||||
newGroup.push(updatedIssue);
|
||||
if (selectedGroupBy !== Object.keys(formData)[0])
|
||||
return {
|
||||
...prevData,
|
||||
[oldGroupTitle ?? ""]: orderArrayBy(
|
||||
oldGroup.map((i) => (i.id === updatedIssue.id ? updatedIssue : i)),
|
||||
orderBy
|
||||
),
|
||||
};
|
||||
|
||||
const groupThatIsUpdated = selectedGroupBy === "priority" ? formData.priority : formData.state;
|
||||
|
||||
return {
|
||||
...prevData,
|
||||
[oldGroupTitle ?? ""]: oldGroup,
|
||||
[groupThatIsUpdated ?? ""]: newGroup,
|
||||
[oldGroupTitle ?? ""]: orderArrayBy(
|
||||
oldGroup.filter((i) => i.id !== updatedIssue.id),
|
||||
orderBy
|
||||
),
|
||||
[groupThatIsUpdated ?? ""]: orderArrayBy([...newGroup, updatedIssue], orderBy),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
@ -12,7 +12,13 @@ export const orderArrayBy = (
|
||||
key: string,
|
||||
ordering: "ascending" | "descending" = "ascending"
|
||||
) => {
|
||||
if (key[0] === "-") {
|
||||
ordering = "descending";
|
||||
key = key.slice(1);
|
||||
}
|
||||
|
||||
const innerKey = key.split("."); // split the key by dot
|
||||
|
||||
return array.sort((a, b) => {
|
||||
const keyA = innerKey.reduce((obj, i) => obj[i], a); // get the value of the inner key
|
||||
const keyB = innerKey.reduce((obj, i) => obj[i], b); // get the value of the inner key
|
||||
|
Loading…
Reference in New Issue
Block a user