serve: split main into index
This commit is contained in:
parent
d1566f6c31
commit
9a1a106e0e
|
@ -0,0 +1,113 @@
|
||||||
|
use gotham::{
|
||||||
|
helpers::http::response::create_response,
|
||||||
|
hyper::{Body, Response},
|
||||||
|
state::{FromState, State},
|
||||||
|
};
|
||||||
|
use http::status::StatusCode;
|
||||||
|
use mime::TEXT_HTML;
|
||||||
|
|
||||||
|
use typed_html::{html, text, dom::DOMTree};
|
||||||
|
use diesel::prelude::*;
|
||||||
|
use chrono::{offset::Local, NaiveDate};
|
||||||
|
|
||||||
|
use libticker::{
|
||||||
|
schema::{self, events::dsl::events},
|
||||||
|
model::Event,
|
||||||
|
};
|
||||||
|
use crate::AppState;
|
||||||
|
|
||||||
|
|
||||||
|
fn fix_url(s: &str) -> std::borrow::Cow<str> {
|
||||||
|
if s.starts_with("http:") || s.starts_with("https:") {
|
||||||
|
s.into()
|
||||||
|
} else {
|
||||||
|
format!("http://{}", s).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_index(app_state: &AppState) -> String {
|
||||||
|
let db = app_state.db.lock().unwrap();
|
||||||
|
let today = Local::today().naive_local().and_hms(0, 0, 0);
|
||||||
|
let es = events
|
||||||
|
.filter(schema::events::dtstart.ge(&today))
|
||||||
|
.order_by(schema::events::dtstart.asc())
|
||||||
|
.then_order_by(schema::events::dtend.desc())
|
||||||
|
.load::<Event>(&*db)
|
||||||
|
.unwrap();
|
||||||
|
let days = group_by_day(&es);
|
||||||
|
|
||||||
|
let doc: DOMTree<String> = html!(
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>"Ticker"</title>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
{ 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>
|
||||||
|
)) }
|
||||||
|
</div>)) }
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
);
|
||||||
|
format!("<DOCTYPE html>\n{}", doc.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn index(state: State) -> (State, Response<Body>) {
|
||||||
|
let message = {
|
||||||
|
let app_state = AppState::borrow_from(&state);
|
||||||
|
render_index(app_state)
|
||||||
|
};
|
||||||
|
let res = create_response(&state, StatusCode::OK, TEXT_HTML, message);
|
||||||
|
(state, res)
|
||||||
|
}
|
|
@ -6,129 +6,20 @@ extern crate gotham_derive;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use gotham::{
|
use gotham::{
|
||||||
handler::assets::FileOptions,
|
handler::assets::FileOptions,
|
||||||
helpers::http::response::create_response,
|
|
||||||
hyper::{Body, Response},
|
|
||||||
router::builder::{DefineSingleRoute, DrawRoutes},
|
router::builder::{DefineSingleRoute, DrawRoutes},
|
||||||
middleware::state::StateMiddleware,
|
middleware::state::StateMiddleware,
|
||||||
pipeline::single::single_pipeline,
|
pipeline::single::single_pipeline,
|
||||||
pipeline::single_middleware,
|
pipeline::single_middleware,
|
||||||
router::builder::*,
|
router::builder::*,
|
||||||
state::{FromState, State},
|
|
||||||
};
|
};
|
||||||
use http::status::StatusCode;
|
use diesel::{Connection, pg::PgConnection};
|
||||||
use mime::TEXT_HTML;
|
|
||||||
|
|
||||||
use typed_html::{html, text, dom::DOMTree};
|
use libticker::config::Config;
|
||||||
use diesel::{Connection, pg::PgConnection, prelude::*};
|
mod index;
|
||||||
use chrono::{offset::Local, NaiveDate};
|
|
||||||
|
|
||||||
use libticker::{
|
|
||||||
config::{Config, CalendarOptions},
|
|
||||||
schema::{self, events::dsl::events},
|
|
||||||
model::{Calendar, Event},
|
|
||||||
ics::{Object, Timestamp, GetValue},
|
|
||||||
};
|
|
||||||
|
|
||||||
fn fix_url(s: &str) -> std::borrow::Cow<str> {
|
|
||||||
if s.starts_with("http:") || s.starts_with("https:") {
|
|
||||||
s.into()
|
|
||||||
} else {
|
|
||||||
format!("http://{}", s).into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, StateData)]
|
#[derive(Clone, StateData)]
|
||||||
struct AppState {
|
pub struct AppState {
|
||||||
db: Arc<Mutex<PgConnection>>,
|
pub db: Arc<Mutex<PgConnection>>,
|
||||||
}
|
|
||||||
|
|
||||||
fn render_index(app_state: &AppState) -> String {
|
|
||||||
let db = app_state.db.lock().unwrap();
|
|
||||||
let today = Local::today().naive_local().and_hms(0, 0, 0);
|
|
||||||
let es = events
|
|
||||||
.filter(schema::events::dtstart.ge(&today))
|
|
||||||
.order_by(schema::events::dtstart.asc())
|
|
||||||
.then_order_by(schema::events::dtend.desc())
|
|
||||||
.load::<Event>(&*db)
|
|
||||||
.unwrap();
|
|
||||||
let days = group_by_day(&es);
|
|
||||||
|
|
||||||
let doc: DOMTree<String> = html!(
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>"Ticker"</title>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>"Ticker"</h1>
|
|
||||||
|
|
||||||
{ 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>
|
|
||||||
)) }
|
|
||||||
</div>)) }
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
);
|
|
||||||
format!("<DOCTYPE html>\n{}", doc.to_string())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn index(state: State) -> (State, Response<Body>) {
|
|
||||||
let message = {
|
|
||||||
let app_state = AppState::borrow_from(&state);
|
|
||||||
render_index(app_state)
|
|
||||||
};
|
|
||||||
let res = create_response(&state, StatusCode::OK, TEXT_HTML, message);
|
|
||||||
(state, res)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -145,7 +36,7 @@ fn main() {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
let router = build_router(chain, pipelines, |route| {
|
let router = build_router(chain, pipelines, |route| {
|
||||||
route.get("/").to(index);
|
route.get("/").to(index::index);
|
||||||
route.get("static/*").to_dir(
|
route.get("static/*").to_dir(
|
||||||
FileOptions::new(&"static")
|
FileOptions::new(&"static")
|
||||||
// TODO:
|
// TODO:
|
||||||
|
|
Loading…
Reference in New Issue