mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-27 08:54:45 +00:00
feat: Search UI
- Search UI with dropdown results - Client class to handle Product Search actions and results - Integrated Search bar into all-products and item group pages - Run db search without redisearch - Cleanup: [Search] change decorator names and variables - Sider fixes
This commit is contained in:
@@ -2,7 +2,16 @@
|
||||
{% extends "templates/web.html" %}
|
||||
|
||||
{% block header %}
|
||||
<!-- <h2>{{ title }}</h2> -->
|
||||
<div class="row mb-6" style="width: 65vw">
|
||||
<div class="mb-6 col-4 order-1">{{ title }}</div>
|
||||
|
||||
<div class="input-group mb-6 col-8 order-2">
|
||||
<div class="dropdown w-100" id="dropdownMenuSearch">
|
||||
<input type="search" name="query" id="search-box" class="form-control" placeholder="Search for products..." aria-label="Product" aria-describedby="button-addon2">
|
||||
<!-- Results dropdown rendered in product_search.js -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock header %}
|
||||
|
||||
{% block script %}
|
||||
@@ -19,7 +28,7 @@
|
||||
<div class="item-group-content" itemscope itemtype="http://schema.org/Product"
|
||||
data-item-group="{{ name }}">
|
||||
<div class="item-group-slideshow">
|
||||
{% if slideshow %}<!-- slideshow -->
|
||||
{% if slideshow %} <!-- slideshow -->
|
||||
{{ web_block(
|
||||
"Hero Slider",
|
||||
values=slideshow,
|
||||
@@ -28,8 +37,8 @@
|
||||
add_bottom_padding=0,
|
||||
) }}
|
||||
{% endif %}
|
||||
<h2 class="mt-3">{{ title }}</h2>
|
||||
{% if description %}<!-- description -->
|
||||
|
||||
{% if description %} <!-- description -->
|
||||
<div class="item-group-description text-muted mb-5" itemprop="description">{{ description or ""}}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
@@ -163,7 +163,7 @@ $.extend(shopping_cart, {
|
||||
item_code: item_code,
|
||||
qty: 0
|
||||
});
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
render_tax_row: function($cart_taxes, doc, shipping_rules) {
|
||||
|
||||
@@ -6,16 +6,14 @@ from frappe.utils import cstr, nowdate, cint
|
||||
from erpnext.setup.doctype.item_group.item_group import get_item_for_list_in_html
|
||||
from erpnext.e_commerce.shopping_cart.product_info import set_product_info_for_website
|
||||
|
||||
# For SEARCH -------
|
||||
from redisearch import AutoCompleter, Client, Query
|
||||
from erpnext.e_commerce.website_item_indexing import (
|
||||
is_search_module_loaded,
|
||||
WEBSITE_ITEM_INDEX,
|
||||
WEBSITE_ITEM_INDEX,
|
||||
WEBSITE_ITEM_NAME_AUTOCOMPLETE,
|
||||
WEBSITE_ITEM_CATEGORY_AUTOCOMPLETE,
|
||||
make_key
|
||||
)
|
||||
# -----------------
|
||||
|
||||
no_cache = 1
|
||||
|
||||
@@ -35,30 +33,29 @@ def get_product_list(search=None, start=0, limit=12):
|
||||
def get_product_data(search=None, start=0, limit=12):
|
||||
# limit = 12 because we show 12 items in the grid view
|
||||
# base query
|
||||
query = """select I.name, I.item_name, I.item_code, I.route, I.image, I.website_image, I.thumbnail, I.item_group,
|
||||
I.description, I.web_long_description as website_description, I.is_stock_item,
|
||||
case when (S.actual_qty - S.reserved_qty) > 0 then 1 else 0 end as in_stock, I.website_warehouse,
|
||||
I.has_batch_no
|
||||
from `tabItem` I
|
||||
left join tabBin S on I.item_code = S.item_code and I.website_warehouse = S.warehouse
|
||||
where (I.show_in_website = 1)
|
||||
and I.disabled = 0
|
||||
and (I.end_of_life is null or I.end_of_life='0000-00-00' or I.end_of_life > %(today)s)"""
|
||||
query = """
|
||||
Select
|
||||
web_item_name, item_name, item_code, brand, route,
|
||||
website_image, thumbnail, item_group,
|
||||
description, web_long_description as website_description,
|
||||
website_warehouse, ranking
|
||||
from `tabWebsite Item`
|
||||
where published = 1
|
||||
"""
|
||||
|
||||
# search term condition
|
||||
if search:
|
||||
query += """ and (I.web_long_description like %(search)s
|
||||
or I.description like %(search)s
|
||||
or I.item_name like %(search)s
|
||||
or I.name like %(search)s)"""
|
||||
query += """ and (item_name like %(search)s
|
||||
or web_item_name like %(search)s
|
||||
or brand like %(search)s
|
||||
or web_long_description like %(search)s)"""
|
||||
search = "%" + cstr(search) + "%"
|
||||
|
||||
# order by
|
||||
query += """ order by I.weightage desc, in_stock desc, I.modified desc limit %s, %s""" % (cint(start), cint(limit))
|
||||
query += """ order by ranking asc, modified desc limit %s, %s""" % (cint(start), cint(limit))
|
||||
|
||||
return frappe.db.sql(query, {
|
||||
"search": search,
|
||||
"today": nowdate()
|
||||
"search": search
|
||||
}, as_dict=1)
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
@@ -80,8 +77,8 @@ def search(query, limit=10, fuzzy_search=True):
|
||||
ac = AutoCompleter(make_key(WEBSITE_ITEM_NAME_AUTOCOMPLETE), conn=red)
|
||||
client = Client(make_key(WEBSITE_ITEM_INDEX), conn=red)
|
||||
suggestions = ac.get_suggestions(
|
||||
query,
|
||||
num=limit,
|
||||
query,
|
||||
num=limit,
|
||||
fuzzy= fuzzy_search and len(query) > 4 # Fuzzy on length < 3 can be real slow
|
||||
)
|
||||
|
||||
@@ -111,11 +108,19 @@ def convert_to_dict(redis_search_doc):
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
def get_category_suggestions(query):
|
||||
search_results = {"from_redisearch": True, "results": []}
|
||||
search_results = {"results": []}
|
||||
|
||||
if not is_search_module_loaded():
|
||||
# Redisearch module not loaded
|
||||
search_results["from_redisearch"] = False
|
||||
# Redisearch module not loaded, query db
|
||||
categories = frappe.db.get_all(
|
||||
"Item Group",
|
||||
filters={
|
||||
"name": ["like", "%{0}%".format(query)],
|
||||
"show_in_website": 1
|
||||
},
|
||||
fields=["name", "route"]
|
||||
)
|
||||
search_results['results'] = categories
|
||||
return search_results
|
||||
|
||||
if not query:
|
||||
@@ -125,5 +130,5 @@ def get_category_suggestions(query):
|
||||
suggestions = ac.get_suggestions(query, num=10)
|
||||
|
||||
search_results['results'] = [s.string for s in suggestions]
|
||||
|
||||
|
||||
return search_results
|
||||
Reference in New Issue
Block a user