Add basic support for batch execution options

This commit is contained in:
Lance Edgar 2016-08-17 16:52:13 -05:00
parent 3b265e19c4
commit db62f82a37
2 changed files with 113 additions and 18 deletions

View file

@ -10,8 +10,32 @@
$('.newgrid-wrapper').gridwrapper(); $('.newgrid-wrapper').gridwrapper();
$('#execute-batch').click(function() { $('#execute-batch').click(function() {
% if master.has_execution_options:
$('#execution-options-dialog').dialog({
title: "Execution Options",
width: 500,
height: 300,
modal: true,
buttons: [
{
text: "Execute",
click: function(event) {
$(event.target).button('option', 'label', "Executing, please wait...").button('disable');
$('form[name="batch-execution"]').submit();
}
},
{
text: "Cancel",
click: function() {
$(this).dialog('close');
}
}
]
});
% else:
$(this).button('option', 'label', "Executing, please wait...").button('disable'); $(this).button('option', 'label', "Executing, please wait...").button('disable');
location.href = '${url('{}.execute'.format(route_prefix), uuid=batch.uuid)}'; $('form[name="batch-execution"]').submit();
% endif
}); });
}); });
@ -52,3 +76,13 @@
</div><!-- form-wrapper --> </div><!-- form-wrapper -->
${rows_grid|n} ${rows_grid|n}
<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:
${rendered_execution_options|n}
% endif
${h.end_form()}
</div>

View file

@ -45,6 +45,7 @@ import formalchemy
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 webhelpers.html import HTML from webhelpers.html import HTML
from tailbone import forms, newgrids as grids from tailbone import forms, newgrids as grids
@ -114,7 +115,8 @@ class BatchMasterView(MasterView):
self.request.response.text = grid.render_grid() self.request.response.text = grid.render_grid()
return self.request.response return self.request.response
return self.render_to_response('view', { context = {
'handler': self.handler,
'instance': batch, 'instance': batch,
'instance_title': self.get_instance_title(batch), 'instance_title': self.get_instance_title(batch),
'instance_editable': self.editable_instance(batch), 'instance_editable': self.editable_instance(batch),
@ -124,7 +126,25 @@ class BatchMasterView(MasterView):
'execute_title': self.get_execute_title(batch), 'execute_title': self.get_execute_title(batch),
'execute_enabled': self.executable(batch), 'execute_enabled': self.executable(batch),
'rows_grid': grid.render_complete(allow_save_defaults=False), 'rows_grid': grid.render_complete(allow_save_defaults=False),
}) }
if context['execute_enabled']:
context['rendered_execution_options'] = self.render_execution_options()
return self.render_to_response('view', context)
def render_execution_options(self):
batch = self.get_instance()
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):
return kwargs
def get_instance_title(self, batch): def get_instance_title(self, batch):
return batch.id_str or unicode(batch) return batch.id_str or unicode(batch)
@ -352,6 +372,26 @@ class BatchMasterView(MasterView):
def executable(self, batch): def executable(self, batch):
return self.handler.executable(batch) return self.handler.executable(batch)
@property
def has_execution_options(self):
return bool(self.execution_options_schema)
# TODO
execution_options_schema = None
def make_execution_options_form(self, batch):
"""
Return a proper Form for execution options.
"""
defaults = {}
for field in self.execution_options_schema.fields:
key = 'batch.{}.execute_option.{}'.format(batch.batch_key, field)
value = self.request.session.get(key)
if value:
defaults[field] = value
return Form(self.request, schema=self.execution_options_schema,
defaults=defaults or None)
def get_execute_title(self, batch): def get_execute_title(self, batch):
return self.handler.get_execute_title(batch) return self.handler.get_execute_title(batch)
@ -648,20 +688,32 @@ 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':
kwargs = {}
if self.has_execution_options:
form = self.make_execution_options_form(batch)
assert form.validate() # TODO
kwargs.update(form.data)
for key, value in form.data.iteritems():
# TODO: properly serialize option values?
self.request.session['batch.{}.execute_option.{}'.format(batch.batch_key, key)] = unicode(value)
key = '{}.execute'.format(self.model_class.__tablename__) key = '{}.execute'.format(self.model_class.__tablename__)
progress = SessionProgress(self.request, key) kwargs['progress'] = SessionProgress(self.request, key)
thread = Thread(target=self.execute_thread, args=(batch.uuid, self.request.user.uuid, progress)) thread = Thread(target=self.execute_thread, args=(batch.uuid, self.request.user.uuid), kwargs=kwargs)
thread.start() thread.start()
kwargs = { return self.render_progress({
'key': key, 'key': key,
'cancel_url': self.get_action_url('view', batch), 'cancel_url': self.get_action_url('view', batch),
'cancel_msg': "Batch execution was canceled.", 'cancel_msg': "Batch execution was canceled.",
} })
return self.render_progress(kwargs)
def execute_thread(self, batch_uuid, user_uuid, progress=None): self.request.session.flash("Sorry, you must POST to execute a batch.", 'error')
return self.redirect(self.get_action_url('view', batch))
def execute_thread(self, batch_uuid, user_uuid, progress=None, **kwargs):
""" """
Thread target for executing a batch with progress indicator. Thread target for executing a batch with progress indicator.
""" """
@ -670,8 +722,9 @@ class BatchMasterView(MasterView):
# transaction binding etc. # transaction binding etc.
session = RattailSession() session = RattailSession()
batch = session.query(self.model_class).get(batch_uuid) batch = session.query(self.model_class).get(batch_uuid)
user = session.query(model.User).get(user_uuid)
try: try:
result = self.handler.execute(batch, progress=progress) result = self.handler.execute(batch, user=user, progress=progress, **kwargs)
# If anything goes wrong, rollback and log the error etc. # If anything goes wrong, rollback and log the error etc.
except Exception as error: except Exception as error:
@ -688,19 +741,27 @@ class BatchMasterView(MasterView):
else: else:
if result: if result:
batch.executed = datetime.datetime.utcnow() batch.executed = datetime.datetime.utcnow()
batch.executed_by_uuid = user_uuid batch.executed_by = user
session.commit() session.commit()
# TODO: this doesn't always work...?
self.request.session.flash("{} has been executed: {}".format(
self.get_model_title(), batch.id_str))
else: else:
session.rollback() session.rollback()
session.refresh(batch) session.refresh(batch)
success_url = self.get_execute_success_url(batch, result, **kwargs)
session.close() session.close()
if progress: if progress:
progress.session.load() progress.session.load()
progress.session['complete'] = True progress.session['complete'] = True
progress.session['success_url'] = self.get_action_url('view', batch) progress.session['success_url'] = success_url
progress.session.save() progress.session.save()
def get_execute_success_url(self, batch, result, **kwargs):
return self.get_action_url('view', batch)
def csv(self): def csv(self):
""" """
Download batch data as CSV. Download batch data as CSV.