Add task scheduling to election/admin UI
This commit is contained in:
parent
788c5c006c
commit
6ba9b1369a
@ -93,6 +93,15 @@ class WorkflowTask(EmbeddedObject):
|
|||||||
self.fire_event('exit')
|
self.fire_event('exit')
|
||||||
self.on_exit()
|
self.on_exit()
|
||||||
|
|
||||||
|
def get_entry_task(self):
|
||||||
|
election = self.recurse_parents('eos.base.election.Election')
|
||||||
|
|
||||||
|
for task in WorkflowTaskEntryTask.get_all():
|
||||||
|
if task.election_id == election._id and task.workflow_task == self._name:
|
||||||
|
return task
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
class Workflow(EmbeddedObject):
|
class Workflow(EmbeddedObject):
|
||||||
tasks = EmbeddedObjectListField()
|
tasks = EmbeddedObjectListField()
|
||||||
meta = {
|
meta = {
|
||||||
|
@ -66,7 +66,7 @@ class TaskScheduler:
|
|||||||
tasks = Task.get_all()
|
tasks = Task.get_all()
|
||||||
|
|
||||||
for task in tasks:
|
for task in tasks:
|
||||||
if task.status == Task.Status.READY and task.run_at and task.run_at < DateTimeField.now():
|
if task.status == Task.Status.READY:
|
||||||
pending_tasks.append(task)
|
pending_tasks.append(task)
|
||||||
|
|
||||||
return pending_tasks
|
return pending_tasks
|
||||||
@ -100,4 +100,5 @@ class TaskScheduler:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def tick():
|
def tick():
|
||||||
for task in TaskScheduler.pending_tasks():
|
for task in TaskScheduler.pending_tasks():
|
||||||
task.run()
|
if task.run_at and task.run_at < DateTimeField.now():
|
||||||
|
task.run()
|
||||||
|
@ -229,11 +229,33 @@ def election_admin_enter_task(election):
|
|||||||
if workflow_task.status != WorkflowTask.Status.READY:
|
if workflow_task.status != WorkflowTask.Status.READY:
|
||||||
return flask.Response('Task is not yet ready or has already exited', 409)
|
return flask.Response('Task is not yet ready or has already exited', 409)
|
||||||
|
|
||||||
task = WorkflowTaskEntryTask(election_id=election._id, workflow_task=workflow_task._name, status=Task.Status.READY, run_strategy=EosObject.lookup(app.config['TASK_RUN_STRATEGY'])())
|
task = WorkflowTaskEntryTask(
|
||||||
|
election_id=election._id,
|
||||||
|
workflow_task=workflow_task._name,
|
||||||
|
status=Task.Status.READY,
|
||||||
|
run_strategy=EosObject.lookup(app.config['TASK_RUN_STRATEGY'])()
|
||||||
|
)
|
||||||
task.run()
|
task.run()
|
||||||
|
|
||||||
return flask.redirect(flask.url_for('election_admin_summary', election_id=election._id))
|
return flask.redirect(flask.url_for('election_admin_summary', election_id=election._id))
|
||||||
|
|
||||||
|
@app.route('/election/<election_id>/admin/schedule_task', methods=['POST'])
|
||||||
|
@using_election
|
||||||
|
@election_admin
|
||||||
|
def election_admin_schedule_task(election):
|
||||||
|
workflow_task = election.workflow.get_task(flask.request.form['task_name'])
|
||||||
|
|
||||||
|
task = WorkflowTaskEntryTask(
|
||||||
|
election_id=election._id,
|
||||||
|
workflow_task=workflow_task._name,
|
||||||
|
run_at=DateTimeField().deserialise(flask.request.form['datetime']),
|
||||||
|
status=Task.Status.READY,
|
||||||
|
run_strategy=EosObject.lookup(app.config['TASK_RUN_STRATEGY'])()
|
||||||
|
)
|
||||||
|
task.save()
|
||||||
|
|
||||||
|
return flask.redirect(flask.url_for('election_admin_summary', election_id=election._id))
|
||||||
|
|
||||||
@app.route('/election/<election_id>/cast_ballot', methods=['POST'])
|
@app.route('/election/<election_id>/cast_ballot', methods=['POST'])
|
||||||
@using_election
|
@using_election
|
||||||
def election_api_cast_vote(election):
|
def election_api_cast_vote(election):
|
||||||
|
@ -28,4 +28,22 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<h2>Schedule a task</h2>
|
||||||
|
|
||||||
|
<form class="ui form" action="{{ url_for('election_admin_schedule_task', election_id=election._id) }}" method="post">
|
||||||
|
<div class="field">
|
||||||
|
<label>Task</label>
|
||||||
|
<select class="ui dropdown" name="task_name">
|
||||||
|
{% for task in election.workflow.tasks %}
|
||||||
|
<option value="{{ task._name }}">{{ task.label }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label>UTC date and time (ISO 8601)</label>
|
||||||
|
<input name="datetime" value="{{ eos.core.objects.DateTimeField().serialise(eos.core.objects.DateTimeField.now()) }}" type="text">
|
||||||
|
</div>
|
||||||
|
<input type="submit" class="ui primary button" value="Schedule task">
|
||||||
|
</form>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -37,17 +37,40 @@
|
|||||||
<p>
|
<p>
|
||||||
Voting in this {{ election.kind }}
|
Voting in this {{ election.kind }}
|
||||||
{% if election.workflow.get_task('eos.base.workflow.TaskOpenVoting').status == Status.EXITED %}
|
{% if election.workflow.get_task('eos.base.workflow.TaskOpenVoting').status == Status.EXITED %}
|
||||||
opened at {{ election.workflow.get_task('eos.base.workflow.TaskOpenVoting').exited_at.strftime('%Y-%m-%d %H:%M:%S') }} UTC
|
opened at
|
||||||
|
{% if election.workflow.get_task('eos.base.workflow.TaskOpenVoting').get_entry_task().run_at %}
|
||||||
|
{{ election.workflow.get_task('eos.base.workflow.TaskOpenVoting').get_entry_task().run_at.strftime('%Y-%m-%d %H:%M:%S') }} UTC
|
||||||
|
according to schedule,
|
||||||
|
{% else %}
|
||||||
|
{{ election.workflow.get_task('eos.base.workflow.TaskOpenVoting').exited_at.strftime('%Y-%m-%d %H:%M:%S') }} UTC
|
||||||
|
at the administrator's discretion,
|
||||||
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
is scheduled to open
|
is scheduled to open at
|
||||||
|
{% if election.workflow.get_task('eos.base.workflow.TaskOpenVoting').get_entry_task().run_at %}
|
||||||
|
{{ election.workflow.get_task('eos.base.workflow.TaskOpenVoting').get_entry_task().run_at.strftime('%Y-%m-%d %H:%M:%S') }} UTC,
|
||||||
|
{% else %}
|
||||||
|
the administrator's discretion,
|
||||||
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
at the administrators' discretion, and
|
and
|
||||||
{% if election.workflow.get_task('eos.base.workflow.TaskCloseVoting').status == Status.EXITED %}
|
{% if election.workflow.get_task('eos.base.workflow.TaskCloseVoting').status == Status.EXITED %}
|
||||||
closed at {{ election.workflow.get_task('eos.base.workflow.TaskCloseVoting').exited_at.strftime('%Y-%m-%d %H:%M:%S') }} UTC
|
closed at
|
||||||
|
{% if election.workflow.get_task('eos.base.workflow.TaskCloseVoting').get_entry_task().run_at %}
|
||||||
|
{{ election.workflow.get_task('eos.base.workflow.TaskCloseVoting').get_entry_task().run_at.strftime('%Y-%m-%d %H:%M:%S') }} UTC
|
||||||
|
according to schedule
|
||||||
|
{% else %}
|
||||||
|
{{ election.workflow.get_task('eos.base.workflow.TaskCloseVoting').exited_at.strftime('%Y-%m-%d %H:%M:%S') }} UTC
|
||||||
|
at the administrator's discretion
|
||||||
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
is scheduled to close
|
is scheduled to close at
|
||||||
|
{% if election.workflow.get_task('eos.base.workflow.TaskCloseVoting').get_entry_task().run_at %}
|
||||||
|
{{ election.workflow.get_task('eos.base.workflow.TaskCloseVoting').get_entry_task().run_at.strftime('%Y-%m-%d %H:%M:%S') }} UTC.
|
||||||
|
{% else %}
|
||||||
|
the administrator's discretion.
|
||||||
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
at the administrators' discretion.
|
|
||||||
</p>
|
</p>
|
||||||
{% else %}
|
{% else %}
|
||||||
<p><button class="ui huge button">This {{ election.kind }} is not yet ready for voting</button></p>
|
<p><button class="ui huge button">This {{ election.kind }} is not yet ready for voting</button></p>
|
||||||
|
Loading…
Reference in New Issue
Block a user