diff --git a/pgml-dashboard/src/components/pages/blog/blog_search/call/call_controller.js b/pgml-dashboard/src/components/pages/blog/blog_search/call/call_controller.js
index 79a4bd368..68fbaaacc 100644
--- a/pgml-dashboard/src/components/pages/blog/blog_search/call/call_controller.js
+++ b/pgml-dashboard/src/components/pages/blog/blog_search/call/call_controller.js
@@ -10,6 +10,23 @@ export default class extends Controller {
connect() {
this.timer;
this.tags = "";
+
+ document.addEventListener("click", this.handle_search_click);
+ }
+
+ handle_search_click(e) {
+ const target = e.target.closest(".blog-search-result");
+ if (target) {
+ const resultIndex = target.getAttribute("data-result-index");
+ const searchId = target.getAttribute("data-search-id");
+ const formData = new FormData();
+ formData.append("search_id", searchId);
+ formData.append("clicked", resultIndex);
+ fetch('/search_event', {
+ method: 'POST',
+ body: formData,
+ });
+ }
}
search() {
@@ -49,4 +66,8 @@ export default class extends Controller {
this.tags = "";
this.search();
}
+
+ disconnect() {
+ document.removeEventListener("click", this.handle_search_click);
+ }
}
diff --git a/pgml-dashboard/src/components/pages/blog/blog_search/response/mod.rs b/pgml-dashboard/src/components/pages/blog/blog_search/response/mod.rs
index ac8a89af1..5091ff85e 100644
--- a/pgml-dashboard/src/components/pages/blog/blog_search/response/mod.rs
+++ b/pgml-dashboard/src/components/pages/blog/blog_search/response/mod.rs
@@ -6,11 +6,15 @@ use sailfish::TemplateOnce;
#[template(path = "pages/blog/blog_search/response/template.html")]
pub struct Response {
html: Vec,
+ search_id: Option,
}
impl Response {
- pub fn new() -> Response {
- Response { html: Vec::new() }
+ pub fn new(search_id: Option) -> Response {
+ Response {
+ html: Vec::new(),
+ search_id,
+ }
}
pub fn pattern(mut self, mut articles: Vec, is_search: bool) -> Response {
@@ -53,7 +57,8 @@ impl Response {
};
articles.reverse();
- while articles.len() > 0 {
+ let mut search_result_index = 0;
+ while !articles.is_empty() {
// Get the row pattern or repeat the last two row patterns.
let pattern = match layout.get(cycle) {
Some(pattern) => pattern,
@@ -74,11 +79,12 @@ impl Response {
for (i, doc) in row.into_iter().enumerate() {
let template = pattern[i];
html.push(
- ArticlePreview::new(&doc.unwrap())
+ ArticlePreview::new(&doc.unwrap(), self.search_id, Some(search_result_index))
.card_type(template)
.render_once()
.unwrap(),
- )
+ );
+ search_result_index += 1;
}
} else {
html.push(format!(
@@ -101,24 +107,36 @@ impl Response {
{}
"#,
- ArticlePreview::new(&row[0].clone().unwrap())
+ ArticlePreview::new(&row[0].clone().unwrap(), self.search_id, Some(search_result_index))
.big()
.render_once()
.unwrap(),
- ArticlePreview::new(&row[1].clone().unwrap()).render_once().unwrap(),
- ArticlePreview::new(&row[2].clone().unwrap()).render_once().unwrap(),
- ArticlePreview::new(&row[0].clone().unwrap()).render_once().unwrap(),
- ArticlePreview::new(&row[1].clone().unwrap()).render_once().unwrap(),
- ArticlePreview::new(&row[2].clone().unwrap()).render_once().unwrap()
- ))
+ ArticlePreview::new(&row[1].clone().unwrap(), self.search_id, Some(search_result_index + 1))
+ .render_once()
+ .unwrap(),
+ ArticlePreview::new(&row[2].clone().unwrap(), self.search_id, Some(search_result_index + 2))
+ .render_once()
+ .unwrap(),
+ ArticlePreview::new(&row[0].clone().unwrap(), self.search_id, Some(search_result_index + 3))
+ .render_once()
+ .unwrap(),
+ ArticlePreview::new(&row[1].clone().unwrap(), self.search_id, Some(search_result_index + 4))
+ .render_once()
+ .unwrap(),
+ ArticlePreview::new(&row[2].clone().unwrap(), self.search_id, Some(search_result_index + 5))
+ .render_once()
+ .unwrap()
+ ));
+ search_result_index += 6;
}
} else {
html.push(
- ArticlePreview::new(&articles.pop().unwrap())
+ ArticlePreview::new(&articles.pop().unwrap(), self.search_id, Some(search_result_index))
.card_type("default")
.render_once()
.unwrap(),
- )
+ );
+ search_result_index += 1;
}
cycle += 1;
}
diff --git a/pgml-dashboard/src/components/pages/blog/landing_page/template.html b/pgml-dashboard/src/components/pages/blog/landing_page/template.html
index c52f1c628..af8cb9505 100644
--- a/pgml-dashboard/src/components/pages/blog/landing_page/template.html
+++ b/pgml-dashboard/src/components/pages/blog/landing_page/template.html
@@ -7,7 +7,7 @@
use crate::utils::config::standalone_dashboard;
let cards = featured_cards.iter().map(|card| {
- ArticlePreview::new(card).featured().render_once().unwrap()
+ ArticlePreview::new(card, None, None).featured().render_once().unwrap()
}).collect::>();
%>
diff --git a/pgml-dashboard/src/forms.rs b/pgml-dashboard/src/forms.rs
index 22f94f264..53ff66008 100644
--- a/pgml-dashboard/src/forms.rs
+++ b/pgml-dashboard/src/forms.rs
@@ -30,3 +30,9 @@ pub struct ChatbotPostData {
#[serde(rename = "knowledgeBase")]
pub knowledge_base: u8,
}
+
+#[derive(FromForm)]
+pub struct SearchEvent {
+ pub search_id: i64,
+ pub clicked: i64
+}
diff --git a/pgml-dashboard/src/templates/docs.rs b/pgml-dashboard/src/templates/docs.rs
index 36a101c07..67d7e77a1 100644
--- a/pgml-dashboard/src/templates/docs.rs
+++ b/pgml-dashboard/src/templates/docs.rs
@@ -8,6 +8,7 @@ use crate::utils::markdown::SearchResult;
#[derive(TemplateOnce)]
#[template(path = "components/search.html")]
pub struct Search {
+ pub search_id: i64,
pub query: String,
pub results: Vec,
}
diff --git a/pgml-dashboard/src/utils/markdown.rs b/pgml-dashboard/src/utils/markdown.rs
index 424dc81e0..0aed062cc 100644
--- a/pgml-dashboard/src/utils/markdown.rs
+++ b/pgml-dashboard/src/utils/markdown.rs
@@ -1286,12 +1286,19 @@ impl SiteSearch {
.collect()
}
+ pub async fn add_search_event(&self, search_id: i64, search_result: i64) -> anyhow::Result<()> {
+ self.collection.add_search_event(search_id, search_result + 1, serde_json::json!({
+ "clicked": true
+ }).into(), &self.pipeline).await?;
+ Ok(())
+ }
+
pub async fn search(
&self,
query: &str,
doc_type: Option,
doc_tags: Option>,
- ) -> anyhow::Result> {
+ ) -> anyhow::Result<(i64, Vec)> {
let mut search = serde_json::json!({
"query": {
// "full_text_search": {
@@ -1335,15 +1342,22 @@ impl SiteSearch {
}
let results = self.collection.search_local(search.into(), &self.pipeline).await?;
- results["results"]
- .as_array()
- .context("Error getting results from search")?
- .iter()
- .map(|r| {
- let document: Document = serde_json::from_value(r["document"].clone())?;
- Ok(document)
- })
- .collect()
+ let search_id = results["search_id"]
+ .as_i64()
+ .context("Error getting search_id from search")?;
+
+ Ok((
+ search_id,
+ results["results"]
+ .as_array()
+ .context("Error getting results from search")?
+ .iter()
+ .map(|r| {
+ let document: Document = serde_json::from_value(r["document"].clone())?;
+ anyhow::Ok(document)
+ })
+ .collect::>>()?,
+ ))
}
pub async fn build(&mut self) -> anyhow::Result<()> {
diff --git a/pgml-dashboard/static/js/search.js b/pgml-dashboard/static/js/search.js
index 02bd989b9..1569790c0 100644
--- a/pgml-dashboard/static/js/search.js
+++ b/pgml-dashboard/static/js/search.js
@@ -1,48 +1,66 @@
import {
- Controller
+ Controller
} from '@hotwired/stimulus'
export default class extends Controller {
- static targets = [
- 'searchTrigger',
- ]
+ static targets = [
+ 'searchTrigger',
+ ]
- connect() {
- this.target = document.getElementById("search");
- this.searchInput = document.getElementById("search-input");
- this.searchFrame = document.getElementById("search-results")
+ connect() {
+ this.target = document.getElementById("search");
+ this.searchInput = document.getElementById("search-input");
+ this.searchFrame = document.getElementById("search-results")
- this.target.addEventListener('shown.bs.modal', this.focusSearchInput)
- this.target.addEventListener('hidden.bs.modal', this.updateSearch)
- this.searchInput.addEventListener('input', (e) => this.search(e))
+ this.target.addEventListener('shown.bs.modal', this.focusSearchInput)
+ this.target.addEventListener('hidden.bs.modal', this.updateSearch)
+ this.searchInput.addEventListener('input', (e) => this.search(e))
- this.timer;
- }
+ this.timer;
- search(e) {
- clearTimeout(this.timer);
- const query = e.currentTarget.value
- this.timer = setTimeout(() => {
- this.searchFrame.src = `/search?query=${query}`
- }, 250);
- }
+ document.addEventListener("click", this.handle_search_click);
+ }
- focusSearchInput = (e) => {
- this.searchInput.focus()
- this.searchTriggerTarget.blur()
+ handle_search_click(e) {
+ const target = e.target.closest(".search-result");
+ if (target) {
+ const resultIndex = target.getAttribute("data-result-index");
+ const searchId = target.getAttribute("data-search-id");
+ const formData = new FormData();
+ formData.append("search_id", searchId);
+ formData.append("clicked", resultIndex);
+ fetch('/search_event', {
+ method: 'POST',
+ body: formData,
+ });
}
+ }
- updateSearch = () => {
- this.searchTriggerTarget.value = this.searchInput.value
- }
+ search(e) {
+ clearTimeout(this.timer);
+ const query = e.currentTarget.value
+ this.timer = setTimeout(() => {
+ this.searchFrame.src = `/search?query=${query}`
+ }, 250);
+ }
- openSearch = (e) => {
- new bootstrap.Modal(this.target).show()
- this.searchInput.value = e.currentTarget.value
- }
+ focusSearchInput = () => {
+ this.searchInput.focus()
+ this.searchTriggerTarget.blur()
+ }
- disconnect() {
- this.searchTriggerTarget.removeEventListener('shown.bs.modal', this.focusSearchInput)
- this.searchTriggerTarget.removeEventListener('hidden.bs.modal', this.updateSearch)
- }
+ updateSearch = () => {
+ this.searchTriggerTarget.value = this.searchInput.value
+ }
+
+ openSearch = (e) => {
+ new bootstrap.Modal(this.target).show()
+ this.searchInput.value = e.currentTarget.value
+ }
+
+ disconnect() {
+ this.searchTriggerTarget.removeEventListener('shown.bs.modal', this.focusSearchInput)
+ this.searchTriggerTarget.removeEventListener('hidden.bs.modal', this.updateSearch)
+ document.removeEventListener("click", this.handle_search_click);
+ }
}
diff --git a/pgml-dashboard/templates/components/search.html b/pgml-dashboard/templates/components/search.html
index 5fa45bd1e..4d795631e 100644
--- a/pgml-dashboard/templates/components/search.html
+++ b/pgml-dashboard/templates/components/search.html
@@ -1,11 +1,11 @@