feat(DurationControl): Parse duration string input

This commit is contained in:
Corentin Forler 2024-08-05 12:57:34 +02:00
parent c06a854ea8
commit 4dbcc12470
No known key found for this signature in database

View file

@ -60,7 +60,7 @@ frappe.ui.form.ControlDuration = class ControlDuration extends frappe.ui.form.Co
}
set_duration_picker_value(value) {
let total_duration = frappe.utils.seconds_to_duration(value, this.duration_options);
let total_duration = frappe.utils.seconds_to_duration(value || 0, this.duration_options);
if (this.$picker) {
Object.keys(total_duration).forEach((duration) => {
@ -108,6 +108,7 @@ frappe.ui.form.ControlDuration = class ControlDuration extends frappe.ui.form.Co
// blur event was not due to duration inputs
this.$picker.hide();
}
this.set_formatted_input(this.value);
});
}
@ -116,7 +117,29 @@ frappe.ui.form.ControlDuration = class ControlDuration extends frappe.ui.form.Co
}
parse(value) {
return !value ? "" : value;
if (!value) {
return "";
} else if (/^\s*\d+\s*$/.test(value)) {
return parseInt(value);
}
this.DURATION_PARSE_REGEX ??= makeDurationParseRegex();
const match = String(value).trim().match(this.DURATION_PARSE_REGEX);
if (!match?.groups || !Object.values(match.groups).some((g) => !!g)) {
return null; // At least one group is required
}
let duration_in_seconds = 0;
for (const [key, multiplier] of Object.entries(DURATION_MULTIPLIERS)) {
duration_in_seconds += parseInt(match.groups?.[key] || 0) * multiplier;
}
return duration_in_seconds;
}
set_formatted_input(value) {
super.set_formatted_input(value);
this.set_duration_picker_value(value);
}
refresh_input() {
@ -160,3 +183,34 @@ frappe.ui.form.ControlDuration = class ControlDuration extends frappe.ui.form.Co
return is_set;
}
};
const DURATION_MULTIPLIERS = {
weeks: 7 * 24 * 60 * 60,
days: 24 * 60 * 60,
hours: 60 * 60,
minutes: 60,
seconds: 1,
};
function makeDurationParseRegex() {
// Wrap in a function for translations to work
// Matches strings like: 1d 2h 3m 4s, with optional parts
const _part = (key, seps) => {
// Use named capture group for the key, then match the separator (h, m, s)
const rCapture = `(?<${key}>\\d+)`;
const rSep = "(?:" + seps.join("|") + ")";
return "\\s*(?:" + rCapture + "\\s*" + rSep + ")?\\s*";
};
return new RegExp(
[
_part("days", [__("d", null, "Days (Field: Duration)")]),
_part("hours", [__("h", null, "Hours (Field: Duration)")]),
_part("minutes", [__("m", null, "Minutes (Field: Duration)")]),
_part("seconds", [__("s", null, "Seconds (Field: Duration)")]),
".*", // Fallback to ignore unknown parts
].join(""),
"i"
);
}