mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
fix: issue peek-overview delete functionality (#3134)
* fix: peek-overview delete issue * refactor: removed unused variables
This commit is contained in:
parent
969a51f425
commit
05e7afab8d
@ -120,8 +120,8 @@ export const BaseCalendarRoot = observer((props: IBaseCalendarRoot) => {
|
||||
workspaceSlug={workspaceSlug.toString()}
|
||||
projectId={peekProjectId.toString()}
|
||||
issueId={peekIssueId.toString()}
|
||||
handleIssue={async (issueToUpdate) =>
|
||||
await handleIssues(issueToUpdate.target_date ?? "", issueToUpdate as IIssue, EIssueActions.UPDATE)
|
||||
handleIssue={async (issueToUpdate, action: EIssueActions) =>
|
||||
await handleIssues(issueToUpdate.target_date ?? "", issueToUpdate as IIssue, action)
|
||||
}
|
||||
/>
|
||||
)}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
import React, { useCallback } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { observer } from "mobx-react-lite";
|
||||
// mobx store
|
||||
@ -25,6 +25,8 @@ import {
|
||||
IViewIssuesStore,
|
||||
} from "store/issues";
|
||||
import { TUnGroupedIssues } from "store/issues/types";
|
||||
import { EIssueActions } from "../types";
|
||||
// constants
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
|
||||
interface IBaseGanttRoot {
|
||||
@ -35,10 +37,15 @@ interface IBaseGanttRoot {
|
||||
| IViewIssuesFilterStore;
|
||||
issueStore: IProjectIssuesStore | IModuleIssuesStore | ICycleIssuesStore | IViewIssuesStore;
|
||||
viewId?: string;
|
||||
issueActions: {
|
||||
[EIssueActions.DELETE]: (issue: IIssue) => Promise<void>;
|
||||
[EIssueActions.UPDATE]?: (issue: IIssue) => Promise<void>;
|
||||
[EIssueActions.REMOVE]?: (issue: IIssue) => Promise<void>;
|
||||
};
|
||||
}
|
||||
|
||||
export const BaseGanttRoot: React.FC<IBaseGanttRoot> = observer((props: IBaseGanttRoot) => {
|
||||
const { issueFiltersStore, issueStore, viewId } = props;
|
||||
const { issueFiltersStore, issueStore, viewId, issueActions } = props;
|
||||
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, peekIssueId, peekProjectId } = router.query;
|
||||
@ -64,11 +71,14 @@ export const BaseGanttRoot: React.FC<IBaseGanttRoot> = observer((props: IBaseGan
|
||||
await issueStore.updateIssue(workspaceSlug.toString(), issue.project, issue.id, payload, viewId);
|
||||
};
|
||||
|
||||
const updateIssue = async (projectId: string, issueId: string, payload: Partial<IIssue>) => {
|
||||
if (!workspaceSlug) return;
|
||||
|
||||
await issueStore.updateIssue(workspaceSlug.toString(), projectId, issueId, payload, viewId);
|
||||
};
|
||||
const handleIssues = useCallback(
|
||||
async (issue: IIssue, action: EIssueActions) => {
|
||||
if (issueActions[action]) {
|
||||
await issueActions[action]!(issue);
|
||||
}
|
||||
},
|
||||
[issueActions]
|
||||
);
|
||||
|
||||
const isAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
|
||||
|
||||
@ -102,8 +112,8 @@ export const BaseGanttRoot: React.FC<IBaseGanttRoot> = observer((props: IBaseGan
|
||||
workspaceSlug={workspaceSlug.toString()}
|
||||
projectId={peekProjectId.toString()}
|
||||
issueId={peekIssueId.toString()}
|
||||
handleIssue={async (issueToUpdate) => {
|
||||
await updateIssue(peekProjectId.toString(), peekIssueId.toString(), issueToUpdate);
|
||||
handleIssue={async (issueToUpdate, action) => {
|
||||
await handleIssues(issueToUpdate as IIssue, action);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
@ -4,15 +4,43 @@ import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// components
|
||||
import { BaseGanttRoot } from "./base-gantt-root";
|
||||
import { useRouter } from "next/router";
|
||||
// types
|
||||
import { EIssueActions } from "../types";
|
||||
import { IIssue } from "types";
|
||||
|
||||
export const CycleGanttLayout: React.FC = observer(() => {
|
||||
const router = useRouter();
|
||||
const { cycleId } = router.query;
|
||||
const { cycleId, workspaceSlug } = router.query;
|
||||
|
||||
const { cycleIssues: cycleIssueStore, cycleIssuesFilter: cycleIssueFilterStore } = useMobxStore();
|
||||
|
||||
const issueActions = {
|
||||
[EIssueActions.UPDATE]: async (issue: IIssue) => {
|
||||
if (!workspaceSlug || !cycleId) return;
|
||||
|
||||
await cycleIssueStore.updateIssue(workspaceSlug.toString(), issue.project, issue.id, issue, cycleId.toString());
|
||||
},
|
||||
[EIssueActions.DELETE]: async (issue: IIssue) => {
|
||||
if (!workspaceSlug || !cycleId) return;
|
||||
|
||||
await cycleIssueStore.removeIssue(workspaceSlug.toString(), issue.project, issue.id, cycleId.toString());
|
||||
},
|
||||
[EIssueActions.REMOVE]: async (issue: IIssue) => {
|
||||
if (!workspaceSlug || !cycleId || !issue.bridge_id) return;
|
||||
|
||||
await cycleIssueStore.removeIssueFromCycle(
|
||||
workspaceSlug.toString(),
|
||||
issue.project,
|
||||
cycleId.toString(),
|
||||
issue.id,
|
||||
issue.bridge_id
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<BaseGanttRoot
|
||||
issueActions={issueActions}
|
||||
issueFiltersStore={cycleIssueFilterStore}
|
||||
issueStore={cycleIssueStore}
|
||||
viewId={cycleId?.toString()}
|
||||
|
@ -4,15 +4,43 @@ import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// components
|
||||
import { BaseGanttRoot } from "./base-gantt-root";
|
||||
import { useRouter } from "next/router";
|
||||
// types
|
||||
import { EIssueActions } from "../types";
|
||||
import { IIssue } from "types";
|
||||
|
||||
export const ModuleGanttLayout: React.FC = observer(() => {
|
||||
const router = useRouter();
|
||||
const { moduleId } = router.query;
|
||||
const { moduleId, workspaceSlug } = router.query;
|
||||
|
||||
const { moduleIssues: moduleIssueStore, moduleIssuesFilter: moduleIssueFilterStore } = useMobxStore();
|
||||
|
||||
const issueActions = {
|
||||
[EIssueActions.UPDATE]: async (issue: IIssue) => {
|
||||
if (!workspaceSlug || !moduleId) return;
|
||||
|
||||
await moduleIssueStore.updateIssue(workspaceSlug.toString(), issue.project, issue.id, issue, moduleId.toString());
|
||||
},
|
||||
[EIssueActions.DELETE]: async (issue: IIssue) => {
|
||||
if (!workspaceSlug || !moduleId) return;
|
||||
|
||||
await moduleIssueStore.removeIssue(workspaceSlug.toString(), issue.project, issue.id, moduleId.toString());
|
||||
},
|
||||
[EIssueActions.REMOVE]: async (issue: IIssue) => {
|
||||
if (!workspaceSlug || !moduleId || !issue.bridge_id) return;
|
||||
|
||||
await moduleIssueStore.removeIssueFromModule(
|
||||
workspaceSlug.toString(),
|
||||
issue.project,
|
||||
moduleId.toString(),
|
||||
issue.id,
|
||||
issue.bridge_id
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<BaseGanttRoot
|
||||
issueActions={issueActions}
|
||||
issueFiltersStore={moduleIssueFilterStore}
|
||||
issueStore={moduleIssueStore}
|
||||
viewId={moduleId?.toString()}
|
||||
|
@ -1,12 +1,36 @@
|
||||
import React from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { observer } from "mobx-react-lite";
|
||||
// hooks
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// components
|
||||
import { BaseGanttRoot } from "./base-gantt-root";
|
||||
// types
|
||||
import { EIssueActions } from "../types";
|
||||
import { IIssue } from "types";
|
||||
|
||||
export const GanttLayout: React.FC = observer(() => {
|
||||
const { projectIssues: projectIssuesStore, projectIssuesFilter: projectIssueFiltersStore } = useMobxStore();
|
||||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
|
||||
return <BaseGanttRoot issueFiltersStore={projectIssueFiltersStore} issueStore={projectIssuesStore} />;
|
||||
const issueActions = {
|
||||
[EIssueActions.UPDATE]: async (issue: IIssue) => {
|
||||
if (!workspaceSlug) return;
|
||||
|
||||
await projectIssuesStore.updateIssue(workspaceSlug.toString(), issue.project, issue.id, issue);
|
||||
},
|
||||
[EIssueActions.DELETE]: async (issue: IIssue) => {
|
||||
if (!workspaceSlug) return;
|
||||
|
||||
await projectIssuesStore.removeIssue(workspaceSlug.toString(), issue.project, issue.id);
|
||||
},
|
||||
};
|
||||
return (
|
||||
<BaseGanttRoot
|
||||
issueActions={issueActions}
|
||||
issueFiltersStore={projectIssueFiltersStore}
|
||||
issueStore={projectIssuesStore}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
@ -1,11 +1,35 @@
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { useRouter } from "next/router";
|
||||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// components
|
||||
import { BaseGanttRoot } from "./base-gantt-root";
|
||||
// types
|
||||
import { EIssueActions } from "../types";
|
||||
import { IIssue } from "types";
|
||||
|
||||
export const ProjectViewGanttLayout: React.FC = observer(() => {
|
||||
const { viewIssues: projectIssueViewStore, viewIssuesFilter: projectIssueViewFiltersStore } = useMobxStore();
|
||||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
|
||||
return <BaseGanttRoot issueFiltersStore={projectIssueViewFiltersStore} issueStore={projectIssueViewStore} />;
|
||||
const issueActions = {
|
||||
[EIssueActions.UPDATE]: async (issue: IIssue) => {
|
||||
if (!workspaceSlug) return;
|
||||
|
||||
await projectIssueViewStore.updateIssue(workspaceSlug.toString(), issue.project, issue.id, issue);
|
||||
},
|
||||
[EIssueActions.DELETE]: async (issue: IIssue) => {
|
||||
if (!workspaceSlug) return;
|
||||
|
||||
await projectIssueViewStore.removeIssue(workspaceSlug.toString(), issue.project, issue.id);
|
||||
},
|
||||
};
|
||||
return (
|
||||
<BaseGanttRoot
|
||||
issueActions={issueActions}
|
||||
issueFiltersStore={projectIssueViewFiltersStore}
|
||||
issueStore={projectIssueViewStore}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
@ -346,8 +346,8 @@ export const BaseKanBanRoot: React.FC<IBaseKanBanLayout> = observer((props: IBas
|
||||
workspaceSlug={workspaceSlug.toString()}
|
||||
projectId={peekProjectId.toString()}
|
||||
issueId={peekIssueId.toString()}
|
||||
handleIssue={async (issueToUpdate) =>
|
||||
await handleIssues(sub_group_by, group_by, issueToUpdate as IIssue, EIssueActions.UPDATE)
|
||||
handleIssue={async (issueToUpdate, action: EIssueActions) =>
|
||||
await handleIssues(sub_group_by, group_by, issueToUpdate as IIssue, action)
|
||||
}
|
||||
/>
|
||||
)}
|
||||
|
@ -168,7 +168,9 @@ export const BaseListRoot = observer((props: IBaseListRoot) => {
|
||||
workspaceSlug={workspaceSlug.toString()}
|
||||
projectId={peekProjectId.toString()}
|
||||
issueId={peekIssueId.toString()}
|
||||
handleIssue={async (issueToUpdate) => await handleIssues(issueToUpdate as IIssue, EIssueActions.UPDATE)}
|
||||
handleIssue={async (issueToUpdate, action: EIssueActions) =>
|
||||
await handleIssues(issueToUpdate as IIssue, action)
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
|
@ -194,7 +194,7 @@ export const SpreadsheetView: React.FC<Props> = observer((props) => {
|
||||
workspaceSlug={workspaceSlug.toString()}
|
||||
projectId={peekProjectId.toString()}
|
||||
issueId={peekIssueId.toString()}
|
||||
handleIssue={async (issueToUpdate: any) => await handleIssues(issueToUpdate, EIssueActions.UPDATE)}
|
||||
handleIssue={async (issueToUpdate: any, action: EIssueActions) => await handleIssues(issueToUpdate, action)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
@ -11,6 +11,7 @@ import { IssueView } from "components/issues";
|
||||
import { copyUrlToClipboard } from "helpers/string.helper";
|
||||
// types
|
||||
import { IIssue, IIssueLink } from "types";
|
||||
import { EIssueActions } from "../issue-layouts/types";
|
||||
// constants
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
|
||||
@ -18,7 +19,7 @@ interface IIssuePeekOverview {
|
||||
workspaceSlug: string;
|
||||
projectId: string;
|
||||
issueId: string;
|
||||
handleIssue: (issue: Partial<IIssue>) => void;
|
||||
handleIssue: (issue: Partial<IIssue>, action: EIssueActions) => Promise<void>;
|
||||
isArchived?: boolean;
|
||||
children?: ReactNode;
|
||||
}
|
||||
@ -31,7 +32,6 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
|
||||
|
||||
const {
|
||||
user: { currentProjectRole },
|
||||
issue: { removeIssueFromStructure },
|
||||
issueDetail: {
|
||||
createIssueComment,
|
||||
updateIssueComment,
|
||||
@ -98,7 +98,7 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
|
||||
|
||||
const issueUpdate = async (_data: Partial<IIssue>) => {
|
||||
if (handleIssue) {
|
||||
await handleIssue(_data);
|
||||
await handleIssue(_data, EIssueActions.UPDATE);
|
||||
fetchIssueActivity(workspaceSlug, projectId, issueId);
|
||||
}
|
||||
};
|
||||
@ -133,7 +133,7 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
|
||||
|
||||
const handleDeleteIssue = async () => {
|
||||
if (isArchived) await deleteArchivedIssue(workspaceSlug, projectId, issue!);
|
||||
else removeIssueFromStructure(workspaceSlug, projectId, issue!);
|
||||
else await handleIssue(issue!, EIssueActions.DELETE);
|
||||
const { query } = router;
|
||||
if (query.peekIssueId) {
|
||||
setPeekId(null);
|
||||
|
@ -10,6 +10,7 @@ import { CustomMenu, Tooltip } from "@plane/ui";
|
||||
// types
|
||||
import { IUser, IIssue } from "types";
|
||||
import { ISubIssuesRootLoaders, ISubIssuesRootLoadersHandler } from "./root";
|
||||
import { EIssueActions } from "../issue-layouts/types";
|
||||
|
||||
export interface ISubIssues {
|
||||
workspaceSlug: string;
|
||||
@ -29,6 +30,7 @@ export interface ISubIssues {
|
||||
issue?: IIssue | null
|
||||
) => void;
|
||||
handleUpdateIssue: (issue: IIssue, data: Partial<IIssue>) => void;
|
||||
handleDeleteIssue: (issue: IIssue) => Promise<void>;
|
||||
}
|
||||
|
||||
export const SubIssues: React.FC<ISubIssues> = ({
|
||||
@ -45,6 +47,7 @@ export const SubIssues: React.FC<ISubIssues> = ({
|
||||
copyText,
|
||||
handleIssueCrudOperation,
|
||||
handleUpdateIssue,
|
||||
handleDeleteIssue,
|
||||
}) => {
|
||||
const router = useRouter();
|
||||
const { peekProjectId, peekIssueId } = router.query;
|
||||
@ -69,7 +72,13 @@ export const SubIssues: React.FC<ISubIssues> = ({
|
||||
workspaceSlug={workspaceSlug}
|
||||
projectId={peekProjectId.toString()}
|
||||
issueId={peekIssueId.toString()}
|
||||
handleIssue={async (issueToUpdate) => await handleUpdateIssue(issue, { ...issue, ...issueToUpdate })}
|
||||
handleIssue={async (issueToUpdate, action) => {
|
||||
if (action === EIssueActions.UPDATE) {
|
||||
await handleUpdateIssue(issue, { ...issue, ...issueToUpdate });
|
||||
} else if (action === EIssueActions.DELETE) {
|
||||
await handleDeleteIssue(issue);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<div>
|
||||
@ -180,6 +189,7 @@ export const SubIssues: React.FC<ISubIssues> = ({
|
||||
|
||||
{issuesLoader.visibility.includes(issue?.id) && issue?.sub_issues_count > 0 && (
|
||||
<SubIssuesRootList
|
||||
handleDeleteIssue={handleDeleteIssue}
|
||||
workspaceSlug={workspaceSlug}
|
||||
projectId={projectId}
|
||||
parentIssue={issue}
|
||||
|
@ -27,6 +27,7 @@ export interface ISubIssuesRootList {
|
||||
issue?: IIssue | null
|
||||
) => void;
|
||||
handleUpdateIssue: (issue: IIssue, data: Partial<IIssue>) => void;
|
||||
handleDeleteIssue: (issue: IIssue) => Promise<void>
|
||||
}
|
||||
|
||||
const issueService = new IssueService();
|
||||
@ -44,6 +45,7 @@ export const SubIssuesRootList: React.FC<ISubIssuesRootList> = ({
|
||||
copyText,
|
||||
handleIssueCrudOperation,
|
||||
handleUpdateIssue,
|
||||
handleDeleteIssue
|
||||
}) => {
|
||||
const { data: issues, isLoading } = useSWR(
|
||||
workspaceSlug && projectId && parentIssue && parentIssue?.id ? SUB_ISSUES(parentIssue?.id) : null,
|
||||
@ -70,6 +72,7 @@ export const SubIssuesRootList: React.FC<ISubIssuesRootList> = ({
|
||||
issues.sub_issues.length > 0 &&
|
||||
issues.sub_issues.map((issue: IIssue) => (
|
||||
<SubIssues
|
||||
handleDeleteIssue={handleDeleteIssue}
|
||||
key={`${issue?.id}`}
|
||||
workspaceSlug={workspaceSlug}
|
||||
projectId={projectId}
|
||||
|
@ -176,6 +176,16 @@ export const SubIssuesRoot: React.FC<ISubIssuesRoot> = observer((props) => {
|
||||
[updateIssueStructure, projectId, updateIssue, user, workspaceSlug]
|
||||
);
|
||||
|
||||
const handleDeleteIssue = useCallback(
|
||||
async (issue: IIssue) => {
|
||||
if (!workspaceSlug || !projectId || !user) return;
|
||||
|
||||
await removeIssue(workspaceSlug.toString(), projectId.toString(), issue.id);
|
||||
await mutate(SUB_ISSUES(parentIssue?.id));
|
||||
},
|
||||
[removeIssue, projectId, user, workspaceSlug, parentIssue?.id]
|
||||
);
|
||||
|
||||
const isEditable = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
|
||||
|
||||
const mutateSubIssues = (parentIssueId: string | null) => {
|
||||
@ -236,6 +246,7 @@ export const SubIssuesRoot: React.FC<ISubIssuesRoot> = observer((props) => {
|
||||
{issuesLoader.visibility.includes(parentIssue?.id) && workspaceSlug && projectId && (
|
||||
<div className="border border-b-0 border-custom-border-100">
|
||||
<SubIssuesRootList
|
||||
handleDeleteIssue={handleDeleteIssue}
|
||||
workspaceSlug={workspaceSlug.toString()}
|
||||
projectId={projectId.toString()}
|
||||
parentIssue={parentIssue}
|
||||
|
@ -82,7 +82,7 @@ const PageDetailsPage: NextPageWithLayout = observer(() => {
|
||||
description_html: newDescription,
|
||||
})
|
||||
.then(() => {
|
||||
mutatePageDetails((prevData) => ({ ...prevData, description_html: newDescription }) as IPage, false);
|
||||
mutatePageDetails((prevData) => ({ ...prevData, description_html: newDescription } as IPage), false);
|
||||
});
|
||||
};
|
||||
|
||||
@ -162,15 +162,12 @@ const PageDetailsPage: NextPageWithLayout = observer(() => {
|
||||
}, [pageDetails?.description_html]); // TODO: Verify the exhaustive-deps warning
|
||||
|
||||
function createObjectFromArray(keys: string[], options: any): any {
|
||||
return keys.reduce(
|
||||
(obj, key) => {
|
||||
return keys.reduce((obj, key) => {
|
||||
if (options[key] !== undefined) {
|
||||
obj[key] = options[key];
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
{} as { [key: string]: any }
|
||||
);
|
||||
}, {} as { [key: string]: any });
|
||||
}
|
||||
|
||||
const mutatePageDetailsHelper = (
|
||||
@ -499,7 +496,7 @@ const PageDetailsPage: NextPageWithLayout = observer(() => {
|
||||
projectId={projectId as string}
|
||||
issueId={peekIssueId ? (peekIssueId as string) : ""}
|
||||
isArchived={false}
|
||||
handleIssue={(issueToUpdate) => {
|
||||
handleIssue={async (issueToUpdate, action) => {
|
||||
if (peekIssueId && typeof peekIssueId === "string") {
|
||||
handleUpdateIssue(peekIssueId, issueToUpdate);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user