From 6446777c7983e5a8194d34c3499b26283fa0e3e0 Mon Sep 17 00:00:00 2001 From: Tal Leibman Date: Sat, 4 Jan 2020 17:14:24 +0200 Subject: [PATCH] widgets: add RRule widget First step towards fixing #50 RRule widget for repeating tasks and calendar events --- src/widgets/RRule.tsx | 293 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 293 insertions(+) create mode 100644 src/widgets/RRule.tsx diff --git a/src/widgets/RRule.tsx b/src/widgets/RRule.tsx new file mode 100644 index 0000000..7cf97dc --- /dev/null +++ b/src/widgets/RRule.tsx @@ -0,0 +1,293 @@ +import * as React from 'react'; +import Container from './Container'; +import { TextField, Select, MenuItem, FormGroup, FormControlLabel, Checkbox, InputLabel, FormControl } from '@material-ui/core'; +import DateTimePicker from '../widgets/DateTimePicker'; +import { isNumber } from 'util'; + +interface PropsType { + onChange: (rrule: RRuleOptions) => void; + rrule: RRuleOptions; +} +export interface RRuleOptions { + freq: Frequency; + interval: number; + until?: Date; + count?: number; + byweekday?: Weekday[]; + bymonthday?: number; + byyearday?: number; + byweekno?: number; + bymonth?: Months; + bysetpos?: number; +} + +enum Frequency { + Year = 0, + Month = 1, + Week = 2, + Day = 3, +} +enum Ends { + Never, + Date, + After, +} +enum Months { + Jan = 1, + Feb, + Mar, + Apr, + May, + Jun, + Jul, + Aug, + Sep, + Oct, + Nov, + Dec, +} +enum MonthRepeat { + Bysetpos, + Bymonthday, +} +enum Weekday { + Mo, + Tu, + We, + Th, + Fr, + Sa, + Su +} + +const menuItemsMonths = Object.keys(Months).filter((key) => Number(key)).map((key) => { + return ( + {Months[key]} + ); +}); +const menuItemsEnds = [Ends.Never, Ends.Date, Ends.After].map((key) => { + return ( + {Ends[key]} + ); +}); +const weekdays = [Weekday.Mo, Weekday.Tu, Weekday.We, Weekday.Th, Weekday.Fr, Weekday.Sa, Weekday.Su]; +const menuItemsFrequency = [Frequency.Year, Frequency.Month, Frequency.Week, Frequency.Day].map((value) => { + return ( + {Frequency[value]} + ); +}); + +export default function RRuleEteSync(props: PropsType) { + const options = props.rrule; + + function updateRule(newOptions: Partial): void { + const updatedOptions = { ...options, ...newOptions }; + props.onChange(updatedOptions); + } + + function getEnds(): Ends { + if (options.until && !options.count) { + return Ends.Date; + } else if (!options.until && options.count) { + return Ends.After; + } else { + return Ends.Never; + } + } + + function handleCheckboxWeekday(event: React.FormEvent<{ value: unknown }>): void { + const checkbox = event.target as HTMLInputElement; + const weekday = Number(checkbox.value); + let byweekdayArray = options.byweekday as Weekday[]; + let byweekday; + if (!checkbox.checked && byweekdayArray) { + byweekday = byweekdayArray.filter((day) => day !== weekday); + } else if (byweekdayArray) { + byweekdayArray = byweekdayArray.filter((day) => day !== weekday); + byweekday = [...byweekdayArray, weekday]; + } else { + byweekday = [weekday]; + } + updateRule({ byweekday: byweekday }); + } + + function isWeekdayChecked(day: number): boolean { + const weekdayArray = options.byweekday; + if (weekdayArray) { + return isNumber(weekdayArray.find((value) => Weekday[value] === Weekday[day])); + } else { + return false; + } + } + + const checkboxWeekDays = weekdays.map((_, index) => { + return ( + } + key={index} + label={Weekday[index]} /> + ); + }); + + return ( + +
+ ) => { + event.preventDefault(); + const inputNode = event.currentTarget as HTMLInputElement; + if (inputNode.value === '') { + updateRule({ interval: undefined }); + } else if (inputNode.valueAsNumber) { + updateRule({ interval: inputNode.valueAsNumber }); + } + }} + />} + /> + +
+
+ + {(options.freq === Frequency.Month) && + + } + + + {options.bysetpos && + + } + {(options.freq === Frequency.Year && options.bymonth) && + + } + {options.bymonthday && + ) => { + event.preventDefault(); + const value = (event.currentTarget as HTMLInputElement).value; + const numberValue = Number(value); + if (value === '') { + updateRule({ bymonthday: undefined }); + } else if (numberValue < 32 && numberValue > 0) { + updateRule({ bymonthday: numberValue }); + } + }} + /> + + } +
+
+ {options.freq !== Frequency.Day && + {checkboxWeekDays} + } + + Ends + + + {options.until && + updateRule({ until: date })} + /> + } + {options.count && + ) => { + event.preventDefault(); + const inputNode = event.currentTarget as HTMLInputElement; + if (inputNode.value === '') { + updateRule({ count: 1 }); + } else if (inputNode.valueAsNumber) { + updateRule({ count: inputNode.valueAsNumber }); + } + }} + /> + } +
+
+ ); +}