From 7f51d554019e02269ebda98f1d097e89862c8da0 Mon Sep 17 00:00:00 2001 From: Lin Hua Cheng Date: Mon, 19 Aug 2013 09:44:12 -0700 Subject: Display the container and object metadata Display some of the useful metadata information from swift: Container Details - Container Name, Object Count, Size Object Details - Name, Hash, Content Type, Last Modified, Size Change-Id: I6611cab08946a81624176c1836ceadaf16a68e45 Implements: blueprint swift-display-metadata --- .../dashboards/project/containers/tables.py | 23 ++++++++++- .../templates/containers/_container_detail.html | 22 +++++++++++ .../templates/containers/_object_detail.html | 26 ++++++++++++ .../templates/containers/container_detail.html | 12 ++++++ .../templates/containers/object_detail.html | 12 ++++++ .../dashboards/project/containers/tests.py | 36 +++++++++++++++++ .../dashboards/project/containers/urls.py | 15 ++++++- .../dashboards/project/containers/views.py | 46 ++++++++++++++++++++++ 8 files changed, 189 insertions(+), 3 deletions(-) create mode 100644 openstack_dashboard/dashboards/project/containers/templates/containers/_container_detail.html create mode 100644 openstack_dashboard/dashboards/project/containers/templates/containers/_object_detail.html create mode 100644 openstack_dashboard/dashboards/project/containers/templates/containers/container_detail.html create mode 100644 openstack_dashboard/dashboards/project/containers/templates/containers/object_detail.html (limited to 'openstack_dashboard/dashboards/project/containers') diff --git a/openstack_dashboard/dashboards/project/containers/tables.py b/openstack_dashboard/dashboards/project/containers/tables.py index ccb9d1bfd..9757a7746 100644 --- a/openstack_dashboard/dashboards/project/containers/tables.py +++ b/openstack_dashboard/dashboards/project/containers/tables.py @@ -36,6 +36,13 @@ def wrap_delimiter(name): return name +class ViewContainer(tables.LinkAction): + name = "view" + verbose_name = _("View Details") + url = "horizon:project:containers:container_detail" + classes = ("ajax-modal", "btn-view") + + class DeleteContainer(tables.DeleteAction): data_type_singular = _("Container") data_type_plural = _("Containers") @@ -127,11 +134,23 @@ class ContainersTable(tables.DataTable): name = "containers" verbose_name = _("Containers") table_actions = (CreateContainer,) - row_actions = (DeleteContainer,) + row_actions = (ViewContainer, DeleteContainer,) browser_table = "navigation" footer = False +class ViewObject(tables.LinkAction): + name = "view" + verbose_name = _("View Details") + url = "horizon:project:containers:object_detail" + classes = ("ajax-modal", "btn-view") + + def get_link_url(self, obj): + container_name = self.table.kwargs['container_name'] + return reverse(self.url, args=(http.urlquote(container_name), + http.urlquote(obj.name))) + + class DeleteObject(tables.DeleteAction): name = "delete_object" data_type_singular = _("Object") @@ -235,7 +254,7 @@ class ObjectsTable(tables.DataTable): verbose_name = _("Objects") table_actions = (ObjectFilterAction, UploadObject, DeleteMultipleObjects) - row_actions = (DownloadObject, CopyObject, DeleteObject) + row_actions = (DownloadObject, CopyObject, ViewObject, DeleteObject) data_types = ("subfolders", "objects") browser_table = "content" footer = False diff --git a/openstack_dashboard/dashboards/project/containers/templates/containers/_container_detail.html b/openstack_dashboard/dashboards/project/containers/templates/containers/_container_detail.html new file mode 100644 index 000000000..691731df0 --- /dev/null +++ b/openstack_dashboard/dashboards/project/containers/templates/containers/_container_detail.html @@ -0,0 +1,22 @@ +{% extends "horizon/common/_modal.html" %} +{% load i18n %} +{% load url from future %} + +{% block modal-header %}{% trans "Container Details" %}{% endblock %} + +{% block modal-body %} +
+
+
{% trans "Container Name" %}
+
{{ container.name }}
+
{% trans "Object Count" %}
+
{{ container.container_object_count }}
+
{% trans "Size" %}
+
{{ container.container_bytes_used|filesizeformat }}
+
+
+{% endblock %} + +{% block modal-footer %} + {% trans "Close" %} +{% endblock %} \ No newline at end of file diff --git a/openstack_dashboard/dashboards/project/containers/templates/containers/_object_detail.html b/openstack_dashboard/dashboards/project/containers/templates/containers/_object_detail.html new file mode 100644 index 000000000..cd07538cd --- /dev/null +++ b/openstack_dashboard/dashboards/project/containers/templates/containers/_object_detail.html @@ -0,0 +1,26 @@ +{% extends "horizon/common/_modal.html" %} +{% load i18n %} +{% load url from future %} + +{% block modal-header %}{% trans "Object Details" %}{% endblock %} + +{% block modal-body %} +
+
+
{% trans "Name" %}
+
{{ object.name }}
+
{% trans "Hash" %}
+
{{ object.etag }}
+
{% trans "Content Type" %}
+
{{ object.content_type }}
+
{% trans "Last Modified" %}
+
{{ object.timestamp|parse_isotime }}
+
{% trans "Size" %}
+
{{ object.bytes|filesizeformat }}
+
+
+{% endblock %} + +{% block modal-footer %} + {% trans "Close" %} +{% endblock %} \ No newline at end of file diff --git a/openstack_dashboard/dashboards/project/containers/templates/containers/container_detail.html b/openstack_dashboard/dashboards/project/containers/templates/containers/container_detail.html new file mode 100644 index 000000000..6fa77c384 --- /dev/null +++ b/openstack_dashboard/dashboards/project/containers/templates/containers/container_detail.html @@ -0,0 +1,12 @@ +{% extends 'base.html' %} +{% load i18n %} +{% block title %}{% trans "Container Details" %}{% endblock %} + +{% block page_header %} + {% include "horizon/common/_page_header.html" with title=_("Container Details") %} +{% endblock page_header %} + +{% block main %} + {% include 'project/containers/_container_detail.html' %} +{% endblock %} + diff --git a/openstack_dashboard/dashboards/project/containers/templates/containers/object_detail.html b/openstack_dashboard/dashboards/project/containers/templates/containers/object_detail.html new file mode 100644 index 000000000..7174389c8 --- /dev/null +++ b/openstack_dashboard/dashboards/project/containers/templates/containers/object_detail.html @@ -0,0 +1,12 @@ +{% extends 'base.html' %} +{% load i18n %} +{% block title %}{% trans "Object Details" %}{% endblock %} + +{% block page_header %} + {% include "horizon/common/_page_header.html" with title=_("Object Details") %} +{% endblock page_header %} + +{% block main %} + {% include 'project/containers/_object_detail.html' %} +{% endblock %} + diff --git a/openstack_dashboard/dashboards/project/containers/tests.py b/openstack_dashboard/dashboards/project/containers/tests.py index 193bb0e0c..36ea84ad3 100644 --- a/openstack_dashboard/dashboards/project/containers/tests.py +++ b/openstack_dashboard/dashboards/project/containers/tests.py @@ -237,3 +237,39 @@ class SwiftTests(test.TestCase): index_url = reverse('horizon:project:containers:index', args=[wrap_delimiter(container_2.name)]) self.assertRedirectsNoFollow(res, index_url) + + @test.create_stubs({api.swift: ('swift_get_container', )}) + def test_view_container(self): + container = self.containers.first() + + api.swift.swift_get_container(IsA(http.HttpRequest), + container.name) \ + .AndReturn(container) + self.mox.ReplayAll() + + view_url = reverse('horizon:project:containers:container_detail', + args=[container.name]) + res = self.client.get(view_url) + + self.assertTemplateUsed(res, + 'project/containers/container_detail.html') + self.assertContains(res, container.name, 1, 200) + + @test.create_stubs({api.swift: ('swift_get_object', )}) + def test_view_object(self): + container = self.containers.first() + obj = self.objects.first() + + api.swift.swift_get_object(IsA(http.HttpRequest), + container.name, + obj.name) \ + .AndReturn(obj) + self.mox.ReplayAll() + + view_url = reverse('horizon:project:containers:object_detail', + args=[container.name, obj.name]) + res = self.client.get(view_url) + + self.assertTemplateUsed(res, + 'project/containers/object_detail.html') + self.assertContains(res, obj.name, 1, 200) diff --git a/openstack_dashboard/dashboards/project/containers/urls.py b/openstack_dashboard/dashboards/project/containers/urls.py index 46c71cc73..dc93a212d 100644 --- a/openstack_dashboard/dashboards/project/containers/urls.py +++ b/openstack_dashboard/dashboards/project/containers/urls.py @@ -21,10 +21,14 @@ from django.conf.urls.defaults import patterns from django.conf.urls.defaults import url +from openstack_dashboard.dashboards.project.containers.views import \ + ContainerDetailView from openstack_dashboard.dashboards.project.containers.views import \ ContainerView from openstack_dashboard.dashboards.project.containers.views import CopyView from openstack_dashboard.dashboards.project.containers.views import CreateView +from openstack_dashboard.dashboards.project.containers.views import \ + ObjectDetailView from openstack_dashboard.dashboards.project.containers.views import UploadView @@ -39,6 +43,15 @@ urlpatterns = patterns(VIEW_MOD, CreateView.as_view(), name='create'), + url(r'^(?P.+?)/(?P(.+/)+)' + '?container_detail$', + ContainerDetailView.as_view(), + name='container_detail'), + + url(r'^(?P[^/]+)/(?P.+)/object_detail$', + ObjectDetailView.as_view(), + name='object_detail'), + url(r'^(?P.+?)/(?P(.+/)+)?upload$', UploadView.as_view(), name='object_upload'), @@ -51,5 +64,5 @@ urlpatterns = patterns(VIEW_MOD, url(r'^(?P[^/]+)/(?P.+)/download$', 'object_download', - name='object_download') + name='object_download'), ) diff --git a/openstack_dashboard/dashboards/project/containers/views.py b/openstack_dashboard/dashboards/project/containers/views.py index 674eaf699..a27e64164 100644 --- a/openstack_dashboard/dashboards/project/containers/views.py +++ b/openstack_dashboard/dashboards/project/containers/views.py @@ -25,6 +25,7 @@ Views for managing Swift containers. from django.core.urlresolvers import reverse from django import http from django.utils.translation import ugettext_lazy as _ +from django.views import generic from horizon import browsers from horizon import exceptions @@ -226,3 +227,48 @@ class CopyView(forms.ModalFormView): context['container_name'] = self.kwargs["container_name"] context['object_name'] = self.kwargs["object_name"] return context + + +class ContainerDetailView(forms.ModalFormMixin, generic.TemplateView): + template_name = 'project/containers/container_detail.html' + + def get_object(self): + if not hasattr(self, "_object"): + try: + self._object = api.swift.swift_get_container( + self.request, + self.kwargs["container_name"]) + except Exception: + redirect = reverse("horizon:project:containers:index") + exceptions.handle(self.request, + _('Unable to retrieve details.'), + redirect=redirect) + return self._object + + def get_context_data(self, **kwargs): + context = super(ContainerDetailView, self).get_context_data(**kwargs) + context['container'] = self.get_object() + return context + + +class ObjectDetailView(forms.ModalFormMixin, generic.TemplateView): + template_name = 'project/containers/object_detail.html' + + def get_object(self): + if not hasattr(self, "_object"): + try: + self._object = api.swift.swift_get_object( + self.request, + self.kwargs["container_name"], + self.kwargs["object_path"]) + except Exception: + redirect = reverse("horizon:project:containers:index") + exceptions.handle(self.request, + _('Unable to retrieve details.'), + redirect=redirect) + return self._object + + def get_context_data(self, **kwargs): + context = super(ObjectDetailView, self).get_context_data(**kwargs) + context['object'] = self.get_object() + return context -- cgit v1.2.1