forked from github/plane
fix: gantt chart blocks drag and resize logic (#2516)
This commit is contained in:
parent
c739b7235d
commit
05a76c5ee3
@ -4,14 +4,14 @@ import { observer } from "mobx-react-lite";
|
|||||||
import { useMobxStore } from "lib/mobx/store-provider";
|
import { useMobxStore } from "lib/mobx/store-provider";
|
||||||
import useProjectDetails from "hooks/use-project-details";
|
import useProjectDetails from "hooks/use-project-details";
|
||||||
// components
|
// components
|
||||||
import { GanttChartRoot, renderIssueBlocksStructure } from "components/gantt-chart";
|
import { GanttChartRoot, IBlockUpdateData, renderIssueBlocksStructure } from "components/gantt-chart";
|
||||||
import { IssueGanttBlock, IssueGanttSidebarBlock, IssuePeekOverview } from "components/issues";
|
import { IssueGanttBlock, IssueGanttSidebarBlock } from "components/issues";
|
||||||
// types
|
// types
|
||||||
import { IIssueUnGroupedStructure } from "store/issue";
|
import { IIssueUnGroupedStructure } from "store/issue";
|
||||||
|
|
||||||
export const CycleGanttLayout: React.FC = observer(() => {
|
export const CycleGanttLayout: React.FC = observer(() => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, projectId } = router.query;
|
const { workspaceSlug, cycleId } = router.query;
|
||||||
|
|
||||||
const { projectDetails } = useProjectDetails();
|
const { projectDetails } = useProjectDetails();
|
||||||
|
|
||||||
@ -21,26 +21,23 @@ export const CycleGanttLayout: React.FC = observer(() => {
|
|||||||
|
|
||||||
const issues = cycleIssueStore.getIssues;
|
const issues = cycleIssueStore.getIssues;
|
||||||
|
|
||||||
|
const updateIssue = (block: any, payload: IBlockUpdateData) => {
|
||||||
|
if (!workspaceSlug || !cycleId) return;
|
||||||
|
|
||||||
|
cycleIssueStore.updateGanttIssueStructure(workspaceSlug.toString(), cycleId.toString(), block, payload);
|
||||||
|
};
|
||||||
|
|
||||||
const isAllowed = projectDetails?.member_role === 20 || projectDetails?.member_role === 15;
|
const isAllowed = projectDetails?.member_role === 20 || projectDetails?.member_role === 15;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<IssuePeekOverview
|
|
||||||
projectId={projectId?.toString() ?? ""}
|
|
||||||
workspaceSlug={workspaceSlug?.toString() ?? ""}
|
|
||||||
readOnly={!isAllowed}
|
|
||||||
/>
|
|
||||||
<div className="w-full h-full">
|
<div className="w-full h-full">
|
||||||
<GanttChartRoot
|
<GanttChartRoot
|
||||||
border={false}
|
border={false}
|
||||||
title="Issues"
|
title="Issues"
|
||||||
loaderTitle="Issues"
|
loaderTitle="Issues"
|
||||||
blocks={issues ? renderIssueBlocksStructure(issues as IIssueUnGroupedStructure) : null}
|
blocks={issues ? renderIssueBlocksStructure(issues as IIssueUnGroupedStructure) : null}
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
blockUpdateHandler={updateIssue}
|
||||||
blockUpdateHandler={(block, payload) => {
|
|
||||||
// TODO: update mutation logic
|
|
||||||
// updateGanttIssue(block, payload, mutateGanttIssues, user, workspaceSlug?.toString())
|
|
||||||
}}
|
|
||||||
BlockRender={IssueGanttBlock}
|
BlockRender={IssueGanttBlock}
|
||||||
SidebarBlockRender={IssueGanttSidebarBlock}
|
SidebarBlockRender={IssueGanttSidebarBlock}
|
||||||
enableBlockLeftResize={isAllowed}
|
enableBlockLeftResize={isAllowed}
|
||||||
|
@ -4,14 +4,14 @@ import { observer } from "mobx-react-lite";
|
|||||||
import { useMobxStore } from "lib/mobx/store-provider";
|
import { useMobxStore } from "lib/mobx/store-provider";
|
||||||
import useProjectDetails from "hooks/use-project-details";
|
import useProjectDetails from "hooks/use-project-details";
|
||||||
// components
|
// components
|
||||||
import { GanttChartRoot, renderIssueBlocksStructure } from "components/gantt-chart";
|
import { GanttChartRoot, IBlockUpdateData, renderIssueBlocksStructure } from "components/gantt-chart";
|
||||||
import { IssueGanttBlock, IssueGanttSidebarBlock, IssuePeekOverview } from "components/issues";
|
import { IssueGanttBlock, IssueGanttSidebarBlock } from "components/issues";
|
||||||
// types
|
// types
|
||||||
import { IIssueUnGroupedStructure } from "store/issue";
|
import { IIssueUnGroupedStructure } from "store/issue";
|
||||||
|
|
||||||
export const ModuleGanttLayout: React.FC = observer(() => {
|
export const ModuleGanttLayout: React.FC = observer(() => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, projectId } = router.query;
|
const { workspaceSlug, moduleId } = router.query;
|
||||||
|
|
||||||
const { projectDetails } = useProjectDetails();
|
const { projectDetails } = useProjectDetails();
|
||||||
|
|
||||||
@ -21,26 +21,23 @@ export const ModuleGanttLayout: React.FC = observer(() => {
|
|||||||
|
|
||||||
const issues = moduleIssueStore.getIssues;
|
const issues = moduleIssueStore.getIssues;
|
||||||
|
|
||||||
|
const updateIssue = (block: any, payload: IBlockUpdateData) => {
|
||||||
|
if (!workspaceSlug || !moduleId) return;
|
||||||
|
|
||||||
|
moduleIssueStore.updateGanttIssueStructure(workspaceSlug.toString(), moduleId.toString(), block, payload);
|
||||||
|
};
|
||||||
|
|
||||||
const isAllowed = projectDetails?.member_role === 20 || projectDetails?.member_role === 15;
|
const isAllowed = projectDetails?.member_role === 20 || projectDetails?.member_role === 15;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<IssuePeekOverview
|
|
||||||
projectId={projectId?.toString() ?? ""}
|
|
||||||
workspaceSlug={workspaceSlug?.toString() ?? ""}
|
|
||||||
readOnly={!isAllowed}
|
|
||||||
/>
|
|
||||||
<div className="w-full h-full">
|
<div className="w-full h-full">
|
||||||
<GanttChartRoot
|
<GanttChartRoot
|
||||||
border={false}
|
border={false}
|
||||||
title="Issues"
|
title="Issues"
|
||||||
loaderTitle="Issues"
|
loaderTitle="Issues"
|
||||||
blocks={issues ? renderIssueBlocksStructure(issues as IIssueUnGroupedStructure) : null}
|
blocks={issues ? renderIssueBlocksStructure(issues as IIssueUnGroupedStructure) : null}
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
blockUpdateHandler={updateIssue}
|
||||||
blockUpdateHandler={(block, payload) => {
|
|
||||||
// TODO: update mutation logic
|
|
||||||
// updateGanttIssue(block, payload, mutateGanttIssues, user, workspaceSlug?.toString())
|
|
||||||
}}
|
|
||||||
BlockRender={IssueGanttBlock}
|
BlockRender={IssueGanttBlock}
|
||||||
SidebarBlockRender={IssueGanttSidebarBlock}
|
SidebarBlockRender={IssueGanttSidebarBlock}
|
||||||
enableBlockLeftResize={isAllowed}
|
enableBlockLeftResize={isAllowed}
|
||||||
|
@ -6,14 +6,14 @@ import { useMobxStore } from "lib/mobx/store-provider";
|
|||||||
// hooks
|
// hooks
|
||||||
import useProjectDetails from "hooks/use-project-details";
|
import useProjectDetails from "hooks/use-project-details";
|
||||||
// components
|
// components
|
||||||
import { GanttChartRoot, renderIssueBlocksStructure } from "components/gantt-chart";
|
import { GanttChartRoot, IBlockUpdateData, renderIssueBlocksStructure } from "components/gantt-chart";
|
||||||
import { IssueGanttBlock, IssueGanttSidebarBlock, IssuePeekOverview } from "components/issues";
|
import { IssueGanttBlock, IssueGanttSidebarBlock } from "components/issues";
|
||||||
// types
|
// types
|
||||||
import { IIssueUnGroupedStructure } from "store/issue";
|
import { IIssueUnGroupedStructure } from "store/issue";
|
||||||
|
|
||||||
export const ProjectViewGanttLayout: React.FC = observer(() => {
|
export const ProjectViewGanttLayout: React.FC = observer(() => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, projectId } = router.query;
|
const { workspaceSlug, viewId } = router.query;
|
||||||
|
|
||||||
const { projectDetails } = useProjectDetails();
|
const { projectDetails } = useProjectDetails();
|
||||||
|
|
||||||
@ -23,26 +23,23 @@ export const ProjectViewGanttLayout: React.FC = observer(() => {
|
|||||||
|
|
||||||
const issues = projectViewIssuesStore.getIssues;
|
const issues = projectViewIssuesStore.getIssues;
|
||||||
|
|
||||||
|
const updateIssue = (block: any, payload: IBlockUpdateData) => {
|
||||||
|
if (!workspaceSlug || !viewId) return;
|
||||||
|
|
||||||
|
projectViewIssuesStore.updateGanttIssueStructure(workspaceSlug.toString(), viewId.toString(), block, payload);
|
||||||
|
};
|
||||||
|
|
||||||
const isAllowed = projectDetails?.member_role === 20 || projectDetails?.member_role === 15;
|
const isAllowed = projectDetails?.member_role === 20 || projectDetails?.member_role === 15;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<IssuePeekOverview
|
|
||||||
projectId={projectId?.toString() ?? ""}
|
|
||||||
workspaceSlug={workspaceSlug?.toString() ?? ""}
|
|
||||||
readOnly={!isAllowed}
|
|
||||||
/>
|
|
||||||
<div className="w-full h-full">
|
<div className="w-full h-full">
|
||||||
<GanttChartRoot
|
<GanttChartRoot
|
||||||
border={false}
|
border={false}
|
||||||
title="Issues"
|
title="Issues"
|
||||||
loaderTitle="Issues"
|
loaderTitle="Issues"
|
||||||
blocks={issues ? renderIssueBlocksStructure(issues as IIssueUnGroupedStructure) : null}
|
blocks={issues ? renderIssueBlocksStructure(issues as IIssueUnGroupedStructure) : null}
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
blockUpdateHandler={updateIssue}
|
||||||
blockUpdateHandler={(block, payload) => {
|
|
||||||
// TODO: update mutation logic
|
|
||||||
// updateGanttIssue(block, payload, mutateGanttIssues, user, workspaceSlug?.toString())
|
|
||||||
}}
|
|
||||||
BlockRender={IssueGanttBlock}
|
BlockRender={IssueGanttBlock}
|
||||||
SidebarBlockRender={IssueGanttSidebarBlock}
|
SidebarBlockRender={IssueGanttSidebarBlock}
|
||||||
enableBlockLeftResize={isAllowed}
|
enableBlockLeftResize={isAllowed}
|
||||||
|
@ -4,14 +4,14 @@ import { observer } from "mobx-react-lite";
|
|||||||
import { useMobxStore } from "lib/mobx/store-provider";
|
import { useMobxStore } from "lib/mobx/store-provider";
|
||||||
import useProjectDetails from "hooks/use-project-details";
|
import useProjectDetails from "hooks/use-project-details";
|
||||||
// components
|
// components
|
||||||
import { GanttChartRoot, renderIssueBlocksStructure } from "components/gantt-chart";
|
import { GanttChartRoot, IBlockUpdateData, renderIssueBlocksStructure } from "components/gantt-chart";
|
||||||
import { IssueGanttBlock, IssueGanttSidebarBlock, IssuePeekOverview } from "components/issues";
|
import { IssueGanttBlock, IssueGanttSidebarBlock } from "components/issues";
|
||||||
// types
|
// types
|
||||||
import { IIssueUnGroupedStructure } from "store/issue";
|
import { IIssueUnGroupedStructure } from "store/issue";
|
||||||
|
|
||||||
export const GanttLayout: React.FC = observer(() => {
|
export const GanttLayout: React.FC = observer(() => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, projectId } = router.query;
|
const { workspaceSlug } = router.query;
|
||||||
|
|
||||||
const { projectDetails } = useProjectDetails();
|
const { projectDetails } = useProjectDetails();
|
||||||
|
|
||||||
@ -21,26 +21,23 @@ export const GanttLayout: React.FC = observer(() => {
|
|||||||
|
|
||||||
const issues = issueStore.getIssues;
|
const issues = issueStore.getIssues;
|
||||||
|
|
||||||
|
const updateIssue = (block: any, payload: IBlockUpdateData) => {
|
||||||
|
if (!workspaceSlug) return;
|
||||||
|
|
||||||
|
issueStore.updateGanttIssueStructure(workspaceSlug.toString(), block, payload);
|
||||||
|
};
|
||||||
|
|
||||||
const isAllowed = projectDetails?.member_role === 20 || projectDetails?.member_role === 15;
|
const isAllowed = projectDetails?.member_role === 20 || projectDetails?.member_role === 15;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<IssuePeekOverview
|
|
||||||
projectId={projectId?.toString() ?? ""}
|
|
||||||
workspaceSlug={workspaceSlug?.toString() ?? ""}
|
|
||||||
readOnly={!isAllowed}
|
|
||||||
/>
|
|
||||||
<div className="w-full h-full">
|
<div className="w-full h-full">
|
||||||
<GanttChartRoot
|
<GanttChartRoot
|
||||||
border={false}
|
border={false}
|
||||||
title="Issues"
|
title="Issues"
|
||||||
loaderTitle="Issues"
|
loaderTitle="Issues"
|
||||||
blocks={issues ? renderIssueBlocksStructure(issues as IIssueUnGroupedStructure) : null}
|
blocks={issues ? renderIssueBlocksStructure(issues as IIssueUnGroupedStructure) : null}
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
blockUpdateHandler={updateIssue}
|
||||||
blockUpdateHandler={(block, payload) => {
|
|
||||||
// TODO: update mutation logic
|
|
||||||
// updateGanttIssue(block, payload, mutateGanttIssues, user, workspaceSlug?.toString())
|
|
||||||
}}
|
|
||||||
BlockRender={IssueGanttBlock}
|
BlockRender={IssueGanttBlock}
|
||||||
SidebarBlockRender={IssueGanttSidebarBlock}
|
SidebarBlockRender={IssueGanttSidebarBlock}
|
||||||
enableBlockLeftResize={isAllowed}
|
enableBlockLeftResize={isAllowed}
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
import { observable, action, computed, makeObservable, runInAction, autorun } from "mobx";
|
import { observable, action, computed, makeObservable, runInAction, autorun } from "mobx";
|
||||||
// store
|
// store
|
||||||
import { RootStore } from "../root";
|
import { RootStore } from "../root";
|
||||||
// types
|
|
||||||
import { IIssue } from "types";
|
|
||||||
// services
|
// services
|
||||||
import { CycleService } from "services/cycle.service";
|
import { CycleService } from "services/cycle.service";
|
||||||
import { IssueService } from "services/issue";
|
import { IssueService } from "services/issue";
|
||||||
// constants
|
// constants
|
||||||
import { sortArrayByDate, sortArrayByPriority } from "constants/kanban-helpers";
|
import { sortArrayByDate, sortArrayByPriority } from "constants/kanban-helpers";
|
||||||
|
// types
|
||||||
|
import { IIssue } from "types";
|
||||||
|
import { IBlockUpdateData } from "components/gantt-chart";
|
||||||
|
|
||||||
export type IIssueType = "grouped" | "groupWithSubGroups" | "ungrouped";
|
export type IIssueType = "grouped" | "groupWithSubGroups" | "ungrouped";
|
||||||
export type IIssueGroupedStructure = { [group_id: string]: IIssue[] };
|
export type IIssueGroupedStructure = { [group_id: string]: IIssue[] };
|
||||||
@ -35,6 +36,7 @@ export interface ICycleIssueStore {
|
|||||||
// action
|
// action
|
||||||
fetchIssues: (workspaceSlug: string, projectId: string, cycleId: string) => Promise<any>;
|
fetchIssues: (workspaceSlug: string, projectId: string, cycleId: string) => Promise<any>;
|
||||||
updateIssueStructure: (group_id: string | null, sub_group_id: string | null, issue: IIssue) => void;
|
updateIssueStructure: (group_id: string | null, sub_group_id: string | null, issue: IIssue) => void;
|
||||||
|
updateGanttIssueStructure: (workspaceSlug: string, cycleId: string, issue: IIssue, payload: IBlockUpdateData) => void;
|
||||||
deleteIssue: (group_id: string | null, sub_group_id: string | null, issue: IIssue) => void;
|
deleteIssue: (group_id: string | null, sub_group_id: string | null, issue: IIssue) => void;
|
||||||
addIssueToCycle: (workspaceSlug: string, projectId: string, cycleId: string, issueId: string) => void;
|
addIssueToCycle: (workspaceSlug: string, projectId: string, cycleId: string, issueId: string) => void;
|
||||||
removeIssueFromCycle: (workspaceSlug: string, projectId: string, cycleId: string, bridgeId: string) => void;
|
removeIssueFromCycle: (workspaceSlug: string, projectId: string, cycleId: string, bridgeId: string) => void;
|
||||||
@ -74,6 +76,7 @@ export class CycleIssueStore implements ICycleIssueStore {
|
|||||||
// actions
|
// actions
|
||||||
fetchIssues: action,
|
fetchIssues: action,
|
||||||
updateIssueStructure: action,
|
updateIssueStructure: action,
|
||||||
|
updateGanttIssueStructure: action,
|
||||||
deleteIssue: action,
|
deleteIssue: action,
|
||||||
addIssueToCycle: action,
|
addIssueToCycle: action,
|
||||||
removeIssueFromCycle: action,
|
removeIssueFromCycle: action,
|
||||||
@ -169,6 +172,50 @@ export class CycleIssueStore implements ICycleIssueStore {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
updateGanttIssueStructure = async (
|
||||||
|
workspaceSlug: string,
|
||||||
|
cycleId: string,
|
||||||
|
issue: IIssue,
|
||||||
|
payload: IBlockUpdateData
|
||||||
|
) => {
|
||||||
|
if (!issue || !workspaceSlug) return;
|
||||||
|
|
||||||
|
const issues = this.getIssues as IIssueUnGroupedStructure;
|
||||||
|
|
||||||
|
const newIssues = issues.map((i) => ({
|
||||||
|
...i,
|
||||||
|
...(i.id === issue.id
|
||||||
|
? {
|
||||||
|
sort_order: payload.sort_order?.newSortOrder ?? i.sort_order,
|
||||||
|
start_date: payload.start_date,
|
||||||
|
target_date: payload.target_date,
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (payload.sort_order) {
|
||||||
|
const removedElement = newIssues.splice(payload.sort_order.sourceIndex, 1)[0];
|
||||||
|
removedElement.sort_order = payload.sort_order.newSortOrder;
|
||||||
|
newIssues.splice(payload.sort_order.destinationIndex, 0, removedElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
runInAction(() => {
|
||||||
|
this.issues = {
|
||||||
|
...this.issues,
|
||||||
|
[cycleId]: {
|
||||||
|
...this.issues[cycleId],
|
||||||
|
ungrouped: newIssues,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const newPayload: any = { ...payload };
|
||||||
|
|
||||||
|
if (newPayload.sort_order && payload.sort_order) newPayload.sort_order = payload.sort_order.newSortOrder;
|
||||||
|
|
||||||
|
this.rootStore.issueDetail.updateIssue(workspaceSlug, issue.project, issue.id, newPayload);
|
||||||
|
};
|
||||||
|
|
||||||
deleteIssue = async (group_id: string | null, sub_group_id: string | null, issue: IIssue) => {
|
deleteIssue = async (group_id: string | null, sub_group_id: string | null, issue: IIssue) => {
|
||||||
const cycleId: string | null = this.rootStore.cycle.cycleId;
|
const cycleId: string | null = this.rootStore.cycle.cycleId;
|
||||||
const issueType = this.getIssueType;
|
const issueType = this.getIssueType;
|
||||||
|
@ -6,6 +6,7 @@ import { IIssue } from "types";
|
|||||||
// services
|
// services
|
||||||
import { IssueService } from "services/issue";
|
import { IssueService } from "services/issue";
|
||||||
import { sortArrayByDate, sortArrayByPriority } from "constants/kanban-helpers";
|
import { sortArrayByDate, sortArrayByPriority } from "constants/kanban-helpers";
|
||||||
|
import { IBlockUpdateData } from "components/gantt-chart";
|
||||||
|
|
||||||
export type IIssueType = "grouped" | "groupWithSubGroups" | "ungrouped";
|
export type IIssueType = "grouped" | "groupWithSubGroups" | "ungrouped";
|
||||||
export type IIssueGroupedStructure = { [group_id: string]: IIssue[] };
|
export type IIssueGroupedStructure = { [group_id: string]: IIssue[] };
|
||||||
@ -34,6 +35,7 @@ export interface IIssueStore {
|
|||||||
fetchIssues: (workspaceSlug: string, projectId: string) => Promise<any>;
|
fetchIssues: (workspaceSlug: string, projectId: string) => Promise<any>;
|
||||||
updateIssueStructure: (group_id: string | null, sub_group_id: string | null, issue: IIssue) => void;
|
updateIssueStructure: (group_id: string | null, sub_group_id: string | null, issue: IIssue) => void;
|
||||||
deleteIssue: (group_id: string | null, sub_group_id: string | null, issue: IIssue) => void;
|
deleteIssue: (group_id: string | null, sub_group_id: string | null, issue: IIssue) => void;
|
||||||
|
updateGanttIssueStructure: (workspaceSlug: string, issue: IIssue, payload: IBlockUpdateData) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class IssueStore implements IIssueStore {
|
export class IssueStore implements IIssueStore {
|
||||||
@ -69,6 +71,7 @@ export class IssueStore implements IIssueStore {
|
|||||||
fetchIssues: action,
|
fetchIssues: action,
|
||||||
updateIssueStructure: action,
|
updateIssueStructure: action,
|
||||||
deleteIssue: action,
|
deleteIssue: action,
|
||||||
|
updateGanttIssueStructure: action,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.rootStore = _rootStore;
|
this.rootStore = _rootStore;
|
||||||
@ -165,6 +168,45 @@ export class IssueStore implements IIssueStore {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
updateGanttIssueStructure = async (workspaceSlug: string, issue: IIssue, payload: IBlockUpdateData) => {
|
||||||
|
if (!issue || !workspaceSlug) return;
|
||||||
|
|
||||||
|
const issues = this.getIssues as IIssueUnGroupedStructure;
|
||||||
|
|
||||||
|
const newIssues = issues.map((i) => ({
|
||||||
|
...i,
|
||||||
|
...(i.id === issue.id
|
||||||
|
? {
|
||||||
|
sort_order: payload.sort_order?.newSortOrder ?? i.sort_order,
|
||||||
|
start_date: payload.start_date,
|
||||||
|
target_date: payload.target_date,
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (payload.sort_order) {
|
||||||
|
const removedElement = newIssues.splice(payload.sort_order.sourceIndex, 1)[0];
|
||||||
|
removedElement.sort_order = payload.sort_order.newSortOrder;
|
||||||
|
newIssues.splice(payload.sort_order.destinationIndex, 0, removedElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
runInAction(() => {
|
||||||
|
this.issues = {
|
||||||
|
...this.issues,
|
||||||
|
[issue.project]: {
|
||||||
|
...this.issues[issue.project],
|
||||||
|
ungrouped: newIssues,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const newPayload: any = { ...payload };
|
||||||
|
|
||||||
|
if (newPayload.sort_order && payload.sort_order) newPayload.sort_order = payload.sort_order.newSortOrder;
|
||||||
|
|
||||||
|
this.rootStore.issueDetail.updateIssue(workspaceSlug, issue.project, issue.id, newPayload);
|
||||||
|
};
|
||||||
|
|
||||||
deleteIssue = async (group_id: string | null, sub_group_id: string | null, issue: IIssue) => {
|
deleteIssue = async (group_id: string | null, sub_group_id: string | null, issue: IIssue) => {
|
||||||
const projectId: string | null = issue?.project;
|
const projectId: string | null = issue?.project;
|
||||||
const issueType = this.getIssueType;
|
const issueType = this.getIssueType;
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import { observable, action, computed, makeObservable, runInAction, autorun } from "mobx";
|
import { observable, action, computed, makeObservable, runInAction, autorun } from "mobx";
|
||||||
// store
|
// store
|
||||||
import { RootStore } from "../root";
|
import { RootStore } from "../root";
|
||||||
// types
|
|
||||||
import { IIssue } from "types";
|
|
||||||
// services
|
// services
|
||||||
import { ModuleService } from "services/module.service";
|
import { ModuleService } from "services/module.service";
|
||||||
// helpers
|
// helpers
|
||||||
import { sortArrayByDate, sortArrayByPriority } from "constants/kanban-helpers";
|
import { sortArrayByDate, sortArrayByPriority } from "constants/kanban-helpers";
|
||||||
|
// types
|
||||||
|
import { IIssue } from "types";
|
||||||
|
import { IBlockUpdateData } from "components/gantt-chart";
|
||||||
|
|
||||||
export type IIssueType = "grouped" | "groupWithSubGroups" | "ungrouped";
|
export type IIssueType = "grouped" | "groupWithSubGroups" | "ungrouped";
|
||||||
export type IIssueGroupedStructure = { [group_id: string]: IIssue[] };
|
export type IIssueGroupedStructure = { [group_id: string]: IIssue[] };
|
||||||
@ -34,6 +35,12 @@ export interface IModuleIssueStore {
|
|||||||
// action
|
// action
|
||||||
fetchIssues: (workspaceSlug: string, projectId: string, moduleId: string) => Promise<any>;
|
fetchIssues: (workspaceSlug: string, projectId: string, moduleId: string) => Promise<any>;
|
||||||
updateIssueStructure: (group_id: string | null, sub_group_id: string | null, issue: IIssue) => void;
|
updateIssueStructure: (group_id: string | null, sub_group_id: string | null, issue: IIssue) => void;
|
||||||
|
updateGanttIssueStructure: (
|
||||||
|
workspaceSlug: string,
|
||||||
|
moduleId: string,
|
||||||
|
issue: IIssue,
|
||||||
|
payload: IBlockUpdateData
|
||||||
|
) => void;
|
||||||
deleteIssue: (group_id: string | null, sub_group_id: string | null, issue: IIssue) => void;
|
deleteIssue: (group_id: string | null, sub_group_id: string | null, issue: IIssue) => void;
|
||||||
addIssueToModule: (workspaceSlug: string, projectId: string, moduleId: string, issueId: string) => Promise<any>;
|
addIssueToModule: (workspaceSlug: string, projectId: string, moduleId: string, issueId: string) => Promise<any>;
|
||||||
removeIssueFromModule: (workspaceSlug: string, projectId: string, moduleId: string, bridgeId: string) => Promise<any>;
|
removeIssueFromModule: (workspaceSlug: string, projectId: string, moduleId: string, bridgeId: string) => Promise<any>;
|
||||||
@ -72,6 +79,7 @@ export class ModuleIssueStore implements IModuleIssueStore {
|
|||||||
// actions
|
// actions
|
||||||
fetchIssues: action,
|
fetchIssues: action,
|
||||||
updateIssueStructure: action,
|
updateIssueStructure: action,
|
||||||
|
updateGanttIssueStructure: action,
|
||||||
deleteIssue: action,
|
deleteIssue: action,
|
||||||
addIssueToModule: action,
|
addIssueToModule: action,
|
||||||
removeIssueFromModule: action,
|
removeIssueFromModule: action,
|
||||||
@ -174,6 +182,50 @@ export class ModuleIssueStore implements IModuleIssueStore {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
updateGanttIssueStructure = async (
|
||||||
|
workspaceSlug: string,
|
||||||
|
moduleId: string,
|
||||||
|
issue: IIssue,
|
||||||
|
payload: IBlockUpdateData
|
||||||
|
) => {
|
||||||
|
if (!issue || !workspaceSlug) return;
|
||||||
|
|
||||||
|
const issues = this.getIssues as IIssueUnGroupedStructure;
|
||||||
|
|
||||||
|
const newIssues = issues.map((i) => ({
|
||||||
|
...i,
|
||||||
|
...(i.id === issue.id
|
||||||
|
? {
|
||||||
|
sort_order: payload.sort_order?.newSortOrder ?? i.sort_order,
|
||||||
|
start_date: payload.start_date,
|
||||||
|
target_date: payload.target_date,
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (payload.sort_order) {
|
||||||
|
const removedElement = newIssues.splice(payload.sort_order.sourceIndex, 1)[0];
|
||||||
|
removedElement.sort_order = payload.sort_order.newSortOrder;
|
||||||
|
newIssues.splice(payload.sort_order.destinationIndex, 0, removedElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
runInAction(() => {
|
||||||
|
this.issues = {
|
||||||
|
...this.issues,
|
||||||
|
[moduleId]: {
|
||||||
|
...this.issues[moduleId],
|
||||||
|
ungrouped: newIssues,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const newPayload: any = { ...payload };
|
||||||
|
|
||||||
|
if (newPayload.sort_order && payload.sort_order) newPayload.sort_order = payload.sort_order.newSortOrder;
|
||||||
|
|
||||||
|
this.rootStore.issueDetail.updateIssue(workspaceSlug, issue.project, issue.id, newPayload);
|
||||||
|
};
|
||||||
|
|
||||||
deleteIssue = async (group_id: string | null, sub_group_id: string | null, issue: IIssue) => {
|
deleteIssue = async (group_id: string | null, sub_group_id: string | null, issue: IIssue) => {
|
||||||
const moduleId: string | null = this.rootStore.module.moduleId;
|
const moduleId: string | null = this.rootStore.module.moduleId;
|
||||||
const issueType = this.getIssueType;
|
const issueType = this.getIssueType;
|
||||||
|
@ -3,16 +3,12 @@ import { observable, action, makeObservable, runInAction, computed, autorun } fr
|
|||||||
import { IssueService } from "services/issue";
|
import { IssueService } from "services/issue";
|
||||||
// helpers
|
// helpers
|
||||||
import { handleIssueQueryParamsByLayout } from "helpers/issue.helper";
|
import { handleIssueQueryParamsByLayout } from "helpers/issue.helper";
|
||||||
|
import { sortArrayByDate, sortArrayByPriority } from "constants/kanban-helpers";
|
||||||
// types
|
// types
|
||||||
import { RootStore } from "../root";
|
import { RootStore } from "../root";
|
||||||
|
import { IIssueGroupWithSubGroupsStructure, IIssueGroupedStructure, IIssueUnGroupedStructure } from "store/issue";
|
||||||
import { IIssue, IIssueFilterOptions } from "types";
|
import { IIssue, IIssueFilterOptions } from "types";
|
||||||
import {
|
import { IBlockUpdateData } from "components/gantt-chart";
|
||||||
IIssueGroupWithSubGroupsStructure,
|
|
||||||
IIssueGroupedStructure,
|
|
||||||
IIssueUnGroupedStructure,
|
|
||||||
} from "../module/module_issue.store";
|
|
||||||
// helpers
|
|
||||||
import { sortArrayByDate, sortArrayByPriority } from "constants/kanban-helpers";
|
|
||||||
|
|
||||||
export interface IProjectViewIssuesStore {
|
export interface IProjectViewIssuesStore {
|
||||||
// states
|
// states
|
||||||
@ -30,6 +26,7 @@ export interface IProjectViewIssuesStore {
|
|||||||
|
|
||||||
// actions
|
// actions
|
||||||
updateIssueStructure: (group_id: string | null, sub_group_id: string | null, issue: IIssue) => void;
|
updateIssueStructure: (group_id: string | null, sub_group_id: string | null, issue: IIssue) => void;
|
||||||
|
updateGanttIssueStructure: (workspaceSlug: string, viewId: string, issue: IIssue, payload: IBlockUpdateData) => void;
|
||||||
deleteIssue: (group_id: string | null, sub_group_id: string | null, issue: IIssue) => void;
|
deleteIssue: (group_id: string | null, sub_group_id: string | null, issue: IIssue) => void;
|
||||||
fetchViewIssues: (
|
fetchViewIssues: (
|
||||||
workspaceSlug: string,
|
workspaceSlug: string,
|
||||||
@ -73,6 +70,7 @@ export class ProjectViewIssuesStore implements IProjectViewIssuesStore {
|
|||||||
|
|
||||||
// actions
|
// actions
|
||||||
updateIssueStructure: action,
|
updateIssueStructure: action,
|
||||||
|
updateGanttIssueStructure: action,
|
||||||
deleteIssue: action,
|
deleteIssue: action,
|
||||||
fetchViewIssues: action,
|
fetchViewIssues: action,
|
||||||
|
|
||||||
@ -169,6 +167,50 @@ export class ProjectViewIssuesStore implements IProjectViewIssuesStore {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
updateGanttIssueStructure = async (
|
||||||
|
workspaceSlug: string,
|
||||||
|
viewId: string,
|
||||||
|
issue: IIssue,
|
||||||
|
payload: IBlockUpdateData
|
||||||
|
) => {
|
||||||
|
if (!issue || !workspaceSlug) return;
|
||||||
|
|
||||||
|
const issues = this.getIssues as IIssueUnGroupedStructure;
|
||||||
|
|
||||||
|
const newIssues = issues.map((i) => ({
|
||||||
|
...i,
|
||||||
|
...(i.id === issue.id
|
||||||
|
? {
|
||||||
|
sort_order: payload.sort_order?.newSortOrder ?? i.sort_order,
|
||||||
|
start_date: payload.start_date,
|
||||||
|
target_date: payload.target_date,
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (payload.sort_order) {
|
||||||
|
const removedElement = newIssues.splice(payload.sort_order.sourceIndex, 1)[0];
|
||||||
|
removedElement.sort_order = payload.sort_order.newSortOrder;
|
||||||
|
newIssues.splice(payload.sort_order.destinationIndex, 0, removedElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
runInAction(() => {
|
||||||
|
this.viewIssues = {
|
||||||
|
...this.viewIssues,
|
||||||
|
[viewId]: {
|
||||||
|
...this.viewIssues[viewId],
|
||||||
|
ungrouped: newIssues,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const newPayload: any = { ...payload };
|
||||||
|
|
||||||
|
if (newPayload.sort_order && payload.sort_order) newPayload.sort_order = payload.sort_order.newSortOrder;
|
||||||
|
|
||||||
|
this.rootStore.issueDetail.updateIssue(workspaceSlug, issue.project, issue.id, newPayload);
|
||||||
|
};
|
||||||
|
|
||||||
deleteIssue = async (group_id: string | null, sub_group_id: string | null, issue: IIssue) => {
|
deleteIssue = async (group_id: string | null, sub_group_id: string | null, issue: IIssue) => {
|
||||||
const viewId: string | null = this.rootStore.projectViews.viewId;
|
const viewId: string | null = this.rootStore.projectViews.viewId;
|
||||||
const issueType = this.rootStore.issue.getIssueType;
|
const issueType = this.rootStore.issue.getIssueType;
|
||||||
|
Loading…
Reference in New Issue
Block a user