|
|
|
@ -1,13 +1,12 @@
|
|
|
|
|
#![feature(proc_macro_hygiene, decl_macro)] |
|
|
|
|
#![recursion_limit="512"] |
|
|
|
|
#![recursion_limit="1024"] |
|
|
|
|
|
|
|
|
|
use std::fs::read_to_string; |
|
|
|
|
use std::sync::Mutex; |
|
|
|
|
#[macro_use] extern crate rocket; |
|
|
|
|
use rocket::{State, response::content}; |
|
|
|
|
use typed_html::{html, text, dom::DOMTree}; |
|
|
|
|
use diesel::{Connection, pg::PgConnection, prelude::*}; |
|
|
|
|
use chrono::offset::Local; |
|
|
|
|
use chrono::{offset::Local, NaiveDate}; |
|
|
|
|
|
|
|
|
|
use libticker::{ |
|
|
|
|
config::{Config, CalendarOptions}, |
|
|
|
@ -24,6 +23,33 @@ fn fix_url(s: &str) -> std::borrow::Cow<str> {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
struct DayEvents<'e> { |
|
|
|
|
date: NaiveDate, |
|
|
|
|
events: &'e [Event], |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// assumes pre-sorted input
|
|
|
|
|
fn group_by_day(es: &[Event]) -> Vec<DayEvents> { |
|
|
|
|
let mut results = vec![]; |
|
|
|
|
|
|
|
|
|
let mut prev_date = None; |
|
|
|
|
let mut date_start = 0; |
|
|
|
|
for (i, event) in es.iter().enumerate() { |
|
|
|
|
if prev_date.is_some() && prev_date != Some(event.dtstart.date()) { |
|
|
|
|
if i > date_start { |
|
|
|
|
results.push(DayEvents { |
|
|
|
|
date: prev_date.unwrap().clone(), |
|
|
|
|
events: &es[date_start..i], |
|
|
|
|
}); |
|
|
|
|
date_start = i; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
prev_date = Some(event.dtstart.date()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
results |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[get("/")] |
|
|
|
|
fn index(db: State<Mutex<PgConnection>>) -> content::Html<String> { |
|
|
|
|
let db = db.lock().unwrap(); |
|
|
|
@ -34,7 +60,8 @@ fn index(db: State<Mutex<PgConnection>>) -> content::Html<String> {
|
|
|
|
|
.then_order_by(schema::events::dtend.desc()) |
|
|
|
|
.load::<Event>(&*db) |
|
|
|
|
.unwrap(); |
|
|
|
|
|
|
|
|
|
let days = group_by_day(&es); |
|
|
|
|
|
|
|
|
|
let doc: DOMTree<String> = html!( |
|
|
|
|
<html> |
|
|
|
|
<head> |
|
|
|
@ -43,29 +70,33 @@ fn index(db: State<Mutex<PgConnection>>) -> content::Html<String> {
|
|
|
|
|
<body> |
|
|
|
|
<h1>"Ticker"</h1> |
|
|
|
|
|
|
|
|
|
{ es.iter().map(|e| html!( |
|
|
|
|
<article class="event"> |
|
|
|
|
{ match &e.url { |
|
|
|
|
None => html!( |
|
|
|
|
<h2>{ text!("{}", &e.summary) }</h2> |
|
|
|
|
), |
|
|
|
|
Some(url) => html!( |
|
|
|
|
<h2> |
|
|
|
|
<a href={ fix_url(url) }> |
|
|
|
|
{ text!("{}", &e.summary) } |
|
|
|
|
</a> |
|
|
|
|
</h2> |
|
|
|
|
), |
|
|
|
|
} } |
|
|
|
|
{ days.iter().map(|day| html!(<div> |
|
|
|
|
<nav><h2>{ text!("{}", &day.date) }</h2></nav> |
|
|
|
|
|
|
|
|
|
{ day.events.iter().map(|e| html!( |
|
|
|
|
<article class="event"> |
|
|
|
|
{ match &e.url { |
|
|
|
|
None => html!( |
|
|
|
|
<h3>{ text!("{}", &e.summary) }</h3> |
|
|
|
|
), |
|
|
|
|
Some(url) => html!( |
|
|
|
|
<h3> |
|
|
|
|
<a href={ fix_url(url) }> |
|
|
|
|
{ text!("{}", &e.summary) } |
|
|
|
|
</a> |
|
|
|
|
</h3> |
|
|
|
|
), |
|
|
|
|
} } |
|
|
|
|
|
|
|
|
|
<p class="dtstart">{ text!("{}", &e.dtstart) }</p> |
|
|
|
|
{ e.location.as_ref().map(|location| html!( |
|
|
|
|
<p> |
|
|
|
|
{ text!("{}", location) } |
|
|
|
|
</p> |
|
|
|
|
)) } |
|
|
|
|
</article> |
|
|
|
|
)) } |
|
|
|
|
<p class="dtstart">{ text!("{}", &e.dtstart) }</p> |
|
|
|
|
{ e.location.as_ref().map(|location| html!( |
|
|
|
|
<p> |
|
|
|
|
{ text!("{}", location) } |
|
|
|
|
</p> |
|
|
|
|
)) } |
|
|
|
|
</article> |
|
|
|
|
)) } |
|
|
|
|
</div>)) } |
|
|
|
|
</body> |
|
|
|
|
</html> |
|
|
|
|
); |
|
|
|
|