1- import { Meeting , MeetingsQuery } from 'lib/model' ;
1+ import { RRule } from 'rrule' ;
2+ import { nanoid } from 'nanoid' ;
3+
4+ import { Meeting , MeetingsQuery , Timeslot } from 'lib/model' ;
25import { addOptionsFilter , addStringFilter , list } from 'lib/api/search' ;
36
47function getFilterStrings ( query : MeetingsQuery ) : string [ ] {
@@ -9,19 +12,52 @@ function getFilterStrings(query: MeetingsQuery): string[] {
912 const to = query . to . valueOf ( ) ;
1013 const from = query . from . valueOf ( ) ;
1114
15+ const endWithin = `time.last >= ${ from } AND time.last <= ${ to } ` ;
16+ const startWithin = `time.from >= ${ from } AND time.from <= ${ to } ` ;
17+
1218 return [
13- // TODO: Time overlaps with top of query (start is before query start).
14- // addStringFilter(str, `(time.to > ${from} AND time.from <= ${from})`),
15- // Meeting time is contained within query (start is after and end before).
16- addStringFilter ( str , `(time.to <= ${ to } AND time.from >= ${ from } )` ) ,
17- // TODO: Time overlaps with bottom of query (end is after query end).
18- // addStringFilter(str, `(time.from < ${to} AND time.to >= ${to})`),
19+ // Start is before window but end is within.
20+ addStringFilter ( str , `(time.from < ${ from } AND ${ endWithin } )` ) ,
21+ // Both start and end are within window.
22+ addStringFilter ( str , `(${ startWithin } AND ${ endWithin } )` ) ,
23+ // End is after window but start is within.
24+ addStringFilter ( str , `(time.last > ${ to } AND ${ startWithin } )` ) ,
25+ // Start is before window and end is after.
26+ addStringFilter ( str , `(time.from < ${ from } AND time.last > ${ to } )` ) ,
1927 ] ;
2028}
2129
30+ // TODO: Generate instance meetings (from recurring parent meetings returned by
31+ // query) within requested time window and send those to the client.
2232export default async function getMeetings (
2333 query : MeetingsQuery
2434) : Promise < { hits : number ; results : Meeting [ ] } > {
2535 const filters = getFilterStrings ( query ) ;
26- return list ( 'meetings' , query , Meeting . fromSearchHit , filters ) ;
36+ const data = await list ( 'meetings' , query , Meeting . fromSearchHit , filters ) ;
37+ let { hits } = data ;
38+ const meetings = data . results
39+ . map ( ( meeting ) => {
40+ if ( ! meeting . time . recur ) return [ meeting ] ;
41+ const options = RRule . parseString ( meeting . time . recur ) ;
42+ const rrule = new RRule ( { ...options , dtstart : meeting . time . from } ) ;
43+ // TODO: What if meeting instance starts before window but end is within?
44+ const starts = rrule . between ( query . from , query . to ) ;
45+ console . log ( 'Starts:' , starts . map ( ( s ) => s . toString ( ) ) . join ( ', ' ) ) ;
46+ hits += starts . length - 1 ;
47+ return starts . map (
48+ ( start ) =>
49+ new Meeting ( {
50+ ...meeting ,
51+ id : nanoid ( ) ,
52+ parentId : meeting . id ,
53+ time : new Timeslot ( {
54+ ...meeting . time ,
55+ from : start ,
56+ to : new Date ( start . valueOf ( ) + meeting . time . duration ) ,
57+ } ) ,
58+ } )
59+ ) ;
60+ } )
61+ . flat ( ) ;
62+ return { hits, results : meetings } ;
2763}
0 commit comments