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

Fixed many usability issues with the CalendarDay field #2930

Merged
merged 3 commits into from
May 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
15 changes: 15 additions & 0 deletions .changeset/sour-taxis-hunt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
'@arch-ui/day-picker': patch
'@keystonejs/fields': patch
---

Fixed many usability issues with the CalendarDay field:
- Fixed field not functioning as a proper controlled component in the Create popout.
- Fixed field initially displaying "Invalid Date" before defaulting to 1970-01-01.
- Filter input no longer defaults to the current date. This was bugged; submitting the form with no changes would match nothing.
- Filter input now falls back to no value when given an invalid date. Previously, it was falling back to 1970-01-01.
- Fixed filter input not initially displaying the current value when in edit mode (it was displaying the current date).
- Fixed filter input not being initially focused.
- Fixed filter input not being submitted properly if focus wasn't lost first.

Updated chrono-node dependency to 1.4.6.
2 changes: 1 addition & 1 deletion packages/arch/packages/day-picker/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"@babel/runtime": "^7.8.4",
"@emotion/core": "^10.0.28",
"@emotion/styled": "^10.0.27",
"chrono-node": "^1.3.5",
"chrono-node": "^1.4.6",
"date-fns": "^1.30.1",
"intersection-observer": "^0.10.0",
"moment": "^2.24.0",
Expand Down
111 changes: 59 additions & 52 deletions packages/arch/packages/day-picker/src/TextDayPicker.js
Original file line number Diff line number Diff line change
@@ -1,57 +1,64 @@
/** @jsx jsx */
import { jsx } from '@emotion/core';
import { useState } from 'react';
import React, { useState, useEffect, forwardRef, useRef } from 'react';
import chrono from 'chrono-node';
import { Input } from '@arch-ui/input';
import { format } from 'date-fns';

export const TextDayPicker = ({
date,
onChange,
format: displayFormat = 'Do MMMM YYYY',
...props
}) => {
const formatDate = newDate => (newDate === null ? '' : format(newDate, displayFormat));

const [isEditing, setIsEditing] = useState(false);
const [value, setValue] = useState({
raw: date,
formatted: formatDate(date),
});

const toggleEditing = () => {
setIsEditing(!isEditing);
};

const onBlur = () => {
toggleEditing();

const newDate = parseDate(value.raw);
onChange(newDate);

setValue({
raw: newDate,
formatted: formatDate(newDate),
export const TextDayPicker = forwardRef(
({ date = '', onChange, format: displayFormat = 'Do MMMM YYYY', ...props }, ref) => {
const formatDate = newDate => (newDate ? format(newDate, displayFormat) : '');

const [isEditing, setIsEditing] = useState(false);
const [value, setValue] = useState({
raw: date,
formatted: formatDate(date),
});
};

const handleChange = ({ target: { value: raw } }) => {
setValue(oldValue => ({ ...oldValue, raw }));
};

return (
<Input
value={isEditing ? value.raw : value.formatted}
placeholder="Enter a date..."
onFocus={toggleEditing}
onBlur={onBlur}
onChange={handleChange}
{...props}
/>
);
};

function parseDate(value) {
const parsed = chrono.parseDate(value);
return parsed === undefined ? null : format(parsed, 'YYYY-MM-DD');
}

const parseCache = useRef();

useEffect(() => {
// Parse the raw input. This may be a string such as 'Today'.
const parsedDate = chrono.parseDate(value.raw);

// If valid, convert it to ISO 8601.
const isoDate = parsedDate ? format(parsedDate, 'YYYY-MM-DD') : null;

// Pass it up the tree. The parent can handle the null case.
onChange(isoDate);

parseCache.current = isoDate;
}, [value.raw]);

const onFocus = () => {
setIsEditing(true);
};

const onBlur = () => {
setIsEditing(false);

const raw = parseCache.current;

// At this point, the parse cache should either be null or an ISO 8601 date.
if (raw) {
setValue({ raw, formatted: formatDate(raw) });
} else {
setValue({ raw: '', formatted: '' });
}
};

const handleChange = ({ target: { value: raw } }) => {
setValue(oldValue => ({ ...oldValue, raw }));
};

return (
<Input
ref={ref}
value={isEditing ? value.raw : value.formatted}
placeholder="Enter a date..."
onFocus={onFocus}
onBlur={onBlur}
onChange={handleChange}
{...props}
/>
);
}
);
16 changes: 5 additions & 11 deletions packages/fields/src/types/CalendarDay/views/Filter.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,18 @@
import React, { useState } from 'react';
import { format } from 'date-fns';
import React from 'react';
import { TextDayPicker } from '@arch-ui/day-picker';

const FORMAT = 'YYYY-MM-DD';

const CalendarDayFilterView = ({ onChange, filter }) => {
const [value, setValue] = useState(format(new Date(), FORMAT));

const handleSelectedChange = newValue => {
const CalendarDayFilterView = ({ onChange, filter, value, innerRef }) => {
const handleChange = newValue => {
if (newValue === null) {
newValue = format(new Date(), FORMAT);
newValue = '';
}

onChange(newValue);
setValue(newValue);
};

if (!filter) return null;

return <TextDayPicker date={value} onChange={handleSelectedChange} />;
return <TextDayPicker ref={innerRef} date={value} onChange={handleChange} />;
};

export default CalendarDayFilterView;
4 changes: 2 additions & 2 deletions packages/fields/src/types/DateTime/views/Filter.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { format } from 'date-fns';
import { DayTimePicker } from '@arch-ui/day-picker';
import { stringifyDate, parseDate } from './utils';

const CalendarDayFilterView = props => {
const DateTimeFilterView = props => {
const parsedDate = props.value ? parseDate(props.value) : parseDate(new Date().toISOString());

let handleDayChange = day => {
Expand Down Expand Up @@ -38,4 +38,4 @@ const CalendarDayFilterView = props => {
);
};

export default CalendarDayFilterView;
export default DateTimeFilterView;
59 changes: 12 additions & 47 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -432,15 +432,6 @@
"@babel/template" "^7.8.3"
"@babel/types" "^7.9.5"

"@babel/helper-function-name@^7.9.5":
version "7.9.5"
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz#2b53820d35275120e1874a82e5aabe1376920a5c"
integrity sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw==
dependencies:
"@babel/helper-get-function-arity" "^7.8.3"
"@babel/template" "^7.8.3"
"@babel/types" "^7.9.5"

"@babel/helper-get-function-arity@^7.7.4":
version "7.7.4"
resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz#cb46348d2f8808e632f0ab048172130e636005f0"
Expand Down Expand Up @@ -609,11 +600,6 @@
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz#90977a8e6fbf6b431a7dc31752eee233bf052d80"
integrity sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==

"@babel/helper-validator-identifier@^7.9.5":
version "7.9.5"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz#90977a8e6fbf6b431a7dc31752eee233bf052d80"
integrity sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==

"@babel/helper-wrap-function@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz#9dbdb2bb55ef14aaa01fe8c99b629bd5352d8610"
Expand Down Expand Up @@ -772,16 +758,7 @@
"@babel/plugin-syntax-object-rest-spread" "^7.8.0"
"@babel/plugin-transform-parameters" "^7.9.5"

"@babel/plugin-proposal-object-rest-spread@^7.0.0", "@babel/plugin-proposal-object-rest-spread@^7.5.5", "@babel/plugin-proposal-object-rest-spread@^7.6.2", "@babel/plugin-proposal-object-rest-spread@^7.7.4", "@babel/plugin-proposal-object-rest-spread@^7.8.3":
version "7.9.6"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.6.tgz#7a093586fcb18b08266eb1a7177da671ac575b63"
integrity sha512-Ga6/fhGqA9Hj+y6whNpPv8psyaK5xzrQwSPsGPloVkvmH+PqW1ixdnfJ9uIO06OjQNYol3PMnfmJ8vfZtkzF+A==
dependencies:
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/plugin-syntax-object-rest-spread" "^7.8.0"
"@babel/plugin-transform-parameters" "^7.9.5"

"@babel/plugin-proposal-object-rest-spread@^7.9.5", "@babel/plugin-proposal-object-rest-spread@^7.9.6":
"@babel/plugin-proposal-object-rest-spread@^7.0.0", "@babel/plugin-proposal-object-rest-spread@^7.5.5", "@babel/plugin-proposal-object-rest-spread@^7.6.2", "@babel/plugin-proposal-object-rest-spread@^7.7.4", "@babel/plugin-proposal-object-rest-spread@^7.8.3", "@babel/plugin-proposal-object-rest-spread@^7.9.5", "@babel/plugin-proposal-object-rest-spread@^7.9.6":
version "7.9.6"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.6.tgz#7a093586fcb18b08266eb1a7177da671ac575b63"
integrity sha512-Ga6/fhGqA9Hj+y6whNpPv8psyaK5xzrQwSPsGPloVkvmH+PqW1ixdnfJ9uIO06OjQNYol3PMnfmJ8vfZtkzF+A==
Expand Down Expand Up @@ -1239,14 +1216,6 @@
"@babel/helper-get-function-arity" "^7.8.3"
"@babel/helper-plugin-utils" "^7.8.3"

"@babel/plugin-transform-parameters@^7.9.5":
version "7.9.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.9.5.tgz#173b265746f5e15b2afe527eeda65b73623a0795"
integrity sha512-0+1FhHnMfj6lIIhVvS4KGQJeuhe1GI//h5uptK4PvLt+BGBxsoUJbd3/IW002yk//6sZPlFgsG1hY6OHLcy6kA==
dependencies:
"@babel/helper-get-function-arity" "^7.8.3"
"@babel/helper-plugin-utils" "^7.8.3"

"@babel/plugin-transform-property-literals@^7.0.0", "@babel/plugin-transform-property-literals@^7.2.0", "@babel/plugin-transform-property-literals@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.8.3.tgz#33194300d8539c1ed28c62ad5087ba3807b98263"
Expand Down Expand Up @@ -1844,15 +1813,6 @@
lodash "^4.17.13"
to-fast-properties "^2.0.0"

"@babel/types@^7.9.5", "@babel/types@^7.9.6":
version "7.9.6"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.6.tgz#2c5502b427251e9de1bd2dff95add646d95cc9f7"
integrity sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==
dependencies:
"@babel/helper-validator-identifier" "^7.9.5"
lodash "^4.17.13"
to-fast-properties "^2.0.0"

"@bcoe/v8-coverage@^0.2.3":
version "0.2.3"
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
Expand Down Expand Up @@ -6851,12 +6811,12 @@ chrome-trace-event@^1.0.0, chrome-trace-event@^1.0.2:
dependencies:
tslib "^1.9.0"

chrono-node@^1.3.5:
version "1.3.5"
resolved "https://registry.yarnpkg.com/chrono-node/-/chrono-node-1.3.5.tgz#a2495298a32da82bcc01ad9be7d77efa5e244122"
integrity sha1-oklSmKMtqCvMAa2b59d++l4kQSI=
chrono-node@^1.4.6:
version "1.4.6"
resolved "https://registry.yarnpkg.com/chrono-node/-/chrono-node-1.4.6.tgz#dcdc59f1cc80e65d8f6c977bd6ad4e9b82008a8e"
integrity sha512-CBUbwkj2gRdCSacmJ4UvKOSsSjW5jWce3kiruZSMgmGf7FKwc2ERat32yPSqJDR8aDeA0lUJxiDzZRhXZmXBqw==
dependencies:
moment "^2.10.3"
dayjs "^1.8.19"

[email protected], ci-info@^2.0.0:
version "2.0.0"
Expand Down Expand Up @@ -8321,6 +8281,11 @@ date-now@^0.1.4:
resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b"
integrity sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=

dayjs@^1.8.19:
version "1.8.26"
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.8.26.tgz#c6d62ccdf058ca72a8d14bb93a23501058db9f1e"
integrity sha512-KqtAuIfdNfZR5sJY1Dixr2Is4ZvcCqhb0dZpCOt5dGEFiMzoIbjkTSzUb4QKTCsP+WNpGwUjAFIZrnZvUxxkhw==

de-indent@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d"
Expand Down Expand Up @@ -16556,7 +16521,7 @@ mocha@^7.1.2:
yargs-parser "13.1.2"
yargs-unparser "1.6.0"

[email protected], moment@^2.10.3, moment@^2.21.0, moment@^2.24.0:
[email protected], moment@^2.21.0, moment@^2.24.0:
version "2.24.0"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b"
integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==
Expand Down