Conversation
✅ Spell Check PassedNo spelling issues found in this PR! 🎉 |
|
|
✅ 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 The staging site shows the combined state of all compatible open PRs. |
|
Re WebP: Knitr's dev chunk option doesn't support that format.
|
✅ Spell Check PassedNo spelling issues found in this PR! 🎉 |
✅ Spell Check PassedNo spelling issues found in this PR! 🎉 |
|
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. • 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
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 |
✅ Spell Check PassedNo spelling issues found in this PR! 🎉 |
|
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. |
There was a problem hiding this comment.
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.
| @@ -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/ | |||
There was a problem hiding this comment.
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.
| var iframe = document.getElementById('network-graph'); | ||
| iframe.onload = function() { | ||
| iframe.style.height = iframe.contentDocument.documentElement.scrollHeight + 'px'; | ||
| }; |
There was a problem hiding this comment.
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.
| 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); | |
| })(); |
| ) |> | ||
| 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) |
There was a problem hiding this comment.
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.
| unite(Contributor, Surname, `First name`, sep = " ", remove = FALSE, na.rm = TRUE) |> | ||
| mutate(Lead = if_else(Role %in% c("lead", "co-lead"), Role, "other")) |
There was a problem hiding this comment.
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.
| 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) |
Description
Fixed contributor analysis link in
tenzing_template.mdChanged 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.Switch to
contributors_cache.csvas data sourceBoth
index.Rmdandnetwork-graph.Rmdpreviously fetched contributor data directly from the Tenzing Automation Source. They now read fromcontributors_cache.csv(generated bytenzing.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.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.htmlwith auto-resize. The layout was updated to useuniversal-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 tostatic/partials/instead oflayouts/partials/.Code readability refactor
dt→credit_roles/contributions)|>instead of%>%,unite()instead ofrowwise()+paste(), etc.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.
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.
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.
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
visIgraphLayoutcentering. 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
Testing
Checklist
Notes