UI: Cron Trigger screens - list and overview
* Added new Cron Trigger screens - main list - detail overview Screenshots: http://pasteboard.co/rPZIMnT.png http://pasteboard.co/rPX6730.png Partially implements blueprint: mistral-dashboard-cron-trigger-screen Change-Id: I69f8b143f6ab4ca91f860e66b34471542cbdb6dd
This commit is contained in:
parent
3a1e52ed63
commit
c56d137a90
@ -300,3 +300,35 @@ def action_delete(request, action_name):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
return mistralclient(request).actions.delete(action_name)
|
return mistralclient(request).actions.delete(action_name)
|
||||||
|
|
||||||
|
|
||||||
|
@handle_errors(_("Unable to retrieve cron trigger list"), [])
|
||||||
|
def cron_trigger_list(request):
|
||||||
|
"""Returns all cron triggers.
|
||||||
|
|
||||||
|
:param request: Request data
|
||||||
|
"""
|
||||||
|
|
||||||
|
return mistralclient(request).cron_triggers.list()
|
||||||
|
|
||||||
|
|
||||||
|
@handle_errors(_("Unable to retrieve cron trigger"), [])
|
||||||
|
def cron_trigger_get(request, cron_trigger_name):
|
||||||
|
"""Get specific cron trigger.
|
||||||
|
|
||||||
|
:param request: Request data
|
||||||
|
:param cron_trigger_name: Cron trigger name
|
||||||
|
"""
|
||||||
|
|
||||||
|
return mistralclient(request).cron_triggers.get(cron_trigger_name)
|
||||||
|
|
||||||
|
|
||||||
|
@handle_errors(_("Unable to delete cron trigger/s"), [])
|
||||||
|
def cron_trigger_delete(request, cron_trigger_name):
|
||||||
|
"""Delete Cron Trigger.
|
||||||
|
|
||||||
|
:param request: Request data
|
||||||
|
:param cron_trigger_name: Cron Trigger name
|
||||||
|
"""
|
||||||
|
|
||||||
|
return mistralclient(request).cron_triggers.delete(cron_trigger_name)
|
||||||
|
0
mistraldashboard/cron_triggers/__init__.py
Normal file
0
mistraldashboard/cron_triggers/__init__.py
Normal file
28
mistraldashboard/cron_triggers/panel.py
Normal file
28
mistraldashboard/cron_triggers/panel.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright 2016 - Alcatel-Lucent.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
import horizon
|
||||||
|
from mistraldashboard import dashboard
|
||||||
|
|
||||||
|
|
||||||
|
class CronTriggers(horizon.Panel):
|
||||||
|
name = _("Cron Triggers")
|
||||||
|
slug = 'cron_triggers'
|
||||||
|
|
||||||
|
|
||||||
|
dashboard.MistralDashboard.register(CronTriggers)
|
105
mistraldashboard/cron_triggers/tables.py
Normal file
105
mistraldashboard/cron_triggers/tables.py
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright 2016 - Alcatel-Lucent.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
from django.core.urlresolvers import reverse
|
||||||
|
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
from django.utils.translation import ungettext_lazy
|
||||||
|
|
||||||
|
from horizon import tables
|
||||||
|
|
||||||
|
from mistraldashboard import api
|
||||||
|
from mistraldashboard.default.utils import humantime
|
||||||
|
|
||||||
|
|
||||||
|
class DeleteCronTrigger(tables.DeleteAction):
|
||||||
|
@staticmethod
|
||||||
|
def action_present(count):
|
||||||
|
return ungettext_lazy(
|
||||||
|
u"Delete Cron Trigger",
|
||||||
|
u"Delete Cron Triggers",
|
||||||
|
count
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def action_past(count):
|
||||||
|
return ungettext_lazy(
|
||||||
|
u"Deleted Cron Trigger",
|
||||||
|
u"Deleted Cron Triggers",
|
||||||
|
count
|
||||||
|
)
|
||||||
|
|
||||||
|
def delete(self, request, cron_trigger_name):
|
||||||
|
api.cron_trigger_delete(request, cron_trigger_name)
|
||||||
|
|
||||||
|
|
||||||
|
class WorkflowColumn(tables.Column):
|
||||||
|
def get_link_url(self, datum):
|
||||||
|
workflow_url = "horizon:mistral:workflows:detail"
|
||||||
|
obj_id = datum.workflow_name
|
||||||
|
return reverse(workflow_url, args=[obj_id])
|
||||||
|
|
||||||
|
|
||||||
|
class CronTriggersTable(tables.DataTable):
|
||||||
|
id = tables.Column(
|
||||||
|
"id",
|
||||||
|
verbose_name=_("ID"),
|
||||||
|
link="horizon:mistral:cron_triggers:detail"
|
||||||
|
)
|
||||||
|
name = tables.Column(
|
||||||
|
"name",
|
||||||
|
verbose_name=_("Name")
|
||||||
|
)
|
||||||
|
workflow_name = WorkflowColumn(
|
||||||
|
"workflow_name",
|
||||||
|
verbose_name=_("Workflow"),
|
||||||
|
link=True
|
||||||
|
)
|
||||||
|
pattern = tables.Column(
|
||||||
|
"pattern",
|
||||||
|
verbose_name=_("Pattern"),
|
||||||
|
)
|
||||||
|
next_execution_time = tables.Column(
|
||||||
|
"next_execution_time",
|
||||||
|
verbose_name=_("Next Execution Time"),
|
||||||
|
)
|
||||||
|
remaining_executions = tables.Column(
|
||||||
|
"remaining_executions",
|
||||||
|
verbose_name=_("Remaining Executions"),
|
||||||
|
)
|
||||||
|
first_execution_time = tables.Column(
|
||||||
|
"first_execution_time",
|
||||||
|
verbose_name=_("First Execution Time"),
|
||||||
|
)
|
||||||
|
created_at = tables.Column(
|
||||||
|
"created_at",
|
||||||
|
verbose_name=_("Created at"),
|
||||||
|
filters=[humantime]
|
||||||
|
)
|
||||||
|
updated_at = tables.Column(
|
||||||
|
"updated_at",
|
||||||
|
verbose_name=_("Updated at"),
|
||||||
|
filters=[humantime]
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_object_id(self, datum):
|
||||||
|
return datum.name
|
||||||
|
|
||||||
|
class Meta(object):
|
||||||
|
name = "cron trigger"
|
||||||
|
verbose_name = _("Cron Trigger")
|
||||||
|
table_actions = (tables.FilterAction, DeleteCronTrigger)
|
||||||
|
row_actions = (DeleteCronTrigger,)
|
@ -0,0 +1,99 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block title %}{% trans "Cron Trigger Details" %}{% endblock %}
|
||||||
|
|
||||||
|
{% block page_header %}
|
||||||
|
<h1>
|
||||||
|
{% trans "Cron Trigger Details" %}
|
||||||
|
</h1>
|
||||||
|
<ol class="breadcrumb">
|
||||||
|
<li><a href={{ cron_trigger.list_url }} title="Cron Triggers">
|
||||||
|
Cron Triggers
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="active" title={{ cron_trigger.name }}>
|
||||||
|
{{ cron_trigger.name }}
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
{% endblock page_header %}
|
||||||
|
|
||||||
|
{% block main %}
|
||||||
|
{% load i18n sizeformat %}
|
||||||
|
<div class="detail">
|
||||||
|
<h4>{% trans "Overview" %}</h4>
|
||||||
|
<hr class="header_rule">
|
||||||
|
<dl class="dl-horizontal">
|
||||||
|
<dt>{% trans "Name" %}</dt>
|
||||||
|
<dd>{{ cron_trigger.name }}</dd>
|
||||||
|
<dt>{% trans "ID" %}</dt>
|
||||||
|
<dd>{{ cron_trigger.id }}</dd>
|
||||||
|
<dt>{% trans "Pattern" %}</dt>
|
||||||
|
<dd>{{ cron_trigger.pattern }}</dd>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<dt>{% trans "Creation Date" %}</dt>
|
||||||
|
<dd>{{ cron_trigger.created_at|parse_isotime }}</dd>
|
||||||
|
<dt>{% trans "Time Since Created" %}</dt>
|
||||||
|
<dd>{{ cron_trigger.created_at|parse_isotime|timesince }}</dd>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<dt>{% trans "First Execution" %}</dt>
|
||||||
|
<dd>
|
||||||
|
{% with time=cron_trigger.first_execution_time %}
|
||||||
|
{{ time|parse_isotime|default:"Empty" }}
|
||||||
|
{% endwith %}
|
||||||
|
</dd>
|
||||||
|
<dt>{% trans "Time Since first Execution" %}</dt>
|
||||||
|
<dd>
|
||||||
|
{% with time=cron_trigger.first_execution_time %}
|
||||||
|
{{ time|parse_isotime|timesince|default:"Empty" }}
|
||||||
|
{% endwith %}
|
||||||
|
</dd>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<dt>{% trans "Update Date" %}</dt>
|
||||||
|
<dd>
|
||||||
|
{{ cron_trigger.updated_at|parse_isotime|default:"Empty" }}
|
||||||
|
</dd>
|
||||||
|
<dt>{% trans "Time Since Updated" %}</dt>
|
||||||
|
<dd>
|
||||||
|
{% with time=cron_trigger.updated_at %}
|
||||||
|
{{ time|parse_isotime|timesince|default:"Empty" }}
|
||||||
|
{% endwith %}
|
||||||
|
</dd>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<dt>{% trans "Next Execution Time" %}</dt>
|
||||||
|
<dd>
|
||||||
|
{% with time=cron_trigger.next_execution_time %}
|
||||||
|
{{ time|parse_isotime|default:"Empty" }}
|
||||||
|
{% endwith %}
|
||||||
|
</dd>
|
||||||
|
<dt>{% trans "Time Until Next Execution" %}</dt>
|
||||||
|
<dd>
|
||||||
|
{% with time=cron_trigger.next_execution_time %}
|
||||||
|
{{ time|parse_isotime|timeuntil|default:"Empty" }}
|
||||||
|
{% endwith %}
|
||||||
|
</dd>
|
||||||
|
<dt>{% trans "Remaining Executions" %}</dt>
|
||||||
|
<dd>{{ cron_trigger.remaining_executions|default:"0"}}</dd>
|
||||||
|
<br/>
|
||||||
|
</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="{{ cron_trigger.workflow_url }}"
|
||||||
|
title=
|
||||||
|
"{{cron_trigger.workflow_name}} {% trans "overview" %}">
|
||||||
|
{{ cron_trigger.workflow_name }}
|
||||||
|
</a>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
@ -0,0 +1,9 @@
|
|||||||
|
{% extends 'mistral/default/table.html' %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% block title %}
|
||||||
|
{% trans "Cron Triggers" %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block page_header %}
|
||||||
|
{% include "horizon/common/_page_header.html" with title=_("Cron Triggers")%}
|
||||||
|
{% endblock page_header %}
|
28
mistraldashboard/cron_triggers/urls.py
Normal file
28
mistraldashboard/cron_triggers/urls.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright 2016 - Alcatel-Lucent.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
from django.conf.urls import patterns # noqa
|
||||||
|
from django.conf.urls import url # noqa
|
||||||
|
|
||||||
|
from mistraldashboard.cron_triggers import views
|
||||||
|
|
||||||
|
CRON_TRIGGERS = r'^(?P<cron_trigger_name>[^/]+)/%s$'
|
||||||
|
|
||||||
|
urlpatterns = patterns(
|
||||||
|
'',
|
||||||
|
url(r'^$', views.IndexView.as_view(), name='index'),
|
||||||
|
url(CRON_TRIGGERS % 'detail', views.OverviewView.as_view(), name='detail'),
|
||||||
|
)
|
57
mistraldashboard/cron_triggers/views.py
Normal file
57
mistraldashboard/cron_triggers/views.py
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright 2016 - Alcatel-Lucent.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
from django.core.urlresolvers import reverse
|
||||||
|
from django.core.urlresolvers import reverse_lazy
|
||||||
|
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
from django.views import generic
|
||||||
|
|
||||||
|
from horizon import tables
|
||||||
|
|
||||||
|
from mistraldashboard import api
|
||||||
|
from mistraldashboard.cron_triggers.tables import CronTriggersTable
|
||||||
|
|
||||||
|
|
||||||
|
class OverviewView(generic.TemplateView):
|
||||||
|
template_name = 'mistral/cron_triggers/detail.html'
|
||||||
|
page_title = _("Cron Trigger Details")
|
||||||
|
workflow_url = 'horizon:mistral:workflows:detail'
|
||||||
|
list_url = 'horizon:mistral:cron_triggers:index'
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super(OverviewView, self).get_context_data(**kwargs)
|
||||||
|
cron_trigger = {}
|
||||||
|
cron_trigger = api.cron_trigger_get(
|
||||||
|
self.request,
|
||||||
|
kwargs['cron_trigger_name']
|
||||||
|
)
|
||||||
|
cron_trigger.workflow_url = reverse(
|
||||||
|
self.workflow_url,
|
||||||
|
args=[cron_trigger.workflow_name]
|
||||||
|
)
|
||||||
|
cron_trigger.list_url = reverse_lazy(self.list_url)
|
||||||
|
context['cron_trigger'] = cron_trigger
|
||||||
|
|
||||||
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
class IndexView(tables.DataTableView):
|
||||||
|
table_class = CronTriggersTable
|
||||||
|
template_name = 'mistral/cron_triggers/index.html'
|
||||||
|
|
||||||
|
def get_data(self):
|
||||||
|
return api.cron_trigger_list(self.request)
|
@ -28,7 +28,8 @@ class MistralDashboard(horizon.Dashboard):
|
|||||||
'workflows',
|
'workflows',
|
||||||
'executions',
|
'executions',
|
||||||
'tasks',
|
'tasks',
|
||||||
'actions'
|
'actions',
|
||||||
|
'cron_triggers'
|
||||||
)
|
)
|
||||||
default_panel = 'default'
|
default_panel = 'default'
|
||||||
roles = ('admin',)
|
roles = ('admin',)
|
||||||
|
@ -58,9 +58,10 @@ def handle_errors(error_message, error_default=None, request_arg=None):
|
|||||||
return func(*args, **kwargs)
|
return func(*args, **kwargs)
|
||||||
try:
|
try:
|
||||||
return func(*args, **kwargs)
|
return func(*args, **kwargs)
|
||||||
except Exception:
|
except Exception as e:
|
||||||
callargs = inspect.getcallargs(func, *args, **kwargs)
|
callargs = inspect.getcallargs(func, *args, **kwargs)
|
||||||
request = callargs[_request_arg]
|
request = callargs[_request_arg]
|
||||||
|
_error_message += ': ' + str(e)
|
||||||
horizon.exceptions.handle(request, _error_message,
|
horizon.exceptions.handle(request, _error_message,
|
||||||
ignore=_error_ignore,
|
ignore=_error_ignore,
|
||||||
redirect=_error_redirect)
|
redirect=_error_redirect)
|
||||||
|
Loading…
Reference in New Issue
Block a user