Skip to content

Commit c73cd2a

Browse files
committed
Prep for saving events
1 parent a790fb8 commit c73cd2a

File tree

6 files changed

+107
-66
lines changed

6 files changed

+107
-66
lines changed

pgml-dashboard/src/api/cms.rs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::{
55

66
use std::str::FromStr;
77

8+
use rocket::form::Form;
89
use comrak::{format_html_with_plugins, parse_document, Arena, ComrakPlugins};
910
use lazy_static::lazy_static;
1011
use markdown::mdast::Node;
@@ -646,9 +647,16 @@ impl Collection {
646647
}
647648
}
648649

650+
651+
#[post("/search_event", data = "<search_event>")]
652+
async fn search_event(search_event: Form<crate::forms::SearchEvent>, site_search: &State<crate::utils::markdown::SiteSearch>) -> ResponseOk {
653+
eprintln!("WE GOT IT: {:?}", search_event.clicked);
654+
ResponseOk("".to_string())
655+
}
656+
649657
#[get("/search?<query>", rank = 20)]
650658
async fn search(query: &str, site_search: &State<crate::utils::markdown::SiteSearch>) -> ResponseOk {
651-
let results = site_search
659+
let (search_id, results) = site_search
652660
.search(query, None, None)
653661
.await
654662
.expect("Error performing search");
@@ -688,6 +696,7 @@ async fn search(query: &str, site_search: &State<crate::utils::markdown::SiteSea
688696

689697
ResponseOk(
690698
Template(Search {
699+
search_id,
691700
query: query.to_string(),
692701
results,
693702
})
@@ -697,25 +706,23 @@ async fn search(query: &str, site_search: &State<crate::utils::markdown::SiteSea
697706

698707
#[get("/search_blog?<query>&<tag>", rank = 20)]
699708
async fn search_blog(query: &str, tag: &str, site_search: &State<crate::utils::markdown::SiteSearch>) -> ResponseOk {
700-
let tag = if tag.len() > 0 {
709+
let tag = if !tag.is_empty() {
701710
Some(Vec::from([tag.to_string()]))
702711
} else {
703712
None
704713
};
705714

706715
// If user is not making a search return all blogs in default design.
707-
let results = if query.len() > 0 || tag.clone().is_some() {
716+
let results = if !query.is_empty() || tag.clone().is_some() {
708717
let results = site_search.search(query, Some(DocType::Blog), tag.clone()).await;
709718

710-
let results = match results {
711-
Ok(results) => results
719+
match results {
720+
Ok((_search_id, results)) => results
712721
.into_iter()
713-
.map(|document| article_preview::DocMeta::from_document(document))
722+
.map(article_preview::DocMeta::from_document)
714723
.collect::<Vec<article_preview::DocMeta>>(),
715724
Err(_) => Vec::new(),
716-
};
717-
718-
results
725+
}
719726
} else {
720727
let mut results = Vec::new();
721728

@@ -728,7 +735,7 @@ async fn search_blog(query: &str, tag: &str, site_search: &State<crate::utils::m
728735
results
729736
};
730737

731-
let is_search = query.len() > 0 || tag.is_some();
738+
let is_search = !query.is_empty() || tag.is_some();
732739

733740
ResponseOk(
734741
crate::components::pages::blog::blog_search::Response::new()
@@ -896,6 +903,7 @@ pub fn routes() -> Vec<Route> {
896903
get_docs_asset,
897904
get_user_guides,
898905
search,
906+
search_event,
899907
search_blog
900908
]
901909
}

pgml-dashboard/src/forms.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,9 @@ pub struct ChatbotPostData {
3030
#[serde(rename = "knowledgeBase")]
3131
pub knowledge_base: u8,
3232
}
33+
34+
#[derive(FromForm)]
35+
pub struct SearchEvent {
36+
pub search_id: i64,
37+
pub clicked: i64
38+
}

pgml-dashboard/src/templates/docs.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use crate::utils::markdown::SearchResult;
88
#[derive(TemplateOnce)]
99
#[template(path = "components/search.html")]
1010
pub struct Search {
11+
pub search_id: i64,
1112
pub query: String,
1213
pub results: Vec<SearchResult>,
1314
}

pgml-dashboard/src/utils/markdown.rs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1291,7 +1291,7 @@ impl SiteSearch {
12911291
query: &str,
12921292
doc_type: Option<DocType>,
12931293
doc_tags: Option<Vec<String>>,
1294-
) -> anyhow::Result<Vec<Document>> {
1294+
) -> anyhow::Result<(i64, Vec<Document>)> {
12951295
let mut search = serde_json::json!({
12961296
"query": {
12971297
// "full_text_search": {
@@ -1335,15 +1335,22 @@ impl SiteSearch {
13351335
}
13361336
let results = self.collection.search_local(search.into(), &self.pipeline).await?;
13371337

1338-
results["results"]
1339-
.as_array()
1340-
.context("Error getting results from search")?
1341-
.iter()
1342-
.map(|r| {
1343-
let document: Document = serde_json::from_value(r["document"].clone())?;
1344-
Ok(document)
1345-
})
1346-
.collect()
1338+
let search_id = results["search_id"]
1339+
.as_i64()
1340+
.context("Error getting search_id from search")?;
1341+
1342+
Ok((
1343+
search_id,
1344+
results["results"]
1345+
.as_array()
1346+
.context("Error getting results from search")?
1347+
.iter()
1348+
.map(|r| {
1349+
let document: Document = serde_json::from_value(r["document"].clone())?;
1350+
anyhow::Ok(document)
1351+
})
1352+
.collect::<anyhow::Result<Vec<Document>>>()?,
1353+
))
13471354
}
13481355

13491356
pub async fn build(&mut self) -> anyhow::Result<()> {

pgml-dashboard/static/js/search.js

Lines changed: 62 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,67 @@
11
import {
2-
Controller
2+
Controller
33
} from '@hotwired/stimulus'
44

55
export default class extends Controller {
6-
static targets = [
7-
'searchTrigger',
8-
]
9-
10-
connect() {
11-
this.target = document.getElementById("search");
12-
this.searchInput = document.getElementById("search-input");
13-
this.searchFrame = document.getElementById("search-results")
14-
15-
this.target.addEventListener('shown.bs.modal', this.focusSearchInput)
16-
this.target.addEventListener('hidden.bs.modal', this.updateSearch)
17-
this.searchInput.addEventListener('input', (e) => this.search(e))
18-
19-
this.timer;
20-
}
21-
22-
search(e) {
23-
clearTimeout(this.timer);
24-
const query = e.currentTarget.value
25-
this.timer = setTimeout(() => {
26-
this.searchFrame.src = `/search?query=${query}`
27-
}, 250);
28-
}
29-
30-
focusSearchInput = (e) => {
31-
this.searchInput.focus()
32-
this.searchTriggerTarget.blur()
33-
}
34-
35-
updateSearch = () => {
36-
this.searchTriggerTarget.value = this.searchInput.value
37-
}
38-
39-
openSearch = (e) => {
40-
new bootstrap.Modal(this.target).show()
41-
this.searchInput.value = e.currentTarget.value
42-
}
43-
44-
disconnect() {
45-
this.searchTriggerTarget.removeEventListener('shown.bs.modal', this.focusSearchInput)
46-
this.searchTriggerTarget.removeEventListener('hidden.bs.modal', this.updateSearch)
47-
}
6+
static targets = [
7+
'searchTrigger',
8+
]
9+
10+
connect() {
11+
this.target = document.getElementById("search");
12+
this.searchInput = document.getElementById("search-input");
13+
this.searchFrame = document.getElementById("search-results")
14+
15+
this.target.addEventListener('shown.bs.modal', this.focusSearchInput)
16+
this.target.addEventListener('hidden.bs.modal', this.updateSearch)
17+
this.searchInput.addEventListener('input', (e) => this.search(e))
18+
19+
this.timer;
20+
21+
// Listen to click events and store clicked results
22+
document.addEventListener("click", function(e) {
23+
const target = e.target.closest(".search-result");
24+
if (target) {
25+
const resultIndex = target.getAttribute("data-result-index");
26+
const searchId = target.getAttribute("data-search-id");
27+
fetch('/search_event', {
28+
method: 'POST',
29+
headers: {
30+
'Content-Type': 'application/json',
31+
},
32+
body: JSON.stringify({
33+
search_id: searchId,
34+
clicked: resultIndex,
35+
}),
36+
});
37+
}
38+
});
39+
}
40+
41+
search(e) {
42+
clearTimeout(this.timer);
43+
const query = e.currentTarget.value
44+
this.timer = setTimeout(() => {
45+
this.searchFrame.src = `/search?query=${query}`
46+
}, 250);
47+
}
48+
49+
focusSearchInput = (e) => {
50+
this.searchInput.focus()
51+
this.searchTriggerTarget.blur()
52+
}
53+
54+
updateSearch = () => {
55+
this.searchTriggerTarget.value = this.searchInput.value
56+
}
57+
58+
openSearch = (e) => {
59+
new bootstrap.Modal(this.target).show()
60+
this.searchInput.value = e.currentTarget.value
61+
}
62+
63+
disconnect() {
64+
this.searchTriggerTarget.removeEventListener('shown.bs.modal', this.focusSearchInput)
65+
this.searchTriggerTarget.removeEventListener('hidden.bs.modal', this.updateSearch)
66+
}
4867
}

pgml-dashboard/templates/components/search.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
<turbo-frame id="search-results">
22
<div class="list-group">
3-
<% if query.len() < 1 { %>
3+
<% if query.is_empty() { %>
44
<p class="mb-0">Type to start searching</p>
55
<% } else if !results.is_empty() {
6-
for result in results.iter() {
6+
for (i, result) in results.iter().enumerate() {
77
%>
8-
<a class="list-group-item" href="<%- result.path %>" data-turbo-frame="_top">
8+
<a class="list-group-item search-result" data-result-index="<%- i %>" data-search-id="<%- search_id %>" href="<%- result.path %>" data-turbo-frame="_top">
99
<div class="text-white">
1010
<h5 class="h5 mb-1"><%= result.title %></h5>
1111
<% if !result.snippet.is_empty() { %>

0 commit comments

Comments
 (0)