Skip to content

Commit

Permalink
Merge pull request #122 from plone/toolbar-showhide
Browse files Browse the repository at this point in the history
Toolbar showhide
  • Loading branch information
agitator authored May 11, 2017
2 parents f6ddd27 + fbd8628 commit 51d9386
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 60 deletions.
11 changes: 10 additions & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Changelog
=========

2.6.6 (unreleased)
2.7.0 (unreleased)
------------------

Breaking changes:
Expand All @@ -13,12 +13,21 @@ New features:
- Do not render social metadata if you are a logged user.
[bsuttor]

- Add method ``is_toolbar_visible`` to context state.
It uses a whitelist and defaults to authenticated users.
Use new method it in toolbar viewlet manager and layout body classes.
[jensens]

Bug fixes:

- Deprecating getIcon() in @@plone_layout
see https://github.com/plone/Products.CMFPlone/issues/1734
[fgrcon]

- Factor toolbar classes out to own method.
Includes minor cleanup.
[jensens]


2.6.5 (2017-03-29)
------------------
Expand Down
10 changes: 9 additions & 1 deletion plone/app/layout/globals/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

BLACKLISTED_PROVIDERS = ('portal_workflow', )
BLACKLISTED_CATEGORIES = ('folder_buttons', 'object_buttons', )
WHITELISTED_TOOLBAR_ROLES = set(('Authenticated', ))


@implementer(IContextState)
Expand Down Expand Up @@ -201,7 +202,7 @@ def is_portal_root(self):

@memoize
def is_editable(self):
tool = getToolByName(self.context, "portal_membership")
tool = getToolByName(self.context, 'portal_membership')
return bool(tool.checkPermission(
'Modify portal content',
aq_inner(self.context)
Expand All @@ -221,6 +222,13 @@ def is_locked(self):
context.aq_explicit, 'wl_isLocked', None) is not None
return lockable and context.wl_isLocked()

@memoize
def is_toolbar_visible(self):
portal_membership = getToolByName(self.context, 'portal_membership')
user = portal_membership.getAuthenticatedMember()
roles = set(user.getRolesInContext(self.context))
return bool(roles & WHITELISTED_TOOLBAR_ROLES)

@memoize
def actions(self, category=None, max=-1):
context = aq_inner(self.context)
Expand Down
8 changes: 7 additions & 1 deletion plone/app/layout/globals/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ def icons_visible():

def getIcon(item):
"""
deprecated for Plone > 5.0 see https://github.com/plone/Products.CMFPlone/issues/1151
deprecated for Plone > 5.0 see
https://github.com/plone/Products.CMFPlone/issues/1151
Returns an object which implements the IContentIcon interface and
provides the informations necessary to render an icon. The item
parameter needs to be adaptable to IContentIcon. Icons can be disabled
Expand Down Expand Up @@ -260,6 +261,10 @@ def is_locked():
"""Whether or not the current object is locked
"""

def is_toolbar_visible():
"""Wether toolbar is visible or not in the actual context
"""

def actions(category):
"""The filtered actions in the context. You can restrict the actions
to just one category.
Expand All @@ -283,6 +288,7 @@ class IPatternsSettingsRenderer(Interface):
DEPRECATED
"""


IPatternsSettingsRenderer = deprecated(
IPatternsSettingsRenderer,
'This interface was deprecated because it was pointless.'
Expand Down
133 changes: 80 additions & 53 deletions plone/app/layout/globals/layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,35 @@
import json


TEMPLATE_CLASSES = (
ViewPageTemplateFile,
ZopeViewPageTemplateFile,
ViewMixinForTemplates
)


@implementer(ILayoutPolicy)
class LayoutPolicy(BrowserView):
"""A view that gives access to various layout related functions.
"""
@property
@memoize
def _context_state(self):
return getMultiAdapter(
(self.context, self.request),
name='plone_context_state'
)

def mark_view(self, view):
"""Adds a marker interface to the view if it is "the" view for the
context May only be called from a template.
"""
if not view:
return

context_state = getMultiAdapter(
(self.context, self.request), name=u'plone_context_state')

if context_state.is_view_template() and not IViewView.providedBy(view):
if (
self._context_state.is_view_template() and
not IViewView.providedBy(view)
):
alsoProvides(view, IViewView)

def hide_columns(self, column_left, column_right):
Expand Down Expand Up @@ -116,9 +129,12 @@ def thumb_visible(self):
return True
else:
return False
@deprecate('deprecated since Plone 4, ContentIcons are rendered \
as Fonts now see \
https://docs.plone.org/develop/addons/index.html#upgrading-to-plone-5-1.')

@deprecate(
'deprecated since Plone 4, ContentIcons are rendered as Fonts now see'
'https://docs.plone.org/develop/addons/index.html'
'#upgrading-to-plone-5-1.'
)
def getIcon(self, item):
"""Returns an object which implements the IContentIcon interface and
provides the informations necessary to render an icon. The item
Expand All @@ -133,6 +149,47 @@ def getIcon(self, item):
icon = getMultiAdapter((context, self.request, item), IContentIcon)
return icon

def _toolbar_classes(self):
"""current toolbar controlling classes
"""
if not self._context_state.is_toolbar_visible():
return []

toolbar_classes = []
registry = getUtility(IRegistry)
site_settings = registry.forInterface(
ISiteSchema,
prefix='plone',
check=False
)
try:
left = site_settings.toolbar_position == 'side'
except KeyError:
left = True
if left:
toolbar_classes.append('plone-toolbar-left')
else:
toolbar_classes.append('plone-toolbar-top')
try:
toolbar_state = {}
toolbar_state_cookie = self.request.cookies.get('plone-toolbar')
if toolbar_state_cookie:
toolbar_state = json.loads(toolbar_state_cookie)
if toolbar_state.get('expanded', True):
toolbar_classes.append('plone-toolbar-expanded')
if left:
toolbar_classes.append('plone-toolbar-left-expanded')
else:
toolbar_classes.append('plone-toolbar-top-expanded')
else:
if left:
toolbar_classes.append('plone-toolbar-left-default')
else:
toolbar_classes.append('plone-toolbar-top-default')
except Exception:
pass
return toolbar_classes

def bodyClass(self, template, view):
"""
Returns the CSS class to be used on the body tag.
Expand Down Expand Up @@ -160,21 +217,18 @@ def bodyClass(self, template, view):
- plone-toolbar-top-default: top toolbar is not expanded
- pat-markspeciallinks: mark special links is set
"""
context = self.context
portal_state = getMultiAdapter(
(context, self.request),
(self.context, self.request),
name=u'plone_portal_state'
)
normalizer = queryUtility(IIDNormalizer)
registry = getUtility(IRegistry)

body_classes = []
body_classes = self._toolbar_classes()

# template class (required)
template_name = ''
if isinstance(template, ViewPageTemplateFile) or \
isinstance(template, ZopeViewPageTemplateFile) or \
isinstance(template, ViewMixinForTemplates):
if isinstance(template, TEMPLATE_CLASSES):
# Browser view
template_name = view.__name__
elif template is not None:
Expand All @@ -187,22 +241,24 @@ def bodyClass(self, template, view):
body_classes.append('template-%s' % template_name)

# portal type class (optional)
portal_type = normalizer.normalize(context.portal_type)
portal_type = normalizer.normalize(self.context.portal_type)
if portal_type:
body_classes.append("portaltype-%s" % portal_type)

# section class (optional)
navroot = portal_state.navigation_root()
body_classes.append("site-%s" % navroot.getId())

contentPath = context.getPhysicalPath()[
contentPath = self.context.getPhysicalPath()[
len(navroot.getPhysicalPath()):]
if contentPath:
body_classes.append("section-%s" % contentPath[0])
# skip first section since we already have that...
if len(contentPath) > 1:
depth = registry.get(
'plone.app.layout.globals.bodyClass.depth', 4)
'plone.app.layout.globals.bodyClass.depth',
4
)
if depth > 1:
classes = ['subsection-%s' % contentPath[1]]
for section in contentPath[2:depth]:
Expand Down Expand Up @@ -234,54 +290,25 @@ def bodyClass(self, template, view):
body_classes.append('viewpermission-' + permission)

# class for user roles
membership = getToolByName(context, "portal_membership")
membership = getToolByName(self.context, "portal_membership")
if membership.isAnonymousUser():
body_classes.append('userrole-anonymous')
else:
user = membership.getAuthenticatedMember()
for role in user.getRolesInContext(self.context):
body_classes.append(
'userrole-' + role.lower().replace(' ', '-'))

# toolbar classes
site_settings = registry.forInterface(
ISiteSchema, prefix='plone', check=False
)
try:
left = site_settings.toolbar_position == 'side'
except KeyError:
left = True
if left:
body_classes.append('plone-toolbar-left')
else:
body_classes.append('plone-toolbar-top')
try:
toolbar_state = self.request.cookies.get('plone-toolbar')
if toolbar_state:
toolbar_state = json.loads(toolbar_state)
else:
toolbar_state = {'expanded': True}
if toolbar_state.get('expanded', True):
body_classes.append('plone-toolbar-expanded')
if left:
body_classes.append('plone-toolbar-left-expanded')
else:
body_classes.append('plone-toolbar-top-expanded')
else:
if left:
body_classes.append('plone-toolbar-left-default')
else:
body_classes.append('plone-toolbar-top-default')
except:
pass
'userrole-' + role.lower().replace(' ', '-')
)

# class for markspeciallinks pattern
link_settings = registry.forInterface(
ILinkSchema, prefix="plone", check=False
ILinkSchema,
prefix="plone",
check=False
)
msl = link_settings.mark_special_links
elonw = link_settings.external_links_open_new_window
if msl or elonw:
body_classes.append('pat-markspeciallinks')

return ' '.join(body_classes)
return ' '.join(sorted(body_classes))
4 changes: 2 additions & 2 deletions plone/app/layout/viewlets/toolbar.pt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<section id="edit-bar" role="toolbar"
tal:define="portal_state view/portal_state;
tal:define="context_state view/context_state;
personal_bar python: view.get_personal_bar()"
tal:condition="not: portal_state/anonymous"
tal:condition="context_state/is_toolbar_visible"
i18n:domain="plone">
<div id="edit-zone" role="toolbar" class="pat-toolbar">
<div class="plone-toolbar-container">
Expand Down
13 changes: 12 additions & 1 deletion plone/app/layout/viewlets/toolbar.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ def base_render(self):
def render(self):
return self.custom_template()

@property
@memoize
def context_state(self):
return getMultiAdapter(
(self.context, self.request),
name='plone_context_state'
)

@property
@memoize
def portal_state(self):
Expand All @@ -28,7 +36,10 @@ def portal_state(self):

def get_personal_bar(self):
viewlet = PersonalBarViewlet(
self.context, self.request, self.__parent__, self)
self.context,
self.request,
self.__parent__, self
)
viewlet.update()
return viewlet

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from setuptools import setup, find_packages

version = '2.6.6.dev0'
version = '2.7.0.dev0'

long_description = \
open("README.rst").read() + "\n" + open("CHANGES.rst").read()
Expand Down

0 comments on commit 51d9386

Please sign in to comment.