Skip to content

extract issues summary widget into edition partials, rework chart legend - #1638

Open
MattBudz wants to merge 27 commits into
developfrom
dashboard/extract-issues-summary-edition-partial
Open

extract issues summary widget into edition partials, rework chart legend#1638
MattBudz wants to merge 27 commits into
developfrom
dashboard/extract-issues-summary-edition-partial

Conversation

@MattBudz

@MattBudz MattBudz commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Summary

Moves the full issues summary widget markup out of _summary.html.erb and into projects/issues/summary/_ce.html.erb, making _summary.html.erb an edition dispatcher:

<%= render "projects/issues/summary/#{Dradis.edition}" %>

This follows the same pattern used by the navbar (layouts/hera/navbar/_main_nav.html.erb) so that Pro can provide its own _pro.html.erb without _summary.html.erb diverging between repos and causing merge conflicts on every ce-sync.

Building on that, the widget now lazy-loads its content instead of ProjectsController#show eagerly computing the tag grouping just to embed it synchronously:

  • IssuesGrouping is renamed to IssuesDimensionGrouping, since it builds more than a plain grouping (chart data, accordion data, and the available dimensions).
  • A new Projects::IssuesSummaryController#show (route resource :issues_summary) owns the tag-grouping computation.
  • The chart and accordion markup is extracted into a shared projects/issues/_summary_content partial, rendered as the actual frame body by issues_summary/show.html.erb.
  • _ce.html.erb becomes a shell: the header plus a turbo_frame_tag with src: pointing at the new controller, instead of embedding the content.

The header now always renders, even with no issues (previously the whole widget, header included, was replaced by the empty state).

Also includes a fix for the shared ComboBox module (app/assets/javascripts/hera/modules/combobox.js): filter() and find() built CSS attribute selectors by interpolating option values directly into a template string. A value containing a double quote breaks the selector with a Sizzle syntax error, leaving the combobox showing a stale label even though the underlying select's value updated correctly. Matching is now done by exact attribute value instead of a raw selector, which can't be broken by selector metacharacters.

Finally, reworks the "Issues so far" bar chart's legend. Tag names used to render as x-axis tick labels directly under each bar, which overlapped and became unreadable once a name was longer than a few characters. The legend is now a separate list below the chart that wraps horizontally, so each name gets a full row's width instead of a single bar's width, and the chart itself stays full size. The chart container is now selected via data-behavior="issue-chart" instead of its id, per the JS element-selection convention.

Testing steps

  1. Visit a project dashboard with issues that have tags. Confirm the "Issues so far" widget loads (briefly showing a blank area while the frame fetches, then) the chart and tag accordion.
  2. Visit a project dashboard with no issues. Confirm the header still renders and the empty state message shows below it.
  3. Visit /styles, open the "Multi-select & User-defined Option Example" combobox, type a value containing a double quote (e.g. Weird"Value) and add it as a custom option. Select it and confirm no console error, and the combobox label and selected tag both display correctly.
  4. Tag some issues with names long enough to overflow a single bar's width. Confirm the legend renders below the chart, wraps to multiple rows as needed, and each name stays readable.

Check List

  • Added a CHANGELOG entry (internal refactor, no user-facing feature change)
  • Commit message has a detailed description of what changed and why.

MattBudz added 5 commits June 29, 2026 14:51
Moves the full widget markup into projects/issues/summary/_ce.html.erb
and makes _summary.html.erb an edition dispatcher so Pro can override
with its own _pro.html.erb without causing merge conflicts on this file.

@etdsoft etdsoft left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Automated peer review -- PR #1638

Reviewers: Claude (sub-agent 1), Codex (sub-agent 2)
Verdict: comment
Findings: 0 High, 0 Medium, 2 Low

What I checked

This is an automated peer code review by two independent LLM sub-agents reading the same rubric. Findings flagged by both agents are higher confidence; findings flagged by only one are still worth your attention. The verdict is computed from severity counts -- there is no editorial judgment in the merge step.

Both reviewers agreed

(none)

Claude only

F1 [Low|consistency] app/controllers/projects_controller.rb:43-45 -- redundant .to_json on hash values

What: @chart_data pre-serializes @tag_names and @count_by_tag with .to_json before handing the hash to tag.div data: @chart_data in the view.

Why: Rails' tag.div data: helper already JSON-encodes Hash and Array values when emitting data-* attributes — the wire result is identical either way. Pre-stringifying duplicates work the framework already does and risks subtle drift if to_json representation ever diverges from what Rails emits.

How to fix:

@chart_data = {
  dimension: 'tags',
  tags: @tag_names,
  issues_count: @count_by_tag
}

The resulting HTML-escaped data-tags / data-issues-count attributes will be identical, and $chartElement.data('tags') / .data('issues-count') in issues_chart.js will still auto-parse them to JS objects.


F2 [Low|hygiene] PR:- -- thin testing steps for a multi-layer refactor

What: Testing steps cover only "render identically to before" on the project dashboard. The PR touches the controller, the dispatcher partial, two new partials, and rewrites the chart JS.

Why: A single render check won't catch a regression in the empty-state branch (no issues), the unassigned bucket, or the chart's tag/count mapping. For a refactor whose claim is "no behavior change," exercising the branches that could silently change is the point of the testing steps.

How to fix: Add steps covering (a) a project with multiple tagged issues, (b) a project with only unassigned issues, (c) a project with no issues (empty state), and confirm chart bar colors/counts and accordion ordering match the pre-refactor build.

Codex only

(none)

Notes

  • Codex ran in a sandboxed environment without GitHub API access; it reviewed the checked-out branch against origin/develop in full but could not perform PR metadata/hygiene checks. Its zero-findings conclusion is based on the local code read.
  • _tags_accordion.html.erb carries forward two pre-existing patterns from the old _summary.html.erb: inline style="..." for dynamic tag colors (unavoidable — colors are user-configurable) and id="collapse<%= tag.display_name %>" (fragile if a display_name contains spaces, #, or ?). Neither introduced by this PR.
  • The old partial had a typo collape<...> on both href and id; the new partial spells it collapse<...> consistently. Incidental cleanup, invisible to users.
  • dimension: 'tags' in @chart_data is unused by the CE chart JS. Reads as deliberate scaffolding for a future Pro partial dispatch key.

Reviewed automatically. Raw outputs in the shared product reviews directory (see TOOLS.md).

Comment thread app/views/projects/issues/summary/_tags_accordion.html.erb Outdated
Comment thread app/controllers/projects_controller.rb Outdated
end
end

@chart_data = {

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 breaks parity with pro since it isn't used there in the same controller. As a compromise, I'm fine with moving this definition in the CE view if we add a comment.

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.

Went a step further than the view-move compromise, extracted the tag-grouping logic (including @chart_data) into a shared IssuesGrouping concern, matching how Pro already needs to call it from more than one controller. ProjectsController#show now just calls build_all_tags_grouping. This should make the sync cleaner since Pro's version of the concern can now land as an addition to this file rather than introducing it from scratch.

MattBudz added 3 commits July 15, 2026 13:26
for..in leaks the loop variable into the surrounding method scope, which
each avoids.
Pro needs this same grouping logic from more than one controller, so it
already lives in a concern there. Duplicating it inline here meant
ProjectsController#show diverged structurally between the two repos.
Extracting it in CE keeps both controllers aligned and lets Pro's version
of the concern sync in as an addition rather than a rewrite.
@@ -0,0 +1,30 @@
module IssuesGrouping

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.

IssuesGrouping sounds a bit vague. Grouping for what? I believe this concern is building the chart data and the name should reflect that.

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.

Renamed it to IssuesDimensionGrouping. It's not just building @chart_data, it also builds the accordion groupings (@issues_by_tag in CE, plus @issues_by_list_value in Pro) and, in Pro, enumerates the available list fields for the dimension dropdown. The name attempts to cover all three, not just the chart.

MattBudz added 18 commits July 16, 2026 15:58
The concern builds chart and accordion data grouped by a selectable
dimension (tags today, RTP list fields in Pro), so "grouping" alone
undersold what it does.
Foundation for lazy-loading the "Issues so far" dashboard widget, so
ProjectsController#show doesn't need to eagerly compute the tag
grouping just to embed it synchronously.
Extracts the chart/accordion markup into a shared summary_content
partial, rendered as the actual frame body by issues_summary/show.
The CE edition partial becomes a shell that fetches this content via
turbo_frame_tag's src instead of embedding it, matching the header
staying visible even with no issues (previously the whole widget,
header included, was replaced by the empty state).
The dashboard widget now lazy-loads its content through
Projects::IssuesSummaryController, so computing the same grouping
here just to embed it synchronously was wasted, duplicated work.
Blocking rubocop-ci for this branch's changed-file set.
The widget now lazy-loads via a turbo frame, so #issue-chart never
exists at turbo:load time. Without this, the chart never rendered.
Request specs alone wouldn't have caught the chart never rendering,
since that regression only showed up in the browser (turbo:frame-load
wasn't wired up to initialize the chart).
The accordion now renders inside the async-loaded issues-summary
frame, so clicking an issue link navigated within that small frame
instead of the full page. Added a spec covering the click-through,
since the existing chart-rendering spec didn't exercise this path.
Drops the manual { unassigned: 0 } seed hash and the per-tag = 0
pre-seed loop. The chart JS already falls back to 0 for any tag
missing from issues_count, so the pre-seed was never load-bearing.
Builds the fill colors alongside the rest of the chart data in one
pass, instead of re-deriving them from tags a second time in the
coloring step. No behavior change.
padding to a fixed column breaks as soon as a variable name changes
length; plain single-space declarations don't drift
filter() and find() built CSS attribute selectors by string-interpolating
option values directly. A value containing a double quote breaks the
selector (Sizzle syntax error), leaving the combobox showing a stale
label even though the underlying select's value updated correctly.
Match by exact attribute value instead, which can't be broken by
selector metacharacters.
…-edition-partial' into dashboard/extract-issues-summary-edition-partial
@MattBudz MattBudz changed the title extract issues summary widget into edition partials extract issues summary widget into edition partials, rework chart legend Aug 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants