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')