diff --git a/apps/app/components/core/board-view/single-board.tsx b/apps/app/components/core/board-view/single-board.tsx index f408bc38b..99ec0029f 100644 --- a/apps/app/components/core/board-view/single-board.tsx +++ b/apps/app/components/core/board-view/single-board.tsx @@ -108,7 +108,9 @@ export const SingleBoard: React.FC = ({ key={issue.id} draggableId={issue.id} index={index} - isDragDisabled={isNotAllowed || selectedGroup === "created_by"} + isDragDisabled={ + isNotAllowed || selectedGroup === "created_by" || selectedGroup === "labels" + } > {(provided, snapshot) => ( = ({ 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 = ({ >( 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 = ({ >( 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 = ({ | 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 = ({ console.log(error); }); }, - [workspaceSlug, projectId, cycleId, moduleId, issue, groupTitle, index, selectedGroup, params] + [ + workspaceSlug, + projectId, + cycleId, + moduleId, + issue, + groupTitle, + index, + selectedGroup, + orderBy, + params, + ] ); const getStyle = ( diff --git a/apps/app/components/core/issues-view.tsx b/apps/app/components/core/issues-view.tsx index 1171371a9..785aa5b4f 100644 --- a/apps/app/components/core/issues-view.tsx +++ b/apps/app/components/core/issues-view.tsx @@ -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 = ({ return { ...prevData, - [sourceGroup]: sourceGroupArray, - [destinationGroup]: destinationGroupArray, + [sourceGroup]: orderArrayBy(sourceGroupArray, orderBy), + [destinationGroup]: orderArrayBy(destinationGroupArray, orderBy), }; }, false @@ -230,8 +231,8 @@ export const IssuesView: React.FC = ({ return { ...prevData, - [sourceGroup]: sourceGroupArray, - [destinationGroup]: destinationGroupArray, + [sourceGroup]: orderArrayBy(sourceGroupArray, orderBy), + [destinationGroup]: orderArrayBy(destinationGroupArray, orderBy), }; }, false @@ -250,8 +251,8 @@ export const IssuesView: React.FC = ({ return { ...prevData, - [sourceGroup]: sourceGroupArray, - [destinationGroup]: destinationGroupArray, + [sourceGroup]: orderArrayBy(sourceGroupArray, orderBy), + [destinationGroup]: orderArrayBy(destinationGroupArray, orderBy), }; }, false @@ -482,24 +483,24 @@ export const IssuesView: React.FC = ({ <> {isCompleted && setTransferIssuesModal(true)} />} {issueView === "list" ? ( - + ) : issueView === "kanban" ? ( = ({ const { setToastAlert } = useToast(); - const { groupByProperty: selectedGroup, params } = useIssueView(); + const { groupByProperty: selectedGroup, orderBy, params } = useIssueView(); const partialUpdateIssue = useCallback( (formData: Partial) => { @@ -97,7 +97,14 @@ export const SingleListIssue: React.FC = ({ >( 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 = ({ >( 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 = ({ >( 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 = ({ } 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 = () => { diff --git a/apps/app/constants/issue.ts b/apps/app/constants/issue.ts index a9a39620a..f113aea9a 100644 --- a/apps/app/constants/issue.ts +++ b/apps/app/constants/issue.ts @@ -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), }; } }; diff --git a/apps/app/helpers/array.helper.ts b/apps/app/helpers/array.helper.ts index d4d2c994c..50c35ec81 100644 --- a/apps/app/helpers/array.helper.ts +++ b/apps/app/helpers/array.helper.ts @@ -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