Skip to content
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

fix(vizBuilder): RN-1054: picks wrong date #5447

Merged
merged 43 commits into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
b6e5f24
adjust `PreviewOptions`’ date picking logic
jaskfla Feb 23, 2024
fed76b7
make start/end dates deselectable again
jaskfla Feb 23, 2024
0f33790
Merge branch 'dev' into rn-1054-vizbuilder-datepicker
jaskfla Feb 28, 2024
26f83e8
Merge branch 'dev' into rn-1054-vizbuilder-datepicker
jaskfla Feb 29, 2024
b55bd45
Merge branch 'dev' into rn-1054-vizbuilder-datepicker
jaskfla Mar 1, 2024
239ca2d
Merge branch 'dev' into rn-1054-vizbuilder-datepicker
jaskfla Mar 1, 2024
358cd58
Merge branch 'dev' into rn-1054-vizbuilder-datepicker
jaskfla Mar 3, 2024
80ffc58
query API with only date, no time
jaskfla Mar 3, 2024
6628627
circumvent unpredictable Yup date coercion
jaskfla Mar 3, 2024
336db16
move `getIsoDate` to tsutils
jaskfla Mar 3, 2024
c471f8a
reusable `ISO_DATE_PATTERN` constant
jaskfla Mar 3, 2024
f2714d7
refactor datepicker change handlers
jaskfla Mar 3, 2024
136cea9
`getIsoDate` → `getIsoDateString`
jaskfla Mar 3, 2024
d62d210
finish renaming `getIsoDate` → `getIsoDateString`
jaskfla Mar 3, 2024
9614890
Merge branch 'dev' into rn-1054-vizbuilder-datepicker
jaskfla Mar 3, 2024
9fc7757
add missing import (and flip a ternary)
jaskfla Mar 3, 2024
e5a46a6
assume valid input
jaskfla Mar 6, 2024
58fbf7f
Merge branch 'dev' into rn-1054-vizbuilder-datepicker
jaskfla Mar 6, 2024
df75ccd
prettier
jaskfla Mar 6, 2024
2995fde
fix string slicing bug
jaskfla Mar 6, 2024
ebff0d7
fix tests
jaskfla Mar 6, 2024
bda83e7
remove `tsutils` dep from `admin-panel`
jaskfla Mar 6, 2024
ab12608
remove erroneous `export`
jaskfla Mar 6, 2024
107beac
update lockfile
jaskfla Mar 6, 2024
1941168
Merge branch 'dev' into rn-1054-vizbuilder-datepicker
jaskfla Mar 7, 2024
d4f2edb
more robust `getIsoDateString`
jaskfla Mar 7, 2024
211bef9
refactor change handlers
jaskfla Mar 7, 2024
2e404ff
organise imports
jaskfla Mar 7, 2024
f93dd35
Merge pull request #5506 from beyondessential/dev
avaek Mar 15, 2024
1916417
Merge pull request #5511 from beyondessential/dev
avaek Mar 17, 2024
45817fc
Merge pull request #5513 from beyondessential/dev
avaek Mar 18, 2024
34f4321
Merge branch 'dev' into rn-1054-vizbuilder-datepicker
jaskfla Mar 24, 2024
82ddf31
more robust `convertDateToIsoString `
jaskfla Mar 24, 2024
6feeab6
fix date picker picking previous day from selected
jaskfla Mar 25, 2024
204d928
comment date correcting helper function
jaskfla Mar 27, 2024
7345518
Merge branch 'dev' into rn-1054-vizbuilder-datepicker
jaskfla Mar 27, 2024
22b17ef
Merge pull request #5550 from beyondessential/dev
avaek Apr 2, 2024
f3f549d
Merge branch 'dev' into rn-1054-vizbuilder-datepicker
jaskfla Apr 3, 2024
b757821
clearer comment
jaskfla Apr 3, 2024
9b78def
use datetime helper
jaskfla Apr 3, 2024
f159054
tidy up import
jaskfla Apr 3, 2024
e162db4
fix header comment reference
jaskfla Apr 3, 2024
f046cc0
simplify explainer comment
jaskfla Apr 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/*
* Tupaia
* Copyright (c) 2017 - 2021 Beyond Essential Systems Pty Ltd
* Copyright (c) 2017 - 2024 Beyond Essential Systems Pty Ltd
*/

import React, { useState } from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
Expand All @@ -16,10 +17,9 @@ import {
FlexStart,
ImportModal,
} from '@tupaia/ui-components';
import { useLocations, useProjects } from '../api/queries';
import { useLocations, useProjects, useUploadTestData } from '../api';
import { usePreviewData, useVizConfig } from '../context';
import { LinkButton } from './LinkButton';
import { useUploadTestData } from '../api';

const Container = styled(FlexSpaceBetween)`
padding: 24px 0;
Expand Down Expand Up @@ -140,6 +140,13 @@ const UploadDataModal = ({ isOpen, onSubmit, onClose }) => (
/>
);

/**
* @returns ISO date string in the format "yyyy-mm-dd", or `null` if the input is not a valid `Date`
* instance.
* @param date A `Date` object.
*/
const getIsoDateString = date => (isNaN(date.getTime()) ? null : date.toISOString().slice(0, 10));
jaskfla marked this conversation as resolved.
Show resolved Hide resolved

export const PreviewOptions = () => {
const { setShowData } = usePreviewData();
const [locationSearch, setLocationSearch] = useState('');
Expand Down Expand Up @@ -174,13 +181,13 @@ export const PreviewOptions = () => {
};

const handleChangeStartDate = date => {
const newDate = date ? date.toISOString() : null;
const newDate = date ? getIsoDateString(date) : null;
jaskfla marked this conversation as resolved.
Show resolved Hide resolved
setSelectedStartDate(newDate);
setStartDate(newDate);
};

const handleChangeEndDate = date => {
const newDate = date ? date.toISOString() : null;
const newDate = date ? getIsoDateString(date) : null;
setSelectedEndDate(newDate);
setEndDate(newDate);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ describe('AnalyticsDataTableService', () => {
dataElementCodes: ['PSSS_AFR_Cases'],
startDate: 'cat',
},
'startDate must be a `date` type',
'startDate must be a valid ISO 8601 date: YYYY-MM-DD',
],
[
'endDate wrong format',
Expand All @@ -103,7 +103,7 @@ describe('AnalyticsDataTableService', () => {
dataElementCodes: ['PSSS_AFR_Cases'],
endDate: 'dog',
},
'endDate must be a `date` type',
'endDate must be a valid ISO 8601 date: YYYY-MM-DD',
],
[
'aggregations wrong format',
Expand Down Expand Up @@ -142,8 +142,8 @@ describe('AnalyticsDataTableService', () => {
},
name: 'dataElementCodes',
},
{ config: { defaultValue: new Date('2018-12-01'), type: 'date' }, name: 'startDate' },
{ config: { defaultValue: new Date('2023-12-31'), type: 'date' }, name: 'endDate' },
{ config: { defaultValue: '2018-12-01', type: 'string' }, name: 'startDate' },
{ config: { defaultValue: '2023-12-31', type: 'string' }, name: 'endDate' },
]);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ describe('EventsDataTableService', () => {
dataGroupCode: 'PSSS_WNR',
startDate: 'cat',
},
'startDate must be a `date` type',
'startDate must be a valid ISO 8601 date: YYYY-MM-DD',
],
[
'endDate wrong format',
Expand All @@ -169,7 +169,7 @@ describe('EventsDataTableService', () => {
dataGroupCode: 'PSSS_WNR',
endDate: 'dog',
},
'endDate must be a `date` type',
'endDate must be a valid ISO 8601 date: YYYY-MM-DD',
],
[
'aggregations wrong format',
Expand Down Expand Up @@ -208,8 +208,8 @@ describe('EventsDataTableService', () => {
config: { innerType: { required: true, type: 'string' }, type: 'dataElementCodes' },
name: 'dataElementCodes',
},
{ config: { defaultValue: new Date('2018-12-01'), type: 'date' }, name: 'startDate' },
{ config: { defaultValue: new Date('2023-12-31'), type: 'date' }, name: 'endDate' },
{ config: { defaultValue: '2018-12-01', type: 'string' }, name: 'startDate' },
{ config: { defaultValue: '2023-12-31', type: 'string' }, name: 'endDate' },
]);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,31 @@ import { TupaiaApiClient } from '@tupaia/api-client';
import { Aggregator } from '@tupaia/aggregator';
import { DataBroker } from '@tupaia/data-broker';
import { yup } from '@tupaia/utils';
import { ISO_DATE_PATTERN } from '@tupaia/tsutils';
import { DataTableService } from '../DataTableService';
import { orderParametersByName } from '../utils';
import { getDefaultEndDate, getDefaultStartDate, mapProjectEntitiesToCountries } from './utils';
import {
getDefaultEndDateString,
getDefaultStartDateString,
mapProjectEntitiesToCountries,
} from './utils';

const requiredParamsSchema = yup.object().shape({
hierarchy: yup.string().default('explore'),
dataElementCodes: yup.array().of(yup.string().required()).required(),
organisationUnitCodes: yup.array().of(yup.string().required()).required(),
startDate: yup.date().default(getDefaultStartDate),
endDate: yup.date().default(getDefaultEndDate),
startDate: yup
.string()
.matches(ISO_DATE_PATTERN, {
message: 'startDate must be a valid ISO 8601 date: YYYY-MM-DD',
})
.default(getDefaultStartDateString),
endDate: yup
.string()
.matches(ISO_DATE_PATTERN, {
message: 'endDate must be a valid ISO 8601 date: YYYY-MM-DD',
})
.default(getDefaultEndDateString),
aggregations: yup.array().of(
yup.object().shape({
type: yup.string().required(),
Expand Down Expand Up @@ -50,21 +65,12 @@ export class AnalyticsDataTableService extends DataTableService<
hierarchy: string;
dataElementCodes: string[];
organisationUnitCodes: string[];
startDate: Date;
endDate: Date;
startDate: string;
endDate: string;
aggregations?: { type: string; config?: Record<string, unknown> }[];
}) {
const {
hierarchy,
dataElementCodes,
organisationUnitCodes,
startDate,
endDate,
aggregations,
} = params;

const startDateString = startDate.toISOString();
const endDateString = endDate.toISOString();
const { hierarchy, dataElementCodes, organisationUnitCodes, startDate, endDate, aggregations } =
params;

// Ensure that if fetching for project, we map it to the underlying countries
const entityCodesForFetch = await mapProjectEntitiesToCountries(
Expand All @@ -85,8 +91,8 @@ export class AnalyticsDataTableService extends DataTableService<
{
organisationUnitCodes: entityCodesForFetch,
hierarchy,
startDate: startDateString,
endDate: endDateString,
startDate,
endDate,
detectDataServices: true,
},
{ aggregations },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,32 @@ import { Aggregator } from '@tupaia/aggregator';
import { TupaiaApiClient } from '@tupaia/api-client';
import { DataBroker } from '@tupaia/data-broker';
import { yup } from '@tupaia/utils';
import { ISO_DATE_PATTERN } from '@tupaia/tsutils';
import { DataTableService } from '../DataTableService';
import { orderParametersByName } from '../utils';
import { getDefaultEndDate, getDefaultStartDate, mapProjectEntitiesToCountries } from './utils';
import {
getDefaultEndDateString,
getDefaultStartDateString,
mapProjectEntitiesToCountries,
} from './utils';

const requiredParamsSchema = yup.object().shape({
hierarchy: yup.string().default('explore'),
dataGroupCode: yup.string().required(),
dataElementCodes: yup.array().of(yup.string().required()).min(1),
organisationUnitCodes: yup.array().of(yup.string().required()).strict().required(),
startDate: yup.date().default(getDefaultStartDate),
endDate: yup.date().default(getDefaultEndDate),
startDate: yup
.string()
.matches(ISO_DATE_PATTERN, {
message: 'startDate must be a valid ISO 8601 date: YYYY-MM-DD',
})
.default(getDefaultStartDateString),
endDate: yup
.string()
.matches(ISO_DATE_PATTERN, {
message: 'endDate must be a valid ISO 8601 date: YYYY-MM-DD',
})
.default(getDefaultEndDateString),
aggregations: yup.array().of(
yup.object().shape({
type: yup.string().required(),
Expand Down Expand Up @@ -73,8 +88,8 @@ export class EventsDataTableService extends DataTableService<
dataGroupCode: string;
dataElementCodes?: string[];
organisationUnitCodes: string[];
startDate?: Date;
endDate?: Date;
startDate?: string;
endDate?: string;
aggregations?: { type: string; config?: Record<string, unknown> }[];
}) {
const {
Expand All @@ -94,9 +109,6 @@ export class EventsDataTableService extends DataTableService<
}),
);

const startDateString = startDate ? startDate.toISOString() : undefined;
const endDateString = endDate ? endDate.toISOString() : undefined;

// Ensure that if fetching for project, we map it to the underlying countries
const entityCodesForFetch = await mapProjectEntitiesToCountries(
this.ctx.apiClient,
Expand All @@ -112,8 +124,8 @@ export class EventsDataTableService extends DataTableService<
{
hierarchy,
organisationUnitCodes: entityCodesForFetch,
startDate: startDateString,
endDate: endDateString,
startDate,
endDate,
dataElementCodes: dataElementCodesForFetch,
},
{ aggregations },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
/**
/*
* Tupaia
* Copyright (c) 2017 - 2023 Beyond Essential Systems Pty Ltd
* Copyright (c) 2017 - 2024 Beyond Essential Systems Pty Ltd
*/

import { convertPeriodStringToDateRange, getDefaultPeriod } from '@tupaia/utils';
import { getIsoDateString } from '@tupaia/tsutils';

export const getDefaultStartDate = () =>
new Date(convertPeriodStringToDateRange(getDefaultPeriod())[0]);
export const getDefaultEndDate = () =>
new Date(convertPeriodStringToDateRange(getDefaultPeriod())[1]);

export const getDefaultStartDateString = () => getIsoDateString(getDefaultStartDate());
export const getDefaultEndDateString = () => getIsoDateString(getDefaultEndDate());
10 changes: 9 additions & 1 deletion packages/tsutils/src/datetime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@
import moment from 'moment';
import momentTimezone from 'moment-timezone';

export const ISO_DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/;

/**
* @returns ISO date string in the format "yyyy-mm-dd".
* @remarks Assumes the input date object is valid.
*/
export const getIsoDateString = (date: Date) => date.toISOString().slice(0, 10);

/**
* @returns utcOffset in format: "+05:00"
*/
Expand All @@ -19,4 +27,4 @@ export const getTimezoneNameFromTimestamp = (timestamp: string) =>
.names()
.find(name => getUtcOffsetFromTimestamp(timestamp) === momentTimezone.tz(name).format('Z'));

export const utcMoment = (...args: Parameters<typeof moment['utc']>) => moment.utc(...args);
export const utcMoment = (...args: Parameters<(typeof moment)['utc']>) => moment.utc(...args);
Loading