forked from github/plane
fix: drag and drop implementation in calendar layout and kanban layout (#2921)
* fix profile issue filters and kanban * chore: calendar drag and drop * chore: kanban drag and drop * dev: remove issue from the kanban layout and resolved build errors --------- Co-authored-by: rahulramesha <rahulramesham@gmail.com>
This commit is contained in:
parent
e16e468b8f
commit
011db50da6
@ -37,10 +37,12 @@ interface IBaseCalendarRoot {
|
|||||||
[EIssueActions.REMOVE]?: (issue: IIssue) => void;
|
[EIssueActions.REMOVE]?: (issue: IIssue) => void;
|
||||||
};
|
};
|
||||||
viewId?: string;
|
viewId?: string;
|
||||||
|
handleDragDrop: (source: any, destination: any, issues: any, issueWithIds: any) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const BaseCalendarRoot = observer((props: IBaseCalendarRoot) => {
|
export const BaseCalendarRoot = observer((props: IBaseCalendarRoot) => {
|
||||||
const { issueStore, issuesFilterStore, calendarViewStore, QuickActions, issueActions, viewId } = props;
|
const { issueStore, issuesFilterStore, calendarViewStore, QuickActions, issueActions, viewId, handleDragDrop } =
|
||||||
|
props;
|
||||||
|
|
||||||
const displayFilters = issuesFilterStore.issueFilters?.displayFilters;
|
const displayFilters = issuesFilterStore.issueFilters?.displayFilters;
|
||||||
|
|
||||||
@ -56,7 +58,7 @@ export const BaseCalendarRoot = observer((props: IBaseCalendarRoot) => {
|
|||||||
// return if dropped on the same date
|
// return if dropped on the same date
|
||||||
if (result.destination.droppableId === result.source.droppableId) return;
|
if (result.destination.droppableId === result.source.droppableId) return;
|
||||||
|
|
||||||
calendarViewStore?.handleDragDrop(result.source, result.destination);
|
if (handleDragDrop) handleDragDrop(result.source, result.destination, issues, groupedIssueIds);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleIssues = useCallback(
|
const handleIssues = useCallback(
|
||||||
|
@ -14,10 +14,15 @@ export const CycleCalendarLayout: React.FC = observer(() => {
|
|||||||
cycleIssues: cycleIssueStore,
|
cycleIssues: cycleIssueStore,
|
||||||
cycleIssuesFilter: cycleIssueFilterStore,
|
cycleIssuesFilter: cycleIssueFilterStore,
|
||||||
cycleIssueCalendarView: cycleIssueCalendarViewStore,
|
cycleIssueCalendarView: cycleIssueCalendarViewStore,
|
||||||
|
calendarHelpers: calendarHelperStore,
|
||||||
} = useMobxStore();
|
} = useMobxStore();
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, cycleId } = router.query as { workspaceSlug: string; cycleId: string };
|
const { workspaceSlug, projectId, cycleId } = router.query as {
|
||||||
|
workspaceSlug: string;
|
||||||
|
projectId: string;
|
||||||
|
cycleId: string;
|
||||||
|
};
|
||||||
|
|
||||||
const issueActions = {
|
const issueActions = {
|
||||||
[EIssueActions.UPDATE]: async (issue: IIssue) => {
|
[EIssueActions.UPDATE]: async (issue: IIssue) => {
|
||||||
@ -35,6 +40,20 @@ export const CycleCalendarLayout: React.FC = observer(() => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleDragDrop = (source: any, destination: any, issues: IIssue[], issueWithIds: any) => {
|
||||||
|
if (calendarHelperStore.handleDragDrop)
|
||||||
|
calendarHelperStore.handleDragDrop(
|
||||||
|
source,
|
||||||
|
destination,
|
||||||
|
workspaceSlug,
|
||||||
|
projectId,
|
||||||
|
cycleIssueStore,
|
||||||
|
issues,
|
||||||
|
issueWithIds,
|
||||||
|
cycleId
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseCalendarRoot
|
<BaseCalendarRoot
|
||||||
issueStore={cycleIssueStore}
|
issueStore={cycleIssueStore}
|
||||||
@ -43,6 +62,7 @@ export const CycleCalendarLayout: React.FC = observer(() => {
|
|||||||
QuickActions={CycleIssueQuickActions}
|
QuickActions={CycleIssueQuickActions}
|
||||||
issueActions={issueActions}
|
issueActions={issueActions}
|
||||||
viewId={cycleId}
|
viewId={cycleId}
|
||||||
|
handleDragDrop={handleDragDrop}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -14,10 +14,15 @@ export const ModuleCalendarLayout: React.FC = observer(() => {
|
|||||||
moduleIssues: moduleIssueStore,
|
moduleIssues: moduleIssueStore,
|
||||||
moduleIssuesFilter: moduleIssueFilterStore,
|
moduleIssuesFilter: moduleIssueFilterStore,
|
||||||
moduleIssueCalendarView: moduleIssueCalendarViewStore,
|
moduleIssueCalendarView: moduleIssueCalendarViewStore,
|
||||||
|
calendarHelpers: calendarHelperStore,
|
||||||
} = useMobxStore();
|
} = useMobxStore();
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, moduleId } = router.query as { workspaceSlug: string; moduleId: string };
|
const { workspaceSlug, projectId, moduleId } = router.query as {
|
||||||
|
workspaceSlug: string;
|
||||||
|
projectId: string;
|
||||||
|
moduleId: string;
|
||||||
|
};
|
||||||
|
|
||||||
const issueActions = {
|
const issueActions = {
|
||||||
[EIssueActions.UPDATE]: (issue: IIssue) => {
|
[EIssueActions.UPDATE]: (issue: IIssue) => {
|
||||||
@ -34,6 +39,20 @@ export const ModuleCalendarLayout: React.FC = observer(() => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleDragDrop = (source: any, destination: any, issues: IIssue[], issueWithIds: any) => {
|
||||||
|
if (calendarHelperStore.handleDragDrop)
|
||||||
|
calendarHelperStore.handleDragDrop(
|
||||||
|
source,
|
||||||
|
destination,
|
||||||
|
workspaceSlug,
|
||||||
|
projectId,
|
||||||
|
moduleIssueStore,
|
||||||
|
issues,
|
||||||
|
issueWithIds,
|
||||||
|
moduleId
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseCalendarRoot
|
<BaseCalendarRoot
|
||||||
issueStore={moduleIssueStore}
|
issueStore={moduleIssueStore}
|
||||||
@ -42,6 +61,7 @@ export const ModuleCalendarLayout: React.FC = observer(() => {
|
|||||||
QuickActions={ModuleIssueQuickActions}
|
QuickActions={ModuleIssueQuickActions}
|
||||||
issueActions={issueActions}
|
issueActions={issueActions}
|
||||||
viewId={moduleId}
|
viewId={moduleId}
|
||||||
|
handleDragDrop={handleDragDrop}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -10,27 +10,41 @@ import { useRouter } from "next/router";
|
|||||||
|
|
||||||
export const CalendarLayout: React.FC = observer(() => {
|
export const CalendarLayout: React.FC = observer(() => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug } = router.query as { workspaceSlug: string };
|
const { workspaceSlug, projectId } = router.query as { workspaceSlug: string; projectId: string };
|
||||||
|
|
||||||
const {
|
const {
|
||||||
projectIssues: issueStore,
|
projectIssues: issueStore,
|
||||||
issueCalendarView: issueCalendarViewStore,
|
issueCalendarView: issueCalendarViewStore,
|
||||||
projectIssuesFilter: projectIssueFiltersStore,
|
projectIssuesFilter: projectIssueFiltersStore,
|
||||||
|
calendarHelpers: calendarHelperStore,
|
||||||
} = useMobxStore();
|
} = useMobxStore();
|
||||||
|
|
||||||
const issueActions = {
|
const issueActions = {
|
||||||
[EIssueActions.UPDATE]: async (issue: IIssue) => {
|
[EIssueActions.UPDATE]: async (issue: IIssue) => {
|
||||||
if (!workspaceSlug) return;
|
if (!workspaceSlug) return;
|
||||||
|
|
||||||
issueStore.updateIssue(workspaceSlug.toString(), issue.project, issue.id, issue);
|
issueStore.updateIssue(workspaceSlug, issue.project, issue.id, issue);
|
||||||
},
|
},
|
||||||
[EIssueActions.DELETE]: async (issue: IIssue) => {
|
[EIssueActions.DELETE]: async (issue: IIssue) => {
|
||||||
if (!workspaceSlug) return;
|
if (!workspaceSlug) return;
|
||||||
|
|
||||||
issueStore.removeIssue(workspaceSlug.toString(), issue.project, issue.id);
|
issueStore.removeIssue(workspaceSlug, issue.project, issue.id);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleDragDrop = (source: any, destination: any, issues: IIssue[], issueWithIds: any) => {
|
||||||
|
if (calendarHelperStore.handleDragDrop)
|
||||||
|
calendarHelperStore.handleDragDrop(
|
||||||
|
source,
|
||||||
|
destination,
|
||||||
|
workspaceSlug,
|
||||||
|
projectId,
|
||||||
|
issueStore,
|
||||||
|
issues,
|
||||||
|
issueWithIds
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseCalendarRoot
|
<BaseCalendarRoot
|
||||||
issueStore={issueStore}
|
issueStore={issueStore}
|
||||||
@ -38,6 +52,7 @@ export const CalendarLayout: React.FC = observer(() => {
|
|||||||
calendarViewStore={issueCalendarViewStore}
|
calendarViewStore={issueCalendarViewStore}
|
||||||
QuickActions={ProjectIssueQuickActions}
|
QuickActions={ProjectIssueQuickActions}
|
||||||
issueActions={issueActions}
|
issueActions={issueActions}
|
||||||
|
handleDragDrop={handleDragDrop}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -14,10 +14,11 @@ export const ProjectViewCalendarLayout: React.FC = observer(() => {
|
|||||||
viewIssues: projectViewIssuesStore,
|
viewIssues: projectViewIssuesStore,
|
||||||
viewIssuesFilter: projectIssueViewFiltersStore,
|
viewIssuesFilter: projectIssueViewFiltersStore,
|
||||||
projectViewIssueCalendarView: projectViewIssueCalendarViewStore,
|
projectViewIssueCalendarView: projectViewIssueCalendarViewStore,
|
||||||
|
calendarHelpers: calendarHelperStore,
|
||||||
} = useMobxStore();
|
} = useMobxStore();
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug } = router.query as { workspaceSlug: string };
|
const { workspaceSlug, projectId } = router.query as { workspaceSlug: string; projectId: string };
|
||||||
|
|
||||||
const issueActions = {
|
const issueActions = {
|
||||||
[EIssueActions.UPDATE]: async (issue: IIssue) => {
|
[EIssueActions.UPDATE]: async (issue: IIssue) => {
|
||||||
@ -32,6 +33,19 @@ export const ProjectViewCalendarLayout: React.FC = observer(() => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleDragDrop = (source: any, destination: any, issues: IIssue[], issueWithIds: any) => {
|
||||||
|
if (calendarHelperStore.handleDragDrop)
|
||||||
|
calendarHelperStore.handleDragDrop(
|
||||||
|
source,
|
||||||
|
destination,
|
||||||
|
workspaceSlug,
|
||||||
|
projectId,
|
||||||
|
projectViewIssuesStore,
|
||||||
|
issues,
|
||||||
|
issueWithIds
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseCalendarRoot
|
<BaseCalendarRoot
|
||||||
issueStore={projectViewIssuesStore}
|
issueStore={projectViewIssuesStore}
|
||||||
@ -39,6 +53,7 @@ export const ProjectViewCalendarLayout: React.FC = observer(() => {
|
|||||||
calendarViewStore={projectViewIssueCalendarViewStore}
|
calendarViewStore={projectViewIssueCalendarViewStore}
|
||||||
QuickActions={ProjectIssueQuickActions}
|
QuickActions={ProjectIssueQuickActions}
|
||||||
issueActions={issueActions}
|
issueActions={issueActions}
|
||||||
|
handleDragDrop={handleDragDrop}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { FC, useCallback, useState } from "react";
|
import { FC, useCallback, useState } from "react";
|
||||||
import { DragDropContext } from "@hello-pangea/dnd";
|
import { DragDropContext, Droppable } from "@hello-pangea/dnd";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
// mobx store
|
// mobx store
|
||||||
import { useMobxStore } from "lib/mobx/store-provider";
|
import { useMobxStore } from "lib/mobx/store-provider";
|
||||||
@ -29,6 +29,7 @@ import { ISSUE_STATE_GROUPS, ISSUE_PRIORITIES } from "constants/issue";
|
|||||||
import { KanBan } from "./default";
|
import { KanBan } from "./default";
|
||||||
import { KanBanSwimLanes } from "./swimlanes";
|
import { KanBanSwimLanes } from "./swimlanes";
|
||||||
import { EProjectStore } from "store/command-palette.store";
|
import { EProjectStore } from "store/command-palette.store";
|
||||||
|
import StrictModeDroppable from "components/dnd/StrictModeDroppable";
|
||||||
|
|
||||||
export interface IBaseKanBanLayout {
|
export interface IBaseKanBanLayout {
|
||||||
issueStore:
|
issueStore:
|
||||||
@ -54,6 +55,14 @@ export interface IBaseKanBanLayout {
|
|||||||
showLoader?: boolean;
|
showLoader?: boolean;
|
||||||
viewId?: string;
|
viewId?: string;
|
||||||
currentStore?: EProjectStore;
|
currentStore?: EProjectStore;
|
||||||
|
handleDragDrop?: (
|
||||||
|
source: any,
|
||||||
|
destination: any,
|
||||||
|
subGroupBy: string | null,
|
||||||
|
groupBy: string | null,
|
||||||
|
issues: any,
|
||||||
|
issueWithIds: any
|
||||||
|
) => void;
|
||||||
addIssuesToView?: (issueIds: string[]) => Promise<IIssue>;
|
addIssuesToView?: (issueIds: string[]) => Promise<IIssue>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,6 +76,7 @@ export const BaseKanBanRoot: React.FC<IBaseKanBanLayout> = observer((props: IBas
|
|||||||
showLoader,
|
showLoader,
|
||||||
viewId,
|
viewId,
|
||||||
currentStore,
|
currentStore,
|
||||||
|
handleDragDrop,
|
||||||
addIssuesToView,
|
addIssuesToView,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
@ -93,9 +103,9 @@ export const BaseKanBanRoot: React.FC<IBaseKanBanLayout> = observer((props: IBas
|
|||||||
|
|
||||||
const currentKanBanView: "swimlanes" | "default" = sub_group_by ? "swimlanes" : "default";
|
const currentKanBanView: "swimlanes" | "default" = sub_group_by ? "swimlanes" : "default";
|
||||||
|
|
||||||
const [isDragStarted, setIsDragStarted] = useState<boolean>(false);
|
|
||||||
|
|
||||||
const { enableInlineEditing, enableQuickAdd, enableIssueCreation } = issueStore?.viewFlags || {};
|
const { enableInlineEditing, enableQuickAdd, enableIssueCreation } = issueStore?.viewFlags || {};
|
||||||
|
|
||||||
|
const [isDragStarted, setIsDragStarted] = useState<boolean>(false);
|
||||||
const onDragStart = () => {
|
const onDragStart = () => {
|
||||||
setIsDragStarted(true);
|
setIsDragStarted(true);
|
||||||
};
|
};
|
||||||
@ -115,9 +125,7 @@ export const BaseKanBanRoot: React.FC<IBaseKanBanLayout> = observer((props: IBas
|
|||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
currentKanBanView === "default"
|
if (handleDragDrop) handleDragDrop(result.source, result.destination, sub_group_by, group_by, issues, issueIds);
|
||||||
? kanbanViewStore?.handleDragDrop(result.source, result.destination)
|
|
||||||
: kanbanViewStore?.handleSwimlaneDragDrop(result.source, result.destination);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleIssues = useCallback(
|
const handleIssues = useCallback(
|
||||||
@ -147,6 +155,24 @@ export const BaseKanBanRoot: React.FC<IBaseKanBanLayout> = observer((props: IBas
|
|||||||
|
|
||||||
<div className={`relative min-w-full w-max min-h-full h-max bg-custom-background-90 px-3`}>
|
<div className={`relative min-w-full w-max min-h-full h-max bg-custom-background-90 px-3`}>
|
||||||
<DragDropContext onDragStart={onDragStart} onDragEnd={onDragEnd}>
|
<DragDropContext onDragStart={onDragStart} onDragEnd={onDragEnd}>
|
||||||
|
<div className={`fixed left-1/2 -translate-x-1/2 z-40 w-72 top-3 flex items-center justify-center mx-3`}>
|
||||||
|
<Droppable droppableId="issue-trash-box" isDropDisabled={!isDragStarted}>
|
||||||
|
{(provided, snapshot) => (
|
||||||
|
<div
|
||||||
|
className={`${
|
||||||
|
isDragStarted ? `opacity-100` : `opacity-0`
|
||||||
|
} w-full flex items-center justify-center rounded border-2 border-red-500/20 bg-custom-background-100 px-3 py-5 text-xs font-medium italic text-red-500 ${
|
||||||
|
snapshot.isDraggingOver ? "bg-red-500 blur-2xl opacity-70" : ""
|
||||||
|
} transition duration-300`}
|
||||||
|
ref={provided.innerRef}
|
||||||
|
{...provided.droppableProps}
|
||||||
|
>
|
||||||
|
Drop here to delete the issue.
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Droppable>
|
||||||
|
</div>
|
||||||
|
|
||||||
{currentKanBanView === "default" ? (
|
{currentKanBanView === "default" ? (
|
||||||
<KanBan
|
<KanBan
|
||||||
issues={issues}
|
issues={issues}
|
||||||
|
@ -16,13 +16,18 @@ export interface ICycleKanBanLayout {}
|
|||||||
|
|
||||||
export const CycleKanBanLayout: React.FC = observer(() => {
|
export const CycleKanBanLayout: React.FC = observer(() => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, cycleId } = router.query as { workspaceSlug: string; cycleId: string };
|
const { workspaceSlug, projectId, cycleId } = router.query as {
|
||||||
|
workspaceSlug: string;
|
||||||
|
projectId: string;
|
||||||
|
cycleId: string;
|
||||||
|
};
|
||||||
|
|
||||||
// store
|
// store
|
||||||
const {
|
const {
|
||||||
cycleIssues: cycleIssueStore,
|
cycleIssues: cycleIssueStore,
|
||||||
cycleIssuesFilter: cycleIssueFilterStore,
|
cycleIssuesFilter: cycleIssueFilterStore,
|
||||||
cycleIssueKanBanView: cycleIssueKanBanViewStore,
|
cycleIssueKanBanView: cycleIssueKanBanViewStore,
|
||||||
|
kanBanHelpers: kanBanHelperStore,
|
||||||
} = useMobxStore();
|
} = useMobxStore();
|
||||||
|
|
||||||
const issueActions = {
|
const issueActions = {
|
||||||
@ -40,6 +45,30 @@ export const CycleKanBanLayout: React.FC = observer(() => {
|
|||||||
cycleIssueStore.removeIssueFromCycle(workspaceSlug, issue.project, cycleId, issue.id, issue.bridge_id);
|
cycleIssueStore.removeIssueFromCycle(workspaceSlug, issue.project, cycleId, issue.id, issue.bridge_id);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleDragDrop = (
|
||||||
|
source: any,
|
||||||
|
destination: any,
|
||||||
|
subGroupBy: string | null,
|
||||||
|
groupBy: string | null,
|
||||||
|
issues: IIssue[],
|
||||||
|
issueWithIds: any
|
||||||
|
) => {
|
||||||
|
if (kanBanHelperStore.handleDragDrop)
|
||||||
|
kanBanHelperStore.handleDragDrop(
|
||||||
|
source,
|
||||||
|
destination,
|
||||||
|
workspaceSlug,
|
||||||
|
projectId,
|
||||||
|
cycleIssueStore,
|
||||||
|
subGroupBy,
|
||||||
|
groupBy,
|
||||||
|
issues,
|
||||||
|
issueWithIds,
|
||||||
|
cycleId
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseKanBanRoot
|
<BaseKanBanRoot
|
||||||
issueActions={issueActions}
|
issueActions={issueActions}
|
||||||
@ -50,6 +79,7 @@ export const CycleKanBanLayout: React.FC = observer(() => {
|
|||||||
QuickActions={CycleIssueQuickActions}
|
QuickActions={CycleIssueQuickActions}
|
||||||
viewId={cycleId}
|
viewId={cycleId}
|
||||||
currentStore={EProjectStore.CYCLE}
|
currentStore={EProjectStore.CYCLE}
|
||||||
|
handleDragDrop={handleDragDrop}
|
||||||
addIssuesToView={(issues: string[]) => cycleIssueStore.addIssueToCycle(workspaceSlug, cycleId, issues)}
|
addIssuesToView={(issues: string[]) => cycleIssueStore.addIssueToCycle(workspaceSlug, cycleId, issues)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -16,13 +16,18 @@ export interface IModuleKanBanLayout {}
|
|||||||
|
|
||||||
export const ModuleKanBanLayout: React.FC = observer(() => {
|
export const ModuleKanBanLayout: React.FC = observer(() => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, moduleId } = router.query as { workspaceSlug: string; moduleId: string };
|
const { workspaceSlug, projectId, moduleId } = router.query as {
|
||||||
|
workspaceSlug: string;
|
||||||
|
projectId: string;
|
||||||
|
moduleId: string;
|
||||||
|
};
|
||||||
|
|
||||||
// store
|
// store
|
||||||
const {
|
const {
|
||||||
moduleIssues: moduleIssueStore,
|
moduleIssues: moduleIssueStore,
|
||||||
moduleIssuesFilter: moduleIssueFilterStore,
|
moduleIssuesFilter: moduleIssueFilterStore,
|
||||||
moduleIssueKanBanView: moduleIssueKanBanViewStore,
|
moduleIssueKanBanView: moduleIssueKanBanViewStore,
|
||||||
|
kanBanHelpers: kanBanHelperStore,
|
||||||
} = useMobxStore();
|
} = useMobxStore();
|
||||||
|
|
||||||
// const handleIssues = useCallback(
|
// const handleIssues = useCallback(
|
||||||
@ -62,6 +67,29 @@ export const ModuleKanBanLayout: React.FC = observer(() => {
|
|||||||
moduleIssueStore.removeIssueFromModule(workspaceSlug, issue.project, moduleId, issue.id, issue.bridge_id);
|
moduleIssueStore.removeIssueFromModule(workspaceSlug, issue.project, moduleId, issue.id, issue.bridge_id);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleDragDrop = (
|
||||||
|
source: any,
|
||||||
|
destination: any,
|
||||||
|
subGroupBy: string | null,
|
||||||
|
groupBy: string | null,
|
||||||
|
issues: IIssue[],
|
||||||
|
issueWithIds: any
|
||||||
|
) => {
|
||||||
|
if (kanBanHelperStore.handleDragDrop)
|
||||||
|
kanBanHelperStore.handleDragDrop(
|
||||||
|
source,
|
||||||
|
destination,
|
||||||
|
workspaceSlug,
|
||||||
|
projectId,
|
||||||
|
moduleIssueStore,
|
||||||
|
subGroupBy,
|
||||||
|
groupBy,
|
||||||
|
issues,
|
||||||
|
issueWithIds,
|
||||||
|
moduleId
|
||||||
|
);
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<BaseKanBanRoot
|
<BaseKanBanRoot
|
||||||
issueActions={issueActions}
|
issueActions={issueActions}
|
||||||
@ -72,6 +100,7 @@ export const ModuleKanBanLayout: React.FC = observer(() => {
|
|||||||
QuickActions={ModuleIssueQuickActions}
|
QuickActions={ModuleIssueQuickActions}
|
||||||
viewId={moduleId}
|
viewId={moduleId}
|
||||||
currentStore={EProjectStore.MODULE}
|
currentStore={EProjectStore.MODULE}
|
||||||
|
handleDragDrop={handleDragDrop}
|
||||||
addIssuesToView={(issues: string[]) => moduleIssueStore.addIssueToModule(workspaceSlug, moduleId, issues)}
|
addIssuesToView={(issues: string[]) => moduleIssueStore.addIssueToModule(workspaceSlug, moduleId, issues)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -15,12 +15,13 @@ export interface IKanBanLayout {}
|
|||||||
|
|
||||||
export const KanBanLayout: React.FC = observer(() => {
|
export const KanBanLayout: React.FC = observer(() => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug } = router.query as { workspaceSlug: string };
|
const { workspaceSlug, projectId } = router.query as { workspaceSlug: string; projectId: string };
|
||||||
|
|
||||||
const {
|
const {
|
||||||
projectIssues: issueStore,
|
projectIssues: issueStore,
|
||||||
projectIssuesFilter: issuesFilterStore,
|
projectIssuesFilter: issuesFilterStore,
|
||||||
issueKanBanView: issueKanBanViewStore,
|
issueKanBanView: issueKanBanViewStore,
|
||||||
|
kanBanHelpers: kanBanHelperStore,
|
||||||
} = useMobxStore();
|
} = useMobxStore();
|
||||||
|
|
||||||
const issueActions = {
|
const issueActions = {
|
||||||
@ -36,6 +37,28 @@ export const KanBanLayout: React.FC = observer(() => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleDragDrop = (
|
||||||
|
source: any,
|
||||||
|
destination: any,
|
||||||
|
subGroupBy: string | null,
|
||||||
|
groupBy: string | null,
|
||||||
|
issues: IIssue[],
|
||||||
|
issueWithIds: any
|
||||||
|
) => {
|
||||||
|
if (kanBanHelperStore.handleDragDrop)
|
||||||
|
kanBanHelperStore.handleDragDrop(
|
||||||
|
source,
|
||||||
|
destination,
|
||||||
|
workspaceSlug,
|
||||||
|
projectId,
|
||||||
|
issueStore,
|
||||||
|
subGroupBy,
|
||||||
|
groupBy,
|
||||||
|
issues,
|
||||||
|
issueWithIds
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseKanBanRoot
|
<BaseKanBanRoot
|
||||||
issueActions={issueActions}
|
issueActions={issueActions}
|
||||||
@ -45,6 +68,7 @@ export const KanBanLayout: React.FC = observer(() => {
|
|||||||
showLoader={true}
|
showLoader={true}
|
||||||
QuickActions={ProjectIssueQuickActions}
|
QuickActions={ProjectIssueQuickActions}
|
||||||
currentStore={EProjectStore.PROJECT}
|
currentStore={EProjectStore.PROJECT}
|
||||||
|
handleDragDrop={handleDragDrop}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -15,12 +15,13 @@ export interface IViewKanBanLayout {}
|
|||||||
|
|
||||||
export const ProjectViewKanBanLayout: React.FC = observer(() => {
|
export const ProjectViewKanBanLayout: React.FC = observer(() => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug } = router.query as { workspaceSlug: string };
|
const { workspaceSlug, projectId } = router.query as { workspaceSlug: string; projectId: string };
|
||||||
|
|
||||||
const {
|
const {
|
||||||
viewIssues: projectViewIssuesStore,
|
viewIssues: projectViewIssuesStore,
|
||||||
viewIssuesFilter: projectIssueViewFiltersStore,
|
viewIssuesFilter: projectIssueViewFiltersStore,
|
||||||
issueKanBanView: projectViewIssueKanBanViewStore,
|
issueKanBanView: projectViewIssueKanBanViewStore,
|
||||||
|
kanBanHelpers: kanBanHelperStore,
|
||||||
} = useMobxStore();
|
} = useMobxStore();
|
||||||
|
|
||||||
const issueActions = {
|
const issueActions = {
|
||||||
@ -36,6 +37,28 @@ export const ProjectViewKanBanLayout: React.FC = observer(() => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleDragDrop = (
|
||||||
|
source: any,
|
||||||
|
destination: any,
|
||||||
|
subGroupBy: string | null,
|
||||||
|
groupBy: string | null,
|
||||||
|
issues: IIssue[],
|
||||||
|
issueWithIds: any
|
||||||
|
) => {
|
||||||
|
if (kanBanHelperStore.handleDragDrop)
|
||||||
|
kanBanHelperStore.handleDragDrop(
|
||||||
|
source,
|
||||||
|
destination,
|
||||||
|
workspaceSlug,
|
||||||
|
projectId,
|
||||||
|
projectViewIssuesStore,
|
||||||
|
subGroupBy,
|
||||||
|
groupBy,
|
||||||
|
issues,
|
||||||
|
issueWithIds
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseKanBanRoot
|
<BaseKanBanRoot
|
||||||
issueActions={issueActions}
|
issueActions={issueActions}
|
||||||
@ -45,6 +68,7 @@ export const ProjectViewKanBanLayout: React.FC = observer(() => {
|
|||||||
showLoader={true}
|
showLoader={true}
|
||||||
QuickActions={ProjectIssueQuickActions}
|
QuickActions={ProjectIssueQuickActions}
|
||||||
currentStore={EProjectStore.PROJECT_VIEW}
|
currentStore={EProjectStore.PROJECT_VIEW}
|
||||||
|
handleDragDrop={handleDragDrop}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -23,9 +23,9 @@
|
|||||||
"@nivo/line": "0.80.0",
|
"@nivo/line": "0.80.0",
|
||||||
"@nivo/pie": "0.80.0",
|
"@nivo/pie": "0.80.0",
|
||||||
"@nivo/scatterplot": "0.80.0",
|
"@nivo/scatterplot": "0.80.0",
|
||||||
|
"@plane/document-editor": "*",
|
||||||
"@plane/lite-text-editor": "*",
|
"@plane/lite-text-editor": "*",
|
||||||
"@plane/rich-text-editor": "*",
|
"@plane/rich-text-editor": "*",
|
||||||
"@plane/document-editor": "*",
|
|
||||||
"@plane/ui": "*",
|
"@plane/ui": "*",
|
||||||
"@popperjs/core": "^2.11.8",
|
"@popperjs/core": "^2.11.8",
|
||||||
"@sentry/nextjs": "^7.36.0",
|
"@sentry/nextjs": "^7.36.0",
|
||||||
@ -58,8 +58,8 @@
|
|||||||
"sharp": "^0.32.1",
|
"sharp": "^0.32.1",
|
||||||
"swr": "^2.1.3",
|
"swr": "^2.1.3",
|
||||||
"tailwind-merge": "^2.0.0",
|
"tailwind-merge": "^2.0.0",
|
||||||
"uuid": "^9.0.0",
|
"use-debounce": "^9.0.4",
|
||||||
"use-debounce": "^9.0.4"
|
"uuid": "^9.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/js-cookie": "^3.0.2",
|
"@types/js-cookie": "^3.0.2",
|
||||||
|
53
web/store/issues/base-issue-calendar-helper.store.ts
Normal file
53
web/store/issues/base-issue-calendar-helper.store.ts
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
export interface ICalendarHelpers {
|
||||||
|
// actions
|
||||||
|
handleDragDrop: (
|
||||||
|
source: any,
|
||||||
|
destination: any,
|
||||||
|
workspaceSlug: string,
|
||||||
|
projectId: string,
|
||||||
|
store: any,
|
||||||
|
issues: any,
|
||||||
|
issueWithIds: any,
|
||||||
|
viewId?: string | null
|
||||||
|
) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class CalendarHelpers implements ICalendarHelpers {
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
handleDragDrop = async (
|
||||||
|
source: any,
|
||||||
|
destination: any,
|
||||||
|
workspaceSlug: string,
|
||||||
|
projectId: string,
|
||||||
|
store: any,
|
||||||
|
issues: any,
|
||||||
|
issueWithIds: any,
|
||||||
|
viewId: string | null = null // it can be moduleId, cycleId
|
||||||
|
) => {
|
||||||
|
if (issues && issueWithIds) {
|
||||||
|
const sourceColumnId = source?.droppableId || null;
|
||||||
|
const destinationColumnId = destination?.droppableId || null;
|
||||||
|
|
||||||
|
if (!workspaceSlug || !projectId || !sourceColumnId || !destinationColumnId) return;
|
||||||
|
|
||||||
|
if (sourceColumnId === destinationColumnId) return;
|
||||||
|
|
||||||
|
// horizontal
|
||||||
|
if (sourceColumnId != destinationColumnId) {
|
||||||
|
const sourceIssues = issueWithIds[sourceColumnId] || [];
|
||||||
|
|
||||||
|
const [removed] = sourceIssues.splice(source.index, 1);
|
||||||
|
const removedIssueDetail = issues[removed];
|
||||||
|
|
||||||
|
const updateIssue = {
|
||||||
|
id: removedIssueDetail?.id,
|
||||||
|
target_date: destinationColumnId,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (viewId) store?.updateIssue(workspaceSlug, projectId, updateIssue.id, updateIssue, viewId);
|
||||||
|
else store?.updateIssue(workspaceSlug, projectId, updateIssue.id, updateIssue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
160
web/store/issues/base-issue-kanban-helper.store.ts
Normal file
160
web/store/issues/base-issue-kanban-helper.store.ts
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
export interface IKanBanHelpers {
|
||||||
|
// actions
|
||||||
|
handleDragDrop: (
|
||||||
|
source: any,
|
||||||
|
destination: any,
|
||||||
|
workspaceSlug: string,
|
||||||
|
projectId: string,
|
||||||
|
store: any,
|
||||||
|
subGroupBy: string | null,
|
||||||
|
groupBy: string | null,
|
||||||
|
issues: any,
|
||||||
|
issueWithIds: any,
|
||||||
|
viewId?: string | null
|
||||||
|
) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class KanBanHelpers implements IKanBanHelpers {
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
handleSortOrder = (destinationIssues: any, destinationIndex: any, issues: any) => {
|
||||||
|
const sortOrderDefaultValue = 65535;
|
||||||
|
let currentIssueState = {};
|
||||||
|
|
||||||
|
if (destinationIssues && destinationIssues.length > 0) {
|
||||||
|
if (destinationIndex === 0) {
|
||||||
|
const destinationIssueId = destinationIssues[destinationIndex];
|
||||||
|
currentIssueState = {
|
||||||
|
...currentIssueState,
|
||||||
|
sort_order: issues[destinationIssueId].sort_order - sortOrderDefaultValue,
|
||||||
|
};
|
||||||
|
} else if (destinationIndex === destinationIssues.length) {
|
||||||
|
const destinationIssueId = destinationIssues[destinationIndex - 1];
|
||||||
|
currentIssueState = {
|
||||||
|
...currentIssueState,
|
||||||
|
sort_order: issues[destinationIssueId].sort_order + sortOrderDefaultValue,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
const destinationTopIssueId = destinationIssues[destinationIndex - 1];
|
||||||
|
const destinationBottomIssueId = destinationIssues[destinationIndex];
|
||||||
|
currentIssueState = {
|
||||||
|
...currentIssueState,
|
||||||
|
sort_order: (issues[destinationTopIssueId].sort_order + issues[destinationBottomIssueId].sort_order) / 2,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
currentIssueState = {
|
||||||
|
...currentIssueState,
|
||||||
|
sort_order: sortOrderDefaultValue,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return currentIssueState;
|
||||||
|
};
|
||||||
|
|
||||||
|
handleDragDrop = async (
|
||||||
|
source: any,
|
||||||
|
destination: any,
|
||||||
|
workspaceSlug: string,
|
||||||
|
projectId: string, // projectId for all views or user id in profile issues
|
||||||
|
store: any,
|
||||||
|
subGroupBy: string | null,
|
||||||
|
groupBy: string | null,
|
||||||
|
issues: any,
|
||||||
|
issueWithIds: any,
|
||||||
|
viewId: string | null = null // it can be moduleId, cycleId
|
||||||
|
) => {
|
||||||
|
if (issues && issueWithIds) {
|
||||||
|
let updateIssue: any = {};
|
||||||
|
|
||||||
|
const sourceColumnId = (source?.droppableId && source?.droppableId.split("__")) || null;
|
||||||
|
const destinationColumnId = (destination?.droppableId && destination?.droppableId.split("__")) || null;
|
||||||
|
|
||||||
|
const sourceGroupByColumnId = sourceColumnId[0] || null;
|
||||||
|
const destinationGroupByColumnId = destinationColumnId[0] || null;
|
||||||
|
|
||||||
|
const sourceSubGroupByColumnId = sourceColumnId[1] || null;
|
||||||
|
const destinationSubGroupByColumnId = destinationColumnId[1] || null;
|
||||||
|
|
||||||
|
if (!workspaceSlug || !projectId || !groupBy || !sourceGroupByColumnId || !destinationGroupByColumnId) return;
|
||||||
|
|
||||||
|
if (destinationGroupByColumnId === "issue-trash-box") {
|
||||||
|
const sourceIssues = subGroupBy
|
||||||
|
? issueWithIds[sourceSubGroupByColumnId][sourceGroupByColumnId]
|
||||||
|
: issueWithIds[sourceGroupByColumnId];
|
||||||
|
|
||||||
|
const [removed] = sourceIssues.splice(source.index, 1);
|
||||||
|
|
||||||
|
console.log("removed", removed);
|
||||||
|
|
||||||
|
if (removed) {
|
||||||
|
if (viewId) store?.removeIssue(workspaceSlug, projectId, removed, viewId);
|
||||||
|
else store?.removeIssue(workspaceSlug, projectId, removed);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const sourceIssues = subGroupBy
|
||||||
|
? issueWithIds[sourceSubGroupByColumnId][sourceGroupByColumnId]
|
||||||
|
: issueWithIds[sourceGroupByColumnId];
|
||||||
|
const destinationIssues = subGroupBy
|
||||||
|
? issueWithIds[sourceSubGroupByColumnId][destinationGroupByColumnId]
|
||||||
|
: issueWithIds[destinationGroupByColumnId];
|
||||||
|
|
||||||
|
const [removed] = sourceIssues.splice(source.index, 1);
|
||||||
|
const removedIssueDetail = issues[removed];
|
||||||
|
|
||||||
|
if (subGroupBy && sourceSubGroupByColumnId && destinationSubGroupByColumnId) {
|
||||||
|
updateIssue = {
|
||||||
|
id: removedIssueDetail?.id,
|
||||||
|
};
|
||||||
|
|
||||||
|
// for both horizontal and vertical dnd
|
||||||
|
updateIssue = {
|
||||||
|
...updateIssue,
|
||||||
|
...this.handleSortOrder(destinationIssues, destination.index, issues),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (sourceSubGroupByColumnId === destinationSubGroupByColumnId) {
|
||||||
|
if (sourceGroupByColumnId != destinationGroupByColumnId) {
|
||||||
|
if (groupBy === "state") updateIssue = { ...updateIssue, state: destinationGroupByColumnId };
|
||||||
|
if (groupBy === "priority") updateIssue = { ...updateIssue, priority: destinationGroupByColumnId };
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (subGroupBy === "state")
|
||||||
|
updateIssue = {
|
||||||
|
...updateIssue,
|
||||||
|
state: destinationSubGroupByColumnId,
|
||||||
|
priority: destinationGroupByColumnId,
|
||||||
|
};
|
||||||
|
if (subGroupBy === "priority")
|
||||||
|
updateIssue = {
|
||||||
|
...updateIssue,
|
||||||
|
state: destinationGroupByColumnId,
|
||||||
|
priority: destinationSubGroupByColumnId,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
updateIssue = {
|
||||||
|
id: removedIssueDetail?.id,
|
||||||
|
};
|
||||||
|
|
||||||
|
// for both horizontal and vertical dnd
|
||||||
|
updateIssue = {
|
||||||
|
...updateIssue,
|
||||||
|
...this.handleSortOrder(destinationIssues, destination.index, issues),
|
||||||
|
};
|
||||||
|
|
||||||
|
// for horizontal dnd
|
||||||
|
if (sourceColumnId != destinationColumnId) {
|
||||||
|
if (groupBy === "state") updateIssue = { ...updateIssue, state: destinationGroupByColumnId };
|
||||||
|
if (groupBy === "priority") updateIssue = { ...updateIssue, priority: destinationGroupByColumnId };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateIssue && updateIssue?.id) {
|
||||||
|
if (viewId) store?.updateIssue(workspaceSlug, projectId, updateIssue.id, updateIssue, viewId);
|
||||||
|
else store?.updateIssue(workspaceSlug, projectId, updateIssue.id, updateIssue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
@ -1,5 +1,9 @@
|
|||||||
/** project issues and issue-filters starts */
|
/** project issues and issue-filters starts */
|
||||||
|
|
||||||
|
// helpers
|
||||||
|
export * from "./base-issue-calendar-helper.store";
|
||||||
|
export * from "./base-issue-kanban-helper.store";
|
||||||
|
|
||||||
// issue and filter helpers
|
// issue and filter helpers
|
||||||
export * from "./project-issues/base-issue.store";
|
export * from "./project-issues/base-issue.store";
|
||||||
export * from "./project-issues/base-issue-filter.store";
|
export * from "./project-issues/base-issue-filter.store";
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { action, makeObservable, observable, runInAction } from "mobx";
|
import { action, makeObservable, observable, runInAction } from "mobx";
|
||||||
|
import isEmpty from "lodash/isEmpty";
|
||||||
// types
|
// types
|
||||||
import { RootStore } from "store/root";
|
import { RootStore } from "store/root";
|
||||||
import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions, TIssueParams } from "types";
|
import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions, TIssueParams } from "types";
|
||||||
import { EFilterType } from "store/issues/types";
|
import { EFilterType } from "store/issues/types";
|
||||||
import { handleIssueQueryParamsByLayout } from "helpers/issue.helper";
|
import { handleIssueQueryParamsByLayout } from "helpers/issue.helper";
|
||||||
import { IssueFilterBaseStore } from "../project-issues/base-issue-filter.store";
|
import { IssueFilterBaseStore } from "../project-issues/base-issue-filter.store";
|
||||||
import isEmpty from "lodash/isEmpty";
|
|
||||||
|
|
||||||
interface IProjectIssuesFiltersOptions {
|
interface IProjectIssuesFiltersOptions {
|
||||||
filters: IIssueFilterOptions;
|
filters: IIssueFilterOptions;
|
||||||
@ -199,14 +199,14 @@ export class ProfileIssuesFilterStore extends IssueFilterBaseStore implements IP
|
|||||||
try {
|
try {
|
||||||
const displayProperties: IIssueDisplayProperties = {
|
const displayProperties: IIssueDisplayProperties = {
|
||||||
assignee: true,
|
assignee: true,
|
||||||
start_date: false,
|
start_date: true,
|
||||||
due_date: false,
|
due_date: true,
|
||||||
labels: true,
|
labels: true,
|
||||||
key: true,
|
key: true,
|
||||||
priority: true,
|
priority: true,
|
||||||
state: false,
|
state: false,
|
||||||
sub_issue_count: false,
|
sub_issue_count: true,
|
||||||
link: false,
|
link: true,
|
||||||
attachment_count: false,
|
attachment_count: false,
|
||||||
estimate: false,
|
estimate: false,
|
||||||
created_on: false,
|
created_on: false,
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
import _ from "lodash";
|
import sortBy from "lodash/sortBy";
|
||||||
|
import get from "lodash/get";
|
||||||
|
import indexOf from "lodash/indexOf";
|
||||||
|
import reverse from "lodash/reverse";
|
||||||
|
import values from "lodash/values";
|
||||||
// types
|
// types
|
||||||
import { IIssue, TIssueGroupByOptions, TIssueOrderByOptions } from "types";
|
import { IIssue, TIssueGroupByOptions, TIssueOrderByOptions } from "types";
|
||||||
import { RootStore } from "store/root";
|
import { RootStore } from "store/root";
|
||||||
@ -51,7 +55,7 @@ export class IssueBaseStore implements IIssueBaseStore {
|
|||||||
|
|
||||||
for (const issue in projectIssues) {
|
for (const issue in projectIssues) {
|
||||||
const _issue = projectIssues[issue];
|
const _issue = projectIssues[issue];
|
||||||
const groupArray = this.getGroupArray(_.get(_issue, groupBy as keyof IIssue), isCalendarIssues);
|
const groupArray = this.getGroupArray(get(_issue, groupBy as keyof IIssue), isCalendarIssues);
|
||||||
|
|
||||||
for (const group of groupArray) {
|
for (const group of groupArray) {
|
||||||
if (group && _issues[group]) _issues[group].push(_issue.id);
|
if (group && _issues[group]) _issues[group].push(_issue.id);
|
||||||
@ -82,8 +86,8 @@ export class IssueBaseStore implements IIssueBaseStore {
|
|||||||
|
|
||||||
for (const issue in projectIssues) {
|
for (const issue in projectIssues) {
|
||||||
const _issue = projectIssues[issue];
|
const _issue = projectIssues[issue];
|
||||||
const subGroupArray = this.getGroupArray(_.get(_issue, subGroupBy as keyof IIssue));
|
const subGroupArray = this.getGroupArray(get(_issue, subGroupBy as keyof IIssue));
|
||||||
const groupArray = this.getGroupArray(_.get(_issue, groupBy as keyof IIssue));
|
const groupArray = this.getGroupArray(get(_issue, groupBy as keyof IIssue));
|
||||||
|
|
||||||
for (const subGroup of subGroupArray) {
|
for (const subGroup of subGroupArray) {
|
||||||
for (const group of groupArray) {
|
for (const group of groupArray) {
|
||||||
@ -121,22 +125,22 @@ export class IssueBaseStore implements IIssueBaseStore {
|
|||||||
};
|
};
|
||||||
|
|
||||||
issuesSortWithOrderBy = (issueObject: IIssueResponse, key: Partial<TIssueOrderByOptions>): IIssue[] => {
|
issuesSortWithOrderBy = (issueObject: IIssueResponse, key: Partial<TIssueOrderByOptions>): IIssue[] => {
|
||||||
let array = _.values(issueObject);
|
let array = values(issueObject);
|
||||||
array = _.sortBy(array, "created_at");
|
array = sortBy(array, "created_at");
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case "sort_order":
|
case "sort_order":
|
||||||
return _.sortBy(array, "sort_order");
|
return sortBy(array, "sort_order");
|
||||||
case "-created_at":
|
case "-created_at":
|
||||||
return _.reverse(_.sortBy(array, "created_at"));
|
return reverse(sortBy(array, "created_at"));
|
||||||
case "-updated_at":
|
case "-updated_at":
|
||||||
return _.reverse(_.sortBy(array, "updated_at"));
|
return reverse(sortBy(array, "updated_at"));
|
||||||
case "start_date":
|
case "start_date":
|
||||||
return _.sortBy(array, "start_date");
|
return sortBy(array, "start_date");
|
||||||
case "target_date":
|
case "target_date":
|
||||||
return _.sortBy(array, "target_date");
|
return sortBy(array, "target_date");
|
||||||
case "priority": {
|
case "priority": {
|
||||||
const sortArray = ISSUE_PRIORITIES.map((i) => i.key);
|
const sortArray = ISSUE_PRIORITIES.map((i) => i.key);
|
||||||
return _.sortBy(array, (_issue: IIssue) => _.indexOf(sortArray, _issue.priority));
|
return sortBy(array, (_issue: IIssue) => indexOf(sortArray, _issue.priority));
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return array;
|
return array;
|
||||||
|
@ -94,24 +94,15 @@ export class ProjectIssuesStore extends IssueBaseStore implements IProjectIssues
|
|||||||
let issues: IIssueResponse | IGroupedIssues | ISubGroupedIssues | TUnGroupedIssues | undefined = undefined;
|
let issues: IIssueResponse | IGroupedIssues | ISubGroupedIssues | TUnGroupedIssues | undefined = undefined;
|
||||||
|
|
||||||
if (layout === "list" && orderBy) {
|
if (layout === "list" && orderBy) {
|
||||||
console.log("list");
|
|
||||||
if (groupBy) issues = this.groupedIssues(groupBy, orderBy, this.issues[projectId]);
|
if (groupBy) issues = this.groupedIssues(groupBy, orderBy, this.issues[projectId]);
|
||||||
else issues = this.unGroupedIssues(orderBy, this.issues[projectId]);
|
else issues = this.unGroupedIssues(orderBy, this.issues[projectId]);
|
||||||
} else if (layout === "kanban" && groupBy && orderBy) {
|
} else if (layout === "kanban" && groupBy && orderBy) {
|
||||||
console.log("kanban");
|
|
||||||
if (subGroupBy) issues = this.subGroupedIssues(subGroupBy, groupBy, orderBy, this.issues[projectId]);
|
if (subGroupBy) issues = this.subGroupedIssues(subGroupBy, groupBy, orderBy, this.issues[projectId]);
|
||||||
else issues = this.groupedIssues(groupBy, orderBy, this.issues[projectId]);
|
else issues = this.groupedIssues(groupBy, orderBy, this.issues[projectId]);
|
||||||
console.log("issues", issues);
|
} else if (layout === "calendar")
|
||||||
} else if (layout === "calendar") {
|
|
||||||
console.log("calendar");
|
|
||||||
issues = this.groupedIssues("target_date" as TIssueGroupByOptions, "target_date", this.issues[projectId], true);
|
issues = this.groupedIssues("target_date" as TIssueGroupByOptions, "target_date", this.issues[projectId], true);
|
||||||
} else if (layout === "spreadsheet") {
|
else if (layout === "spreadsheet") issues = this.unGroupedIssues(orderBy ?? "-created_at", this.issues[projectId]);
|
||||||
console.log("spreadsheet");
|
else if (layout === "gantt_chart") issues = this.unGroupedIssues(orderBy ?? "sort_order", this.issues[projectId]);
|
||||||
issues = this.unGroupedIssues(orderBy ?? "-created_at", this.issues[projectId]);
|
|
||||||
} else if (layout === "gantt_chart") {
|
|
||||||
console.log("gantt_chart");
|
|
||||||
issues = this.unGroupedIssues(orderBy ?? "sort_order", this.issues[projectId]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return issues;
|
return issues;
|
||||||
}
|
}
|
||||||
|
@ -164,6 +164,11 @@ import {
|
|||||||
// global issues filter
|
// global issues filter
|
||||||
IGlobalIssuesFilterStore,
|
IGlobalIssuesFilterStore,
|
||||||
GlobalIssuesFilterStore,
|
GlobalIssuesFilterStore,
|
||||||
|
// helpers
|
||||||
|
ICalendarHelpers,
|
||||||
|
CalendarHelpers,
|
||||||
|
IKanBanHelpers,
|
||||||
|
KanBanHelpers,
|
||||||
} from "store/issues";
|
} from "store/issues";
|
||||||
|
|
||||||
import { CycleIssueFiltersStore, ICycleIssueFiltersStore } from "store/cycle-issues";
|
import { CycleIssueFiltersStore, ICycleIssueFiltersStore } from "store/cycle-issues";
|
||||||
@ -274,6 +279,10 @@ export class RootStore {
|
|||||||
|
|
||||||
workspaceGlobalIssues: IGlobalIssuesStore;
|
workspaceGlobalIssues: IGlobalIssuesStore;
|
||||||
workspaceGlobalIssuesFilter: IGlobalIssuesFilterStore;
|
workspaceGlobalIssuesFilter: IGlobalIssuesFilterStore;
|
||||||
|
|
||||||
|
calendarHelpers: ICalendarHelpers;
|
||||||
|
|
||||||
|
kanBanHelpers: IKanBanHelpers;
|
||||||
// project v3 issue and issue-filters ends
|
// project v3 issue and issue-filters ends
|
||||||
|
|
||||||
cycleIssueFilters: ICycleIssueFiltersStore;
|
cycleIssueFilters: ICycleIssueFiltersStore;
|
||||||
@ -378,6 +387,10 @@ export class RootStore {
|
|||||||
|
|
||||||
this.workspaceGlobalIssues = new GlobalIssuesStore(this);
|
this.workspaceGlobalIssues = new GlobalIssuesStore(this);
|
||||||
this.workspaceGlobalIssuesFilter = new GlobalIssuesFilterStore(this);
|
this.workspaceGlobalIssuesFilter = new GlobalIssuesFilterStore(this);
|
||||||
|
|
||||||
|
this.calendarHelpers = new CalendarHelpers();
|
||||||
|
|
||||||
|
this.kanBanHelpers = new KanBanHelpers();
|
||||||
// project v3 issue and issue-filters ends
|
// project v3 issue and issue-filters ends
|
||||||
|
|
||||||
this.cycleIssueFilters = new CycleIssueFiltersStore(this);
|
this.cycleIssueFilters = new CycleIssueFiltersStore(this);
|
||||||
|
Loading…
Reference in New Issue
Block a user