/** */ type type_role = ( "editor" | "viewer" ); /** */ type type_user_id = int; /** */ type type_user_object = { name : string; }; /** */ type type_event = { name : string; begin : type_datetime; end : ( null | type_datetime ); description : ( null | string ); }; /** */ type type_calendar_id = int; /** */ type type_calendar_object = ( { kind : "concrete"; data : { name : string; users : Array< { id : type_user_id; role : type_role; } >; events : Array; }; } | { kind : "collection"; data : { name : string; sources : Array< type_calendar_id >; } } ); /** */ type type_datamodel = { users : Array< { id : type_user_id; object : type_user_object; } >; calendars : Array< { id : type_calendar_id; object : type_calendar_object; } >; }; /** */ function calendar_list( data : type_datamodel ) : Array< { key : type_calendar_id; preview : { name : string; } } > { return ( data.calendars .map( (calendar_entry) => ({ "key": calendar_entry.id, "preview": { "name": calendar_entry.object.data.name, } }) ) ); } /** */ function calendar_read( data : type_datamodel, calendar_id : type_calendar_id ) : type_calendar_object { const hits = ( data.calendars .filter( (calendar_entry) => (calendar_entry.id === calendar_id) ) ); if (hits.length <= 0) { throw (new Error("not found")); } else { return hits[0].object; } } /** */ function calendar_gather_events( data : type_datamodel, calendar_id : type_calendar_id, from_pit : type_pit, to_pit : type_pit ) : Array< { calendar_id : type_calendar_id; event : type_event; } > { const calendar_object : type_calendar_object = calendar_read( data, calendar_id ); switch (calendar_object.kind) { case "concrete": { return ( calendar_object.data.events .filter( (event) => pit_is_between( pit_from_datetime(event.begin), from_pit, to_pit ) ) .map( (event) => ({"calendar_id": calendar_id, "event": event}) ) ); break; } case "collection": { return ( calendar_object.data.sources .map( (source_calendar_id) => calendar_gather_events( data, source_calendar_id, from_pit, to_pit ) ) .reduce( (x, y) => x.concat(y), [] ) ); break; } } } /** */ function calendar_view_table( data : type_datamodel, calendar_id : type_calendar_id, from : { year : int; week : int; }, to : { year : int; week : int; }, options : { timezone_shift ?: int; } = {} ) : Array< Array< { pit : type_pit; entries : Array< { calendar_id : type_calendar_id; event : type_event; } >; } > > { options = Object.assign( { "timezone_shift": 0, }, options ); /* const calendar_object : type_calendar_object = calendar_read( data, calendar_id ); */ const from_pit : type_pit = pit_from_year_and_week( from.year, from.week, { "timezone_shift": (options.timezone_shift as int), } ); const to_pit : type_pit = pit_from_year_and_week( to.year, to.week, { "timezone_shift": (options.timezone_shift as int), } ); // prepare const entries : Array< { calendar_id : type_calendar_id; event : type_event; } > = calendar_gather_events( data, calendar_id, from_pit, to_pit ); let result : Array< Array< { pit : type_pit; entries : Array< { calendar_id : type_calendar_id; event : type_event; } >; } > > = []; let row : Array< { pit : type_pit; entries : Array< { calendar_id : type_calendar_id; event : type_event; } >; } > = []; let day : int = 0; while (true) { const pit_current : type_pit = pit_shift_day(from_pit, day); if (pit_is_before(pit_current, to_pit)) { day += 1; row.push( { "pit": pit_current, "entries": [], } ); if (day % 7 === 0) { result.push(row); row = []; } else { // do nothing } } else { break; } } // fill ( entries .forEach( (entry) => { const distance_seconds : int = (pit_from_datetime(entry.event.begin) - from_pit); // process.stderr.write(JSON.stringify({"begin": entry.event.begin, "begin_pit": pit_from_datetime(entry.event.begin), "from": from_pit, "diff": distance_seconds}) + "\n"); const distance_days : int = (distance_seconds / (60 * 60 * 24)); const week : int = Math.floor(Math.floor(distance_days) / 7); const day : int = (Math.floor(distance_days) % 7); process.stderr.write(JSON.stringify({entry, distance_days, week, day}, undefined, "\t") + "\n"); result[week][day].entries.push(entry); } ) ); return result; } /** */ function calendar_view_table_html( data : type_datamodel, calendar_id : type_calendar_id, from : { year : int; week : int; }, to : { year : int; week : int; }, options : { timezone_shift ?: int; } = {} ) : string { options = Object.assign( { "timezone_shift": 0, }, options ); const rows = calendar_view_table( data, calendar_id, from, to, { "timezone_shift": options.timezone_shift, } ); return ( ( "\n" ) + "\n" + ( "\t\n" + "\t\n" ) + ( "\t\n" + ( rows .map( (row) => ( "\t\t\n" + ( row .map( (cell) => ( "\t\t\t\n" ) ) .join("") ) + "\t\t\n" ) ) .join("") ) + "\t\n" ) + "
\n" + ( "\t\t\t\t
    \n" + ( cell.entries .map( entry => ( "\t\t\t\t\t
  • \n" + entry.event.name + "\t\t\t\t\t
  • \n" ) ) .join("") ) + "\t\t\t\t
\n" ) // JSON.stringify(cell) + "\n" + "\t\t\t
\n" ); }