Add UI for PyScripts rating module

Change-Id: Ic5dfa0cdc2b484841bb80d9fb78ecaa6b33626ba
This commit is contained in:
Pierre-Alexandre Bardina 2015-10-20 15:58:51 +02:00
parent e30609ca36
commit 9869b26b43
12 changed files with 406 additions and 0 deletions

View File

@ -0,0 +1,122 @@
# Copyright 2015 Objectif Libre
#
# 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.
import logging
from django.utils.text import normalize_newlines
from django.utils.translation import ugettext_lazy as _
from horizon import forms
from cloudkittydashboard.api import cloudkitty as api
from cloudkittydashboard.dashboards import common
LOG = logging.getLogger(__name__)
class CreateScriptForm(forms.SelfHandlingForm):
help_text = _('Create a new rating script.')
name = forms.CharField(label=_("Name"))
source_choices = [('raw', _('Direct Input')),
('file', _('File'))]
script_source = forms.ChoiceField(
label=_('Rating Script Source'),
choices=source_choices,
widget=forms.Select(attrs={
'class': 'switchable',
'data-slug': 'scriptsource'}),
required=True)
script_help = _("A script or set of python commands to modify rating "
"calculations.")
script_upload = forms.FileField(
label=_('Script File'),
help_text=script_help,
widget=forms.FileInput(attrs={
'class': 'switched',
'data-switch-on': 'scriptsource',
'data-scriptsource-file': _('Script File')}),
required=False)
script_data = forms.CharField(
label=_('Script Data'),
help_text=script_help,
widget=forms.widgets.Textarea(attrs={
'class': 'switched',
'data-switch-on': 'scriptsource',
'data-scriptsource-raw': _('Script Data')}),
required=False)
class Meta(object):
name = _('Create Script')
def clean(self):
cleaned = super(CreateScriptForm, self).clean()
files = self.request.FILES
script = self.clean_uploaded_files('script', files)
if script is not None:
cleaned['script_data'] = script
return cleaned
def clean_uploaded_files(self, prefix, files):
upload_str = prefix + "_upload"
has_upload = upload_str in files
if has_upload:
upload_file = files[upload_str]
log_script_name = upload_file.name
LOG.info('got upload %s' % log_script_name)
script = upload_file.read()
if script != "":
try:
normalize_newlines(script)
except Exception as e:
msg = _('There was a problem parsing the'
' %(prefix)s: %(error)s')
msg = msg % {'prefix': prefix, 'error': e}
raise forms.ValidationError(msg)
return script
else:
return None
def handle(self, request, data):
name = data['name']
LOG.info('Creating script with name %s' % (name))
ck_client = api.cloudkittyclient(request)
return ck_client.pyscripts.scripts.create(
name=name,
data=data['script_data'])
class EditScriptForm(CreateScriptForm, common.OrderFieldsMixin):
script_id = forms.CharField(label=_("Script ID"),
widget=forms.TextInput(
attrs={'readonly': 'readonly'}))
fields_order = ['script_id', 'name', 'script_source', 'script_upload',
'script_data']
def __init__(self, request, *args, **kwargs):
super(EditScriptForm, self).__init__(request, *args, **kwargs)
self.order_fields()
class Meta(object):
name = _("Upate Script")
def handle(self, request, data):
script_id = self.initial['script_id']
LOG.info('Updating script with id %s' % (script_id))
ck_client = api.cloudkittyclient(request)
return ck_client.pyscripts.scripts.update(script_id=script_id,
name=data['name'],
data=data['script_data'])

View File

@ -0,0 +1,22 @@
# Copyright 2015 Objectif Libre
#
# 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
class PyScripts(horizon.Panel):
name = _("PyScripts")
slug = "pyscripts"

View File

@ -0,0 +1,71 @@
# Copyright 2015 Objectif Libre
#
# 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 horizon import tables
from cloudkittydashboard.api import cloudkitty as api
def get_detail_link(datum):
if datum.script_id:
url = "horizon:admin:pyscripts:script_details"
return reverse(url, kwargs={'script_id': datum.script_id})
class CreatePyScript(tables.LinkAction):
name = "createpyscript"
verbose_name = _("Create Script")
url = "horizon:admin:pyscripts:script_create"
icon = "create"
ajax = True
classes = ("ajax-modal",)
class UpdateScript(tables.LinkAction):
name = "updatepyscript"
verbose_name = _("Edit Script")
classes = ("ajax-modal",)
icon = "pencil"
def get_link_url(self, datum=None):
url = "horizon:admin:pyscripts:script_update"
return reverse(url, kwargs={'script_id': datum.script_id})
class DeletePyScript(tables.DeleteAction):
name = "deletepyscript"
verbose_name = _("Delete Script")
action_present = _("Delete")
action_past = _("Deleted")
data_type_singular = _("PyScript")
data_type_plural = _("PyScripts")
icon = "remove"
def action(self, request, script_id):
api.cloudkittyclient(request).pyscripts.scripts.delete(
script_id=script_id)
class PyScriptsTable(tables.DataTable):
id = tables.Column("id", verbose_name=_("id"), link=get_detail_link)
name = tables.Column("name", verbose_name=_("Name"))
checksum = tables.Column("checksum", verbose_name=_("Checksum"))
class Meta(object):
name = "pyscripts"
verbose_name = _("pyscripts")
table_actions = (CreatePyScript, DeletePyScript)
row_actions = (UpdateScript, DeletePyScript)

View File

@ -0,0 +1,3 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% block form_attrs %}enctype="multipart/form-data"{% endblock %}

View File

@ -0,0 +1,21 @@
{% extends 'base.html' %}
{% load i18n sizeformat %}
{% block title %}{% trans "Script Details" %}{% endblock %}
{% block main %}
<div class="row">
<div class="col-sm-12">
<div class="detail">
<dl>
<dt>{{ _("Id") }}</dt>
<dd>{{ script.script_id }}</dd>
<dt>{{ _("Name") }}</dt>
<dd>{{ script.name }}</dd>
<dt>{{ _("Data") }}</dt>
<dd>{{ script.data|linebreaksbr }}</dd>
</dl>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,8 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% endblock %}
{% block main %}
{% include 'admin/pyscripts/_form.html' %}
{% endblock %}

View File

@ -0,0 +1,14 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "PyScripts" %}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title=_("PyScripts") %}
{% endblock page_header %}
{% block main %}
{{ table.render }}
{{ modules }}
{% endblock %}

View File

@ -0,0 +1,21 @@
# Copyright 2015 Objectif Libre
#
# 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 horizon.test import helpers as test
class CkprojectTests(test.TestCase):
# Unit tests for ckproject.
def test_me(self):
self.assertTrue(1 + 1 == 2)

View File

@ -0,0 +1,28 @@
# Copyright 2015 Objectif Libre
#
# 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
from django.conf.urls import url
from cloudkittydashboard.dashboards.admin.pyscripts import views
urlpatterns = patterns(
'',
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^create/?$', views.ScriptCreateView.as_view(), name="script_create"),
url(r'^update/(?P<script_id>[^/]+)/?$', views.ScriptUpdateView.as_view(),
name="script_update"),
url(r'^(?P<script_id>[^/]+)/?$', views.ScriptDetailsView.as_view(),
name="script_details"),
)

View File

@ -0,0 +1,91 @@
# Copyright 2015 Objectif Libre
#
# 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 horizon import forms
from horizon import tables
from horizon import views
from cloudkittydashboard.api import cloudkitty as api
from cloudkittydashboard.dashboards.admin.pyscripts import forms \
as pyscripts_forms
from cloudkittydashboard.dashboards.admin.pyscripts import tables \
as pyscripts_tables
class IndexView(tables.DataTableView):
table_class = pyscripts_tables.PyScriptsTable
template_name = 'admin/pyscripts/pyscripts_list.html'
def get_data(self):
data = api.cloudkittyclient(self.request).pyscripts.scripts.list()
data = api.identify(data, name=False)
return data
class ScriptCreateView(forms.ModalFormView):
form_class = pyscripts_forms.CreateScriptForm
form_id = "create_script"
modal_header = _("Create Script")
page_title = _("Create Script")
submit_url = reverse_lazy('horizon:admin:pyscripts:script_create')
success_url = reverse_lazy('horizon:admin:pyscripts:index')
template_name = 'admin/pyscripts/form.html'
def get_object_id(self, obj):
return obj
class ScriptUpdateView(forms.ModalFormView):
form_class = pyscripts_forms.EditScriptForm
form_id = "update_script"
modal_header = _("Update Script")
page_title = _("Update Script")
submit_url = 'horizon:admin:pyscripts:script_update'
success_url = 'horizon:admin:pyscripts:script_update'
template_name = 'admin/pyscripts/form.html'
def get_initial(self):
script = api.cloudkittyclient(self.request).pyscripts.scripts.get(
script_id=self.kwargs['script_id'])
self.initial = script.to_dict()
self.initial['script_data'] = self.initial['data']
return self.initial
def get_context_data(self, **kwargs):
context = super(ScriptUpdateView, self).get_context_data(**kwargs)
context['script_id'] = self.kwargs.get('script_id')
context['submit_url'] = reverse_lazy(self.submit_url,
args=(context['script_id'], ))
return context
def get_success_url(self, **kwargs):
return reverse('horizon:admin:pyscripts:index')
class ScriptDetailsView(views.APIView):
template_name = 'admin/pyscripts/details.html'
page_title = _("Script Details : {{ script.name }}")
def get_data(self, request, context, *args, **kwargs):
script_id = kwargs.get("script_id")
try:
script = api.cloudkittyclient(self.request).pyscripts.scripts.get(
script_id=script_id)
except Exception:
script = None
context['script'] = script
return context

View File

@ -0,0 +1,5 @@
PANEL_GROUP = 'rating'
PANEL_DASHBOARD = 'admin'
PANEL = 'pyscripts'
ADD_PANEL = 'cloudkittydashboard.dashboards.admin.pyscripts.panel.PyScripts'