# HG changeset patch # User Thierry Florac # Date 1545988833 -3600 # Node ID 8e8f528f8d3b3b66be6294a2211458249ed51a92 # Parent 9870e7467087399ab61cbc580ce4a6805d91ad61 Added resource shared content diff -r 9870e7467087 -r 8e8f528f8d3b src/pyams_content/generations/__init__.py --- a/src/pyams_content/generations/__init__.py Fri Dec 28 10:19:45 2018 +0100 +++ b/src/pyams_content/generations/__init__.py Fri Dec 28 10:20:33 2018 +0100 @@ -37,6 +37,7 @@ from pyams_content.shared.imagemap.interfaces import IImageMapManagerFactory from pyams_content.shared.logo.interfaces import ILogosManagerFactory from pyams_content.shared.news.interfaces import INewsManagerFactory +from pyams_content.shared.resource.interfaces import IResourceManagerFactory from pyams_content.shared.topic.interfaces import ITopicManagerFactory from pyams_content.shared.view.interfaces import IViewsManagerFactory from pyams_i18n.index import I18nTextIndexWithInterface @@ -96,7 +97,8 @@ ('imagemaps', IImageMapManagerFactory), ('forms', IFormsManagerFactory), ('news', INewsManagerFactory), - ('topics', ITopicManagerFactory) + ('topics', ITopicManagerFactory), + ('resources', IResourceManagerFactory) ] REQUIRED_INDEXES = [ diff -r 9870e7467087 -r 8e8f528f8d3b src/pyams_content/shared/resource/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_content/shared/resource/__init__.py Fri Dec 28 10:20:33 2018 +0100 @@ -0,0 +1,88 @@ +# +# 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 zope.container.contained import Contained +from zope.interface import implementer, provider +from zope.schema.fieldproperty import FieldProperty + +from pyams_content.component.illustration.interfaces import IIllustrationTarget, ILinkIllustrationTarget +from pyams_content.component.paragraph.interfaces import IParagraphContainerTarget +from pyams_content.component.theme.interfaces import ICollectionsTarget, ITagsTarget, IThemesTarget +from pyams_content.features.preview.interfaces import IPreviewTarget +from pyams_content.features.review.interfaces import IReviewTarget +from pyams_content.shared.common import SharedContent, register_content_type +from pyams_content.shared.common.interfaces import IWfSharedContentFactory +from pyams_content.shared.common.types import WfTypedSharedContent +from pyams_content.shared.resource.interfaces import IWfResource, RESOURCE_CONTENT_TYPE, RESOURCE_CONTENT_NAME, IResourceInfo, \ + RESOURCE_INFO_ANNOTATIONS_KEY, IWfResourceFactory, IResource +from pyams_utils.adapter import adapter_config, get_annotation_adapter + + +@implementer(IWfResource, IIllustrationTarget, ILinkIllustrationTarget, IParagraphContainerTarget, + ITagsTarget, ICollectionsTarget, IThemesTarget, IPreviewTarget, IReviewTarget) +class WfResource(WfTypedSharedContent): + """Resource class""" + + content_type = RESOURCE_CONTENT_TYPE + content_name = RESOURCE_CONTENT_NAME + + +register_content_type(WfResource) + + +@implementer(IResourceInfo) +class ResourceInfo(Persistent, Contained): + """Resource persistent informations""" + + original_country = FieldProperty(IResourceInfo['original_country']) + author = FieldProperty(IResourceInfo['author']) + drawer = FieldProperty(IResourceInfo['drawer']) + colourist = FieldProperty(IResourceInfo['colourist']) + lettering = FieldProperty(IResourceInfo['lettering']) + producer = FieldProperty(IResourceInfo['producer']) + director = FieldProperty(IResourceInfo['director']) + actors = FieldProperty(IResourceInfo['actors']) + editor = FieldProperty(IResourceInfo['editor']) + collection = FieldProperty(IResourceInfo['collection']) + series = FieldProperty(IResourceInfo['series']) + volume = FieldProperty(IResourceInfo['volume']) + format = FieldProperty(IResourceInfo['format']) + release_year = FieldProperty(IResourceInfo['release_year']) + awards = FieldProperty(IResourceInfo['awards']) + nb_pages = FieldProperty(IResourceInfo['nb_pages']) + editor_reference = FieldProperty(IResourceInfo['editor_reference']) + isbn_number = FieldProperty(IResourceInfo['isbn_number']) + source_url = FieldProperty(IResourceInfo['source_url']) + price = FieldProperty(IResourceInfo['price']) + summary = FieldProperty(IResourceInfo['summary']) + synopsis = FieldProperty(IResourceInfo['synopsis']) + publisher_words = FieldProperty(IResourceInfo['publisher_words']) + + +@adapter_config(context=IWfResource, provides=IResourceInfo) +def resource_info_factory(context): + """Resource info factory""" + return get_annotation_adapter(context, RESOURCE_INFO_ANNOTATIONS_KEY, ResourceInfo, name='++info++') + + +@provider(IWfResourceFactory) +@implementer(IResource) +class Resource(SharedContent): + """Workflow managed resource""" + + +@adapter_config(context=IWfResourceFactory, provides=IWfSharedContentFactory) +def resource_content_factory(context): + return WfResource diff -r 9870e7467087 -r 8e8f528f8d3b src/pyams_content/shared/resource/interfaces.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_content/shared/resource/interfaces.py Fri Dec 28 10:20:33 2018 +0100 @@ -0,0 +1,129 @@ +# +# 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 datetime import datetime + +from zope.interface import Interface +from zope.schema import Choice, Float, Int, TextLine, URI + +from pyams_content.shared.common import ISharedContent +from pyams_content.shared.common.interfaces.types import ITypedSharedToolPortalContext, \ + IWfTypedSharedContentPortalContext +from pyams_i18n.schema import I18nHTMLField, I18nTextField + +from pyams_content import _ + + +RESOURCE_CONTENT_TYPE = 'resource' +RESOURCE_CONTENT_NAME = _("Resource") + + +class IResourceManager(ITypedSharedToolPortalContext): + """Resource manager interface""" + + +class IResourceManagerFactory(Interface): + """Resource manager factory interface""" + + +class IWfResource(IWfTypedSharedContentPortalContext): + """Resource content interface""" + + +class IWfResourceFactory(Interface): + """Resource content factory interface""" + + +class IResource(ISharedContent): + """Workflow managed resource interface""" + + +RESOURCE_INFO_ANNOTATIONS_KEY = 'pyams_content.resource' + + +class IResourceInfo(Interface): + """Resource info interface""" + + original_country = TextLine(title=_("Original country"), + required=False) + + author = TextLine(title=_("Author"), + required=False) + + drawer = TextLine(title=_("Drawer"), + required=False) + + colourist = TextLine(title=_("Colourist"), + required=False) + + lettering = TextLine(title=_("Lettering"), + required=False) + + producer = TextLine(title=_("Producer"), + required=False) + + director = TextLine(title=_("Director"), + required=False) + + actors = TextLine(title=_("Actors"), + required=False) + + editor = TextLine(title=_("Editor"), + required=False) + + collection = TextLine(title=_("Collection"), + required=False) + + series = TextLine(title=_("Series"), + required=False) + + volume = TextLine(title=_("Volume"), + required=False) + + format = TextLine(title=_("Format"), + required=False) + + release_year = Choice(title=_("Release year"), + values=range(datetime.today().year, 1970, -1), + required=False) + + awards = I18nTextField(title=_("Awards"), + required=False) + + nb_pages = Int(title=_("Nb pages"), + min=0, + required=False) + + editor_reference = TextLine(title=_("Editor reference"), + required=False) + + isbn_number = TextLine(title=_("ISBN number"), + required=False) + + source_url = URI(title=_("Source URI"), + description=_("External URL used to get more information about resource"), + required=False) + + price = Float(title=_("Price"), + min=0.0, + required=False) + + summary = I18nHTMLField(title=_("Summary"), + required=False) + + synopsis = I18nHTMLField(title=_("Synopsis"), + required=False) + + publisher_words = I18nHTMLField(title=_("Publisher's words"), + required=False) diff -r 9870e7467087 -r 8e8f528f8d3b src/pyams_content/shared/resource/manager.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_content/shared/resource/manager.py Fri Dec 28 10:20:33 2018 +0100 @@ -0,0 +1,72 @@ +# +# 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 pyramid.events import subscriber +from zope.component.interfaces import ISite +from zope.interface import implementer +from zope.lifecycleevent import IObjectAddedEvent +from zope.schema.fieldproperty import FieldProperty + +from pyams_content.component.paragraph import IParagraphFactorySettings +from pyams_content.component.theme import ICollectionsManagerTarget, IThemesManagerTarget +from pyams_content.reference.pictograms.interfaces import IPictogramManagerTarget +from pyams_content.shared.common.interfaces import IManagerRestrictionsFactory, ISharedContentFactory +from pyams_content.shared.common.security import SharedToolManagerRestrictionInfo +from pyams_content.shared.common.types import TypedSharedTool +from pyams_content.shared.resource import RESOURCE_CONTENT_TYPE, IResourceInfo, Resource +from pyams_content.shared.resource.interfaces import IResourceManager, IResourceManagerFactory +from pyams_utils.adapter import adapter_config +from pyams_utils.registry import utility_config +from pyams_utils.traversing import get_parent + + +@implementer(IResourceManager, IParagraphFactorySettings, IPictogramManagerTarget, + IThemesManagerTarget, ICollectionsManagerTarget) +class ResourceManager(TypedSharedTool): + """Resource manager class""" + + shared_content_type = RESOURCE_CONTENT_TYPE + + shared_content_types_fields = IResourceInfo + + allowed_paragraphs = FieldProperty(IParagraphFactorySettings['allowed_paragraphs']) + auto_created_paragraphs = FieldProperty(IParagraphFactorySettings['auto_created_paragraphs']) + + +@utility_config(provides=IResourceManagerFactory) +class ResourceManagerFactory(object): + """Default resource manager factory""" + + def __new__(cls): + return ResourceManager + + +@adapter_config(context=IResourceManager, provides=IManagerRestrictionsFactory) +def resource_manager_restrictions_factory(context): + """Resource manager custom restrictions factory""" + return SharedToolManagerRestrictionInfo + + +@adapter_config(context=IResourceManager, provides=ISharedContentFactory) +def resource_manager_content_factory(context): + return Resource + + +@subscriber(IObjectAddedEvent, context_selector=IResourceManager) +def handle_added_resource_manager(event): + """Register resource manager when added""" + site = get_parent(event.newParent, ISite) + registry = site.getSiteManager() + if registry is not None: + registry.registerUtility(event.object, IResourceManager) diff -r 9870e7467087 -r 8e8f528f8d3b src/pyams_content/shared/resource/zmi/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_content/shared/resource/zmi/__init__.py Fri Dec 28 10:20:33 2018 +0100 @@ -0,0 +1,96 @@ +# +# 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.interfaces import CREATE_CONTENT_PERMISSION, MANAGE_CONTENT_PERMISSION +from pyams_content.shared.common.zmi import SharedContentAJAXAddForm +from pyams_content.shared.common.zmi.types import TypedSharedContentAddForm, TypedSharedContentTypeFieldsEditForm +from pyams_content.shared.resource import IWfResource +from pyams_content.shared.resource.interfaces import IResourceManager +from pyams_form.form import ajax_config +from pyams_i18n.interfaces import II18n +from pyams_pagelet.pagelet import pagelet_config +from pyams_skin.interfaces import IContentTitle +from pyams_skin.interfaces.viewlet import IMenuHeader, IWidgetTitleViewletManager +from pyams_skin.layer import IPyAMSLayer +from pyams_skin.viewlet.menu import MenuItem +from pyams_skin.viewlet.toolbar import ToolbarAction +from pyams_utils.adapter import ContextRequestAdapter, ContextRequestViewAdapter, adapter_config +from pyams_viewlet.viewlet import viewlet_config +from pyams_zmi.interfaces.menu import IContentManagementMenu, IPropertiesMenu +from pyams_zmi.layer import IAdminLayer + +from pyams_content import _ + + +@adapter_config(context=(IWfResource, IContentManagementMenu), provides=IMenuHeader) +class ResourceContentMenuHeader(ContextRequestAdapter): + """Resource content menu header adapter""" + + header = _("This resource") + + +@adapter_config(context=(IWfResource, IPyAMSLayer, Interface), provides=IContentTitle) +class ResourceTitleAdapter(ContextRequestViewAdapter): + """Resource title adapter""" + + @property + def title(self): + translate = self.request.localizer.translate + return translate(_("Resource « {title} »")).format( + title=II18n(self.context).query_attribute('title', request=self.request)) + + +@viewlet_config(name='add-shared-content.action', context=IResourceManager, layer=IAdminLayer, view=Interface, + manager=IWidgetTitleViewletManager, permission=CREATE_CONTENT_PERMISSION, weight=1) +class ResourceAddAction(ToolbarAction): + """Resource adding action""" + + label = _("Add resource") + label_css_class = 'fa fa-fw fa-plus' + url = 'add-shared-content.html' + modal_target = True + + +@pagelet_config(name='add-shared-content.html', context=IResourceManager, layer=IPyAMSLayer, + permission=CREATE_CONTENT_PERMISSION) +@ajax_config(name='add-shared-content.json', context=IResourceManager, request_type=IPyAMSLayer, + permission=CREATE_CONTENT_PERMISSION, base=SharedContentAJAXAddForm) +class ResourceAddForm(TypedSharedContentAddForm): + """Resource add form""" + + legend = _("Add resource") + + +# +# Resource info edit form +# + +@viewlet_config(name='custom-properties.menu', context=IWfResource, layer=IPyAMSLayer, + manager=IPropertiesMenu, permission=MANAGE_CONTENT_PERMISSION, weight=15) +class ResourceTypePropertiesMenu(MenuItem): + """Resource type properties menu""" + + label = _("Specific properties") + icon_class = 'fa-paperclip' + url = '#type-properties.html' + + +@pagelet_config(name='type-properties.html', context=IWfResource, layer=IPyAMSLayer, + permission=MANAGE_CONTENT_PERMISSION) +@ajax_config(name='type-properties.json', context=IWfResource, layer=IPyAMSLayer, + permission=MANAGE_CONTENT_PERMISSION) +class ResourceTypePropertiesEditForm(TypedSharedContentTypeFieldsEditForm): + """Resource type properties edit form"""