Get article revisions from database during diff lookup.

Diffs for missing revisions now cause 404-errors
This commit is contained in:
Magnus Hoff 2017-11-06 15:45:11 +01:00
parent 2e5b549ea8
commit bfd2acda4f
2 changed files with 38 additions and 35 deletions

View file

@ -1,20 +1,20 @@
use std::{self, fmt}; use std::fmt;
use diff; use diff;
use futures::{self, Future}; use futures::{self, Future};
use futures::future::done; use futures::future::{finished, done};
use hyper; use hyper;
use hyper::header::ContentType; use hyper::header::ContentType;
use hyper::server::*; use hyper::server::*;
use serde_urlencoded; use serde_urlencoded;
use mimes::*; use mimes::*;
use models::ArticleRevision;
use site::Layout; use site::Layout;
use state::State; use state::State;
use web::{Resource, ResponseFuture}; use web::{Resource, ResponseFuture};
type BoxResource = Box<Resource + Sync + Send>; type BoxResource = Box<Resource + Sync + Send>;
type Error = Box<std::error::Error + Send + Sync>;
#[derive(Clone)] #[derive(Clone)]
pub struct DiffLookup { pub struct DiffLookup {
@ -47,31 +47,35 @@ impl DiffLookup {
pub fn lookup(&self, article_id: u32, query: Option<&str>) -> Box<Future<Item=Option<BoxResource>, Error=::web::Error>> { pub fn lookup(&self, article_id: u32, query: Option<&str>) -> Box<Future<Item=Option<BoxResource>, Error=::web::Error>> {
let state = self.state.clone(); let state = self.state.clone();
Box::new(done((|| -> Result<Option<BoxResource>, ::web::Error> { Box::new(done(
let params: QueryParameters = serde_urlencoded::from_str(query.unwrap_or(""))?; serde_urlencoded::from_str(query.unwrap_or(""))
.map_err(Into::into)
).and_then(move |params: QueryParameters| {
let from = state.get_article_revision(article_id as i32, params.from as i32);
let to = state.get_article_revision(article_id as i32, params.to as i32);
Ok(Some(Box::new(DiffResource::new(state, article_id, params.from, params.to)))) finished(state).join3(from, to)
}()))) }).and_then(move |(state, from, to)| {
match (from, to) {
(Some(from), Some(to)) =>
Ok(Some(Box::new(DiffResource::new(state, from, to)) as BoxResource)),
_ =>
Ok(None),
}
}))
} }
} }
pub struct DiffResource { pub struct DiffResource {
state: State, state: State,
article_id: u32, from: ArticleRevision,
from: u32, to: ArticleRevision,
to: u32,
} }
impl DiffResource { impl DiffResource {
pub fn new(state: State, article_id: u32, from: u32, to: u32) -> Self { pub fn new(state: State, from: ArticleRevision, to: ArticleRevision) -> Self {
Self { state, article_id, from, to } assert_eq!(from.article_id, to.article_id);
} Self { state, from, to }
fn query_args(&self) -> QueryParameters {
QueryParameters {
from: self.from.clone(),
to: self.to.clone(),
}
} }
} }
@ -92,6 +96,8 @@ impl Resource for DiffResource {
#[derive(BartDisplay)] #[derive(BartDisplay)]
#[template = "templates/diff.html"] #[template = "templates/diff.html"]
struct Template<'a> { struct Template<'a> {
consecutive: bool,
article_id: u32,
title: &'a [Diff<char>], title: &'a [Diff<char>],
lines: &'a [Diff<&'a str>], lines: &'a [Diff<&'a str>],
} }
@ -103,22 +109,18 @@ impl Resource for DiffResource {
added: Option<T>, added: Option<T>,
} }
let from = self.state.get_article_revision(self.article_id as i32, self.from as i32);
let to = self.state.get_article_revision(self.article_id as i32, self.to as i32);
let head = self.head(); let head = self.head();
Box::new(head.join3(from, to) Box::new(head
.and_then(move |(head, from, to)| { .and_then(move |head| {
Ok(head Ok(head
.with_body(Layout { .with_body(Layout {
base: Some("../"), // Hmm, should perhaps accept `base` as argument base: Some("../"), // Hmm, should perhaps accept `base` as argument
title: "Difference", title: "Difference",
body: &Template { body: &Template {
title: &diff::chars( consecutive: self.to.revision - self.from.revision == 1,
from.as_ref().map(|x| &*x.title).unwrap_or(""), article_id: self.from.article_id as u32,
to.as_ref().map(|x| &*x.title).unwrap_or("") title: &diff::chars(&self.from.title, &self.to.title)
)
.into_iter() .into_iter()
.map(|x| match x { .map(|x| match x {
diff::Result::Left(x) => Diff { removed: Some(x), ..Default::default() }, diff::Result::Left(x) => Diff { removed: Some(x), ..Default::default() },
@ -126,10 +128,7 @@ impl Resource for DiffResource {
diff::Result::Right(x) => Diff { added: Some(x), ..Default::default() }, diff::Result::Right(x) => Diff { added: Some(x), ..Default::default() },
}) })
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
lines: &diff::lines( lines: &diff::lines(&self.from.body, &self.to.body)
from.as_ref().map(|x| &*x.body).unwrap_or(""),
to.as_ref().map(|x| &*x.body).unwrap_or("")
)
.into_iter() .into_iter()
.map(|x| match x { .map(|x| match x {
diff::Result::Left(x) => Diff { removed: Some(x), ..Default::default() }, diff::Result::Left(x) => Diff { removed: Some(x), ..Default::default() },

View file

@ -1,7 +1,11 @@
<div class="container"> <div class="container">
<header>
<h1>Difference</h1> <div class="notice">
</header> <p>
You are viewing the difference between two {{#consecutive?}}consecutive{{/consecutive}}
revisions of <a href="_by_id/{{article_id}}">this article</a>.
</p>
</div>
<header> <header>
<h1>{{#title}}{{#.removed}}<span class="removed">{{.}}</span>{{/.removed}}{{#.same}}{{.}}{{/.same}}{{#.added}}<span class="added">{{.}}</span>{{/.added}}{{/title}}</h1> <h1>{{#title}}{{#.removed}}<span class="removed">{{.}}</span>{{/.removed}}{{#.same}}{{.}}{{/.same}}{{#.added}}<span class="added">{{.}}</span>{{/.added}}{{/title}}</h1>