Update action for namespaces table public/protected attributes
With the inline edit deprecation the ability to edit the public/protected attributes for a namespace was also removed. This patch adds an update action to the namespaces table so users can edit these attributes. Change-Id: I7476b49a5bfe161c000046dfb5d622bfec924da7 Closes-Bug: #1617353
This commit is contained in:
@@ -14,6 +14,8 @@
|
||||
|
||||
METADATA_CREATE_TEMPLATE = 'admin/metadata_defs/create.html'
|
||||
METADATA_CREATE_URL = "horizon:admin:metadata_defs:create"
|
||||
METADATA_UPDATE_TEMPLATE = 'admin/metadata_defs/update.html'
|
||||
METADATA_UPDATE_URL = "horizon:admin:metadata_defs:update"
|
||||
METADATA_DETAIL_OVERVIEW_TEMPLATE = "admin/metadata_defs/_detail_overview.html"
|
||||
METADATA_DETAIL_CONTENTS_TEMPLATE = "admin/metadata_defs/_detail_contents.html"
|
||||
METADATA_DETAIL_TEMPLATE = 'horizon/common/_detail.html'
|
||||
|
@@ -18,6 +18,7 @@ Forms for managing metadata.
|
||||
"""
|
||||
import json
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.forms import ValidationError # noqa
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
@@ -146,3 +147,30 @@ class ManageResourceTypesForm(forms.SelfHandlingForm):
|
||||
|
||||
def get_names(self, items):
|
||||
return [item['name'] for item in items]
|
||||
|
||||
|
||||
class UpdateNamespaceForm(forms.SelfHandlingForm):
|
||||
|
||||
public = forms.BooleanField(label=_("Public"), required=False)
|
||||
protected = forms.BooleanField(label=_("Protected"), required=False)
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
super(UpdateNamespaceForm, self).__init__(request, *args, **kwargs)
|
||||
|
||||
def handle(self, request, data):
|
||||
try:
|
||||
params = {
|
||||
'visibility': 'public' if data['public'] else 'private',
|
||||
'protected': data['protected']
|
||||
}
|
||||
glance.metadefs_namespace_update(request,
|
||||
self.initial['namespace_id'],
|
||||
**params)
|
||||
msg = _('Namespace successfully updated.')
|
||||
messages.success(request, msg)
|
||||
except Exception:
|
||||
msg = _('Error updating attributes for namespace.')
|
||||
redirect = reverse(constants.METADATA_INDEX_URL)
|
||||
exceptions.handle(request, msg, redirect=redirect)
|
||||
return False
|
||||
return True
|
||||
|
@@ -33,6 +33,13 @@ class ImportNamespace(tables.LinkAction):
|
||||
policy_rules = (("image", "add_metadef_namespace"),)
|
||||
|
||||
|
||||
class EditNamespace(tables.LinkAction):
|
||||
name = 'update'
|
||||
verbose_name = _('Edit Namespace')
|
||||
url = constants.METADATA_UPDATE_URL
|
||||
classes = ('ajax-modal',)
|
||||
|
||||
|
||||
class DeleteNamespace(tables.DeleteAction):
|
||||
@staticmethod
|
||||
def action_present(count):
|
||||
@@ -138,6 +145,7 @@ class AdminNamespacesTable(tables.DataTable):
|
||||
table_actions = (AdminMetadataFilterAction,
|
||||
ImportNamespace,
|
||||
DeleteNamespace,)
|
||||
row_actions = (ManageResourceTypeAssociations,
|
||||
row_actions = (EditNamespace,
|
||||
ManageResourceTypeAssociations,
|
||||
DeleteNamespace,)
|
||||
pagination_param = "namespace_marker"
|
||||
|
@@ -0,0 +1,18 @@
|
||||
{% extends "horizon/common/_modal_form.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block modal-header %}{% trans "Edit Namespace Attributes" %}{% endblock %}
|
||||
|
||||
{% block modal-body %}
|
||||
<div class="left">
|
||||
<fieldset>
|
||||
{% include "horizon/common/_form_fields.html" %}
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="right">
|
||||
<h3>{% trans "Description:" %}</h3>
|
||||
<p>
|
||||
{% trans "Edit Public/Protected attributes for the namespace." %}
|
||||
</p>
|
||||
</div>
|
||||
{% endblock %}
|
@@ -0,0 +1,7 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Update a Metadata Namespace" %}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
{% include 'admin/metadata_defs/_update.html' %}
|
||||
{% endblock %}
|
@@ -305,3 +305,99 @@ class MetadataDefinitionsCreateViewTest(test.BaseAdminViewTests):
|
||||
|
||||
self.assertFormError(res, "form", None, ['No input was provided for '
|
||||
'the namespace content.'])
|
||||
|
||||
|
||||
class MetadataDefinitionsUpdateViewTest(test.BaseAdminViewTests):
|
||||
|
||||
@test.create_stubs({api.glance: ('metadefs_namespace_get', )})
|
||||
def test_admin_metadata_defs_update_namespace_get(self):
|
||||
namespace = self.metadata_defs.first()
|
||||
|
||||
api.glance.metadefs_namespace_get(
|
||||
IsA(http.HttpRequest),
|
||||
namespace["namespace"]).AndReturn(namespace)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
res = self.client.get(reverse(
|
||||
constants.METADATA_UPDATE_URL,
|
||||
args=[namespace['namespace']]))
|
||||
self.assertTemplateUsed(res, constants.METADATA_UPDATE_TEMPLATE)
|
||||
|
||||
@test.create_stubs({api.glance: ('metadefs_namespace_get',)})
|
||||
def test_admin_metadata_defs_update_namespace_get_exception(self):
|
||||
namespace = self.metadata_defs.first()
|
||||
|
||||
api.glance.metadefs_namespace_get(
|
||||
IsA(http.HttpRequest),
|
||||
namespace["namespace"]).AndRaise(self.exceptions.glance)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
res = self.client.get(reverse(
|
||||
constants.METADATA_UPDATE_URL,
|
||||
args=[namespace['namespace']]))
|
||||
self.assertRedirectsNoFollow(res,
|
||||
reverse(constants.METADATA_INDEX_URL))
|
||||
|
||||
@test.create_stubs({api.glance: ('metadefs_namespace_get',
|
||||
'metadefs_namespace_update',)})
|
||||
def test_admin_metadata_defs_update_namespace_post(self):
|
||||
namespace = self.metadata_defs.first()
|
||||
params = {
|
||||
'visibility': namespace.visibility,
|
||||
'protected': namespace.protected
|
||||
}
|
||||
|
||||
api.glance.metadefs_namespace_update(
|
||||
IsA(http.HttpRequest),
|
||||
namespace.namespace,
|
||||
**params).AndReturn(namespace)
|
||||
|
||||
api.glance.metadefs_namespace_get(
|
||||
IsA(http.HttpRequest),
|
||||
namespace["namespace"]).AndReturn(namespace)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
form_data = {
|
||||
'namespace_id': namespace.namespace,
|
||||
'public': True,
|
||||
'protected': True
|
||||
}
|
||||
|
||||
url = reverse(constants.METADATA_UPDATE_URL,
|
||||
args=[namespace.namespace])
|
||||
res = self.client.post(url, form_data)
|
||||
|
||||
self.assertRedirectsNoFollow(res,
|
||||
reverse(constants.METADATA_INDEX_URL))
|
||||
|
||||
@test.create_stubs({api.glance: ('metadefs_namespace_get',
|
||||
'metadefs_namespace_update',)})
|
||||
def test_admin_metadata_defs_update_namespace_post_exception(self):
|
||||
namespace = self.metadata_defs.first()
|
||||
params = {
|
||||
'visibility': namespace.visibility,
|
||||
'protected': namespace.protected
|
||||
}
|
||||
|
||||
api.glance.metadefs_namespace_update(
|
||||
IsA(http.HttpRequest),
|
||||
namespace.namespace,
|
||||
**params).AndRaise(self.exceptions.glance)
|
||||
|
||||
api.glance.metadefs_namespace_get(
|
||||
IsA(http.HttpRequest),
|
||||
namespace["namespace"]).AndReturn(namespace)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
form_data = {
|
||||
'namespace_id': namespace.namespace,
|
||||
'public': True,
|
||||
'protected': True
|
||||
}
|
||||
|
||||
url = reverse(constants.METADATA_UPDATE_URL,
|
||||
args=[namespace.namespace])
|
||||
res = self.client.post(url, form_data)
|
||||
|
||||
self.assertRedirectsNoFollow(res,
|
||||
reverse(constants.METADATA_INDEX_URL))
|
||||
|
@@ -23,6 +23,7 @@ NAMESPACES = r'^(?P<namespace_id>[^/]+)/%s$'
|
||||
urlpatterns = [
|
||||
url(r'^$', views.AdminIndexView.as_view(), name='index'),
|
||||
url(r'^create/$', views.CreateView.as_view(), name='create'),
|
||||
url(NAMESPACES % 'update', views.UpdateView.as_view(), name='update'),
|
||||
url(NAMESPACES % 'detail', views.DetailView.as_view(), name='detail'),
|
||||
url(r'^(?P<id>[^/]+)/resource_types/$',
|
||||
views.ManageResourceTypes.as_view(), name='resource_types'),
|
||||
|
@@ -14,6 +14,7 @@
|
||||
|
||||
import json
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.core.urlresolvers import reverse_lazy
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
@@ -89,6 +90,42 @@ class CreateView(forms.ModalFormView):
|
||||
submit_label = _("Import Namespace")
|
||||
|
||||
|
||||
class UpdateView(forms.ModalFormView):
|
||||
form_class = admin_forms.UpdateNamespaceForm
|
||||
form_id = 'update_namespace_attributes_form'
|
||||
template_name = constants.METADATA_UPDATE_TEMPLATE
|
||||
context_object_name = 'namespace'
|
||||
success_url = reverse_lazy(constants.METADATA_INDEX_URL)
|
||||
submit_url = constants.METADATA_UPDATE_URL
|
||||
page_title = _("Edit Metadata Namespace")
|
||||
submit_label = _("Save Changes")
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(UpdateView, self).get_context_data(**kwargs)
|
||||
args = (self.kwargs['namespace_id'],)
|
||||
context["namespace_id"] = self.kwargs['namespace_id']
|
||||
context["submit_url"] = reverse(self.submit_url, args=args)
|
||||
return context
|
||||
|
||||
def _get_object(self, *args, **kwargs):
|
||||
namespace_id = self.kwargs['namespace_id']
|
||||
try:
|
||||
return glance.metadefs_namespace_get(self.request, namespace_id)
|
||||
except Exception:
|
||||
redirect = self.success_url
|
||||
msg = _('Unable to retrieve namespace details.')
|
||||
exceptions.handle(self.request, msg, redirect=redirect)
|
||||
|
||||
def get_initial(self):
|
||||
namespace = self._get_object()
|
||||
visibility = \
|
||||
True if namespace['visibility'] == 'public' else False
|
||||
return {'namespace_id': namespace['namespace'],
|
||||
'public': visibility,
|
||||
'protected': namespace['protected'],
|
||||
}
|
||||
|
||||
|
||||
class DetailView(tabs.TabView):
|
||||
redirect_url = constants.METADATA_INDEX_URL
|
||||
tab_group_class = admin_tabs.NamespaceDetailTabs
|
||||
|
Reference in New Issue
Block a user