plone.restapi/plone-only-login: Make navigation component expandable

Thomas Buchberger <jenkins-z4DKO/[email protected]>
Newsgroups gmane.comp.web.zope.plone.cvs
Message-ID <[email protected]>
Repository: plone.restapi
Branch: refs/heads/plone-only-login
Date: 2017-07-25T10:37:43+02:00
Author: Thomas Buchberger (buchi) <t.buchberger-/8aE7x569Db/[email protected]>
Commit: https://github.com/plone/plone.restapi/commit/bcf1fb5eb03717a5f03781d8cd8b42acdd9bfd1b

Make navigation component expandable

Files changed:
A src/plone/restapi/services/components/navigation.py
M docs/source/_json/collection.resp
M docs/source/_json/content_get.resp
M docs/source/_json/content_post.resp
M docs/source/_json/document.resp
M docs/source/_json/event.resp
M docs/source/_json/file.resp
M docs/source/_json/folder.resp
M docs/source/_json/image.resp
M docs/source/_json/jwt_logged_in.resp
M docs/source/_json/link.resp
M docs/source/_json/newsitem.resp
M docs/source/_json/siteroot.resp
M src/plone/restapi/services/components/configure.zcml
M src/plone/restapi/services/components/get.py
M src/plone/restapi/tests/test_components.py

diff --git a/docs/source/_json/collection.resp b/docs/source/_json/collection.resp
index 12cac672..ac162329 100644
--- a/docs/source/_json/collection.resp
+++ b/docs/source/_json/collection.resp
@@ -2,6 +2,11 @@ HTTP/1.1 200 OK
 Content-Type: application/json
 
 {
+  "@components": {
+    "navigation": {
+      "@id": "http://localhost:55001/plone/collection/@components/navigation"
+    }
+  }, 
   "@id": "http://localhost:55001/plone/collection", 
   "@type": "Collection", 
   "@workflow": {
diff --git a/docs/source/_json/content_get.resp b/docs/source/_json/content_get.resp
index 69c3f4b9..ad1e0345 100644
--- a/docs/source/_json/content_get.resp
+++ b/docs/source/_json/content_get.resp
@@ -2,6 +2,11 @@ HTTP/1.1 200 OK
 Content-Type: application/json
 
 {
+  "@components": {
+    "navigation": {
+      "@id": "http://localhost:55001/plone/folder/my-document/@components/navigation"
+    }
+  }, 
   "@id": "http://localhost:55001/plone/folder/my-document", 
   "@type": "Document", 
   "@workflow": {
diff --git a/docs/source/_json/content_post.resp b/docs/source/_json/content_post.resp
index ae35de46..4cde4d25 100644
--- a/docs/source/_json/content_post.resp
+++ b/docs/source/_json/content_post.resp
@@ -3,6 +3,11 @@ Content-Type: application/json
 Location: http://localhost:55001/plone/folder/my-document
 
 {
+  "@components": {
+    "navigation": {
+      "@id": "http://localhost:55001/plone/folder/my-document/@components/navigation"
+    }
+  }, 
   "@id": "http://localhost:55001/plone/folder/my-document", 
   "@type": "Document", 
   "@workflow": {
diff --git a/docs/source/_json/document.resp b/docs/source/_json/document.resp
index 31dfecfa..87a16856 100644
--- a/docs/source/_json/document.resp
+++ b/docs/source/_json/document.resp
@@ -2,6 +2,11 @@ HTTP/1.1 200 OK
 Content-Type: application/json
 
 {
+  "@components": {
+    "navigation": {
+      "@id": "http://localhost:55001/plone/front-page/@components/navigation"
+    }
+  }, 
   "@id": "http://localhost:55001/plone/front-page", 
   "@type": "Document", 
   "@workflow": {
diff --git a/docs/source/_json/event.resp b/docs/source/_json/event.resp
index f2ac6eea..d749122d 100644
--- a/docs/source/_json/event.resp
+++ b/docs/source/_json/event.resp
@@ -2,6 +2,11 @@ HTTP/1.1 200 OK
 Content-Type: application/json
 
 {
+  "@components": {
+    "navigation": {
+      "@id": "http://localhost:55001/plone/event/@components/navigation"
+    }
+  }, 
   "@id": "http://localhost:55001/plone/event", 
   "@type": "Event", 
   "@workflow": {
diff --git a/docs/source/_json/file.resp b/docs/source/_json/file.resp
index b19631d4..ed46fc3c 100644
--- a/docs/source/_json/file.resp
+++ b/docs/source/_json/file.resp
@@ -2,6 +2,11 @@ HTTP/1.1 200 OK
 Content-Type: application/json
 
 {
+  "@components": {
+    "navigation": {
+      "@id": "http://localhost:55001/plone/file/@components/navigation"
+    }
+  }, 
   "@id": "http://localhost:55001/plone/file", 
   "@type": "File", 
   "@workflow": {
diff --git a/docs/source/_json/folder.resp b/docs/source/_json/folder.resp
index 7b10cfab..19685167 100644
--- a/docs/source/_json/folder.resp
+++ b/docs/source/_json/folder.resp
@@ -2,6 +2,11 @@ HTTP/1.1 200 OK
 Content-Type: application/json
 
 {
+  "@components": {
+    "navigation": {
+      "@id": "http://localhost:55001/plone/folder/@components/navigation"
+    }
+  }, 
   "@id": "http://localhost:55001/plone/folder", 
   "@type": "Folder", 
   "@workflow": {
diff --git a/docs/source/_json/image.resp b/docs/source/_json/image.resp
index 42b0afc0..4d2b0751 100644
--- a/docs/source/_json/image.resp
+++ b/docs/source/_json/image.resp
@@ -2,6 +2,11 @@ HTTP/1.1 200 OK
 Content-Type: application/json
 
 {
+  "@components": {
+    "navigation": {
+      "@id": "http://localhost:55001/plone/image/@components/navigation"
+    }
+  }, 
   "@id": "http://localhost:55001/plone/image", 
   "@type": "Image", 
   "@workflow": {
diff --git a/docs/source/_json/jwt_logged_in.resp b/docs/source/_json/jwt_logged_in.resp
index 0559a5bb..331ee0c9 100644
--- a/docs/source/_json/jwt_logged_in.resp
+++ b/docs/source/_json/jwt_logged_in.resp
@@ -2,6 +2,11 @@ HTTP/1.1 200 OK
 Content-Type: application/json
 
 {
+  "@components": {
+    "navigation": {
+      "@id": "http://localhost:55001/plone/@components/navigation"
+    }
+  }, 
   "@id": "http://localhost:55001/plone/", 
   "@type": "Plone Site", 
   "id": "plone", 
diff --git a/docs/source/_json/link.resp b/docs/source/_json/link.resp
index b7f72838..05360f3e 100644
--- a/docs/source/_json/link.resp
+++ b/docs/source/_json/link.resp
@@ -2,6 +2,11 @@ HTTP/1.1 200 OK
 Content-Type: application/json
 
 {
+  "@components": {
+    "navigation": {
+      "@id": "http://localhost:55001/plone/link/@components/navigation"
+    }
+  }, 
   "@id": "http://localhost:55001/plone/link", 
   "@type": "Link", 
   "@workflow": {
diff --git a/docs/source/_json/newsitem.resp b/docs/source/_json/newsitem.resp
index cde39d44..b0013e66 100644
--- a/docs/source/_json/newsitem.resp
+++ b/docs/source/_json/newsitem.resp
@@ -2,6 +2,11 @@ HTTP/1.1 200 OK
 Content-Type: application/json
 
 {
+  "@components": {
+    "navigation": {
+      "@id": "http://localhost:55001/plone/newsitem/@components/navigation"
+    }
+  }, 
   "@id": "http://localhost:55001/plone/newsitem", 
   "@type": "News Item", 
   "@workflow": {
diff --git a/docs/source/_json/siteroot.resp b/docs/source/_json/siteroot.resp
index db02eb31..46705593 100644
--- a/docs/source/_json/siteroot.resp
+++ b/docs/source/_json/siteroot.resp
@@ -2,6 +2,11 @@ HTTP/1.1 200 OK
 Content-Type: application/json
 
 {
+  "@components": {
+    "navigation": {
+      "@id": "http://localhost:55001/plone/@components/navigation"
+    }
+  }, 
   "@id": "http://localhost:55001/plone", 
   "@type": "Plone Site", 
   "id": "plone", 
diff --git a/src/plone/restapi/services/components/configure.zcml b/src/plone/restapi/services/components/configure.zcml
index 1ce44ab5..fa6faebd 100644
--- a/src/plone/restapi/services/components/configure.zcml
+++ b/src/plone/restapi/services/components/configure.zcml
@@ -10,4 +10,6 @@
     permission="zope2.View"
     />
 
+    <adapter factory=".navigation.Navigation" name="navigation"/>
+
 </configure>
\ No newline at end of file
diff --git a/src/plone/restapi/services/components/get.py b/src/plone/restapi/services/components/get.py
index 65345dd3..f580e3a1 100644
--- a/src/plone/restapi/services/components/get.py
+++ b/src/plone/restapi/services/components/get.py
@@ -1,5 +1,6 @@
 # -*- coding: utf-8 -*-
 from plone.restapi.services import Service
+from plone.restapi.services.components.navigation import Navigation
 from zope.deprecation import deprecate
 from zope.component import getMultiAdapter
 from zope.interface import implements
@@ -33,17 +34,6 @@ def _wrap_component_items(self, items, component_id):
         }
         return component
 
-    def get_navigation(self):
-        tabs = getMultiAdapter((self.context, self.request),
-                               name="portal_tabs_view")
-        result = []
-        for tab in tabs.topLevelTabs():
-            result.append({
-                'title': tab.get('title', tab.get('name')),
-                'url': tab['url'] + ''
-            })
-        return result
-
     def get_breadcrumbs(self):
         breadcrumbs_view = getMultiAdapter((self.context, self.request),
                                            name="breadcrumbs_view")
@@ -57,7 +47,8 @@ def get_breadcrumbs(self):
 
     def _render_component(self, component_id):
         if component_id == 'navigation':
-            items = self.get_navigation()
+            items = Navigation(self.context, self.request)(expand=True)[
+                '@components']['navigation']
         elif component_id == 'breadcrumbs':
             items = self.get_breadcrumbs()
         else:
diff --git a/src/plone/restapi/services/components/navigation.py b/src/plone/restapi/services/components/navigation.py
new file mode 100644
index 00000000..379cbb50
--- /dev/null
+++ b/src/plone/restapi/services/components/navigation.py
@@ -0,0 +1,32 @@
+# -*- coding: utf-8 -*-
+from plone.restapi.interfaces import IExpandableElement
+from zope.component import adapter
+from zope.component import getMultiAdapter
+from zope.interface import Interface
+from zope.interface import implementer
+
+
+@implementer(IExpandableElement)
+@adapter(Interface, Interface)
+class Navigation(object):
+
+    def __init__(self, context, request):
+        self.context = context
+        self.request = request
+
+    def __call__(self, expand=False):
+        if not expand:
+            return {'@components': {'navigation': {
+                '@id': '{}/@components/navigation'.format(
+                    self.context.absolute_url()),
+            }}}
+
+        tabs = getMultiAdapter((self.context, self.request),
+                               name="portal_tabs_view")
+        result = []
+        for tab in tabs.topLevelTabs():
+            result.append({
+                'title': tab.get('title', tab.get('name')),
+                'url': tab['url'] + ''
+            })
+        return {'@components': {'navigation': result}}
diff --git a/src/plone/restapi/tests/test_components.py b/src/plone/restapi/tests/test_components.py
index 97f1390e..3006146a 100644
--- a/src/plone/restapi/tests/test_components.py
+++ b/src/plone/restapi/tests/test_components.py
@@ -72,3 +72,23 @@ def test_navigation(self):
                 }],
             }]
         )
+
+    def test_collapsed_navigation_in_content_serialization(self):
+        obj = self.api_session.get('/folder').json()
+        self.assertIn('@components', obj)
+        self.assertIn('navigation', obj['@components'])
+        self.assertIn('@id', obj['@components']['navigation'])
+
+    def test_expanded_navigation_in_content_serialization(self):
+        obj = self.api_session.get('/folder?expand=navigation').json()
+        self.assertIn('@components', obj)
+        self.assertIn('navigation', obj['@components'])
+        self.assertEqual(
+            [{
+                u'title': u'Home',
+                u'url': u'http://localhost:55001/plone'
+            }, {
+                u'title': u'Some Folder',
+                u'url': u'http://localhost:55001/plone/folder'
+            }],
+            obj['@components']['navigation'])



------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.