Add support for making new product on-the-fly during mobile ordering
let's face it, that will be necessary sometimes. this feature still needs some work before can be called complete though...
This commit is contained in:
parent
6ec0ddb94e
commit
652f51d484
|
@ -52,7 +52,7 @@ div.fieldset {
|
||||||
margin: 15px;
|
margin: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.field-wrapper.error {
|
.field-wrapper.with-error {
|
||||||
background-color: #ddcccc;
|
background-color: #ddcccc;
|
||||||
border: 2px solid #dd6666;
|
border: 2px solid #dd6666;
|
||||||
padding-bottom: 1em;
|
padding-bottom: 1em;
|
||||||
|
@ -71,7 +71,7 @@ div.fieldset {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.field-wrapper.error label {
|
.field-wrapper.with-error label {
|
||||||
padding-left: 1em;
|
padding-left: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
/* error flash messages */
|
/* error flash messages */
|
||||||
.error {
|
.error,
|
||||||
|
.error-messages {
|
||||||
color: red;
|
color: red;
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
}
|
}
|
||||||
|
@ -35,11 +36,21 @@
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.field-wrapper.with-error {
|
||||||
|
background-color: #ddcccc;
|
||||||
|
border: 2px solid #dd6666;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
.field-wrapper label {
|
.field-wrapper label {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
margin-top: 1em;
|
margin-top: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.field-error .error-msg {
|
||||||
|
color: Red;
|
||||||
|
}
|
||||||
|
|
||||||
/* make sure space comes between simple filter and "grid" list */
|
/* make sure space comes between simple filter and "grid" list */
|
||||||
.simple-filter {
|
.simple-filter {
|
||||||
margin-bottom: 1.5em;
|
margin-bottom: 1.5em;
|
||||||
|
|
|
@ -30,7 +30,7 @@ ${h.csrf_token(request)}
|
||||||
<% field = dform[field] %>
|
<% field = dform[field] %>
|
||||||
|
|
||||||
% if form.field_visible(field.name):
|
% if form.field_visible(field.name):
|
||||||
<div class="field-wrapper ${field.name} ${'error' if field.error else ''}">
|
<div class="field-wrapper ${field.name} ${'with-error' if field.error else ''}">
|
||||||
% if field.error:
|
% if field.error:
|
||||||
<div class="field-error">
|
<div class="field-error">
|
||||||
% for msg in field.error.messages():
|
% for msg in field.error.messages():
|
||||||
|
|
|
@ -5,12 +5,14 @@
|
||||||
|
|
||||||
<%def name="page_title()">${h.link_to(index_title, index_url)} » ${h.link_to(parent_title, parent_url)} » ${h.link_to(instance_title, instance_url)} » Edit</%def>
|
<%def name="page_title()">${h.link_to(index_title, index_url)} » ${h.link_to(parent_title, parent_url)} » ${h.link_to(instance_title, instance_url)} » Edit</%def>
|
||||||
|
|
||||||
<%def name="buttons()">
|
## TODO: this should not be necessary, correct?
|
||||||
<br />
|
## <%def name="buttons()">
|
||||||
${h.submit('create', form.update_label)}
|
## <br />
|
||||||
<a href="${form.cancel_url}" class="ui-btn">Cancel</a>
|
## ${h.submit('create', form.update_label)}
|
||||||
</%def>
|
## ${h.link_to("Cancel", form.cancel_url, class_='ui-btn ui-corner-all')}
|
||||||
|
## </%def>
|
||||||
|
|
||||||
<div class="form-wrapper">
|
<div class="form-wrapper">
|
||||||
${form.render(buttons=capture(self.buttons))|n}
|
## ${form.render(buttons=capture(self.buttons))|n}
|
||||||
|
${form.render()|n}
|
||||||
</div><!-- form-wrapper -->
|
</div><!-- form-wrapper -->
|
||||||
|
|
6
tailbone/templates/mobile/ordering/new_product.mako
Normal file
6
tailbone/templates/mobile/ordering/new_product.mako
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
## -*- coding: utf-8; -*-
|
||||||
|
<%inherit file="/mobile/master/create_row.mako" />
|
||||||
|
|
||||||
|
<%def name="page_title()">${h.link_to(index_title, index_url)} » ${h.link_to(instance_title, instance_url)} » Add Item</%def>
|
||||||
|
|
||||||
|
${parent.body()}
|
|
@ -1045,6 +1045,7 @@ class MasterView(View):
|
||||||
"""
|
"""
|
||||||
defaults = {
|
defaults = {
|
||||||
'request': self.request,
|
'request': self.request,
|
||||||
|
'mobile': True,
|
||||||
'readonly': self.viewing,
|
'readonly': self.viewing,
|
||||||
'model_class': getattr(self, 'model_row_class', None),
|
'model_class': getattr(self, 'model_row_class', None),
|
||||||
'action_url': self.request.current_route_url(_query=None),
|
'action_url': self.request.current_route_url(_query=None),
|
||||||
|
|
|
@ -47,6 +47,7 @@ class PurchasingBatchView(BatchMasterView):
|
||||||
model_class = model.PurchaseBatch
|
model_class = model.PurchaseBatch
|
||||||
model_row_class = model.PurchaseBatchRow
|
model_row_class = model.PurchaseBatchRow
|
||||||
default_handler_spec = 'rattail.batch.purchase:PurchaseBatchHandler'
|
default_handler_spec = 'rattail.batch.purchase:PurchaseBatchHandler'
|
||||||
|
supports_new_product = False
|
||||||
|
|
||||||
grid_columns = [
|
grid_columns = [
|
||||||
'id',
|
'id',
|
||||||
|
@ -701,6 +702,42 @@ class PurchasingBatchView(BatchMasterView):
|
||||||
# else:
|
# else:
|
||||||
# f.remove_field('product')
|
# f.remove_field('product')
|
||||||
|
|
||||||
|
def mobile_new_product(self):
|
||||||
|
"""
|
||||||
|
View which allows user to create a new Product and add a row for it to
|
||||||
|
the Purchasing Batch.
|
||||||
|
"""
|
||||||
|
batch = self.get_instance()
|
||||||
|
batch_url = self.get_action_url('view', batch, mobile=True)
|
||||||
|
form = forms.Form(schema=self.make_new_product_schema(),
|
||||||
|
request=self.request,
|
||||||
|
mobile=True,
|
||||||
|
cancel_url=batch_url)
|
||||||
|
|
||||||
|
if form.validate(newstyle=True):
|
||||||
|
product = model.Product()
|
||||||
|
product.item_id = form.validated['item_id']
|
||||||
|
product.description = form.validated['description']
|
||||||
|
row = self.model_row_class()
|
||||||
|
row.product = product
|
||||||
|
self.handler.add_row(batch, row)
|
||||||
|
self.Session.flush()
|
||||||
|
return self.redirect(self.get_row_action_url('edit', row, mobile=True))
|
||||||
|
|
||||||
|
return self.render_to_response('new_product', {
|
||||||
|
'form': form,
|
||||||
|
'dform': form.make_deform_form(),
|
||||||
|
'instance_title': self.get_instance_title(batch),
|
||||||
|
'instance_url': batch_url,
|
||||||
|
}, mobile=True)
|
||||||
|
|
||||||
|
def make_new_product_schema(self):
|
||||||
|
"""
|
||||||
|
Must return a ``colander.Schema`` instance for use with the form in the
|
||||||
|
:meth:`mobile_new_product()` view.
|
||||||
|
"""
|
||||||
|
return NewProduct()
|
||||||
|
|
||||||
# def item_lookup(self, value, field=None):
|
# def item_lookup(self, value, field=None):
|
||||||
# """
|
# """
|
||||||
# Try to locate a single product using ``value`` as a lookup code.
|
# Try to locate a single product using ``value`` as a lookup code.
|
||||||
|
@ -785,8 +822,24 @@ class PurchasingBatchView(BatchMasterView):
|
||||||
config.add_view(cls, attr='eligible_purchases', route_name='{}.eligible_purchases'.format(route_prefix),
|
config.add_view(cls, attr='eligible_purchases', route_name='{}.eligible_purchases'.format(route_prefix),
|
||||||
renderer='json', permission='{}.view'.format(permission_prefix))
|
renderer='json', permission='{}.view'.format(permission_prefix))
|
||||||
|
|
||||||
|
# add new product
|
||||||
|
if cls.supports_new_product:
|
||||||
|
config.add_tailbone_permission(permission_prefix, '{}.new_product'.format(permission_prefix),
|
||||||
|
"Create new Product when adding row to {}".format(model_title))
|
||||||
|
config.add_route('mobile.{}.new_product'.format(route_prefix), '{}/{{{}}}/new-product'.format(url_prefix, model_key))
|
||||||
|
config.add_view(cls, attr='mobile_new_product', route_name='mobile.{}.new_product'.format(route_prefix),
|
||||||
|
permission='{}.new_product'.format(permission_prefix))
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def defaults(cls, config):
|
def defaults(cls, config):
|
||||||
cls._purchasing_defaults(config)
|
cls._purchasing_defaults(config)
|
||||||
cls._batch_defaults(config)
|
cls._batch_defaults(config)
|
||||||
cls._defaults(config)
|
cls._defaults(config)
|
||||||
|
|
||||||
|
|
||||||
|
class NewProduct(colander.Schema):
|
||||||
|
|
||||||
|
item_id = colander.SchemaNode(colander.String())
|
||||||
|
|
||||||
|
description = colander.SchemaNode(colander.String())
|
||||||
|
|
Loading…
Reference in a new issue