Add basic support for batch execution options
This commit is contained in:
parent
3b265e19c4
commit
db62f82a37
|
@ -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>
|
||||||
|
|
|
@ -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.
|
||||||
|
|
Loading…
Reference in a new issue