From ad43f72f8bdaa823e1c925fa644efe9ada135e55 Mon Sep 17 00:00:00 2001 From: Delilah <23665803+goplayoutside3@users.noreply.github.com> Date: Mon, 4 Nov 2024 16:45:25 -0600 Subject: [PATCH] use a getDefaultDateRange() util --- packages/lib-user/dev/components/App/App.js | 11 +++-- .../src/components/Certificate/Certificate.js | 6 +-- .../Certificate/CertificateContainer.js | 12 ++--- .../GroupStats/GroupStatsContainer.js | 6 +-- .../StatsTabs/StatsTabsContainer.js | 17 +++---- .../UserStats/UserStatsContainer.js | 20 ++++---- .../shared/MainContent/MainContent.js | 11 ++--- .../helpers/getDateRangeSelectOptions.js | 16 +++--- .../lib-user/src/utils/getDateInterval.js | 49 +++++++------------ .../lib-user/src/utils/getDefaultDateRange.js | 36 ++++++++++++++ .../lib-user/src/utils/getStatsDateString.js | 6 ++- packages/lib-user/src/utils/index.js | 1 + 12 files changed, 103 insertions(+), 88 deletions(-) create mode 100644 packages/lib-user/src/utils/getDefaultDateRange.js diff --git a/packages/lib-user/dev/components/App/App.js b/packages/lib-user/dev/components/App/App.js index e5defebcc1..3f218f53bc 100644 --- a/packages/lib-user/dev/components/App/App.js +++ b/packages/lib-user/dev/components/App/App.js @@ -13,21 +13,24 @@ import { UserHome, UserStats } from '@components' +import { getDefaultDateRange, getStatsDateString } from '../../../src/utils' const isBrowser = typeof window !== 'undefined' -const todayUTC = new Date().toISOString().substring(0, 10) -const sevenDaysAgoUTC = new Date(new Date().setDate(new Date().getDate() - 6)).toISOString().substring(0, 10) +const today = new Date() +const todayUTC = getStatsDateString(today) if (isBrowser) { auth.checkCurrent() } +const DEFAULT_DATE_RANGE = getDefaultDateRange() + function App({ - endDate = todayUTC, + endDate = DEFAULT_DATE_RANGE.endDate, groups = null, joinToken = null, projectId = undefined, - startDate = sevenDaysAgoUTC, + startDate = DEFAULT_DATE_RANGE.startDate, updateQueryParams = () => true, users = null }) { diff --git a/packages/lib-user/src/components/Certificate/Certificate.js b/packages/lib-user/src/components/Certificate/Certificate.js index e772425f00..94ba2db5d2 100644 --- a/packages/lib-user/src/components/Certificate/Certificate.js +++ b/packages/lib-user/src/components/Certificate/Certificate.js @@ -10,6 +10,7 @@ import { } from '@components/shared' import { formatDateRange } from './helpers/formatDateRange' +import { getDefaultDateRange } from '@utils' const PrintableBox = styled(Box)` font-size: 16px; @@ -57,10 +58,7 @@ const PrintableBox = styled(Box)` } ` -const DEFAULT_DATE_RANGE = { - endDate: undefined, - startDate: undefined -} +const DEFAULT_DATE_RANGE = getDefaultDateRange() function handleClickPrint() { window.print() diff --git a/packages/lib-user/src/components/Certificate/CertificateContainer.js b/packages/lib-user/src/components/Certificate/CertificateContainer.js index 215a7b0ec3..ce7112e386 100644 --- a/packages/lib-user/src/components/Certificate/CertificateContainer.js +++ b/packages/lib-user/src/components/Certificate/CertificateContainer.js @@ -10,15 +10,13 @@ import { import { convertStatsSecondsToHours, - getDateInterval + getDateInterval, + getDefaultDateRange } from '@utils' import Certificate from './Certificate' -const DEFAULT_DATE_RANGE = { - endDate: null, - startDate: null -} +const DEFAULT_DATE_RANGE = getDefaultDateRange() const STATS_ENDPOINT = '/classifications/users' function CertificateContainer({ @@ -52,7 +50,7 @@ function CertificateContainer({ } else { statsQuery.project_id = parseInt(selectedProject) } - + const { data: stats, error: statsError, @@ -71,7 +69,7 @@ function CertificateContainer({ cards: true, id: selectedProject }) - + const error = userError || statsError || projectsError const hours = convertStatsSecondsToHours(stats?.time_spent) || 0 const loading = userLoading || statsLoading || projectsLoading diff --git a/packages/lib-user/src/components/GroupStats/GroupStatsContainer.js b/packages/lib-user/src/components/GroupStats/GroupStatsContainer.js index f9fcdde0a2..c7bdcad723 100644 --- a/packages/lib-user/src/components/GroupStats/GroupStatsContainer.js +++ b/packages/lib-user/src/components/GroupStats/GroupStatsContainer.js @@ -3,13 +3,11 @@ import { bool, func, shape, string } from 'prop-types' import { GroupContainer } from '@components/shared' +import { getDefaultDateRange } from '../../utils' import GroupStats from './GroupStats' -const DEFAULT_DATE_RANGE = { - endDate: undefined, - startDate: undefined -} +const DEFAULT_DATE_RANGE = getDefaultDateRange() const DEFAULT_HANDLER = () => true function GroupStatsContainer({ diff --git a/packages/lib-user/src/components/UserHome/components/Dashboard/components/StatsTabs/StatsTabsContainer.js b/packages/lib-user/src/components/UserHome/components/Dashboard/components/StatsTabs/StatsTabsContainer.js index 48a8863bb8..84aac6a283 100644 --- a/packages/lib-user/src/components/UserHome/components/Dashboard/components/StatsTabs/StatsTabsContainer.js +++ b/packages/lib-user/src/components/UserHome/components/Dashboard/components/StatsTabs/StatsTabsContainer.js @@ -3,6 +3,7 @@ import { shape, string } from 'prop-types' import { useStats } from '@hooks' import { getDateInterval, + getDefaultDateRange, getStatsDateString } from '@utils' import StatsTabs from './StatsTabs' @@ -20,16 +21,10 @@ const formatStatsPreview = (thisWeekData, allTimeData) => { } } +const DEFAULT_DATE_RANGE = getDefaultDateRange() // last 7 days + export default function StatsTabsContainer({ user }) { - const today = new Date() - const todayUTC = getStatsDateString(today) - - const thisWeekStart = new Date() - thisWeekStart.setUTCDate(today.getUTCDate() - 6) - const thisWeekQuery = getDateInterval({ - endDate: todayUTC, - startDate: getStatsDateString(thisWeekStart) - }) + const thisWeekQuery = getDateInterval(DEFAULT_DATE_RANGE) thisWeekQuery.project_contributions = true const { data: thisWeekData } = useStats({ sourceId: user?.id, @@ -37,8 +32,8 @@ export default function StatsTabsContainer({ user }) { }) const allTimeQuery = getDateInterval({ - endDate: todayUTC, - startDate: getStatsDateString(user?.created_at) + endDate: getStatsDateString(new Date()), // Today's UTC date string like 24-09-23. + startDate: getStatsDateString(user?.created_at) // Limit stats range to when the user acccount was created in panoptes. }) allTimeQuery.project_contributions = true const { data: allTimeData } = useStats({ diff --git a/packages/lib-user/src/components/UserStats/UserStatsContainer.js b/packages/lib-user/src/components/UserStats/UserStatsContainer.js index 1f6342e489..0de855fef5 100644 --- a/packages/lib-user/src/components/UserStats/UserStatsContainer.js +++ b/packages/lib-user/src/components/UserStats/UserStatsContainer.js @@ -9,15 +9,13 @@ import { } from '@hooks' import { - getDateInterval + getDateInterval, + getDefaultDateRange } from '@utils' import UserStats from './UserStats' -const DEFAULT_DATE_RANGE = { - endDate: undefined, - startDate: undefined -} +const DEFAULT_DATE_RANGE = getDefaultDateRange() const DEFAULT_HANDLER = () => true const STATS_ENDPOINT = '/classifications/users' @@ -40,12 +38,12 @@ function UserStatsContainer({ login, requiredUserProperty: 'created_at' }) - + // fetch all projects stats, used by projects select and top projects regardless of selected project const allProjectsStatsQuery = getDateInterval(selectedDateRange) allProjectsStatsQuery.project_contributions = true allProjectsStatsQuery.time_spent = true - + const { data: allProjectsStats, error: statsError, @@ -55,12 +53,12 @@ function UserStatsContainer({ sourceId: paramsValidationMessage ? null : user?.id, query: allProjectsStatsQuery }) - + // fetch individual project stats const projectStatsQuery = getDateInterval(selectedDateRange) projectStatsQuery.project_id = parseInt(selectedProject) projectStatsQuery.time_spent = true - + const { data: projectStats, error: projectStatsError, @@ -70,10 +68,10 @@ function UserStatsContainer({ sourceId: selectedProject ? user?.id : null, query: projectStatsQuery }) - + // fetch projects const projectIds = allProjectsStats?.project_contributions?.map(project => project.project_id) - + const { data: projects, error: projectsError, diff --git a/packages/lib-user/src/components/shared/MainContent/MainContent.js b/packages/lib-user/src/components/shared/MainContent/MainContent.js index cfd0a18383..29a42df11c 100644 --- a/packages/lib-user/src/components/shared/MainContent/MainContent.js +++ b/packages/lib-user/src/components/shared/MainContent/MainContent.js @@ -2,9 +2,11 @@ import { Loader, MovableModal, SpacedText } from '@zooniverse/react-components' import { Anchor, Box, Calendar, ResponsiveContext, Text } from 'grommet' import { arrayOf, bool, func, number, shape, string } from 'prop-types' import { useCallback, useContext, useEffect, useState } from 'react' +import Link from 'next/link' import { convertStatsSecondsToHours, + getDefaultDateRange, getStatsDateString } from '@utils' @@ -22,13 +24,10 @@ import { StyledTab } from './components' import { getDateRangeSelectOptions, getProjectSelectOptions } from './helpers' -import Link from 'next/link' + const DEFAULT_HANDLER = () => true -const DEFAULT_DATE_RANGE = { - endDate: null, - startDate: null -} +const DEFAULT_DATE_RANGE = getDefaultDateRange() const DEFAULT_STATS = { data: [], time_spent: 0, @@ -67,7 +66,7 @@ function MainContent({ const size = useContext(ResponsiveContext) const hoursSpent = convertStatsSecondsToHours(stats?.time_spent) - + const noStats = !stats?.data?.length const sourceCreatedAtDate = getStatsDateString(source?.created_at) diff --git a/packages/lib-user/src/components/shared/MainContent/helpers/getDateRangeSelectOptions.js b/packages/lib-user/src/components/shared/MainContent/helpers/getDateRangeSelectOptions.js index 961c93fd76..edc681057c 100644 --- a/packages/lib-user/src/components/shared/MainContent/helpers/getDateRangeSelectOptions.js +++ b/packages/lib-user/src/components/shared/MainContent/helpers/getDateRangeSelectOptions.js @@ -1,5 +1,6 @@ import { - getStatsDateString + getStatsDateString, + getDefaultDateRange } from '@utils' import { formatSelectOptionDateLabel } from './formatSelectOptionDateLabel' @@ -41,10 +42,7 @@ function getPresetSelectOptions({ sourceCreatedAtDate, today }) { ] } -const DEFAULT_DATE_RANGE = { - endDate: getStatsDateString(new Date()), - startDate: getStatsDateString(new Date(new Date().setUTCDate(new Date().getUTCDate() - 6))) -} +const DEFAULT_DATE_RANGE = getDefaultDateRange() export function getDateRangeSelectOptions({ sourceCreatedAtDate = '', @@ -53,14 +51,14 @@ export function getDateRangeSelectOptions({ }) { const today = new Date() const todayUTC = getStatsDateString(today) - + const dateRangeOptions = getPresetSelectOptions({ sourceCreatedAtDate, today }) - + let selectedDateRangeOption = dateRangeOptions.find(option => (selectedDateRange.endDate === todayUTC) && (option.value === selectedDateRange.startDate) ) - + if (!selectedDateRangeOption && !paramsValidationMessage) { const customDateRangeOption = { label: `${formatSelectOptionDateLabel(selectedDateRange)}`, @@ -74,6 +72,6 @@ export function getDateRangeSelectOptions({ value: 'custom' }) } - + return { dateRangeOptions, selectedDateRangeOption } } diff --git a/packages/lib-user/src/utils/getDateInterval.js b/packages/lib-user/src/utils/getDateInterval.js index 54cdd311ed..abb1640e76 100644 --- a/packages/lib-user/src/utils/getDateInterval.js +++ b/packages/lib-user/src/utils/getDateInterval.js @@ -1,42 +1,29 @@ -import { getStatsDateString } from '@utils' - -export function getDateInterval({ endDate, startDate }) { - const today = new Date() - const todayUTC = getStatsDateString(today) - const end_date = endDate ? endDate : todayUTC - const defaultStartDate = new Date() - defaultStartDate.setUTCDate(today.getUTCDate() - 6) - const start_date = startDate ? startDate : getStatsDateString(defaultStartDate) - - const differenceInDays = (new Date(end_date) - new Date(start_date)) / (1000 * 60 * 60 * 24) - +/* + ERAS accepts queries in time interval "buckets" of day, week, month, or year. +*/ +function getInterval(differenceInDays) { if (differenceInDays <= 31) { - return { - end_date, - period: 'day', - start_date - } + return 'day' } if (differenceInDays <= 183) { - return { - end_date, - period: 'week', - start_date - } + return 'week' } if (differenceInDays <= 1460) { - return { - end_date, - period: 'month', - start_date - } + return 'month' } + return 'year' +} + +export function getDateInterval({ endDate, startDate }) { + // Get new Date timestamps based on UTC strings, and then convert from ms to days. + const differenceInDays = (new Date(endDate) - new Date(startDate)) / (1000 * 60 * 60 * 24) + return { - end_date, - period: 'year', - start_date - } + end_date: endDate, + period: getInterval(differenceInDays), + start_date: startDate + } } diff --git a/packages/lib-user/src/utils/getDefaultDateRange.js b/packages/lib-user/src/utils/getDefaultDateRange.js new file mode 100644 index 0000000000..247e3dd549 --- /dev/null +++ b/packages/lib-user/src/utils/getDefaultDateRange.js @@ -0,0 +1,36 @@ +import { getStatsDateString } from '@utils' + +/* + Get the default end date (UTC) for stats query +*/ +function getDefaultEndDate() { + // Construct a new Javascript Date object + const today = new Date() + + // .toISOString() in this function returns a UTC string like 2024-05-05 + return getStatsDateString(today) +} + +/* + Get the default start date (UTC) for stats query +*/ +function getDefaultStartDate() { + // Construct a new Javascript Date object + const defaultStartDate = new Date() + + // .getUTCDate() returns numeric day of the month (UTC). + // If a negative number is provided to .setUTCDate(), the date will be + // set counting backwards from the last day of the previous month. + const sevenDaysAgo = defaultStartDate.getUTCDate() - 6 + defaultStartDate.setUTCDate(sevenDaysAgo) + + // .toISOString() in this function returns a UTC string + return getStatsDateString(defaultStartDate) +} + +export function getDefaultDateRange() { + return { + endDate: getDefaultEndDate(), + startDate: getDefaultStartDate() + } +} diff --git a/packages/lib-user/src/utils/getStatsDateString.js b/packages/lib-user/src/utils/getStatsDateString.js index aed1550698..961b60b817 100644 --- a/packages/lib-user/src/utils/getStatsDateString.js +++ b/packages/lib-user/src/utils/getStatsDateString.js @@ -1,6 +1,10 @@ +/* + Stats dates are always handled in UTC strings such as 24-09-23. +*/ + export function getStatsDateString(date) { if (date instanceof Date) { - return date.toISOString().substring(0, 10) + return date.toISOString().substring(0, 10) // .toISOString returns UTC } else { return date?.substring(0, 10) } diff --git a/packages/lib-user/src/utils/index.js b/packages/lib-user/src/utils/index.js index 8d68522234..22d69875a2 100644 --- a/packages/lib-user/src/utils/index.js +++ b/packages/lib-user/src/utils/index.js @@ -5,6 +5,7 @@ export { deletePanoptesMembership } from './deletePanoptesMembership.js' export { deletePanoptesUserGroup } from './deletePanoptesUserGroup.js' export { fetchPanoptesUsers } from './fetchPanoptesUsers.js' export { getDateInterval } from './getDateInterval.js' +export { getDefaultDateRange } from './getDefaultDateRange.js' export { getStatsDateString } from './getStatsDateString.js' export { updatePanoptesMembership } from './updatePanoptesMembership.js' export { updatePanoptesUserGroup } from './updatePanoptesUserGroup.js'