From 788bcf41b33e3966aa3843914a94c911aa2b9af2 Mon Sep 17 00:00:00 2001 From: Anton Khorev Date: Sun, 16 Mar 2025 01:34:36 +0300 Subject: [PATCH] Add links to days in user history from heatmap --- app/assets/javascripts/heatmap.js | 11 +++++++++++ app/controllers/users_controller.rb | 7 ++++--- app/views/users/show.html.erb | 2 +- test/controllers/users_controller_test.rb | 11 ++++++----- 4 files changed, 22 insertions(+), 9 deletions(-) diff --git a/app/assets/javascripts/heatmap.js b/app/assets/javascripts/heatmap.js index 058f71cfe..b96a47a22 100644 --- a/app/assets/javascripts/heatmap.js +++ b/app/assets/javascripts/heatmap.js @@ -12,6 +12,7 @@ document.addEventListener("DOMContentLoaded", () => { } const heatmapData = heatmapElement.dataset.heatmap ? JSON.parse(heatmapElement.dataset.heatmap) : []; + const displayName = heatmapElement.dataset.displayName; const colorScheme = document.documentElement.getAttribute("data-bs-theme") ?? "auto"; const rangeColors = ["#14432a", "#166b34", "#37a446", "#4dd05a"]; const startDate = new Date(Date.now() - (365 * 24 * 60 * 60 * 1000)); @@ -68,6 +69,16 @@ document.addEventListener("DOMContentLoaded", () => { text: (date, value) => getTooltipText(date, value) }] ]); + + cal.on("click", (_event, timestamp) => { + if (!displayName) return; + for (const { date, max_id } of heatmapData) { + if (!max_id) continue; + if (timestamp !== Date.parse(date)) continue; + const params = new URLSearchParams([["before", max_id + 1]]); + location = `/user/${encodeURIComponent(displayName)}/history?${params}`; + } + }); } function getTooltipText(date, value) { diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index c6e2298ab..2ea2ea36f 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -24,7 +24,7 @@ class UsersController < ApplicationController if @user && (@user.visible? || current_user&.administrator?) @title = @user.display_name - @heatmap_data = Rails.cache.fetch("heatmap_data_user_#{@user.id}", :expires_in => 1.day) do + @heatmap_data = Rails.cache.fetch("heatmap_data_with_ids_user_#{@user.id}", :expires_in => 1.day) do one_year_ago = 1.year.ago.beginning_of_day today = Time.zone.now.end_of_day @@ -33,12 +33,13 @@ class UsersController < ApplicationController .where(:created_at => one_year_ago..today) .where(:num_changes => 1..) .group("date_trunc('day', created_at)") - .select("date_trunc('day', created_at) AS date, SUM(num_changes) AS total_changes") + .select("date_trunc('day', created_at) AS date, SUM(num_changes) AS total_changes, MAX(id) AS max_id") .order("date") .map do |changeset| { :date => changeset.date.to_date.to_s, - :total_changes => changeset.total_changes.to_i + :total_changes => changeset.total_changes.to_i, + :max_id => changeset.max_id } end end diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb index e9f364523..5ee0c1900 100644 --- a/app/views/users/show.html.erb +++ b/app/views/users/show.html.erb @@ -253,7 +253,7 @@
+ data-heatmap="<%= @heatmap_data.to_json %>" data-display-name="<%= @user.display_name %>">
diff --git a/test/controllers/users_controller_test.rb b/test/controllers/users_controller_test.rb index a4326cf5c..5066faec3 100644 --- a/test/controllers/users_controller_test.rb +++ b/test/controllers/users_controller_test.rb @@ -364,7 +364,7 @@ class UsersControllerTest < ActionDispatch::IntegrationTest assert_equal 1, first_response_data.size, "Expected one entry in the heatmap data" # Inspect cache after the first request - cached_data = Rails.cache.read("heatmap_data_user_#{user.id}") + cached_data = Rails.cache.read("heatmap_data_with_ids_user_#{user.id}") assert_equal first_response_data, cached_data, "Expected the cache to contain the first response data" # Add a new changeset to the database @@ -408,16 +408,17 @@ class UsersControllerTest < ActionDispatch::IntegrationTest # Test user with changesets user_with_changesets = create(:user) - create(:changeset, :user => user_with_changesets, :created_at => 3.months.ago.beginning_of_day, :num_changes => 42) - create(:changeset, :user => user_with_changesets, :created_at => 4.months.ago.beginning_of_day, :num_changes => 39) + changeset39 = create(:changeset, :user => user_with_changesets, :created_at => 4.months.ago.beginning_of_day, :num_changes => 39) + _changeset5 = create(:changeset, :user => user_with_changesets, :created_at => 3.months.ago.beginning_of_day, :num_changes => 5) + changeset11 = create(:changeset, :user => user_with_changesets, :created_at => 3.months.ago.beginning_of_day, :num_changes => 11) get user_path(user_with_changesets) assert_response :success assert_select "div#cal-heatmap[data-heatmap]" do |elements| # Check the data-heatmap attribute is present and contains expected JSON heatmap_data = JSON.parse(elements.first["data-heatmap"]) expected_data = [ - { "date" => 4.months.ago.to_date.to_s, "total_changes" => 39 }, - { "date" => 3.months.ago.to_date.to_s, "total_changes" => 42 } + { "date" => 4.months.ago.to_date.to_s, "total_changes" => 39, "max_id" => changeset39.id }, + { "date" => 3.months.ago.to_date.to_s, "total_changes" => 16, "max_id" => changeset11.id } ] assert_equal expected_data, heatmap_data end -- 2.39.5