diff --git a/src/changes_resource.rs b/src/changes_resource.rs new file mode 100644 index 0000000..1befd1a --- /dev/null +++ b/src/changes_resource.rs @@ -0,0 +1,82 @@ +use futures::{self, Future}; +use hyper; +use hyper::header::ContentType; +use hyper::server::*; + +use assets::StyleCss; +use mimes::*; +use site::Layout; +use state::State; +use web::{Resource, ResponseFuture}; + +pub struct ChangesResource { + state: State, + before: Option, +} + +impl ChangesResource { + pub fn new(state: State, before: Option) -> Self { + Self { state, before } + } +} + +impl Resource for ChangesResource { + fn allow(&self) -> Vec { + use hyper::Method::*; + vec![Options, Head, Get] + } + + fn head(&self) -> ResponseFuture { + Box::new(futures::finished(Response::new() + .with_status(hyper::StatusCode::Ok) + .with_header(ContentType(TEXT_HTML.clone())) + )) + } + + fn get(self: Box) -> ResponseFuture { + use chrono::{TimeZone, Local}; + + struct Row { + article_id: i32, + revision: i32, + created: String, + + slug: String, + title: String, + + latest: bool, + } + + #[derive(BartDisplay)] + #[template="templates/changes.html"] + struct Template<'a> { + changes: &'a [Row], + } + + let data = self.state.get_article_revision_stubs(self.before, 30); + let head = self.head(); + + Box::new(data.join(head) + .and_then(move |(data, head)| { + use std::iter::Iterator; + + let changes = &data.into_iter().map(|x| { + Row { + article_id: x.article_id, + revision: x.revision, + created: Local.from_utc_datetime(&x.created).to_string(), + slug: x.slug, + title: x.title, + latest: x.latest, + } + }).collect::>(); + + Ok(head + .with_body(Layout { + title: "Changes", + body: &Template { changes }, + style_css_checksum: StyleCss::checksum(), + }.to_string())) + })) + } +} diff --git a/src/main.rs b/src/main.rs index dafed6c..d8775e6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -26,6 +26,7 @@ use std::net::SocketAddr; mod article_redirect_resource; mod article_resource; mod assets; +mod changes_resource; mod db; mod mimes; mod models; diff --git a/src/models.rs b/src/models.rs index 6064986..033e58c 100644 --- a/src/models.rs +++ b/src/models.rs @@ -14,3 +14,17 @@ pub struct ArticleRevision { pub latest: bool, } + +#[derive(Debug, Queryable)] +pub struct ArticleRevisionStub { + pub sequence_number: i32, + + pub article_id: i32, + pub revision: i32, + pub created: chrono::NaiveDateTime, + + pub slug: String, + pub title: String, + + pub latest: bool, +} diff --git a/src/state.rs b/src/state.rs index bf4effd..ab70b97 100644 --- a/src/state.rs +++ b/src/state.rs @@ -100,6 +100,35 @@ impl State { }) } + pub fn get_article_revision_stubs(&self, before: Option, limit: i32) -> CpuFuture, Error> { + let connection_pool = self.connection_pool.clone(); + + self.cpu_pool.spawn_fn(move || { + use schema::article_revisions; + + let query = article_revisions::table + .order(article_revisions::sequence_number.desc()) + .limit(limit as i64) + .select(( + article_revisions::sequence_number, + article_revisions::article_id, + article_revisions::revision, + article_revisions::created, + article_revisions::slug, + article_revisions::title, + article_revisions::latest, + )) + .into_boxed(); + + let query = match before { + Some(before) => query.filter(article_revisions::sequence_number.lt(before)), + None => query + }; + + Ok(query.load(&*connection_pool.get()?)?) + }) + } + pub fn lookup_slug(&self, slug: String) -> CpuFuture { #[derive(Queryable)] struct ArticleRevisionStub { diff --git a/src/wiki_lookup.rs b/src/wiki_lookup.rs index 894e6ac..a1f6ca2 100644 --- a/src/wiki_lookup.rs +++ b/src/wiki_lookup.rs @@ -17,6 +17,16 @@ lazy_static! { static ref LOOKUP_MAP: HashMap = { let mut lookup_map = HashMap::new(); + use changes_resource::ChangesResource; + + lookup_map.insert( + "/_changes".to_string(), + Box::new(|state: &State| + // TODO Use query arguments to fill in the `before` parameter below + Box::new(ChangesResource::new(state.clone(), None)) as BoxResource + ) as ResourceFn + ); + lookup_map.insert( "/_new".to_string(), Box::new(|state: &State| diff --git a/templates/changes.html b/templates/changes.html new file mode 100644 index 0000000..1ee0698 --- /dev/null +++ b/templates/changes.html @@ -0,0 +1,37 @@ +
+
+

Changes

+
+ +
+ + + + + + + + + {{#changes}} + + + + + + + + {{/changes}} +
TitleSlugArticle IDRevisionCreated
+ {{#.latest?}}{{/.latest}} + {{.title}} + {{#.latest?}}{{/.latest}} + {{#.slug.is_empty()?}}/{{/.slug.is_empty()}}{{.slug}}{{.article_id}}{{.revision}}{{.created}}
+
+
+ +