diff --git a/ts/graphs/CalendarGraph.svelte b/ts/graphs/CalendarGraph.svelte index 059668333..c11606c09 100644 --- a/ts/graphs/CalendarGraph.svelte +++ b/ts/graphs/CalendarGraph.svelte @@ -74,6 +74,7 @@ + diff --git a/ts/graphs/calendar.ts b/ts/graphs/calendar.ts index a5b1deb23..49069b320 100644 --- a/ts/graphs/calendar.ts +++ b/ts/graphs/calendar.ts @@ -28,6 +28,7 @@ export interface GraphData { // indexed by day, where day is relative to today reviewCount: Map; timeFunction: CountableTimeInterval; + weekdayLabels: number[]; } interface DayDatum { @@ -63,7 +64,12 @@ export function gatherData(data: pb.BackendProto.GraphsOut): GraphData { ? timeSaturday : timeSunday; - return { reviewCount, timeFunction }; + const weekdayLabels: number[] = []; + for (let i = 0; i < 7; i++) { + weekdayLabels.push((data.firstWeekday + i) % 7); + } + + return { reviewCount, timeFunction, weekdayLabels }; } export function renderCalendar( @@ -82,7 +88,8 @@ export function renderCalendar( const x = scaleLinear() .range([bounds.marginLeft, bounds.width - bounds.marginRight]) - .domain([0, 53]); + .domain([-1, 53]); + // map of 0-365 -> day const dayMap: Map = new Map(); let maxCount = 0; @@ -153,20 +160,31 @@ export function renderCalendar( } const height = bounds.height / 10; - let emptyColour = "#ddd"; - if (nightMode) { - emptyColour = "#333"; - } - svg.select(`g.days`) + const emptyColour = nightMode ? "#333" : "#ddd"; + + svg.select("g.weekdays") + .selectAll("text") + .data(sourceData.weekdayLabels) + .join("text") + .text((d: number) => i18n.weekdayLabel(d)) + .attr("width", x(-1)! - 2) + .attr("height", height - 2) + .attr("x", x(1)! - 3) + .attr("y", (_d, index) => bounds.marginTop + index * height) + .attr("dominant-baseline", "hanging") + .attr("text-anchor", "end") + .attr("font-size", "small") + .attr("font-family", "monospace") + .style("user-select", "none"); + + svg.select("g.days") .selectAll("rect") .data(data) .join("rect") .attr("fill", emptyColour) - .attr("width", (d) => { - return x(d.weekNumber + 1)! - x(d.weekNumber)! - 2; - }) + .attr("width", (d) => x(d.weekNumber + 1)! - x(d.weekNumber)! - 2) .attr("height", height - 2) - .attr("x", (d) => x(d.weekNumber)!) + .attr("x", (d) => x(d.weekNumber + 1)!) .attr("y", (d) => bounds.marginTop + d.weekDay * height) .on("mousemove", function (this: any, d: any) { const [x, y] = mouse(document.body); diff --git a/ts/lib/i18n.ts b/ts/lib/i18n.ts index 443c9c687..7210196ed 100644 --- a/ts/lib/i18n.ts +++ b/ts/lib/i18n.ts @@ -59,6 +59,13 @@ export class I18n { } } + weekdayLabel(n: number): string { + const firstLang = this.bundles[0].locales[0]; + return new Date(86_400_000 * (3 + n)).toLocaleDateString(firstLang, { + weekday: "narrow", + }); + } + private keyName(msg: pb.FluentProto.FluentString): string { return this.TR[msg].toLowerCase().replace(/_/g, "-"); }