Skip to content

Commit

Permalink
Merge pull request #32738 from dimagi/es/daterange
Browse files Browse the repository at this point in the history
Add placeholder and pattern to daterange picker widget
  • Loading branch information
esoergel authored Mar 21, 2023
2 parents bd82509 + 1f0f5d2 commit 43c0bf1
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 26 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* eslint-env mocha */
/* globals moment */

describe('Entries', function () {
var constants = hqImport("cloudcare/js/form_entry/const"),
Expand Down Expand Up @@ -339,6 +340,31 @@ describe('Entries', function () {
assert.equal(utils.convertTwoDigitYear("not-a-date"), "not-a-date");
});

it('Should coerce user input dates to moment objects', function () {
let assertParsesAs = function (userInput, expected) {
let res = utils.parseInputDate(userInput);
assert.isTrue(moment.isMoment(res));
assert.equal(
res.toISOString(),
moment(expected, "YYYY-MM-DD").toISOString()
);
};

assertParsesAs("03/04/20", "2020-03-04");
assertParsesAs("3/4/20", "2020-03-04");
assertParsesAs("2020-03-04", "2020-03-04");
});

it('Should fail to interpret invalid date inputs', function () {
let assertInvalid = function (userInput) {
assert.isNull(utils.parseInputDate(userInput));
};

assertInvalid("23/01/2022");
assertInvalid("23/1/22");
assertInvalid("23-1-22");
});

it('Should return TimeEntry', function () {
questionJSON.datatype = constants.TIME;
questionJSON.answer = '12:30';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,14 @@ hqDefine("cloudcare/js/formplayer/menus/views/query", function () {
var separator = " to ",
serverSeparator = "__",
serverPrefix = "__range__",
dateFormat = "MM/DD/YYYY",
// A list of acceptable date formats, in order of preference
dateFormats = ['YYYY-MM-DD', 'MM/DD/YYYY', 'MM-DD-YYYY', 'MM/DD/YY', 'MM-DD-YY', moment.defaultFormat],
dateFormat = cloudcareUtils.dateFormat,
selectDelimiter = "#,#"; // Formplayer also uses this

var toIsoDate = function (dateString) {
return moment(dateString, dateFormats, true).format('YYYY-MM-DD');
return cloudcareUtils.parseInputDate(dateString).format('YYYY-MM-DD');
};
var toUiDate = function (dateString) {
return moment(dateString, dateFormats, true).format(dateFormat);
return cloudcareUtils.parseInputDate(dateString).format(dateFormat);
};

var encodeValue = function (model, searchForBlank) {
Expand Down Expand Up @@ -361,7 +359,7 @@ hqDefine("cloudcare/js/formplayer/menus/views/query", function () {
escapeMarkup: function (m) { return DOMPurify.sanitize(m); },
});
this.ui.hqHelp.hqHelp();
cloudcareUtils.initDatePicker(this.ui.date, this.model.get('value'), dateFormat);
cloudcareUtils.initDatePicker(this.ui.date, this.model.get('value'));
this.ui.dateRange.daterangepicker({
locale: {
format: dateFormat,
Expand All @@ -370,25 +368,30 @@ hqDefine("cloudcare/js/formplayer/menus/views/query", function () {
autoUpdateInput: false,
"autoApply": true,
});
this.ui.dateRange.attr("placeholder", dateFormat + separator + dateFormat);
let separatorChars = _.unique(separator).join("");
this.ui.dateRange.attr("pattern", "^[\\d\\/\\-" + separatorChars + "]*$");
this.ui.dateRange.on('cancel.daterangepicker', function () {
$(this).val('').trigger('change');
});
this.ui.dateRange.on('apply.daterangepicker', function(ev, picker) {
$(this).val(picker.startDate.format(dateFormat) + separator + picker.endDate.format(dateFormat)).trigger('change');
});
this.ui.dateRange.on('change', function () {
// Validate free-text input. Accept anything moment can recognize as a date, reformatting for ES.
var $input = $(this),
// Validate free-text input
var start, end,
$input = $(this),
oldValue = $input.val(),
parts = _.map(oldValue.split(separator), function (v) { return moment(v, dateFormats); }),
parts = _.map(oldValue.split(separator), cloudcareUtils.parseInputDate),
newValue = '';

if (_.every(parts, function (part) { return part.isValid(); })) {
if (_.every(parts, part => part !== null)) {
if (parts.length === 1) { // condition where only one valid date is typed in rather than a range
newValue = oldValue + separator + oldValue;
start = end = parts[0];
} else if (parts.length === 2) {
newValue = parts[0].format(dateFormat) + separator + parts[1].format(dateFormat);
[start, end] = parts;
}
newValue = start.format(dateFormat) + separator + end.format(dateFormat);
}
if (oldValue !== newValue) {
$input.val(newValue).trigger('change');
Expand Down
34 changes: 20 additions & 14 deletions corehq/apps/cloudcare/static/cloudcare/js/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -371,13 +371,23 @@ hqDefine('cloudcare/js/utils', [
return inputDate;
};

var initDatePicker = function ($el, selectedDate, dateFormat) {
var dateFormat = 'MM/DD/YYYY';
var dateFormats = ['MM/DD/YYYY', 'YYYY-MM-DD', 'M/D/YYYY', 'M/D/YY', 'M-D-YYYY', 'M-D-YY', moment.defaultFormat];

/** Coerce an input date string to a moment object */
var parseInputDate = function (dateString) {
if (!moment.isMoment(dateString)) {
dateString = convertTwoDigitYear(dateString);
}
let dateObj = moment(dateString, dateFormats, true);
return dateObj.isValid() ? dateObj : null;
};

var initDatePicker = function ($el, selectedDate) {
if (!$el.length) {
return;
}

dateFormat = dateFormat || "MM/DD/YYYY";
let formats = _.union([dateFormat], ["MM/DD/YYYY", "MM/DD/YY", "YYYY-MM-DD"]);
$el.datetimepicker({
date: selectedDate,
useCurrent: false,
Expand All @@ -386,35 +396,29 @@ hqDefine('cloudcare/js/utils', [
showTodayButton: true,
debug: true,
format: dateFormat,
extraFormats: formats,
extraFormats: dateFormats,
useStrict: true,
icons: {
today: 'glyphicon glyphicon-calendar',
},
tooltips: dateTimePickerTooltips,
parseInputDate: function (dateString) {
if (!moment.isMoment(dateString) || dateString instanceof Date) {
dateString = convertTwoDigitYear(dateString);
}
let dateObj = moment(dateString, formats, true);
return dateObj.isValid() ? dateObj : null;
},
parseInputDate: parseInputDate,
});

$el.on("focusout", $el.data("DateTimePicker").hide);
$el.attr("placeholder", dateFormat);
$el.attr("pattern", "[0-9-/]+");
};

var initTimePicker = function ($el, selectedTime, dateFormat) {
var initTimePicker = function ($el, selectedTime, timeFormat) {
if (!$el.length) {
return;
}

let date = moment(selectedTime, dateFormat);
let date = moment(selectedTime, timeFormat);
$el.datetimepicker({
date: date.isValid() ? date : null,
format: dateFormat,
format: timeFormat,
useStrict: true,
useCurrent: false,
showClear: true,
Expand All @@ -427,7 +431,9 @@ hqDefine('cloudcare/js/utils', [
};

return {
dateFormat: dateFormat,
convertTwoDigitYear: convertTwoDigitYear,
parseInputDate: parseInputDate,
initDatePicker: initDatePicker,
initTimePicker: initTimePicker,
getFormUrl: getFormUrl,
Expand Down

0 comments on commit 43c0bf1

Please sign in to comment.