[WEB-4554]fix: initiative epics stats (#3730)

This commit is contained in:
Vamsi Krishna
2025-07-23 20:20:46 +05:30
committed by GitHub
parent 2d9cdf0ae7
commit 5c3d09fd7f
4 changed files with 46 additions and 9 deletions

View File

@@ -401,6 +401,25 @@ class InitiativeAnalyticsEndpoint(BaseAPIView):
"cancelled",
]
},
# Total issue count
**{
f"total_{state}_issues": Count(
"id",
filter=Q(
Q(project_id__in=project_ids)
| Q(id__in=initiative_epics)
| Q(id__in=related_issues_ids),
)
& Q(state__group=state),
)
for state in [
"backlog",
"unstarted",
"started",
"completed",
"cancelled",
]
},
)
return issues_counts
@@ -506,6 +525,13 @@ class InitiativeAnalyticsEndpoint(BaseAPIView):
"completed_issues": issues_counts.get("completed_issues", 0),
"cancelled_issues": issues_counts.get("cancelled_issues", 0),
},
"total_count": {
"backlog_issues": issues_counts.get("total_backlog_issues", 0),
"unstarted_issues": issues_counts.get("total_unstarted_issues", 0),
"started_issues": issues_counts.get("total_started_issues", 0),
"completed_issues": issues_counts.get("total_completed_issues", 0),
"cancelled_issues": issues_counts.get("total_cancelled_issues", 0),
},
}
return Response(

View File

@@ -22,13 +22,11 @@ export const InitiativeProgressSection: FC<Props> = observer((props) => {
// derived values
const initiative = getInitiativeById(initiativeId);
const initiativeProjectAnalytics = getInitiativeAnalyticsById(initiativeId)?.project;
const cumulatedAnalytics = getInitiativeAnalyticsById(initiativeId)?.total_count;
const projectsIds = initiative?.project_ids ?? [];
const initiativeEpics = initiative?.epic_ids ?? [];
const totalIssues = initiativeProjectAnalytics
? Object.values(omit(initiativeProjectAnalytics, "overdue_issues")).reduce((acc, val) => acc + val, 0)
: 0;
const totalIssues = Object.values(cumulatedAnalytics ?? {}).reduce((acc, val) => acc + val, 0);
const shouldRenderProgressSection = (projectsIds.length ?? 0) > 0 || initiativeEpics.length > 0 || totalIssues > 0;
@@ -36,7 +34,7 @@ export const InitiativeProgressSection: FC<Props> = observer((props) => {
return (
<ProgressSection
data={initiativeProjectAnalytics as TStateAnalytics}
data={cumulatedAnalytics as TStateAnalytics}
indicatorElement={
<>
<Tooltip

View File

@@ -87,14 +87,19 @@ type Props = {
export const ScopeBreakdown = observer((props: Props) => {
const { workspaceSlug, initiativeId, toggleProjectModal, toggleEpicModal, disabled } = props;
const {
initiative: { getInitiativeAnalyticsById, getInitiativeById },
initiative: {
getInitiativeAnalyticsById,
getInitiativeById,
epics: { getInitiativeEpicsById },
},
} = useInitiatives();
// derived values
const initiativeAnalytics = getInitiativeAnalyticsById(initiativeId);
const initiative = getInitiativeById(initiativeId);
const initiativeEpics = getInitiativeEpicsById(initiativeId);
const epicsCount = initiative?.epic_ids?.length ?? 0;
const epicsCount = initiativeEpics?.length ?? 0;
const projectsCount = initiative?.project_ids?.length ?? 0;
return (
@@ -119,7 +124,7 @@ export const ScopeBreakdown = observer((props: Props) => {
</div>
</div>
{/* content */}
{!projectsCount && !epicsCount ? (
{projectsCount === 0 && epicsCount === 0 ? (
<SectionEmptyState
heading="No scope added to this initiative yet"
subHeading="Link projects and epics and track that work in this space."

View File

@@ -169,21 +169,29 @@ export type TInitiativeAnalyticsGroup =
| "cancelled_issues"
| "overdue_issues";
export type TInitiativeAnalyticData = {
export type TInitiativeIssueAnalytics = {
backlog_issues: number;
unstarted_issues: number;
started_issues: number;
completed_issues: number;
cancelled_issues: number;
overdue_issues: number;
};
export type TInitiativeUpdateAnalytics = {
on_track_updates: number;
at_risk_updates: number;
off_track_updates: number;
};
export type TInitiativeAnalyticData = TInitiativeIssueAnalytics & TInitiativeUpdateAnalytics;
export type TInitiativeAnalyticDataWithCumulated = TInitiativeIssueAnalytics;
export type TInitiativeAnalytics = TInitiativeAnalyticData & {
project: TInitiativeAnalyticData;
epic: TInitiativeAnalyticData;
total_count: TInitiativeAnalyticDataWithCumulated;
};
export type TInitiativeStats = {