diff --git a/tailbone/grids/core.py b/tailbone/grids/core.py
index f918fad4..d825e4b4 100644
--- a/tailbone/grids/core.py
+++ b/tailbone/grids/core.py
@@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
-# Copyright © 2010-2021 Lance Edgar
+# Copyright © 2010-2022 Lance Edgar
#
# This file is part of Rattail.
#
@@ -197,7 +197,7 @@ class Grid(object):
"""
Mark the given column as "invisible" (but do not remove it).
- Use :meth:`hide_column()` if you actually want to remove it.
+ Use :meth:`remove()` if you actually want to remove it.
"""
if invisible:
if key not in self.invisible:
@@ -217,7 +217,7 @@ class Grid(object):
def replace(self, oldfield, newfield):
self.insert_after(oldfield, newfield)
- self.hide_column(oldfield)
+ self.remove(oldfield)
def set_joiner(self, key, joiner):
if joiner is None:
diff --git a/tailbone/templates/formposter.mako b/tailbone/templates/formposter.mako
index 6fc6eadc..885ac6c2 100644
--- a/tailbone/templates/formposter.mako
+++ b/tailbone/templates/formposter.mako
@@ -21,7 +21,8 @@
} else {
this.$buefy.toast.open({
- message: "Submit failed: " + response.data.error,
+ message: "Submit failed: " + (response.data.error ||
+ "(unknown error)"),
type: 'is-danger',
duration: 4000, // 4 seconds
})
diff --git a/tailbone/templates/master/index.mako b/tailbone/templates/master/index.mako
index 48e51286..5830519b 100644
--- a/tailbone/templates/master/index.mako
+++ b/tailbone/templates/master/index.mako
@@ -162,9 +162,6 @@
${h.link_to("Create a new {}".format(model_title), url('{}.create'.format(route_prefix)))}
% endif
% endif
- % if not use_buefy and master.configurable and master.has_perm('configure'):
- ${h.link_to("Configure {}".format(config_title), url('{}.configure'.format(route_prefix)))}
- % endif
% if master.has_input_file_templates and master.has_perm('create'):
% for template in six.itervalues(input_file_templates):
${h.link_to("Download {} Template".format(template['label']), template['effective_url'])}
diff --git a/tailbone/templates/products/configure.mako b/tailbone/templates/products/configure.mako
index 3b75bc7f..612b8d36 100644
--- a/tailbone/templates/products/configure.mako
+++ b/tailbone/templates/products/configure.mako
@@ -3,7 +3,7 @@
<%def name="form_content()">
- Key Field
+ Display
@@ -27,6 +27,15 @@
+
+
+ Show "POD" Images as fallback
+
+
+
Handling
@@ -43,18 +52,28 @@
- Display
+ Labels
-
-
+
- Show "POD" Images as fallback
+ Allow quick/direct label printing from Products page
+
+
+
+
+
%def>
diff --git a/tailbone/templates/products/index.mako b/tailbone/templates/products/index.mako
index 3f65cd68..8eada2fc 100644
--- a/tailbone/templates/products/index.mako
+++ b/tailbone/templates/products/index.mako
@@ -1,8 +1,9 @@
-## -*- coding: utf-8 -*-
+## -*- coding: utf-8; -*-
<%inherit file="/master/index.mako" />
<%def name="extra_styles()">
${parent.extra_styles()}
+ % if not use_buefy:
+ % endif
%def>
<%def name="extra_javascript()">
${parent.extra_javascript()}
- % if label_profiles and request.has_perm('products.print_labels'):
+ % if not use_buefy and label_profiles and master.has_perm('print_labels'):
+ % endif
+%def>
+
+
${parent.body()}
diff --git a/tailbone/views/master.py b/tailbone/views/master.py
index 7eb9ebc8..7fd3cccf 100644
--- a/tailbone/views/master.py
+++ b/tailbone/views/master.py
@@ -4368,6 +4368,8 @@ class MasterView(View):
if simple.get('type') is bool:
value = six.text_type(bool(value)).lower()
+ elif simple.get('type') is int:
+ value = six.text_type(int(value or '0'))
else:
value = six.text_type(value)
diff --git a/tailbone/views/products.py b/tailbone/views/products.py
index 0e192bca..cf7be401 100644
--- a/tailbone/views/products.py
+++ b/tailbone/views/products.py
@@ -181,7 +181,9 @@ class ProductView(MasterView):
self.print_labels = request.rattail_config.getbool('tailbone', 'products.print_labels', default=False)
app = self.get_rattail_app()
- self.handler = app.get_products_handler()
+ self.product_handler = app.get_products_handler()
+ # TODO: deprecate / remove this
+ self.handler = self.product_handler
def query(self, session):
user = self.request.user
@@ -358,8 +360,13 @@ class ProductView(MasterView):
g.set_sort_defaults('upc')
- if self.print_labels and self.request.has_perm('products.print_labels'):
- g.more_actions.append(grids.GridAction('print_label', icon='print'))
+ if self.print_labels and self.has_perm('print_labels'):
+ if use_buefy:
+ g.more_actions.append(self.make_action(
+ 'print_label', icon='print', url='#',
+ click_handler='quickLabelPrint(props.row)'))
+ else:
+ g.more_actions.append(grids.GridAction('print_label', icon='print'))
g.set_type('upc', 'gpc')
@@ -522,7 +529,7 @@ class ProductView(MasterView):
if not product.not_for_sale:
price = product[field]
if price:
- return self.handler.render_price(price)
+ return self.product_handler.render_price(price)
def render_current_price_for_grid(self, product, field):
text = self.render_price(product, field) or ""
@@ -651,13 +658,20 @@ class ProductView(MasterView):
return pretty_quantity(inventory.on_order)
def template_kwargs_index(self, **kwargs):
- if self.print_labels:
- kwargs['label_profiles'] = Session.query(model.LabelProfile)\
- .filter(model.LabelProfile.visible == True)\
- .order_by(model.LabelProfile.ordinal)\
- .all()
- return kwargs
+ kwargs = super(ProductView, self).template_kwargs_index(**kwargs)
+ model = self.model
+ if self.print_labels:
+
+ kwargs['label_profiles'] = self.Session.query(model.LabelProfile)\
+ .filter(model.LabelProfile.visible == True)\
+ .order_by(model.LabelProfile.ordinal)\
+ .all()
+
+ kwargs['quick_label_speedbump_threshold'] = self.rattail_config.getint(
+ 'tailbone', 'products.quick_labels.speedbump_threshold')
+
+ return kwargs
def grid_extra_class(self, product, i):
classes = []
@@ -794,10 +808,10 @@ class ProductView(MasterView):
def get_instance(self):
key = self.request.matchdict['uuid']
- product = Session.query(model.Product).get(key)
+ product = self.Session.query(model.Product).get(key)
if product:
return product
- price = Session.query(model.ProductPrice).get(key)
+ price = self.Session.query(model.ProductPrice).get(key)
if price:
return price.product
raise httpexceptions.HTTPNotFound()
@@ -1151,7 +1165,7 @@ class ProductView(MasterView):
product = kwargs['instance']
use_buefy = self.get_use_buefy()
- kwargs['image_url'] = self.handler.get_image_url(product)
+ kwargs['image_url'] = self.product_handler.get_image_url(product)
kwargs['product_key_field'] = self.rattail_config.product_key()
# add price history, if user has access
@@ -1701,11 +1715,11 @@ class ProductView(MasterView):
upc = self.request.GET.get('upc', '').strip()
upc = re.sub(r'\D', '', upc)
if upc:
- product = api.get_product_by_upc(Session(), upc)
+ product = api.get_product_by_upc(self.Session(), upc)
if not product:
# Try again, assuming caller did not include check digit.
upc = GPC(upc, calc_check_digit='upc')
- product = api.get_product_by_upc(Session(), upc)
+ product = api.get_product_by_upc(self.Session(), upc)
if product and (not product.deleted or self.request.has_perm('products.view_deleted')):
data = {
'uuid': product.uuid,
@@ -1716,7 +1730,7 @@ class ProductView(MasterView):
}
uuid = self.request.GET.get('with_vendor_cost')
if uuid:
- vendor = Session.query(model.Vendor).get(uuid)
+ vendor = self.Session.query(model.Vendor).get(uuid)
if not vendor:
return {'error': "Vendor not found"}
cost = product.cost_for_vendor(vendor)
@@ -1912,21 +1926,28 @@ class ProductView(MasterView):
def configure_get_simple_settings(self):
return [
- # key field
+ # display
{'section': 'rattail',
'option': 'product.key'},
{'section': 'rattail',
'option': 'product.key_title'},
+ {'section': 'tailbone',
+ 'option': 'products.show_pod_image',
+ 'type': bool},
# handling
{'section': 'rattail',
'option': 'products.convert_type2_for_gpc_lookup',
'type': bool},
- # display
+ # labels
{'section': 'tailbone',
- 'option': 'products.show_pod_image',
+ 'option': 'products.print_labels',
'type': bool},
+ {'section': 'tailbone',
+ 'option': 'products.quick_labels.speedbump_threshold',
+ 'type': int},
+
]
@classmethod
@@ -2254,7 +2275,7 @@ def print_labels(request):
except Exception as error:
log.warning("error occurred while printing labels", exc_info=True)
return {'error': six.text_type(error)}
- return {}
+ return {'ok': True}
def includeme(config):