feat: Add Category autocomplete with config in settings
This commit is contained in:
parent
8e55c95ecc
commit
f3421554ad
@ -46,7 +46,8 @@
|
|||||||
"shop_by_category_section",
|
"shop_by_category_section",
|
||||||
"slideshow",
|
"slideshow",
|
||||||
"item_search_settings_section",
|
"item_search_settings_section",
|
||||||
"search_index_fields"
|
"search_index_fields",
|
||||||
|
"show_categories_in_search_autocomplete"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
@ -313,12 +314,18 @@
|
|||||||
"fieldname": "item_search_settings_section",
|
"fieldname": "item_search_settings_section",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "Item Search Settings"
|
"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,
|
"index_web_pages_for_search": 1,
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-04-23 13:30:50.286088",
|
"modified": "2021-04-26 09:50:40.581354",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "E-commerce",
|
"module": "E-commerce",
|
||||||
"name": "E Commerce Settings",
|
"name": "E Commerce Settings",
|
||||||
|
@ -17,6 +17,7 @@ from redisearch import (
|
|||||||
WEBSITE_ITEM_INDEX = 'website_items_index'
|
WEBSITE_ITEM_INDEX = 'website_items_index'
|
||||||
WEBSITE_ITEM_KEY_PREFIX = 'website_item:'
|
WEBSITE_ITEM_KEY_PREFIX = 'website_item:'
|
||||||
WEBSITE_ITEM_NAME_AUTOCOMPLETE = 'website_items_name_dict'
|
WEBSITE_ITEM_NAME_AUTOCOMPLETE = 'website_items_name_dict'
|
||||||
|
WEBSITE_ITEM_CATEGORY_AUTOCOMPLETE = 'website_items_category_dict'
|
||||||
|
|
||||||
ALLOWED_INDEXABLE_FIELDS_SET = {
|
ALLOWED_INDEXABLE_FIELDS_SET = {
|
||||||
'item_code',
|
'item_code',
|
||||||
@ -108,27 +109,36 @@ def delete_item_from_index(website_item_doc):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def define_autocomplete_dictionary():
|
def define_autocomplete_dictionary():
|
||||||
print("Defining ac dict...")
|
"""Creates an autocomplete search dictionary for `name`.
|
||||||
# AC for name
|
Also creats autocomplete dictionary for `categories` if
|
||||||
# TODO: AC for category
|
checked in E Commerce Settings"""
|
||||||
|
|
||||||
r = redis.Redis("localhost", 13000)
|
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:
|
try:
|
||||||
r.delete(WEBSITE_ITEM_NAME_AUTOCOMPLETE)
|
r.delete(WEBSITE_ITEM_NAME_AUTOCOMPLETE)
|
||||||
|
r.delete(WEBSITE_ITEM_CATEGORY_AUTOCOMPLETE)
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
items = frappe.get_all(
|
items = frappe.get_all(
|
||||||
'Website Item',
|
'Website Item',
|
||||||
fields=['web_item_name'],
|
fields=['web_item_name', 'item_group'],
|
||||||
filters={"published": True}
|
filters={"published": True}
|
||||||
)
|
)
|
||||||
|
|
||||||
for item in items:
|
for item in items:
|
||||||
print("adding suggestion: " + item.web_item_name)
|
name_ac.add_suggestions(Suggestion(item.web_item_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
|
return True
|
||||||
|
|
||||||
|
@ -9,7 +9,11 @@ from erpnext.e_commerce.shopping_cart.product_info import set_product_info_for_w
|
|||||||
|
|
||||||
# For SEARCH -------
|
# For SEARCH -------
|
||||||
from redisearch import AutoCompleter, Client, Query
|
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
|
no_cache = 1
|
||||||
@ -83,3 +87,14 @@ def search(query):
|
|||||||
|
|
||||||
def convert_to_dict(redis_search_doc):
|
def convert_to_dict(redis_search_doc):
|
||||||
return redis_search_doc.__dict__
|
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]
|
@ -12,7 +12,19 @@
|
|||||||
|
|
||||||
{% block page_content %}
|
{% block page_content %}
|
||||||
<input type="text" name="query" id="search-box">
|
<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 %}
|
{% endblock %}
|
@ -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 results = document.getElementById("results");
|
||||||
|
const categoryList = document.getElementById("category-suggestions");
|
||||||
|
|
||||||
function populateResults(data) {
|
function populateResults(data) {
|
||||||
console.log(data);
|
|
||||||
html = ""
|
html = ""
|
||||||
for (let res of data.message) {
|
for (let res of data.message) {
|
||||||
html += `<li>
|
html += `<li>
|
||||||
@ -12,11 +12,24 @@ function populateResults(data) {
|
|||||||
<a href="/${res.route}">${res.web_item_name}</a>
|
<a href="/${res.route}">${res.web_item_name}</a>
|
||||||
</li>`
|
</li>`
|
||||||
}
|
}
|
||||||
console.log(html);
|
|
||||||
results.innerHTML = 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({
|
frappe.call({
|
||||||
method: "erpnext.templates.pages.product_search.search",
|
method: "erpnext.templates.pages.product_search.search",
|
||||||
args: {
|
args: {
|
||||||
@ -25,5 +38,19 @@ search_box.addEventListener("input", (e) => {
|
|||||||
callback: (data) => {
|
callback: (data) => {
|
||||||
populateResults(data);
|
populateResults(data);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user