widgets: change RRule to get type ICAL.Recur as prop

in ICAL.Recur many values are an array of numbers currently the
RRule widget only handle multiple values for weekday.
this change is not final since it may cause user data to be lost
when editing an existing event
master
Tal Leibman 5 years ago committed by Tom Hacohen
parent aae9cd5d16
commit 8d9482b720

@ -2,33 +2,29 @@ import * as React from 'react';
import { TextField, Select, MenuItem, FormGroup, FormControlLabel, Checkbox, InputLabel, FormControl } from '@material-ui/core'; import { TextField, Select, MenuItem, FormGroup, FormControlLabel, Checkbox, InputLabel, FormControl } from '@material-ui/core';
import DateTimePicker from '../widgets/DateTimePicker'; import DateTimePicker from '../widgets/DateTimePicker';
import { isNumber } from 'util'; import { isNumber } from 'util';
import * as ICAL from 'ical.js';
interface PropsType { interface PropsType {
onChange: (rrule: RRuleOptions) => void; onChange: (rrule: RRuleOptions) => void;
rrule: RRuleOptions; rrule: RRuleOptions;
} }
type Frequency = 'YEARLY' | 'MONTHLY' | 'WEEKLY' | 'DAILY' | 'HOURLY' | 'MINUTELY' | 'SECONDLY';
export interface RRuleOptions { export interface RRuleOptions {
freq: Frequency; freq: Frequency;
interval: number; interval?: number;
until?: Date; wkst?: WeekDay;
until?: ICAL.Time;
count?: number; count?: number;
byweekday?: Weekday[];
bymonthday?: number;
byyearday?: number;
byweekno?: number;
bymonth?: Months;
bysetpos?: number;
wkst?: Weekday;
bysecond?: number[]; bysecond?: number[];
byminute?: number[]; byminute?: number[];
byhour?: number[];
byday?: number[]; byday?: number[];
bymonthday?: number[];
} byyearday?: number[];
enum Frequency { byweekno?: number[];
YEARLY, bymonth?: number[];
MONTHLY, bysetpos?: number[];
WEEKLY,
DAILY,
} }
enum Ends { enum Ends {
Never, Never,
@ -53,14 +49,14 @@ enum MonthRepeat {
Bysetpos, Bysetpos,
Bymonthday, Bymonthday,
} }
enum Weekday { enum WeekDay {
Su = 1,
Mo, Mo,
Tu, Tu,
We, We,
Th, Th,
Fr, Fr,
Sa, Sa,
Su
} }
const menuItemsMonths = Object.keys(Months).filter((key) => Number(key)).map((key) => { const menuItemsMonths = Object.keys(Months).filter((key) => Number(key)).map((key) => {
@ -73,10 +69,10 @@ const menuItemsEnds = [Ends.Never, Ends.Date, Ends.After].map((key) => {
<MenuItem key={key} value={key}>{Ends[key]}</MenuItem> <MenuItem key={key} value={key}>{Ends[key]}</MenuItem>
); );
}); });
const weekdays = [Weekday.Mo, Weekday.Tu, Weekday.We, Weekday.Th, Weekday.Fr, Weekday.Sa, Weekday.Su]; const weekdays = [WeekDay.Su, WeekDay.Mo, WeekDay.Tu, WeekDay.We, WeekDay.Th, WeekDay.Fr, WeekDay.Sa];
const menuItemsFrequency = [Frequency.YEARLY, Frequency.MONTHLY, Frequency.WEEKLY, Frequency.DAILY].map((value) => { const menuItemsFrequency = ['YEARLY', 'MONTHLY', 'WEEKLY', 'DAILY'].map((value) => {
return ( return (
<MenuItem key={value} value={value}>{Frequency[value]}</MenuItem> <MenuItem key={value} value={value}>{value}</MenuItem>
); );
}); });
@ -101,7 +97,7 @@ export default function RRuleEteSync(props: PropsType) {
function handleCheckboxWeekday(event: React.FormEvent<{ value: unknown }>): void { function handleCheckboxWeekday(event: React.FormEvent<{ value: unknown }>): void {
const checkbox = event.target as HTMLInputElement; const checkbox = event.target as HTMLInputElement;
const weekday = Number(checkbox.value); const weekday = Number(checkbox.value);
let byweekdayArray = options.byweekday as Weekday[]; let byweekdayArray = options.byday as WeekDay[];
let byweekday; let byweekday;
if (!checkbox.checked && byweekdayArray) { if (!checkbox.checked && byweekdayArray) {
byweekday = byweekdayArray.filter((day) => day !== weekday); byweekday = byweekdayArray.filter((day) => day !== weekday);
@ -111,30 +107,29 @@ export default function RRuleEteSync(props: PropsType) {
} else { } else {
byweekday = [weekday]; byweekday = [weekday];
} }
updateRule({ byweekday: byweekday }); updateRule({ byday: byweekday });
} }
function isWeekdayChecked(day: number): boolean { function isWeekdayChecked(day: number): boolean {
const weekdayArray = options.byweekday; if (options.byday) {
if (weekdayArray) { return isNumber(options.byday.find((value) => WeekDay[value] === WeekDay[day]));
return isNumber(weekdayArray.find((value) => Weekday[value] === Weekday[day]));
} else { } else {
return false; return false;
} }
} }
const checkboxWeekDays = weekdays.map((_, index) => { const checkboxWeekDays = weekdays.map((day) => {
return ( return (
<FormControlLabel <FormControlLabel
control={ control={
<Checkbox <Checkbox
key={index} key={day}
value={index} value={day}
checked={isWeekdayChecked(index)} checked={isWeekdayChecked(day)}
onChange={handleCheckboxWeekday} onChange={handleCheckboxWeekday}
/>} />}
key={index} key={day}
label={Weekday[index]} /> label={WeekDay[day]} />
); );
}); });
@ -164,13 +159,13 @@ export default function RRuleEteSync(props: PropsType) {
value={options.freq} value={options.freq}
style={{ alignSelf: 'flex-end', marginLeft: 20 }} style={{ alignSelf: 'flex-end', marginLeft: 20 }}
onChange={(event: React.FormEvent<{ value: unknown }>) => { onChange={(event: React.FormEvent<{ value: unknown }>) => {
const freq = Number((event.target as HTMLSelectElement).value); const freq = (event.target as HTMLSelectElement).value as Frequency;
const updatedOptions = { const updatedOptions = {
freq: freq, freq: freq,
bysetpos: undefined, bysetpos: undefined,
bymonthday: freq === Frequency.MONTHLY || Frequency.YEARLY === freq ? 1 : undefined, bymonthday: freq === 'MONTHLY' || 'YEARLY' === freq ? [1] : undefined,
byweekday: undefined, byweekday: undefined,
bymonth: freq === Frequency.YEARLY ? Months.Jan : undefined, bymonth: freq === 'YEARLY' ? [Months.Jan] : undefined,
}; };
updateRule(updatedOptions); updateRule(updatedOptions);
}} }}
@ -180,15 +175,15 @@ export default function RRuleEteSync(props: PropsType) {
</div> </div>
<div style={{ display: 'flex' }}> <div style={{ display: 'flex' }}>
{(options.freq === Frequency.MONTHLY) && {(options.freq === 'MONTHLY') &&
<Select <Select
value={options.bysetpos ? MonthRepeat.Bysetpos : MonthRepeat.Bymonthday} value={options.bysetpos ? MonthRepeat.Bysetpos : MonthRepeat.Bymonthday}
onChange={(event: React.FormEvent<{ value: unknown }>) => { onChange={(event: React.FormEvent<{ value: unknown }>) => {
const value = Number((event.target as HTMLInputElement).value); const value = Number((event.target as HTMLInputElement).value);
if (value === MonthRepeat.Bymonthday) { if (value === MonthRepeat.Bymonthday) {
updateRule({ bymonthday: 1, bysetpos: undefined, bymonth: Months.Jan }); updateRule({ bymonthday: [1], bysetpos: undefined, bymonth: [Months.Jan] });
} else if (value === MonthRepeat.Bysetpos) { } else if (value === MonthRepeat.Bysetpos) {
updateRule({ bysetpos: 1, bymonthday: undefined, bymonth: undefined }); updateRule({ bysetpos: [1], bymonthday: undefined, bymonth: undefined });
} }
}} }}
> >
@ -200,9 +195,9 @@ export default function RRuleEteSync(props: PropsType) {
{options.bysetpos && {options.bysetpos &&
<Select <Select
value={options.bysetpos} value={options.bysetpos[0]}
onChange={(event: React.FormEvent<{ value: unknown }>) => { onChange={(event: React.FormEvent<{ value: unknown }>) => {
updateRule({ bysetpos: Number((event.target as HTMLInputElement).value) }); updateRule({ bysetpos: [Number((event.target as HTMLInputElement).value)] });
}}> }}>
<MenuItem value={1}>First</MenuItem> <MenuItem value={1}>First</MenuItem>
<MenuItem value={2}>Second</MenuItem> <MenuItem value={2}>Second</MenuItem>
@ -211,11 +206,11 @@ export default function RRuleEteSync(props: PropsType) {
<MenuItem value={-1}>Last</MenuItem> <MenuItem value={-1}>Last</MenuItem>
</Select> </Select>
} }
{(options.freq === Frequency.YEARLY && options.bymonth) && {(options.freq === 'YEARLY' && options.bymonth) &&
<Select <Select
value={options.bymonth} value={options.bymonth}
onChange={(event: React.FormEvent<{ value: unknown }>) => { onChange={(event: React.FormEvent<{ value: unknown }>) => {
updateRule({ bymonth: Number((event.target as HTMLInputElement).value) }); updateRule({ bymonth: [Number((event.target as HTMLInputElement).value)] });
}}> }}>
{menuItemsMonths} {menuItemsMonths}
</Select> </Select>
@ -223,7 +218,7 @@ export default function RRuleEteSync(props: PropsType) {
{options.bymonthday && {options.bymonthday &&
<TextField <TextField
type="number" type="number"
value={options.bymonthday} value={options.bymonthday[0]}
label="Month day" label="Month day"
style={{ width: 100 }} style={{ width: 100 }}
inputProps={{ min: 1, step: 1, max: 31 }} inputProps={{ min: 1, step: 1, max: 31 }}
@ -234,7 +229,7 @@ export default function RRuleEteSync(props: PropsType) {
if (value === '') { if (value === '') {
updateRule({ bymonthday: undefined }); updateRule({ bymonthday: undefined });
} else if (numberValue < 32 && numberValue > 0) { } else if (numberValue < 32 && numberValue > 0) {
updateRule({ bymonthday: numberValue }); updateRule({ bymonthday: [numberValue] });
} }
}} }}
/> />
@ -242,7 +237,7 @@ export default function RRuleEteSync(props: PropsType) {
} }
</div> </div>
<div> <div>
{options.freq !== Frequency.DAILY && {(options.freq && options.freq !== 'DAILY') &&
<FormGroup row>{checkboxWeekDays}</FormGroup> <FormGroup row>{checkboxWeekDays}</FormGroup>
} }
<FormControl> <FormControl>
@ -253,7 +248,7 @@ export default function RRuleEteSync(props: PropsType) {
const value = Number((event.target as HTMLSelectElement).value); const value = Number((event.target as HTMLSelectElement).value);
let updateOptions; let updateOptions;
if (value === Ends.Date) { if (value === Ends.Date) {
updateOptions = { count: undefined, until: new Date() }; updateOptions = { count: undefined, until: ICAL.Time.now() };
} else if (value === Ends.After) { } else if (value === Ends.After) {
updateOptions = { until: undefined, count: 1 }; updateOptions = { until: undefined, count: 1 };
} else { } else {
@ -267,9 +262,12 @@ export default function RRuleEteSync(props: PropsType) {
{options.until && {options.until &&
<DateTimePicker <DateTimePicker
dateOnly dateOnly
value={options.until || undefined} value={options.until?.toJSDate() || undefined}
placeholder="Ends" placeholder="Ends"
onChange={(date?: Date) => updateRule({ until: date })} onChange={(date?: Date) => {
const value = date ? date : null;
updateRule({ until: ICAL.Time.fromJSDate(value, true) });
}}
/> />
} }
{options.count && {options.count &&

Loading…
Cancel
Save