Skip to content

Commit

Permalink
Merge pull request #364 from kbss-cvut/363-invalid-time-value
Browse files Browse the repository at this point in the history
Fix RangeError: Invalid time value
  • Loading branch information
blcham authored Oct 16, 2024
2 parents 8ab53fd + 835620a commit cbbae1f
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 70 deletions.
56 changes: 33 additions & 23 deletions src/components/answer/DateTimeAnswer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,13 @@ import { FormGroup, Form } from "react-bootstrap";
import PropTypes from "prop-types";
import { format, parse } from "date-fns";
import FormUtils from "../../util/FormUtils";
import Constants from "../../constants/Constants";
import { ConfigurationContext } from "../../contexts/ConfigurationContext";
import classNames from "classnames";

const DateTimeAnswer = (props) => {
const { componentsOptions } = useContext(ConfigurationContext);
const [date, setDate] = useState(null);

useEffect(() => {
if (props.value) {
setDate(new Date(parse(props.value, datePickerFormat, new Date())));
}
}, []);
const [errorMessage, setErrorMessage] = useState("");

const dateFormat = FormUtils.resolveDateTimeFormat(
props.question,
Expand All @@ -26,38 +20,54 @@ const DateTimeAnswer = (props) => {

const isDate = FormUtils.isDate(props.question);
const isTime = FormUtils.isTime(props.question);
const isTimestampFormat = FormUtils.isTimestamp(props.question);

// DatePicker does not know dateFormat "x", translate to datetime
const datePickerFormat =
dateFormat === "x"
? componentsOptions.dateTimeAnswer.dateTimeFormat
: dateFormat;

const handleDateChange = (date) => {
setDate(date);
if (!date) {
props.onChange("");
}
if (dateFormat === Constants.DATETIME_NUMBER_FORMAT) {
props.onChange(Number(date));
useEffect(() => {
const parsedDate = parseDate(props.value);
if (parsedDate) {
setDate(parsedDate);
} else {
props.onChange(format(date, dateFormat));
setDate(null);
setErrorMessage(
`Invalid date value ${props.value} of question ${props.question["@id"]}.`
);
console.error(errorMessage);
}
}, [props.value, dateFormat]);

const parseDate = (value) => {
if (!value) return null;

const parsed = isTimestampFormat
? new Date(value)
: parse(value, dateFormat, new Date());
return isNaN(parsed.getTime()) ? null : parsed;
};

const handleDateChange = (selectedDate) => {
setDate(selectedDate);
const timeValue = selectedDate
? isTimestampFormat
? selectedDate.getTime()
: format(selectedDate, dateFormat)
: "";

props.onChange(timeValue);
};

return (
<FormGroup size="small">
<Form.Label className={"w-100"}>{props.label}</Form.Label>
<DatePicker
selected={date}
placeholderText={datePickerFormat}
placeholderText={dateFormat}
onChange={handleDateChange}
showTimeSelect={!isDate}
showTimeSelectOnly={isTime}
timeFormat="HH:mm"
timeIntervals={1}
timeCaption="Time"
dateFormat={datePickerFormat}
dateFormat={dateFormat}
className={classNames("form-control", props.validation.classname)}
disabled={
componentsOptions.readOnly || FormUtils.isDisabled(props.question)
Expand Down
3 changes: 3 additions & 0 deletions src/constants/Constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export default class Constants {
static COLUMN_COUNT = 12;
static INPUT_LENGTH_THRESHOLD = 50;
static DATETIME_NUMBER_FORMAT = "x";
static EPOCH_MILLISECONDS = "epoch-milliseconds";

/**
* Contains mainly definition of constants used to parse the form declaration.
Expand Down Expand Up @@ -146,6 +147,8 @@ export default class Constants {
static DATE_FORMAT = "http://onto.fel.cvut.cz/ontologies/form/date-format";
static DATETIME_FORMAT =
"http://onto.fel.cvut.cz/ontologies/form/datetime-format";
static TIMESTAMP_FORMAT =
"http://onto.fel.cvut.cz/ontologies/form/timestamp-format";

static NOT_ANSWERED_QUESTION =
"http://onto.fel.cvut.cz/ontologies/form/not-answered-question";
Expand Down
64 changes: 30 additions & 34 deletions src/stories/assets/form/form1.json
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,9 @@
"date-format": {
"@id": "http://onto.fel.cvut.cz/ontologies/form/date-format"
},
"timestamp-format": {
"@id": "http://onto.fel.cvut.cz/ontologies/form/timestamp-format"
},
"datetime-format": {
"@id": "http://onto.fel.cvut.cz/ontologies/form/datetime-format"
}
Expand Down Expand Up @@ -1346,6 +1349,20 @@
"has-layout-class": "section",
"has_answer": []
},
{
"label": "Technical section 3",
"form:has-question-origin": "http://onto.fel.cvut.cz/ontologies/vfn-form-mod/techical-section-3",
"@type": "doc:question",
"@id": "doc:question-e7e8eae0-6340-4a96-b13e-7dedaxxxaaaaa",
"has_related_question": [
"http://vfn.cz/ontologies/fss-form/simple-date-q",
"http://vfn.cz/ontologies/fss-form/simple-date-time-q",
"http://vfn.cz/ontologies/fss-form/simple-time-q",
"http://vfn.cz/ontologies/fss-form/timestamp-in-db-q"
],
"has-layout-class": "section",
"has_answer": []
},
{
"http://onto.fel.cvut.cz/ontologies/form-spin/has-declared-prefix": [],
"label": "Vfn",
Expand Down Expand Up @@ -1434,15 +1451,6 @@
"has-answer-origin": "http://onto.fel.cvut.cz/ontologies/eccairs/model/instance#instance-1236864794",
"@id": "http://onto.fel.cvut.cz/ontologies/eccairs/model/instance#instance-1236864794-a"
},
{
"@type": "doc:answer",
"has-answer-origin": "http://onto.fel.cvut.cz/ontologies/eccairs/model/instance#instance-1293838025",
"@id": "http://onto.fel.cvut.cz/ontologies/eccairs/model/instance#instance-1293838025-a",
"has_data_value": {
"@value": "0",
"@language": "en"
}
},
{
"@id": "http://onto.fel.cvut.cz/ontologies/eccairs/model/instance#instance-1345228433-a",
"@type": "doc:answer",
Expand Down Expand Up @@ -2380,7 +2388,6 @@
},
{
"@type": "doc:question",
"has_answer": "http://onto.fel.cvut.cz/ontologies/eccairs/model/instance#instance-1293838025-a",
"has-layout-class": "date",
"has-template": "http://onto.fel.cvut.cz/ontologies/eccairs/aviation-3.4.0.2/a-462-qt",
"comment": {
Expand Down Expand Up @@ -2448,32 +2455,33 @@
"label": "no of cycles"
},
{
"@id": "http://vfn.cz/ontologies/fss-form/primary-treatment--c--neoadjuvant--no-of-cycles-q",
"has-layout-class": ["section", "answerable", "datetime"],
"@id": "http://vfn.cz/ontologies/fss-form/simple-date-time-q",
"has-layout-class": ["datetime"],
"@type": "doc:question",
"label": "Date and time",
"datetime-format": "yyyy-MM-dd HH:mm"
},
{
"label": "Time",
"@type": "doc:question",
"has-layout-class": ["section", "answerable", "time"],
"has-layout-class": ["time"],
"time-format": "HH:mm",
"@id": "http://vfn.cz/ontologies/fss-form/primary-treatment--c--neoadjuvant--no-of-cycles-q1"
"@id": "http://vfn.cz/ontologies/fss-form/simple-time-q"
},
{
"label": "Date",
"has-layout-class": ["section", "answerable", "date"],
"@id": "http://vfn.cz/ontologies/fss-form/primary-treatment--c--neoadjuvant--no-of-cycles-q2",
"has-layout-class": ["date"],
"@id": "http://vfn.cz/ontologies/fss-form/simple-date-q",
"@type": "doc:question",
"date-format": "yyyy-MM-dd HH:mm"
"date-format": "yyyy-MM-dd"
},
{
"label": "Timestamp in db",
"@id": "http://vfn.cz/ontologies/fss-form/primary-treatment--c--neoadjuvant--no-of-cycles-q3",
"has-layout-class": ["section", "answerable", "datetime"],
"@id": "http://vfn.cz/ontologies/fss-form/timestamp-in-db-q",
"has-layout-class": ["datetime"],
"has_answer": "http://onto.fel.cvut.cz/ontologies/custom/model/instance#instance123456-a",
"@type": "doc:question"
"@type": "doc:question",
"timestamp-format": "epoch-milliseconds"
},
{
"has_related_question": "http://vfn.cz/ontologies/fss-form/primary-treatment--c--adjuvant--no-of-cycles-q",
Expand All @@ -2482,18 +2490,6 @@
"has-layout-class": ["section", "answerable", "checkbox"],
"label": "Adjuvant (after treatment procedure)"
},
{
"has_related_question": [
"http://vfn.cz/ontologies/fss-form/primary-treatment--c--neoadjuvant--no-of-cycles-q2",
"http://vfn.cz/ontologies/fss-form/primary-treatment--c--neoadjuvant--no-of-cycles-q",
"http://vfn.cz/ontologies/fss-form/primary-treatment--c--neoadjuvant--no-of-cycles-q1",
"http://vfn.cz/ontologies/fss-form/primary-treatment--c--neoadjuvant--no-of-cycles-q3"
],
"@type": "doc:question",
"@id": "http://vfn.cz/ontologies/fss-form/primary-treatment--chemotherapy--neoadjuvant-q",
"has-layout-class": ["section", "answerable", "checkbox"],
"label": "Neoadjuvant (before treatment procedure)"
},
{
"label": "No",
"@id": "http://vfn.cz/ontologies/fss-form/primary-treatment--chemotherapy--no-q",
Expand All @@ -2505,7 +2501,6 @@
"label": "Chemotherapy",
"has_related_question": [
"http://vfn.cz/ontologies/fss-form/primary-treatment--chemotherapy--adjuvant-q",
"http://vfn.cz/ontologies/fss-form/primary-treatment--chemotherapy--neoadjuvant-q",
"http://vfn.cz/ontologies/fss-form/primary-treatment--chemotherapy--no-q"
],
"@type": "doc:question",
Expand Down Expand Up @@ -2690,7 +2685,8 @@
"http://vfn.cz/ontologies/fss-form/primary-treatment--definitive-histology-q",
"http://vfn.cz/ontologies/fss-form/primary-treatment--surgical-treatment-q",
"doc:question-e7e8eae0-6340-4a96-b13e-7ded2b87abd4",
"doc:question-e7e8eae0-6340-4a96-b13e-7dedaaaaaaaa"
"doc:question-e7e8eae0-6340-4a96-b13e-7dedaaaaaaaa",
"doc:question-e7e8eae0-6340-4a96-b13e-7dedaxxxaaaaa"
],
"@type": "doc:question",
"@id": "http://vfn.cz/ontologies/fss-form/primary-treatment-q",
Expand Down
32 changes: 19 additions & 13 deletions src/util/FormUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,14 @@ export default class FormUtils {
);
}

static isTimestamp(question) {
return JsonLdUtils.hasValue(
question,
Constants.TIMESTAMP_FORMAT,
Constants.EPOCH_MILLISECONDS
);
}

static isCheckbox(question) {
return JsonLdUtils.hasValue(
question,
Expand Down Expand Up @@ -443,24 +451,22 @@ export default class FormUtils {
* @return {*} Format from Configuration
*/
static resolveDateTimeFormat(question, originalValue, options) {
const isNumber = typeof originalValue === "number";
const isDate = FormUtils.isDate(question);
const isTime = FormUtils.isTime(question);
const isDatetime = FormUtils.isDateTime(question);

if (isNumber) {
return Constants.DATETIME_NUMBER_FORMAT;
}
if (isDate) {
return question[Constants.DATE_FORMAT] || options.dateFormat;
}
if (isTime) {
return question[Constants.TIME_FORMAT] || options.timeFormat;
}
if (isDatetime) {
return question[Constants.DATETIME_FORMAT] || options.dateTimeFormat;
switch (true) {
case isDate:
return question[Constants.DATE_FORMAT] || options.dateFormat;

case isTime:
return question[Constants.TIME_FORMAT] || options.timeFormat;

case isDatetime:
return question[Constants.DATETIME_FORMAT] || options.dateTimeFormat;
default:
return null;
}
return null;
}

/**
Expand Down

0 comments on commit cbbae1f

Please sign in to comment.