Add handlers for smart-case, spaced node queries
This commit is contained in:
parent
435cf4d18f
commit
be6578bee2
5 changed files with 53 additions and 22 deletions
|
|
@ -2,7 +2,14 @@ use axum::{routing::get, Router};
|
|||
|
||||
use crate::{syntax::serial::Format, types::Graph};
|
||||
|
||||
mod handlers;
|
||||
mod handlers {
|
||||
pub mod graph;
|
||||
pub mod template;
|
||||
pub mod raw;
|
||||
pub mod navigation;
|
||||
pub mod fixed;
|
||||
pub mod error;
|
||||
}
|
||||
|
||||
pub fn new(graph: &Graph) -> Router {
|
||||
let mut router = Router::default()
|
||||
|
|
@ -11,6 +18,7 @@ pub fn new(graph: &Graph) -> Router {
|
|||
get(|| handlers::navigation::page("index.html"))
|
||||
.post(handlers::navigation::search),
|
||||
)
|
||||
.route("/redirect", get(handlers::navigation::redirect))
|
||||
.route(
|
||||
"/static/style.css",
|
||||
get(|| handlers::fixed::file("./static/style.css", "text/css")),
|
||||
|
|
@ -38,6 +46,8 @@ pub fn new(graph: &Graph) -> Router {
|
|||
}
|
||||
|
||||
if graph.meta.config.raw {
|
||||
router = router
|
||||
.route("/data", get(|| handlers::navigation::page("data.html")));
|
||||
if graph.meta.config.raw_json {
|
||||
router = router.route(
|
||||
"/graph/json",
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
pub mod graph;
|
||||
pub mod template;
|
||||
pub mod raw;
|
||||
pub mod navigation;
|
||||
pub mod fixed;
|
||||
pub mod error;
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
use crate::prelude::*;
|
||||
use axum::response::IntoResponse as _;
|
||||
use axum::{body::Body, extract::Path, http::Response, response::Redirect};
|
||||
|
||||
|
|
@ -8,9 +7,12 @@ use crate::{syntax::serial::populate_graph, router::handlers, types::Node};
|
|||
|
||||
pub async fn node(Path(id): Path<String>) -> Response<Body> {
|
||||
let graph = populate_graph();
|
||||
let empty_node = Node::new(Some(format!("Could not find node ID {id}.")));
|
||||
let (node_match, exact) = graph.find_node(&id);
|
||||
let node = node_match.unwrap_or(empty_node.clone());
|
||||
let result = graph.find_node(&id);
|
||||
let nodes: Vec<Node> = graph.nodes.into_values().collect();
|
||||
let not_found = result.node.is_none();
|
||||
let node = result
|
||||
.node
|
||||
.unwrap_or(Node::new(Some(format!("Could not find node ID {id}."))));
|
||||
|
||||
if !node.redirect.is_empty() {
|
||||
return Redirect::permanent(
|
||||
|
|
@ -19,20 +21,18 @@ pub async fn node(Path(id): Path<String>) -> Response<Body> {
|
|||
.into_response();
|
||||
}
|
||||
|
||||
if !exact {
|
||||
log!("Redirecting non-exact match to {}", node.id);
|
||||
if result.redirect {
|
||||
return Redirect::permanent(format!("/node/{}", node.id).as_str())
|
||||
.into_response();
|
||||
}
|
||||
|
||||
let mut context = tera::Context::default();
|
||||
context.insert("node", &node);
|
||||
context.insert("nodes", &nodes);
|
||||
context.insert("text", &content::parse(&node.text, &graph.meta.config));
|
||||
context.insert("incoming", &graph.incoming.get(&id));
|
||||
context.insert("config", &graph.meta.config);
|
||||
|
||||
let not_found = node == empty_node;
|
||||
|
||||
handlers::template::by_filename(
|
||||
"node.html",
|
||||
&context,
|
||||
|
|
|
|||
|
|
@ -25,6 +25,10 @@ pub async fn search(Form(query): Form<Query>) -> Redirect {
|
|||
Redirect::permanent(format!("/node/{}", query.node).as_str())
|
||||
}
|
||||
|
||||
pub async fn redirect(Form(query): Form<Query>) -> Redirect {
|
||||
Redirect::permanent(format!("/node/{}", query.node).as_str())
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
pub struct Query {
|
||||
node: String,
|
||||
|
|
@ -63,4 +67,13 @@ mod tests {
|
|||
let response = page("HBvcwqT8wLk6hxk1GdvNcEzJ6IiZ2Fod").await;
|
||||
assert_eq!(response.status(), StatusCode::INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn id_redirect() {
|
||||
let query = Form(Query {
|
||||
node: String::from("ancHOr syntaX"),
|
||||
});
|
||||
let response = search(query).await;
|
||||
assert!(response.status_code() == StatusCode::PERMANENT_REDIRECT);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
28
src/types.rs
28
src/types.rs
|
|
@ -121,6 +121,11 @@ fn mk8() -> u16 {
|
|||
8
|
||||
}
|
||||
|
||||
pub struct QueryResult {
|
||||
pub node: Option<Node>,
|
||||
pub redirect: bool,
|
||||
}
|
||||
|
||||
impl Graph {
|
||||
pub fn new(message: Option<&str>) -> Graph {
|
||||
Graph {
|
||||
|
|
@ -136,17 +141,26 @@ impl Graph {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn find_node(&self, query: &str) -> (Option<Node>, bool) {
|
||||
pub fn find_node(&self, query: &str) -> QueryResult {
|
||||
let collapsed_query = query.trim().replace(" ", "");
|
||||
|
||||
if let Some(exact_match) = self.nodes.get(query) {
|
||||
(Some(exact_match.clone()), true)
|
||||
QueryResult {
|
||||
node: Some(exact_match.clone()),
|
||||
redirect: false,
|
||||
}
|
||||
} else if let Some(lower_key) =
|
||||
self.lowercase_keymap.get(&collapsed_query)
|
||||
self.lowercase_keymap.get(&collapsed_query.to_lowercase())
|
||||
{
|
||||
(self.nodes.get(lower_key).cloned(), false)
|
||||
QueryResult {
|
||||
node: self.nodes.get(lower_key).cloned(),
|
||||
redirect: true,
|
||||
}
|
||||
} else {
|
||||
(None, false)
|
||||
QueryResult {
|
||||
node: None,
|
||||
redirect: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -162,7 +176,7 @@ impl Node {
|
|||
title: "Not Found".to_string(),
|
||||
text: match message {
|
||||
Some(s) => s,
|
||||
None => "Node is empty, missing or wasn't found.".to_string(),
|
||||
None => "Node not found.".to_string(),
|
||||
},
|
||||
connections: None,
|
||||
links: vec![],
|
||||
|
|
@ -233,7 +247,7 @@ mod tests {
|
|||
#[test]
|
||||
fn empty_node_message() {
|
||||
let node = Node::new(None);
|
||||
assert_eq!(node.text, "Node is empty, missing or wasn't found.");
|
||||
assert_eq!(node.text, "Node not found.");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue