Skip to content

[AGILE-66] Sprint reports: velocity widget - #25885

Open
EinLama wants to merge 17 commits into
devfrom
feature/agile-66-provide-velocity-charts
Open

EinLama wants to merge 17 commits into
devfrom
feature/agile-66-provide-velocity-charts

Conversation

@EinLama

@EinLama EinLama commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Ticket

https://community.openproject.org/wp/AGILE-66

What are you trying to accomplish?

Show a chart for the (at most) past 6 sprints plus the currently viewed sprint and their velocity.

Screenshots

image

What approach did you choose and why?

Introduced a new POR class Velocity which, much like SprintWorkPackageBreakdown contains all the logic to collect the relevant sprints and calculate their velocity. To do this, Velocity makes use of SprintWorkPackageBreakdown, as that class already provides counts for committed and completed work packages and their story points.

The chart itself only renders the given data. Worth mentioning here is the introduction of a the AverageLinePlugin that will render a dashed line across the diagram. It is used to render an average baseline through the chart. It could be useful for other charts, too.
Apart from making use of the plugin, the chart overrides the default primer colors to match the design's colors. It works well in both light and dark mode.

For now, only story points are supported as a metric. Other estimation units will be added in AGILE-457.

AI involvement

Collaborative – AI generated a substantial part of the code; I reviewed and understand every line.

Merge checklist

  • Added/updated tests
  • Added/updated documentation in Lookbook (patterns, previews, etc)
  • Tested major browsers (Chrome, Firefox, Edge, ...)

@github-actions github-actions Bot added the ai: Collaborative 💻 AI generated a substantial part of the code; A human reviewed and understands every line. label Oct 8, 2026
@EinLama
EinLama force-pushed the feature/agile-66-provide-velocity-charts branch from 31674ea to bebdc0d Compare October 8, 2026 07:43
@EinLama
EinLama requested a balanced review from Copilot October 8, 2026 08:03

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The chart lacks an accessible representation of its historical data, and its frontend drawing behavior needs focused tests.

3 open findings
What changed in this PR

Adds a sprint velocity widget showing committed/completed story points and an average baseline across up to seven sprints.

Changes:

  • Adds historical velocity calculation and reporting UI.
  • Introduces an Angular bar chart and average-line plugin.
  • Adds backend, component, and feature coverage.
File Description
modules/​backlogs/​spec/​models/​backlogs/​velocity_spec.rb Tests velocity calculations.
modules/​backlogs/​spec/​features/​backlogs/​sprint_reports/​velocity_chart_widget_spec.rb Tests widget integration.
modules/​backlogs/​spec/​features/​backlogs/​sprint_reports/​show_spec.rb Verifies widget ordering.
modules/​backlogs/​spec/​components/​backlogs/​sprint_reports/​widgets/​velocity_chart_spec.rb Tests rendered chart data.
modules/​backlogs/​config/​locales/​en.yml Adds velocity labels.
modules/​backlogs/​app/​views/​backlogs/​sprint_reports/​show.html.erb Adds the widget to reports.
modules/​backlogs/​app/​models/​backlogs/​velocity.rb Calculates sprint velocity data.
modules/​backlogs/​app/​components/​backlogs/​sprint_reports/​widgets/​velocity_chart.rb Builds widget data and summaries.
modules/​backlogs/​app/​components/​backlogs/​sprint_reports/​widgets/​velocity_chart.html.erb Renders the widget.
frontend/​src/​app/​features/​backlogs/​velocity-chart.component.ts Configures the bar chart.
frontend/​src/​app/​features/​backlogs/​velocity-chart.component.html Provides the chart canvas.
frontend/​src/​app/​features/​backlogs/​plugin.average-line.ts Draws the average baseline.
frontend/​src/​app/​app.module.ts Registers the custom element.

🧠 Review effort: Balanced


Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.

Comment thread frontend/src/app/features/backlogs/velocity-chart.component.html
Comment thread frontend/src/app/features/backlogs/plugin.average-line.ts
Comment thread modules/backlogs/app/components/backlogs/sprint_reports/widgets/velocity_chart.rb Outdated
@github-actions

github-actions Bot commented Oct 8, 2026

Copy link
Copy Markdown

Warning

Flaky specs

  • rspec ./modules/gantt/spec/features/timeline/timeline_dates_spec.rb[1:2:1]
  • rspec ./spec/features/users/invite_user_modal/invite_user_modal_spec.rb[1:3:1:1:3:1:1]
🤖 Ask Copilot to investigate

Copy the prompt below into a new comment on this PR to delegate the investigation to GitHub Copilot. It will look into the flakiness and open a separate pull request with you as reviewer.

@copilot The following spec(s) are flaky in CI (first seen on PR #25885, linked for reference only):

- `rspec ./modules/gantt/spec/features/timeline/timeline_dates_spec.rb[1:2:1]`
- `rspec ./spec/features/users/invite_user_modal/invite_user_modal_spec.rb[1:3:1:1:3:1:1]`

Treat this as a standalone task, unrelated to PR #25885. Create a new branch from origin/dev and open a new pull request targeting dev — do not stack it on PR #25885 or reuse that branch.

Follow the playbook in docs/development/testing/handling-flaky-tests/README.md to find the root cause and fix the underlying race — do not skip, delete, or weaken the spec to make it pass; disabling is a last resort per the playbook, and only with a bug ticket. Verify the fix by running the spec(s) repeatedly (e.g. `script/bulk_run_rspec --run-count 10`).

If you cannot reproduce the flake or are not confident in a fix after reasonable investigation, do not fabricate a change or skip the spec to force CI green. Instead, leave the pull request in draft and document what you tried, the suspected cause, and any leads in its description, then assign @EinLama to take over.

Once the fix is verified, title the PR after the spec(s) it fixes, and use the PR description to explain the root cause, how the change resolves it, and the before/after results. Label the PR `flaky-spec`, assign @EinLama, and request a review from @EinLama.
On every commit, set @EinLama as the sole co-author with a `Co-authored-by:` trailer (use their GitHub no-reply email so it links to their account), so it is traceable who dispatched the fix.

@ulferts ulferts left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not done with the review. I haven't read the tests yet and I also need to thoroughly test the changes in the application. Whether you @EinLama want to start addressing the topics is up to you.

But from my first glimpses, I think this is behaving nicely. I personally liked rendering a table for screen reader. The code structure is 'boring', in a good way. Everything is where I would expect it to be.

Todos

Visual

Average line number font

The number on the average line should be in bold and at least according to the figma files look just like the ones in each bar:

PR:
Image

Figma:

Image

Low numbers and disabling a data set

When having a bar with very low numbers e.g. 0 and disabling the other data set, the number overlaps the sprint name

Image

Empty space above bars

Probably depending on the data, there is as much empty space in the chart as there is filled one. From what I remember, it is not easy to get ChartJS to use a less wasteful approach but it could be worth a try. In the Burndown chart a suggestedMax is provided

Image

This is probably the result of combining grace: '10%' and maxTicksLimit: 3.

Unclear average line semantics

For a user, it might be unclear, what the line showing the average of the completed story points means. The line has no description and is displayed both when the 'Completed' data set is enabled but also when it is disabled:

Image

This is more a product question than a technical one. In a meeting we discussed the option to let the line work just like the other data sets. If that happens, there would be a legend explaining what it does.

Average line when disabling both data sets

This is maybe a non issue, maybe a nitpick: when disabling both data sets, the graph is empty with a small y-axis visible. In it, the average line is then not displayed:

Image

@@ -0,0 +1,33 @@
<div class="position-relative" style="height: 320px">

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll need to extract this hard wired height into a class to then be used by all the charts on the reports page. The Burndown PR does it admittedly with a name that is not generic.

Probably to be done after merging both PRs.

Comment thread frontend/src/app/features/backlogs/velocity-chart.component.ts Outdated
Comment thread frontend/src/app/features/backlogs/velocity-chart.component.html

function truncate(label:string):string {
return label.length > MAX_LABEL_LENGTH ? `${label.slice(0, MAX_LABEL_LENGTH - 1).trimEnd()}…` : label;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code should probably be shared with other charts so it should be extracted.

One could also work on measuring the text that is rendered and trim when necessary. That would allow more flexibility when showing the charts on wider screens vs on narrow ones. But I would be ok with this coming at a later stage when we feel it necessary.

Comment thread modules/backlogs/app/components/backlogs/sprint_reports/widgets/velocity_chart.rb Outdated
Comment thread modules/backlogs/app/models/sprints/velocity.rb Outdated
Comment thread modules/backlogs/app/models/sprints/velocity.rb
end

def breakdowns
@breakdowns ||= sprints.map { SprintWorkPackageBreakdown.new(sprint: it, project:) }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This leads to four queries being fired per sprint displayed so 28 max (as snapshot_block does two queries each count and sum). Of those, only half are used.

The WorkPackages::JournalTimeline can do it in a single query and could be applied here. If used, it will also:

  • apply visibility at the time of querying. E.g. a work package moved out of the project would still be counted. WorkPackage.at_timestamp(...).visible does not do that AFAIK.
  • because of the above, with Burndown using WorkPackages::JournalTimeline I expect the widgets to show different values potentially. The discrepancy would also apply to the Overview widget.

Using WorkPackages::JournalTimeline here and in SprintWorkPackageBreakdown.snapshot_block would resolve those discrepancies.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I too think it would make sense to apply the JournalTimeline to SprintWorkPackageBreakdown, too. This would also keep this (velocity) chart and the work package overview widget in sync. If they used two different mechanics to count work packages, a user would see different numbers for the same metric in some edge cases.

@ulferts ulferts left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only some small additions to what I have commented on yesterday. They lean more towards asking product. The other parts are nitpicks.

Todo

Average factoring in current sprint

This is more of a specification question - we need to discuss this with Product. The chart currently factors in the current sprint as well when calculating the average. Naturally, at the beginning of a sprint, that number is low, reducing the average without any actual reason. I think we should not factor in the current sprint in the average.

Average if there is no predecessor

Again a question for Product: We might want to display no average if there is no previous sprint. This looks off:

Image

Omitting the dashed line and the mentioning of the average in the header would be one option. We could also think about not showing the chart at all if there is no previous sprint.

Comment thread modules/backlogs/spec/models/sprints/velocity_spec.rb Outdated
Comment thread modules/backlogs/spec/models/sprints/velocity_spec.rb Outdated
Comment thread modules/backlogs/app/models/sprints/velocity.rb Outdated
Comment thread frontend/src/app/features/backlogs/velocity-chart.component.ts Outdated
@EinLama
EinLama force-pushed the feature/agile-66-provide-velocity-charts branch from 30ff1a7 to 5483925 Compare October 23, 2026 07:47
@EinLama

EinLama commented Oct 23, 2026

Copy link
Copy Markdown
Contributor Author

Average factoring in current sprint

This is more of a specification question - we need to discuss this with Product. The chart currently factors in the current sprint as well when calculating the average. Naturally, at the beginning of a sprint, that number is low, reducing the average without any actual reason. I think we should not factor in the current sprint in the average.

Average if there is no predecessor

Again a question for Product: We might want to display no average if there is no previous sprint.

We discussed both of these today and both were agreed upon.

We will not factor in the current sprint for calculating the average. Additionally, when there's no average to show (there's no previous sprint), we don't show the dotted line and legend and we also don't show the title caption about the average.

@EinLama
EinLama force-pushed the feature/agile-66-provide-velocity-charts branch from 7ec5d77 to 86f7d28 Compare October 26, 2026 07:06
@EinLama
EinLama force-pushed the feature/agile-66-provide-velocity-charts branch from 86f7d28 to 06755de Compare October 26, 2026 07:36

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai: Collaborative 💻 AI generated a substantial part of the code; A human reviewed and understands every line.

Development

Successfully merging this pull request may close these issues.

3 participants