Skip to content

Commit

Permalink
Add heatmap javascript logic, styles and localization
Browse files Browse the repository at this point in the history
  • Loading branch information
kcne committed Dec 17, 2024
1 parent 9d87115 commit a0abf9e
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 0 deletions.
135 changes: 135 additions & 0 deletions app/assets/javascripts/heatmap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/* global CalHeatmap, CalendarLabel, Tooltip */
document.addEventListener("DOMContentLoaded", () => {
const heatmapElement = document.querySelector("#cal-heatmap");

// Don't render heatmap if there is no heatmap element in the DOM
if (!heatmapElement) {
console.warn("Heatmap element not found in the DOM.");
return;
}

const { heatmapData, locale, weekdays, rangeColors, startDate } = initializeHeatmapConfig(heatmapElement);

let cal = new CalHeatmap();

// Initialize/repaint the heatmap
function renderHeatmap(theme) {
cal.destroy(); // Ensure no duplication when repainting
cal = new CalHeatmap();
cal.paint({
itemSelector: "#cal-heatmap",
theme: theme,
domain: {
type: "month",
gutter: 4,
label: {
text: (timestamp) => getMonthNameFromTranslations(locale, new Date(timestamp).getMonth()),
position: "top",
textAlign: "middle"
},
dynamicDimension: true
},
subDomain: {
type: "ghDay",
radius: 2,
width: 11,
height: 11,
gutter: 4
},
date: {
start: startDate
},
range: 13,
data: {
source: heatmapData,
type: "json",
x: "date",
y: "total_changes"
},
scale: {
color: {
type: "threshold",
range: theme === "dark" ? rangeColors : rangeColors.reverse(),
domain: [10, 20, 30, 40]
}
}
}, [
[CalendarLabel, {
position: "left",
key: "left",
text: () => weekdays,
textAlign: "end",
width: 30,
padding: [23, 10, 0, 0]
}],
[Tooltip, {
text: (date, value) => getTooltipText(date, value, locale)
}]
]);
}

// Initialize the heatmap with the current theme
let currentTheme = getTheme();
renderHeatmap(currentTheme);

// Listen for theme changes
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
mediaQuery.addEventListener("change", (e) => {
const newTheme = e.matches ? "dark" : "light";
if (newTheme !== currentTheme) {
currentTheme = newTheme;
renderHeatmap(currentTheme);
}
});
}, { once: true });

function initializeHeatmapConfig(heatmapElement) {
const heatmapData = heatmapElement.dataset.heatmap ? JSON.parse(heatmapElement.dataset.heatmap) : [];
const applicationData = $("head").data();
const locale = applicationData.locale;
const weekdays = getLocalizedWeekdays(locale);
const rangeColors = ["#14432a", "#166b34", "#37a446", "#4dd05a"];
const startDate = new Date(Date.now() - (365 * 24 * 60 * 60 * 1000));

return { heatmapData, locale, weekdays, rangeColors, startDate };
}

function getTheme() {
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
}

function getLocalizedWeekdays(locale) {
const translations = I18n.translations[locale] || I18n.translations.en;
const date = translations && translations.date;
const abbrDayNames = date && date.abbr_day_names;

return (abbrDayNames || []).map((day, index) =>
index % 2 === 0 ? day : ""
);
}

function getMonthNameFromTranslations(locale, monthIndex) {
const translations = I18n.translations[locale] || I18n.translations.en;
const date = translations && translations.date;
const abbrMonthNames = date && date.abbr_month_names;

const months = abbrMonthNames || [];
return months[monthIndex + 1] || "";
}

function getTooltipText(date, value, locale) {
const jsDate = new Date(date);
const translations = I18n.translations[locale] || I18n.translations.en;
const dateObj = translations && translations.date;
const monthNames = dateObj && dateObj.month_names;

const months = monthNames || [];
const monthName = months[jsDate.getMonth() + 1] || "";
const day = jsDate.getDate();
const year = jsDate.getFullYear();

const localizedDate = `${monthName} ${day}. ${year}.`;
return value > 0 ?
I18n.t("javascripts.heatmap.tooltip.contributions", { count: value, date: localizedDate }) :
I18n.t("javascripts.heatmap.tooltip.no_contributions", { date: localizedDate });
}
3 changes: 3 additions & 0 deletions app/assets/stylesheets/heatmap.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/*
*= require cal-heatmap
*/
4 changes: 4 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3215,6 +3215,10 @@ en:
show_address: Show address
query_features: Query features
centre_map: Centre map here
heatmap:
tooltip:
contributions: "%{count} contributions on %{date}"
no_contributions: "No contributions on %{date}"
redactions:
edit:
heading: "Edit Redaction"
Expand Down

0 comments on commit a0abf9e

Please sign in to comment.