mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
[WEB-1142] chore: optimistically add issue to cycle/modules (#4334)
* chore: optimistically add issue to cycle and module * chore: update toast alerts * refactor: module issue store * chore: added addCycleToIssueFunction
This commit is contained in:
parent
a85517de99
commit
780b239ecb
@ -34,7 +34,7 @@ export const IssueCycleSelect: React.FC<TIssueCycleSelect> = observer((props) =>
|
|||||||
const handleIssueCycleChange = async (cycleId: string | null) => {
|
const handleIssueCycleChange = async (cycleId: string | null) => {
|
||||||
if (!issue || issue.cycle_id === cycleId) return;
|
if (!issue || issue.cycle_id === cycleId) return;
|
||||||
setIsUpdating(true);
|
setIsUpdating(true);
|
||||||
if (cycleId) await issueOperations.addIssueToCycle?.(workspaceSlug, projectId, cycleId, [issueId]);
|
if (cycleId) await issueOperations.addCycleToIssue?.(workspaceSlug, projectId, cycleId, issueId);
|
||||||
else await issueOperations.removeIssueFromCycle?.(workspaceSlug, projectId, issue.cycle_id ?? "", issueId);
|
else await issueOperations.removeIssueFromCycle?.(workspaceSlug, projectId, issue.cycle_id ?? "", issueId);
|
||||||
setIsUpdating(false);
|
setIsUpdating(false);
|
||||||
};
|
};
|
||||||
|
@ -26,6 +26,7 @@ export type TIssueOperations = {
|
|||||||
remove: (workspaceSlug: string, projectId: string, issueId: string) => Promise<void>;
|
remove: (workspaceSlug: string, projectId: string, issueId: string) => Promise<void>;
|
||||||
archive?: (workspaceSlug: string, projectId: string, issueId: string) => Promise<void>;
|
archive?: (workspaceSlug: string, projectId: string, issueId: string) => Promise<void>;
|
||||||
restore?: (workspaceSlug: string, projectId: string, issueId: string) => Promise<void>;
|
restore?: (workspaceSlug: string, projectId: string, issueId: string) => Promise<void>;
|
||||||
|
addCycleToIssue?: (workspaceSlug: string, projectId: string, cycleId: string, issueId: string) => Promise<void>;
|
||||||
addIssueToCycle?: (workspaceSlug: string, projectId: string, cycleId: string, issueIds: string[]) => Promise<void>;
|
addIssueToCycle?: (workspaceSlug: string, projectId: string, cycleId: string, issueIds: string[]) => Promise<void>;
|
||||||
removeIssueFromCycle?: (workspaceSlug: string, projectId: string, cycleId: string, issueId: string) => Promise<void>;
|
removeIssueFromCycle?: (workspaceSlug: string, projectId: string, cycleId: string, issueId: string) => Promise<void>;
|
||||||
addModulesToIssue?: (workspaceSlug: string, projectId: string, issueId: string, moduleIds: string[]) => Promise<void>;
|
addModulesToIssue?: (workspaceSlug: string, projectId: string, issueId: string, moduleIds: string[]) => Promise<void>;
|
||||||
@ -62,6 +63,7 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
|
|||||||
updateIssue,
|
updateIssue,
|
||||||
removeIssue,
|
removeIssue,
|
||||||
archiveIssue,
|
archiveIssue,
|
||||||
|
addCycleToIssue,
|
||||||
addIssueToCycle,
|
addIssueToCycle,
|
||||||
removeIssueFromCycle,
|
removeIssueFromCycle,
|
||||||
addModulesToIssue,
|
addModulesToIssue,
|
||||||
@ -158,21 +160,38 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
addCycleToIssue: async (workspaceSlug: string, projectId: string, cycleId: string, issueId: string) => {
|
||||||
|
try {
|
||||||
|
await addCycleToIssue(workspaceSlug, projectId, cycleId, issueId);
|
||||||
|
captureIssueEvent({
|
||||||
|
eventName: ISSUE_UPDATED,
|
||||||
|
payload: { issueId, state: "SUCCESS", element: "Issue detail page" },
|
||||||
|
updates: {
|
||||||
|
changed_property: "cycle_id",
|
||||||
|
change_details: cycleId,
|
||||||
|
},
|
||||||
|
path: router.asPath,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
setToast({
|
||||||
|
type: TOAST_TYPE.ERROR,
|
||||||
|
title: "Error!",
|
||||||
|
message: "Issue could not be added to the cycle. Please try again.",
|
||||||
|
});
|
||||||
|
captureIssueEvent({
|
||||||
|
eventName: ISSUE_UPDATED,
|
||||||
|
payload: { state: "FAILED", element: "Issue detail page" },
|
||||||
|
updates: {
|
||||||
|
changed_property: "cycle_id",
|
||||||
|
change_details: cycleId,
|
||||||
|
},
|
||||||
|
path: router.asPath,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
addIssueToCycle: async (workspaceSlug: string, projectId: string, cycleId: string, issueIds: string[]) => {
|
addIssueToCycle: async (workspaceSlug: string, projectId: string, cycleId: string, issueIds: string[]) => {
|
||||||
try {
|
try {
|
||||||
const addToCyclePromise = addIssueToCycle(workspaceSlug, projectId, cycleId, issueIds);
|
await addIssueToCycle(workspaceSlug, projectId, cycleId, issueIds);
|
||||||
setPromiseToast(addToCyclePromise, {
|
|
||||||
loading: "Adding cycle to issue...",
|
|
||||||
success: {
|
|
||||||
title: "Success!",
|
|
||||||
message: () => "Cycle added to issue successfully",
|
|
||||||
},
|
|
||||||
error: {
|
|
||||||
title: "Error!",
|
|
||||||
message: () => "Cycle add to issue failed",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
await addToCyclePromise;
|
|
||||||
captureIssueEvent({
|
captureIssueEvent({
|
||||||
eventName: ISSUE_UPDATED,
|
eventName: ISSUE_UPDATED,
|
||||||
payload: { ...issueIds, state: "SUCCESS", element: "Issue detail page" },
|
payload: { ...issueIds, state: "SUCCESS", element: "Issue detail page" },
|
||||||
@ -183,6 +202,11 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
|
|||||||
path: router.asPath,
|
path: router.asPath,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
setToast({
|
||||||
|
type: TOAST_TYPE.ERROR,
|
||||||
|
title: "Error!",
|
||||||
|
message: "Issue could not be added to the cycle. Please try again.",
|
||||||
|
});
|
||||||
captureIssueEvent({
|
captureIssueEvent({
|
||||||
eventName: ISSUE_UPDATED,
|
eventName: ISSUE_UPDATED,
|
||||||
payload: { state: "FAILED", element: "Issue detail page" },
|
payload: { state: "FAILED", element: "Issue detail page" },
|
||||||
@ -198,14 +222,14 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
|
|||||||
try {
|
try {
|
||||||
const removeFromCyclePromise = removeIssueFromCycle(workspaceSlug, projectId, cycleId, issueId);
|
const removeFromCyclePromise = removeIssueFromCycle(workspaceSlug, projectId, cycleId, issueId);
|
||||||
setPromiseToast(removeFromCyclePromise, {
|
setPromiseToast(removeFromCyclePromise, {
|
||||||
loading: "Removing cycle from issue...",
|
loading: "Removing issue from the cycle...",
|
||||||
success: {
|
success: {
|
||||||
title: "Success!",
|
title: "Success!",
|
||||||
message: () => "Cycle removed from issue successfully",
|
message: () => "Issue removed from the cycle successfully.",
|
||||||
},
|
},
|
||||||
error: {
|
error: {
|
||||||
title: "Error!",
|
title: "Error!",
|
||||||
message: () => "Cycle remove from issue failed",
|
message: () => "Issue could not be removed from the cycle. Please try again.",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
await removeFromCyclePromise;
|
await removeFromCyclePromise;
|
||||||
@ -232,19 +256,7 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
|
|||||||
},
|
},
|
||||||
addModulesToIssue: async (workspaceSlug: string, projectId: string, issueId: string, moduleIds: string[]) => {
|
addModulesToIssue: async (workspaceSlug: string, projectId: string, issueId: string, moduleIds: string[]) => {
|
||||||
try {
|
try {
|
||||||
const addToModulePromise = addModulesToIssue(workspaceSlug, projectId, issueId, moduleIds);
|
const response = await addModulesToIssue(workspaceSlug, projectId, issueId, moduleIds);
|
||||||
setPromiseToast(addToModulePromise, {
|
|
||||||
loading: "Adding module to issue...",
|
|
||||||
success: {
|
|
||||||
title: "Success!",
|
|
||||||
message: () => "Module added to issue successfully",
|
|
||||||
},
|
|
||||||
error: {
|
|
||||||
title: "Error!",
|
|
||||||
message: () => "Module add to issue failed",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const response = await addToModulePromise;
|
|
||||||
captureIssueEvent({
|
captureIssueEvent({
|
||||||
eventName: ISSUE_UPDATED,
|
eventName: ISSUE_UPDATED,
|
||||||
payload: { ...response, state: "SUCCESS", element: "Issue detail page" },
|
payload: { ...response, state: "SUCCESS", element: "Issue detail page" },
|
||||||
@ -255,6 +267,11 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
|
|||||||
path: router.asPath,
|
path: router.asPath,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
setToast({
|
||||||
|
type: TOAST_TYPE.ERROR,
|
||||||
|
title: "Error!",
|
||||||
|
message: "Issue could not be added to the module. Please try again.",
|
||||||
|
});
|
||||||
captureIssueEvent({
|
captureIssueEvent({
|
||||||
eventName: ISSUE_UPDATED,
|
eventName: ISSUE_UPDATED,
|
||||||
payload: { id: issueId, state: "FAILED", element: "Issue detail page" },
|
payload: { id: issueId, state: "FAILED", element: "Issue detail page" },
|
||||||
@ -270,14 +287,14 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
|
|||||||
try {
|
try {
|
||||||
const removeFromModulePromise = removeIssueFromModule(workspaceSlug, projectId, moduleId, issueId);
|
const removeFromModulePromise = removeIssueFromModule(workspaceSlug, projectId, moduleId, issueId);
|
||||||
setPromiseToast(removeFromModulePromise, {
|
setPromiseToast(removeFromModulePromise, {
|
||||||
loading: "Removing module from issue...",
|
loading: "Removing issue from the module...",
|
||||||
success: {
|
success: {
|
||||||
title: "Success!",
|
title: "Success!",
|
||||||
message: () => "Module removed from issue successfully",
|
message: () => "Issue removed from the module successfully.",
|
||||||
},
|
},
|
||||||
error: {
|
error: {
|
||||||
title: "Error!",
|
title: "Error!",
|
||||||
message: () => "Module remove from issue failed",
|
message: () => "Issue could not be removed from the module. Please try again.",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
await removeFromModulePromise;
|
await removeFromModulePromise;
|
||||||
@ -335,6 +352,8 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
|
|||||||
addModulesToIssue,
|
addModulesToIssue,
|
||||||
removeIssueFromModule,
|
removeIssueFromModule,
|
||||||
removeModulesFromIssue,
|
removeModulesFromIssue,
|
||||||
|
captureIssueEvent,
|
||||||
|
router.asPath,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1,19 +1,18 @@
|
|||||||
import { FC, useEffect, useState, useMemo } from "react";
|
import { FC, useEffect, useState, useMemo } from "react";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
// types
|
||||||
import { TIssue } from "@plane/types";
|
import { TIssue } from "@plane/types";
|
||||||
// hooks
|
|
||||||
import { TOAST_TYPE, setPromiseToast, setToast } from "@plane/ui";
|
|
||||||
import { IssueView } from "@/components/issues";
|
|
||||||
// ui
|
// ui
|
||||||
|
import { TOAST_TYPE, setPromiseToast, setToast } from "@plane/ui";
|
||||||
// components
|
// components
|
||||||
|
import { IssueView } from "@/components/issues";
|
||||||
|
// constants
|
||||||
import { ISSUE_UPDATED, ISSUE_DELETED, ISSUE_ARCHIVED, ISSUE_RESTORED } from "@/constants/event-tracker";
|
import { ISSUE_UPDATED, ISSUE_DELETED, ISSUE_ARCHIVED, ISSUE_RESTORED } from "@/constants/event-tracker";
|
||||||
import { EIssuesStoreType } from "@/constants/issue";
|
import { EIssuesStoreType } from "@/constants/issue";
|
||||||
import { EUserProjectRoles } from "@/constants/project";
|
import { EUserProjectRoles } from "@/constants/project";
|
||||||
|
// hooks
|
||||||
import { useEventTracker, useIssueDetail, useIssues, useUser } from "@/hooks/store";
|
import { useEventTracker, useIssueDetail, useIssues, useUser } from "@/hooks/store";
|
||||||
// components
|
|
||||||
// types
|
|
||||||
// constants
|
|
||||||
|
|
||||||
interface IIssuePeekOverview {
|
interface IIssuePeekOverview {
|
||||||
is_archived?: boolean;
|
is_archived?: boolean;
|
||||||
@ -60,8 +59,14 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
|
|||||||
archiveIssue,
|
archiveIssue,
|
||||||
issue: { getIssueById, fetchIssue },
|
issue: { getIssueById, fetchIssue },
|
||||||
} = useIssueDetail();
|
} = useIssueDetail();
|
||||||
const { addIssueToCycle, removeIssueFromCycle, addModulesToIssue, removeIssueFromModule, removeModulesFromIssue } =
|
const {
|
||||||
useIssueDetail();
|
addCycleToIssue,
|
||||||
|
addIssueToCycle,
|
||||||
|
removeIssueFromCycle,
|
||||||
|
addModulesToIssue,
|
||||||
|
removeIssueFromModule,
|
||||||
|
removeModulesFromIssue,
|
||||||
|
} = useIssueDetail();
|
||||||
const { captureIssueEvent } = useEventTracker();
|
const { captureIssueEvent } = useEventTracker();
|
||||||
// state
|
// state
|
||||||
const [loader, setLoader] = useState(false);
|
const [loader, setLoader] = useState(false);
|
||||||
@ -174,21 +179,39 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
addCycleToIssue: async (workspaceSlug: string, projectId: string, cycleId: string, issueId: string) => {
|
||||||
|
try {
|
||||||
|
console.log("Peek adding...");
|
||||||
|
await addCycleToIssue(workspaceSlug, projectId, cycleId, issueId);
|
||||||
|
captureIssueEvent({
|
||||||
|
eventName: ISSUE_UPDATED,
|
||||||
|
payload: { issueId, state: "SUCCESS", element: "Issue peek-overview" },
|
||||||
|
updates: {
|
||||||
|
changed_property: "cycle_id",
|
||||||
|
change_details: cycleId,
|
||||||
|
},
|
||||||
|
path: router.asPath,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
setToast({
|
||||||
|
type: TOAST_TYPE.ERROR,
|
||||||
|
title: "Error!",
|
||||||
|
message: "Issue could not be added to the cycle. Please try again.",
|
||||||
|
});
|
||||||
|
captureIssueEvent({
|
||||||
|
eventName: ISSUE_UPDATED,
|
||||||
|
payload: { state: "FAILED", element: "Issue peek-overview" },
|
||||||
|
updates: {
|
||||||
|
changed_property: "cycle_id",
|
||||||
|
change_details: cycleId,
|
||||||
|
},
|
||||||
|
path: router.asPath,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
addIssueToCycle: async (workspaceSlug: string, projectId: string, cycleId: string, issueIds: string[]) => {
|
addIssueToCycle: async (workspaceSlug: string, projectId: string, cycleId: string, issueIds: string[]) => {
|
||||||
try {
|
try {
|
||||||
const addToCyclePromise = addIssueToCycle(workspaceSlug, projectId, cycleId, issueIds);
|
await addIssueToCycle(workspaceSlug, projectId, cycleId, issueIds);
|
||||||
setPromiseToast(addToCyclePromise, {
|
|
||||||
loading: "Adding cycle to issue...",
|
|
||||||
success: {
|
|
||||||
title: "Success!",
|
|
||||||
message: () => "Cycle added to issue successfully",
|
|
||||||
},
|
|
||||||
error: {
|
|
||||||
title: "Error!",
|
|
||||||
message: () => "Cycle add to issue failed",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
await addToCyclePromise;
|
|
||||||
captureIssueEvent({
|
captureIssueEvent({
|
||||||
eventName: ISSUE_UPDATED,
|
eventName: ISSUE_UPDATED,
|
||||||
payload: { ...issueIds, state: "SUCCESS", element: "Issue peek-overview" },
|
payload: { ...issueIds, state: "SUCCESS", element: "Issue peek-overview" },
|
||||||
@ -199,6 +222,11 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
|
|||||||
path: router.asPath,
|
path: router.asPath,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
setToast({
|
||||||
|
type: TOAST_TYPE.ERROR,
|
||||||
|
title: "Error!",
|
||||||
|
message: "Issue could not be added to the cycle. Please try again.",
|
||||||
|
});
|
||||||
captureIssueEvent({
|
captureIssueEvent({
|
||||||
eventName: ISSUE_UPDATED,
|
eventName: ISSUE_UPDATED,
|
||||||
payload: { state: "FAILED", element: "Issue peek-overview" },
|
payload: { state: "FAILED", element: "Issue peek-overview" },
|
||||||
@ -214,14 +242,14 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
|
|||||||
try {
|
try {
|
||||||
const removeFromCyclePromise = removeIssueFromCycle(workspaceSlug, projectId, cycleId, issueId);
|
const removeFromCyclePromise = removeIssueFromCycle(workspaceSlug, projectId, cycleId, issueId);
|
||||||
setPromiseToast(removeFromCyclePromise, {
|
setPromiseToast(removeFromCyclePromise, {
|
||||||
loading: "Removing cycle from issue...",
|
loading: "Removing issue from the cycle...",
|
||||||
success: {
|
success: {
|
||||||
title: "Success!",
|
title: "Success!",
|
||||||
message: () => "Cycle removed from issue successfully",
|
message: () => "Issue removed from the cycle successfully.",
|
||||||
},
|
},
|
||||||
error: {
|
error: {
|
||||||
title: "Error!",
|
title: "Error!",
|
||||||
message: () => "Cycle remove from issue failed",
|
message: () => "Issue could not be removed from the cycle. Please try again.",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
await removeFromCyclePromise;
|
await removeFromCyclePromise;
|
||||||
@ -248,19 +276,7 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
|
|||||||
},
|
},
|
||||||
addModulesToIssue: async (workspaceSlug: string, projectId: string, issueId: string, moduleIds: string[]) => {
|
addModulesToIssue: async (workspaceSlug: string, projectId: string, issueId: string, moduleIds: string[]) => {
|
||||||
try {
|
try {
|
||||||
const addToModulePromise = addModulesToIssue(workspaceSlug, projectId, issueId, moduleIds);
|
const response = await addModulesToIssue(workspaceSlug, projectId, issueId, moduleIds);
|
||||||
setPromiseToast(addToModulePromise, {
|
|
||||||
loading: "Adding module to issue...",
|
|
||||||
success: {
|
|
||||||
title: "Success!",
|
|
||||||
message: () => "Module added to issue successfully",
|
|
||||||
},
|
|
||||||
error: {
|
|
||||||
title: "Error!",
|
|
||||||
message: () => "Module add to issue failed",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const response = await addToModulePromise;
|
|
||||||
captureIssueEvent({
|
captureIssueEvent({
|
||||||
eventName: ISSUE_UPDATED,
|
eventName: ISSUE_UPDATED,
|
||||||
payload: { ...response, state: "SUCCESS", element: "Issue peek-overview" },
|
payload: { ...response, state: "SUCCESS", element: "Issue peek-overview" },
|
||||||
@ -271,6 +287,11 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
|
|||||||
path: router.asPath,
|
path: router.asPath,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
setToast({
|
||||||
|
type: TOAST_TYPE.ERROR,
|
||||||
|
title: "Error!",
|
||||||
|
message: "Issue could not be added to the module. Please try again.",
|
||||||
|
});
|
||||||
captureIssueEvent({
|
captureIssueEvent({
|
||||||
eventName: ISSUE_UPDATED,
|
eventName: ISSUE_UPDATED,
|
||||||
payload: { id: issueId, state: "FAILED", element: "Issue peek-overview" },
|
payload: { id: issueId, state: "FAILED", element: "Issue peek-overview" },
|
||||||
@ -286,14 +307,14 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
|
|||||||
try {
|
try {
|
||||||
const removeFromModulePromise = removeIssueFromModule(workspaceSlug, projectId, moduleId, issueId);
|
const removeFromModulePromise = removeIssueFromModule(workspaceSlug, projectId, moduleId, issueId);
|
||||||
setPromiseToast(removeFromModulePromise, {
|
setPromiseToast(removeFromModulePromise, {
|
||||||
loading: "Removing module from issue...",
|
loading: "Removing issue from the module...",
|
||||||
success: {
|
success: {
|
||||||
title: "Success!",
|
title: "Success!",
|
||||||
message: () => "Module removed from issue successfully",
|
message: () => "Issue removed from the module successfully.",
|
||||||
},
|
},
|
||||||
error: {
|
error: {
|
||||||
title: "Error!",
|
title: "Error!",
|
||||||
message: () => "Module remove from issue failed",
|
message: () => "Issue could not be removed from the module. Please try again.",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
await removeFromModulePromise;
|
await removeFromModulePromise;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { EIssueFilterType, EIssuesStoreType } from "@/constants/issue";
|
import { useCallback, useMemo } from "react";
|
||||||
import { useApplication, useIssues } from "./store";
|
// types
|
||||||
import {
|
import {
|
||||||
IIssueDisplayFilterOptions,
|
IIssueDisplayFilterOptions,
|
||||||
IIssueDisplayProperties,
|
IIssueDisplayProperties,
|
||||||
@ -8,7 +8,10 @@ import {
|
|||||||
TIssueKanbanFilters,
|
TIssueKanbanFilters,
|
||||||
TLoader,
|
TLoader,
|
||||||
} from "@plane/types";
|
} from "@plane/types";
|
||||||
import { useCallback, useMemo } from "react";
|
// constants
|
||||||
|
import { EIssueFilterType, EIssuesStoreType } from "@/constants/issue";
|
||||||
|
// hooks
|
||||||
|
import { useApplication, useIssues } from "./store";
|
||||||
|
|
||||||
interface IssueActions {
|
interface IssueActions {
|
||||||
fetchIssues?: (projectId: string, loadType: TLoader) => Promise<TIssue[] | undefined>;
|
fetchIssues?: (projectId: string, loadType: TLoader) => Promise<TIssue[] | undefined>;
|
||||||
@ -238,9 +241,9 @@ const useModuleIssueActions = () => {
|
|||||||
const removeIssueFromView = useCallback(
|
const removeIssueFromView = useCallback(
|
||||||
async (projectId: string, issueId: string) => {
|
async (projectId: string, issueId: string) => {
|
||||||
if (!moduleId || !workspaceSlug) return;
|
if (!moduleId || !workspaceSlug) return;
|
||||||
return await issues.removeIssueFromModule(workspaceSlug, projectId, moduleId, issueId);
|
return await issues.removeIssuesFromModule(workspaceSlug, projectId, moduleId, [issueId]);
|
||||||
},
|
},
|
||||||
[issues.removeIssueFromModule, moduleId, workspaceSlug]
|
[issues.removeIssuesFromModule, moduleId, workspaceSlug]
|
||||||
);
|
);
|
||||||
const archiveIssue = useCallback(
|
const archiveIssue = useCallback(
|
||||||
async (projectId: string, issueId: string) => {
|
async (projectId: string, issueId: string) => {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
// services
|
// types
|
||||||
import { API_BASE_URL } from "@/helpers/common.helper";
|
|
||||||
import { APIService } from "@/services/api.service";
|
|
||||||
// type
|
|
||||||
import type { TIssue, IIssueDisplayProperties, TIssueLink, TIssueSubIssues, TIssueActivity } from "@plane/types";
|
import type { TIssue, IIssueDisplayProperties, TIssueLink, TIssueSubIssues, TIssueActivity } from "@plane/types";
|
||||||
// helper
|
// helpers
|
||||||
|
import { API_BASE_URL } from "@/helpers/common.helper";
|
||||||
|
// services
|
||||||
|
import { APIService } from "@/services/api.service";
|
||||||
|
|
||||||
export class IssueService extends APIService {
|
export class IssueService extends APIService {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
|
// types
|
||||||
|
import type { IModule, TIssue, ILinkDetails, ModuleLink } from "@plane/types";
|
||||||
// services
|
// services
|
||||||
import { API_BASE_URL } from "@/helpers/common.helper";
|
import { API_BASE_URL } from "@/helpers/common.helper";
|
||||||
import { APIService } from "@/services/api.service";
|
import { APIService } from "@/services/api.service";
|
||||||
// types
|
|
||||||
import type { IModule, TIssue, ILinkDetails, ModuleLink } from "@plane/types";
|
|
||||||
|
|
||||||
export class ModuleService extends APIService {
|
export class ModuleService extends APIService {
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -106,19 +106,6 @@ export class ModuleService extends APIService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async removeIssueFromModule(
|
|
||||||
workspaceSlug: string,
|
|
||||||
projectId: string,
|
|
||||||
moduleId: string,
|
|
||||||
issueId: string
|
|
||||||
): Promise<any> {
|
|
||||||
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/issues/${issueId}/`)
|
|
||||||
.then((response) => response?.data)
|
|
||||||
.catch((error) => {
|
|
||||||
throw error?.response?.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async removeIssuesFromModuleBulk(
|
async removeIssuesFromModuleBulk(
|
||||||
workspaceSlug: string,
|
workspaceSlug: string,
|
||||||
projectId: string,
|
projectId: string,
|
||||||
|
@ -4,12 +4,12 @@ import set from "lodash/set";
|
|||||||
import uniq from "lodash/uniq";
|
import uniq from "lodash/uniq";
|
||||||
import update from "lodash/update";
|
import update from "lodash/update";
|
||||||
import { action, observable, makeObservable, computed, runInAction } from "mobx";
|
import { action, observable, makeObservable, computed, runInAction } from "mobx";
|
||||||
// base class
|
// types
|
||||||
|
import { TIssue, TSubGroupedIssues, TGroupedIssues, TLoader, TUnGroupedIssues, ViewFlags } from "@plane/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";
|
||||||
// types
|
// types
|
||||||
import { TIssue, TSubGroupedIssues, TGroupedIssues, TLoader, TUnGroupedIssues, ViewFlags } from "@plane/types";
|
|
||||||
import { IssueHelperStore } from "../helpers/issue-helper.store";
|
import { IssueHelperStore } from "../helpers/issue-helper.store";
|
||||||
import { IIssueRootStore } from "../root.store";
|
import { IIssueRootStore } from "../root.store";
|
||||||
|
|
||||||
@ -59,6 +59,7 @@ export interface ICycleIssues {
|
|||||||
fetchAddedIssues?: boolean
|
fetchAddedIssues?: boolean
|
||||||
) => Promise<void>;
|
) => Promise<void>;
|
||||||
removeIssueFromCycle: (workspaceSlug: string, projectId: string, cycleId: string, issueId: string) => Promise<void>;
|
removeIssueFromCycle: (workspaceSlug: string, projectId: string, cycleId: string, issueId: string) => Promise<void>;
|
||||||
|
addCycleToIssue: (workspaceSlug: string, projectId: string, cycleId: string, issueId: string) => Promise<void>;
|
||||||
transferIssuesFromCycle: (
|
transferIssuesFromCycle: (
|
||||||
workspaceSlug: string,
|
workspaceSlug: string,
|
||||||
projectId: string,
|
projectId: string,
|
||||||
@ -101,6 +102,7 @@ export class CycleIssues extends IssueHelperStore implements ICycleIssues {
|
|||||||
quickAddIssue: action,
|
quickAddIssue: action,
|
||||||
addIssueToCycle: action,
|
addIssueToCycle: action,
|
||||||
removeIssueFromCycle: action,
|
removeIssueFromCycle: action,
|
||||||
|
addCycleToIssue: action,
|
||||||
transferIssuesFromCycle: action,
|
transferIssuesFromCycle: action,
|
||||||
fetchActiveCycleIssues: action,
|
fetchActiveCycleIssues: action,
|
||||||
});
|
});
|
||||||
@ -303,18 +305,22 @@ export class CycleIssues extends IssueHelperStore implements ICycleIssues {
|
|||||||
|
|
||||||
if (fetchAddedIssues) await this.rootIssueStore.issues.getIssues(workspaceSlug, projectId, issueIds);
|
if (fetchAddedIssues) await this.rootIssueStore.issues.getIssues(workspaceSlug, projectId, issueIds);
|
||||||
|
|
||||||
|
// add the new issue ids to the cycle issues map
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
update(this.issues, cycleId, (cycleIssueIds = []) => uniq(concat(cycleIssueIds, issueIds)));
|
update(this.issues, cycleId, (cycleIssueIds = []) => uniq(concat(cycleIssueIds, issueIds)));
|
||||||
});
|
});
|
||||||
issueIds.forEach((issueId) => {
|
issueIds.forEach((issueId) => {
|
||||||
const issueCycleId = this.rootIssueStore.issues.getIssueById(issueId)?.cycle_id;
|
const issueCycleId = this.rootIssueStore.issues.getIssueById(issueId)?.cycle_id;
|
||||||
|
// remove issue from previous cycle if it exists
|
||||||
if (issueCycleId && issueCycleId !== cycleId) {
|
if (issueCycleId && issueCycleId !== cycleId) {
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
pull(this.issues[issueCycleId], issueId);
|
pull(this.issues[issueCycleId], issueId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// update the root issue map with the new cycle id
|
||||||
this.rootStore.issues.updateIssue(issueId, { cycle_id: cycleId });
|
this.rootStore.issues.updateIssue(issueId, { cycle_id: cycleId });
|
||||||
});
|
});
|
||||||
|
|
||||||
this.rootIssueStore.rootStore.cycle.fetchCycleDetails(workspaceSlug, projectId, cycleId);
|
this.rootIssueStore.rootStore.cycle.fetchCycleDetails(workspaceSlug, projectId, cycleId);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error;
|
throw error;
|
||||||
@ -336,6 +342,43 @@ export class CycleIssues extends IssueHelperStore implements ICycleIssues {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
addCycleToIssue = async (workspaceSlug: string, projectId: string, cycleId: string, issueId: string) => {
|
||||||
|
const issueCycleId = this.rootIssueStore.issues.getIssueById(issueId)?.cycle_id;
|
||||||
|
try {
|
||||||
|
// add the new issue ids to the cycle issues map
|
||||||
|
runInAction(() => {
|
||||||
|
update(this.issues, cycleId, (cycleIssueIds = []) => uniq(concat(cycleIssueIds, [issueId])));
|
||||||
|
});
|
||||||
|
// remove issue from previous cycle if it exists
|
||||||
|
if (issueCycleId && issueCycleId !== cycleId) {
|
||||||
|
runInAction(() => {
|
||||||
|
pull(this.issues[issueCycleId], issueId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// update the root issue map with the new cycle id
|
||||||
|
this.rootStore.issues.updateIssue(issueId, { cycle_id: cycleId });
|
||||||
|
|
||||||
|
await this.issueService.addIssueToCycle(workspaceSlug, projectId, cycleId, {
|
||||||
|
issues: [issueId],
|
||||||
|
});
|
||||||
|
|
||||||
|
this.rootIssueStore.rootStore.cycle.fetchCycleDetails(workspaceSlug, projectId, cycleId);
|
||||||
|
} catch (error) {
|
||||||
|
// remove the new issue ids from the cycle issues map
|
||||||
|
runInAction(() => {
|
||||||
|
pull(this.issues[cycleId], issueId);
|
||||||
|
});
|
||||||
|
// add issue back to the previous cycle if it exists
|
||||||
|
if (issueCycleId)
|
||||||
|
runInAction(() => {
|
||||||
|
update(this.issues, issueCycleId, (cycleIssueIds = []) => uniq(concat(cycleIssueIds, [issueId])));
|
||||||
|
});
|
||||||
|
// update the root issue map with the original cycle id
|
||||||
|
this.rootStore.issues.updateIssue(issueId, { cycle_id: issueCycleId ?? null });
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
transferIssuesFromCycle = async (
|
transferIssuesFromCycle = async (
|
||||||
workspaceSlug: string,
|
workspaceSlug: string,
|
||||||
projectId: string,
|
projectId: string,
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import { makeObservable } from "mobx";
|
import { makeObservable } from "mobx";
|
||||||
// services
|
|
||||||
import { computedFn } from "mobx-utils";
|
import { computedFn } from "mobx-utils";
|
||||||
import { IssueArchiveService, IssueDraftService, IssueService } from "@/services/issue";
|
|
||||||
// types
|
// types
|
||||||
import { TIssue } from "@plane/types";
|
import { TIssue } from "@plane/types";
|
||||||
|
// services
|
||||||
|
import { IssueArchiveService, IssueDraftService, IssueService } from "@/services/issue";
|
||||||
|
// types
|
||||||
import { IIssueDetail } from "./root.store";
|
import { IIssueDetail } from "./root.store";
|
||||||
|
|
||||||
export interface IIssueStoreActions {
|
export interface IIssueStoreActions {
|
||||||
@ -17,6 +18,7 @@ export interface IIssueStoreActions {
|
|||||||
updateIssue: (workspaceSlug: string, projectId: string, issueId: string, data: Partial<TIssue>) => Promise<void>;
|
updateIssue: (workspaceSlug: string, projectId: string, issueId: string, data: Partial<TIssue>) => Promise<void>;
|
||||||
removeIssue: (workspaceSlug: string, projectId: string, issueId: string) => Promise<void>;
|
removeIssue: (workspaceSlug: string, projectId: string, issueId: string) => Promise<void>;
|
||||||
archiveIssue: (workspaceSlug: string, projectId: string, issueId: string) => Promise<void>;
|
archiveIssue: (workspaceSlug: string, projectId: string, issueId: string) => Promise<void>;
|
||||||
|
addCycleToIssue: (workspaceSlug: string, projectId: string, cycleId: string, issueId: string) => Promise<void>;
|
||||||
addIssueToCycle: (workspaceSlug: string, projectId: string, cycleId: string, issueIds: string[]) => Promise<void>;
|
addIssueToCycle: (workspaceSlug: string, projectId: string, cycleId: string, issueIds: string[]) => Promise<void>;
|
||||||
removeIssueFromCycle: (workspaceSlug: string, projectId: string, cycleId: string, issueId: string) => Promise<void>;
|
removeIssueFromCycle: (workspaceSlug: string, projectId: string, cycleId: string, issueId: string) => Promise<void>;
|
||||||
addModulesToIssue: (workspaceSlug: string, projectId: string, issueId: string, moduleIds: string[]) => Promise<any>;
|
addModulesToIssue: (workspaceSlug: string, projectId: string, issueId: string, moduleIds: string[]) => Promise<any>;
|
||||||
@ -161,6 +163,16 @@ export class IssueStore implements IIssueStore {
|
|||||||
archiveIssue = async (workspaceSlug: string, projectId: string, issueId: string) =>
|
archiveIssue = async (workspaceSlug: string, projectId: string, issueId: string) =>
|
||||||
this.rootIssueDetailStore.rootIssueStore.projectIssues.archiveIssue(workspaceSlug, projectId, issueId);
|
this.rootIssueDetailStore.rootIssueStore.projectIssues.archiveIssue(workspaceSlug, projectId, issueId);
|
||||||
|
|
||||||
|
addCycleToIssue = async (workspaceSlug: string, projectId: string, cycleId: string, issueId: string) => {
|
||||||
|
await this.rootIssueDetailStore.rootIssueStore.cycleIssues.addCycleToIssue(
|
||||||
|
workspaceSlug,
|
||||||
|
projectId,
|
||||||
|
cycleId,
|
||||||
|
issueId
|
||||||
|
);
|
||||||
|
await this.rootIssueDetailStore.activity.fetchActivities(workspaceSlug, projectId, issueId);
|
||||||
|
};
|
||||||
|
|
||||||
addIssueToCycle = async (workspaceSlug: string, projectId: string, cycleId: string, issueIds: string[]) => {
|
addIssueToCycle = async (workspaceSlug: string, projectId: string, cycleId: string, issueIds: string[]) => {
|
||||||
await this.rootIssueDetailStore.rootIssueStore.cycleIssues.addIssueToCycle(
|
await this.rootIssueDetailStore.rootIssueStore.cycleIssues.addIssueToCycle(
|
||||||
workspaceSlug,
|
workspaceSlug,
|
||||||
@ -208,11 +220,11 @@ export class IssueStore implements IIssueStore {
|
|||||||
};
|
};
|
||||||
|
|
||||||
removeIssueFromModule = async (workspaceSlug: string, projectId: string, moduleId: string, issueId: string) => {
|
removeIssueFromModule = async (workspaceSlug: string, projectId: string, moduleId: string, issueId: string) => {
|
||||||
const currentModule = await this.rootIssueDetailStore.rootIssueStore.moduleIssues.removeIssueFromModule(
|
const currentModule = await this.rootIssueDetailStore.rootIssueStore.moduleIssues.removeIssuesFromModule(
|
||||||
workspaceSlug,
|
workspaceSlug,
|
||||||
projectId,
|
projectId,
|
||||||
moduleId,
|
moduleId,
|
||||||
issueId
|
[issueId]
|
||||||
);
|
);
|
||||||
await this.rootIssueDetailStore.activity.fetchActivities(workspaceSlug, projectId, issueId);
|
await this.rootIssueDetailStore.activity.fetchActivities(workspaceSlug, projectId, issueId);
|
||||||
return currentModule;
|
return currentModule;
|
||||||
|
@ -191,6 +191,8 @@ export class IssueDetail implements IIssueDetail {
|
|||||||
this.issue.removeIssue(workspaceSlug, projectId, issueId);
|
this.issue.removeIssue(workspaceSlug, projectId, issueId);
|
||||||
archiveIssue = async (workspaceSlug: string, projectId: string, issueId: string) =>
|
archiveIssue = async (workspaceSlug: string, projectId: string, issueId: string) =>
|
||||||
this.issue.archiveIssue(workspaceSlug, projectId, issueId);
|
this.issue.archiveIssue(workspaceSlug, projectId, issueId);
|
||||||
|
addCycleToIssue = async (workspaceSlug: string, projectId: string, cycleId: string, issueId: string) =>
|
||||||
|
this.issue.addCycleToIssue(workspaceSlug, projectId, cycleId, issueId);
|
||||||
addIssueToCycle = async (workspaceSlug: string, projectId: string, cycleId: string, issueIds: string[]) =>
|
addIssueToCycle = async (workspaceSlug: string, projectId: string, cycleId: string, issueIds: string[]) =>
|
||||||
this.issue.addIssueToCycle(workspaceSlug, projectId, cycleId, issueIds);
|
this.issue.addIssueToCycle(workspaceSlug, projectId, cycleId, issueIds);
|
||||||
removeIssueFromCycle = async (workspaceSlug: string, projectId: string, cycleId: string, issueId: string) =>
|
removeIssueFromCycle = async (workspaceSlug: string, projectId: string, cycleId: string, issueId: string) =>
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import isEmpty from "lodash/isEmpty";
|
import isEmpty from "lodash/isEmpty";
|
||||||
import set from "lodash/set";
|
import set from "lodash/set";
|
||||||
// store
|
|
||||||
import { action, makeObservable, observable, runInAction } from "mobx";
|
import { action, makeObservable, observable, runInAction } from "mobx";
|
||||||
import { computedFn } from "mobx-utils";
|
import { computedFn } from "mobx-utils";
|
||||||
// types
|
// types
|
||||||
import { IssueService } from "@/services/issue";
|
|
||||||
import { TIssue } from "@plane/types";
|
import { TIssue } from "@plane/types";
|
||||||
|
// helpers
|
||||||
import { getCurrentDateTimeInISO } from "@/helpers/date-time.helper";
|
import { getCurrentDateTimeInISO } from "@/helpers/date-time.helper";
|
||||||
//services
|
// services
|
||||||
|
import { IssueService } from "@/services/issue";
|
||||||
|
|
||||||
export type IIssueStore = {
|
export type IIssueStore = {
|
||||||
// observables
|
// observables
|
||||||
|
@ -4,13 +4,14 @@ import set from "lodash/set";
|
|||||||
import uniq from "lodash/uniq";
|
import uniq from "lodash/uniq";
|
||||||
import update from "lodash/update";
|
import update from "lodash/update";
|
||||||
import { action, observable, makeObservable, computed, runInAction } from "mobx";
|
import { action, observable, makeObservable, computed, runInAction } from "mobx";
|
||||||
// base class
|
// types
|
||||||
|
import { TIssue, TLoader, TGroupedIssues, TSubGroupedIssues, TUnGroupedIssues, ViewFlags } from "@plane/types";
|
||||||
// services
|
// services
|
||||||
import { IssueService } from "@/services/issue";
|
import { IssueService } from "@/services/issue";
|
||||||
import { ModuleService } from "@/services/module.service";
|
import { ModuleService } from "@/services/module.service";
|
||||||
// types
|
// helpers
|
||||||
import { TIssue, TLoader, TGroupedIssues, TSubGroupedIssues, TUnGroupedIssues, ViewFlags } from "@plane/types";
|
|
||||||
import { IssueHelperStore } from "../helpers/issue-helper.store";
|
import { IssueHelperStore } from "../helpers/issue-helper.store";
|
||||||
|
// store
|
||||||
import { IIssueRootStore } from "../root.store";
|
import { IIssueRootStore } from "../root.store";
|
||||||
|
|
||||||
export interface IModuleIssues {
|
export interface IModuleIssues {
|
||||||
@ -69,7 +70,6 @@ export interface IModuleIssues {
|
|||||||
issueId: string,
|
issueId: string,
|
||||||
moduleIds: string[]
|
moduleIds: string[]
|
||||||
) => Promise<void>;
|
) => Promise<void>;
|
||||||
removeIssueFromModule: (workspaceSlug: string, projectId: string, moduleId: string, issueId: string) => Promise<void>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ModuleIssues extends IssueHelperStore implements IModuleIssues {
|
export class ModuleIssues extends IssueHelperStore implements IModuleIssues {
|
||||||
@ -106,7 +106,6 @@ export class ModuleIssues extends IssueHelperStore implements IModuleIssues {
|
|||||||
removeIssuesFromModule: action,
|
removeIssuesFromModule: action,
|
||||||
addModulesToIssue: action,
|
addModulesToIssue: action,
|
||||||
removeModulesFromIssue: action,
|
removeModulesFromIssue: action,
|
||||||
removeIssueFromModule: action,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.rootIssueStore = _rootStore;
|
this.rootIssueStore = _rootStore;
|
||||||
@ -301,27 +300,39 @@ export class ModuleIssues extends IssueHelperStore implements IModuleIssues {
|
|||||||
fetchAddedIssues = true
|
fetchAddedIssues = true
|
||||||
) => {
|
) => {
|
||||||
try {
|
try {
|
||||||
await this.moduleService.addIssuesToModule(workspaceSlug, projectId, moduleId, {
|
// add the new issue ids to the module issues map
|
||||||
issues: issueIds,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (fetchAddedIssues) await this.rootIssueStore.issues.getIssues(workspaceSlug, projectId, issueIds);
|
|
||||||
|
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
update(this.issues, moduleId, (moduleIssueIds = []) => {
|
update(this.issues, moduleId, (moduleIssueIds = []) => {
|
||||||
if (!moduleIssueIds) return [...issueIds];
|
if (!moduleIssueIds) return [...issueIds];
|
||||||
else return uniq(concat(moduleIssueIds, issueIds));
|
else return uniq(concat(moduleIssueIds, issueIds));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
// update the root issue map with the new module ids
|
||||||
issueIds.forEach((issueId) => {
|
issueIds.forEach((issueId) => {
|
||||||
update(this.rootStore.issues.issuesMap, [issueId, "module_ids"], (issueModuleIds = []) => {
|
update(this.rootStore.issues.issuesMap, [issueId, "module_ids"], (issueModuleIds = []) => {
|
||||||
if (issueModuleIds.includes(moduleId)) return issueModuleIds;
|
if (issueModuleIds.includes(moduleId)) return issueModuleIds;
|
||||||
else return uniq(concat(issueModuleIds, [moduleId]));
|
else return uniq(concat(issueModuleIds, [moduleId]));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await this.moduleService.addIssuesToModule(workspaceSlug, projectId, moduleId, {
|
||||||
|
issues: issueIds,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (fetchAddedIssues) await this.rootIssueStore.issues.getIssues(workspaceSlug, projectId, issueIds);
|
||||||
|
|
||||||
this.rootIssueStore.rootStore.module.fetchModuleDetails(workspaceSlug, projectId, moduleId);
|
this.rootIssueStore.rootStore.module.fetchModuleDetails(workspaceSlug, projectId, moduleId);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
issueIds.forEach((issueId) => {
|
||||||
|
runInAction(() => {
|
||||||
|
// remove the new issue ids from the module issues map
|
||||||
|
pull(this.issues[moduleId], issueId);
|
||||||
|
// remove the new module ids from the root issue map
|
||||||
|
update(this.rootStore.issues.issuesMap, [issueId, "module_ids"], (issueModuleIds = []) =>
|
||||||
|
pull(issueModuleIds, moduleId)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -358,25 +369,38 @@ export class ModuleIssues extends IssueHelperStore implements IModuleIssues {
|
|||||||
};
|
};
|
||||||
|
|
||||||
addModulesToIssue = async (workspaceSlug: string, projectId: string, issueId: string, moduleIds: string[]) => {
|
addModulesToIssue = async (workspaceSlug: string, projectId: string, issueId: string, moduleIds: string[]) => {
|
||||||
|
// keep a copy of the original module ids
|
||||||
|
const originalModuleIds = this.rootStore.issues.issuesMap[issueId]?.module_ids ?? [];
|
||||||
try {
|
try {
|
||||||
const issueToModule = await this.moduleService.addModulesToIssue(workspaceSlug, projectId, issueId, {
|
|
||||||
modules: moduleIds,
|
|
||||||
});
|
|
||||||
|
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
|
// add the new issue ids to the module issues map
|
||||||
moduleIds.forEach((moduleId) => {
|
moduleIds.forEach((moduleId) => {
|
||||||
update(this.issues, moduleId, (moduleIssueIds = []) => {
|
update(this.issues, moduleId, (moduleIssueIds = []) => {
|
||||||
if (moduleIssueIds.includes(issueId)) return moduleIssueIds;
|
if (moduleIssueIds.includes(issueId)) return moduleIssueIds;
|
||||||
else return uniq(concat(moduleIssueIds, [issueId]));
|
else return uniq(concat(moduleIssueIds, [issueId]));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
// update the root issue map with the new module ids
|
||||||
update(this.rootStore.issues.issuesMap, [issueId, "module_ids"], (issueModuleIds = []) =>
|
update(this.rootStore.issues.issuesMap, [issueId, "module_ids"], (issueModuleIds = []) =>
|
||||||
uniq(concat(issueModuleIds, moduleIds))
|
uniq(concat(issueModuleIds, moduleIds))
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const issueToModule = await this.moduleService.addModulesToIssue(workspaceSlug, projectId, issueId, {
|
||||||
|
modules: moduleIds,
|
||||||
|
});
|
||||||
|
|
||||||
return issueToModule;
|
return issueToModule;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
// revert the issue back to its original module ids
|
||||||
|
set(this.rootStore.issues.issuesMap, [issueId, "module_ids"], originalModuleIds);
|
||||||
|
// remove the new issue ids from the module issues map
|
||||||
|
moduleIds.forEach((moduleId) => {
|
||||||
|
runInAction(() => {
|
||||||
|
update(this.issues, moduleId, (moduleIssueIds = []) => pull(moduleIssueIds, issueId));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -407,21 +431,4 @@ export class ModuleIssues extends IssueHelperStore implements IModuleIssues {
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
removeIssueFromModule = async (workspaceSlug: string, projectId: string, moduleId: string, issueId: string) => {
|
|
||||||
try {
|
|
||||||
runInAction(() => {
|
|
||||||
pull(this.issues[moduleId], issueId);
|
|
||||||
update(this.rootStore.issues.issuesMap, [issueId, "module_ids"], (issueModuleIds = []) =>
|
|
||||||
pull(issueModuleIds, moduleId)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
const response = await this.moduleService.removeIssueFromModule(workspaceSlug, projectId, moduleId, issueId);
|
|
||||||
|
|
||||||
return response;
|
|
||||||
} catch (error) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import isEmpty from "lodash/isEmpty";
|
import isEmpty from "lodash/isEmpty";
|
||||||
import { autorun, makeObservable, observable } from "mobx";
|
import { autorun, makeObservable, observable } from "mobx";
|
||||||
|
import { ICycle, IIssueLabel, IModule, IProject, IState, IUserLite } from "@plane/types";
|
||||||
// root store
|
// root store
|
||||||
import { IWorkspaceMembership } from "@/store/member/workspace-member.store";
|
import { IWorkspaceMembership } from "@/store/member/workspace-member.store";
|
||||||
import { ICycle, IIssueLabel, IModule, IProject, IState, IUserLite } from "@plane/types";
|
|
||||||
import { RootStore } from "../root.store";
|
import { RootStore } from "../root.store";
|
||||||
import { IStateStore, StateStore } from "../state.store";
|
import { IStateStore, StateStore } from "../state.store";
|
||||||
// issues data store
|
// issues data store
|
||||||
|
Loading…
Reference in New Issue
Block a user