Skip to content

Update contributor analysis#645

Open
rivaquiroga wants to merge 7 commits intomasterfrom
update-contributor-analysis
Open

Update contributor analysis#645
rivaquiroga wants to merge 7 commits intomasterfrom
update-contributor-analysis

Conversation

@rivaquiroga
Copy link
Contributor

@rivaquiroga rivaquiroga commented Feb 12, 2026

Description

  1. Fixed contributor analysis link in tenzing_template.md
    Changed the link to the contributor analysis page from an absolute URL (https://forrt.org/contributor-analysis) to a relative path (/contributor-analysis), so it works correctly in staging and local development environments.

  2. Switch to contributors_cache.csv as data source
    Both index.Rmd and network-graph.Rmd previously fetched contributor data directly from the Tenzing Automation Source. They now read from contributors_cache.csv (generated by tenzing.py), making local rendering possible without credentials (in case people from Team Credit want to work on this). Role column names are still fetched dynamically from the public fields sheet.

  3. Network graph CSS isolation (iframe)
    The network graph HTML (a self-contained visNetwork widget) was previously included as a Hugo partial. This leaked its embedded CSS (Bootstrap, etc.) into the parent page, breaking the navbar and logo styling. Changed to an iframe approach: the HTML is now served from static/partials/network-graph.html with auto-resize. The layout was updated to use universal-wrapper (matching site width), consistent font size, and matching background color. The CI workflow (data-processing.yml) was updated accordingly to move the rendered HTML to static/partials/ instead of layouts/partials/.

  4. Code readability refactor

    • Renamed some variables to use snake_case more consistently and made them more descriptive in some cases (e.g., dtcredit_roles/contributions)
    • Used more modern R: |> instead of %>%, unite() instead of rowwise() + paste(), etc.
    • Replaced glue template block with inline R code in a markdown paragraph (so it's easier to edit in the future)
    • Removed unused libraries
  5. New treemap visualization
    Added a treemap between the two existing plots to illustrate how contributor engagement is distributed. It shows the share of contributors by number of projects contributed to (1, 2, 3, 4, 5+), complementing the text that mentions the average number of contributions per person.

  6. Lollipop chart for project contributors
    The original bar chart showed the top 10 projects but only labeled the first five (the long project names didn't fit as x-axis labels, and the remaining five bars were unlabeled). Flipping to horizontal bars looked too similar to the roles plot. Converted to a horizontal lollipop chart where every project name is legible on the y-axis.

  7. Cleaner roles plot
    Added contributor count labels at the end of each bar, removed x-axis numbers and grid lines (redundant with the labels). This also allowed increasing the y-axis font size for readability. All plots now use the Domine font (matching the website) via sysfonts/showtext, with centered titles and consistent styling.

  8. Network graph palette
    Edges changed from light blue (#87CEEB) to soft rose (#e08a8a) to align with the FORRT red palette. Default node color softened from black to gray (#666666) so that the red selected node (#A52828) stands out more clearly.

TODO: Leadership roles handling in the network
Currently, the network only uses data from the Tenzing sheets, leaving out the leadership roles. I tried to add them, but this changes the graph topology significantly, breaking the visIgraphLayout centering. I left a TODO comment in the code to document this in case someone wants to work on this in the future. So for now the network still doesn't consider leadership roles.

Fixes # (issue)

Type of Change

  • Content/documentation update
  • New feature
  • Bug fix
  • Breaking change

Testing

Checklist

  • Self-reviewed my changes
  • Verified links and formatting are correct
  • No new warnings or errors

Notes

@github-actions
Copy link
Contributor

✅ Spell Check Passed

No spelling issues found in this PR! 🎉

@github-actions
Copy link
Contributor

⚠️ Image files/references in png/jpg format detected

Note that we generally rely on webp format for this webpage, so please consider converting these images to WebP format and updating references accordingly.

Image files:

  • content/contributor-analysis/projects-plot-1.png
  • content/contributor-analysis/roles-plot-1.png
  • content/contributor-analysis/treemap-plot-1.png

References to image files:

  • content/contributor-analysis/index.md: projects-plot-1.png
  • content/contributor-analysis/index.md: treemap-plot-1.png
  • content/contributor-analysis/index.md: roles-plot-1.png

@rivaquiroga rivaquiroga marked this pull request as ready for review February 12, 2026 22:29
@rivaquiroga rivaquiroga requested a review from a team as a code owner February 12, 2026 22:29
@LukasWallrich
Copy link
Contributor

LukasWallrich commented Feb 12, 2026

Staging Deployment Status

This PR has been successfully deployed to staging as part of an aggregated deployment.

Deployed at: 2026-02-13 12:52:55 UTC
Staging URL: https://staging.forrt.org

The staging site shows the combined state of all compatible open PRs.

@rivaquiroga
Copy link
Contributor Author

Re WebP: Knitr's dev chunk option doesn't support that format.
Possible alternatives:

  1. adding a post-processing step: keep the current png output and convert the images to WebP after rendering with the webp R package. Or adding a step in the CI workflow and convert them using cwebp
  2. Try switching to SVG, which knitr supports natively and is often smaller than PNG for chart-style plots

@github-actions
Copy link
Contributor

✅ Spell Check Passed

No spelling issues found in this PR! 🎉

@github-actions
Copy link
Contributor

✅ Spell Check Passed

No spelling issues found in this PR! 🎉

@richarddushime
Copy link
Contributor

Great improvements — especially on the contributors analysis 👏

A few things to address:

• There are duplicate IDs, for example “Dushime Richard” and “Dushime Mudahera Richard.” These should be merged so the same contributor is not represented as two separate nodes.
same as it is done here on contributors

• Regarding colors: the blue used in the old graph is still my preferred one. It works better visually, especially since a selected node is already highlighted in red.

• In general, we usually use the red color for links

Also, if possible, it would be great to include a short explanation on how to navigate and interpret the network graph. For example:

How to read the graph

  • Nodes = contributor names. Each node connects to the other people involved in the same project(s).
  • When you search by ID, the corresponding node is highlighted in red so it’s easy to identify.
  • Edges = the connections between contributors (people who worked on the same project), shown using this color.
    • It would also be helpful if hovering over an edge and clicking on an edge used different colors.
    Right now, when I click on an edge it shows the two connected people, but the edge itself doesn’t clearly stand out. If the selected edge could be highlighted (with a stronger/different color) after a click, it would make it much easier to see which relationship is being inspected.

Adding a small legend or short guide(before the search options) like this would really help users understand what they are looking at when they first open the graph

@github-actions
Copy link
Contributor

✅ Spell Check Passed

No spelling issues found in this PR! 🎉

@LukasWallrich
Copy link
Contributor

Looks brilliant, thanks so much. Let's not worry about file format here - that is a useful rule across the website, but I would stick to the safe default for auto-generated images. Please do have a look at Richard's comments re merging IDs and explaining the chart - personally, I am ok with the new colors and we don't have a clear enough style at the moment to break any ties here - so I'd say that is your call.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the contributor analysis pages and build pipeline to support local/staging rendering without private Google Sheets credentials, refreshes visualizations (including a new treemap), and isolates the network graph styling by serving it via an iframe.

Changes:

  • Switch contributor-analysis R Markdown sources to read from contributors_cache.csv (plus public fields mapping / leads sheet).
  • Embed the network graph HTML via an iframe to prevent CSS leakage into the main Hugo page; update CI to move the rendered HTML into static/partials/.
  • Update contributor-analysis narrative and plots (treemap + lollipop chart + refreshed styling).

Reviewed changes

Copilot reviewed 6 out of 11 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
scripts/forrt_contribs/tenzing_template.md Fix contributor-analysis link to a site-relative path.
layouts/contributors_analysis/single.html Serve the network graph via an iframe and attempt auto-resizing.
content/contributor-analysis/treemap-plot-1.png Add the rendered treemap image output for the analysis page.
content/contributor-analysis/network-graph.Rmd Read contributor data from cache + refactor network build; add iframe-specific CSS.
content/contributor-analysis/index.md Update the rendered analysis page text and include the treemap image.
content/contributor-analysis/index.Rmd Refactor data ingestion to use cached contributor data; add treemap + plot restyling.
.github/workflows/data-processing.yml Update R deps and move rendered network HTML into static/partials/.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 129 to 139
@@ -134,9 +134,9 @@ jobs:
echo "🕸️ Rendering network visualization..."
Rscript -e "rmarkdown::render('content/contributor-analysis/network-graph.Rmd')"

# Move generated HTML file to layouts/partials
echo "📁 Moving network graph to partials..."
mv content/contributor-analysis/network-graph.html layouts/partials/
# Move generated HTML file to static/partials (served via iframe)
echo "📁 Moving network graph to static/partials..."
mv content/contributor-analysis/network-graph.html static/partials/
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

The contributor analysis now reads from scripts/forrt_contribs/contributors_cache.csv (generated by tenzing.py), but this workflow renders index.Rmd/network-graph.Rmd before running the Tenzing script. That means the monthly report will use a stale cache (from the repo) instead of the freshly generated data for that run. Reorder the workflow so tenzing.py runs (and updates contributors_cache.csv) before rendering the contributor-analysis Rmd files, at least for the monthly path.

Copilot uses AI. Check for mistakes.
Comment on lines +27 to +30
var iframe = document.getElementById('network-graph');
iframe.onload = function() {
iframe.style.height = iframe.contentDocument.documentElement.scrollHeight + 'px';
};
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

The iframe auto-resize only runs once on iframe.onload, but the visNetwork widget layout/stabilization can change the document height after load (and user interactions like expanding node selectors can also change it). This can result in the graph being clipped or leaving extra whitespace. Consider a more robust resizing approach (e.g., postMessage from the iframe on render/stabilized/resize, or re-measuring on a timer + on window resize) and guard against contentDocument being unavailable.

Suggested change
var iframe = document.getElementById('network-graph');
iframe.onload = function() {
iframe.style.height = iframe.contentDocument.documentElement.scrollHeight + 'px';
};
(function() {
var iframe = document.getElementById('network-graph');
if (!iframe) {
return;
}
function resizeIframe() {
if (!iframe.contentWindow) {
return;
}
var doc = iframe.contentDocument || iframe.contentWindow.document;
if (!doc || !doc.documentElement) {
return;
}
var newHeight = doc.documentElement.scrollHeight;
if (!newHeight) {
return;
}
var targetHeight = newHeight + 'px';
if (iframe.style.height !== targetHeight) {
iframe.style.height = targetHeight;
}
}
iframe.addEventListener('load', function() {
resizeIframe();
if (!iframe._autoResizeInterval) {
iframe._autoResizeInterval = setInterval(function() {
if (!document.body.contains(iframe)) {
clearInterval(iframe._autoResizeInterval);
iframe._autoResizeInterval = null;
return;
}
resizeIframe();
}, 500);
}
});
window.addEventListener('resize', resizeIframe);
})();

Copilot uses AI. Check for mistakes.
Comment on lines +193 to 200
) |>
visEdges(color = list(color = "#87CEEB", opacity = 0.3)) |>
visNodes(
font = list(size = 4, strokeWidth = 1, strokeColor = "white"),
size = 7,
borderWidth = 0,
color = list(background = "#000000", highlight = list(background = "#A52828", border = "darkred")),
scaling = list(min = 3, max = 15)
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

This still sets edge/node colors to the old palette (#87CEEB edges, #000000 nodes), but the PR description says edges were changed to a rose color and default nodes softened to gray. Either update these colors to match the intended palette, or adjust the PR description so it matches the actual behavior.

Copilot uses AI. Check for mistakes.
Comment on lines +118 to 119
unite(Contributor, Surname, `First name`, sep = " ", remove = FALSE, na.rm = TRUE) |>
mutate(Lead = if_else(Role %in% c("lead", "co-lead"), Role, "other"))
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

Lead is computed here but never used anywhere else in this document (no other references to Lead). This adds noise to the data pipeline; consider removing it or wiring it into the visualization (e.g., styling lead/co-lead nodes) if it's intended to be used.

Suggested change
unite(Contributor, Surname, `First name`, sep = " ", remove = FALSE, na.rm = TRUE) |>
mutate(Lead = if_else(Role %in% c("lead", "co-lead"), Role, "other"))
unite(Contributor, Surname, `First name`, sep = " ", remove = FALSE, na.rm = TRUE)

Copilot uses AI. Check for mistakes.
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