plone.restapi/expansion: Add navigation and breadcrumbs as top-level services.
Timo Stollenwerk <jenkins-z4DKO/[email protected]>
| Newsgroups | gmane.comp.web.zope.plone.cvs |
|---|---|
| Message-ID | <[email protected]> |
Repository: plone.restapi Branch: refs/heads/expansion Date: 2017-07-16T12:05:47+02:00 Author: Timo Stollenwerk (tisto) <[email protected]> Commit: https://github.com/plone/plone.restapi/commit/9ddd322df0634573aa2554a53c9445726ef884e1 Add navigation and breadcrumbs as top-level services. Files changed: A src/plone/restapi/services/breadcrumbs/__init__.py A src/plone/restapi/services/breadcrumbs/configure.zcml A src/plone/restapi/services/breadcrumbs/get.py A src/plone/restapi/services/navigation/__init__.py A src/plone/restapi/services/navigation/configure.zcml A src/plone/restapi/services/navigation/get.py A src/plone/restapi/tests/test_services_breadcrumbs.py A src/plone/restapi/tests/test_services_navigation.py M CHANGES.rst M src/plone/restapi/services/configure.zcml diff --git a/CHANGES.rst b/CHANGES.rst index 9997ba8f..c3b2fd8e 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,7 +4,11 @@ Changelog 1.0a20 (unreleased) ------------------- -- Nothing changed yet. +New Features: + +- Add navigation and breadcrumbs as top-level services. Deprecate navigation + and breadcrumbs as components. + [timo] 1.0a19 (2017-06-25) diff --git a/src/plone/restapi/services/breadcrumbs/__init__.py b/src/plone/restapi/services/breadcrumbs/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/plone/restapi/services/breadcrumbs/configure.zcml b/src/plone/restapi/services/breadcrumbs/configure.zcml new file mode 100644 index 00000000..0c39c889 --- /dev/null +++ b/src/plone/restapi/services/breadcrumbs/configure.zcml @@ -0,0 +1,13 @@ +<configure + xmlns="http://namespaces.zope.org/zope" + xmlns:plone="http://namespaces.plone.org/plone"> + + <plone:service + method="GET" + for="zope.interface.Interface" + factory=".get.BreadcrumbsGet" + name="@breadcrumbs" + permission="zope2.View" + /> + +</configure> diff --git a/src/plone/restapi/services/breadcrumbs/get.py b/src/plone/restapi/services/breadcrumbs/get.py new file mode 100644 index 00000000..b8d9b97a --- /dev/null +++ b/src/plone/restapi/services/breadcrumbs/get.py @@ -0,0 +1,17 @@ +# -*- coding: utf-8 -*- +from plone.restapi.services import Service +from zope.component import getMultiAdapter + + +class BreadcrumbsGet(Service): + + def reply(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 diff --git a/src/plone/restapi/services/configure.zcml b/src/plone/restapi/services/configure.zcml index ac5d8a69..a36166fe 100644 --- a/src/plone/restapi/services/configure.zcml +++ b/src/plone/restapi/services/configure.zcml @@ -2,12 +2,14 @@ xmlns="http://namespaces.zope.org/zope"> <include package=".auth" /> + <include package=".breadcrumbs"/> <include package=".components"/> <include package=".content"/> <include package=".copymove"/> <include package=".discussion"/> <include package=".groups"/> <include package=".history"/> + <include package=".navigation"/> <include package=".principals"/> <include package=".registry"/> <include package=".roles"/> diff --git a/src/plone/restapi/services/navigation/__init__.py b/src/plone/restapi/services/navigation/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/plone/restapi/services/navigation/configure.zcml b/src/plone/restapi/services/navigation/configure.zcml new file mode 100644 index 00000000..05e200e4 --- /dev/null +++ b/src/plone/restapi/services/navigation/configure.zcml @@ -0,0 +1,13 @@ +<configure + xmlns="http://namespaces.zope.org/zope" + xmlns:plone="http://namespaces.plone.org/plone"> + + <plone:service + method="GET" + for="zope.interface.Interface" + factory=".get.NavigationGet" + name="@navigation" + permission="zope2.View" + /> + +</configure> diff --git a/src/plone/restapi/services/navigation/get.py b/src/plone/restapi/services/navigation/get.py new file mode 100644 index 00000000..a2bf0504 --- /dev/null +++ b/src/plone/restapi/services/navigation/get.py @@ -0,0 +1,17 @@ +# -*- coding: utf-8 -*- +from plone.restapi.services import Service +from zope.component import getMultiAdapter + + +class NavigationGet(Service): + + def reply(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 diff --git a/src/plone/restapi/tests/test_services_breadcrumbs.py b/src/plone/restapi/tests/test_services_breadcrumbs.py new file mode 100644 index 00000000..59dfc008 --- /dev/null +++ b/src/plone/restapi/tests/test_services_breadcrumbs.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +from plone.app.testing import setRoles +from plone.app.testing import SITE_OWNER_NAME +from plone.app.testing import SITE_OWNER_PASSWORD +from plone.app.testing import TEST_USER_ID +from plone.dexterity.utils import createContentInContainer +from plone.restapi.testing import PLONE_RESTAPI_DX_FUNCTIONAL_TESTING +from plone.restapi.testing import RelativeSession + +import transaction +import unittest + + +class TestServicesBreadcrumbs(unittest.TestCase): + + layer = PLONE_RESTAPI_DX_FUNCTIONAL_TESTING + + def setUp(self): + self.app = self.layer['app'] + self.portal = self.layer['portal'] + self.portal_url = self.portal.absolute_url() + setRoles(self.portal, TEST_USER_ID, ['Manager']) + + self.api_session = RelativeSession(self.portal_url) + self.api_session.headers.update({'Accept': 'application/json'}) + self.api_session.auth = (SITE_OWNER_NAME, SITE_OWNER_PASSWORD) + + self.folder = createContentInContainer( + self.portal, u'Folder', + id=u'folder', + title=u'Some Folder') + createContentInContainer( + self.folder, u'Document', + id=u'doc1', + title=u'A document') + transaction.commit() + + def test_breadcrumbs(self): + response = self.api_session.get('/folder/doc1/@breadcrumbs') + + self.assertEqual(response.status_code, 200) + self.assertEqual( + response.json(), + [{ + 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' + }] + ) diff --git a/src/plone/restapi/tests/test_services_navigation.py b/src/plone/restapi/tests/test_services_navigation.py new file mode 100644 index 00000000..ad55a612 --- /dev/null +++ b/src/plone/restapi/tests/test_services_navigation.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +from plone.app.testing import setRoles +from plone.app.testing import SITE_OWNER_NAME +from plone.app.testing import SITE_OWNER_PASSWORD +from plone.app.testing import TEST_USER_ID +from plone.dexterity.utils import createContentInContainer +from plone.restapi.testing import PLONE_RESTAPI_DX_FUNCTIONAL_TESTING +from plone.restapi.testing import RelativeSession + +import transaction +import unittest + + +class TestServicesNavigation(unittest.TestCase): + + layer = PLONE_RESTAPI_DX_FUNCTIONAL_TESTING + + def setUp(self): + self.app = self.layer['app'] + self.portal = self.layer['portal'] + self.portal_url = self.portal.absolute_url() + setRoles(self.portal, TEST_USER_ID, ['Manager']) + + self.api_session = RelativeSession(self.portal_url) + self.api_session.headers.update({'Accept': 'application/json'}) + self.api_session.auth = (SITE_OWNER_NAME, SITE_OWNER_PASSWORD) + + self.folder = createContentInContainer( + self.portal, u'Folder', + id=u'folder', + title=u'Some Folder') + createContentInContainer( + self.folder, u'Document', + id=u'doc1', + title=u'A document') + transaction.commit() + + def test_navigation(self): + response = self.api_session.get('/folder/@navigation') + + self.assertEqual(response.status_code, 200) + self.assertEqual( + response.json(), + [ + { + u'title': u'Home', + u'url': u'http://localhost:55001/plone' + }, + { + u'title': u'Some Folder', + u'url': u'http://localhost:55001/plone/folder' + } + ] + ) ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot