feat: Add Category autocomplete with config in settings
diff --git a/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.json b/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.json
index 76bf283..bfdfb0d 100644
--- a/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.json
+++ b/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.json
@@ -46,7 +46,8 @@
"shop_by_category_section",
"slideshow",
"item_search_settings_section",
- "search_index_fields"
+ "search_index_fields",
+ "show_categories_in_search_autocomplete"
],
"fields": [
{
@@ -313,12 +314,18 @@
"fieldname": "item_search_settings_section",
"fieldtype": "Section Break",
"label": "Item Search Settings"
+ },
+ {
+ "default": "1",
+ "fieldname": "show_categories_in_search_autocomplete",
+ "fieldtype": "Check",
+ "label": "Show Categories in Search Autocomplete"
}
],
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
- "modified": "2021-04-23 13:30:50.286088",
+ "modified": "2021-04-26 09:50:40.581354",
"modified_by": "Administrator",
"module": "E-commerce",
"name": "E Commerce Settings",
diff --git a/erpnext/e_commerce/website_item_indexing.py b/erpnext/e_commerce/website_item_indexing.py
index 0e48a2d..faf5760 100644
--- a/erpnext/e_commerce/website_item_indexing.py
+++ b/erpnext/e_commerce/website_item_indexing.py
@@ -17,6 +17,7 @@
WEBSITE_ITEM_INDEX = 'website_items_index'
WEBSITE_ITEM_KEY_PREFIX = 'website_item:'
WEBSITE_ITEM_NAME_AUTOCOMPLETE = 'website_items_name_dict'
+WEBSITE_ITEM_CATEGORY_AUTOCOMPLETE = 'website_items_category_dict'
ALLOWED_INDEXABLE_FIELDS_SET = {
'item_code',
@@ -108,27 +109,36 @@
return True
def define_autocomplete_dictionary():
- print("Defining ac dict...")
- # AC for name
- # TODO: AC for category
+ """Creates an autocomplete search dictionary for `name`.
+ Also creats autocomplete dictionary for `categories` if
+ checked in E Commerce Settings"""
r = redis.Redis("localhost", 13000)
- ac = AutoCompleter(WEBSITE_ITEM_NAME_AUTOCOMPLETE, port=13000)
+ name_ac = AutoCompleter(WEBSITE_ITEM_NAME_AUTOCOMPLETE, port=13000)
+ cat_ac = AutoCompleter(WEBSITE_ITEM_CATEGORY_AUTOCOMPLETE, port=13000)
+ ac_categories = frappe.db.get_single_value(
+ 'E Commerce Settings',
+ 'show_categories_in_search_autocomplete'
+ )
+
+ # Delete both autocomplete dicts
try:
r.delete(WEBSITE_ITEM_NAME_AUTOCOMPLETE)
+ r.delete(WEBSITE_ITEM_CATEGORY_AUTOCOMPLETE)
except:
return False
items = frappe.get_all(
'Website Item',
- fields=['web_item_name'],
+ fields=['web_item_name', 'item_group'],
filters={"published": True}
)
for item in items:
- print("adding suggestion: " + item.web_item_name)
- ac.add_suggestions(Suggestion(item.web_item_name))
+ name_ac.add_suggestions(Suggestion(item.web_item_name))
+ if ac_categories and item.item_group:
+ cat_ac.add_suggestions(Suggestion(item.item_group))
return True
diff --git a/erpnext/templates/pages/product_search.py b/erpnext/templates/pages/product_search.py
index d935a7a..755dfec 100644
--- a/erpnext/templates/pages/product_search.py
+++ b/erpnext/templates/pages/product_search.py
@@ -9,7 +9,11 @@
# For SEARCH -------
from redisearch import AutoCompleter, Client, Query
-from erpnext.e_commerce.website_item_indexing import WEBSITE_ITEM_INDEX, WEBSITE_ITEM_NAME_AUTOCOMPLETE
+from erpnext.e_commerce.website_item_indexing import (
+ WEBSITE_ITEM_INDEX,
+ WEBSITE_ITEM_NAME_AUTOCOMPLETE,
+ WEBSITE_ITEM_CATEGORY_AUTOCOMPLETE
+)
# -----------------
no_cache = 1
@@ -83,3 +87,14 @@
def convert_to_dict(redis_search_doc):
return redis_search_doc.__dict__
+
+@frappe.whitelist(allow_guest=True)
+def get_category_suggestions(query):
+ if not query:
+ # TODO: return top/recent searches
+ return []
+
+ ac = AutoCompleter(WEBSITE_ITEM_CATEGORY_AUTOCOMPLETE, port=13000)
+ suggestions = ac.get_suggestions(query, num=10)
+
+ return [s.string for s in suggestions]
\ No newline at end of file
diff --git a/erpnext/www/all-products/search.html b/erpnext/www/all-products/search.html
index ef74536..1c58e65 100644
--- a/erpnext/www/all-products/search.html
+++ b/erpnext/www/all-products/search.html
@@ -12,7 +12,19 @@
{% block page_content %}
<input type="text" name="query" id="search-box">
-<ul id="results">
-</ul>
+<!-- Search Results -->
+<h2>Products</h2>
+<ul id="results">Start typing...</ul>
+
+{% set show_categories = frappe.db.get_single_value('E Commerce Settings', 'show_categories_in_search_autocomplete') %}
+
+{% if show_categories %}
+<div id="categories">
+ <h2>Categories</h2>
+ <ul id="category-suggestions">
+ </ul>
+</div>
+{% endif %}
+
{% endblock %}
\ No newline at end of file
diff --git a/erpnext/www/all-products/search.js b/erpnext/www/all-products/search.js
index 2080f35..aa47a4d 100644
--- a/erpnext/www/all-products/search.js
+++ b/erpnext/www/all-products/search.js
@@ -1,10 +1,10 @@
-console.log("search.js reloaded");
+console.log("search.js loaded");
-const search_box = document.getElementById("search-box");
+const searchBox = document.getElementById("search-box");
const results = document.getElementById("results");
+const categoryList = document.getElementById("category-suggestions");
function populateResults(data) {
- console.log(data);
html = ""
for (let res of data.message) {
html += `<li>
@@ -12,11 +12,24 @@
<a href="/${res.route}">${res.web_item_name}</a>
</li>`
}
- console.log(html);
results.innerHTML = html;
}
-search_box.addEventListener("input", (e) => {
+function populateCategoriesList(data) {
+ if (data.length === 0) {
+ categoryList.innerText = "No matches";
+ return;
+ }
+
+ html = ""
+ for (let category of data.message) {
+ html += `<li>${category}</li>`
+ }
+
+ categoryList.innerHTML = html;
+}
+
+searchBox.addEventListener("input", (e) => {
frappe.call({
method: "erpnext.templates.pages.product_search.search",
args: {
@@ -25,5 +38,19 @@
callback: (data) => {
populateResults(data);
}
- })
-});
\ No newline at end of file
+ });
+
+ // If there is a suggestion list node
+ if (categoryList) {
+ frappe.call({
+ method: "erpnext.templates.pages.product_search.get_category_suggestions",
+ args: {
+ query: e.target.value
+ },
+ callback: (data) => {
+ populateCategoriesList(data);
+ }
+ });
+ }
+});
+