diff --git a/src/handlers.rs b/src/handlers.rs index 33f33decc..02ff99394 100644 --- a/src/handlers.rs +++ b/src/handlers.rs @@ -176,6 +176,22 @@ pub fn reply_thread(state: State, .responder() } +/// This handler executes a full-text search on the forum database and +/// displays the results to the user. +pub fn search_forum(state: State, + query: Form) -> ConverseResponse { + let query_string = query.0.query.clone(); + state.db.send(query.0) + .flatten() + .and_then(move |results| state.renderer.send(SearchResultPage { + results, + query: query_string, + }).from_err()) + .flatten() + .map(|res| HttpResponse::Ok().content_type(HTML).body(res)) + .responder() +} + /// This handler initiates an OIDC login. pub fn login(state: State) -> ConverseResponse { state.oidc.send(GetLoginUrl) diff --git a/src/main.rs b/src/main.rs index 9f4eea03f..92eeca48d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -153,6 +153,7 @@ fn main() { .resource("/thread/submit", |r| r.method(Method::POST).with3(submit_thread)) .resource("/thread/reply", |r| r.method(Method::POST).with3(reply_thread)) .resource("/thread/{id}", |r| r.method(Method::GET).with2(forum_thread)) + .resource("/search", |r| r.method(Method::POST).with2(search_forum)) .resource("/oidc/login", |r| r.method(Method::GET).with(login)) .resource("/oidc/callback", |r| r.method(Method::POST).with3(callback)); diff --git a/src/models.rs b/src/models.rs index 927a78513..dfadd53fd 100644 --- a/src/models.rs +++ b/src/models.rs @@ -74,7 +74,7 @@ pub struct NewPost { /// This struct models the response of a full-text search query. It /// does not use a table/schema definition struct like the other /// tables, as no table of this type actually exists. -#[derive(QueryableByName, Debug)] +#[derive(QueryableByName, Debug, Serialize)] pub struct SearchResult { #[sql_type = "Integer"] pub post_id: i32, diff --git a/src/render.rs b/src/render.rs index 186b96d24..537cab59d 100644 --- a/src/render.rs +++ b/src/render.rs @@ -175,3 +175,24 @@ impl Handler for Renderer { Ok(self.tera.render("new-thread.html", &ctx)?) } } + +/// Message used to render search results +pub struct SearchResultPage { + pub query: String, + pub results: Vec, +} + +impl Message for SearchResultPage { + type Result = Result; +} + +impl Handler for Renderer { + type Result = Result; + + fn handle(&mut self, msg: SearchResultPage, _: &mut Self::Context) -> Self::Result { + let mut ctx = Context::new(); + ctx.add("query", &msg.query); + ctx.add("results", &msg.results); + Ok(self.tera.render("search.html", &ctx)?) + } +} diff --git a/templates/index.html b/templates/index.html index 35cfeba05..263c8828a 100644 --- a/templates/index.html +++ b/templates/index.html @@ -14,9 +14,9 @@

Converse

-
- - + + + New thread
diff --git a/templates/search.html b/templates/search.html new file mode 100644 index 000000000..95384b1ca --- /dev/null +++ b/templates/search.html @@ -0,0 +1,48 @@ + + + + + + + + + Converse Index + + +
+ +
+
+
+
+

Search results for '{{ query }}':

+
+
+ +
+ +