UI: Task & Execution screen refactored

* code view is now a public template
* emptyform is now a public form

* tasks overview screen
  * add state info field
  * add iso filter to time fields
  * add workflow link
  * refactored detail layout

* tasks main screen
   * main table now has result and
      published columns which use the
      code view template

Screenshots:
http://pasteboard.co/1T2U8Ers.png
http://pasteboard.co/1T2Son9w.png
http://pasteboard.co/1Uj47Rvk.png

Partially implements blueprint: tasks-screen-improvments
Partially implements blueprint: mistral-dashboard-executions-screen

Change-Id: I8978746f645949aed174f893a5195073f156e24d
This commit is contained in:
Gal Margalit 2015-11-03 12:58:49 +00:00
parent b800df51a8
commit 85e0a077b3
9 changed files with 136 additions and 65 deletions

View File

@ -5,10 +5,8 @@
{% endblock %} {% endblock %}
{% block modal-body %} {% block modal-body %}
<div class="row"> <div class="detail">
<div class="col-sm-12">
{{ io.value }} {{ io.value }}
</div>
</div> </div>
{% endblock %} {% endblock %}

View File

@ -52,7 +52,10 @@ class ExecutionsTable(tables.DataTable):
link="horizon:mistral:executions:detail" link="horizon:mistral:executions:detail"
) )
workflow_name = tables.Column("workflow_name", verbose_name=_("Workflow")) workflow_name = tables.Column(
"workflow_name",
verbose_name=_("Workflow")
)
task = tables.Column( task = tables.Column(
"task", "task",

View File

@ -17,17 +17,14 @@
from django.conf.urls import patterns # noqa from django.conf.urls import patterns # noqa
from django.conf.urls import url # noqa from django.conf.urls import url # noqa
from mistraldashboard.executions.views import IndexView
from mistraldashboard.executions.views import TaskView
from mistraldashboard.executions import views from mistraldashboard.executions import views
EXECUTIONS = r'^(?P<execution_id>[^/]+)/%s$' EXECUTIONS = r'^(?P<execution_id>[^/]+)/%s$'
urlpatterns = patterns( urlpatterns = patterns(
'', '',
url(r'^$', IndexView.as_view(), name='index'), url(r'^$', views.IndexView.as_view(), name='index'),
url(EXECUTIONS % 'tasks', TaskView.as_view(), name='tasks'), url(EXECUTIONS % 'tasks', views.TaskView.as_view(), name='tasks'),
url(EXECUTIONS % 'detail', views.DetailView.as_view(), name='detail'), url(EXECUTIONS % 'detail', views.DetailView.as_view(), name='detail'),
url(EXECUTIONS % 'output', views.CodeView.as_view(), url(EXECUTIONS % 'output', views.CodeView.as_view(),
{'column': 'output'}, name='output'), {'column': 'output'}, name='output'),

View File

@ -26,9 +26,9 @@ from horizon import tables
from mistraldashboard import api from mistraldashboard import api
from mistraldashboard.default.utils import prettyprint from mistraldashboard.default.utils import prettyprint
from mistraldashboard.executions import forms as mistral_forms
from mistraldashboard.executions.tables import ExecutionsTable from mistraldashboard.executions.tables import ExecutionsTable
from mistraldashboard.executions.tables import TaskTable from mistraldashboard.executions.tables import TaskTable
from mistraldashboard import forms as mistral_forms
def get_execution_data(request, execution_id): def get_execution_data(request, execution_id):
@ -76,7 +76,7 @@ class DetailView(generic.TemplateView):
class CodeView(forms.ModalFormView): class CodeView(forms.ModalFormView):
template_name = 'mistral/executions/code.html' template_name = 'mistral/default/code.html'
modal_header = _("Code view") modal_header = _("Code view")
form_id = "code_view" form_id = "code_view"
form_class = mistral_forms.EmptyForm form_class = mistral_forms.EmptyForm

View File

@ -26,14 +26,31 @@ class TaskTable(tables.DataTable):
id = tables.Column( id = tables.Column(
"id", "id",
verbose_name=_("ID"), verbose_name=_("ID"),
link="horizon:mistral:tasks:detail") link="horizon:mistral:tasks:detail"
name = tables.Column("name", verbose_name=_("Name")) )
name = tables.Column(
"name",
verbose_name=_("Name")
)
workflow_execution_id = tables.Column( workflow_execution_id = tables.Column(
"workflow_execution_id", "workflow_execution_id",
verbose_name=_("Workflow Execution ID"), verbose_name=_("Workflow Execution ID"),
link="horizon:mistral:tasks:execution" link="horizon:mistral:tasks:execution"
) )
result = tables.Column(
"",
verbose_name=_("Result"),
empty_value=_("View"),
link="horizon:mistral:tasks:result",
link_classes=("ajax-modal",)
)
published = tables.Column(
"",
verbose_name=_("Published"),
empty_value=_("View"),
link="horizon:mistral:tasks:published",
link_classes=("ajax-modal",)
)
created_at = tables.Column( created_at = tables.Column(
"created_at", "created_at",
verbose_name=_("Created at"), verbose_name=_("Created at"),

View File

@ -1,41 +1,65 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% load i18n %} {% load i18n %}
{% load i18n sizeformat %}
{% block title %}{% trans "Task Details" %}{% endblock %} {% block title %}{% trans "Task Details" %}{% endblock %}
{% block page_header %} {% block page_header %}
<h1> <h1>
{% trans "Task Details: " %} {% trans "Task Details" %}
{{ task.name}}
</h1> </h1>
{% endblock page_header %} {% endblock page_header %}
{% block main %} {% block main %}
<div class="row"> <div class="detail">
<div class="col-sm-12"> <h4>{% trans "Overview" %}</h4>
<h4>{% trans "Task Overview" %}</h4> <hr class="header_rule">
<hr class="header_rule"> <dl class="dl-horizontal">
<dl class="dl-horizontal"> <dt>{% trans "Name" %}</dt>
<dt><span class="pull-left">{% trans "ID" %}</span></dt> <dd>{{ task.name }}</dd>
<dd>{{ task.id }}</dd> <dt>{% trans "ID" %}</dt>
<dt><span class="pull-left">{% trans "Name" %}</span></dt> <dd>{{ task.id }}</dd>
<dd>{{ task.name }}</dd> {% if task.state_info %}
<dt><span class="pull-left">{% trans "WorkFlow Name" %}</span></dt> <dt>{% trans "State Info" %}</dt>
<dd>{{ task.workflow_name }}</dd> <dd>{{ task.state_info }}</dd>
<dt><span class="pull-left">{% trans "WorkFlow Execution Id" %}</span></dt> {% endif %}
<dd>{{ task.workflow_execution_id }}</dd> <dt>{% trans "State" %}</dt>
<dt><span class="pull-left">{% trans "Result" %}</span></dt> <dd>{{ task.state }}</dd>
<dd>{{ task.result }}</dd> <br/>
<dt><span class="pull-left">{% trans "Created At" %}</span></dt> <dt>{% trans "Creation Date" %}</dt>
<dd>{{ task.created_at }}</dd> <dd>{{ task.created_at|parse_isotime }}</dd>
<dt><span class="pull-left">{% trans "Updated At" %}</span></dt> <dt>{% trans "Time Since Created" %}</dt>
<dd>{{ task.updated_at }}</dd> <dd>{{ task.created_at|parse_isotime|timesince }}</dd>
<dt><span class="pull-left">{% trans "Published" %}</span></dt> <br/>
<dd>{{ task.published }}</dd> <dt>{% trans "Update Date" %}</dt>
<dt><span class="pull-left">{% trans "State" %}</span></dt> <dd>{{ task.updated_at|parse_isotime }}</dd>
<dd>{{ task.state }}</dd> <dt>{% trans "Time Since Updated" %}</dt>
</dl> <dd>{{ task.updated_at|parse_isotime|timesince }}</dd>
</div> <br/>
<dt>{% trans "Result" %}</dt>
<dd>{{ task.result }}</dd>
<dt>{% trans "Published" %}</dt>
<dd>{{ task.published }}</dd>
</dl>
</div>
<div class="detail">
<h4>{% trans "Workflow" %}</h4>
<hr class="header_rule">
<dl class="dl-horizontal">
<dt>{% trans "Workflow Name" %}</dt>
<dd>
<a href="{{ task.workflow_url }}"
title="{{task.workflow_name}} {% trans "overview" %}">
{{ task.workflow_name }}
</a>
</dd>
<dt>{% trans "Workflow Execution ID" %}</dt>
<dd>
<a href="{{ task.execution_url }}"
title="{{ task.workflow_execution_id }} {% trans "overview" %}">
{{ task.workflow_execution_id }}
</a>
</dd>
</dl>
</div> </div>
{% endblock %} {% endblock %}

View File

@ -26,4 +26,8 @@ urlpatterns = patterns(
url(r'^$', views.IndexView.as_view(), name='index'), url(r'^$', views.IndexView.as_view(), name='index'),
url(TASKS % 'detail', views.OverviewView.as_view(), name='detail'), url(TASKS % 'detail', views.OverviewView.as_view(), name='detail'),
url(TASKS % 'execution', views.ExecutionView.as_view(), name='execution'), url(TASKS % 'execution', views.ExecutionView.as_view(), name='execution'),
url(TASKS % 'result', views.CodeView.as_view(),
{'column': 'result'}, name='result'),
url(TASKS % 'published', views.CodeView.as_view(),
{'column': 'published'}, name='published'),
) )

View File

@ -15,25 +15,40 @@
# limitations under the License. # limitations under the License.
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.core.urlresolvers import reverse_lazy
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.views import generic from django.views import generic
from horizon import exceptions from horizon import exceptions
from horizon import forms
from horizon import tables from horizon import tables
from mistraldashboard import api from mistraldashboard import api
from mistraldashboard.default.utils import prettyprint from mistraldashboard.default.utils import prettyprint
from mistraldashboard import forms as mistral_forms
from mistraldashboard.tasks.tables import TaskTable from mistraldashboard.tasks.tables import TaskTable
def get_single_task_data(request, **kwargs):
try:
task_id = kwargs['task_id']
task = api.task_get(request, task_id)
except Exception:
msg = _('Unable to get task "%s".') % task_id
redirect = reverse('horizon:mistral:tasks:index')
exceptions.handle(request, msg, redirect=redirect)
return task
class ExecutionView(generic.TemplateView): class ExecutionView(generic.TemplateView):
template_name = 'mistral/tasks/execution.html' template_name = 'mistral/tasks/execution.html'
page_title = _("Execution Overview") page_title = _("Execution Overview")
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(ExecutionView, self).get_context_data(**kwargs) context = super(ExecutionView, self).get_context_data(**kwargs)
task = self.get_data(self.request, **kwargs) task = get_single_task_data(self.request, **kwargs)
execution = api.execution_get(self.request, task.workflow_execution_id) execution = api.execution_get(self.request, task.workflow_execution_id)
execution.input = prettyprint(execution.input) execution.input = prettyprint(execution.input)
execution.output = prettyprint(execution.output) execution.output = prettyprint(execution.output)
@ -44,39 +59,52 @@ class ExecutionView(generic.TemplateView):
return context return context
def get_data(self, request, **kwargs):
try:
task_id = kwargs['task_id']
task = api.task_get(request, task_id)
except Exception:
msg = _('Unable to get task "%s".') % task_id
redirect = reverse('horizon:mistral:tasks:index')
exceptions.handle(self.request, msg, redirect=redirect)
return task
class OverviewView(generic.TemplateView): class OverviewView(generic.TemplateView):
template_name = 'mistral/tasks/detail.html' template_name = 'mistral/tasks/detail.html'
page_title = _("Task Details") page_title = _("Task Details")
workflow_url = 'horizon:mistral:workflows:detail'
execution_url = 'horizon:mistral:executions:detail'
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(OverviewView, self).get_context_data(**kwargs) context = super(OverviewView, self).get_context_data(**kwargs)
task = self.get_data(self.request, **kwargs) task = get_single_task_data(self.request, **kwargs)
task.workflow_url = reverse(self.workflow_url,
args=[task.workflow_name])
task.execution_url = reverse(self.execution_url,
args=[task.workflow_execution_id])
task.result = prettyprint(task.result) task.result = prettyprint(task.result)
task.published = prettyprint(task.published)
context['task'] = task context['task'] = task
return context return context
def get_data(self, request, **kwargs):
try:
task_id = kwargs['task_id']
task = api.task_get(request, task_id)
except Exception:
msg = _('Unable to get task "%s".') % task_id
redirect = reverse('horizon:mistral:tasks:index')
exceptions.handle(self.request, msg, redirect=redirect)
return task class CodeView(forms.ModalFormView):
template_name = 'mistral/default/code.html'
modal_header = _("Code view")
form_id = "code_view"
form_class = mistral_forms.EmptyForm
cancel_label = "OK"
cancel_url = reverse_lazy("horizon:mistral:tasks:index")
page_title = _("Code view")
def get_context_data(self, **kwargs):
context = super(CodeView, self).get_context_data(**kwargs)
column = self.kwargs['column']
task = get_single_task_data(self.request, **self.kwargs)
io = {}
if column == 'result':
io['name'] = _('Result')
io['value'] = task.result = prettyprint(task.result)
elif column == 'published':
io['name'] = _('Published')
io['value'] = task.published = prettyprint(task.published)
context['io'] = io
return context
class IndexView(tables.DataTableView): class IndexView(tables.DataTableView):