-
Notifications
You must be signed in to change notification settings - Fork 927
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
base: master
Are you sure you want to change the base?
Changes from all commits
ada1658
467ef94
f46796f
9d87115
197af84
904951e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
//= require d3 | ||
//= require cal-heatmap | ||
//= require calendar-label | ||
//= require popper | ||
//= require tooltip | ||
|
||
|
||
/* global CalHeatmap, CalendarLabel, Tooltip */ | ||
document.addEventListener("DOMContentLoaded", () => { | ||
const heatmapElement = document.querySelector("#cal-heatmap"); | ||
|
||
if (!heatmapElement) { | ||
console.warn("Heatmap element not found in the DOM."); | ||
return; | ||
} | ||
|
||
const heatmapData = heatmapElement.dataset.heatmap ? JSON.parse(heatmapElement.dataset.heatmap) : []; | ||
const colorScheme = heatmapElement.dataset.siteColorScheme || "auto"; | ||
const locale = $("head").data().locale; | ||
const weekdays = getLocalizedWeekdays(locale); | ||
const rangeColors = ["#14432a", "#166b34", "#37a446", "#4dd05a"]; | ||
const startDate = new Date(Date.now() - (365 * 24 * 60 * 60 * 1000)); | ||
|
||
const theme = getThemeFromColorScheme(colorScheme); | ||
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); | ||
|
||
let cal = new CalHeatmap(); | ||
renderHeatmap(theme); | ||
|
||
if (colorScheme === "auto") { | ||
mediaQuery.addEventListener("change", (e) => { | ||
const newTheme = e.matches ? "dark" : "light"; | ||
renderHeatmap(newTheme); | ||
}); | ||
} | ||
|
||
function renderHeatmap(currentTheme) { | ||
cal.destroy(); | ||
cal = new CalHeatmap(); | ||
cal.paint({ | ||
itemSelector: "#cal-heatmap", | ||
theme: currentTheme, | ||
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: currentTheme === "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) | ||
}] | ||
]); | ||
} | ||
}); | ||
kcne marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
function getThemeFromColorScheme(colorScheme) { | ||
if (colorScheme === "auto") { | ||
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"; | ||
} | ||
return colorScheme; | ||
} | ||
|
||
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 dateTranslations = translations && translations.date; | ||
const monthNames = dateTranslations && dateTranslations.month_names; | ||
|
||
const months = monthNames || []; | ||
const monthName = months[jsDate.getMonth() + 1] || `${jsDate.getMonth + 1}.`; | ||
const day = jsDate.getDate(); | ||
const year = jsDate.getFullYear(); | ||
|
||
const localizedDate = `${day}. ${monthName} ${year}.`; | ||
return value > 0 ? | ||
I18n.t("javascripts.heatmap.tooltip.contributions", { count: value, date: localizedDate }) : | ||
I18n.t("javascripts.heatmap.tooltip.no_contributions", { date: localizedDate }); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
/* | ||
*= require cal-heatmap | ||
*/ |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hlfan Sorry about confusion here.
In the process of rebasing the commit for latest changes I forgot to pop stashed changes so the file version didn't reflect last changes. Thanks for catching that and pointing it out.
This is the updated version. Manually tested this locally in firefox browser and is working as expected. Please let me know if there is something else I should modify here.
Thank you.