diff --git a/web/core/components/issues/sub-issues/issue-list-item.tsx b/web/core/components/issues/sub-issues/issue-list-item.tsx index 4d10587fd7..85055331a2 100644 --- a/web/core/components/issues/sub-issues/issue-list-item.tsx +++ b/web/core/components/issues/sub-issues/issue-list-item.tsx @@ -18,6 +18,7 @@ import { usePlatformOS } from "@/hooks/use-platform-os"; // plane web components import { IssueIdentifier } from "@/plane-web/components/issues"; // local components +import { useEpicAnalytics } from "@/plane-web/hooks/store"; import { IssueList } from "./issues-list"; import { IssueProperty } from "./properties"; // ui @@ -66,8 +67,10 @@ export const IssueListItem: React.FC = observer((props) => { const project = useProject(); const { getProjectStates } = useProjectState(); const { handleRedirection } = useIssuePeekOverviewRedirection(); + const { fetchEpicAnalytics } = useEpicAnalytics(); const { isMobile } = usePlatformOS(); const issue = getIssueById(issueId); + const parentIssue = getIssueById(parentIssueId); // derived values const projectDetail = (issue && issue.project_id && project.getProjectById(issue.project_id)) || undefined; @@ -214,11 +217,15 @@ export const IssueListItem: React.FC = observer((props) => { {disabled && ( { + onClick={async (e) => { e.stopPropagation(); e.preventDefault(); if (issue.project_id) - subIssueOperations.removeSubIssue(workspaceSlug, issue.project_id, parentIssueId, issue.id); + await subIssueOperations + .removeSubIssue(workspaceSlug, issue.project_id, parentIssueId, issue.id) + .then(() => { + if (parentIssue?.is_epic) fetchEpicAnalytics(workspaceSlug, projectId, parentIssue.id); + }); }} >
diff --git a/web/ee/components/epics/details/main/overview-section/issues-root.tsx b/web/ee/components/epics/details/main/overview-section/issues-root.tsx index 2d08920971..556df78574 100644 --- a/web/ee/components/epics/details/main/overview-section/issues-root.tsx +++ b/web/ee/components/epics/details/main/overview-section/issues-root.tsx @@ -19,6 +19,7 @@ import { cn } from "@/helpers/common.helper"; import { useIssueDetail } from "@/hooks/store"; // plane web imports import { SectionEmptyState } from "@/plane-web/components/common/layout/main/common"; +import { useEpicAnalytics } from "@/plane-web/hooks/store"; import { useInitiatives } from "@/plane-web/hooks/store/use-initiatives"; type Props = { @@ -68,6 +69,7 @@ export const EpicIssuesOverviewRoot: FC = observer((props) => { peekIssue: epicPeekIssue, } = useIssueDetail(EIssueServiceType.EPICS); const { toggleCreateIssueModal, toggleDeleteIssueModal } = useIssueDetail(EIssueServiceType.EPICS); + const { fetchEpicAnalytics } = useEpicAnalytics(); const { initiative: { fetchInitiativeAnalytics }, } = useInitiatives(); @@ -95,6 +97,27 @@ export const EpicIssuesOverviewRoot: FC = observer((props) => { await subIssueOperations.fetchSubIssues(workspaceSlug, projectId, epicId); }, [epicId, projectId, subIssueOperations, workspaceSlug]); + const handleDeleteSubIssue = async () => { + await subIssueOperations + .deleteSubIssue( + workspaceSlug, + projectId, + issueCrudState?.delete?.parentIssueId as string, + issueCrudState?.delete?.issue?.id as string + ) + .then(() => { + fetchEpicAnalytics(workspaceSlug, projectId, epicId); + }); + }; + + const handleUpdateSubIssue = async (_issue: TIssue) => { + await subIssueOperations + .updateSubIssue(workspaceSlug, projectId, epicId, _issue.id, _issue, issueCrudState?.update?.issue, true) + .then(() => { + fetchEpicAnalytics(workspaceSlug, projectId, epicId); + }); + }; + useEffect(() => { handleFetchSubIssues(); @@ -182,14 +205,7 @@ export const EpicIssuesOverviewRoot: FC = observer((props) => { toggleDeleteIssueModal(null); }} data={issueCrudState?.delete?.issue as TIssue} - onSubmit={async () => - await subIssueOperations.deleteSubIssue( - workspaceSlug, - projectId, - issueCrudState?.delete?.parentIssueId as string, - issueCrudState?.delete?.issue?.id as string - ) - } + onSubmit={handleDeleteSubIssue} isSubIssue /> )} @@ -202,17 +218,7 @@ export const EpicIssuesOverviewRoot: FC = observer((props) => { toggleCreateIssueModal(false); }} data={issueCrudState?.update?.issue ?? undefined} - onSubmit={async (_issue: TIssue) => { - await subIssueOperations.updateSubIssue( - workspaceSlug, - projectId, - epicId, - _issue.id, - _issue, - issueCrudState?.update?.issue, - true - ); - }} + onSubmit={async (_issue: TIssue) => handleUpdateSubIssue(_issue)} /> )} diff --git a/web/ee/components/epics/details/main/overview-section/modals-root.tsx b/web/ee/components/epics/details/main/overview-section/modals-root.tsx index 440b9470dd..118e99d5cf 100644 --- a/web/ee/components/epics/details/main/overview-section/modals-root.tsx +++ b/web/ee/components/epics/details/main/overview-section/modals-root.tsx @@ -127,9 +127,7 @@ export const EpicOverviewWidgetModals: FC = observer((props) => { const isParentEpic = parentIssueTypeDetails?.is_epic; if (isParentEpic) { - await addSubIssueToEpic(workspaceSlug, projectId, _issue.parent_id, [_issue.id]).then(() => { - fetchEpicAnalytics(workspaceSlug, projectId, epicId); - }); + await addSubIssueToEpic(workspaceSlug, projectId, _issue.parent_id, [_issue.id]); } else { await addSubIssue(workspaceSlug, projectId, _issue.parent_id, [_issue.id]); } diff --git a/web/ee/store/issue/epic/analytic.store.ts b/web/ee/store/issue/epic/analytic.store.ts index 29a406463e..2ed621a858 100644 --- a/web/ee/store/issue/epic/analytic.store.ts +++ b/web/ee/store/issue/epic/analytic.store.ts @@ -93,6 +93,16 @@ export class EpicAnalytics implements IEpicAnalyticStore { const analytics = await this.epicService.getIssueProgressAnalytics(workspaceSlug, projectId, epicId); runInAction(() => { set(this.epicAnalyticsMap, epicId, analytics); + set(this.epicStatsMap, epicId, { + total_issues: + analytics.backlog_issues + + analytics.unstarted_issues + + analytics.started_issues + + analytics.completed_issues + + analytics.cancelled_issues, + cancelled_issues: analytics.cancelled_issues, + completed_issues: analytics.completed_issues, + }); this.epicAnalyticsLoader[epicId] = "loaded"; }); return analytics;