Skip to content

Commit 9c2e001

Browse files
authored
Merge pull request #631 from mapswipe/fix/community-dashboard-timezone-issue
Fix community dashboard timezone issue
2 parents 06ec554 + ce3407a commit 9c2e001

File tree

5 files changed

+61
-28
lines changed

5 files changed

+61
-28
lines changed

community-dashboard/app/Base/utils/temporal.ts

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
11
import { isDefined } from '@togglecorp/fujs';
22

3+
export function getDateSafe(value: Date | number | string) {
4+
if (typeof value === 'string') {
5+
return new Date(`${value}T00:00`);
6+
}
7+
8+
return new Date(value);
9+
}
10+
311
export function resolveTime(date: Date | number | string, resolution: 'day' | 'month' | 'year'): Date {
4-
const newDate = new Date(date);
12+
const newDate = getDateSafe(date);
13+
514
if (resolution === 'day' || resolution === 'month' || resolution === 'year') {
615
newDate.setUTCHours(0, 0, 0, 0);
716
}
@@ -22,42 +31,51 @@ export function getTimestamps(
2231
const sanitizedStartDate = resolveTime(startDate, resolution);
2332
const sanitizedEndDate = resolveTime(endDate, resolution);
2433

25-
const returns: number[] = [
34+
const timestamps: number[] = [
2635
sanitizedStartDate.getTime(),
2736
];
2837

29-
while (sanitizedStartDate < sanitizedEndDate) {
38+
let increment = 1;
39+
while (true) {
40+
const myDate = new Date(sanitizedStartDate);
3041
if (resolution === 'year') {
31-
sanitizedStartDate.setFullYear(sanitizedStartDate.getFullYear() + 1);
42+
myDate.setFullYear(sanitizedStartDate.getFullYear() + increment);
3243
} else if (resolution === 'month') {
33-
sanitizedStartDate.setMonth(sanitizedStartDate.getMonth() + 1);
44+
myDate.setMonth(sanitizedStartDate.getMonth() + increment);
3445
} else {
35-
sanitizedStartDate.setDate(sanitizedStartDate.getDate() + 1);
46+
myDate.setDate(sanitizedStartDate.getDate() + increment);
47+
}
48+
myDate.setUTCHours(0, 0, 0, 0);
49+
50+
if (myDate > sanitizedEndDate) {
51+
break;
3652
}
37-
returns.push(sanitizedStartDate.getTime());
53+
54+
timestamps.push(myDate.getTime());
55+
increment += 1;
3856
}
3957

40-
return returns;
58+
return timestamps;
4159
}
4260

4361
export function formatDate(value: number | string) {
44-
const date = new Date(value);
62+
const date = getDateSafe(value);
4563
return new Intl.DateTimeFormat(
4664
navigator.language,
4765
{ year: 'numeric', month: 'short', day: 'numeric' },
4866
).format(date);
4967
}
5068

5169
export function formatMonth(value: number | string) {
52-
const date = new Date(value);
70+
const date = getDateSafe(value);
5371
return new Intl.DateTimeFormat(
5472
navigator.language,
5573
{ year: 'numeric', month: 'short' },
5674
).format(date);
5775
}
5876

5977
export function formatYear(value: number | string) {
60-
const date = new Date(value);
78+
const date = getDateSafe(value);
6179
return new Intl.DateTimeFormat(
6280
navigator.language,
6381
{ year: 'numeric' },

community-dashboard/app/components/Calendar/index.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import {
1111
IoCalendarOutline,
1212
} from 'react-icons/io5';
1313

14+
import { getDateSafe } from '#utils/temporal';
15+
1416
import Button from '../Button';
1517
import NumberInput from '../NumberInput';
1618
import SelectInput from '../SelectInput';
@@ -124,7 +126,7 @@ function Calendar<P extends CalendarDateProps>(props: Props<P>) {
124126
} = props;
125127

126128
const today = new Date();
127-
const current = initialDate ? new Date(initialDate) : today;
129+
const current = initialDate ? getDateSafe(initialDate) : today;
128130
const currentYear = current.getFullYear();
129131
const currentMonth = current.getMonth();
130132

@@ -193,8 +195,8 @@ function Calendar<P extends CalendarDateProps>(props: Props<P>) {
193195
styles.monthSelectionPopup,
194196
)}
195197
optionsPopupContentClassName={styles.popupContent}
196-
optionRenderer={undefined}
197-
optionRendererParams={undefined}
198+
// optionRenderer={undefined}
199+
// optionRendererParams={undefined}
198200
/>
199201
</div>
200202
</div>

community-dashboard/app/components/CalendarHeatMapContainer/index.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import { scaleQuantile } from 'd3-scale';
55
import ReactTooltip from 'react-tooltip';
66
import InformationCard from '#components/InformationCard';
77

8+
import { getDateSafe } from '#utils/temporal';
9+
810
import styles from './styles.css';
911

1012
const githubColors = [' #eeeeee', '#d6e685', '#8cc665', '#44a340', '#1e6823'];
@@ -24,15 +26,16 @@ function getDateRange(data: Data[] | null | undefined) {
2426
const startDate = sortedData[0].date;
2527
const endDate = sortedData[sortedData.length - 1].date;
2628

27-
if (getDifferenceInDays(new Date(endDate).getTime(), new Date(startDate).getTime()) <= 365) {
28-
const currentYear = new Date(startDate).getFullYear();
29+
if (getDifferenceInDays(getDateSafe(endDate).getTime(),
30+
getDateSafe(startDate).getTime()) <= 365) {
31+
const currentYear = getDateSafe(startDate).getFullYear();
2932
return {
3033
startDate: encodeDate(new Date(currentYear, 0, 1)),
3134
endDate: encodeDate(new Date(currentYear, 11, 31)),
3235
};
3336
}
34-
const startDateTime = new Date(startDate);
35-
const endDateTime = new Date(endDate);
37+
const startDateTime = getDateSafe(startDate);
38+
const endDateTime = getDateSafe(endDate);
3639

3740
return {
3841
startDate: encodeDate(new Date(startDateTime.getFullYear(), startDateTime.getMonth(), 1)),

community-dashboard/app/components/Page/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ function Page(props: Props) {
195195
value={props.totalUserGroups}
196196
label="Total Groups"
197197
// eslint-disable-next-line react/destructuring-assignment
198-
secondaryValue={props.totalContributorsLastMonth}
198+
secondaryValue={props.totalUserGroupsLastMonth}
199199
secondaryValueDescription="active groups in the last 30 days"
200200
/>
201201
</>

community-dashboard/app/views/StatsBoard/index.tsx

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ import {
5858
formatYear,
5959
resolveTime,
6060
getTimestamps,
61+
getDateSafe,
6162
} from '#utils/temporal';
6263
import styles from './styles.css';
6364

@@ -120,6 +121,10 @@ const organizationTotalSwipeFormatter = (value: number, name: string) => (
120121
[value.toLocaleString(), organizationNameFormatter(name)]
121122
);
122123

124+
const missionTypeTotalSwipeFormatter = (value: number, name: string) => (
125+
[value.toLocaleString(), name]
126+
);
127+
123128
// Timeseries by week day
124129

125130
interface Day {
@@ -208,14 +213,15 @@ function StatsBoard(props: Props) {
208213
React.useEffect(
209214
() => {
210215
const timestamps = contributionTimeStats?.map(
211-
(item) => new Date(item.date).getTime(),
216+
(item) => getDateSafe(item.date).getTime(),
212217
) ?? [];
218+
213219
if (timestamps.length <= 0) {
214220
timestamps.push(new Date().getTime());
215221
}
216222

217-
const minDate = new Date(Math.min(...timestamps));
218-
const maxDate = new Date(Math.max(...timestamps));
223+
const minDate = getDateSafe(Math.min(...timestamps));
224+
const maxDate = getDateSafe(Math.max(...timestamps));
219225

220226
const minDateYear = minDate.getFullYear();
221227
const maxDateYear = maxDate.getFullYear();
@@ -295,11 +301,13 @@ function StatsBoard(props: Props) {
295301
(item) => item.total,
296302
);
297303

298-
return getTimestamps(
304+
const timestamps = getTimestamps(
299305
contributionTimeSeries[0].date,
300306
contributionTimeSeries[contributionTimeSeries.length - 1].date,
301307
resolution,
302-
).map((item) => ({
308+
);
309+
310+
return timestamps.map((item) => ({
303311
total: mapping[item] ?? 0,
304312
date: item,
305313
}));
@@ -325,7 +333,7 @@ function StatsBoard(props: Props) {
325333
const totalContributionByDay = useMemo(() => {
326334
const dayWiseContribution = listToGroupList(
327335
contributionTimeStats,
328-
(d) => new Date(d.date).getDay(),
336+
(d) => getDateSafe(d.date).getDay(),
329337
(d) => d.totalSwipeTime,
330338
);
331339

@@ -364,7 +372,7 @@ function StatsBoard(props: Props) {
364372
...item,
365373
projectType: item.projectType ?? '-1',
366374
}))
367-
.sort((a, b) => compareNumber(a.totalSwipes, b.totalSwipes)) ?? []
375+
.sort((a, b) => compareNumber(a.totalSwipes, b.totalSwipes, -1)) ?? []
368376
),
369377
[swipeByProjectType],
370378
);
@@ -382,7 +390,7 @@ function StatsBoard(props: Props) {
382390
organizationName: item.organizationName ?? 'Unknown',
383391
}))
384392
.filter((project) => isDefined(project.organizationName))
385-
.sort((a, b) => compareNumber(a.totalSwipes, b.totalSwipes)) ?? [];
393+
.sort((a, b) => compareNumber(a.totalSwipes, b.totalSwipes, -1)) ?? [];
386394

387395
if (sortedTotalSwipeByOrganization.length <= 5) {
388396
return sortedTotalSwipeByOrganization;
@@ -706,7 +714,9 @@ function StatsBoard(props: Props) {
706714
{sortedProjectSwipeType.length > 0 ? (
707715
<ResponsiveContainer>
708716
<PieChart>
709-
<Tooltip />
717+
<Tooltip
718+
formatter={missionTypeTotalSwipeFormatter}
719+
/>
710720
<Legend
711721
align={documentWidth <= CHART_BREAKPOINT ? 'center' : 'right'}
712722
layout={documentWidth <= CHART_BREAKPOINT ? 'horizontal' : 'vertical'}

0 commit comments

Comments
 (0)