Refactor batch execution options to use colander/deform
This commit is contained in:
parent
2cbacd6187
commit
dd04459748
|
@ -697,7 +697,7 @@ class Form(object):
|
||||||
context = kwargs
|
context = kwargs
|
||||||
context['form'] = self
|
context['form'] = self
|
||||||
context['dform'] = dform
|
context['dform'] = dform
|
||||||
context['form_kwargs'] = {}
|
context.setdefault('form_kwargs', {})
|
||||||
# TODO: deprecate / remove the latter option here
|
# TODO: deprecate / remove the latter option here
|
||||||
if self.auto_disable_save or self.auto_disable:
|
if self.auto_disable_save or self.auto_disable:
|
||||||
context['form_kwargs']['class_'] = 'autodisable'
|
context['form_kwargs']['class_'] = 'autodisable'
|
||||||
|
|
12
tailbone/static/js/jquery.ui.tailbone.js
vendored
12
tailbone/static/js/jquery.ui.tailbone.js
vendored
|
@ -261,6 +261,18 @@
|
||||||
that.grid.gridcore();
|
that.grid.gridcore();
|
||||||
that.element.unmask();
|
that.element.unmask();
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
results_count: function(as_text) {
|
||||||
|
var count = null;
|
||||||
|
var match = /showing \d+ thru \d+ of (\S+)/.exec(this.element.find('.pager .showing').text());
|
||||||
|
if (match) {
|
||||||
|
count = match[1];
|
||||||
|
if (!as_text) {
|
||||||
|
count = parseInt(count, 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,8 +10,6 @@
|
||||||
|
|
||||||
$(function() {
|
$(function() {
|
||||||
|
|
||||||
$('.grid-wrapper').gridwrapper();
|
|
||||||
|
|
||||||
$('#execute-batch').click(function() {
|
$('#execute-batch').click(function() {
|
||||||
if (has_execution_options) {
|
if (has_execution_options) {
|
||||||
$('#execution-options-dialog').dialog({
|
$('#execution-options-dialog').dialog({
|
||||||
|
|
|
@ -6,8 +6,6 @@
|
||||||
${h.javascript_link(request.static_url('tailbone:static/js/tailbone.batch.js'))}
|
${h.javascript_link(request.static_url('tailbone:static/js/tailbone.batch.js'))}
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
||||||
var has_execution_options = ${'true' if master.has_execution_options(batch) else 'false'};
|
|
||||||
|
|
||||||
$(function() {
|
$(function() {
|
||||||
|
|
||||||
$('#save-refresh').click(function() {
|
$('#save-refresh').click(function() {
|
||||||
|
@ -55,13 +53,3 @@
|
||||||
<div class="form-wrapper">
|
<div class="form-wrapper">
|
||||||
${form.render()|n}
|
${form.render()|n}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="execution-options-dialog" style="display: none;">
|
|
||||||
|
|
||||||
${h.form(url('{}.execute'.format(route_prefix), uuid=batch.uuid), name='batch-execution')}
|
|
||||||
% if master.has_execution_options(batch):
|
|
||||||
${rendered_execution_options|n}
|
|
||||||
% endif
|
|
||||||
${h.end_form()}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
## -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
${form.field_div('action', form.select('action', options=ACTION_OPTIONS), label="Action to Perform")}
|
|
|
@ -12,6 +12,11 @@
|
||||||
$(function() {
|
$(function() {
|
||||||
|
|
||||||
$('#execute-results-button').click(function() {
|
$('#execute-results-button').click(function() {
|
||||||
|
var count = $('.grid-wrapper').gridwrapper('results_count');
|
||||||
|
if (!count) {
|
||||||
|
alert("There are no batch results to execute.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
var form = $('form[name="execute-results"]');
|
var form = $('form[name="execute-results"]');
|
||||||
if (has_execution_options) {
|
if (has_execution_options) {
|
||||||
$('#execution-options-dialog').dialog({
|
$('#execution-options-dialog').dialog({
|
||||||
|
@ -66,16 +71,11 @@ ${parent.body()}
|
||||||
|
|
||||||
% if master.results_executable and request.has_perm('{}.execute_multiple'.format(permission_prefix)):
|
% if master.results_executable and request.has_perm('{}.execute_multiple'.format(permission_prefix)):
|
||||||
<div id="execution-options-dialog" style="display: none;">
|
<div id="execution-options-dialog" style="display: none;">
|
||||||
${h.form(url('{}.execute_results'.format(route_prefix)), name='execute-results')}
|
|
||||||
${h.csrf_token(request)}
|
|
||||||
<br />
|
<br />
|
||||||
<p>
|
<p>
|
||||||
Please be advised, you are about to execute multiple batches!
|
Please be advised, you are about to execute multiple batches!
|
||||||
</p>
|
</p>
|
||||||
<br />
|
<br />
|
||||||
% if master.has_execution_options(batch):
|
${execute_form.render_deform(form_kwargs={'name': 'execute-results'}, buttons=False)|n}
|
||||||
${rendered_execution_options|n}
|
|
||||||
% endif
|
|
||||||
${h.end_form()}
|
|
||||||
</div>
|
</div>
|
||||||
% endif
|
% endif
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
<%def name="extra_javascript()">
|
||||||
${parent.extra_javascript()}
|
${parent.extra_javascript()}
|
||||||
${h.javascript_link(request.static_url('tailbone:static/js/tailbone.batch.js'))}
|
${h.javascript_link(request.static_url('tailbone:static/js/tailbone.batch.js') + '?ver={}'.format(tailbone.__version__))}
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
||||||
var has_execution_options = ${'true' if master.has_execution_options(batch) else 'false'};
|
var has_execution_options = ${'true' if master.has_execution_options(batch) else 'false'};
|
||||||
|
@ -84,13 +84,6 @@ ${rows_grid|n}
|
||||||
|
|
||||||
% if not batch.executed:
|
% if not batch.executed:
|
||||||
<div id="execution-options-dialog" style="display: none;">
|
<div id="execution-options-dialog" style="display: none;">
|
||||||
|
${execute_form.render_deform(form_kwargs={'name': 'batch-execution'}, buttons=False)|n}
|
||||||
${h.form(url('{}.execute'.format(route_prefix), uuid=batch.uuid), name='batch-execution')}
|
|
||||||
${h.csrf_token(request)}
|
|
||||||
% if master.has_execution_options(batch):
|
|
||||||
${rendered_execution_options|n}
|
|
||||||
% endif
|
|
||||||
${h.end_form()}
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
% endif
|
% endif
|
||||||
|
|
|
@ -43,11 +43,8 @@
|
||||||
% if master.bulk_deletable and request.has_perm('{}.bulk_delete'.format(permission_prefix)):
|
% if master.bulk_deletable and request.has_perm('{}.bulk_delete'.format(permission_prefix)):
|
||||||
|
|
||||||
$('form[name="bulk-delete"] button').click(function() {
|
$('form[name="bulk-delete"] button').click(function() {
|
||||||
var count = 0;
|
var count = $('.grid-wrapper').gridwrapper('results_count', true);
|
||||||
var match = /showing \d+ thru \d+ of (\S+)/.exec($('.pager .showing').text());
|
if (count === null) {
|
||||||
if (match) {
|
|
||||||
count = match[1];
|
|
||||||
} else {
|
|
||||||
alert("There don't seem to be any results to delete!");
|
alert("There don't seem to be any results to delete!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ from __future__ import unicode_literals, absolute_import
|
||||||
import os
|
import os
|
||||||
import datetime
|
import datetime
|
||||||
import logging
|
import logging
|
||||||
|
import tempfile
|
||||||
from cStringIO import StringIO
|
from cStringIO import StringIO
|
||||||
|
|
||||||
import six
|
import six
|
||||||
|
@ -39,13 +40,16 @@ from rattail.db import model, Session as RattailSession
|
||||||
from rattail.threads import Thread
|
from rattail.threads import Thread
|
||||||
from rattail.util import load_object, prettify
|
from rattail.util import load_object, prettify
|
||||||
|
|
||||||
|
import colander
|
||||||
|
import deform
|
||||||
|
from deform import widget as dfwidget
|
||||||
from pyramid import httpexceptions
|
from pyramid import httpexceptions
|
||||||
from pyramid.renderers import render_to_response
|
from pyramid.renderers import render_to_response
|
||||||
from pyramid.response import FileResponse
|
from pyramid.response import FileResponse
|
||||||
from pyramid_simpleform import Form
|
from pyramid_deform import SessionFileUploadTempStore
|
||||||
from webhelpers2.html import HTML, tags
|
from webhelpers2.html import HTML, tags
|
||||||
|
|
||||||
from tailbone import forms, grids
|
from tailbone import forms2 as forms, grids
|
||||||
from tailbone.db import Session
|
from tailbone.db import Session
|
||||||
from tailbone.views import MasterView
|
from tailbone.views import MasterView
|
||||||
from tailbone.progress import SessionProgress
|
from tailbone.progress import SessionProgress
|
||||||
|
@ -133,8 +137,9 @@ class BatchMasterView(MasterView):
|
||||||
kwargs['handler'] = self.handler
|
kwargs['handler'] = self.handler
|
||||||
kwargs['execute_title'] = self.get_execute_title(batch)
|
kwargs['execute_title'] = self.get_execute_title(batch)
|
||||||
kwargs['execute_enabled'] = self.instance_executable(batch)
|
kwargs['execute_enabled'] = self.instance_executable(batch)
|
||||||
if kwargs['execute_enabled'] and self.has_execution_options(batch):
|
if kwargs['execute_enabled']:
|
||||||
kwargs['rendered_execution_options'] = self.render_execution_options(batch)
|
url = self.get_action_url('execute', batch)
|
||||||
|
kwargs['execute_form'] = self.make_execute_form(batch, action_url=url)
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
def allow_worksheet(self, batch):
|
def allow_worksheet(self, batch):
|
||||||
|
@ -179,22 +184,12 @@ class BatchMasterView(MasterView):
|
||||||
return batch.id_str
|
return batch.id_str
|
||||||
|
|
||||||
def template_kwargs_index(self, **kwargs):
|
def template_kwargs_index(self, **kwargs):
|
||||||
kwargs['execute_enabled'] = self.instance_executable(None)
|
route_prefix = self.get_route_prefix()
|
||||||
if kwargs['execute_enabled'] and self.has_execution_options():
|
if self.results_executable:
|
||||||
kwargs['rendered_execution_options'] = self.render_execution_options()
|
url = self.request.route_url('{}.execute_results'.format(route_prefix))
|
||||||
|
kwargs['execute_form'] = self.make_execute_form(action_url=url)
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
def render_execution_options(self, batch=None):
|
|
||||||
if batch is None:
|
|
||||||
batch = self.model_class
|
|
||||||
form = self.make_execution_options_form(batch)
|
|
||||||
kwargs = {
|
|
||||||
'batch': batch,
|
|
||||||
'form': forms.FormRenderer(form),
|
|
||||||
}
|
|
||||||
kwargs = self.get_exec_options_kwargs(**kwargs)
|
|
||||||
return self.render('exec_options', kwargs)
|
|
||||||
|
|
||||||
def get_exec_options_kwargs(self, **kwargs):
|
def get_exec_options_kwargs(self, **kwargs):
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
|
@ -422,10 +417,6 @@ class BatchMasterView(MasterView):
|
||||||
def template_kwargs_edit(self, **kwargs):
|
def template_kwargs_edit(self, **kwargs):
|
||||||
batch = kwargs['instance']
|
batch = kwargs['instance']
|
||||||
kwargs['batch'] = batch
|
kwargs['batch'] = batch
|
||||||
kwargs['execute_title'] = self.get_execute_title(batch)
|
|
||||||
kwargs['execute_enabled'] = self.instance_executable(batch)
|
|
||||||
if kwargs['execute_enabled'] and self.has_execution_options(batch):
|
|
||||||
kwargs['rendered_execution_options'] = self.render_execution_options(batch)
|
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
def mobile_mark_complete(self):
|
def mobile_mark_complete(self):
|
||||||
|
@ -609,19 +600,28 @@ class BatchMasterView(MasterView):
|
||||||
# TODO
|
# TODO
|
||||||
execution_options_schema = None
|
execution_options_schema = None
|
||||||
|
|
||||||
def make_execution_options_form(self, batch=None):
|
def make_execute_schema(self):
|
||||||
|
return self.execution_options_schema()
|
||||||
|
|
||||||
|
def make_execute_form(self, batch=None, **kwargs):
|
||||||
"""
|
"""
|
||||||
Return a proper Form for execution options.
|
Return a proper Form for execution options.
|
||||||
"""
|
"""
|
||||||
if batch is None:
|
|
||||||
batch = self.model_class
|
|
||||||
defaults = {}
|
defaults = {}
|
||||||
for field in self.execution_options_schema.fields:
|
route_prefix = self.get_route_prefix()
|
||||||
key = 'batch.{}.execute_option.{}'.format(batch.batch_key, field)
|
|
||||||
if key in self.request.session:
|
if self.has_execution_options(batch):
|
||||||
defaults[field] = self.request.session[key]
|
if batch is None:
|
||||||
return Form(self.request, schema=self.execution_options_schema,
|
batch = self.model_class
|
||||||
defaults=defaults or None)
|
schema = self.make_execute_schema()
|
||||||
|
for field in schema:
|
||||||
|
key = 'batch.{}.execute_option.{}'.format(batch.batch_key, field.name)
|
||||||
|
if key in self.request.session:
|
||||||
|
defaults[field.name] = self.request.session[key]
|
||||||
|
else:
|
||||||
|
schema = colander.Schema()
|
||||||
|
|
||||||
|
return forms.Form(schema=schema, request=self.request, defaults=defaults, **kwargs)
|
||||||
|
|
||||||
def get_execute_title(self, batch):
|
def get_execute_title(self, batch):
|
||||||
if hasattr(self.handler, 'get_execute_title'):
|
if hasattr(self.handler, 'get_execute_title'):
|
||||||
|
@ -855,7 +855,8 @@ class BatchMasterView(MasterView):
|
||||||
"""
|
"""
|
||||||
batch = self.get_instance()
|
batch = self.get_instance()
|
||||||
query = self.get_effective_row_data(sort=False)
|
query = self.get_effective_row_data(sort=False)
|
||||||
batch.rowcount -= query.count()
|
if batch.rowcount is not None:
|
||||||
|
batch.rowcount -= query.count()
|
||||||
query.update({'removed': True}, synchronize_session=False)
|
query.update({'removed': True}, synchronize_session=False)
|
||||||
return self.redirect(self.get_action_url('view', batch))
|
return self.redirect(self.get_action_url('view', batch))
|
||||||
|
|
||||||
|
@ -865,17 +866,14 @@ class BatchMasterView(MasterView):
|
||||||
displays a progress indicator page.
|
displays a progress indicator page.
|
||||||
"""
|
"""
|
||||||
batch = self.get_instance()
|
batch = self.get_instance()
|
||||||
if self.request.method == 'POST':
|
self.executing = True
|
||||||
|
form = self.make_execute_form(batch)
|
||||||
|
if form.validate(newstyle=True):
|
||||||
|
kwargs = dict(form.validated)
|
||||||
|
|
||||||
kwargs = {}
|
# cache options to use as defaults next time
|
||||||
if self.has_execution_options(batch):
|
for key, value in form.validated.items():
|
||||||
form = self.make_execution_options_form(batch)
|
self.request.session['batch.{}.execute_option.{}'.format(batch.batch_key, key)] = value
|
||||||
assert form.validate() # TODO
|
|
||||||
kwargs.update(form.data)
|
|
||||||
|
|
||||||
# cache options to use as defaults next time
|
|
||||||
for key, value in form.data.iteritems():
|
|
||||||
self.request.session['batch.{}.execute_option.{}'.format(batch.batch_key, key)] = value
|
|
||||||
|
|
||||||
key = '{}.execute'.format(self.model_class.__tablename__)
|
key = '{}.execute'.format(self.model_class.__tablename__)
|
||||||
progress = SessionProgress(self.request, key)
|
progress = SessionProgress(self.request, key)
|
||||||
|
@ -888,7 +886,7 @@ class BatchMasterView(MasterView):
|
||||||
'cancel_msg': "Batch execution was canceled.",
|
'cancel_msg': "Batch execution was canceled.",
|
||||||
})
|
})
|
||||||
|
|
||||||
self.request.session.flash("Sorry, you must POST to execute a batch.", 'error')
|
self.request.session.flash("Invalid request: {}".format(form.make_deform_form().error), 'error')
|
||||||
return self.redirect(self.get_action_url('view', batch))
|
return self.redirect(self.get_action_url('view', batch))
|
||||||
|
|
||||||
def execute_error_message(self, error):
|
def execute_error_message(self, error):
|
||||||
|
@ -949,18 +947,13 @@ class BatchMasterView(MasterView):
|
||||||
Starts a separate thread for the execution, and displays a progress
|
Starts a separate thread for the execution, and displays a progress
|
||||||
indicator page.
|
indicator page.
|
||||||
"""
|
"""
|
||||||
if self.request.method == 'POST':
|
form = self.make_execute_form()
|
||||||
|
if form.validate(newstyle=True):
|
||||||
|
kwargs = dict(form.validated)
|
||||||
|
|
||||||
kwargs = {}
|
# cache options to use as defaults next time
|
||||||
if self.has_execution_options():
|
for key, value in form.validated.items():
|
||||||
form = self.make_execution_options_form()
|
self.request.session['batch.{}.execute_option.{}'.format(self.model_class.batch_key, key)] = value
|
||||||
if not form.validate():
|
|
||||||
raise RuntimeError("Execution options form did not validate")
|
|
||||||
kwargs.update(form.data)
|
|
||||||
|
|
||||||
# cache options to use as defaults next time
|
|
||||||
for key, value in form.data.iteritems():
|
|
||||||
self.request.session['batch.{}.execute_option.{}'.format(self.model_class.batch_key, key)] = value
|
|
||||||
|
|
||||||
key = '{}.execute_results'.format(self.model_class.__tablename__)
|
key = '{}.execute_results'.format(self.model_class.__tablename__)
|
||||||
batches = self.get_effective_data()
|
batches = self.get_effective_data()
|
||||||
|
@ -974,7 +967,7 @@ class BatchMasterView(MasterView):
|
||||||
'cancel_msg': "Batch execution was canceled",
|
'cancel_msg': "Batch execution was canceled",
|
||||||
})
|
})
|
||||||
|
|
||||||
self.request.session.flash("Sorry, you must POST to execute batches", 'error')
|
self.request.session.flash("Invalid request: {}".format(form.make_deform_form().error), 'error')
|
||||||
return self.redirect(self.get_index_url())
|
return self.redirect(self.get_index_url())
|
||||||
|
|
||||||
def execute_results_thread(self, batches, user_uuid, progress=None, **kwargs):
|
def execute_results_thread(self, batches, user_uuid, progress=None, **kwargs):
|
||||||
|
|
|
@ -31,9 +31,10 @@ import os
|
||||||
from rattail.db import model
|
from rattail.db import model
|
||||||
from rattail.util import OrderedDict
|
from rattail.util import OrderedDict
|
||||||
|
|
||||||
import formencode as fe
|
import colander
|
||||||
from webhelpers2.html import tags
|
from webhelpers2.html import tags
|
||||||
|
|
||||||
|
from tailbone import forms2 as forms
|
||||||
from tailbone.db import Session
|
from tailbone.db import Session
|
||||||
from tailbone.views.batch import FileBatchMasterView
|
from tailbone.views.batch import FileBatchMasterView
|
||||||
|
|
||||||
|
@ -44,10 +45,12 @@ ACTION_OPTIONS = OrderedDict([
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
class ExecutionOptions(fe.Schema):
|
class ExecutionOptions(colander.Schema):
|
||||||
allow_extra_fields = True
|
|
||||||
filter_extra_fields = True
|
action = colander.SchemaNode(
|
||||||
action = fe.validators.OneOf(ACTION_OPTIONS)
|
colander.String(),
|
||||||
|
validator=colander.OneOf(ACTION_OPTIONS),
|
||||||
|
widget=forms.widgets.PlainSelectWidget(values=ACTION_OPTIONS.items()))
|
||||||
|
|
||||||
|
|
||||||
class HandheldBatchView(FileBatchMasterView):
|
class HandheldBatchView(FileBatchMasterView):
|
||||||
|
@ -207,6 +210,9 @@ class HandheldBatchView(FileBatchMasterView):
|
||||||
return super(HandheldBatchView, self).get_execute_success_url(batch)
|
return super(HandheldBatchView, self).get_execute_success_url(batch)
|
||||||
|
|
||||||
def get_execute_results_success_url(self, result, **kwargs):
|
def get_execute_results_success_url(self, result, **kwargs):
|
||||||
|
if result is True:
|
||||||
|
# no batches were actually executed
|
||||||
|
return self.get_index_url()
|
||||||
batch = result
|
batch = result
|
||||||
return self.get_execute_success_url(batch, result, **kwargs)
|
return self.get_execute_success_url(batch, result, **kwargs)
|
||||||
|
|
||||||
|
|
|
@ -95,6 +95,7 @@ class MasterView(View):
|
||||||
viewing = False
|
viewing = False
|
||||||
editing = False
|
editing = False
|
||||||
deleting = False
|
deleting = False
|
||||||
|
executing = False
|
||||||
has_pk_fields = False
|
has_pk_fields = False
|
||||||
|
|
||||||
row_attrs = {}
|
row_attrs = {}
|
||||||
|
|
5
tailbone/views/vendors/catalogs.py
vendored
5
tailbone/views/vendors/catalogs.py
vendored
|
@ -58,23 +58,26 @@ class VendorCatalogsView(FileBatchMasterView):
|
||||||
rows_bulk_deletable = True
|
rows_bulk_deletable = True
|
||||||
|
|
||||||
grid_columns = [
|
grid_columns = [
|
||||||
|
'id',
|
||||||
'created',
|
'created',
|
||||||
'created_by',
|
'created_by',
|
||||||
'vendor',
|
'vendor',
|
||||||
'effective',
|
'effective',
|
||||||
'filename',
|
'filename',
|
||||||
|
'rowcount',
|
||||||
'executed',
|
'executed',
|
||||||
]
|
]
|
||||||
|
|
||||||
form_fields = [
|
form_fields = [
|
||||||
|
'id',
|
||||||
'vendor',
|
'vendor',
|
||||||
'filename',
|
'filename',
|
||||||
'effective',
|
'effective',
|
||||||
'created',
|
'created',
|
||||||
'created_by',
|
'created_by',
|
||||||
|
'rowcount',
|
||||||
'executed',
|
'executed',
|
||||||
'executed_by',
|
'executed_by',
|
||||||
'rowcount',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
row_grid_columns = [
|
row_grid_columns = [
|
||||||
|
|
Loading…
Reference in a new issue