Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add user profile heatmap visualization for contributions #5402

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

kcne
Copy link
Contributor

@kcne kcne commented Dec 16, 2024

Description

This PR addresses #5373 by adding a heatmap visualization on user profile pages to display daily contribution activity over the past year.

Key changes include:

  • Added a heatmap container in the user profile view (users/show.html.erb).
  • Implemented JavaScript logic (heatmap.js) using CalHeatmap to render the heatmap dynamically based on contribution data.
  • Updated localization (config/locales/en.yml) to include tooltips and month/weekday labels for the heatmap.
  • Added tests in users_controller_test.rb to validate heatmap data handling.

Screenshots:
Screenshot 2024-12-16 at 16 35 58
Screenshot 2024-12-16 at 16 37 14
Screenshot 2024-12-16 at 16 36 25

How has this been tested?

  • Verified heatmap rendering with mock data for different users and activity levels.
  • Tested responsiveness and theme support (light/dark mode).
  • Checked correct localization of tooltips, month names, and weekday labels.
  • Ran automated tests to ensure proper heatmap data handling in the controller.

Let me know if you need further tweaks or enhancements!

@kcne kcne force-pushed the contribution-heatmap-nw branch 2 times, most recently from b27b7a6 to b134a0a Compare December 17, 2024 12:16
@HolgerJeromin
Copy link
Contributor

Oh, I forgot about this.
But the user can now set his "Preferred Website Color Scheme" which should be the basis of the theme not the browser setting.

@Dimitar5555
Copy link
Contributor

Dimitar5555 commented Dec 17, 2024

It is a very minor nitpick, but is it possible to dynamically determine what's the first weekday based on the user's locale and adjust the heatmap accordingly? Intl.Locale.prototype.getWeekInfo() could be used. It isn't currently available in Firefox but all other browsers have it.

P.S. Added bug 1937867 to Firefox's bug tracker.

@gravitystorm
Copy link
Collaborator

What's the source(s) of all the javascript in vendor/? I would expect to see Vendorfile updated, or preferably if these are sourced from e.g. node modules, then they should be included in package.json and added using the assets pipeline. If any of these are source files, i.e. written just for this project, then they should be in app/.

Also, how does the inclusion of popper interact with the popper already included? We end up with //= require popper twice in application.js.

@gravitystorm
Copy link
Collaborator

What's the source(s) of all the javascript in vendor/?

OK, I found the answer for the cal-heatmap part of the code, which is available as an npm module. In which case, using package.json will allow us to upgrade to new versions automatically, and would be the preferred option.

@tordans
Copy link
Contributor

tordans commented Dec 18, 2024

UX thoughts:

  • Do we want users to be able to disable this feature in their profile? – I am not a fan of this kind of configurations, but we do give a lot more visibility to once activity with this that we had before and the page is public (AKA no login required).
  • How do we want to handle the "never contributed" case? Showing the heatmap in this case would suggest "this user might have contributed changes before that time…". – I think it would be best to not show it or show a placeholder instead.

Code comments:

@tomhughes
Copy link
Member

I've tested the performance of the underlying query and using the user with the most changesets in the last year (just over 50 thousand) it took a fraction over one second which is probably acceptable.

That result (which was a full 365 days of data) serialised to just under 10Kb which is a fair chunk to be caching but hopefully most entries will be smaller than that.

@kcne
Copy link
Contributor Author

kcne commented Dec 19, 2024

Oh, I forgot about this. But the user can now set his "Preferred Website Color Scheme" which should be the basis of the theme not the browser setting.

Thank you for the suggestion. I’ll refactor accordingly to ensure alignment with the preferred color scheme setting.

It is a very minor nitpick, but is it possible to dynamically determine what's the first weekday based on the user's locale and adjust the heatmap accordingly? Intl.Locale.prototype.getWeekInfo() could be used. It isn't currently available in Firefox but all other browsers have it.

P.S. Added bug 1937867 to Firefox's bug tracker.

I tried dynamically adjusting the start and end weekdays using ghDay as the subdomain, but it rounds to the first and last weeks of the month, making implementation tricky. Accommodating this would require significant effort, which may not be worth it for such a minor adjustment.

What's the source(s) of all the javascript in vendor/? I would expect to see Vendorfile updated, or preferably if these are sourced from e.g. node modules, then they should be included in package.json and added using the assets pipeline. If any of these are source files, i.e. written just for this project, then they should be in app/.

To be honest I wasn’t too familiar with how our assets pipeline works,so I just added the cal-heatmap library and its dependencies in vendor/ and added required code in manifest.js and application.js to make it load correctly. If using package.json is preferred, I can update the PR accordingly. I'm not sure if there is some additional config needed for this to be accomplished or would updating the package.json file would be enough.

Thank you for pointing out the existing popper inclusion. I’ll remove the duplicate entry from application.js and the vendor folder.

@nertc nertc mentioned this pull request Dec 23, 2024
@kcne kcne force-pushed the contribution-heatmap-nw branch from b134a0a to 0a8fc14 Compare December 24, 2024 13:39
@kcne kcne force-pushed the contribution-heatmap-nw branch from 0a8fc14 to af02b6a Compare December 24, 2024 13:43
@kcne
Copy link
Contributor Author

kcne commented Dec 26, 2024

I've updated the code to account for the "Preferred Website Color Scheme." Theme settings should now be working correctly.

UX Thoughts:

  • Disabling Feature in Profile: Data is already public and open, so I believe all mappers should have a contribution graph. This feature provides valuable insights for more experienced mappers as a reference point to understand others' activity.
  • "Never Contributed" Case: Showing an empty heatmap with a fallback message seems like a good approach. From a UX perspective, maintaining a consistent layout across profiles would be more intuitive and visually cohesive.

Code Comments:

  • Localizing Starting Week: I attempted to localize the starting week as suggested but couldn't find a clean solution due to limitations with the ghDays subdomain. If anyone has suggestions, I'm open to exploring further.
  • Separate JS Files: There's already a heatmap.js file containing heatmap-related functionality, included in application.js for precompilation. I'm hesitant to introduce additional files unless there's a clear benefit. Consolidating heatmap logic here seems to make sense for now.
  • Updating package.json: I’ll update the package.json as part of the changes, but I’m unsure if additional configuration is needed. Please let me know if there are any dependencies or settings to consider. @gravitystorm

Also a big thank you to @tomhughes for testing the performance here.
Let me know if further adjustments or discussions are needed!

@AntonKhorev
Copy link
Collaborator

Separate JS Files: There's already a heatmap.js file containing heatmap-related functionality, included in application.js for precompilation.

How is it included in application.js if you're including heatmap.js here? But d3 and cal-heatmap are added to application.js, bringing its size up to ~400kb from ~250kb.

@AntonKhorev
Copy link
Collaborator

CSP violations, days of week won't be visible if not resolved:

Content-Security-Policy: (Report-Only policy) The page’s settings would block an inline style (style-src-attr) from being applied

image

@AntonKhorev
Copy link
Collaborator

I've updated the code to account for the "Preferred Website Color Scheme." Theme settings should now be working correctly.

It's not going to work correctly because our Auto option follows prefers-color-scheme which can change any time. If it does, you'll get for example this:

image

Looks like cal-heatmap doesn't have a proper auto scheme "as not all websites support dark/light mode".

You'd have to then setup a listener like this but without using Leaflet of course and redraw the heatmap.

Same is true for #5426 by the way.

@hlfan
Copy link
Contributor

hlfan commented Dec 30, 2024

You'd have to then setup a listener like this but without using Leaflet of course and redraw the heatmap.

Same is true for #5426 by the way.

Any other change to the theme of the page without reloading will break most of the CSS theming anyway since the stylesheets were split in #5362 by the way.

It would be great to have a global leaflet-independent watcher where clients can add themselves to a callback list.

@AntonKhorev
Copy link
Collaborator

AntonKhorev commented Dec 30, 2024

Any other change to the theme of the page without reloading will break most of the CSS theming anyway since the stylesheets were split in #5362 by the way.

You don't need to change the theme of the page, neither here, nor in #5426.

Or do you say that you haven't tried switching prefers-color-scheme while in Auto scheme? Then try it with browser dev tools for example.

It would be great to have a global leaflet-independent watcher where clients can add themselves to a callback list.

Leaflet code is just a wrapper for addEventListener. You can do the same with jQuery.

@hlfan
Copy link
Contributor

hlfan commented Dec 30, 2024

You don't need to change the theme of the page

I did that for testing, but since listening increased the complexity unnecessarily, I left that for a second pass.

But suppose the site needs a theme watcher anyway because the cal-heatmap doesn't want to let CSS do the color mixing theme-agnostically. In that case, instead of having two listeners, a common solution that includes MutationObservers outside of jQuery would be the one with the least overhead.

@AntonKhorev
Copy link
Collaborator

Why MutationObservers?

@AntonKhorev
Copy link
Collaborator

AntonKhorev commented Dec 30, 2024

Also the conditions under which watching prefers-color-scheme are different for this PR and #5426. Here you need to watch if the website theme is auto, in #5426 you need to watch when the website and the map themes are both auto. So maybe you don't want one global watcher.

@hlfan
Copy link
Contributor

hlfan commented Dec 30, 2024

The MutationObserver thought came from my tinkering with the site locally wanting to reduce the reloads, forgetting that a toggle if added would already have onchange events.

So maybe you don't want one global watcher.

Yeah, I kinda missed that... Still, having a similar style on such similar functions and having them moved to some unified location would be a nice thing to have, currently, they could be much more different. But that's more of a refactor thing if both are merged.

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.

8 participants