feat: (wip) Toggle Views
- Auto Height on Cards - Title with ellipses on length exceed - Changed namepaces - Moved product card rendering to JS - Added Image and List View Toggling buttons - Kept basic filters rendering just as before
This commit is contained in:
parent
f9929ed8a6
commit
48b3ce82b9
@ -22,7 +22,7 @@ class ProductQuery:
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.settings = frappe.get_doc("E Commerce Settings")
|
self.settings = frappe.get_doc("E Commerce Settings")
|
||||||
self.page_length = self.settings.products_per_page or 20
|
self.page_length = self.settings.products_per_page or 20
|
||||||
self.fields = ['wi.name', 'wi.item_name', 'wi.item_code', 'wi.website_image', 'wi.variant_of',
|
self.fields = ['wi.web_item_name', 'wi.name', 'wi.item_name', 'wi.item_code', 'wi.website_image', 'wi.variant_of',
|
||||||
'wi.has_variants', 'wi.item_group', 'wi.image', 'wi.web_long_description', 'wi.description',
|
'wi.has_variants', 'wi.item_group', 'wi.image', 'wi.web_long_description', 'wi.description',
|
||||||
'wi.route', 'wi.website_warehouse']
|
'wi.route', 'wi.website_warehouse']
|
||||||
self.conditions = ""
|
self.conditions = ""
|
||||||
|
124
erpnext/e_commerce/product_view.js
Normal file
124
erpnext/e_commerce/product_view.js
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
erpnext.ProductView = class {
|
||||||
|
/* Options: View Type */
|
||||||
|
constructor(options) {
|
||||||
|
Object.assign(this, options);
|
||||||
|
this.render_view_toggler();
|
||||||
|
this.get_item_filter_data();
|
||||||
|
this.render_list_view();
|
||||||
|
this.render_grid_view();
|
||||||
|
}
|
||||||
|
|
||||||
|
render_view_toggler() {
|
||||||
|
["btn-list-view", "btn-grid-view"].forEach(view => {
|
||||||
|
let icon = view === "btn-list-view" ? "list" : "image-view";
|
||||||
|
this.products_section.append(`
|
||||||
|
<div class="form-group mb-0" id="toggle-view">
|
||||||
|
<button id="${icon}" class="btn ${view} mr-2">
|
||||||
|
<span>
|
||||||
|
<svg class="icon icon-md">
|
||||||
|
<use href="#icon-${icon}"></use>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>`);
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#list").click(function() {
|
||||||
|
let $btn = $(this);
|
||||||
|
$btn.removeClass('btn-primary');
|
||||||
|
$btn.addClass('btn-primary');
|
||||||
|
$(".btn-grid-view").removeClass('btn-primary');
|
||||||
|
})
|
||||||
|
|
||||||
|
$("#image-view").click(function() {
|
||||||
|
let $btn = $(this);
|
||||||
|
$btn.removeClass('btn-primary');
|
||||||
|
$btn.addClass('btn-primary');
|
||||||
|
$(".btn-list-view").removeClass('btn-primary');
|
||||||
|
});
|
||||||
|
|
||||||
|
this.products_area = this.products_section.append(`
|
||||||
|
<br><br>
|
||||||
|
<div id="products-area" class="row products-list mt-4"></div>
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
|
||||||
|
get_item_filter_data() {
|
||||||
|
// Get Items and Discount Filters to render
|
||||||
|
let me = this;
|
||||||
|
const filters = frappe.utils.get_query_params();
|
||||||
|
let {field_filters, attribute_filters} = filters;
|
||||||
|
|
||||||
|
field_filters = field_filters ? JSON.parse(field_filters) : {};
|
||||||
|
attribute_filters = attribute_filters ? JSON.parse(attribute_filters) : {};
|
||||||
|
|
||||||
|
frappe.call({
|
||||||
|
method: 'erpnext.www.all-products.index.get_product_filter_data',
|
||||||
|
args: {
|
||||||
|
field_filters: field_filters,
|
||||||
|
attribute_filters: attribute_filters,
|
||||||
|
item_group: me.item_group
|
||||||
|
},
|
||||||
|
callback: function(result) {
|
||||||
|
if (!result.exc) {
|
||||||
|
me.render_filters(result.message[1]);
|
||||||
|
|
||||||
|
// Append pre-rendered products
|
||||||
|
// TODO: get products as is and style via js
|
||||||
|
me.products = result.message;
|
||||||
|
$("#products-area").append(result.message[0]);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$("#products-area").append(`
|
||||||
|
<div class="d-flex justify-content-center p-3 text-muted">
|
||||||
|
${__('No products found')}
|
||||||
|
</div>`);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render_filters(filter_data) {
|
||||||
|
this.get_discount_filter_html(filter_data.discount_filters);
|
||||||
|
}
|
||||||
|
|
||||||
|
get_discount_filter_html(filter_data) {
|
||||||
|
if (filter_data) {
|
||||||
|
$("#product-filters").append(`
|
||||||
|
<div id="discount-filters" class="mb-4 filter-block pb-5">
|
||||||
|
<div class="filter-label mb-3">${__("Discounts")}</div>
|
||||||
|
</div>
|
||||||
|
`);
|
||||||
|
|
||||||
|
let html = `<div class="filter-options">`;
|
||||||
|
filter_data.forEach(filter => {
|
||||||
|
html += `
|
||||||
|
<div class="checkbox">
|
||||||
|
<label data-value="${filter[0]}">
|
||||||
|
<input type="radio" class="product-filter discount-filter"
|
||||||
|
name="discount" id="${filter[0]}"
|
||||||
|
data-filter-name="discount" data-filter-value="${filter[0]}"
|
||||||
|
>
|
||||||
|
<span class="label-area" for="${filter[0]}">
|
||||||
|
${filter[1]}
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
});
|
||||||
|
html += `</div>`;
|
||||||
|
|
||||||
|
$("#discount-filters").append(html);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render_list_view() {
|
||||||
|
// loop over data and add list html to it
|
||||||
|
}
|
||||||
|
|
||||||
|
render_grid_view() {
|
||||||
|
// loop over data and add grid html to it
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -66,5 +66,8 @@
|
|||||||
"js/hierarchy-chart.min.js": [
|
"js/hierarchy-chart.min.js": [
|
||||||
"public/js/hierarchy_chart/hierarchy_chart_desktop.js",
|
"public/js/hierarchy_chart/hierarchy_chart_desktop.js",
|
||||||
"public/js/hierarchy_chart/hierarchy_chart_mobile.js"
|
"public/js/hierarchy_chart/hierarchy_chart_mobile.js"
|
||||||
|
],
|
||||||
|
"js/e-commerce.min.js": [
|
||||||
|
"e_commerce/product_view.js"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
// License: GNU General Public License v3. See license.txt
|
// License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
// shopping cart
|
// shopping cart
|
||||||
frappe.provide("erpnext.shopping_cart");
|
frappe.provide("e_commerce.shopping_cart");
|
||||||
var shopping_cart = erpnext.shopping_cart;
|
var shopping_cart = e_commerce.shopping_cart;
|
||||||
|
|
||||||
var getParams = function (url) {
|
var getParams = function (url) {
|
||||||
var params = [];
|
var params = [];
|
||||||
@ -214,7 +214,7 @@ $.extend(shopping_cart, {
|
|||||||
this.animate_add_to_cart($btn);
|
this.animate_add_to_cart($btn);
|
||||||
|
|
||||||
const item_code = $btn.data('item-code');
|
const item_code = $btn.data('item-code');
|
||||||
erpnext.shopping_cart.update_cart({
|
e_commerce.shopping_cart.update_cart({
|
||||||
item_code,
|
item_code,
|
||||||
qty: 1
|
qty: 1
|
||||||
});
|
});
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
frappe.provide("erpnext.wishlist");
|
frappe.provide("e_commerce.wishlist");
|
||||||
var wishlist = erpnext.wishlist;
|
var wishlist = e_commerce.wishlist;
|
||||||
|
|
||||||
frappe.provide("erpnext.shopping_cart");
|
frappe.provide("e_commerce.shopping_cart");
|
||||||
var shopping_cart = erpnext.shopping_cart;
|
var shopping_cart = e_commerce.shopping_cart;
|
||||||
|
|
||||||
$.extend(wishlist, {
|
$.extend(wishlist, {
|
||||||
set_wishlist_count: function() {
|
set_wishlist_count: function() {
|
||||||
@ -79,7 +79,7 @@ $.extend(wishlist, {
|
|||||||
let me = this;
|
let me = this;
|
||||||
|
|
||||||
let success_action = function() {
|
let success_action = function() {
|
||||||
erpnext.wishlist.set_wishlist_count();
|
e_commerce.wishlist.set_wishlist_count();
|
||||||
};
|
};
|
||||||
|
|
||||||
if ($wish_icon.hasClass('wished')) {
|
if ($wish_icon.hasClass('wished')) {
|
||||||
|
@ -68,7 +68,6 @@ body.product-page {
|
|||||||
|
|
||||||
.item-card-group-section {
|
.item-card-group-section {
|
||||||
.card {
|
.card {
|
||||||
height: 400px;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
@ -779,3 +778,7 @@ body.product-page {
|
|||||||
padding: 6px;
|
padding: 6px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#toggle-view {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
@ -67,35 +67,12 @@ class ItemGroup(NestedSet, WebsiteGenerator):
|
|||||||
def get_context(self, context):
|
def get_context(self, context):
|
||||||
context.show_search = True
|
context.show_search = True
|
||||||
context.page_length = cint(frappe.db.get_single_value('E Commerce Settings', 'products_per_page')) or 6
|
context.page_length = cint(frappe.db.get_single_value('E Commerce Settings', 'products_per_page')) or 6
|
||||||
context.e_commerce_settings = frappe.get_cached_doc('E Commerce Settings', 'E Commerce Settings')
|
|
||||||
context.search_link = '/product_search'
|
context.search_link = '/product_search'
|
||||||
|
|
||||||
if frappe.form_dict:
|
|
||||||
search = frappe.form_dict.search
|
|
||||||
field_filters = frappe.parse_json(frappe.form_dict.field_filters)
|
|
||||||
attribute_filters = frappe.parse_json(frappe.form_dict.attribute_filters)
|
|
||||||
start = frappe.parse_json(frappe.form_dict.start)
|
|
||||||
else:
|
|
||||||
search = None
|
|
||||||
attribute_filters = None
|
|
||||||
field_filters = {}
|
|
||||||
start = 0
|
|
||||||
|
|
||||||
if not field_filters:
|
|
||||||
field_filters = {}
|
|
||||||
|
|
||||||
# Ensure the query remains within current item group
|
|
||||||
field_filters['item_group'] = self.name
|
|
||||||
|
|
||||||
engine = ProductQuery()
|
|
||||||
context.items, discounts = engine.query(attribute_filters, field_filters, search, start)
|
|
||||||
|
|
||||||
filter_engine = ProductFiltersBuilder(self.name)
|
filter_engine = ProductFiltersBuilder(self.name)
|
||||||
|
|
||||||
context.field_filters = filter_engine.get_field_filters()
|
context.field_filters = filter_engine.get_field_filters()
|
||||||
context.attribute_filters = filter_engine.get_attribute_filters()
|
context.attribute_filters = filter_engine.get_attribute_filters()
|
||||||
if discounts:
|
|
||||||
context.discount_filters = filter_engine.get_discount_filters(discounts)
|
|
||||||
|
|
||||||
context.update({
|
context.update({
|
||||||
"parents": get_parent_item_groups(self.parent_item_group),
|
"parents": get_parent_item_groups(self.parent_item_group),
|
||||||
@ -124,6 +101,7 @@ class ItemGroup(NestedSet, WebsiteGenerator):
|
|||||||
|
|
||||||
context.no_breadcrumbs = False
|
context.no_breadcrumbs = False
|
||||||
context.title = self.website_title or self.name
|
context.title = self.website_title or self.name
|
||||||
|
context.name = self.name
|
||||||
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@
|
|||||||
const $btn = $(e.currentTarget);
|
const $btn = $(e.currentTarget);
|
||||||
$btn.prop('disabled', true);
|
$btn.prop('disabled', true);
|
||||||
const item_code = $btn.data('item-code');
|
const item_code = $btn.data('item-code');
|
||||||
erpnext.shopping_cart.update_cart({
|
e_commerce.shopping_cart.update_cart({
|
||||||
item_code,
|
item_code,
|
||||||
qty: 1,
|
qty: 1,
|
||||||
callback(r) {
|
callback(r) {
|
||||||
@ -170,11 +170,11 @@
|
|||||||
};
|
};
|
||||||
let success_action = function() {
|
let success_action = function() {
|
||||||
$btn.prop('disabled', false);
|
$btn.prop('disabled', false);
|
||||||
erpnext.wishlist.set_wishlist_count();
|
e_commerce.wishlist.set_wishlist_count();
|
||||||
$('.btn-add-to-wishlist, .btn-view-in-wishlist').toggleClass('hidden');
|
$('.btn-add-to-wishlist, .btn-view-in-wishlist').toggleClass('hidden');
|
||||||
|
|
||||||
};
|
};
|
||||||
erpnext.wishlist.add_remove_from_wishlist("add", args, success_action, failure_action);
|
e_commerce.wishlist.add_remove_from_wishlist("add", args, success_action, failure_action);
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.page_content').on('click', '.offer-details', (e) => {
|
$('.page_content').on('click', '.offer-details', (e) => {
|
||||||
|
@ -247,7 +247,7 @@ class ItemConfigure {
|
|||||||
const additional_notes = Object.keys(this.range_values || {}).map(attribute => {
|
const additional_notes = Object.keys(this.range_values || {}).map(attribute => {
|
||||||
return `${attribute}: ${this.range_values[attribute]}`;
|
return `${attribute}: ${this.range_values[attribute]}`;
|
||||||
}).join('\n');
|
}).join('\n');
|
||||||
erpnext.shopping_cart.update_cart({
|
e_commerce.shopping_cart.update_cart({
|
||||||
item_code,
|
item_code,
|
||||||
additional_notes,
|
additional_notes,
|
||||||
qty: 1
|
qty: 1
|
||||||
|
@ -16,7 +16,8 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block page_content %}
|
{% block page_content %}
|
||||||
<div class="item-group-content" itemscope itemtype="http://schema.org/Product" data-item-group="{{ name }}">
|
<div class="item-group-content" itemscope itemtype="http://schema.org/Product"
|
||||||
|
data-item-group="{{ name }}">
|
||||||
<div class="item-group-slideshow">
|
<div class="item-group-slideshow">
|
||||||
{% if slideshow %}<!-- slideshow -->
|
{% if slideshow %}<!-- slideshow -->
|
||||||
{{ web_block(
|
{{ web_block(
|
||||||
@ -33,7 +34,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12 order-2 col-md-9 order-md-2 item-card-group-section">
|
<div id="product-listing" class="col-12 order-2 col-md-9 order-md-2 item-card-group-section">
|
||||||
{% if sub_categories %}
|
{% if sub_categories %}
|
||||||
<div class="sub-category-container">
|
<div class="sub-category-container">
|
||||||
<div class="heading"> {{ _('Sub Categories') }} </div>
|
<div class="heading"> {{ _('Sub Categories') }} </div>
|
||||||
@ -48,15 +49,9 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="row products-list">
|
|
||||||
{% if items %}
|
<!-- Products Rendered in all-products/index.js-->
|
||||||
{% for item in items %}
|
|
||||||
{% include "erpnext/www/all-products/item_row.html" %}
|
|
||||||
{% endfor %}
|
|
||||||
{% else %}
|
|
||||||
{% include "erpnext/www/all-products/not_found.html" %}
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 order-1 col-md-3 order-md-1">
|
<div class="col-12 order-1 col-md-3 order-md-1">
|
||||||
<div class="collapse d-md-block mr-4 filters-section" id="product-filters">
|
<div class="collapse d-md-block mr-4 filters-section" id="product-filters">
|
||||||
@ -70,10 +65,6 @@
|
|||||||
<!-- attribute filters -->
|
<!-- attribute filters -->
|
||||||
{{ attribute_filter_section(attribute_filters) }}
|
{{ attribute_filter_section(attribute_filters) }}
|
||||||
|
|
||||||
<!-- discount filters -->
|
|
||||||
{% if discount_filters %}
|
|
||||||
{{ discount_range_filters(discount_filters) }}
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
// js inside blog page
|
// js inside blog page
|
||||||
|
|
||||||
// shopping cart
|
// shopping cart
|
||||||
frappe.provide("erpnext.shopping_cart");
|
frappe.provide("e_commerce.shopping_cart");
|
||||||
var shopping_cart = erpnext.shopping_cart;
|
var shopping_cart = e_commerce.shopping_cart;
|
||||||
|
|
||||||
$.extend(shopping_cart, {
|
$.extend(shopping_cart, {
|
||||||
show_error: function(title, text) {
|
show_error: function(title, text) {
|
||||||
|
@ -66,7 +66,8 @@
|
|||||||
'align-items-start': align == 'Left',
|
'align-items-start': align == 'Left',
|
||||||
}) -%}
|
}) -%}
|
||||||
{%- set col_size = 3 if is_full_width else 4 -%}
|
{%- set col_size = 3 if is_full_width else 4 -%}
|
||||||
{%- set title = item.item_name or item.item_code -%}
|
{%- set title = item.web_item_name or item.item_name or item.item_code -%}
|
||||||
|
{%- set title = title[:50] + "..." if title|len > 50 else title -%}
|
||||||
{%- set image = item.website_image or item.image -%}
|
{%- set image = item.website_image or item.image -%}
|
||||||
{%- set description = item.website_description or item.description-%}
|
{%- set description = item.website_description or item.description-%}
|
||||||
|
|
||||||
@ -120,11 +121,13 @@
|
|||||||
<div class="card-body {{ align_class }}" style="width:100%">
|
<div class="card-body {{ align_class }}" style="width:100%">
|
||||||
<div style="margin-top: 16px; display: flex;">
|
<div style="margin-top: 16px; display: flex;">
|
||||||
<a href="/{{ item.route or '#' }}">
|
<a href="/{{ item.route or '#' }}">
|
||||||
<div class="product-title">{{ title or '' }}</div>
|
<div class="product-title">
|
||||||
</a>
|
{{ title or '' }}
|
||||||
{% if item.in_stock %}
|
{% if item.in_stock %}
|
||||||
<span class="indicator {{ item.in_stock }} card-indicator"></span>
|
<span class="indicator {{ item.in_stock }} card-indicator"></span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
{% if not item.has_variants and settings.enable_wishlist %}
|
{% if not item.has_variants and settings.enable_wishlist %}
|
||||||
<div class="like-action"
|
<div class="like-action"
|
||||||
data-item-code="{{ item.item_code }}"
|
data-item-code="{{ item.item_code }}"
|
||||||
@ -363,7 +366,7 @@
|
|||||||
<div class="filter-options">
|
<div class="filter-options">
|
||||||
{% for attr_value in attribute.item_attribute_values %}
|
{% for attr_value in attribute.item_attribute_values %}
|
||||||
<div class="checkbox">
|
<div class="checkbox">
|
||||||
<label data-value="{{ value }}">
|
<label data-value="{{ attr_value }}">
|
||||||
<input type="checkbox"
|
<input type="checkbox"
|
||||||
class="product-filter attribute-filter"
|
class="product-filter attribute-filter"
|
||||||
id="{{attr_value.name}}"
|
id="{{attr_value.name}}"
|
||||||
@ -381,24 +384,3 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{%- endmacro -%}
|
{%- endmacro -%}
|
||||||
|
|
||||||
{%- macro discount_range_filters(filters)-%}
|
|
||||||
<div class="mb-4 filter-block pb-5">
|
|
||||||
<div class="filter-label mb-3">{{ _("Discounts") }}</div>
|
|
||||||
<div class="filter-options">
|
|
||||||
{% for entry in filters %}
|
|
||||||
<div class="checkbox">
|
|
||||||
<label data-value="{{ entry[0] }}">
|
|
||||||
<input type="radio" class="product-filter discount-filter"
|
|
||||||
name="discount" id="{{ entry[0] }}"
|
|
||||||
data-filter-name="discount" data-filter-value="{{ entry[0] }}"
|
|
||||||
>
|
|
||||||
<span class="label-area" for="{{ entry[0] }}">
|
|
||||||
{{ entry[1] }}
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{%- endmacro -%}
|
|
||||||
|
@ -7,7 +7,8 @@
|
|||||||
{% endblock header %}
|
{% endblock header %}
|
||||||
|
|
||||||
{% block page_content %}
|
{% block page_content %}
|
||||||
<div class="row" style="display: none;">
|
<!-- Old Search -->
|
||||||
|
<!-- <div class="row" style="display: none;">
|
||||||
<div class="col-8">
|
<div class="col-8">
|
||||||
<div class="input-group input-group-sm mb-3">
|
<div class="input-group input-group-sm mb-3">
|
||||||
<input type="search" class="form-control" placeholder="{{_('Search')}}"
|
<input type="search" class="form-control" placeholder="{{_('Search')}}"
|
||||||
@ -29,22 +30,16 @@
|
|||||||
{{ _('Toggle Filters') }}
|
{{ _('Toggle Filters') }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> -->
|
||||||
|
|
||||||
|
<!-- Items section -->
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12 order-2 col-md-9 order-md-2 item-card-group-section">
|
<div id="product-listing" class="col-12 order-2 col-md-9 order-md-2 item-card-group-section">
|
||||||
<div class="row products-list">
|
<!-- Rendered via JS -->
|
||||||
{% if items %}
|
|
||||||
{% for item in items %}
|
|
||||||
{% include "erpnext/www/all-products/item_row.html" %}
|
|
||||||
{% endfor %}
|
|
||||||
{% else %}
|
|
||||||
{% include "erpnext/www/all-products/not_found.html" %}
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="col-12 order-1 col-md-3 order-md-1">
|
|
||||||
|
|
||||||
|
<!-- Filters Section -->
|
||||||
|
<div class="col-12 order-1 col-md-3 order-md-1">
|
||||||
{% if frappe.form_dict.start or frappe.form_dict.field_filters or frappe.form_dict.attribute_filters or frappe.form_dict.search %}
|
{% if frappe.form_dict.start or frappe.form_dict.field_filters or frappe.form_dict.attribute_filters or frappe.form_dict.search %}
|
||||||
|
|
||||||
|
|
||||||
@ -64,11 +59,6 @@
|
|||||||
{% if attribute_filters %}
|
{% if attribute_filters %}
|
||||||
{{ attribute_filter_section(attribute_filters) }}
|
{{ attribute_filter_section(attribute_filters) }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<!-- discount filters -->
|
|
||||||
{% if discount_filters %}
|
|
||||||
{{ discount_range_filters(discount_filters) }}
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -91,7 +81,10 @@
|
|||||||
</script>
|
</script>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row product-paging-area mt-5">
|
|
||||||
|
<!-- TODO -->
|
||||||
|
<!-- Paging Section -->
|
||||||
|
<!-- <div class="row product-paging-area mt-5">
|
||||||
<div class="col-3">
|
<div class="col-3">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-9 text-right">
|
<div class="col-9 text-right">
|
||||||
@ -102,7 +95,7 @@
|
|||||||
<button class="btn btn-default btn-next" data-start="{{ frappe.form_dict.start|int + page_length }}">{{ _("Next") }}</button>
|
<button class="btn btn-default btn-next" data-start="{{ frappe.form_dict.start|int + page_length }}">{{ _("Next") }}</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> -->
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
frappe.ready(() => {
|
frappe.ready(() => {
|
||||||
|
@ -1,6 +1,17 @@
|
|||||||
$(() => {
|
$(() => {
|
||||||
class ProductListing {
|
class ProductListing {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
let is_item_group_page = $(".item-group-content").data("item-group");
|
||||||
|
let item_group = is_item_group_page || null;
|
||||||
|
|
||||||
|
// Render Products
|
||||||
|
frappe.require('assets/js/e-commerce.min.js', function() {
|
||||||
|
new erpnext.ProductView({
|
||||||
|
products_section: $('#product-listing'),
|
||||||
|
item_group: item_group
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
this.bind_filters();
|
this.bind_filters();
|
||||||
this.bind_card_actions();
|
this.bind_card_actions();
|
||||||
this.bind_search();
|
this.bind_search();
|
||||||
@ -77,8 +88,8 @@ $(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bind_card_actions() {
|
bind_card_actions() {
|
||||||
erpnext.shopping_cart.bind_add_to_cart_action();
|
e_commerce.shopping_cart.bind_add_to_cart_action();
|
||||||
erpnext.wishlist.bind_wishlist_action();
|
e_commerce.wishlist.bind_wishlist_action();
|
||||||
}
|
}
|
||||||
|
|
||||||
bind_search() {
|
bind_search() {
|
||||||
|
@ -6,33 +6,55 @@ from erpnext.e_commerce.filters import ProductFiltersBuilder
|
|||||||
sitemap = 1
|
sitemap = 1
|
||||||
|
|
||||||
def get_context(context):
|
def get_context(context):
|
||||||
|
# Add homepage as parent
|
||||||
|
context.parents = [{"name": frappe._("Home"), "route":"/"}]
|
||||||
|
|
||||||
|
filter_engine = ProductFiltersBuilder()
|
||||||
|
context.field_filters = filter_engine.get_field_filters()
|
||||||
|
context.attribute_filters = filter_engine.get_attribute_filters()
|
||||||
|
|
||||||
|
context.page_length = cint(frappe.db.get_single_value('E Commerce Settings', 'products_per_page'))or 20
|
||||||
|
|
||||||
|
context.no_cache = 1
|
||||||
|
|
||||||
|
@frappe.whitelist(allow_guest=True)
|
||||||
|
def get_product_filter_data():
|
||||||
|
"""Get pre-rendered filtered products and discount filters on load."""
|
||||||
if frappe.form_dict:
|
if frappe.form_dict:
|
||||||
search = frappe.form_dict.search
|
search = frappe.form_dict.search
|
||||||
field_filters = frappe.parse_json(frappe.form_dict.field_filters)
|
field_filters = frappe.parse_json(frappe.form_dict.field_filters)
|
||||||
attribute_filters = frappe.parse_json(frappe.form_dict.attribute_filters)
|
attribute_filters = frappe.parse_json(frappe.form_dict.attribute_filters)
|
||||||
start = cint(frappe.parse_json(frappe.form_dict.start))
|
start = cint(frappe.parse_json(frappe.form_dict.start))
|
||||||
|
item_group = frappe.form_dict.item_group
|
||||||
else:
|
else:
|
||||||
search = field_filters = attribute_filters = None
|
search, attribute_filters, item_group = None, None, None
|
||||||
|
field_filters = {}
|
||||||
start = 0
|
start = 0
|
||||||
|
|
||||||
|
if item_group:
|
||||||
|
field_filters['item_group'] = item_group
|
||||||
|
|
||||||
engine = ProductQuery()
|
engine = ProductQuery()
|
||||||
context.items, discounts = engine.query(attribute_filters, field_filters, search, start)
|
items, discounts = engine.query(attribute_filters, field_filters, search_term=search, start=start)
|
||||||
|
|
||||||
# Add homepage as parent
|
item_html = []
|
||||||
context.parents = [{"name": frappe._("Home"), "route":"/"}]
|
for item in items:
|
||||||
|
item_html.append(frappe.render_template('erpnext/www/all-products/item_row.html', {
|
||||||
|
'item': item,
|
||||||
|
'e_commerce_settings': engine.settings
|
||||||
|
}))
|
||||||
|
html = ''.join(item_html)
|
||||||
|
|
||||||
filter_engine = ProductFiltersBuilder()
|
if not items:
|
||||||
|
html = frappe.render_template('erpnext/www/all-products/not_found.html', {})
|
||||||
|
|
||||||
context.field_filters = filter_engine.get_field_filters()
|
# discount filter data
|
||||||
context.attribute_filters = filter_engine.get_attribute_filters()
|
filters = {}
|
||||||
if discounts:
|
if discounts:
|
||||||
context.discount_filters = filter_engine.get_discount_filters(discounts)
|
filter_engine = ProductFiltersBuilder()
|
||||||
|
filters["discount_filters"] = filter_engine.get_discount_filters(discounts)
|
||||||
|
|
||||||
context.e_commerce_settings = engine.settings
|
return html, filters
|
||||||
context.page_length = engine.settings.products_per_page or 20
|
|
||||||
|
|
||||||
context.no_cache = 1
|
|
||||||
|
|
||||||
@frappe.whitelist(allow_guest=True)
|
@frappe.whitelist(allow_guest=True)
|
||||||
def get_products_html_for_website(field_filters=None, attribute_filters=None):
|
def get_products_html_for_website(field_filters=None, attribute_filters=None):
|
||||||
@ -47,7 +69,7 @@ def get_products_html_for_website(field_filters=None, attribute_filters=None):
|
|||||||
for item in items:
|
for item in items:
|
||||||
item_html.append(frappe.render_template('erpnext/www/all-products/item_row.html', {
|
item_html.append(frappe.render_template('erpnext/www/all-products/item_row.html', {
|
||||||
'item': item,
|
'item': item,
|
||||||
'e_commerce_settings': None
|
'e_commerce_settings': engine.settings
|
||||||
}))
|
}))
|
||||||
html = ''.join(item_html)
|
html = ''.join(item_html)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user