diff --git a/web/components/issues/issue-layouts/gantt/cycle-root.tsx b/web/components/issues/issue-layouts/gantt/cycle-root.tsx
index f411543e8..66b4dc05c 100644
--- a/web/components/issues/issue-layouts/gantt/cycle-root.tsx
+++ b/web/components/issues/issue-layouts/gantt/cycle-root.tsx
@@ -4,14 +4,14 @@ import { observer } from "mobx-react-lite";
import { useMobxStore } from "lib/mobx/store-provider";
import useProjectDetails from "hooks/use-project-details";
// components
-import { GanttChartRoot, renderIssueBlocksStructure } from "components/gantt-chart";
-import { IssueGanttBlock, IssueGanttSidebarBlock, IssuePeekOverview } from "components/issues";
+import { GanttChartRoot, IBlockUpdateData, renderIssueBlocksStructure } from "components/gantt-chart";
+import { IssueGanttBlock, IssueGanttSidebarBlock } from "components/issues";
// types
import { IIssueUnGroupedStructure } from "store/issue";
export const CycleGanttLayout: React.FC = observer(() => {
const router = useRouter();
- const { workspaceSlug, projectId } = router.query;
+ const { workspaceSlug, cycleId } = router.query;
const { projectDetails } = useProjectDetails();
@@ -21,26 +21,23 @@ export const CycleGanttLayout: React.FC = observer(() => {
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;
return (
<>
-
{
- // TODO: update mutation logic
- // updateGanttIssue(block, payload, mutateGanttIssues, user, workspaceSlug?.toString())
- }}
+ blockUpdateHandler={updateIssue}
BlockRender={IssueGanttBlock}
SidebarBlockRender={IssueGanttSidebarBlock}
enableBlockLeftResize={isAllowed}
diff --git a/web/components/issues/issue-layouts/gantt/module-root.tsx b/web/components/issues/issue-layouts/gantt/module-root.tsx
index 4158b663b..9c9d840b1 100644
--- a/web/components/issues/issue-layouts/gantt/module-root.tsx
+++ b/web/components/issues/issue-layouts/gantt/module-root.tsx
@@ -4,14 +4,14 @@ import { observer } from "mobx-react-lite";
import { useMobxStore } from "lib/mobx/store-provider";
import useProjectDetails from "hooks/use-project-details";
// components
-import { GanttChartRoot, renderIssueBlocksStructure } from "components/gantt-chart";
-import { IssueGanttBlock, IssueGanttSidebarBlock, IssuePeekOverview } from "components/issues";
+import { GanttChartRoot, IBlockUpdateData, renderIssueBlocksStructure } from "components/gantt-chart";
+import { IssueGanttBlock, IssueGanttSidebarBlock } from "components/issues";
// types
import { IIssueUnGroupedStructure } from "store/issue";
export const ModuleGanttLayout: React.FC = observer(() => {
const router = useRouter();
- const { workspaceSlug, projectId } = router.query;
+ const { workspaceSlug, moduleId } = router.query;
const { projectDetails } = useProjectDetails();
@@ -21,26 +21,23 @@ export const ModuleGanttLayout: React.FC = observer(() => {
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;
return (
<>
-
{
- // TODO: update mutation logic
- // updateGanttIssue(block, payload, mutateGanttIssues, user, workspaceSlug?.toString())
- }}
+ blockUpdateHandler={updateIssue}
BlockRender={IssueGanttBlock}
SidebarBlockRender={IssueGanttSidebarBlock}
enableBlockLeftResize={isAllowed}
diff --git a/web/components/issues/issue-layouts/gantt/project-view-root.tsx b/web/components/issues/issue-layouts/gantt/project-view-root.tsx
index 095137996..ce6ebe0f0 100644
--- a/web/components/issues/issue-layouts/gantt/project-view-root.tsx
+++ b/web/components/issues/issue-layouts/gantt/project-view-root.tsx
@@ -6,14 +6,14 @@ import { useMobxStore } from "lib/mobx/store-provider";
// hooks
import useProjectDetails from "hooks/use-project-details";
// components
-import { GanttChartRoot, renderIssueBlocksStructure } from "components/gantt-chart";
-import { IssueGanttBlock, IssueGanttSidebarBlock, IssuePeekOverview } from "components/issues";
+import { GanttChartRoot, IBlockUpdateData, renderIssueBlocksStructure } from "components/gantt-chart";
+import { IssueGanttBlock, IssueGanttSidebarBlock } from "components/issues";
// types
import { IIssueUnGroupedStructure } from "store/issue";
export const ProjectViewGanttLayout: React.FC = observer(() => {
const router = useRouter();
- const { workspaceSlug, projectId } = router.query;
+ const { workspaceSlug, viewId } = router.query;
const { projectDetails } = useProjectDetails();
@@ -23,26 +23,23 @@ export const ProjectViewGanttLayout: React.FC = observer(() => {
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;
return (
<>
-
{
- // TODO: update mutation logic
- // updateGanttIssue(block, payload, mutateGanttIssues, user, workspaceSlug?.toString())
- }}
+ blockUpdateHandler={updateIssue}
BlockRender={IssueGanttBlock}
SidebarBlockRender={IssueGanttSidebarBlock}
enableBlockLeftResize={isAllowed}
diff --git a/web/components/issues/issue-layouts/gantt/root.tsx b/web/components/issues/issue-layouts/gantt/root.tsx
index 8277aa52a..bf52e29f5 100644
--- a/web/components/issues/issue-layouts/gantt/root.tsx
+++ b/web/components/issues/issue-layouts/gantt/root.tsx
@@ -4,14 +4,14 @@ import { observer } from "mobx-react-lite";
import { useMobxStore } from "lib/mobx/store-provider";
import useProjectDetails from "hooks/use-project-details";
// components
-import { GanttChartRoot, renderIssueBlocksStructure } from "components/gantt-chart";
-import { IssueGanttBlock, IssueGanttSidebarBlock, IssuePeekOverview } from "components/issues";
+import { GanttChartRoot, IBlockUpdateData, renderIssueBlocksStructure } from "components/gantt-chart";
+import { IssueGanttBlock, IssueGanttSidebarBlock } from "components/issues";
// types
import { IIssueUnGroupedStructure } from "store/issue";
export const GanttLayout: React.FC = observer(() => {
const router = useRouter();
- const { workspaceSlug, projectId } = router.query;
+ const { workspaceSlug } = router.query;
const { projectDetails } = useProjectDetails();
@@ -21,26 +21,23 @@ export const GanttLayout: React.FC = observer(() => {
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;
return (
<>
-
{
- // TODO: update mutation logic
- // updateGanttIssue(block, payload, mutateGanttIssues, user, workspaceSlug?.toString())
- }}
+ blockUpdateHandler={updateIssue}
BlockRender={IssueGanttBlock}
SidebarBlockRender={IssueGanttSidebarBlock}
enableBlockLeftResize={isAllowed}
diff --git a/web/store/cycle/cycle_issue.store.ts b/web/store/cycle/cycle_issue.store.ts
index ce484c0bb..e343a733d 100644
--- a/web/store/cycle/cycle_issue.store.ts
+++ b/web/store/cycle/cycle_issue.store.ts
@@ -1,13 +1,14 @@
import { observable, action, computed, makeObservable, runInAction, autorun } from "mobx";
// store
import { RootStore } from "../root";
-// types
-import { IIssue } from "types";
// services
import { CycleService } from "services/cycle.service";
import { IssueService } from "services/issue";
// constants
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 IIssueGroupedStructure = { [group_id: string]: IIssue[] };
@@ -35,6 +36,7 @@ export interface ICycleIssueStore {
// action
fetchIssues: (workspaceSlug: string, projectId: string, cycleId: string) => Promise;
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;
addIssueToCycle: (workspaceSlug: string, projectId: string, cycleId: string, issueId: string) => void;
removeIssueFromCycle: (workspaceSlug: string, projectId: string, cycleId: string, bridgeId: string) => void;
@@ -74,6 +76,7 @@ export class CycleIssueStore implements ICycleIssueStore {
// actions
fetchIssues: action,
updateIssueStructure: action,
+ updateGanttIssueStructure: action,
deleteIssue: action,
addIssueToCycle: 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) => {
const cycleId: string | null = this.rootStore.cycle.cycleId;
const issueType = this.getIssueType;
diff --git a/web/store/issue/issue.store.ts b/web/store/issue/issue.store.ts
index 5b29fe9e2..ec337abcb 100644
--- a/web/store/issue/issue.store.ts
+++ b/web/store/issue/issue.store.ts
@@ -6,6 +6,7 @@ import { IIssue } from "types";
// services
import { IssueService } from "services/issue";
import { sortArrayByDate, sortArrayByPriority } from "constants/kanban-helpers";
+import { IBlockUpdateData } from "components/gantt-chart";
export type IIssueType = "grouped" | "groupWithSubGroups" | "ungrouped";
export type IIssueGroupedStructure = { [group_id: string]: IIssue[] };
@@ -34,6 +35,7 @@ export interface IIssueStore {
fetchIssues: (workspaceSlug: string, projectId: string) => Promise;
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;
+ updateGanttIssueStructure: (workspaceSlug: string, issue: IIssue, payload: IBlockUpdateData) => void;
}
export class IssueStore implements IIssueStore {
@@ -69,6 +71,7 @@ export class IssueStore implements IIssueStore {
fetchIssues: action,
updateIssueStructure: action,
deleteIssue: action,
+ updateGanttIssueStructure: action,
});
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) => {
const projectId: string | null = issue?.project;
const issueType = this.getIssueType;
diff --git a/web/store/module/module_issue.store.ts b/web/store/module/module_issue.store.ts
index 5cd794861..9751ef708 100644
--- a/web/store/module/module_issue.store.ts
+++ b/web/store/module/module_issue.store.ts
@@ -1,12 +1,13 @@
import { observable, action, computed, makeObservable, runInAction, autorun } from "mobx";
// store
import { RootStore } from "../root";
-// types
-import { IIssue } from "types";
// services
import { ModuleService } from "services/module.service";
// 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 IIssueGroupedStructure = { [group_id: string]: IIssue[] };
@@ -34,6 +35,12 @@ export interface IModuleIssueStore {
// action
fetchIssues: (workspaceSlug: string, projectId: string, moduleId: string) => Promise;
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;
addIssueToModule: (workspaceSlug: string, projectId: string, moduleId: string, issueId: string) => Promise;
removeIssueFromModule: (workspaceSlug: string, projectId: string, moduleId: string, bridgeId: string) => Promise;
@@ -72,6 +79,7 @@ export class ModuleIssueStore implements IModuleIssueStore {
// actions
fetchIssues: action,
updateIssueStructure: action,
+ updateGanttIssueStructure: action,
deleteIssue: action,
addIssueToModule: 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) => {
const moduleId: string | null = this.rootStore.module.moduleId;
const issueType = this.getIssueType;
diff --git a/web/store/project-view/project_view_issues.store.ts b/web/store/project-view/project_view_issues.store.ts
index 8022204cf..9588237fe 100644
--- a/web/store/project-view/project_view_issues.store.ts
+++ b/web/store/project-view/project_view_issues.store.ts
@@ -3,16 +3,12 @@ import { observable, action, makeObservable, runInAction, computed, autorun } fr
import { IssueService } from "services/issue";
// helpers
import { handleIssueQueryParamsByLayout } from "helpers/issue.helper";
+import { sortArrayByDate, sortArrayByPriority } from "constants/kanban-helpers";
// types
import { RootStore } from "../root";
+import { IIssueGroupWithSubGroupsStructure, IIssueGroupedStructure, IIssueUnGroupedStructure } from "store/issue";
import { IIssue, IIssueFilterOptions } from "types";
-import {
- IIssueGroupWithSubGroupsStructure,
- IIssueGroupedStructure,
- IIssueUnGroupedStructure,
-} from "../module/module_issue.store";
-// helpers
-import { sortArrayByDate, sortArrayByPriority } from "constants/kanban-helpers";
+import { IBlockUpdateData } from "components/gantt-chart";
export interface IProjectViewIssuesStore {
// states
@@ -30,6 +26,7 @@ export interface IProjectViewIssuesStore {
// actions
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;
fetchViewIssues: (
workspaceSlug: string,
@@ -73,6 +70,7 @@ export class ProjectViewIssuesStore implements IProjectViewIssuesStore {
// actions
updateIssueStructure: action,
+ updateGanttIssueStructure: action,
deleteIssue: 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) => {
const viewId: string | null = this.rootStore.projectViews.viewId;
const issueType = this.rootStore.issue.getIssueType;