redirect to detail if there’s only a single result
This commit is contained in:
parent
8691d3c685
commit
2056b9b9f2
36
Cargo.lock
generated
36
Cargo.lock
generated
@ -57,12 +57,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "actix-macros"
|
||||
version = "0.2.3"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "465a6172cf69b960917811022d8f29bc0b7fa1398bc4f78b3c466673db1213b6"
|
||||
checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"syn 2.0.27",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -359,9 +359,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.8.1"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
|
||||
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||
|
||||
[[package]]
|
||||
name = "encoding_rs"
|
||||
@ -741,9 +741,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.31"
|
||||
version = "1.0.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5fe8a65d69dd0808184ebb5f836ab526bb259db23c657efa38711b1072ee47f0"
|
||||
checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
@ -839,9 +839,9 @@ checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
@ -851,29 +851,29 @@ checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.171"
|
||||
version = "1.0.177"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "30e27d1e4fd7659406c492fd6cfaf2066ba8773de45ca75e855590f856dc34a9"
|
||||
checksum = "63ba2516aa6bf82e0b19ca8b50019d52df58455d3cf9bdaf6315225fdd0c560a"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.171"
|
||||
version = "1.0.177"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "389894603bd18c46fa56231694f8d827779c0951a667087194cf9de94ed24682"
|
||||
checksum = "401797fe7833d72109fedec6bfcbe67c0eed9b99772f26eb8afd261f0abc6fd3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.26",
|
||||
"syn 2.0.27",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.103"
|
||||
version = "1.0.104"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d03b412469450d4404fe8499a268edd7f8b79fecb074b0d812ad64ca21f4031b"
|
||||
checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
@ -950,9 +950,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.26"
|
||||
version = "2.0.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45c3457aacde3c65315de5031ec191ce46604304d2446e803d71ade03308d970"
|
||||
checksum = "b60f673f44a8255b9c8c657daf66a596d435f2da81a555b06dc644d080ba45e0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
10
Cargo.toml
10
Cargo.toml
@ -6,11 +6,11 @@ edition = "2021"
|
||||
[dependencies]
|
||||
serde_json = "1.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
nom = "7.1.3"
|
||||
actix-web = { version = "4.3.0", default_features = false, features = ["macros"] }
|
||||
itertools = "0.11.0"
|
||||
time = { version = "0.3.17", features = ["serde", "serde-human-readable"] }
|
||||
regex = { version = "1.7.1", default_features = false, features = ["std"] }
|
||||
nom = "7.1"
|
||||
actix-web = { version = "4.3", default_features = false, features = ["macros"] }
|
||||
itertools = "0.11"
|
||||
time = { version = "0.3", features = ["serde", "serde-human-readable"] }
|
||||
regex = { version = "1.7", default_features = false, features = ["std"] }
|
||||
|
||||
[dev-dependencies]
|
||||
test-case = "3.1"
|
||||
|
@ -66,7 +66,7 @@ pub struct Set {
|
||||
impl Card {
|
||||
pub fn extended_info(&self) -> Result<String, fmt::Error> {
|
||||
let mut s = String::with_capacity(1000);
|
||||
write!(s, "<p><a href=\"https://db.ygorganization.com/search#card:{}\">Rulings</a> – <a href=\"https://yugipedia.com/wiki/{}\">Yugipedia</a></p>", &self.name, &self.name.replace(' ', "_"))?;
|
||||
write!(s, "<p><a href=\"https://db.ygorganization.com/search#card:{}\">Rulings</a> – <a href=\"https://yugipedia.com/wiki/{}\">Yugipedia</a></p>", &self.name, &self.id)?;
|
||||
s.push_str("<h3>Printings:</h3>");
|
||||
for printing in &self.card_sets {
|
||||
write!(s, "{}: {} ({})", printing.set_name, printing.set_code, printing.set_rarity)?;
|
||||
|
70
src/main.rs
70
src/main.rs
@ -82,6 +82,12 @@ struct Query {
|
||||
q: String,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum TargetPage {
|
||||
Data(PageData),
|
||||
Redirect(String),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct PageData {
|
||||
description: String,
|
||||
@ -118,7 +124,7 @@ async fn search(q: Option<Either<web::Query<Query>, web::Form<Query>>>) -> AnyRe
|
||||
let mut res = String::with_capacity(10_000);
|
||||
let data = match q {
|
||||
Some(q) => compute_results(q)?,
|
||||
None => PageData {
|
||||
None => TargetPage::Data(PageData {
|
||||
title: "YGO card search".to_owned(),
|
||||
description: "Enter a query above to search".to_owned(),
|
||||
query: None,
|
||||
@ -126,10 +132,15 @@ async fn search(q: Option<Either<web::Query<Query>, web::Form<Query>>>) -> AnyRe
|
||||
<p>Enter a query above to search or read the <a href=\"/help\">query syntax</a> for more information.</p>\
|
||||
<p>The source code is available <a href=\"https://git.kageru.moe/kageru/aro\">on Gitea</a>.</p>"
|
||||
.to_owned(),
|
||||
},
|
||||
}),
|
||||
};
|
||||
add_data(&mut res, &data)?;
|
||||
Ok(HttpResponse::Ok().insert_header(header::ContentType::html()).body(res))
|
||||
match data {
|
||||
TargetPage::Data(data) => {
|
||||
add_data(&mut res, &data)?;
|
||||
Ok(HttpResponse::Ok().insert_header(header::ContentType::html()).body(res))
|
||||
}
|
||||
TargetPage::Redirect(target) => Ok(HttpResponse::Found().insert_header((header::LOCATION, target)).finish()),
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/card/{id}")]
|
||||
@ -187,18 +198,18 @@ fn add_searchbox(res: &mut String, query: &Option<String>) -> std::fmt::Result {
|
||||
)
|
||||
}
|
||||
|
||||
fn compute_results(raw_query: String) -> AnyResult<PageData> {
|
||||
fn compute_results(raw_query: String) -> AnyResult<TargetPage> {
|
||||
let mut body = String::with_capacity(10_000);
|
||||
let (raw_filters, query) = match parser::parse_filters(raw_query.trim()) {
|
||||
Ok(q) => q,
|
||||
Err(e) => {
|
||||
let s = format!("Could not parse query: {e:?}");
|
||||
return Ok(PageData {
|
||||
return Ok(TargetPage::Data(PageData {
|
||||
description: s.clone(),
|
||||
query: Some(raw_query),
|
||||
body: s,
|
||||
title: "YGO Card Database".to_owned(),
|
||||
});
|
||||
}));
|
||||
}
|
||||
};
|
||||
let now = Instant::now();
|
||||
@ -210,32 +221,35 @@ fn compute_results(raw_query: String) -> AnyResult<PageData> {
|
||||
.collect();
|
||||
let readable_query = format!("Showing {} results where {}", matches.len(), raw_filters.iter().map(|f| f.to_string()).join(" and "),);
|
||||
write!(body, "<span class=\"meta\">{readable_query} (took {:?})</span>", now.elapsed())?;
|
||||
if matches.is_empty() {
|
||||
return Ok(PageData {
|
||||
match matches[..] {
|
||||
[] => Ok(TargetPage::Data(PageData {
|
||||
description: readable_query,
|
||||
query: Some(raw_query),
|
||||
body,
|
||||
title: "No results - YGO Card Database".to_owned(),
|
||||
});
|
||||
})),
|
||||
[card] => Ok(TargetPage::Redirect(format!("/card/{}", card.id))),
|
||||
ref cards => {
|
||||
body.push_str("<div style=\"display: flex; flex-wrap: wrap;\">");
|
||||
for card in cards {
|
||||
write!(
|
||||
body,
|
||||
r#"<a class="cardresult" href="/card/{}"><img alt="Card Image: {}" src="{}/static/thumb/{}.jpg" class="thumb"/>{card}</a>"#,
|
||||
card.id,
|
||||
card.name,
|
||||
IMG_HOST.as_str(),
|
||||
card.id
|
||||
)?;
|
||||
}
|
||||
body.push_str("</div>");
|
||||
Ok(TargetPage::Data(PageData {
|
||||
description: readable_query,
|
||||
query: Some(raw_query),
|
||||
body,
|
||||
title: format!("{} results - YGO Card Database", cards.len()),
|
||||
}))
|
||||
}
|
||||
}
|
||||
body.push_str("<div style=\"display: flex; flex-wrap: wrap;\">");
|
||||
for card in &matches {
|
||||
write!(
|
||||
body,
|
||||
r#"<a class="cardresult" href="/card/{}"><img alt="Card Image: {}" src="{}/static/thumb/{}.jpg" class="thumb"/>{card}</a>"#,
|
||||
card.id,
|
||||
card.name,
|
||||
IMG_HOST.as_str(),
|
||||
card.id
|
||||
)?;
|
||||
}
|
||||
body.push_str("</div>");
|
||||
Ok(PageData {
|
||||
description: readable_query,
|
||||
query: Some(raw_query),
|
||||
body,
|
||||
title: format!("{} results - YGO Card Database", matches.len()),
|
||||
})
|
||||
}
|
||||
|
||||
fn add_data(res: &mut String, pd: &PageData) -> AnyResult<()> {
|
||||
|
Loading…
Reference in New Issue
Block a user