plone.restapi/plone-only-login: Make breadcrumbs component expandable
Thomas Buchberger <jenkins-z4DKO/[email protected]> Wed, 26 Jul 2017 07:45:36 -0700 (PDT)
| Newsgroups | gmane.comp.web.zope.plone.cvs |
|---|---|
| Message-ID | <[email protected]> |
Repository: plone.restapi Branch: refs/heads/plone-only-login Date: 2017-07-25T11:48:31+02:00 Author: Thomas Buchberger (buchi) <t.buchberger-/8aE7x569Db/[email protected]> Commit: https://github.com/plone/plone.restapi/commit/526b397c9c2562072e55a056d01d16f24d1b7568 Make breadcrumbs component expandable Files changed: A src/plone/restapi/services/components/breadcrumbs.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/serializer/expansion.py 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 ac162329..7640e732 100644 --- a/docs/source/_json/collection.resp +++ b/docs/source/_json/collection.resp @@ -3,6 +3,9 @@ Content-Type: application/json { "@components": { + "breadcrumbs": { + "@id": "http://localhost:55001/plone/collection/@components/breadcrumbs" + }, "navigation": { "@id": "http://localhost:55001/plone/collection/@components/navigation" } diff --git a/docs/source/_json/content_get.resp b/docs/source/_json/content_get.resp index ad1e0345..2a7b48ee 100644 --- a/docs/source/_json/content_get.resp +++ b/docs/source/_json/content_get.resp @@ -3,6 +3,9 @@ Content-Type: application/json { "@components": { + "breadcrumbs": { + "@id": "http://localhost:55001/plone/folder/my-document/@components/breadcrumbs" + }, "navigation": { "@id": "http://localhost:55001/plone/folder/my-document/@components/navigation" } diff --git a/docs/source/_json/content_post.resp b/docs/source/_json/content_post.resp index 4cde4d25..36da1d20 100644 --- a/docs/source/_json/content_post.resp +++ b/docs/source/_json/content_post.resp @@ -4,6 +4,9 @@ Location: http://localhost:55001/plone/folder/my-document { "@components": { + "breadcrumbs": { + "@id": "http://localhost:55001/plone/folder/my-document/@components/breadcrumbs" + }, "navigation": { "@id": "http://localhost:55001/plone/folder/my-document/@components/navigation" } diff --git a/docs/source/_json/document.resp b/docs/source/_json/document.resp index 87a16856..e3aadc15 100644 --- a/docs/source/_json/document.resp +++ b/docs/source/_json/document.resp @@ -3,6 +3,9 @@ Content-Type: application/json { "@components": { + "breadcrumbs": { + "@id": "http://localhost:55001/plone/front-page/@components/breadcrumbs" + }, "navigation": { "@id": "http://localhost:55001/plone/front-page/@components/navigation" } diff --git a/docs/source/_json/event.resp b/docs/source/_json/event.resp index d749122d..974db379 100644 --- a/docs/source/_json/event.resp +++ b/docs/source/_json/event.resp @@ -3,6 +3,9 @@ Content-Type: application/json { "@components": { + "breadcrumbs": { + "@id": "http://localhost:55001/plone/event/@components/breadcrumbs" + }, "navigation": { "@id": "http://localhost:55001/plone/event/@components/navigation" } diff --git a/docs/source/_json/file.resp b/docs/source/_json/file.resp index ed46fc3c..515cfeb8 100644 --- a/docs/source/_json/file.resp +++ b/docs/source/_json/file.resp @@ -3,6 +3,9 @@ Content-Type: application/json { "@components": { + "breadcrumbs": { + "@id": "http://localhost:55001/plone/file/@components/breadcrumbs" + }, "navigation": { "@id": "http://localhost:55001/plone/file/@components/navigation" } diff --git a/docs/source/_json/folder.resp b/docs/source/_json/folder.resp index 19685167..4a12e3eb 100644 --- a/docs/source/_json/folder.resp +++ b/docs/source/_json/folder.resp @@ -3,6 +3,9 @@ Content-Type: application/json { "@components": { + "breadcrumbs": { + "@id": "http://localhost:55001/plone/folder/@components/breadcrumbs" + }, "navigation": { "@id": "http://localhost:55001/plone/folder/@components/navigation" } diff --git a/docs/source/_json/image.resp b/docs/source/_json/image.resp index 4d2b0751..df1bd765 100644 --- a/docs/source/_json/image.resp +++ b/docs/source/_json/image.resp @@ -3,6 +3,9 @@ Content-Type: application/json { "@components": { + "breadcrumbs": { + "@id": "http://localhost:55001/plone/image/@components/breadcrumbs" + }, "navigation": { "@id": "http://localhost:55001/plone/image/@components/navigation" } diff --git a/docs/source/_json/jwt_logged_in.resp b/docs/source/_json/jwt_logged_in.resp index 331ee0c9..d9a441ca 100644 --- a/docs/source/_json/jwt_logged_in.resp +++ b/docs/source/_json/jwt_logged_in.resp @@ -3,6 +3,9 @@ Content-Type: application/json { "@components": { + "breadcrumbs": { + "@id": "http://localhost:55001/plone/@components/breadcrumbs" + }, "navigation": { "@id": "http://localhost:55001/plone/@components/navigation" } diff --git a/docs/source/_json/link.resp b/docs/source/_json/link.resp index 05360f3e..6eba0e69 100644 --- a/docs/source/_json/link.resp +++ b/docs/source/_json/link.resp @@ -3,6 +3,9 @@ Content-Type: application/json { "@components": { + "breadcrumbs": { + "@id": "http://localhost:55001/plone/link/@components/breadcrumbs" + }, "navigation": { "@id": "http://localhost:55001/plone/link/@components/navigation" } diff --git a/docs/source/_json/newsitem.resp b/docs/source/_json/newsitem.resp index b0013e66..ae9f6d09 100644 --- a/docs/source/_json/newsitem.resp +++ b/docs/source/_json/newsitem.resp @@ -3,6 +3,9 @@ Content-Type: application/json { "@components": { + "breadcrumbs": { + "@id": "http://localhost:55001/plone/newsitem/@components/breadcrumbs" + }, "navigation": { "@id": "http://localhost:55001/plone/newsitem/@components/navigation" } diff --git a/docs/source/_json/siteroot.resp b/docs/source/_json/siteroot.resp index 46705593..30894897 100644 --- a/docs/source/_json/siteroot.resp +++ b/docs/source/_json/siteroot.resp @@ -3,6 +3,9 @@ Content-Type: application/json { "@components": { + "breadcrumbs": { + "@id": "http://localhost:55001/plone/@components/breadcrumbs" + }, "navigation": { "@id": "http://localhost:55001/plone/@components/navigation" } diff --git a/src/plone/restapi/serializer/expansion.py b/src/plone/restapi/serializer/expansion.py index 6253f69c..825d34ba 100644 --- a/src/plone/restapi/serializer/expansion.py +++ b/src/plone/restapi/serializer/expansion.py @@ -11,7 +11,17 @@ def expandable_elements(context, request): res = {} for element in elements: if element[0] in expands: - res.update(element[1](expand=True)) + update_dict_recursively(res, element[1](expand=True)) else: - res.update(element[1](expand=False)) + update_dict_recursively(res, element[1](expand=False)) return res + + +def update_dict_recursively(d, u): + for key, value in u.iteritems(): + if isinstance(value, dict): + r = update_dict_recursively(d.get(key, {}), value) + d[key] = r + else: + d[key] = u[key] + return d diff --git a/src/plone/restapi/services/components/breadcrumbs.py b/src/plone/restapi/services/components/breadcrumbs.py new file mode 100644 index 00000000..24287963 --- /dev/null +++ b/src/plone/restapi/services/components/breadcrumbs.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 Breadcrumbs(object): + + def __init__(self, context, request): + self.context = context + self.request = request + + def __call__(self, expand=False): + if not expand: + return {'@components': {'breadcrumbs': { + '@id': '{}/@components/breadcrumbs'.format( + self.context.absolute_url()), + }}} + + breadcrumbs_view = getMultiAdapter((self.context, self.request), + name="breadcrumbs_view") + result = [] + for crumb in breadcrumbs_view.breadcrumbs(): + result.append({ + 'title': crumb['Title'], + 'url': crumb['absolute_url'] + }) + return {'@components': {'breadcrumbs': result}} diff --git a/src/plone/restapi/services/components/configure.zcml b/src/plone/restapi/services/components/configure.zcml index fa6faebd..da8a360e 100644 --- a/src/plone/restapi/services/components/configure.zcml +++ b/src/plone/restapi/services/components/configure.zcml @@ -11,5 +11,6 @@ /> <adapter factory=".navigation.Navigation" name="navigation"/> + <adapter factory=".breadcrumbs.Breadcrumbs" name="breadcrumbs"/> </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 f580e3a1..5947d0c3 100644 --- a/src/plone/restapi/services/components/get.py +++ b/src/plone/restapi/services/components/get.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- from plone.restapi.services import Service +from plone.restapi.services.components.breadcrumbs import Breadcrumbs from plone.restapi.services.components.navigation import Navigation from zope.deprecation import deprecate -from zope.component import getMultiAdapter from zope.interface import implements from zope.publisher.interfaces import IPublishTraverse @@ -34,23 +34,13 @@ def _wrap_component_items(self, items, component_id): } return component - def get_breadcrumbs(self): - breadcrumbs_view = getMultiAdapter((self.context, self.request), - name="breadcrumbs_view") - result = [] - for crumb in breadcrumbs_view.breadcrumbs(): - result.append({ - 'title': crumb['Title'], - 'url': crumb['absolute_url'] - }) - return result - def _render_component(self, component_id): if component_id == 'navigation': items = Navigation(self.context, self.request)(expand=True)[ '@components']['navigation'] elif component_id == 'breadcrumbs': - items = self.get_breadcrumbs() + items = Breadcrumbs(self.context, self.request)(expand=True)[ + '@components']['breadcrumbs'] else: raise NotImplementedError( 'This endpoint does not currently support the ' diff --git a/src/plone/restapi/tests/test_components.py b/src/plone/restapi/tests/test_components.py index 3006146a..1c7e232b 100644 --- a/src/plone/restapi/tests/test_components.py +++ b/src/plone/restapi/tests/test_components.py @@ -54,6 +54,26 @@ def test_breadcrumb(self): }] ) + def test_collapsed_breadcrumbs_in_content_serialization(self): + obj = self.api_session.get('/folder').json() + self.assertIn('@components', obj) + self.assertIn('breadcrumbs', obj['@components']) + self.assertIn('@id', obj['@components']['breadcrumbs']) + + def test_expanded_breadcrumbs_in_content_serialization(self): + obj = self.api_session.get('/folder/doc1?expand=breadcrumbs').json() + self.assertIn('@components', obj) + self.assertIn('breadcrumbs', obj['@components']) + self.assertEqual( + [{ + u'url': u'http://localhost:55001/plone/folder', + u'title': u'Some Folder' + }, { + u'url': u'http://localhost:55001/plone/folder/doc1', + u'title': u'A document' + }], + obj['@components']['breadcrumbs']) + def test_navigation(self): response = self.api_session.get('/folder/@components/navigation') ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot