Merge "Allow inline name editing"

This commit is contained in:
Jenkins
2015-07-27 15:04:21 +00:00
committed by Gerrit Code Review
5 changed files with 92 additions and 26 deletions

View File

@@ -21,15 +21,17 @@ from django.template import defaultfilters
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from horizon import exceptions from horizon import exceptions
from horizon import forms
from horizon import messages from horizon import messages
from horizon import tables from horizon import tables
from muranodashboard import api as api_utils
from muranodashboard.api import packages as pkg_api
from muranodashboard.catalog import views as catalog_views from muranodashboard.catalog import views as catalog_views
from muranodashboard.environments import api from muranodashboard.environments import api
from muranodashboard.environments import consts from muranodashboard.environments import consts
from muranodashboard import api as api_utils from muranoclient.common import exceptions as exc
from muranodashboard.api import packages as pkg_api
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
@@ -135,21 +137,6 @@ class AbandonEnvironment(tables.DeleteAction):
exceptions.handle(request, msg, redirect=redirect) exceptions.handle(request, msg, redirect=redirect)
class EditEnvironment(tables.LinkAction):
name = 'edit'
verbose_name = _('Edit Environment')
url = 'horizon:murano:environments:update_environment'
classes = ('ajax-modal', 'btn-edit')
icon = 'edit'
def allowed(self, request, environment):
"""Allow edit environment only when status not deploying and deleting.
"""
status = getattr(environment, 'status', None)
return status not in [consts.STATUS_ID_DEPLOYING,
consts.STATUS_ID_DELETING]
class DeleteService(tables.DeleteAction): class DeleteService(tables.DeleteAction):
data_type_singular = _('Component') data_type_singular = _('Component')
data_type_plural = _('Components') data_type_plural = _('Components')
@@ -270,10 +257,36 @@ class UpdateServiceRow(tables.Row):
return api.service_get(request, environment_id, service_id) return api.service_get(request, environment_id, service_id)
class UpdateName(tables.UpdateAction):
def update_cell(self, request, datum, obj_id, cell_name, new_cell_value):
try:
mc = api_utils.muranoclient(request)
mc.environments.update(datum.id, name=new_cell_value)
except exc.HTTPConflict:
message = _("This name is already taken.")
messages.warning(request, message)
LOG.warning(_("Couldn't update environment. Reason: ") + message)
# FIXME(kzaitsev): There is a bug in horizon and inline error
# icons are missing. This means, that if we return 400 here, by
# raising django.core.exceptions.ValidationError(message) the UI
# will break a little. Until the bug is fixed this will raise 500
# bug link: https://bugs.launchpad.net/horizon/+bug/1359399
# Alternatively this could somehow raise 409, which would result
# in the same behaviour.
raise ValueError(message)
except Exception:
exceptions.handle(request, ignore=True)
return False
return True
class EnvironmentsTable(tables.DataTable): class EnvironmentsTable(tables.DataTable):
name = tables.Column('name', name = tables.Column('name',
link='horizon:murano:environments:services', link='horizon:murano:environments:services',
verbose_name=_('Name')) verbose_name=_('Name'),
form_field=forms.CharField(),
update_action=UpdateName)
status = tables.Column('status', status = tables.Column('status',
verbose_name=_('Status'), verbose_name=_('Status'),
@@ -290,7 +303,7 @@ class EnvironmentsTable(tables.DataTable):
no_data_message = _('NO ENVIRONMENTS') no_data_message = _('NO ENVIRONMENTS')
table_actions = (CreateEnvironment,) table_actions = (CreateEnvironment,)
row_actions = (ShowEnvironmentServices, DeployEnvironment, row_actions = (ShowEnvironmentServices, DeployEnvironment,
EditEnvironment, DeleteEnvironment, AbandonEnvironment) DeleteEnvironment, AbandonEnvironment)
multi_select = False multi_select = False

View File

@@ -1,3 +1,35 @@
table#murano div.table_cell_wrapper div.inline-edit-form input {
/*
* overrides from form-control, to make inline edit consistent
* with the rest of UI
*/
display: block;
height: 32px;
font-size: 13px;
line-height: 1.42857;
color: #555;
background-color: #fff;
background-image: none;
border: 1px solid #ccc;
border-radius: 4px;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
-o-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
/* Additional styles, not present in form-control */
margin: 7px 7px 0 7px;
width: calc(100% - 14px);
}
table#murano div.table_cell_wrapper div.inline-edit-form input:focus {
border-color: #66afe9;
outline: 0;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
}
.table_header.catalog { .table_header.catalog {
border-bottom: 2px solid #e5e5e5; border-bottom: 2px solid #e5e5e5;
padding-bottom:5px; padding-bottom:5px;

View File

@@ -12,11 +12,11 @@
{% endblock %} {% endblock %}
{% block css %} {% block css %}
{% include "_stylesheets.html" %} {{ block.super }}
<link href='{{ STATIC_URL }}muranodashboard/css/catalog.css' type='text/css' media='screen' rel='stylesheet' /> <link href='{{ STATIC_URL }}muranodashboard/css/catalog.css' type='text/css' media='screen' rel='stylesheet' />
{% endblock %} {% endblock %}
{% block js %} {% block js %}
{% include 'horizon/_scripts.html' %} {% include 'horizon/_scripts.html' %}
<script src="{% static 'muranodashboard/js/environments-in-place.js' %}"></script> <script src="{% static 'muranodashboard/js/environments-in-place.js' %}"></script>
{% endblock %} {% endblock %}

View File

@@ -23,6 +23,7 @@ from keystoneclient.v2_0 import client as ksclient
from muranoclient import client as mclient from muranoclient import client as mclient
from selenium.common import exceptions as exc from selenium.common import exceptions as exc
from selenium import webdriver from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
import selenium.webdriver.common.by as by import selenium.webdriver.common.by as by
from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support import ui from selenium.webdriver.support import ui
@@ -195,10 +196,29 @@ class UITestCase(BaseDeps):
self.wait_for_alert_message() self.wait_for_alert_message()
def edit_environment(self, old_name, new_name): def edit_environment(self, old_name, new_name):
self.select_action_for_environment(old_name, 'edit') el_td = self.driver.find_element_by_css_selector(
self.fill_field(by.By.ID, 'id_name', new_name) 'tr[data-display="{0}"] td:first-of-type'.format(old_name))
self.driver.find_element_by_xpath(consts.InputSubmit).click() el_pencil = el_td.find_element_by_css_selector(
self.wait_for_alert_message() 'button.ajax-inline-edit')
# hover to make pencil visible
hover = ActionChains(self.driver).move_to_element(el_td)
hover.perform()
el_pencil.click()
# fill in inline input
el_inline_input = self.driver.find_element_by_css_selector(
'tr[data-display="{0}"] '.format(old_name) +
'td:first-of-type .inline-edit-form input')
el_inline_input.clear()
el_inline_input.send_keys(new_name)
# click submit
el_submit = self.driver.find_element_by_css_selector(
'tr[data-display="{0}"] '.format(old_name) +
'td:first-of-type .inline-edit-actions button[type="submit"]')
el_submit.click()
# there is no alert message
def select_action_for_environment(self, env_name, action): def select_action_for_environment(self, env_name, action):
element_id = self.get_element_id(env_name) element_id = self.get_element_id(env_name)

View File

@@ -74,9 +74,10 @@ class TestSuiteEnvironment(base.ApplicationTestCase):
self.go_to_submenu('Environments') self.go_to_submenu('Environments')
self.create_environment('test_edit_env') self.create_environment('test_edit_env')
self.go_to_submenu('Environments') self.go_to_submenu('Environments')
self.driver.find_element_by_link_text('test_edit_env')
self.edit_environment(old_name='test_edit_env', new_name='edited_env') self.edit_environment(old_name='test_edit_env', new_name='edited_env')
self.go_to_submenu('Environments')
self.check_element_on_page(by.By.LINK_TEXT, 'edited_env') self.check_element_on_page(by.By.LINK_TEXT, 'edited_env')
self.check_element_not_on_page(by.By.LINK_TEXT, 'test_edit_env') self.check_element_not_on_page(by.By.LINK_TEXT, 'test_edit_env')