diff -r 29b1aaf9e080 -r d1db251eeea3 src/pyams_content/features/search/zmi/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_content/features/search/zmi/__init__.py Wed Nov 07 17:29:54 2018 +0100 @@ -0,0 +1,198 @@ +# +# 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 zope.interface import Interface +from zope.intid import IIntIds + +from pyams_content.features.search import ISearchFolder, SearchFolder +from pyams_content.interfaces import MANAGE_SITE_PERMISSION +from pyams_content.shared.common.zmi.summary import SharedContentDublinCoreSummary, SharedContentWorkflowHistorySummary, \ + SharedContentWorkflowPublicationState +from pyams_content.shared.site.interfaces import ISiteContainer +from pyams_content.shared.site.zmi import SiteManagerFoldersSelectorFieldWidget +from pyams_content.shared.site.zmi.folder import ISiteFolderAddFormFields +from pyams_form.form import AJAXAddForm, ajax_config +from pyams_form.interfaces.form import IInnerSubForm +from pyams_i18n.interfaces import II18n, INegotiator +from pyams_pagelet.pagelet import pagelet_config +from pyams_security.zmi.interfaces import IObjectSecurityMenu +from pyams_skin.interfaces import IContentTitle, IPageHeader +from pyams_skin.interfaces.viewlet import IMenuHeader, IToolbarAddingMenu, IContextActions +from pyams_skin.layer import IPyAMSLayer +from pyams_skin.page import DefaultPageHeaderAdapter, HeaderContentProvider +from pyams_skin.viewlet.toolbar import ToolbarMenuItem +from pyams_utils.adapter import ContextRequestAdapter, ContextRequestViewAdapter, NullAdapter, adapter_config +from pyams_utils.registry import get_utility +from pyams_utils.unicode import translate_string +from pyams_utils.url import absolute_url +from pyams_viewlet.viewlet import contentprovider_config, viewlet_config +from pyams_workflow.interfaces import IWorkflowPublicationInfo +from pyams_zmi.form import AdminDialogAddForm +from pyams_zmi.interfaces.menu import IContentManagementMenu +from pyams_zmi.layer import IAdminLayer + +from pyams_content import _ + + +@adapter_config(context=(ISearchFolder, IPyAMSLayer, Interface), provides=IPageHeader) +class SearchFolderPropertiesHeaderAdapter(DefaultPageHeaderAdapter): + """Search folder header adapter""" + + back_url = '/admin#properties.html' + back_target = None + + icon_class = 'fa fa-fw fa-edit' + + +@adapter_config(context=(ISearchFolder, IContentManagementMenu), provides=IMenuHeader) +class SearchFolderContentMenuHeader(ContextRequestAdapter): + """Search folder menu header adapter""" + + header = _("This search folder") + + +@adapter_config(context=(ISearchFolder, IPyAMSLayer, Interface), provides=IContentTitle) +class SearchFolderTitleAdapter(ContextRequestViewAdapter): + """Search folder title adapter""" + + @property + def title(self): + translate = self.request.localizer.translate + return translate(_("Search folder « {title} »")).format( + title=II18n(self.context).query_attribute('title', request=self.request)) + + +@viewlet_config(name='add-search-folder.menu', context=ISiteContainer, layer=IAdminLayer, view=Interface, + manager=IToolbarAddingMenu, permission=MANAGE_SITE_PERMISSION, weight=11) +class SearchFolderAddMenu(ToolbarMenuItem): + """Search folder add menu""" + + label = _("Add search folder...") + label_css_class = 'fa fa-fw fa-search' + url = 'add-search-folder.html' + modal_target = True + + +@pagelet_config(name='add-search-folder.html', context=ISiteContainer, layer=IPyAMSLayer, + permission=MANAGE_SITE_PERMISSION) +@ajax_config(name='add-search-folder.json', context=ISiteContainer, layer=IPyAMSLayer, base=AJAXAddForm) +class SearchFolderAddForm(AdminDialogAddForm): + """Search folder add form""" + + @property + def title(self): + return II18n(self.context).query_attribute('title', request=self.request) + + legend = _("Add search folder") + icon_css_class = 'fa fa-fw fa-search' + + fields = field.Fields(ISiteFolderAddFormFields) + fields['parent'].widgetFactory = SiteManagerFoldersSelectorFieldWidget + + edit_permission = MANAGE_SITE_PERMISSION + + def updateWidgets(self, prefix=None): + super(SearchFolderAddForm, self).updateWidgets(prefix) + if 'parent' in self.widgets: + self.widgets['parent'].permission = MANAGE_SITE_PERMISSION + + def create(self, data): + return SearchFolder() + + def update_content(self, content, data): + data = data.get(self, data) + # initialize + content.title = data['title'] + content.short_name = data['title'] + content.notepad = data['notepad'] + intids = get_utility(IIntIds) + parent = intids.queryObject(data.get('parent')) + if parent is not None: + negotiator = get_utility(INegotiator) + title = II18n(content).get_attribute('title', lang=negotiator.server_language) + name = translate_string(title, force_lower=True, spaces='-') + if name in parent: + index = 1 + new_name = '{name}-{index:02}'.format(name=name, index=index) + while new_name in parent: + index += 1 + new_name = '{name}-{index:02}'.format(name=name, index=index) + name = new_name + parent[name] = content + + def add(self, content): + pass + + def nextURL(self): + return absolute_url(self.context, self.request, 'admin#site-tree.html') + + def get_ajax_output(self, changes): + return {'status': 'reload'} + + +# +# Search folder content providers +# + +@contentprovider_config(name='content_header', context=ISearchFolder, view=Interface, layer=IPyAMSLayer) +class SearchFolderHeaderContentProvider(HeaderContentProvider): + """Search folder header content provider""" + + +# +# Custom search folders adapters +# + +@adapter_config(name='workflow-publication-state', + context=(ISearchFolder, IPyAMSLayer, SharedContentDublinCoreSummary), + provides=IInnerSubForm) +class SearchFolderWorkflowPublicationState(SharedContentWorkflowPublicationState): + """Search folder workflow publication state is disabled""" + + fields = field.Fields(IWorkflowPublicationInfo).select('publication_effective_date', + 'publication_expiration_date') + + +@adapter_config(name='workflow-history-summary', + context=(ISearchFolder, IPyAMSLayer, SharedContentDublinCoreSummary), + provides=IInnerSubForm) +class SearchFolderWorkflowHistorySummary(SharedContentWorkflowHistorySummary): + """Search folder workflow history summary""" + + fields = field.Fields(IWorkflowPublicationInfo).select('first_publication_date') + + +@viewlet_config(name='change-owner.menu', context=ISearchFolder, layer=IPyAMSLayer, + view=Interface, manager=IObjectSecurityMenu, permission=MANAGE_SITE_PERMISSION, weight=10) +class SearchFolderOwnerChangeMenu(NullAdapter): + """Search folder owner change menu is disabled""" + + +@viewlet_config(name='duplication.divider', context=ISearchFolder, layer=IPyAMSLayer, + view=Interface, manager=IContextActions, permission=MANAGE_SITE_PERMISSION, weight=49) +class SearchFolderDuplicationMenuDivider(NullAdapter): + """Search folder duplication menu divider is disabled""" + + +@viewlet_config(name='duplication.menu', context=ISearchFolder, layer=IPyAMSLayer, + view=Interface, manager=IContextActions, permission=MANAGE_SITE_PERMISSION, weight=50) +class SearchFolderDuplicateMenu(NullAdapter): + """Search folder duplication menu item is disabled""" + + +@viewlet_config(name='ask-review.menu', context=ISearchFolder, layer=IPyAMSLayer, + view=Interface, manager=IContextActions, permission=MANAGE_SITE_PERMISSION, weight=10) +class SearchFolderReviewMenu(NullAdapter): + """Search folder review menu is disabled"""