@ -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 = [ Week day. Mo , Weekday . Tu , Weekday . We , Weekday . Th , Weekday . Fr , Weekday . Sa , Weekday . Su ] ;
const weekdays = [ Week Day. 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 . by weekday as Weekd ay[ ] ;
let byweekdayArray = options . by day as WeekD ay[ ] ;
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 ( { by week day: byweekday } ) ;
updateRule ( { by day: 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 = { Week day[ index ] } / >
label = { Week Day[ 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 &&