fix(client): localise calendar to user's current timezone (#38217)
* fix: localise Heatmap to user's timezone Rather than using ISO formatted date strings, this uses Date objects for simplicity and to ensure that the heatmap is correct for the timezone it is viewed in. It should also match the timeline which is also localised to the viewing computer's timezone. * test: update snapshotpull/38220/head
parent
cc79999a31
commit
3fff454872
|
@ -5,7 +5,7 @@ import ReactTooltip from 'react-tooltip';
|
||||||
import addDays from 'date-fns/add_days';
|
import addDays from 'date-fns/add_days';
|
||||||
import addMonths from 'date-fns/add_months';
|
import addMonths from 'date-fns/add_months';
|
||||||
import startOfDay from 'date-fns/start_of_day';
|
import startOfDay from 'date-fns/start_of_day';
|
||||||
import format from 'date-fns/format';
|
import isEqual from 'date-fns/is_equal';
|
||||||
|
|
||||||
import FullWidthRow from '../../helpers/FullWidthRow';
|
import FullWidthRow from '../../helpers/FullWidthRow';
|
||||||
import Spacer from '../../helpers/Spacer';
|
import Spacer from '../../helpers/Spacer';
|
||||||
|
@ -22,33 +22,17 @@ const propTypes = {
|
||||||
};
|
};
|
||||||
|
|
||||||
function HeatMap({ calendar, streak }) {
|
function HeatMap({ calendar, streak }) {
|
||||||
// an issue with react-calendar-heatmap makes the days off by one
|
const endOfCalendar = startOfDay(Date.now());
|
||||||
// see this https://github.com/kevinsqi/react-calendar-heatmap/issues/112
|
const startOfCalendar = addMonths(endOfCalendar, -6);
|
||||||
// I have added one day in the marked places to account for the offset
|
|
||||||
|
|
||||||
// this logic adds a day to all the timestamps (remove if issue gets fixed)
|
|
||||||
let tempCalendar = {};
|
|
||||||
const secondsInADay = 60 * 60 * 24;
|
|
||||||
for (let timestamp of Object.keys(calendar)) {
|
|
||||||
tempCalendar[parseInt(timestamp, 10) + secondsInADay] = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
calendar = tempCalendar;
|
|
||||||
|
|
||||||
// the addDays of 1 to startOfToday (remove if issue gets fixed)
|
|
||||||
const startOfToday = addDays(startOfDay(Date.now()), 1);
|
|
||||||
const sixMonthsAgo = addMonths(startOfToday, -6);
|
|
||||||
const startOfCalendar = format(addDays(sixMonthsAgo, -1), 'YYYY-MM-DD');
|
|
||||||
const endOfCalendar = format(startOfToday, 'YYYY-MM-DD');
|
|
||||||
|
|
||||||
let calendarData = [];
|
let calendarData = [];
|
||||||
let dayCounter = sixMonthsAgo;
|
let dayCounter = startOfCalendar;
|
||||||
|
|
||||||
// create a data point for each day of the calendar period (six months)
|
// create a data point for each day of the calendar period (six months)
|
||||||
while (dayCounter <= startOfToday) {
|
while (dayCounter <= endOfCalendar) {
|
||||||
// this is the format needed for react-calendar-heatmap
|
// this is the format needed for react-calendar-heatmap
|
||||||
const newDay = {
|
const newDay = {
|
||||||
date: format(dayCounter, 'YYYY-MM-DD'),
|
date: startOfDay(dayCounter),
|
||||||
count: 0
|
count: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -56,13 +40,11 @@ function HeatMap({ calendar, streak }) {
|
||||||
dayCounter = addDays(dayCounter, 1);
|
dayCounter = addDays(dayCounter, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// this adds one to the count of the day for each timestamp
|
|
||||||
for (let timestamp of Object.keys(calendar)) {
|
for (let timestamp of Object.keys(calendar)) {
|
||||||
timestamp = Number(timestamp * 1000) || null;
|
timestamp = Number(timestamp * 1000) || null;
|
||||||
if (timestamp) {
|
if (timestamp) {
|
||||||
const startOfTimestampDay = format(startOfDay(timestamp), 'YYYY-MM-DD');
|
const index = calendarData.findIndex(day =>
|
||||||
const index = calendarData.findIndex(
|
isEqual(day.date, startOfDay(timestamp))
|
||||||
day => day.date === startOfTimestampDay
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
|
@ -93,14 +75,16 @@ function HeatMap({ calendar, streak }) {
|
||||||
} else {
|
} else {
|
||||||
valueCount = 'No points';
|
valueCount = 'No points';
|
||||||
}
|
}
|
||||||
return {
|
const dateFormatted = value.date
|
||||||
'data-tip': `<b>${valueCount}</b> on ${new Date(
|
? 'on ' +
|
||||||
value.date
|
value.date.toLocaleDateString('en-US', {
|
||||||
).toLocaleDateString('en-US', {
|
|
||||||
year: 'numeric',
|
year: 'numeric',
|
||||||
month: 'short',
|
month: 'short',
|
||||||
day: 'numeric'
|
day: 'numeric'
|
||||||
})}`
|
})
|
||||||
|
: '';
|
||||||
|
return {
|
||||||
|
'data-tip': `<b>${valueCount}</b> ${dateFormatted}`
|
||||||
};
|
};
|
||||||
}}
|
}}
|
||||||
values={calendarData}
|
values={calendarData}
|
||||||
|
|
|
@ -2168,9 +2168,9 @@ exports[`<HeatMap/> renders correctly 1`] = `
|
||||||
<title />
|
<title />
|
||||||
</rect>
|
</rect>
|
||||||
<rect
|
<rect
|
||||||
class="color-empty"
|
class="color-scale-1"
|
||||||
currentItem="false"
|
currentItem="false"
|
||||||
data-tip="<b>No points</b> on Jan 30, 2020"
|
data-tip="<b>2 points</b> on Jan 30, 2020"
|
||||||
height="10"
|
height="10"
|
||||||
width="10"
|
width="10"
|
||||||
x="0"
|
x="0"
|
||||||
|
@ -2179,9 +2179,9 @@ exports[`<HeatMap/> renders correctly 1`] = `
|
||||||
<title />
|
<title />
|
||||||
</rect>
|
</rect>
|
||||||
<rect
|
<rect
|
||||||
class="color-scale-1"
|
class="color-empty"
|
||||||
currentItem="false"
|
currentItem="false"
|
||||||
data-tip="<b>2 points</b> on Jan 31, 2020"
|
data-tip="<b>No points</b> on Jan 31, 2020"
|
||||||
height="10"
|
height="10"
|
||||||
width="10"
|
width="10"
|
||||||
x="0"
|
x="0"
|
||||||
|
@ -2227,17 +2227,6 @@ exports[`<HeatMap/> renders correctly 1`] = `
|
||||||
>
|
>
|
||||||
<title />
|
<title />
|
||||||
</rect>
|
</rect>
|
||||||
<rect
|
|
||||||
class="color-empty"
|
|
||||||
currentItem="false"
|
|
||||||
data-tip="<b>No points</b> on Feb 4, 2020"
|
|
||||||
height="10"
|
|
||||||
width="10"
|
|
||||||
x="0"
|
|
||||||
y="22"
|
|
||||||
>
|
|
||||||
<title />
|
|
||||||
</rect>
|
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
<g
|
<g
|
||||||
|
|
Loading…
Reference in New Issue