# HG changeset patch # User Thierry Florac # Date 1531297090 -7200 # Node ID f933926ed0a1f3cc0477128926d53d4d32a7dbab # Parent bf12603398b24ccb8ce044f8c6237307a2ed4a05 Added support for collections diff -r bf12603398b2 -r f933926ed0a1 src/pyams_content/component/theme/__init__.py --- a/src/pyams_content/component/theme/__init__.py Tue Jul 10 16:59:55 2018 +0200 +++ b/src/pyams_content/component/theme/__init__.py Wed Jul 11 10:18:10 2018 +0200 @@ -18,7 +18,8 @@ # import interfaces from pyams_content.component.theme.interfaces import IThemesManagerTarget, IThemesManager, THEMES_MANAGER_KEY, \ IThemesTarget, IThemesInfo, THEMES_INFO_KEY, ITagsManager, ITagsManagerTarget, TAGS_MANAGER_KEY, ITagsInfo, \ - ITagsTarget, TAGS_INFO_KEY + ITagsTarget, TAGS_INFO_KEY, ICollectionsManager, ICollectionsManagerTarget, COLLECTIONS_MANAGER_KEY, \ + ICollectionsInfo, ICollectionsTarget, COLLECTIONS_INFO_KEY from pyams_content.features.checker.interfaces import IContentChecker, ERROR_VALUE # import packages @@ -116,7 +117,7 @@ """Themes info content checker""" label = _("Themes") - weight = 200 + weight = 210 def inner_check(self, request): output = [] @@ -126,3 +127,51 @@ output.append(translate(ERROR_VALUE).format(field=translate(IThemesInfo['themes'].title), message=translate(_("no defined theme")))) return output + + +# +# Collections management +# + +@implementer(ICollectionsManager) +class CollectionsManager(Persistent, Contained): + """Collections manager persistent class""" + + thesaurus_name = FieldProperty(ICollectionsManager['thesaurus_name']) + extract_name = FieldProperty(ICollectionsManager['extract_name']) + + +@adapter_config(context=ICollectionsManagerTarget, provides=ICollectionsManager) +def collections_manager_factory(target): + """Collections manager factory""" + return get_annotation_adapter(target, COLLECTIONS_MANAGER_KEY, CollectionsManager, name='++collections-manager++') + + +@implementer(ICollectionsInfo) +class CollectionsInfo(Persistent, Contained): + """Collections info persistent class""" + + collections = FieldProperty(ICollectionsInfo['collections']) + + +@adapter_config(context=ICollectionsTarget, provides=ICollectionsInfo) +def collections_info_factory(target): + """Collections info factory""" + return get_annotation_adapter(target, COLLECTIONS_INFO_KEY, CollectionsInfo, name='++collections++') + + +@adapter_config(name='collections', context=ICollectionsTarget, provides=IContentChecker) +class CollectionsContentChecker(BaseContentChecker): + """Collections info content checker""" + + label = _("Collections") + weight = 215 + + def inner_check(self, request): + output = [] + translate = request.localizer.translate + collections = ICollectionsInfo(self.context) + if not collections.collections: + output.append(translate(ERROR_VALUE).format(field=translate(ICollectionsInfo['collections'].title), + message=translate(_("no defined collection")))) + return output diff -r bf12603398b2 -r f933926ed0a1 src/pyams_content/component/theme/interfaces/__init__.py --- a/src/pyams_content/component/theme/interfaces/__init__.py Tue Jul 10 16:59:55 2018 +0200 +++ b/src/pyams_content/component/theme/interfaces/__init__.py Wed Jul 11 10:18:10 2018 +0200 @@ -58,13 +58,16 @@ class IPortletTagsSettings(Interface): """Interface for portlet settings managing tags""" + tags = ThesaurusTermsListField(title=_("Tags"), + required=False) + class IPortletTagsSettingsTarget(Interface): """Marker interface for portlet settings managing tags""" # -# Tags management +# Themes management # THEMES_MANAGER_KEY = 'pyams_content.themes.manager' @@ -96,6 +99,50 @@ class IPortletThemesSettings(Interface): """Interface for portlet settings managing themes""" + themes = ThesaurusTermsListField(title=_("Themes"), + required=False) + class IPortletThemesSettingsTarget(Interface): """Marker interface for portlet settings managing themes""" + + +# +# Collections management +# + +COLLECTIONS_MANAGER_KEY = 'pyams_content.collections.manager' +COLLECTIONS_INFO_KEY = 'pyams_content.collections.info' + + +class ICollectionsManager(IThesaurusContextManager): + """Collections manager interface""" + + +class ICollectionsManagerTarget(IThesaurusContextManagerTarget): + """Marker interface for tools managing collections""" + + +class ICollectionsInfo(Interface): + """Collections information interface""" + + collections = ThesaurusTermsListField(title=_("Collections"), + required=False) + + +class ICollectionsTarget(Interface): + """Collections target interface""" + + +PORTLET_SETTINGS_COLLECTIONS_KEY = 'pyams_content.portlet.collections.settings' + + +class IPortletCollectionsSettings(Interface): + """Interface for portlet settings managing collections""" + + collections = ThesaurusTermsListField(title=_("Collections"), + required=False) + + +class IPortletCollectionsSettingsTarget(Interface): + """Marker interface for portlet settings managing collections""" diff -r bf12603398b2 -r f933926ed0a1 src/pyams_content/component/theme/portlet.py --- a/src/pyams_content/component/theme/portlet.py Tue Jul 10 16:59:55 2018 +0200 +++ b/src/pyams_content/component/theme/portlet.py Wed Jul 11 10:18:10 2018 +0200 @@ -16,8 +16,10 @@ # import standard library # import interfaces -from pyams_content.component.theme.interfaces import IPortletThemesSettings, IPortletThemesSettingsTarget, \ - PORTLET_SETTINGS_THEMES_KEY +from pyams_content.component.theme.interfaces import \ + IPortletThemesSettings, IPortletThemesSettingsTarget, PORTLET_SETTINGS_THEMES_KEY, \ + IPortletTagsSettings, IPortletTagsSettingsTarget, PORTLET_SETTINGS_TAGS_KEY, \ + IPortletCollectionsSettings, IPortletCollectionsSettingsTarget, PORTLET_SETTINGS_COLLECTIONS_KEY from zope.traversing.interfaces import ITraversable # import packages @@ -25,17 +27,51 @@ from pyams_utils.adapter import adapter_config, ContextAdapter, get_annotation_adapter from zope.container.contained import Contained from zope.interface import implementer +from zope.schema.fieldproperty import FieldProperty +# +# Portlets tags management +# + +@implementer(IPortletTagsSettings) +class PortletTagsSettings(Persistent, Contained): + """Portlet tags settings""" + + tags = FieldProperty(IPortletTagsSettings['tags']) + + +@adapter_config(context=IPortletTagsSettingsTarget, provides=IPortletTagsSettings) +def portlet_tags_settings_factory(context): + """Portlet tags settings adapter""" + return get_annotation_adapter(context, PORTLET_SETTINGS_TAGS_KEY, PortletTagsSettings, + name='++tags++') + + +@adapter_config(name='tags', context=IPortletTagsSettingsTarget, provides=ITraversable) +class TagsPortletsSettingsTraverser(ContextAdapter): + """++tags++ portlet settings adapter""" + + def traverse(self, name, furtherpath=None): + return IPortletTagsSettings(self.context) + + +# +# Portlets themes management +# + @implementer(IPortletThemesSettings) class PortletThemesSettings(Persistent, Contained): """Portlet themes settings""" + themes = FieldProperty(IPortletThemesSettings['themes']) + @adapter_config(context=IPortletThemesSettingsTarget, provides=IPortletThemesSettings) def portlet_themes_settings_factory(context): """Portlet themes settings adapter""" - return get_annotation_adapter(context, PORTLET_SETTINGS_THEMES_KEY, PortletThemesSettings, name='++themes++') + return get_annotation_adapter(context, PORTLET_SETTINGS_THEMES_KEY, PortletThemesSettings, + name='++themes++') @adapter_config(name='themes', context=IPortletThemesSettingsTarget, provides=ITraversable) @@ -44,3 +80,29 @@ def traverse(self, name, furtherpath=None): return IPortletThemesSettings(self.context) + + +# +# Portlets collections management +# + +@implementer(IPortletCollectionsSettings) +class PortletCollectionsSettings(Persistent, Contained): + """Portlet collections settings""" + + collections = FieldProperty(IPortletCollectionsSettings['collections']) + + +@adapter_config(context=IPortletCollectionsSettingsTarget, provides=IPortletCollectionsSettings) +def portlet_collections_settings_factory(context): + """Portlet collections settings adapter""" + return get_annotation_adapter(context, PORTLET_SETTINGS_COLLECTIONS_KEY, PortletCollectionsSettings, + name='++collections++') + + +@adapter_config(name='collections', context=IPortletCollectionsSettingsTarget, provides=ITraversable) +class CollectionsPortletsSettingsTraverser(ContextAdapter): + """++collections++ portlet settings adapter""" + + def traverse(self, name, furtherpath=None): + return IPortletCollectionsSettings(self.context) diff -r bf12603398b2 -r f933926ed0a1 src/pyams_content/component/theme/zmi/__init__.py --- a/src/pyams_content/component/theme/zmi/__init__.py Tue Jul 10 16:59:55 2018 +0200 +++ b/src/pyams_content/component/theme/zmi/__init__.py Wed Jul 11 10:18:10 2018 +0200 @@ -17,12 +17,12 @@ # import interfaces from pyams_content.component.theme import ITagsTarget, ITagsInfo, ITagsManager, IThemesTarget, IThemesInfo, \ - IThemesManagerTarget, IThemesManager + IThemesManagerTarget, IThemesManager, ICollectionsTarget, ICollectionsInfo, ICollectionsManager, \ + ICollectionsManagerTarget from pyams_content.interfaces import MANAGE_CONTENT_PERMISSION from pyams_form.interfaces.form import IWidgetForm from pyams_skin.interfaces import IInnerPage, IPageHeader, IDialog from pyams_skin.layer import IPyAMSLayer -from pyams_thesaurus.interfaces.thesaurus import IThesaurus from pyams_utils.interfaces import VIEW_SYSTEM_PERMISSION from pyams_zmi.interfaces.menu import IPropertiesMenu from pyams_zmi.layer import IAdminLayer @@ -32,9 +32,8 @@ from pyams_form.form import ajax_config, AJAXEditForm, EditForm from pyams_pagelet.pagelet import pagelet_config from pyams_skin.viewlet.menu import MenuItem -from pyams_thesaurus.widget import ThesaurusTermsTreeFieldWidget +from pyams_thesaurus.zmi.widget import ThesaurusTermsTreeFieldWidget from pyams_utils.adapter import adapter_config -from pyams_utils.registry import query_utility from pyams_utils.traversing import get_parent from pyams_viewlet.viewlet import viewlet_config from pyams_zmi.form import AdminEditForm, AdminDialogEditForm @@ -72,33 +71,13 @@ fields = field.Fields(ITagsInfo) fields['tags'].widgetFactory = ThesaurusTermsTreeFieldWidget - def __init__(self, context, request): - super(TagsEditForm, self).__init__(context, request) - manager = ITagsManager(request.root) - self.thesaurus_name = manager.thesaurus_name - self.extract_name = manager.extract_name - def updateWidgets(self, prefix=None): super(TagsEditForm, self).updateWidgets(prefix) - widget = self.widgets['tags'] - widget.thesaurus_name = self.thesaurus_name - widget.extract_name = self.extract_name - - @property - def top_terms(self): - thesaurus = query_utility(IThesaurus, name=self.thesaurus_name) - if thesaurus is not None: - return sorted(thesaurus.get_top_terms(extract=self.extract_name), - key=lambda x: x.label) - else: - return () - - def get_subterms(self, term): - for subterm in term.specifics: - if (not self.extract_name) or (self.extract_name in subterm.extracts): - yield subterm - for another in self.get_subterms(subterm): - yield another + if 'tags' in self.widgets: + widget = self.widgets['tags'] + manager = ITagsManager(self.request.root) + widget.thesaurus_name = manager.thesaurus_name + widget.extract_name = manager.extract_name @adapter_config(context=(ITagsTarget, IAdminLayer, TagsEditForm), provides=IPageHeader) @@ -166,3 +145,57 @@ """Dialog themes edit form""" dialog_class = 'modal-large' + + +# +# Collections management +# + +@viewlet_config(name='collections.menu', context=ICollectionsTarget, layer=IAdminLayer, + manager=IPropertiesMenu, permission=VIEW_SYSTEM_PERMISSION, weight=354) +class CollectionsMenu(MenuItem): + """Collections menu""" + + label = _("Collections...") + icon_class = 'fa-book' + url = '#collections.html' + + +@pagelet_config(name='collections.html', context=ICollectionsTarget, layer=IPyAMSLayer, + permission=VIEW_SYSTEM_PERMISSION) +@ajax_config(name='collections.json', context=ICollectionsTarget, layer=IPyAMSLayer, + permission=MANAGE_CONTENT_PERMISSION) +@implementer(IWidgetForm, IInnerPage) +class CollectionsEditForm(AdminEditForm): + """Collections edit form""" + + legend = _("Content collections") + + label_css_class = 'control-label hidden' + input_css_class = 'col-md-12' + + fields = field.Fields(ICollectionsInfo) + fields['collections'].widgetFactory = ThesaurusTermsTreeFieldWidget + + def __init__(self, context, request): + super(CollectionsEditForm, self).__init__(context, request) + target = get_parent(self.context, ICollectionsManagerTarget) + manager = ICollectionsManager(target) + self.thesaurus_name = manager.thesaurus_name + self.extract_name = manager.extract_name + + def updateWidgets(self, prefix=None): + super(CollectionsEditForm, self).updateWidgets(prefix) + if 'collections' in self.widgets: + widget = self.widgets['collections'] + target = get_parent(self.context, ICollectionsManagerTarget) + manager = ICollectionsManager(target) + widget.thesaurus_name = manager.thesaurus_name + widget.extract_name = manager.extract_name + + +@adapter_config(context=(ICollectionsTarget, IAdminLayer, CollectionsEditForm), provides=IPageHeader) +class CollectionsHeaderAdapter(WfSharedContentHeaderAdapter): + """Shared content collections header adapter""" + + icon_class = 'fa fa-fw fa-book' diff -r bf12603398b2 -r f933926ed0a1 src/pyams_content/component/theme/zmi/manager.py --- a/src/pyams_content/component/theme/zmi/manager.py Tue Jul 10 16:59:55 2018 +0200 +++ b/src/pyams_content/component/theme/zmi/manager.py Wed Jul 11 10:18:10 2018 +0200 @@ -9,6 +9,7 @@ # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # +from pyams_content.component.theme import ICollectionsManagerTarget, ICollectionsManager __docformat__ = 'restructuredtext' @@ -106,7 +107,7 @@ class ThemesManagerEditForm(AdminDialogEditForm): """Themes manager edit form""" - prefix = 'manager_tags.' + prefix = 'manager_themes.' legend = _("Selected themes") @@ -130,3 +131,50 @@ } } alsoProvides(widget, IObjectData) + + +# +# Collections management view +# + +@viewlet_config(name='collections-manager.menu', context=ICollectionsManagerTarget, layer=IAdminLayer, + manager=IPropertiesMenu, permission=MANAGE_TOOL_PERMISSION, weight=42) +class CollectionsManagerMenu(MenuItem): + """Collections menu""" + + label = _("Collections settings...") + icon_class = 'fa-book' + url = 'collections.html' + modal_target = True + + +@pagelet_config(name='collections.html', context=ICollectionsManagerTarget, layer=IPyAMSLayer, + permission=MANAGE_TOOL_PERMISSION) +@ajax_config(name='collections.json', context=ICollectionsManagerTarget, layer=IPyAMSLayer) +class CollectionsManagerEditForm(AdminDialogEditForm): + """Collections manager edit form""" + + prefix = 'manager_collections.' + + legend = _("Selected collections") + + fields = field.Fields(ICollectionsManager) + edit_permission = MANAGE_TOOL_PERMISSION + + def updateWidgets(self, prefix=None): + super(CollectionsManagerEditForm, self).updateWidgets(prefix) + widget = self.widgets['thesaurus_name'] + widget.object_data = { + 'ams-plugins': 'pyams_content', + 'ams-plugin-pyams_content-src': get_resource_path(pyams_content), + 'ams-plugin-pyams_content-callback': 'PyAMS_content.collections.initExtracts', + 'ams-plugin-pyams_content-async': 'false' + } + alsoProvides(widget, IObjectData) + widget = self.widgets['extract_name'] + widget.object_data = { + 'ams-events-handlers': { + 'select2-open': 'PyAMS_content.themes.getExtracts' + } + } + alsoProvides(widget, IObjectData) diff -r bf12603398b2 -r f933926ed0a1 src/pyams_content/component/theme/zmi/portlet.py --- a/src/pyams_content/component/theme/zmi/portlet.py Tue Jul 10 16:59:55 2018 +0200 +++ b/src/pyams_content/component/theme/zmi/portlet.py Wed Jul 11 10:18:10 2018 +0200 @@ -16,7 +16,8 @@ # import standard library # import interfaces -from pyams_content.component.theme.interfaces import IPortletThemesSettingsTarget +from pyams_content.component.theme.interfaces import IPortletTagsSettingsTarget, IPortletThemesSettingsTarget, \ + IPortletCollectionsSettingsTarget, IPortletTagsSettings, IPortletThemesSettings, IPortletCollectionsSettings from pyams_form.interfaces.form import IInnerTabForm from pyams_skin.layer import IPyAMSLayer @@ -25,11 +26,25 @@ from pyams_utils.adapter import adapter_config from pyams_zmi.form import InnerAdminEditForm from z3c.form import field -from zope.interface import Interface from pyams_content import _ +@adapter_config(name='tags', context=(IPortletTagsSettingsTarget, IPyAMSLayer, PortletSettingsEditor), + provides=IInnerTabForm) +class PortletSettingsTagsEditor(InnerAdminEditForm): + """Portlet settings for tags""" + + prefix = 'tags_form.' + + tab_label = _("Tags") + legend = None + + fields = field.Fields(IPortletTagsSettings) + + weight = 50 + + @adapter_config(name='themes', context=(IPortletThemesSettingsTarget, IPyAMSLayer, PortletSettingsEditor), provides=IInnerTabForm) class PortletSettingsThemesEditor(InnerAdminEditForm): @@ -40,6 +55,21 @@ tab_label = _("Themes") legend = None - fields = field.Fields(Interface) + fields = field.Fields(IPortletThemesSettings) + + weight = 52 + - weight = 50 +@adapter_config(name='collections', context=(IPortletCollectionsSettingsTarget, IPyAMSLayer, PortletSettingsEditor), + provides=IInnerTabForm) +class PortletSettingsCollectionsEditor(InnerAdminEditForm): + """Portlet settings for collections""" + + prefix = 'collections_form.' + + tab_label = _("Collections") + legend = None + + fields = field.Fields(IPortletCollectionsSettings) + + weight = 54 diff -r bf12603398b2 -r f933926ed0a1 src/pyams_content/generations/__init__.py --- a/src/pyams_content/generations/__init__.py Tue Jul 10 16:59:55 2018 +0200 +++ b/src/pyams_content/generations/__init__.py Wed Jul 11 10:18:10 2018 +0200 @@ -19,7 +19,7 @@ # import interfaces from pyams_catalog.interfaces import MINUTE_RESOLUTION, DATE_RESOLUTION -from pyams_content.component.theme import ITagsInfo, IThemesInfo +from pyams_content.component.theme import ITagsInfo, IThemesInfo, ICollectionsInfo from pyams_content.interfaces import IBaseContent, WEBMASTER_ROLE, OWNER_ROLE, PILOT_ROLE, MANAGER_ROLE, \ CONTRIBUTOR_ROLE from pyams_content.root.interfaces import ISiteRootToolsConfiguration @@ -145,7 +145,11 @@ ('themes_all', ThesaurusTermsListFieldIndex, {'interface': IThemesInfo, 'discriminator': 'themes', 'include_parents': True, - 'include_synonyms': True}) + 'include_synonyms': True}), + ('collections', ThesaurusTermsListFieldIndex, {'interface': ICollectionsInfo, + 'discriminator': 'collections', + 'include_parents': False, + 'include_synonyms': False}) ] diff -r bf12603398b2 -r f933926ed0a1 src/pyams_content/locales/fr/LC_MESSAGES/pyams_content.mo Binary file src/pyams_content/locales/fr/LC_MESSAGES/pyams_content.mo has changed diff -r bf12603398b2 -r f933926ed0a1 src/pyams_content/locales/fr/LC_MESSAGES/pyams_content.po --- a/src/pyams_content/locales/fr/LC_MESSAGES/pyams_content.po Tue Jul 10 16:59:55 2018 +0200 +++ b/src/pyams_content/locales/fr/LC_MESSAGES/pyams_content.po Wed Jul 11 10:18:10 2018 +0200 @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE 1.0\n" -"POT-Creation-Date: 2018-07-10 16:58+0200\n" +"POT-Creation-Date: 2018-07-11 09:29+0200\n" "PO-Revision-Date: 2015-09-10 10:42+0200\n" "Last-Translator: Thierry Florac \n" "Language-Team: French\n" @@ -1279,59 +1279,90 @@ msgid "Presentation template used for this header" msgstr "Mode de rendu utilisé par ce chapô" -#: src/pyams_content/component/theme/__init__.py:70 +#: src/pyams_content/component/theme/__init__.py:71 +#: src/pyams_content/component/theme/zmi/portlet.py:40 #: src/pyams_content/component/theme/interfaces/__init__.py:47 +#: src/pyams_content/component/theme/interfaces/__init__.py:61 msgid "Tags" msgstr "Tags" -#: src/pyams_content/component/theme/__init__.py:118 -#: src/pyams_content/component/theme/zmi/portlet.py:40 -#: src/pyams_content/component/theme/interfaces/__init__.py:85 +#: src/pyams_content/component/theme/__init__.py:119 +#: src/pyams_content/component/theme/zmi/portlet.py:55 +#: src/pyams_content/component/theme/interfaces/__init__.py:88 +#: src/pyams_content/component/theme/interfaces/__init__.py:102 msgid "Themes" msgstr "Thèmes" -#: src/pyams_content/component/theme/__init__.py:79 +#: src/pyams_content/component/theme/__init__.py:167 +#: src/pyams_content/component/theme/zmi/portlet.py:70 +#: src/pyams_content/component/theme/interfaces/__init__.py:129 +#: src/pyams_content/component/theme/interfaces/__init__.py:143 +msgid "Collections" +msgstr "Collections" + +#: src/pyams_content/component/theme/__init__.py:80 msgid "no defined tag" msgstr "aucun tag défini" -#: src/pyams_content/component/theme/__init__.py:127 +#: src/pyams_content/component/theme/__init__.py:128 msgid "no defined theme" msgstr "aucun thème défini" -#: src/pyams_content/component/theme/zmi/__init__.py:56 -#: src/pyams_content/shared/view/zmi/theme.py:53 +#: src/pyams_content/component/theme/__init__.py:176 +msgid "no defined collection" +msgstr "aucune collection définie" + +#: src/pyams_content/component/theme/zmi/__init__.py:55 +#: src/pyams_content/shared/view/zmi/theme.py:56 msgid "Tags..." msgstr "Tags" -#: src/pyams_content/component/theme/zmi/__init__.py:67 +#: src/pyams_content/component/theme/zmi/__init__.py:66 msgid "Content tags" msgstr "Tags du contenu" -#: src/pyams_content/component/theme/zmi/__init__.py:120 -#: src/pyams_content/shared/view/zmi/theme.py:92 +#: src/pyams_content/component/theme/zmi/__init__.py:99 +#: src/pyams_content/shared/view/zmi/theme.py:99 msgid "Themes..." msgstr "Thèmes" -#: src/pyams_content/component/theme/zmi/__init__.py:128 +#: src/pyams_content/component/theme/zmi/__init__.py:107 msgid "Content themes" msgstr "Thèmes du contenu" -#: src/pyams_content/component/theme/zmi/manager.py:50 +#: src/pyams_content/component/theme/zmi/__init__.py:159 +#: src/pyams_content/shared/view/zmi/theme.py:141 +msgid "Collections..." +msgstr "Collections" + +#: src/pyams_content/component/theme/zmi/__init__.py:172 +msgid "Content collections" +msgstr "Collections associées au contenu" + +#: src/pyams_content/component/theme/zmi/manager.py:51 msgid "Tags settings..." msgstr "Paramétrage des tags" -#: src/pyams_content/component/theme/zmi/manager.py:64 +#: src/pyams_content/component/theme/zmi/manager.py:65 msgid "Selected tags" msgstr "Tags sélectionnés" -#: src/pyams_content/component/theme/zmi/manager.py:97 +#: src/pyams_content/component/theme/zmi/manager.py:98 msgid "Themes settings..." msgstr "Paramétrage des thèmes" -#: src/pyams_content/component/theme/zmi/manager.py:111 +#: src/pyams_content/component/theme/zmi/manager.py:112 msgid "Selected themes" msgstr "Thèmes sélectionnés" +#: src/pyams_content/component/theme/zmi/manager.py:145 +msgid "Collections settings..." +msgstr "Paramétrage des collections" + +#: src/pyams_content/component/theme/zmi/manager.py:159 +msgid "Selected collections" +msgstr "Collections sélectionnées" + #: src/pyams_content/component/association/container.py:88 #: src/pyams_content/component/association/zmi/__init__.py:296 #: src/pyams_content/component/association/interfaces/__init__.py:90 @@ -3582,14 +3613,18 @@ msgid "View « {title} »" msgstr "Vue « {title} »" -#: src/pyams_content/shared/view/zmi/theme.py:64 +#: src/pyams_content/shared/view/zmi/theme.py:67 msgid "View tags settings" msgstr "Paramétrage des tags de la vue" -#: src/pyams_content/shared/view/zmi/theme.py:103 +#: src/pyams_content/shared/view/zmi/theme.py:110 msgid "View themes settings" msgstr "Paramétrage des thèmes de la vue" +#: src/pyams_content/shared/view/zmi/theme.py:152 +msgid "View collections settings" +msgstr "Paramétrage des collections de la vue" + #: src/pyams_content/shared/view/zmi/reference.py:52 msgid "References..." msgstr "Références" @@ -3802,6 +3837,20 @@ msgid "Other themes" msgstr "Autres thèmes" +#: src/pyams_content/shared/view/interfaces/__init__.py:220 +msgid "Select context collections?" +msgstr "Collections du contexte ?" + +#: src/pyams_content/shared/view/interfaces/__init__.py:221 +msgid "If 'yes', collections will be extracted from context" +msgstr "" +"Si 'oui', les collections associées au contexte d'application de la vue seront " +"automatiquement sélectionnés" + +#: src/pyams_content/shared/view/interfaces/__init__.py:225 +msgid "Other collections" +msgstr "Autres collections" + #: src/pyams_content/shared/imagemap/paragraph.py:91 msgid "no selected image map" msgstr "aucune image cliquable sélectionnée" @@ -5488,9 +5537,6 @@ #~ msgid "The content « {0} » has been archived" #~ msgstr "Le contenu « {0} » a été archivé" -#~ msgid "Publication settings" -#~ msgstr "Dates de publication et de retrait" - #~ msgid "Add new data subtype" #~ msgstr "Ajout d'un sous-type" diff -r bf12603398b2 -r f933926ed0a1 src/pyams_content/locales/pyams_content.pot --- a/src/pyams_content/locales/pyams_content.pot Tue Jul 10 16:59:55 2018 +0200 +++ b/src/pyams_content/locales/pyams_content.pot Wed Jul 11 10:18:10 2018 +0200 @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE 1.0\n" -"POT-Creation-Date: 2018-07-10 16:58+0200\n" +"POT-Creation-Date: 2018-07-11 09:29+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" @@ -1228,59 +1228,90 @@ msgid "Presentation template used for this header" msgstr "" -#: ./src/pyams_content/component/theme/__init__.py:70 +#: ./src/pyams_content/component/theme/__init__.py:71 +#: ./src/pyams_content/component/theme/zmi/portlet.py:40 #: ./src/pyams_content/component/theme/interfaces/__init__.py:47 +#: ./src/pyams_content/component/theme/interfaces/__init__.py:61 msgid "Tags" msgstr "" -#: ./src/pyams_content/component/theme/__init__.py:118 -#: ./src/pyams_content/component/theme/zmi/portlet.py:40 -#: ./src/pyams_content/component/theme/interfaces/__init__.py:85 +#: ./src/pyams_content/component/theme/__init__.py:119 +#: ./src/pyams_content/component/theme/zmi/portlet.py:55 +#: ./src/pyams_content/component/theme/interfaces/__init__.py:88 +#: ./src/pyams_content/component/theme/interfaces/__init__.py:102 msgid "Themes" msgstr "" -#: ./src/pyams_content/component/theme/__init__.py:79 +#: ./src/pyams_content/component/theme/__init__.py:167 +#: ./src/pyams_content/component/theme/zmi/portlet.py:70 +#: ./src/pyams_content/component/theme/interfaces/__init__.py:129 +#: ./src/pyams_content/component/theme/interfaces/__init__.py:143 +msgid "Collections" +msgstr "" + +#: ./src/pyams_content/component/theme/__init__.py:80 msgid "no defined tag" msgstr "" -#: ./src/pyams_content/component/theme/__init__.py:127 +#: ./src/pyams_content/component/theme/__init__.py:128 msgid "no defined theme" msgstr "" -#: ./src/pyams_content/component/theme/zmi/__init__.py:56 -#: ./src/pyams_content/shared/view/zmi/theme.py:53 +#: ./src/pyams_content/component/theme/__init__.py:176 +msgid "no defined collection" +msgstr "" + +#: ./src/pyams_content/component/theme/zmi/__init__.py:55 +#: ./src/pyams_content/shared/view/zmi/theme.py:56 msgid "Tags..." msgstr "" -#: ./src/pyams_content/component/theme/zmi/__init__.py:67 +#: ./src/pyams_content/component/theme/zmi/__init__.py:66 msgid "Content tags" msgstr "" -#: ./src/pyams_content/component/theme/zmi/__init__.py:120 -#: ./src/pyams_content/shared/view/zmi/theme.py:92 +#: ./src/pyams_content/component/theme/zmi/__init__.py:99 +#: ./src/pyams_content/shared/view/zmi/theme.py:99 msgid "Themes..." msgstr "" -#: ./src/pyams_content/component/theme/zmi/__init__.py:128 +#: ./src/pyams_content/component/theme/zmi/__init__.py:107 msgid "Content themes" msgstr "" -#: ./src/pyams_content/component/theme/zmi/manager.py:50 +#: ./src/pyams_content/component/theme/zmi/__init__.py:159 +#: ./src/pyams_content/shared/view/zmi/theme.py:141 +msgid "Collections..." +msgstr "" + +#: ./src/pyams_content/component/theme/zmi/__init__.py:172 +msgid "Content collections" +msgstr "" + +#: ./src/pyams_content/component/theme/zmi/manager.py:51 msgid "Tags settings..." msgstr "" -#: ./src/pyams_content/component/theme/zmi/manager.py:64 +#: ./src/pyams_content/component/theme/zmi/manager.py:65 msgid "Selected tags" msgstr "" -#: ./src/pyams_content/component/theme/zmi/manager.py:97 +#: ./src/pyams_content/component/theme/zmi/manager.py:98 msgid "Themes settings..." msgstr "" -#: ./src/pyams_content/component/theme/zmi/manager.py:111 +#: ./src/pyams_content/component/theme/zmi/manager.py:112 msgid "Selected themes" msgstr "" +#: ./src/pyams_content/component/theme/zmi/manager.py:145 +msgid "Collections settings..." +msgstr "" + +#: ./src/pyams_content/component/theme/zmi/manager.py:159 +msgid "Selected collections" +msgstr "" + #: ./src/pyams_content/component/association/container.py:88 #: ./src/pyams_content/component/association/zmi/__init__.py:296 #: ./src/pyams_content/component/association/interfaces/__init__.py:90 @@ -3357,14 +3388,18 @@ msgid "View « {title} »" msgstr "" -#: ./src/pyams_content/shared/view/zmi/theme.py:64 +#: ./src/pyams_content/shared/view/zmi/theme.py:67 msgid "View tags settings" msgstr "" -#: ./src/pyams_content/shared/view/zmi/theme.py:103 +#: ./src/pyams_content/shared/view/zmi/theme.py:110 msgid "View themes settings" msgstr "" +#: ./src/pyams_content/shared/view/zmi/theme.py:152 +msgid "View collections settings" +msgstr "" + #: ./src/pyams_content/shared/view/zmi/reference.py:52 msgid "References..." msgstr "" @@ -3544,6 +3579,18 @@ msgid "Other themes" msgstr "" +#: ./src/pyams_content/shared/view/interfaces/__init__.py:220 +msgid "Select context collections?" +msgstr "" + +#: ./src/pyams_content/shared/view/interfaces/__init__.py:221 +msgid "If 'yes', collections will be extracted from context" +msgstr "" + +#: ./src/pyams_content/shared/view/interfaces/__init__.py:225 +msgid "Other collections" +msgstr "" + #: ./src/pyams_content/shared/imagemap/paragraph.py:91 msgid "no selected image map" msgstr "" diff -r bf12603398b2 -r f933926ed0a1 src/pyams_content/shared/view/interfaces/__init__.py --- a/src/pyams_content/shared/view/interfaces/__init__.py Tue Jul 10 16:59:55 2018 +0200 +++ b/src/pyams_content/shared/view/interfaces/__init__.py Wed Jul 11 10:18:10 2018 +0200 @@ -177,7 +177,7 @@ select_context_tags = Bool(title=_("Select context tags?"), description=_("If 'yes', tags will be extracted from context"), - required=True, + required=False, default=False) tags = ThesaurusTermsListField(title=_("Other tags"), @@ -198,7 +198,7 @@ select_context_themes = Bool(title=_("Select context themes?"), description=_("If 'yes', themes will be extracted from context"), - required=True, + required=False, default=False) themes = ThesaurusTermsListField(title=_("Other themes"), @@ -211,6 +211,27 @@ """Get all themes index values for given context""" +VIEW_COLLECTIONS_SETTINGS_KEY = 'pyams_content.view.collections' + + +class IViewCollectionsSettings(IViewSettings): + """View collections settings""" + + select_context_collections = Bool(title=_("Select context collections?"), + description=_("If 'yes', collections will be extracted from context"), + required=False, + default=False) + + collections = ThesaurusTermsListField(title=_("Other collections"), + required=False) + + def get_collections(self, context): + """Get all collections for given context""" + + def get_collections_index(self, context): + """Get all collections index values for given context""" + + VIEWS_MERGERS_VOCABULARY = 'pyams_content.views.mergers' diff -r bf12603398b2 -r f933926ed0a1 src/pyams_content/shared/view/manager.py --- a/src/pyams_content/shared/view/manager.py Tue Jul 10 16:59:55 2018 +0200 +++ b/src/pyams_content/shared/view/manager.py Wed Jul 11 10:18:10 2018 +0200 @@ -16,7 +16,7 @@ # import standard library # import interfaces -from pyams_content.component.theme.interfaces import IThemesManagerTarget +from pyams_content.component.theme.interfaces import IThemesManagerTarget, ICollectionsManagerTarget from pyams_content.shared.common.interfaces import ISharedContentFactory from pyams_content.shared.view.interfaces import IViewsManager, VIEW_CONTENT_TYPE, IViewsManagerFactory from zope.annotation.interfaces import IAttributeAnnotatable @@ -33,7 +33,7 @@ from zope.interface import implementer -@implementer(IViewsManager, IThemesManagerTarget, IAttributeAnnotatable) +@implementer(IViewsManager, IThemesManagerTarget, ICollectionsManagerTarget, IAttributeAnnotatable) class ViewsManager(SharedTool): """Views manager class""" diff -r bf12603398b2 -r f933926ed0a1 src/pyams_content/shared/view/theme.py --- a/src/pyams_content/shared/view/theme.py Tue Jul 10 16:59:55 2018 +0200 +++ b/src/pyams_content/shared/view/theme.py Wed Jul 11 10:18:10 2018 +0200 @@ -9,6 +9,7 @@ # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # +from pyams_content.component.theme import ICollectionsInfo __docformat__ = 'restructuredtext' @@ -19,7 +20,8 @@ from hypatia.interfaces import ICatalog from pyams_content.component.theme.interfaces import ITagsInfo, IThemesInfo from pyams_content.shared.view.interfaces import IWfView, IViewSettings, IViewThemesSettings, \ - IViewQueryParamsExtension, VIEW_THEMES_SETTINGS_KEY, IViewTagsSettings, VIEW_TAGS_SETTINGS_KEY + IViewQueryParamsExtension, VIEW_THEMES_SETTINGS_KEY, IViewTagsSettings, VIEW_TAGS_SETTINGS_KEY, \ + IViewCollectionsSettings, VIEW_COLLECTIONS_SETTINGS_KEY from zope.intid.interfaces import IIntIds # import packages @@ -141,3 +143,58 @@ if themes: params = and_(params, Any(catalog['themes'], themes)) return params + + +# +# Collections management +# + +@implementer(IViewCollectionsSettings) +class ViewCollectionsSettings(Persistent, Contained): + """View collections settings""" + + select_context_collections = FieldProperty(IViewCollectionsSettings['select_context_collections']) + collections = FieldProperty(IViewCollectionsSettings['collections']) + + @property + def is_using_context(self): + return self.select_context_collections + + def get_collections(self, context): + collections = set() + if self.select_context_collections: + collections_info = ICollectionsInfo(context, None) + if collections_info is not None: + collections |= set(collections_info.collections or ()) + if self.collections: + collections |= set(self.collections) + return collections + + def get_collections_index(self, context): + intids = get_utility(IIntIds) + return [intids.register(term) for term in self.get_collections(context)] + + +@adapter_config(context=IWfView, provides=IViewCollectionsSettings) +@adapter_config(name='collections', context=IWfView, provides=IViewSettings) +def view_collections_settings_factory(view): + """View collections settings factory""" + return get_annotation_adapter(view, VIEW_COLLECTIONS_SETTINGS_KEY, ViewCollectionsSettings, + name='++view:collections++') + + +@adapter_config(name='collections', context=IWfView, provides=IViewQueryParamsExtension) +class ViewCollectionsQueryParamsExtension(ContextAdapter): + """View collections query params extension""" + + weight = 54 + + def get_params(self, context): + catalog = get_utility(ICatalog) + settings = IViewCollectionsSettings(self.context) + params = None + # check collections + collections = settings.get_collections_index(context) + if collections: + params = and_(params, Any(catalog['collections'], collections)) + return params diff -r bf12603398b2 -r f933926ed0a1 src/pyams_content/shared/view/zmi/theme.py --- a/src/pyams_content/shared/view/zmi/theme.py Tue Jul 10 16:59:55 2018 +0200 +++ b/src/pyams_content/shared/view/zmi/theme.py Wed Jul 11 10:18:10 2018 +0200 @@ -9,7 +9,6 @@ # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # -from pyams_content.component.theme import ITagsManager __docformat__ = 'restructuredtext' @@ -18,7 +17,8 @@ # import interfaces from pyams_content.interfaces import MANAGE_CONTENT_PERMISSION -from pyams_content.shared.view.interfaces import IWfView, IViewThemesSettings, IViewsManager, IViewTagsSettings +from pyams_content.shared.view.interfaces import IWfView, IViewThemesSettings, IViewsManager, IViewTagsSettings, \ + IViewCollectionsSettings from pyams_form.interfaces.form import IWidgetForm, IUncheckedEditFormButtons from pyams_skin.interfaces import IInnerPage from pyams_skin.layer import IPyAMSLayer @@ -29,13 +29,16 @@ from z3c.form.interfaces import INPUT_MODE # import packages +from pyams_content.component.theme import ITagsManager from pyams_form.form import ajax_config from pyams_pagelet.pagelet import pagelet_config from pyams_skin.viewlet.menu import MenuItem +from pyams_thesaurus.zmi.widget import ThesaurusTermsTreeFieldWidget from pyams_utils.registry import get_utility from pyams_viewlet.viewlet import viewlet_config from pyams_zmi.form import AdminEditForm from z3c.form import field, button +from z3c.form.browser.checkbox import SingleCheckBoxFieldWidget from zope.interface import implementer, Interface from pyams_content import _ @@ -62,8 +65,12 @@ """View tags settings edit form""" legend = _("View tags settings") + label_css_class = 'control-label col-md-1' + input_css_class = 'col-md-11' fields = field.Fields(IViewTagsSettings) + fields['select_context_tags'].widgetFactory = SingleCheckBoxFieldWidget + fields['tags'].widgetFactory = ThesaurusTermsTreeFieldWidget @property def buttons(self): @@ -76,8 +83,11 @@ super(ViewTagsEditForm, self).updateWidgets(prefix) if 'tags' in self.widgets: manager = ITagsManager(self.request.root) - self.widgets['tags'].thesaurus_name = manager.thesaurus_name - self.widgets['tags'].extract_name = manager.extract_name + widget = self.widgets['tags'] + widget.label_css_class = 'control-label col-md-2' + widget.input_css_class = 'col-md-12' + widget.thesaurus_name = manager.thesaurus_name + widget.extract_name = manager.extract_name # @@ -101,8 +111,12 @@ """View themes settings edit form""" legend = _("View themes settings") + label_css_class = 'control-label col-md-1' + input_css_class = 'col-md-11' fields = field.Fields(IViewThemesSettings) + fields['select_context_themes'].widgetFactory = SingleCheckBoxFieldWidget + fields['themes'].widgetFactory = ThesaurusTermsTreeFieldWidget @property def buttons(self): @@ -114,5 +128,55 @@ def updateWidgets(self, prefix=None): super(ViewThemesEditForm, self).updateWidgets(prefix) if 'themes' in self.widgets: - manager = get_utility(IViewsManager) - self.widgets['themes'].thesaurus_name = IThesaurusContextManager(manager).thesaurus_name + manager = IThesaurusContextManager(get_utility(IViewsManager)) + widget = self.widgets['themes'] + widget.label_css_class = 'control-label col-md-2' + widget.input_css_class = 'col-md-12' + widget.thesaurus_name = manager.thesaurus_name + widget.extract_name = manager.extract_name + + +# +# Collections management +# + +@viewlet_config(name='collections.menu', context=IWfView, layer=IAdminLayer, + manager=IPropertiesMenu, permission=VIEW_SYSTEM_PERMISSION, weight=354) +class ViewCollectionsMenu(MenuItem): + """View collections menu""" + + label = _("Collections...") + icon_class = 'fa-book' + url = '#collections.html' + + +@pagelet_config(name='collections.html', context=IWfView, layer=IPyAMSLayer, permission=VIEW_SYSTEM_PERMISSION) +@ajax_config(name='collections.json', context=IWfView, layer=IPyAMSLayer, permission=MANAGE_CONTENT_PERMISSION) +@implementer(IWidgetForm, IInnerPage) +class ViewCollectionsEditForm(AdminEditForm): + """View collections settings edit form""" + + legend = _("View collections settings") + label_css_class = 'control-label col-md-1' + input_css_class = 'col-md-11' + + fields = field.Fields(IViewCollectionsSettings) + fields['select_context_collections'].widgetFactory = SingleCheckBoxFieldWidget + fields['collections'].widgetFactory = ThesaurusTermsTreeFieldWidget + + @property + def buttons(self): + if self.mode == INPUT_MODE: + return button.Buttons(IUncheckedEditFormButtons) + else: + return button.Buttons(Interface) + + def updateWidgets(self, prefix=None): + super(ViewCollectionsEditForm, self).updateWidgets(prefix) + if 'collections' in self.widgets: + manager = IThesaurusContextManager(get_utility(IViewsManager)) + widget = self.widgets['collections'] + widget.label_css_class = 'control-label col-md-2' + widget.input_css_class = 'col-md-12' + widget.thesaurus_name = manager.thesaurus_name + widget.extract_name = manager.extract_name