Refactor generation of links from slugs
This fixes a bug where the cancel-link on the front page would be to "" rather than "."
This commit is contained in:
parent
4ca748f180
commit
1bdc21039b
6 changed files with 28 additions and 52 deletions
|
@ -1,5 +1,13 @@
|
||||||
use chrono;
|
use chrono;
|
||||||
|
|
||||||
|
fn slug_link(slug: &str) -> &str {
|
||||||
|
if slug.is_empty() {
|
||||||
|
"."
|
||||||
|
} else {
|
||||||
|
slug
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Queryable)]
|
#[derive(Debug, Queryable)]
|
||||||
pub struct ArticleRevision {
|
pub struct ArticleRevision {
|
||||||
pub sequence_number: i32,
|
pub sequence_number: i32,
|
||||||
|
@ -18,13 +26,7 @@ pub struct ArticleRevision {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ArticleRevision {
|
impl ArticleRevision {
|
||||||
pub fn link(&self) -> &str {
|
pub fn link(&self) -> &str { slug_link(&self.slug) }
|
||||||
if self.slug.is_empty() {
|
|
||||||
"."
|
|
||||||
} else {
|
|
||||||
&self.slug
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Queryable)]
|
#[derive(Debug, Queryable)]
|
||||||
|
@ -43,9 +45,17 @@ pub struct ArticleRevisionStub {
|
||||||
pub author: Option<String>,
|
pub author: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ArticleRevisionStub {
|
||||||
|
pub fn link(&self) -> &str { slug_link(&self.slug) }
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Queryable, Serialize)]
|
#[derive(Debug, Queryable, Serialize)]
|
||||||
pub struct SearchResult {
|
pub struct SearchResult {
|
||||||
pub title: String,
|
pub title: String,
|
||||||
pub snippet: String,
|
pub snippet: String,
|
||||||
pub slug: String,
|
pub slug: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SearchResult {
|
||||||
|
pub fn link(&self) -> &str { slug_link(&self.slug) }
|
||||||
|
}
|
||||||
|
|
|
@ -106,7 +106,7 @@ impl Resource for ArticleResource {
|
||||||
data.author.as_ref().map(|x| &**x)
|
data.author.as_ref().map(|x| &**x)
|
||||||
)),
|
)),
|
||||||
edit: self.edit,
|
edit: self.edit,
|
||||||
cancel_url: Some(&data.slug),
|
cancel_url: Some(data.link()),
|
||||||
title: &data.title,
|
title: &data.title,
|
||||||
raw: &data.body,
|
raw: &data.body,
|
||||||
rendered: render_markdown(&data.body),
|
rendered: render_markdown(&data.body),
|
||||||
|
|
|
@ -6,7 +6,7 @@ use serde_json;
|
||||||
use serde_urlencoded;
|
use serde_urlencoded;
|
||||||
|
|
||||||
use mimes::*;
|
use mimes::*;
|
||||||
use models;
|
use models::SearchResult;
|
||||||
use site::Layout;
|
use site::Layout;
|
||||||
use state::State;
|
use state::State;
|
||||||
use web::{Resource, ResponseFuture};
|
use web::{Resource, ResponseFuture};
|
||||||
|
@ -148,33 +148,16 @@ impl Resource for SearchResource {
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct JsonResponse<'a> {
|
struct JsonResponse<'a> {
|
||||||
query: &'a str,
|
query: &'a str,
|
||||||
hits: &'a [models::SearchResult],
|
hits: &'a [SearchResult],
|
||||||
prev: Option<String>,
|
prev: Option<String>,
|
||||||
next: Option<String>,
|
next: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Hit<'a> {
|
|
||||||
index: usize,
|
|
||||||
slug: &'a str,
|
|
||||||
title: &'a str,
|
|
||||||
snippet: &'a str,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Hit<'a> {
|
|
||||||
fn link(&self) -> &'a str {
|
|
||||||
if self.slug == "" {
|
|
||||||
"."
|
|
||||||
} else {
|
|
||||||
self.slug
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(BartDisplay)]
|
#[derive(BartDisplay)]
|
||||||
#[template="templates/search.html"]
|
#[template="templates/search.html"]
|
||||||
struct Template<'a> {
|
struct Template<'a> {
|
||||||
query: &'a str,
|
query: &'a str,
|
||||||
hits: &'a [Hit<'a>],
|
hits: &'a [(usize, &'a SearchResult)],
|
||||||
prev: Option<String>,
|
prev: Option<String>,
|
||||||
next: Option<String>,
|
next: Option<String>,
|
||||||
}
|
}
|
||||||
|
@ -223,12 +206,6 @@ impl Resource for SearchResource {
|
||||||
query: self.query.as_ref().map(|x| &**x).unwrap_or(""),
|
query: self.query.as_ref().map(|x| &**x).unwrap_or(""),
|
||||||
hits: &data.iter()
|
hits: &data.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, result)| Hit {
|
|
||||||
index: i,
|
|
||||||
slug: &result.slug,
|
|
||||||
title: &result.title,
|
|
||||||
snippet: &result.snippet,
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
prev,
|
prev,
|
||||||
next,
|
next,
|
||||||
|
|
|
@ -4,6 +4,7 @@ use hyper::header::ContentType;
|
||||||
use hyper::server::*;
|
use hyper::server::*;
|
||||||
|
|
||||||
use mimes::*;
|
use mimes::*;
|
||||||
|
use models::ArticleRevisionStub;
|
||||||
use site::Layout;
|
use site::Layout;
|
||||||
use state::State;
|
use state::State;
|
||||||
use web::{Resource, ResponseFuture};
|
use web::{Resource, ResponseFuture};
|
||||||
|
@ -35,12 +36,7 @@ impl Resource for SitemapResource {
|
||||||
#[derive(BartDisplay)]
|
#[derive(BartDisplay)]
|
||||||
#[template="templates/sitemap.html"]
|
#[template="templates/sitemap.html"]
|
||||||
struct Template<'a> {
|
struct Template<'a> {
|
||||||
articles: &'a [ArticleReference],
|
articles: &'a [ArticleRevisionStub],
|
||||||
}
|
|
||||||
|
|
||||||
struct ArticleReference {
|
|
||||||
link: String,
|
|
||||||
title: String,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let data = self.state.get_latest_article_revision_stubs();
|
let data = self.state.get_latest_article_revision_stubs();
|
||||||
|
@ -48,20 +44,13 @@ impl Resource for SitemapResource {
|
||||||
|
|
||||||
Box::new(data.join(head)
|
Box::new(data.join(head)
|
||||||
.and_then(move |(articles, head)| {
|
.and_then(move |(articles, head)| {
|
||||||
use std::iter::Iterator;
|
|
||||||
|
|
||||||
let articles = &articles.into_iter().map(|x| {
|
|
||||||
ArticleReference {
|
|
||||||
link: if x.slug.is_empty() { ".".to_owned() } else { x.slug },
|
|
||||||
title: x.title,
|
|
||||||
}
|
|
||||||
}).collect::<Vec<_>>();
|
|
||||||
|
|
||||||
Ok(head
|
Ok(head
|
||||||
.with_body(Layout {
|
.with_body(Layout {
|
||||||
base: None, // Hmm, should perhaps accept `base` as argument
|
base: None, // Hmm, should perhaps accept `base` as argument
|
||||||
title: "Sitemap",
|
title: "Sitemap",
|
||||||
body: &Template { articles },
|
body: &Template {
|
||||||
|
articles: &articles,
|
||||||
|
},
|
||||||
}.to_string()))
|
}.to_string()))
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
<ul class="search-results default-keyboard-focus-control">
|
<ul class="search-results default-keyboard-focus-control">
|
||||||
{{#hits}}
|
{{#hits}}
|
||||||
<li class="search-result"><a data-focusindex="{{.index}}" class="link" href="{{.link()}}"><p class="title">{{.title}}</p><p class="snippet">{{.snippet}}</p></a></li>
|
<li class="search-result"><a data-focusindex="{{.0}}" class="link" href="{{.1.link()}}"><p class="title">{{.1.title}}</p><p class="snippet">{{.1.snippet}}</p></a></li>
|
||||||
{{/hits}}
|
{{/hits}}
|
||||||
</ul>
|
</ul>
|
||||||
{{/hits}}
|
{{/hits}}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<article>
|
<article>
|
||||||
<ul class="dense"
|
<ul class="dense"
|
||||||
{{#articles}}
|
{{#articles}}
|
||||||
><li><a href="{{.link}}">{{.title}}</a></li
|
><li><a href="{{.link()}}">{{.title}}</a></li
|
||||||
{{/articles}}
|
{{/articles}}
|
||||||
></ul>
|
></ul>
|
||||||
</article>
|
</article>
|
||||||
|
|
Loading…
Reference in a new issue