about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVincent Ambo <tazjin@gmail.com>2018-04-11T10·18+0200
committerVincent Ambo <tazjin@gmail.com>2018-04-11T10·18+0200
commit1cce37446b3dbc558ffe82b1b1728279dec92175 (patch)
tree76758a111a2d54c44c324e17a4f2abc858f04b8e
parentfe7e5e48b5702a0547b3008e06a1f0c04d88e3bf (diff)
refactor(handlers): Use rendering actor for page renders
This currently breaks error handling in page render flows. To fix it
properly, the database actor should return failable futures instead of
`Result<T>` wrapped in a future.
-rw-r--r--src/handlers.rs72
-rw-r--r--todo.org5
2 files changed, 31 insertions, 46 deletions
diff --git a/src/handlers.rs b/src/handlers.rs
index 3af8a8c40929..9732414b31cf 100644
--- a/src/handlers.rs
+++ b/src/handlers.rs
@@ -5,7 +5,7 @@
 //! the tera templates stored in the `/templates` directory in the
 //! project root.
 
-use actix::prelude::{Addr, Syn};
+use actix::prelude::*;
 use actix_web;
 use actix_web::*;
 use actix_web::middleware::{Started, Middleware, RequestSession};
@@ -15,9 +15,12 @@ use futures::Future;
 use models::*;
 use oidc::*;
 use tera;
+use render::*;
 
 type ConverseResponse = Box<Future<Item=HttpResponse, Error=ConverseError>>;
 
+const HTML: &'static str = "text/html";
+
 /// Represents the state carried by the web server actors.
 pub struct AppState {
     /// Address of the database actor
@@ -26,68 +29,47 @@ pub struct AppState {
     /// Address of the OIDC actor
     pub oidc: Addr<Syn, OidcExecutor>,
 
-    /// Compiled templates
-    pub tera: tera::Tera,
+    /// Address of the rendering actor
+    pub renderer: Addr<Syn, Renderer>,
 }
 
-/// This function renders an overview of threads into the default
-/// thread list template.
-fn render_threads(tpl: &tera::Tera, threads: Vec<Thread>) -> Result<HttpResponse> {
-    let mut ctx = tera::Context::new();
-    ctx.add("threads", &threads);
-    let body = tpl.render("index.html", &ctx)?;
-    Ok(HttpResponse::Ok().content_type("text/html").body(body))
-}
+// impl AppState {
+//     fn render_ok<M>(self, msg: M) -> ConverseResponse
+//         where M: Send + Message, Renderer: Handler<M> {
+//         self.renderer.send(msg);
+//         unimplemented!()
+//     }
+// }
 
 pub fn forum_index(state: State<AppState>) -> ConverseResponse {
     state.db.send(ListThreads)
+        .and_then(move |res| state.renderer.send(IndexPage { threads: res.unwrap() }))
         .from_err()
-        .and_then(move |res| match res {
-            Ok(threads) => Ok(render_threads(&state.tera, threads)?),
-            Err(err) => {
-                error!("Error loading threads: {}", err);
-                Ok(HttpResponse::InternalServerError().into())
-            }
-        })
+        .map(|res| HttpResponse::Ok().content_type(HTML).body(res.unwrap()))
         .responder()
 }
 
-/// This function renders a single forum thread into the default
-/// thread view.
-fn render_thread(tpl: &tera::Tera, thread: Thread, posts: Vec<Post>)
-                 -> Result<HttpResponse> {
-    let mut ctx = tera::Context::new();
-    ctx.add("thread", &thread);
-    ctx.add("posts", &posts);
-
-    let body = tpl.render("thread.html", &ctx)?;
-    Ok(HttpResponse::Ok()
-        .content_type("text/html")
-        .body(body))
-}
-
 /// This handler retrieves and displays a single forum thread.
 pub fn forum_thread(state: State<AppState>, thread_id: Path<i32>) -> ConverseResponse {
     let id = thread_id.into_inner();
     state.db.send(GetThread(id))
-        .from_err()
-        .and_then(move |res| match res {
-            Ok((thread, posts)) => Ok(render_thread(&state.tera, thread, posts)?),
-            Err(err) => {
-                error!("Error loading thread {}: {}", id, err);
-                Ok(HttpResponse::InternalServerError().into())
-            }
+        .and_then(move |res| {
+            let u = res.unwrap();
+            state.renderer.send(ThreadPage {
+                thread: u.0,
+                posts: u.1,
+            })
         })
+        .from_err()
+        .map(|res| HttpResponse::Ok().content_type(HTML).body(res.unwrap()))
         .responder()
 }
 
 /// This handler presents the user with the "New Thread" form.
-pub fn new_thread(state: State<AppState>) -> Result<HttpResponse> {
-    let ctx = tera::Context::new();
-    let body = state.tera.render("new-thread.html", &ctx)?;
-    Ok(HttpResponse::Ok()
-       .content_type("text/html")
-       .body(body))
+pub fn new_thread(state: State<AppState>) -> ConverseResponse {
+    state.renderer.send(NewThreadPage).from_err()
+        .map(|res| HttpResponse::Ok().content_type(HTML).body(res.unwrap()))
+        .responder()
 }
 
 #[derive(Deserialize)]
diff --git a/todo.org b/todo.org
index af8fb223a2f3..63ad4ebb0645 100644
--- a/todo.org
+++ b/todo.org
@@ -1,4 +1,7 @@
+* DONE Pin *-versions in cargo.toml
 * TODO Configurable number of DB workers
-* TODO Pin *-versions in cargo.toml
 * TODO Match certain types of Diesel errors (esp. for "not found")
 * TODO Sketch out categories vs. tags system
+* TODO Markdown support
+* TODO Quote button
+* TODO Multiquote buttons