Summary
Adds a third closed series to the PR Activity chart on the repository details page's Pull Requests tab, drawn as a red line using STATUS_COLORS.closed so it matches the Closed pill used elsewhere in the app. The behavior mirrors the existing Opened and Merged series in RepositoryPrActivityChart: same countByKey bucketing, same eachDayOfInterval / eachMonthOfInterval axis, same line/bar mode toggle, same 7D / 35D / All range selector. The third series counts PRs that were closed without merge (closedAt set, mergedAt null), so merged PRs aren't double-counted on both lines.
Motivation
The repository PR totals row directly above the chart breaks PRs into Open, Merged, and Closed (e.g. 601 / 325 / 268 on entrius/gittensor-ui), but the chart underneath only visualizes two of those three outcomes. A meaningful slice of repository activity — 268 PRs in this repo's case — is invisible in the trend view, and the chart visibly contradicts the totals row sitting above it.
Surfacing the Closed series lets users spot stretches where PRs were being closed without merge (drift, churn, low-quality submissions) versus periods of healthy merge activity, compare repository "health" at a glance, and trust the chart as an honest summary of the totals row above it. The pattern of charting multiple PR/issue states on one axis is already used by the chart's own issue mode (Opened/Closed), so adding a third PR-mode series brings the two modes to parity.
Scope
| Surface |
Change |
RepositoryPrActivityChart (PR mode) |
Third Closed series added |
| Legend |
Opened / Merged / Closed |
| Line color |
STATUS_COLORS.closed (red) |
| Counted PRs |
closedAt set and mergedAt null |
| Range selector (7D / 35D / All) |
Applies to all three series |
| Mode toggle (line / bar) |
Applies to all three series |
| Tooltip |
Shows all three counts on hover |
Out of scope: any change to issue mode (already has its own Opened/Closed pairing); changing the default range (still 35D); changes to the totals row above the chart; backend changes (closedAt and mergedAt are already returned).
Technical notes
buildChartOption in src/components/repositories/RepositoryPrActivityChart.tsx takes hardcoded prOpened / prMerged arrays and firstLabel / secondLabel / secondSeriesColor args; extend it to accept a third series (prClosed, thirdLabel, thirdSeriesColor) and push a third entry into legend.data, color, and series.
- The
useMemo that derives firstSeries / secondSeries already flattens pr.closedAt into the axis-date pool (src/components/repositories/RepositoryPrActivityChart.tsx:297) — add a thirdSeries next to it: countByKey(repoPrs.filter((pr) => !pr.mergedAt), axisKeys, (pr) => pr.closedAt, bucket).
- Use
alpha(STATUS_COLORS.closed, 0.95) for the line + area-fill gradient, matching how STATUS_COLORS.merged is consumed today.
- Issue-mode call site (
isIssueMode === true) should keep its existing two-series shape — pass undefined for the new third-series args so buildChartOption only renders three series in PR mode.
hasAny should account for the new series: first.some(n => n > 0) || second.some(n => n > 0) || third.some(n => n > 0).
Summary
Adds a third
closedseries to the PR Activity chart on the repository details page's Pull Requests tab, drawn as a red line usingSTATUS_COLORS.closedso it matches the Closed pill used elsewhere in the app. The behavior mirrors the existing Opened and Merged series inRepositoryPrActivityChart: samecountByKeybucketing, sameeachDayOfInterval/eachMonthOfIntervalaxis, same line/bar mode toggle, same 7D / 35D / All range selector. The third series counts PRs that were closed without merge (closedAtset,mergedAtnull), so merged PRs aren't double-counted on both lines.Motivation
The repository PR totals row directly above the chart breaks PRs into Open, Merged, and Closed (e.g. 601 / 325 / 268 on
entrius/gittensor-ui), but the chart underneath only visualizes two of those three outcomes. A meaningful slice of repository activity — 268 PRs in this repo's case — is invisible in the trend view, and the chart visibly contradicts the totals row sitting above it.Surfacing the Closed series lets users spot stretches where PRs were being closed without merge (drift, churn, low-quality submissions) versus periods of healthy merge activity, compare repository "health" at a glance, and trust the chart as an honest summary of the totals row above it. The pattern of charting multiple PR/issue states on one axis is already used by the chart's own issue mode (Opened/Closed), so adding a third PR-mode series brings the two modes to parity.
Scope
RepositoryPrActivityChart(PR mode)Opened/Merged/ClosedSTATUS_COLORS.closed(red)closedAtset andmergedAtnullOut of scope: any change to issue mode (already has its own Opened/Closed pairing); changing the default range (still 35D); changes to the totals row above the chart; backend changes (
closedAtandmergedAtare already returned).Technical notes
buildChartOptionin src/components/repositories/RepositoryPrActivityChart.tsx takes hardcodedprOpened/prMergedarrays andfirstLabel/secondLabel/secondSeriesColorargs; extend it to accept a third series (prClosed,thirdLabel,thirdSeriesColor) and push a third entry intolegend.data,color, andseries.useMemothat derivesfirstSeries/secondSeriesalready flattenspr.closedAtinto the axis-date pool (src/components/repositories/RepositoryPrActivityChart.tsx:297) — add athirdSeriesnext to it:countByKey(repoPrs.filter((pr) => !pr.mergedAt), axisKeys, (pr) => pr.closedAt, bucket).alpha(STATUS_COLORS.closed, 0.95)for the line + area-fill gradient, matching howSTATUS_COLORS.mergedis consumed today.isIssueMode === true) should keep its existing two-series shape — passundefinedfor the new third-series args sobuildChartOptiononly renders three series in PR mode.hasAnyshould account for the new series:first.some(n => n > 0) || second.some(n => n > 0) || third.some(n => n > 0).