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:
guru_sainath 2023-11-28 19:17:38 +05:30 committed by sriram veeraghanta
parent e16e468b8f
commit 011db50da6
18 changed files with 480 additions and 50 deletions

View File

@ -37,10 +37,12 @@ interface IBaseCalendarRoot {
[EIssueActions.REMOVE]?: (issue: IIssue) => void;
};
viewId?: string;
handleDragDrop: (source: any, destination: any, issues: any, issueWithIds: any) => void;
}
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;
@ -56,7 +58,7 @@ export const BaseCalendarRoot = observer((props: IBaseCalendarRoot) => {
// return if dropped on the same date
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(

View File

@ -14,10 +14,15 @@ export const CycleCalendarLayout: React.FC = observer(() => {
cycleIssues: cycleIssueStore,
cycleIssuesFilter: cycleIssueFilterStore,
cycleIssueCalendarView: cycleIssueCalendarViewStore,
calendarHelpers: calendarHelperStore,
} = useMobxStore();
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 = {
[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 (
<BaseCalendarRoot
issueStore={cycleIssueStore}
@ -43,6 +62,7 @@ export const CycleCalendarLayout: React.FC = observer(() => {
QuickActions={CycleIssueQuickActions}
issueActions={issueActions}
viewId={cycleId}
handleDragDrop={handleDragDrop}
/>
);
});

View File

@ -14,10 +14,15 @@ export const ModuleCalendarLayout: React.FC = observer(() => {
moduleIssues: moduleIssueStore,
moduleIssuesFilter: moduleIssueFilterStore,
moduleIssueCalendarView: moduleIssueCalendarViewStore,
calendarHelpers: calendarHelperStore,
} = useMobxStore();
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 = {
[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 (
<BaseCalendarRoot
issueStore={moduleIssueStore}
@ -42,6 +61,7 @@ export const ModuleCalendarLayout: React.FC = observer(() => {
QuickActions={ModuleIssueQuickActions}
issueActions={issueActions}
viewId={moduleId}
handleDragDrop={handleDragDrop}
/>
);
});

View File

@ -10,27 +10,41 @@ import { useRouter } from "next/router";
export const CalendarLayout: React.FC = observer(() => {
const router = useRouter();
const { workspaceSlug } = router.query as { workspaceSlug: string };
const { workspaceSlug, projectId } = router.query as { workspaceSlug: string; projectId: string };
const {
projectIssues: issueStore,
issueCalendarView: issueCalendarViewStore,
projectIssuesFilter: projectIssueFiltersStore,
calendarHelpers: calendarHelperStore,
} = useMobxStore();
const issueActions = {
[EIssueActions.UPDATE]: async (issue: IIssue) => {
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) => {
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 (
<BaseCalendarRoot
issueStore={issueStore}
@ -38,6 +52,7 @@ export const CalendarLayout: React.FC = observer(() => {
calendarViewStore={issueCalendarViewStore}
QuickActions={ProjectIssueQuickActions}
issueActions={issueActions}
handleDragDrop={handleDragDrop}
/>
);
});

View File

@ -14,10 +14,11 @@ export const ProjectViewCalendarLayout: React.FC = observer(() => {
viewIssues: projectViewIssuesStore,
viewIssuesFilter: projectIssueViewFiltersStore,
projectViewIssueCalendarView: projectViewIssueCalendarViewStore,
calendarHelpers: calendarHelperStore,
} = useMobxStore();
const router = useRouter();
const { workspaceSlug } = router.query as { workspaceSlug: string };
const { workspaceSlug, projectId } = router.query as { workspaceSlug: string; projectId: string };
const issueActions = {
[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 (
<BaseCalendarRoot
issueStore={projectViewIssuesStore}
@ -39,6 +53,7 @@ export const ProjectViewCalendarLayout: React.FC = observer(() => {
calendarViewStore={projectViewIssueCalendarViewStore}
QuickActions={ProjectIssueQuickActions}
issueActions={issueActions}
handleDragDrop={handleDragDrop}
/>
);
});

View File

@ -1,5 +1,5 @@
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";
// mobx store
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 { KanBanSwimLanes } from "./swimlanes";
import { EProjectStore } from "store/command-palette.store";
import StrictModeDroppable from "components/dnd/StrictModeDroppable";
export interface IBaseKanBanLayout {
issueStore:
@ -54,6 +55,14 @@ export interface IBaseKanBanLayout {
showLoader?: boolean;
viewId?: string;
currentStore?: EProjectStore;
handleDragDrop?: (
source: any,
destination: any,
subGroupBy: string | null,
groupBy: string | null,
issues: any,
issueWithIds: any
) => void;
addIssuesToView?: (issueIds: string[]) => Promise<IIssue>;
}
@ -67,6 +76,7 @@ export const BaseKanBanRoot: React.FC<IBaseKanBanLayout> = observer((props: IBas
showLoader,
viewId,
currentStore,
handleDragDrop,
addIssuesToView,
} = props;
@ -93,9 +103,9 @@ export const BaseKanBanRoot: React.FC<IBaseKanBanLayout> = observer((props: IBas
const currentKanBanView: "swimlanes" | "default" = sub_group_by ? "swimlanes" : "default";
const [isDragStarted, setIsDragStarted] = useState<boolean>(false);
const { enableInlineEditing, enableQuickAdd, enableIssueCreation } = issueStore?.viewFlags || {};
const [isDragStarted, setIsDragStarted] = useState<boolean>(false);
const onDragStart = () => {
setIsDragStarted(true);
};
@ -115,9 +125,7 @@ export const BaseKanBanRoot: React.FC<IBaseKanBanLayout> = observer((props: IBas
)
return;
currentKanBanView === "default"
? kanbanViewStore?.handleDragDrop(result.source, result.destination)
: kanbanViewStore?.handleSwimlaneDragDrop(result.source, result.destination);
if (handleDragDrop) handleDragDrop(result.source, result.destination, sub_group_by, group_by, issues, issueIds);
};
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`}>
<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" ? (
<KanBan
issues={issues}

View File

@ -16,13 +16,18 @@ export interface ICycleKanBanLayout {}
export const CycleKanBanLayout: React.FC = observer(() => {
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
const {
cycleIssues: cycleIssueStore,
cycleIssuesFilter: cycleIssueFilterStore,
cycleIssueKanBanView: cycleIssueKanBanViewStore,
kanBanHelpers: kanBanHelperStore,
} = useMobxStore();
const issueActions = {
@ -40,6 +45,30 @@ export const CycleKanBanLayout: React.FC = observer(() => {
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 (
<BaseKanBanRoot
issueActions={issueActions}
@ -50,6 +79,7 @@ export const CycleKanBanLayout: React.FC = observer(() => {
QuickActions={CycleIssueQuickActions}
viewId={cycleId}
currentStore={EProjectStore.CYCLE}
handleDragDrop={handleDragDrop}
addIssuesToView={(issues: string[]) => cycleIssueStore.addIssueToCycle(workspaceSlug, cycleId, issues)}
/>
);

View File

@ -16,13 +16,18 @@ export interface IModuleKanBanLayout {}
export const ModuleKanBanLayout: React.FC = observer(() => {
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
const {
moduleIssues: moduleIssueStore,
moduleIssuesFilter: moduleIssueFilterStore,
moduleIssueKanBanView: moduleIssueKanBanViewStore,
kanBanHelpers: kanBanHelperStore,
} = useMobxStore();
// const handleIssues = useCallback(
@ -62,6 +67,29 @@ export const ModuleKanBanLayout: React.FC = observer(() => {
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 (
<BaseKanBanRoot
issueActions={issueActions}
@ -72,6 +100,7 @@ export const ModuleKanBanLayout: React.FC = observer(() => {
QuickActions={ModuleIssueQuickActions}
viewId={moduleId}
currentStore={EProjectStore.MODULE}
handleDragDrop={handleDragDrop}
addIssuesToView={(issues: string[]) => moduleIssueStore.addIssueToModule(workspaceSlug, moduleId, issues)}
/>
);

View File

@ -15,12 +15,13 @@ export interface IKanBanLayout {}
export const KanBanLayout: React.FC = observer(() => {
const router = useRouter();
const { workspaceSlug } = router.query as { workspaceSlug: string };
const { workspaceSlug, projectId } = router.query as { workspaceSlug: string; projectId: string };
const {
projectIssues: issueStore,
projectIssuesFilter: issuesFilterStore,
issueKanBanView: issueKanBanViewStore,
kanBanHelpers: kanBanHelperStore,
} = useMobxStore();
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 (
<BaseKanBanRoot
issueActions={issueActions}
@ -45,6 +68,7 @@ export const KanBanLayout: React.FC = observer(() => {
showLoader={true}
QuickActions={ProjectIssueQuickActions}
currentStore={EProjectStore.PROJECT}
handleDragDrop={handleDragDrop}
/>
);
});

View File

@ -15,12 +15,13 @@ export interface IViewKanBanLayout {}
export const ProjectViewKanBanLayout: React.FC = observer(() => {
const router = useRouter();
const { workspaceSlug } = router.query as { workspaceSlug: string };
const { workspaceSlug, projectId } = router.query as { workspaceSlug: string; projectId: string };
const {
viewIssues: projectViewIssuesStore,
viewIssuesFilter: projectIssueViewFiltersStore,
issueKanBanView: projectViewIssueKanBanViewStore,
kanBanHelpers: kanBanHelperStore,
} = useMobxStore();
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 (
<BaseKanBanRoot
issueActions={issueActions}
@ -45,6 +68,7 @@ export const ProjectViewKanBanLayout: React.FC = observer(() => {
showLoader={true}
QuickActions={ProjectIssueQuickActions}
currentStore={EProjectStore.PROJECT_VIEW}
handleDragDrop={handleDragDrop}
/>
);
});

View File

@ -23,9 +23,9 @@
"@nivo/line": "0.80.0",
"@nivo/pie": "0.80.0",
"@nivo/scatterplot": "0.80.0",
"@plane/document-editor": "*",
"@plane/lite-text-editor": "*",
"@plane/rich-text-editor": "*",
"@plane/document-editor": "*",
"@plane/ui": "*",
"@popperjs/core": "^2.11.8",
"@sentry/nextjs": "^7.36.0",
@ -58,8 +58,8 @@
"sharp": "^0.32.1",
"swr": "^2.1.3",
"tailwind-merge": "^2.0.0",
"uuid": "^9.0.0",
"use-debounce": "^9.0.4"
"use-debounce": "^9.0.4",
"uuid": "^9.0.0"
},
"devDependencies": {
"@types/js-cookie": "^3.0.2",

View 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);
}
}
};
}

View 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);
}
}
}
};
}

View File

@ -1,5 +1,9 @@
/** 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
export * from "./project-issues/base-issue.store";
export * from "./project-issues/base-issue-filter.store";

View File

@ -1,11 +1,11 @@
import { action, makeObservable, observable, runInAction } from "mobx";
import isEmpty from "lodash/isEmpty";
// types
import { RootStore } from "store/root";
import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions, TIssueParams } from "types";
import { EFilterType } from "store/issues/types";
import { handleIssueQueryParamsByLayout } from "helpers/issue.helper";
import { IssueFilterBaseStore } from "../project-issues/base-issue-filter.store";
import isEmpty from "lodash/isEmpty";
interface IProjectIssuesFiltersOptions {
filters: IIssueFilterOptions;
@ -199,14 +199,14 @@ export class ProfileIssuesFilterStore extends IssueFilterBaseStore implements IP
try {
const displayProperties: IIssueDisplayProperties = {
assignee: true,
start_date: false,
due_date: false,
start_date: true,
due_date: true,
labels: true,
key: true,
priority: true,
state: false,
sub_issue_count: false,
link: false,
sub_issue_count: true,
link: true,
attachment_count: false,
estimate: false,
created_on: false,

View File

@ -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
import { IIssue, TIssueGroupByOptions, TIssueOrderByOptions } from "types";
import { RootStore } from "store/root";
@ -51,7 +55,7 @@ export class IssueBaseStore implements IIssueBaseStore {
for (const issue in projectIssues) {
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) {
if (group && _issues[group]) _issues[group].push(_issue.id);
@ -82,8 +86,8 @@ export class IssueBaseStore implements IIssueBaseStore {
for (const issue in projectIssues) {
const _issue = projectIssues[issue];
const subGroupArray = this.getGroupArray(_.get(_issue, subGroupBy as keyof IIssue));
const groupArray = this.getGroupArray(_.get(_issue, groupBy as keyof IIssue));
const subGroupArray = this.getGroupArray(get(_issue, subGroupBy as keyof IIssue));
const groupArray = this.getGroupArray(get(_issue, groupBy as keyof IIssue));
for (const subGroup of subGroupArray) {
for (const group of groupArray) {
@ -121,22 +125,22 @@ export class IssueBaseStore implements IIssueBaseStore {
};
issuesSortWithOrderBy = (issueObject: IIssueResponse, key: Partial<TIssueOrderByOptions>): IIssue[] => {
let array = _.values(issueObject);
array = _.sortBy(array, "created_at");
let array = values(issueObject);
array = sortBy(array, "created_at");
switch (key) {
case "sort_order":
return _.sortBy(array, "sort_order");
return sortBy(array, "sort_order");
case "-created_at":
return _.reverse(_.sortBy(array, "created_at"));
return reverse(sortBy(array, "created_at"));
case "-updated_at":
return _.reverse(_.sortBy(array, "updated_at"));
return reverse(sortBy(array, "updated_at"));
case "start_date":
return _.sortBy(array, "start_date");
return sortBy(array, "start_date");
case "target_date":
return _.sortBy(array, "target_date");
return sortBy(array, "target_date");
case "priority": {
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:
return array;

View File

@ -94,24 +94,15 @@ export class ProjectIssuesStore extends IssueBaseStore implements IProjectIssues
let issues: IIssueResponse | IGroupedIssues | ISubGroupedIssues | TUnGroupedIssues | undefined = undefined;
if (layout === "list" && orderBy) {
console.log("list");
if (groupBy) issues = this.groupedIssues(groupBy, orderBy, this.issues[projectId]);
else issues = this.unGroupedIssues(orderBy, this.issues[projectId]);
} else if (layout === "kanban" && groupBy && orderBy) {
console.log("kanban");
if (subGroupBy) issues = this.subGroupedIssues(subGroupBy, groupBy, orderBy, this.issues[projectId]);
else issues = this.groupedIssues(groupBy, orderBy, this.issues[projectId]);
console.log("issues", issues);
} else if (layout === "calendar") {
console.log("calendar");
} else if (layout === "calendar")
issues = this.groupedIssues("target_date" as TIssueGroupByOptions, "target_date", this.issues[projectId], true);
} else if (layout === "spreadsheet") {
console.log("spreadsheet");
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]);
}
else if (layout === "spreadsheet") issues = this.unGroupedIssues(orderBy ?? "-created_at", this.issues[projectId]);
else if (layout === "gantt_chart") issues = this.unGroupedIssues(orderBy ?? "sort_order", this.issues[projectId]);
return issues;
}

View File

@ -164,6 +164,11 @@ import {
// global issues filter
IGlobalIssuesFilterStore,
GlobalIssuesFilterStore,
// helpers
ICalendarHelpers,
CalendarHelpers,
IKanBanHelpers,
KanBanHelpers,
} from "store/issues";
import { CycleIssueFiltersStore, ICycleIssueFiltersStore } from "store/cycle-issues";
@ -274,6 +279,10 @@ export class RootStore {
workspaceGlobalIssues: IGlobalIssuesStore;
workspaceGlobalIssuesFilter: IGlobalIssuesFilterStore;
calendarHelpers: ICalendarHelpers;
kanBanHelpers: IKanBanHelpers;
// project v3 issue and issue-filters ends
cycleIssueFilters: ICycleIssueFiltersStore;
@ -378,6 +387,10 @@ export class RootStore {
this.workspaceGlobalIssues = new GlobalIssuesStore(this);
this.workspaceGlobalIssuesFilter = new GlobalIssuesFilterStore(this);
this.calendarHelpers = new CalendarHelpers();
this.kanBanHelpers = new KanBanHelpers();
// project v3 issue and issue-filters ends
this.cycleIssueFilters = new CycleIssueFiltersStore(this);