# HG changeset patch # User Thierry Florac # Date 1543424062 -3600 # Node ID 6de2ab88b4fe8c493bdbd2af166b9b94ff764825 # Parent b8068bb58b9ed048e7cd537853dc56bbe7928044 Added content sharing support diff -r b8068bb58b9e -r 6de2ab88b4fe src/pyams_content/features/share/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_content/features/share/__init__.py Wed Nov 28 17:54:22 2018 +0100 @@ -0,0 +1,67 @@ +# +# Copyright (c) 2008-2018 Thierry Florac +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# + +__docformat__ = 'restructuredtext' + +from persistent import Persistent +from pyramid.encode import url_quote +from zope.container.contained import Contained +from zope.interface import implementer +from zope.schema.fieldproperty import FieldProperty + +from pyams_content.features.share.interfaces import ISocialShareItem +from pyams_content.interfaces import MANAGE_SITE_ROOT_PERMISSION +from pyams_content.reference.pictograms import IPictogramTable +from pyams_form.interfaces.form import IFormContextPermissionChecker +from pyams_i18n.interfaces import II18n +from pyams_utils.adapter import ContextAdapter, adapter_config +from pyams_utils.registry import query_utility +from pyams_utils.url import canonical_url +from pyams_utils.zodb import volatile_property + + +@implementer(ISocialShareItem) +class SocialShareItem(Persistent, Contained): + """Social network share item""" + + active = FieldProperty(ISocialShareItem['active']) + label = FieldProperty(ISocialShareItem['label']) + target_url = FieldProperty(ISocialShareItem['target_url']) + _pictogram_name = FieldProperty(ISocialShareItem['pictogram_name']) + + @property + def pictogram_name(self): + return self._pictogram_name + + @pictogram_name.setter + def pictogram_name(self, value): + if value != self._pictogram_name: + self._pictogram_name = value + del self.pictogram + + @volatile_property + def pictogram(self): + table = query_utility(IPictogramTable) + if table is not None: + return table.get(self._pictogram_name) + + def get_url(self, context, request): + url = II18n(self).query_attribute('target_url', request=request) + return url.format(url=url_quote(canonical_url(context, request)), + title=url_quote(II18n(context).query_attribute('title', request=request))) + + +@adapter_config(context=ISocialShareItem, provides=IFormContextPermissionChecker) +class SocialShareItemPermissionChecker(ContextAdapter): + """Social share item permission checker""" + + edit_permission = MANAGE_SITE_ROOT_PERMISSION diff -r b8068bb58b9e -r 6de2ab88b4fe src/pyams_content/features/share/container.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_content/features/share/container.py Wed Nov 28 17:54:22 2018 +0100 @@ -0,0 +1,68 @@ +# +# Copyright (c) 2008-2018 Thierry Florac +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# + +__docformat__ = 'restructuredtext' + +from zope.container.ordered import OrderedContainer +from zope.interface import implementer +from zope.location import locate +from zope.location.interfaces import ISublocations +from zope.traversing.interfaces import ITraversable + +from pyams_catalog.utils import index_object +from pyams_content.features.share import ISocialShareItem +from pyams_content.features.share.interfaces import ISocialShareManager, ISocialShareManagerTarget, \ + SOCIAL_SHARE_MANAGER_KEY +from pyams_utils.adapter import ContextAdapter, adapter_config, get_annotation_adapter + + +@implementer(ISocialShareManager) +class SocialShareManager(OrderedContainer): + """Social network share manager""" + + last_id = 1 + + def append(self, value, notify=True): + key = str(self.last_id) + if not notify: + # pre-locate item to avoid multiple notifications + locate(value, self, key) + self[key] = value + self.last_id += 1 + if not notify: + # make sure that item is correctly indexed + index_object(value) + + def get_active_items(self): + yield from filter(lambda x: ISocialShareItem(x).active, self.values()) + + +@adapter_config(context=ISocialShareManagerTarget, provides=ISocialShareManager) +def social_share_manager_factory(context): + """Social network share manager factory""" + return get_annotation_adapter(context, SOCIAL_SHARE_MANAGER_KEY, SocialShareManager, name='++social-share++') + + +@adapter_config(name='social-share', context=ISocialShareManagerTarget, provides=ITraversable) +class SocialShareManagerNamespace(ContextAdapter): + """Social network share manager ++social-share++ namespace""" + + def traverse(self, name, furtherpath=None): + return ISocialShareManager(self.context) + + +@adapter_config(name='social-share', context=ISocialShareManagerTarget, provides=ISublocations) +class SocialShareManagerSublocations(ContextAdapter): + """Social network share manager sub-locations adapter""" + + def sublocations(self): + return ISocialShareManager(self.context).values() diff -r b8068bb58b9e -r 6de2ab88b4fe src/pyams_content/features/share/interfaces.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_content/features/share/interfaces.py Wed Nov 28 17:54:22 2018 +0100 @@ -0,0 +1,73 @@ +# +# Copyright (c) 2008-2018 Thierry Florac +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# + +__docformat__ = 'restructuredtext' + +from zope.container.constraints import containers, contains +from zope.interface import Attribute, Interface +from zope.schema import Bool, Choice + +from pyams_content.interfaces.container import IOrderedContainer +from pyams_content.reference.pictograms.interfaces import SELECTED_PICTOGRAM_VOCABULARY +from pyams_i18n.schema import I18nTextLineField + +from pyams_content import _ + + +SOCIAL_SHARE_MANAGER_KEY = 'pyams_content.social_share' + + +class ISocialShareItem(Interface): + """Social network share item interface""" + + containers('.ISocialShareManager') + + active = Bool(title=_("Active item?"), + description=_("If 'no', selected item is inactive"), + required=True, + default=True) + + label = I18nTextLineField(title=_("Label"), + description=_("This label will be associated to share link"), + required=True) + + target_url = I18nTextLineField(title=_("Content share URL"), + description=_("URL used to share this content on given network; {url} string " + "will be replaced automatically by content canonical URL, " + "and {title} by content title (if required)"), + required=True) + + def get_url(self, context, request): + """Get canonical URL for given context and request""" + + pictogram_name = Choice(title=_("Pictogram"), + description=_("Name of pictogram associated with this social network"), + required=False, + vocabulary=SELECTED_PICTOGRAM_VOCABULARY) + + pictogram = Attribute("Selected pictogram object") + + +class ISocialShareManager(IOrderedContainer): + """Social network share item container interface""" + + contains(ISocialShareItem) + + def append(self, value, notify=True): + """Append given pictogram item to container""" + + def get_active_items(self): + """Get list of visible pictogram items""" + + +class ISocialShareManagerTarget(Interface): + """Content share manager target marker interface""" diff -r b8068bb58b9e -r 6de2ab88b4fe src/pyams_content/features/share/portlet/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_content/features/share/portlet/__init__.py Wed Nov 28 17:54:22 2018 +0100 @@ -0,0 +1,47 @@ +# +# Copyright (c) 2008-2018 Thierry Florac +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# + +__docformat__ = 'restructuredtext' + +from zope.interface import implementer +from zope.schema.fieldproperty import FieldProperty + +from pyams_content.features.share.portlet.interfaces import IToolboxPortletSettings +from pyams_portal.portlet import Portlet, PortletSettings, portlet_config +from pyams_utils.factory import factory_config +from pyams_utils.interfaces import VIEW_PERMISSION + +from pyams_content import _ + + +TOOLBOX_PORTLET_NAME = 'pyams_content.portlet.toolbox' + + +@implementer(IToolboxPortletSettings) +@factory_config(provided=IToolboxPortletSettings) +class ToolboxPortletSettings(PortletSettings): + """Toolbox portlet settings""" + + allow_printing = FieldProperty(IToolboxPortletSettings['allow_printing']) + allow_sharing = FieldProperty(IToolboxPortletSettings['allow_sharing']) + + +@portlet_config(permission=VIEW_PERMISSION) +class ToolboxPortet(Portlet): + """Toolbox portlet""" + + name = TOOLBOX_PORTLET_NAME + label = _("Toolbox") + + toolbar_css_class = 'fa fa-fw fa-print' + + settings_factory = IToolboxPortletSettings diff -r b8068bb58b9e -r 6de2ab88b4fe src/pyams_content/features/share/portlet/interfaces.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_content/features/share/portlet/interfaces.py Wed Nov 28 17:54:22 2018 +0100 @@ -0,0 +1,33 @@ +# +# Copyright (c) 2008-2018 Thierry Florac +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# + +__docformat__ = 'restructuredtext' + +from zope.schema import Bool + +from pyams_portal.interfaces import IPortletSettings + +from pyams_content import _ + + +class IToolboxPortletSettings(IPortletSettings): + """Toolbox portlet settings""" + + allow_printing = Bool(title=_("Allow printing?"), + description=_("If 'no', printing will be disabled"), + required=True, + default=True) + + allow_sharing = Bool(title=_("Allow sharing?"), + description=_("If 'no', sharing buttons won't be displayed"), + required=True, + default=True) diff -r b8068bb58b9e -r 6de2ab88b4fe src/pyams_content/features/share/portlet/zmi/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_content/features/share/portlet/zmi/__init__.py Wed Nov 28 17:54:22 2018 +0100 @@ -0,0 +1,47 @@ +# +# Copyright (c) 2008-2018 Thierry Florac +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# + +__docformat__ = 'restructuredtext' + +from zope.interface import Interface + +from pyams_content.features.share.portlet import IToolboxPortletSettings +from pyams_form.form import AJAXEditForm +from pyams_pagelet.interfaces import IPagelet +from pyams_pagelet.pagelet import pagelet_config +from pyams_portal.interfaces import IPortletPreviewer +from pyams_portal.portlet import PortletPreviewer +from pyams_portal.zmi.portlet import PortletSettingsEditor +from pyams_skin.layer import IPyAMSLayer +from pyams_template.template import template_config +from pyams_utils.adapter import adapter_config +from pyams_utils.interfaces import VIEW_SYSTEM_PERMISSION + + +@pagelet_config(name='properties.html', context=IToolboxPortletSettings, layer=IPyAMSLayer, + permission=VIEW_SYSTEM_PERMISSION) +class ToolboxPortletSettingsEditor(PortletSettingsEditor): + """Toolbox portlet settings editor""" + + settings = IToolboxPortletSettings + + +@adapter_config(name='properties.json', context=(IToolboxPortletSettings, IPyAMSLayer), provides=IPagelet) +class ToolboxPortletSettingsAJAXEditor(AJAXEditForm, ToolboxPortletSettingsEditor): + """Toolbox portlet settings editor, JSON renderer""" + + +@adapter_config(context=(Interface, IPyAMSLayer, Interface, IToolboxPortletSettings), + provides=IPortletPreviewer) +@template_config(template='templates/toolbox-preview.pt', layer=IPyAMSLayer) +class ToolboxPortletPreviewer(PortletPreviewer): + """Toolbox portlet previewer""" diff -r b8068bb58b9e -r 6de2ab88b4fe src/pyams_content/features/share/portlet/zmi/templates/toolbox-preview.pt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_content/features/share/portlet/zmi/templates/toolbox-preview.pt Wed Nov 28 17:54:22 2018 +0100 @@ -0,0 +1,10 @@ + +
+ + Allow printing +
+
+ + Allow sharing +
+
\ No newline at end of file diff -r b8068bb58b9e -r 6de2ab88b4fe src/pyams_content/features/share/zmi/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_content/features/share/zmi/__init__.py Wed Nov 28 17:54:22 2018 +0100 @@ -0,0 +1,97 @@ +# +# Copyright (c) 2008-2018 Thierry Florac +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# + +__docformat__ = 'restructuredtext' + +from z3c.form import field + +from pyams_content.features.share import ISocialShareItem, SocialShareItem +from pyams_content.features.share.interfaces import ISocialShareManager, ISocialShareManagerTarget +from pyams_content.features.share.zmi.container import SocialShareContainerTable, SocialShareContainerView +from pyams_content.interfaces import MANAGE_SITE_ROOT_PERMISSION +from pyams_content.reference.pictograms.zmi.widget import PictogramSelectFieldWidget +from pyams_form.form import AJAXAddForm, ajax_config +from pyams_pagelet.pagelet import pagelet_config +from pyams_skin.event import get_json_table_row_refresh_event +from pyams_skin.interfaces.viewlet import IWidgetTitleViewletManager +from pyams_skin.layer import IPyAMSLayer +from pyams_skin.viewlet.toolbar import ToolbarAction +from pyams_utils.traversing import get_parent +from pyams_utils.url import absolute_url +from pyams_viewlet.viewlet import viewlet_config +from pyams_zmi.form import AdminDialogAddForm, AdminDialogEditForm + +from pyams_content import _ + + +@viewlet_config(name='add-social-share.action', context=ISocialShareManagerTarget, layer=IPyAMSLayer, + view=SocialShareContainerView, manager=IWidgetTitleViewletManager, + permission=MANAGE_SITE_ROOT_PERMISSION, weight=1) +class SocialShareItemAddAction(ToolbarAction): + """Social network share item add action""" + + label = _("Add network share") + label_css_class = 'fa fa-fw fa-plus' + url = 'add-social-share.html' + modal_target = True + + +@pagelet_config(name='add-social-share.html', context=ISocialShareManagerTarget, layer=IPyAMSLayer, + permission=MANAGE_SITE_ROOT_PERMISSION) +@ajax_config(name='add-social-share.json', context=ISocialShareManagerTarget, layer=IPyAMSLayer, base=AJAXAddForm) +class SocialShareItemAddForm(AdminDialogAddForm): + """Social network share item add form""" + + dialog_class = 'modal-large' + legend = _("Add social network share") + icon_css_class = 'fa fa-fw fa-share-alt' + + fields = field.Fields(ISocialShareItem).omit('__parent__', '__name__', 'active') + fields['pictogram_name'].widgetFactory = PictogramSelectFieldWidget + + edit_permission = MANAGE_SITE_ROOT_PERMISSION + + def create(self, data): + return SocialShareItem() + + def add(self, object): + ISocialShareManager(self.context).append(object) + + def nextURL(self): + return absolute_url(self.context, self.request, 'social-share.html') + + +@pagelet_config(name='properties.html', context=ISocialShareItem, layer=IPyAMSLayer, + permission=MANAGE_SITE_ROOT_PERMISSION) +@ajax_config(name='properties.json', context=ISocialShareItem, layer=IPyAMSLayer) +class SocialShareItemPropertiesEditForm(AdminDialogEditForm): + """Social network share item properties edit form""" + + dialog_class = 'modal-large' + prefix = 'social_share_properties.' + + legend = _("Edit social network share properties") + icon_css_class = 'fa fa-fw fa-share-alt' + + fields = field.Fields(ISocialShareItem).omit('__parent__', '__name__', 'active') + fields['pictogram_name'].widgetFactory = PictogramSelectFieldWidget + + edit_permission = MANAGE_SITE_ROOT_PERMISSION + + def get_ajax_output(self, changes): + output = super(SocialShareItemPropertiesEditForm, self).get_ajax_output(changes) + updated = changes.get(ISocialShareItem, ()) + if updated: + target = get_parent(self.context, ISocialShareManagerTarget) + output.setdefault('events', []).append( + get_json_table_row_refresh_event(target, self.request, SocialShareContainerTable, self.context)) + return output diff -r b8068bb58b9e -r 6de2ab88b4fe src/pyams_content/features/share/zmi/container.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_content/features/share/zmi/container.py Wed Nov 28 17:54:22 2018 +0100 @@ -0,0 +1,186 @@ +# +# Copyright (c) 2008-2018 Thierry Florac +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# + +__docformat__ = 'restructuredtext' + +import json + +from pyramid.decorator import reify +from pyramid.exceptions import NotFound +from pyramid.view import view_config +from z3c.table.interfaces import IColumn, IValues + +from pyams_content.features.share.interfaces import ISocialShareManager, ISocialShareManagerTarget +from pyams_content.interfaces import MANAGE_SITE_ROOT_PERMISSION +from pyams_content.zmi import pyams_content +from pyams_pagelet.pagelet import pagelet_config +from pyams_skin.help import ContentHelp +from pyams_skin.interfaces import IContentHelp, IPageHeader +from pyams_skin.layer import IPyAMSLayer +from pyams_skin.page import DefaultPageHeaderAdapter +from pyams_skin.table import AttributeSwitcherColumn, BaseTable, I18nColumn, I18nValueColumn, SorterColumn, TrashColumn +from pyams_skin.viewlet.menu import MenuItem +from pyams_utils.adapter import ContextRequestViewAdapter, adapter_config +from pyams_utils.fanstatic import get_resource_path +from pyams_utils.url import absolute_url +from pyams_viewlet.viewlet import viewlet_config +from pyams_zmi.interfaces.menu import IPropertiesMenu +from pyams_zmi.layer import IAdminLayer +from pyams_zmi.view import ContainerAdminView + +from pyams_content import _ + + +@viewlet_config(name='social-share.menu', context=ISocialShareManagerTarget, layer=IPyAMSLayer, + manager=IPropertiesMenu, permission=MANAGE_SITE_ROOT_PERMISSION, weight=25) +class SocialShareMenu(MenuItem): + """Social network share menu""" + + label = _("Network shares...") + icon_class = 'fa-share-alt' + url = '#social-share.html' + + +class SocialShareContainerTable(BaseTable): + """Social network share items container table""" + + prefix = 'social' + + hide_header = True + sortOn = None + + cssClasses = {'table': 'table table-bordered table-striped table-hover table-tight table-dnd'} + + @property + def data_attributes(self): + attributes = super(SocialShareContainerTable, self).data_attributes + attributes.setdefault('table', {}).update({ + 'data-ams-plugins': 'pyams_content', + 'data-ams-plugin-pyams_content-src': get_resource_path(pyams_content), + 'data-ams-location': absolute_url(ISocialShareManager(self.context), self.request), + 'data-ams-tablednd-drag-handle': 'td.sorter', + 'data-ams-tablednd-drop-target': 'set-social-items-order.json', + 'data-ams-active-icon-on': 'fa fa-fw fa-check-square-o', + 'data-ams-active-icon-off': 'fa fa-fw fa-square-o txt-color-silver opacity-75' + }) + attributes.setdefault('td', {}).update({ + 'data-ams-attribute-switcher': 'switch-item-activity.json', + 'data-ams-switcher-attribute-name': 'active' + }) + return attributes + + @reify + def values(self): + return list(super(SocialShareContainerTable, self).values) + + def render(self): + if not self.values: + translate = self.request.localizer.translate + return translate(_("No currently defined social network share item.")) + return super(SocialShareContainerTable, self).render() + + +@adapter_config(context=(ISocialShareManagerTarget, IPyAMSLayer, SocialShareContainerTable), provides=IValues) +class SocialShareContainerValues(ContextRequestViewAdapter): + """Social network share items container values""" + + @property + def values(self): + return ISocialShareManager(self.context).values() + + +@adapter_config(name='sorter', context=(ISocialShareManagerTarget, IPyAMSLayer, SocialShareContainerTable), + provides=IColumn) +class SocialShareContainerSorterColumn(SorterColumn): + """Social network share items container sorter column""" + + +@view_config(name='set-social-items-order.json', context=ISocialShareManager, request_type=IPyAMSLayer, + permission=MANAGE_SITE_ROOT_PERMISSION, renderer='json', xhr=True) +def set_social_items_order(request): + """Update social network share items order""" + order = list(map(str, json.loads(request.params.get('names')))) + request.context.updateOrder(order) + return {'status': 'success'} + + +@adapter_config(name='enable-disable', context=(ISocialShareManagerTarget, IPyAMSLayer, SocialShareContainerTable), + provides=IColumn) +class SocialShareContainerEnablerColumn(AttributeSwitcherColumn): + """Social network share items container enabler switcher column""" + + switch_attribute = 'active' + + on_icon_class = 'fa fa-fw fa-check-square-o' + off_icon_class = 'fa fa-fw fa-square-o txt-color-silver opacity-75' + + icon_hint = _("Enable/disable item") + + weight = 6 + + +@view_config(name='switch-item-activity.json', context=ISocialShareManager, request_type=IPyAMSLayer, + permission=MANAGE_SITE_ROOT_PERMISSION, renderer='json', xhr=True) +def switch_social_item_activity(request): + """Switch social item activity""" + container = ISocialShareManager(request.context) + item = container.get(str(request.params.get('object_name'))) + if item is None: + raise NotFound() + item.active = not item.active + return {'on': item.active} + + +@adapter_config(name='name', context=(ISocialShareManagerTarget, IPyAMSLayer, SocialShareContainerTable), + provides=IColumn) +class SocialShareContainerNameColumn(I18nColumn, I18nValueColumn): + """Social network share items container name column""" + + _header = _("Label") + attrName = 'label' + weight = 10 + + +@adapter_config(name='trash', context=(ISocialShareManagerTarget, IPyAMSLayer, SocialShareContainerTable), + provides=IColumn) +class SocialShareContainerTrashColumn(TrashColumn): + """Social network share items container trash column""" + + permission = MANAGE_SITE_ROOT_PERMISSION + + +@pagelet_config(name='social-share.html', context=ISocialShareManagerTarget, layer=IPyAMSLayer, + permission=MANAGE_SITE_ROOT_PERMISSION) +class SocialShareContainerView(ContainerAdminView): + """Social network share items container view""" + + title = _("Social networks share") + table_class = SocialShareContainerTable + + +@adapter_config(context=(ISocialShareManagerTarget, IAdminLayer, SocialShareContainerView), provides=IPageHeader) +class SocialShareContainerViewHeaderAdapter(DefaultPageHeaderAdapter): + """Social network share items container view header adapter""" + + icon_class = 'fa fa-fw fa-share-alt' + + +@adapter_config(context=(ISocialShareManagerTarget, IAdminLayer, SocialShareContainerView), provides=IContentHelp) +class SocialShareContainerHelpAdapter(ContentHelp): + """Social network share items container help adapter""" + + header = _("Social networks share") + message = _("""Social networks share items are used to define share options available on your contents. + +**WARNING**: don't forget to include a toolbox in your presentation template to display social networks shares!! +""") + message_format = 'rest' diff -r b8068bb58b9e -r 6de2ab88b4fe src/pyams_content/root/__init__.py --- a/src/pyams_content/root/__init__.py Wed Nov 28 11:56:29 2018 +0100 +++ b/src/pyams_content/root/__init__.py Wed Nov 28 17:54:22 2018 +0100 @@ -18,7 +18,6 @@ from pyramid.events import subscriber from zope.interface import implementer -from pyams_content import _ from pyams_content.component.illustration.interfaces import IIllustrationTarget from pyams_content.component.theme.interfaces import ITagsManagerTarget from pyams_content.features.alert.interfaces import IAlertTarget @@ -26,6 +25,7 @@ from pyams_content.features.header.interfaces import IHeaderTarget from pyams_content.features.preview.interfaces import IPreviewTarget from pyams_content.features.redirect.interfaces import IRedirectionManagerTarget +from pyams_content.features.share.interfaces import ISocialShareManagerTarget from pyams_content.interfaces import MANAGE_SITE_ROOT_PERMISSION, OPERATOR_ROLE, WEBMASTER_ROLE from pyams_content.root.interfaces import ISiteRoot, ISiteRootBackOfficeConfiguration, ISiteRootConfiguration, \ ISiteRootRoles, ISiteRootToolsConfiguration @@ -44,10 +44,12 @@ from pyams_utils.site import BaseSiteRoot from pyams_utils.traversing import get_parent +from pyams_content import _ + @implementer(IDefaultProtectionPolicy, ISiteRoot, ISiteRootRoles, IPortalContext, ITagsManagerTarget, - IIllustrationTarget, IHeaderTarget, IFooterTarget, IAlertTarget, IRedirectionManagerTarget, - IPreviewTarget) + IIllustrationTarget, IHeaderTarget, IFooterTarget, ISocialShareManagerTarget, IAlertTarget, + IRedirectionManagerTarget, IPreviewTarget) class SiteRoot(ProtectedObject, BaseSiteRoot, UserSkinnableContent): """Main site root"""