Add view for consuming new batch ID; misc. tweaks for grids etc.

This commit is contained in:
Lance Edgar 2017-08-02 19:16:45 -05:00
parent 6ae129ea24
commit 8186366b69
5 changed files with 76 additions and 38 deletions

View file

@ -26,6 +26,7 @@ Core Grid Classes
from __future__ import unicode_literals, absolute_import from __future__ import unicode_literals, absolute_import
import datetime
import urllib import urllib
import six import six
@ -34,7 +35,7 @@ from sqlalchemy import orm
from rattail.db import api from rattail.db import api
from rattail.db.types import GPCType from rattail.db.types import GPCType
from rattail.util import pretty_boolean, pretty_quantity, prettify from rattail.util import prettify, pretty_boolean, pretty_quantity, pretty_hours
import webhelpers2_grid import webhelpers2_grid
from pyramid.renderers import render from pyramid.renderers import render
@ -149,6 +150,8 @@ class Grid(object):
self.set_renderer(key, self.render_percent) self.set_renderer(key, self.render_percent)
elif type_ == 'quantity': elif type_ == 'quantity':
self.set_renderer(key, self.render_quantity) self.set_renderer(key, self.render_quantity)
elif type_ == 'duration':
self.set_renderer(key, self.render_duration)
else: else:
raise ValueError("Unsupported type for column '{}': {}".format(key, type_)) raise ValueError("Unsupported type for column '{}': {}".format(key, type_))
@ -211,6 +214,12 @@ class Grid(object):
value = self.obtain_value(obj, column_name) value = self.obtain_value(obj, column_name)
return pretty_quantity(value) return pretty_quantity(value)
def render_duration(self, obj, column_name):
value = self.obtain_value(obj, column_name)
if value is None:
return ""
return pretty_hours(datetime.timedelta(seconds=value))
def set_url(self, url): def set_url(self, url):
self.url = url self.url = url

View file

@ -24,6 +24,7 @@
.grid-wrapper .grid-header td.tools { .grid-wrapper .grid-header td.tools {
margin: 0; margin: 0;
padding: 0; padding: 0;
text-align: right;
vertical-align: bottom; vertical-align: bottom;
white-space: nowrap; white-space: nowrap;
} }

View file

@ -27,13 +27,16 @@ function disable_filter_options() {
/* /*
* Convenience function to disable a form button. * Convenience function to disable a UI button.
*/ */
function disable_button(button, label) { function disable_button(button, label) {
if (label) { $(button).button('disable');
$(button).html(label + ", please wait..."); if (label === undefined) {
label = "Working, please wait...";
}
if (label) {
$(button).button('option', 'label', label);
} }
$(button).attr('disabled', 'disabled');
} }

View file

@ -90,37 +90,39 @@
## ${grid.render_complete(tools=capture(self.grid_tools).strip(), context_menu=capture(self.context_menu_items).strip())|n} ## ${grid.render_complete(tools=capture(self.grid_tools).strip(), context_menu=capture(self.context_menu_items).strip())|n}
<div class="grid-wrapper"> ${grid.render_complete(tools=capture(self.grid_tools).strip(), context_menu=capture(self.context_menu_items).strip())|n}
<table class="grid-header"> ## <div class="grid-wrapper">
<tbody> ##
<tr> ## <table class="grid-header">
## <tbody>
<td class="filters" rowspan="2"> ## <tr>
% if grid.filterable: ##
## TODO: should this be variable sometimes? ## <td class="filters" rowspan="2">
${grid.render_filters(allow_save_defaults=True)|n} ## % if grid.filterable:
% endif ## ## TODO: should this be variable sometimes?
</td> ## ${grid.render_filters(allow_save_defaults=True)|n}
## % endif
<td class="menu"> ## </td>
<ul id="context-menu"> ##
${self.context_menu_items()} ## <td class="menu">
</ul> ## <ul id="context-menu">
</td> ## ${self.context_menu_items()}
</tr> ## </ul>
## </td>
<tr> ## </tr>
<td class="tools"> ##
<div class="grid-tools"> ## <tr>
${self.grid_tools()} ## <td class="tools">
</div><!-- grid-tools --> ## <div class="grid-tools">
</td> ## ${self.grid_tools()}
</tr> ## </div><!-- grid-tools -->
## </td>
</tbody> ## </tr>
</table><!-- grid-header --> ##
## </tbody>
${grid.render_grid()|n} ## </table><!-- grid-header -->
##
</div><!-- grid-wrapper --> ## ${grid.render_grid()|n}
##
## </div><!-- grid-wrapper -->

View file

@ -29,6 +29,7 @@ from __future__ import unicode_literals, absolute_import
import six import six
import rattail import rattail
from rattail.batch import consume_batch_id
from rattail.mail import send_email from rattail.mail import send_email
from rattail.util import OrderedDict from rattail.util import OrderedDict
from rattail.files import resource_path from rattail.files import resource_path
@ -40,6 +41,7 @@ from pyramid_simpleform import Form
import tailbone import tailbone
from tailbone import forms from tailbone import forms
from tailbone.db import Session
from tailbone.views import View from tailbone.views import View
@ -124,6 +126,14 @@ class CommonView(View):
return httpexceptions.HTTPFound(location=form.data['referrer']) return httpexceptions.HTTPFound(location=form.data['referrer'])
return {'form': forms.FormRenderer(form)} return {'form': forms.FormRenderer(form)}
def consume_batch_id(self):
"""
Consume next batch ID from the PG sequence, and display via flash message.
"""
batch_id = consume_batch_id(Session())
self.request.session.flash("Batch ID has been consumed: {:08d}".format(batch_id))
return self.redirect(self.request.get_referrer())
def bogus_error(self): def bogus_error(self):
""" """
A special view which simply raises an error, for the sake of testing A special view which simply raises an error, for the sake of testing
@ -133,6 +143,10 @@ class CommonView(View):
@classmethod @classmethod
def defaults(cls, config): def defaults(cls, config):
cls._defaults(config)
@classmethod
def _defaults(cls, config):
rattail_config = config.registry.settings.get('rattail_config') rattail_config = config.registry.settings.get('rattail_config')
# auto-correct URLs which require trailing slash # auto-correct URLs which require trailing slash
@ -142,6 +156,9 @@ class CommonView(View):
if rattail_config and rattail_config.production(): if rattail_config and rattail_config.production():
config.add_exception_view(cls, attr='exception', renderer='/exception.mako') config.add_exception_view(cls, attr='exception', renderer='/exception.mako')
# permissions
config.add_tailbone_permission_group('common', "(common)", overwrite=False)
# home # home
config.add_route('home', '/') config.add_route('home', '/')
config.add_view(cls, attr='home', route_name='home', renderer='/home.mako') config.add_view(cls, attr='home', route_name='home', renderer='/home.mako')
@ -162,6 +179,12 @@ class CommonView(View):
config.add_route('feedback', '/feedback') config.add_route('feedback', '/feedback')
config.add_view(cls, attr='feedback', route_name='feedback', renderer='/feedback.mako') config.add_view(cls, attr='feedback', route_name='feedback', renderer='/feedback.mako')
# consume batch ID
config.add_tailbone_permission('common', 'common.consume_batch_id',
"Consume new Batch ID")
config.add_route('consume_batch_id', '/consume-batch-id')
config.add_view(cls, attr='consume_batch_id', route_name='consume_batch_id')
# bogus error # bogus error
config.add_route('bogus_error', '/bogus-error') config.add_route('bogus_error', '/bogus-error')
config.add_view(cls, attr='bogus_error', route_name='bogus_error', permission='errors.bogus') config.add_view(cls, attr='bogus_error', route_name='bogus_error', permission='errors.bogus')