diff --git a/muranodashboard/environments/tables.py b/muranodashboard/environments/tables.py
index a61e0705b..309c0dae7 100644
--- a/muranodashboard/environments/tables.py
+++ b/muranodashboard/environments/tables.py
@@ -21,15 +21,17 @@ from django.template import defaultfilters
from django.utils.translation import ugettext_lazy as _
from horizon import exceptions
+from horizon import forms
from horizon import messages
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.environments import api
from muranodashboard.environments import consts
-from muranodashboard import api as api_utils
-from muranodashboard.api import packages as pkg_api
+from muranoclient.common import exceptions as exc
LOG = logging.getLogger(__name__)
@@ -135,21 +137,6 @@ class AbandonEnvironment(tables.DeleteAction):
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):
data_type_singular = _('Component')
data_type_plural = _('Components')
@@ -270,10 +257,36 @@ class UpdateServiceRow(tables.Row):
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):
name = tables.Column('name',
link='horizon:murano:environments:services',
- verbose_name=_('Name'))
+ verbose_name=_('Name'),
+ form_field=forms.CharField(),
+ update_action=UpdateName)
status = tables.Column('status',
verbose_name=_('Status'),
@@ -290,7 +303,7 @@ class EnvironmentsTable(tables.DataTable):
no_data_message = _('NO ENVIRONMENTS')
table_actions = (CreateEnvironment,)
row_actions = (ShowEnvironmentServices, DeployEnvironment,
- EditEnvironment, DeleteEnvironment, AbandonEnvironment)
+ DeleteEnvironment, AbandonEnvironment)
multi_select = False
diff --git a/muranodashboard/static/muranodashboard/css/catalog.css b/muranodashboard/static/muranodashboard/css/catalog.css
index 7728a6b7b..fa9eef5b2 100644
--- a/muranodashboard/static/muranodashboard/css/catalog.css
+++ b/muranodashboard/static/muranodashboard/css/catalog.css
@@ -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 {
border-bottom: 2px solid #e5e5e5;
padding-bottom:5px;
diff --git a/muranodashboard/templates/environments/index.html b/muranodashboard/templates/environments/index.html
index 7e5c9364e..35951d5a6 100644
--- a/muranodashboard/templates/environments/index.html
+++ b/muranodashboard/templates/environments/index.html
@@ -12,11 +12,11 @@
{% endblock %}
{% block css %}
- {% include "_stylesheets.html" %}
+ {{ block.super }}
{% endblock %}
{% block js %}
{% include 'horizon/_scripts.html' %}
-{% endblock %}
\ No newline at end of file
+{% endblock %}
diff --git a/muranodashboard/tests/functional/base.py b/muranodashboard/tests/functional/base.py
index e19d0c0af..a400de380 100644
--- a/muranodashboard/tests/functional/base.py
+++ b/muranodashboard/tests/functional/base.py
@@ -23,6 +23,7 @@ from keystoneclient.v2_0 import client as ksclient
from muranoclient import client as mclient
from selenium.common import exceptions as exc
from selenium import webdriver
+from selenium.webdriver.common.action_chains import ActionChains
import selenium.webdriver.common.by as by
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support import ui
@@ -195,10 +196,29 @@ class UITestCase(BaseDeps):
self.wait_for_alert_message()
def edit_environment(self, old_name, new_name):
- self.select_action_for_environment(old_name, 'edit')
- self.fill_field(by.By.ID, 'id_name', new_name)
- self.driver.find_element_by_xpath(consts.InputSubmit).click()
- self.wait_for_alert_message()
+ el_td = self.driver.find_element_by_css_selector(
+ 'tr[data-display="{0}"] td:first-of-type'.format(old_name))
+ el_pencil = el_td.find_element_by_css_selector(
+ '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):
element_id = self.get_element_id(env_name)
diff --git a/muranodashboard/tests/functional/sanity_check.py b/muranodashboard/tests/functional/sanity_check.py
index 5d07121e3..399bb6a55 100644
--- a/muranodashboard/tests/functional/sanity_check.py
+++ b/muranodashboard/tests/functional/sanity_check.py
@@ -74,9 +74,10 @@ class TestSuiteEnvironment(base.ApplicationTestCase):
self.go_to_submenu('Environments')
self.create_environment('test_edit_env')
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.go_to_submenu('Environments')
self.check_element_on_page(by.By.LINK_TEXT, 'edited_env')
self.check_element_not_on_page(by.By.LINK_TEXT, 'test_edit_env')