Skip to content

Commit 8918309

Browse files
committed
Add search event tracking to the blogs page
1 parent 6a343ce commit 8918309

File tree

6 files changed

+86
-30
lines changed

6 files changed

+86
-30
lines changed

pgml-dashboard/src/api/cms.rs

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

66
use std::str::FromStr;
77

8-
use rocket::form::Form;
98
use comrak::{format_html_with_plugins, parse_document, Arena, ComrakPlugins};
109
use lazy_static::lazy_static;
1110
use markdown::mdast::Node;
11+
use rocket::form::Form;
1212
use rocket::{fs::NamedFile, http::uri::Origin, route::Route, State};
1313
use yaml_rust::YamlLoader;
1414

@@ -647,14 +647,19 @@ impl Collection {
647647
}
648648
}
649649

650-
651650
#[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-
match site_search.add_search_event(search_event.search_id, search_event.clicked).await {
651+
async fn search_event(
652+
search_event: Form<crate::forms::SearchEvent>,
653+
site_search: &State<crate::utils::markdown::SiteSearch>,
654+
) -> ResponseOk {
655+
match site_search
656+
.add_search_event(search_event.search_id, search_event.clicked)
657+
.await
658+
{
654659
Ok(_) => ResponseOk("ok".to_string()),
655660
Err(e) => {
656661
eprintln!("{:?}", e);
657-
ResponseOk("error".to_string())
662+
ResponseOk("error".to_string())
658663
}
659664
}
660665
}
@@ -718,15 +723,18 @@ async fn search_blog(query: &str, tag: &str, site_search: &State<crate::utils::m
718723
};
719724

720725
// If user is not making a search return all blogs in default design.
721-
let results = if !query.is_empty() || tag.clone().is_some() {
726+
let (search_id, results) = if !query.is_empty() || tag.clone().is_some() {
722727
let results = site_search.search(query, Some(DocType::Blog), tag.clone()).await;
723728

724729
match results {
725-
Ok((_search_id, results)) => results
726-
.into_iter()
727-
.map(article_preview::DocMeta::from_document)
728-
.collect::<Vec<article_preview::DocMeta>>(),
729-
Err(_) => Vec::new(),
730+
Ok((search_id, results)) => (
731+
Some(search_id),
732+
results
733+
.into_iter()
734+
.map(article_preview::DocMeta::from_document)
735+
.collect::<Vec<article_preview::DocMeta>>(),
736+
),
737+
Err(_) => (None, Vec::new()),
730738
}
731739
} else {
732740
let mut results = Vec::new();
@@ -737,13 +745,13 @@ async fn search_blog(query: &str, tag: &str, site_search: &State<crate::utils::m
737745
results.push(article_preview::DocMeta::from_document(doc));
738746
}
739747

740-
results
748+
(None, results)
741749
};
742750

743751
let is_search = !query.is_empty() || tag.is_some();
744752

745753
ResponseOk(
746-
crate::components::pages::blog::blog_search::Response::new()
754+
crate::components::pages::blog::blog_search::Response::new(search_id)
747755
.pattern(results, is_search)
748756
.render_once()
749757
.unwrap(),

pgml-dashboard/src/components/cards/blog/article_preview/mod.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,17 @@ impl DocMeta {
3838
pub struct ArticlePreview {
3939
card_type: String,
4040
meta: DocMeta,
41+
search_id: Option<i64>,
42+
search_result_index: Option<i64>,
4143
}
4244

4345
impl ArticlePreview {
44-
pub fn new(meta: &DocMeta) -> ArticlePreview {
46+
pub fn new(meta: &DocMeta, search_id: Option<i64>, search_result_index: Option<i64>) -> ArticlePreview {
4547
ArticlePreview {
4648
card_type: String::from("default"),
4749
meta: meta.to_owned(),
50+
search_id,
51+
search_result_index,
4852
}
4953
}
5054

@@ -76,7 +80,7 @@ impl ArticlePreview {
7680
pub async fn from_path(path: &str) -> ArticlePreview {
7781
let doc = Document::from_path(&PathBuf::from(path)).await.unwrap();
7882
let meta = DocMeta::from_document(doc);
79-
ArticlePreview::new(&meta)
83+
ArticlePreview::new(&meta, None, None)
8084
}
8185
}
8286

pgml-dashboard/src/components/cards/blog/article_preview/template.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,12 @@ <h4 style="color: inherit">{}</h4>
4141
);
4242
%>
4343

44+
<%
45+
if let (Some(search_id), Some(search_result_index)) = (search_id, search_result_index) { %>
46+
<div data-controller="cards-blog-article-preview" class="blog-search-result" data-search-id="<%- search_id %>" data-result-index="<%- search_result_index %>">
47+
<% } else { %>
4448
<div data-controller="cards-blog-article-preview">
49+
<% } %>
4550
<% if card_type == String::from("featured") {%>
4651
<a class="doc-card feature-card d-flex flex-column flex-xxl-row" href="<%- meta.path %>">
4752
<div class="cover-image-container">

pgml-dashboard/src/components/pages/blog/blog_search/call/call_controller.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,23 @@ export default class extends Controller {
1010
connect() {
1111
this.timer;
1212
this.tags = "";
13+
14+
document.addEventListener("click", this.handle_search_click);
15+
}
16+
17+
handle_search_click(e) {
18+
const target = e.target.closest(".blog-search-result");
19+
if (target) {
20+
const resultIndex = target.getAttribute("data-result-index");
21+
const searchId = target.getAttribute("data-search-id");
22+
const formData = new FormData();
23+
formData.append("search_id", searchId);
24+
formData.append("clicked", resultIndex);
25+
fetch('/search_event', {
26+
method: 'POST',
27+
body: formData,
28+
});
29+
}
1330
}
1431

1532
search() {
@@ -49,4 +66,8 @@ export default class extends Controller {
4966
this.tags = "";
5067
this.search();
5168
}
69+
70+
disconnect() {
71+
document.removeEventListener("click", this.handle_search_click);
72+
}
5273
}

pgml-dashboard/src/components/pages/blog/blog_search/response/mod.rs

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,15 @@ use sailfish::TemplateOnce;
66
#[template(path = "pages/blog/blog_search/response/template.html")]
77
pub struct Response {
88
html: Vec<String>,
9+
search_id: Option<i64>,
910
}
1011

1112
impl Response {
12-
pub fn new() -> Response {
13-
Response { html: Vec::new() }
13+
pub fn new(search_id: Option<i64>) -> Response {
14+
Response {
15+
html: Vec::new(),
16+
search_id,
17+
}
1418
}
1519

1620
pub fn pattern(mut self, mut articles: Vec<DocMeta>, is_search: bool) -> Response {
@@ -53,7 +57,8 @@ impl Response {
5357
};
5458

5559
articles.reverse();
56-
while articles.len() > 0 {
60+
let mut search_result_index = 0;
61+
while !articles.is_empty() {
5762
// Get the row pattern or repeat the last two row patterns.
5863
let pattern = match layout.get(cycle) {
5964
Some(pattern) => pattern,
@@ -74,11 +79,12 @@ impl Response {
7479
for (i, doc) in row.into_iter().enumerate() {
7580
let template = pattern[i];
7681
html.push(
77-
ArticlePreview::new(&doc.unwrap())
82+
ArticlePreview::new(&doc.unwrap(), self.search_id, Some(search_result_index))
7883
.card_type(template)
7984
.render_once()
8085
.unwrap(),
81-
)
86+
);
87+
search_result_index += 1;
8288
}
8389
} else {
8490
html.push(format!(
@@ -101,24 +107,36 @@ impl Response {
101107
{}
102108
</div>
103109
"#,
104-
ArticlePreview::new(&row[0].clone().unwrap())
110+
ArticlePreview::new(&row[0].clone().unwrap(), self.search_id, Some(search_result_index))
105111
.big()
106112
.render_once()
107113
.unwrap(),
108-
ArticlePreview::new(&row[1].clone().unwrap()).render_once().unwrap(),
109-
ArticlePreview::new(&row[2].clone().unwrap()).render_once().unwrap(),
110-
ArticlePreview::new(&row[0].clone().unwrap()).render_once().unwrap(),
111-
ArticlePreview::new(&row[1].clone().unwrap()).render_once().unwrap(),
112-
ArticlePreview::new(&row[2].clone().unwrap()).render_once().unwrap()
113-
))
114+
ArticlePreview::new(&row[1].clone().unwrap(), self.search_id, Some(search_result_index + 1))
115+
.render_once()
116+
.unwrap(),
117+
ArticlePreview::new(&row[2].clone().unwrap(), self.search_id, Some(search_result_index + 2))
118+
.render_once()
119+
.unwrap(),
120+
ArticlePreview::new(&row[0].clone().unwrap(), self.search_id, Some(search_result_index + 3))
121+
.render_once()
122+
.unwrap(),
123+
ArticlePreview::new(&row[1].clone().unwrap(), self.search_id, Some(search_result_index + 4))
124+
.render_once()
125+
.unwrap(),
126+
ArticlePreview::new(&row[2].clone().unwrap(), self.search_id, Some(search_result_index + 5))
127+
.render_once()
128+
.unwrap()
129+
));
130+
search_result_index += 6;
114131
}
115132
} else {
116133
html.push(
117-
ArticlePreview::new(&articles.pop().unwrap())
134+
ArticlePreview::new(&articles.pop().unwrap(), self.search_id, Some(search_result_index))
118135
.card_type("default")
119136
.render_once()
120137
.unwrap(),
121-
)
138+
);
139+
search_result_index += 1;
122140
}
123141
cycle += 1;
124142
}

pgml-dashboard/src/components/pages/blog/landing_page/template.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use crate::utils::config::standalone_dashboard;
88

99
let cards = featured_cards.iter().map(|card| {
10-
ArticlePreview::new(card).featured().render_once().unwrap()
10+
ArticlePreview::new(card, None, None).featured().render_once().unwrap()
1111
}).collect::<Vec<String>>();
1212
%>
1313

0 commit comments

Comments
 (0)