add schedule form validation to ensure at least one occurrence

This commit is contained in:
Keith J. Grant 2022-09-07 10:19:25 -07:00
parent 0005d249c0
commit 078c3ae6d8
3 changed files with 79 additions and 33 deletions

View File

@ -20,6 +20,7 @@ import ScheduleFormFields from './ScheduleFormFields';
import UnsupportedScheduleForm from './UnsupportedScheduleForm';
import parseRuleObj, { UnsupportedRRuleError } from './parseRuleObj';
import buildRuleObj from './buildRuleObj';
import buildRuleSet from './buildRuleSet';
const NUM_DAYS_PER_FREQUENCY = {
week: 7,
@ -411,6 +412,26 @@ function ScheduleForm({
}
});
if (values.exceptionFrequency.length > 0) {
let rangeToCheck = 1;
values.frequency.forEach((freq) => {
if (NUM_DAYS_PER_FREQUENCY[freq] > rangeToCheck) {
rangeToCheck = NUM_DAYS_PER_FREQUENCY[freq];
}
});
const ruleSet = buildRuleSet(values, true);
const startDate = DateTime.fromISO(values.startDate);
const endDate = startDate.plus({ days: rangeToCheck });
const instances = ruleSet.between(
startDate.toJSDate(),
endDate.toJSDate(),
true
);
if (instances.length === 0) {
errors.exceptionFrequency = t`This schedule has no occurrences due to the selected exceptions.`;
}
}
return errors;
};

View File

@ -36,11 +36,19 @@ function pad(num) {
return num < 10 ? `0${num}` : num;
}
export default function buildRuleObj(values) {
export default function buildRuleObj(values, includeStart) {
const ruleObj = {
interval: values.interval,
};
if (includeStart) {
ruleObj.dtstart = buildDateTime(
values.startDate,
values.startTime,
values.timezone
);
}
switch (values.frequency) {
case 'none':
ruleObj.count = 1;
@ -91,16 +99,11 @@ export default function buildRuleObj(values) {
ruleObj.count = values.occurrences;
break;
case 'onDate': {
const [endHour, endMinute] = parseTime(values.endTime);
const localEndDate = DateTime.fromISO(`${values.endDate}T000000`, {
zone: values.timezone,
});
const localEndTime = localEndDate.set({
hour: endHour,
minute: endMinute,
second: 0,
});
ruleObj.until = localEndTime.toJSDate();
ruleObj.until = buildDateTime(
values.endDate,
values.endTime,
values.timezone
);
break;
}
default:
@ -110,3 +113,16 @@ export default function buildRuleObj(values) {
return ruleObj;
}
function buildDateTime(dateString, timeString, timezone) {
const localDate = DateTime.fromISO(`${dateString}T000000`, {
zone: timezone,
});
const [hour, minute] = parseTime(timeString);
const localTime = localDate.set({
hour,
minute,
second: 0,
});
return localTime.toJSDate();
}

View File

@ -4,7 +4,7 @@ import buildRuleObj, { buildDtStartObj } from './buildRuleObj';
window.RRuleSet = RRuleSet;
const frequencies = ['minute', 'hour', 'day', 'week', 'month', 'year'];
export default function buildRuleSet(values) {
export default function buildRuleSet(values, includeStart) {
const set = new RRuleSet();
const startRule = buildDtStartObj({
@ -15,13 +15,16 @@ export default function buildRuleSet(values) {
set.rrule(startRule);
if (values.frequency.length === 0) {
const rule = buildRuleObj({
startDate: values.startDate,
startTime: values.startTime,
timezone: values.timezone,
frequency: 'none',
interval: 1,
});
const rule = buildRuleObj(
{
startDate: values.startDate,
startTime: values.startTime,
timezone: values.timezone,
frequency: 'none',
interval: 1,
},
includeStart
);
set.rrule(new RRule(rule));
}
@ -29,13 +32,16 @@ export default function buildRuleSet(values) {
if (!values.frequency.includes(frequency)) {
return;
}
const rule = buildRuleObj({
startDate: values.startDate,
startTime: values.startTime,
timezone: values.timezone,
frequency,
...values.frequencyOptions[frequency],
});
const rule = buildRuleObj(
{
startDate: values.startDate,
startTime: values.startTime,
timezone: values.timezone,
frequency,
...values.frequencyOptions[frequency],
},
includeStart
);
set.rrule(new RRule(rule));
});
@ -43,13 +49,16 @@ export default function buildRuleSet(values) {
if (!values.exceptionFrequency?.includes(frequency)) {
return;
}
const rule = buildRuleObj({
startDate: values.startDate,
startTime: values.startTime,
timezone: values.timezone,
frequency,
...values.exceptionOptions[frequency],
});
const rule = buildRuleObj(
{
startDate: values.startDate,
startTime: values.startTime,
timezone: values.timezone,
frequency,
...values.exceptionOptions[frequency],
},
includeStart
);
set.exrule(new RRule(rule));
});