# HG changeset patch # User Thierry Florac # Date 1453129687 -3600 # Node ID cbc55162b64e3a927e2384cdb58d295e49d80695 # Parent b952eda9bb42f1b2832cfe16a2834a49e29a8da9 Changes inner forms base class diff -r b952eda9bb42 -r cbc55162b64e src/pyams_content/component/extfile/zmi/container.py --- a/src/pyams_content/component/extfile/zmi/container.py Thu Oct 15 15:42:01 2015 +0200 +++ b/src/pyams_content/component/extfile/zmi/container.py Mon Jan 18 16:08:07 2016 +0100 @@ -251,3 +251,13 @@ permission=MANAGE_CONTENT_PERMISSION, renderer='json', xhr=True) class ExtFileLinksContainerAJAXEditForm(AJAXEditForm, ExtFileLinksContainerLinksEditForm): """External file links container edit form, JSON renderer""" + + def get_ajax_output(self, changes): + if 'files' in changes.get(IExtFileLinksContainer, ()): + return {'status': 'success', + 'event': 'PyAMS_content.changed_item', + 'event_options': {'object_type': 'extfiles_container', + 'object_name': self.context.__name__, + 'nb_files': len(IExtFileLinksContainer(self.context).files or ())}} + else: + return super(ExtFileLinksContainerAJAXEditForm, self).get_ajax_output(changes) diff -r b952eda9bb42 -r cbc55162b64e src/pyams_content/component/gallery/zmi/__init__.py --- a/src/pyams_content/component/gallery/zmi/__init__.py Thu Oct 15 15:42:01 2015 +0200 +++ b/src/pyams_content/component/gallery/zmi/__init__.py Mon Jan 18 16:08:07 2016 +0100 @@ -59,7 +59,7 @@ @pagelet_config(name='add-gallery.html', context=IGalleryContainerTarget, layer=IPyAMSLayer, - permission='pyams.ManageContent') + permission=MANAGE_CONTENT_PERMISSION) class GalleryAddForm(AdminDialogAddForm): """Gallery add form""" diff -r b952eda9bb42 -r cbc55162b64e src/pyams_content/component/gallery/zmi/container.py --- a/src/pyams_content/component/gallery/zmi/container.py Thu Oct 15 15:42:01 2015 +0200 +++ b/src/pyams_content/component/gallery/zmi/container.py Mon Jan 18 16:08:07 2016 +0100 @@ -114,6 +114,20 @@ return super(GalleryContainerTable, self).render() +@adapter_config(name='manage', context=(IGalleryContainerTarget, IPyAMSLayer, GalleryContainerTable), provides=IColumn) +class GalleryContainerManageColumn(ActionColumn): + """Gallery container manage column""" + + icon_class = 'fa fa-fw fa-camera' + icon_hint = _("Display gallery contents") + + url = 'contents.html' + target = None + modal_target = True + + weight = 5 + + @adapter_config(name='name', context=(IGalleryContainerTarget, IPyAMSLayer, GalleryContainerTable), provides=IColumn) class GalleryContainerNameColumn(I18nColumn, WfModifiedContentColumnMixin, GetAttrColumn): """Galleries container name column""" @@ -138,20 +152,6 @@ return len(obj) -@adapter_config(name='manage', context=(IGalleryContainerTarget, IPyAMSLayer, GalleryContainerTable), provides=IColumn) -class GalleryContainerManageColumn(ActionColumn): - """Gallery container manage column""" - - icon_class = 'fa fa-fw fa-camera' - icon_hint = _("Display gallery contents") - - url = 'contents.html' - target = None - modal_target = True - - weight = 30 - - @adapter_config(name='trash', context=(IGalleryContainerTarget, IPyAMSLayer, GalleryContainerTable), provides=IColumn) class GalleryContainerTrashColumn(ProtectedFormObjectMixin, TrashColumn): """Galleries container trash column""" @@ -196,3 +196,13 @@ permission=MANAGE_CONTENT_PERMISSION, renderer='json', xhr=True) class GalleryLinksContainerAJAXEditForm(AJAXEditForm, GalleryLinksContainerLinksEditForm): """Galleries links container edit form, JSON renderer""" + + def get_ajax_output(self, changes): + if 'galleries' in changes.get(IGalleryLinksContainer, ()): + return {'status': 'success', + 'event': 'PyAMS_content.changed_item', + 'event_options': {'object_type': 'galleries_container', + 'object_name': self.context.__name__, + 'nb_galleries': len(IGalleryLinksContainer(self.context).galleries or ())}} + else: + return super(GalleryLinksContainerAJAXEditForm, self).get_ajax_output(changes) diff -r b952eda9bb42 -r cbc55162b64e src/pyams_content/component/links/zmi/container.py --- a/src/pyams_content/component/links/zmi/container.py Thu Oct 15 15:42:01 2015 +0200 +++ b/src/pyams_content/component/links/zmi/container.py Mon Jan 18 16:08:07 2016 +0100 @@ -209,3 +209,13 @@ permission=MANAGE_CONTENT_PERMISSION, renderer='json', xhr=True) class LinkLinksContainerAJAXEditForm(AJAXEditForm, LinkLinksContainerLinksEditForm): """Links links container edit form, JSON renderer""" + + def get_ajax_output(self, changes): + if 'links' in changes.get(ILinkLinksContainer, ()): + return {'status': 'success', + 'event': 'PyAMS_content.changed_item', + 'event_options': {'object_type': 'links_container', + 'object_name': self.context.__name__, + 'nb_links': len(ILinkLinksContainer(self.context).links or ())}} + else: + return super(LinkLinksContainerAJAXEditForm, self).get_ajax_output(changes) diff -r b952eda9bb42 -r cbc55162b64e src/pyams_content/component/paragraph/__init__.py --- a/src/pyams_content/component/paragraph/__init__.py Thu Oct 15 15:42:01 2015 +0200 +++ b/src/pyams_content/component/paragraph/__init__.py Mon Jan 18 16:08:07 2016 +0100 @@ -37,6 +37,7 @@ class BaseParagraph(Persistent, Contained): """Base paragraph persistent class""" + visible = FieldProperty(IBaseParagraph['visible']) title = FieldProperty(IBaseParagraph['title']) diff -r b952eda9bb42 -r cbc55162b64e src/pyams_content/component/paragraph/interfaces/__init__.py --- a/src/pyams_content/component/paragraph/interfaces/__init__.py Thu Oct 15 15:42:01 2015 +0200 +++ b/src/pyams_content/component/paragraph/interfaces/__init__.py Mon Jan 18 16:08:07 2016 +0100 @@ -25,7 +25,7 @@ from pyams_i18n.schema import I18nTextLineField, I18nHTMLField from zope.container.constraints import containers, contains from zope.interface import Interface, Attribute -from zope.schema import Choice +from zope.schema import Bool, Choice from pyams_content import _ @@ -38,6 +38,11 @@ containers('.IParagraphContainer') + visible = Bool(title=_("Visible?"), + description=_("Is this paragraph visible in front-office?"), + required=True, + default=True) + title = I18nTextLineField(title=_("Title"), description=_("Paragraph title"), required=False) diff -r b952eda9bb42 -r cbc55162b64e src/pyams_content/component/paragraph/zmi/__init__.py --- a/src/pyams_content/component/paragraph/zmi/__init__.py Thu Oct 15 15:42:01 2015 +0200 +++ b/src/pyams_content/component/paragraph/zmi/__init__.py Mon Jan 18 16:08:07 2016 +0100 @@ -16,5 +16,27 @@ # import standard library # import interfaces +from pyams_content.component.paragraph.interfaces import IBaseParagraph +from pyams_i18n.interfaces import II18n # import packages +from pyams_form.form import AJAXEditForm + + +class BaseParagraphAJAXEditForm(AJAXEditForm): + """Base paragraph AJAX edit form""" + + def get_ajax_output(self, changes): + updated = changes.get(IBaseParagraph, ()) + if ('title' in updated) or ('visible' in updated): + return {'status': 'success', + 'event': 'PyAMS_content.changed_item', + 'event_options': {'object_type': 'paragraph', + 'object_name': self.context.__name__, + 'title': II18n(self.context).query_attribute('title', request=self.request), + 'visible': self.context.visible}} + if 'title' in changes.get(IBaseParagraph, ()): + return {'status': 'reload', + 'location': '#paragraphs.html'} + else: + return super(BaseParagraphAJAXEditForm, self).get_ajax_output(changes) diff -r b952eda9bb42 -r cbc55162b64e src/pyams_content/component/paragraph/zmi/container.py --- a/src/pyams_content/component/paragraph/zmi/container.py Thu Oct 15 15:42:01 2015 +0200 +++ b/src/pyams_content/component/paragraph/zmi/container.py Mon Jan 18 16:08:07 2016 +0100 @@ -9,6 +9,7 @@ # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # +from pyams_form.interfaces.form import IFormSecurityContext __docformat__ = 'restructuredtext' @@ -18,10 +19,11 @@ # import interfaces from pyams_content.interfaces import MANAGE_CONTENT_PERMISSION -from pyams_content.component.extfile.interfaces import IExtFileLinksContainerTarget -from pyams_content.component.gallery.interfaces import IGalleryLinksContainerTarget -from pyams_content.component.links.interfaces import ILinkLinksContainerTarget -from pyams_content.component.paragraph.interfaces import IParagraphContainerTarget, IParagraphContainer +from pyams_content.component.extfile.interfaces import IExtFileLinksContainerTarget, IExtFileLinksContainer +from pyams_content.component.gallery.interfaces import IGalleryLinksContainerTarget, IGalleryLinksContainer +from pyams_content.component.links.interfaces import ILinkLinksContainerTarget, ILinkLinksContainer +from pyams_content.component.paragraph.interfaces import IParagraphContainerTarget, IParagraphContainer, IBaseParagraph +from pyams_content.component.paragraph.zmi.interfaces import IParagraphInnerEditor from pyams_i18n.interfaces import II18n from pyams_skin.interfaces import IInnerPage, IPageHeader from pyams_skin.layer import IPyAMSLayer @@ -35,11 +37,12 @@ from pyams_form.security import ProtectedFormObjectMixin from pyams_pagelet.pagelet import pagelet_config from pyams_skin.page import DefaultPageHeaderAdapter -from pyams_skin.table import BaseTable, I18nColumn, TrashColumn, ActionColumn +from pyams_skin.table import BaseTable, I18nColumn, TrashColumn, ActionColumn, JsActionColumn from pyams_skin.viewlet.menu import MenuItem from pyams_template.template import template_config -from pyams_utils.adapter import adapter_config, ContextRequestViewAdapter +from pyams_utils.adapter import adapter_config, ContextRequestViewAdapter, ContextAdapter from pyams_utils.url import absolute_url +from pyramid.exceptions import NotFound from pyramid.view import view_config from pyams_viewlet.viewlet import viewlet_config from pyams_zmi.view import AdminView @@ -64,7 +67,8 @@ # Paragraphs container view # -@pagelet_config(name='paragraphs.html', context=IParagraphContainerTarget, layer=IPyAMSLayer, permission=VIEW_SYSTEM_PERMISSION) +@pagelet_config(name='paragraphs.html', context=IParagraphContainerTarget, layer=IPyAMSLayer, + permission=VIEW_SYSTEM_PERMISSION) @template_config(template='templates/container.pt', layer=IPyAMSLayer) @implementer(IInnerPage) class ParagraphContainerView(AdminView): @@ -103,10 +107,12 @@ @property def data_attributes(self): attributes = super(ParagraphContainerTable, self).data_attributes - del attributes['tr']['data-ams-url'] - del attributes['tr']['data-toggle'] attributes['table'] = {'id': self.id, + 'data-ams-plugins': 'pyams_content', + 'data-ams-plugin-pyams_content-src': + '/--static--/pyams_content/js/pyams_content{MyAMS.devext}.js', 'data-ams-location': absolute_url(IParagraphContainer(self.context), self.request), + 'data-ams-tablednd-drag-handle': 'td.sorter', 'data-ams-tablednd-drop-target': 'set-paragraphs-order.json'} return attributes @@ -121,19 +127,58 @@ return super(ParagraphContainerTable, self).render() -@adapter_config(name='properties', context=(IParagraphContainerTarget, IPyAMSLayer, ParagraphContainerTable), +@adapter_config(name='sorter', context=(IParagraphContainerTarget, IPyAMSLayer, ParagraphContainerTable), provides=IColumn) -class ParagraphContainerPropertiesColumn(ActionColumn): - """Paragraphs container properties column""" +class ParagraphContainerSorterColumn(ProtectedFormObjectMixin, ActionColumn): + """Paragraphs container sorter column""" + + cssClasses = {'th': 'action', + 'td': 'action sorter'} + + icon_class = 'fa fa-fw fa-sort' + icon_hint = _("Click and drag to sort paragraphs...") + + url = '#' + weight = 1 - icon_class = 'fa fa-fw fa-edit' - icon_hint = _("Paragraph properties") + def get_url(self, item): + return '#' + - url = 'properties.html' - modal_target = True +@adapter_config(name='show-hide', context=(IParagraphContainerTarget, IPyAMSLayer, ParagraphContainerTable), + provides=IColumn) +class ParagraphContainerShowHideColumn(ProtectedFormObjectMixin, JsActionColumn): + """Paragraphs container visibility switcher column""" + + cssClasses = {'th': 'action', + 'td': 'action switcher'} + + icon_class = 'fa fa-fw fa-eye' + icon_hint = _("Switch paragraph visibility") + + url = 'PyAMS_content.paragraphs.switchVisibility' weight = 5 + def get_icon(self, item): + if item.visible: + icon_class = 'fa fa-fw fa-eye' + else: + icon_class = 'fa fa-fw fa-eye-slash text-danger' + return ''.format(icon_class=icon_class) + + def renderCell(self, item): + if self.permission and not self.request.has_permission(self.permission, context=item): + return self.get_icon(item) + else: + return super(ParagraphContainerShowHideColumn, self).renderCell(item) + + +@adapter_config(context=ParagraphContainerShowHideColumn, provides=IFormSecurityContext) +def ShowHideColumnSecurityContextFactory(column): + """Show/hide column security context factory""" + return column.table.context + @adapter_config(name='files', context=(IParagraphContainerTarget, IPyAMSLayer, ParagraphContainerTable), provides=IColumn) @@ -143,6 +188,8 @@ icon_class = 'fa fa-fw fa-file-text-o' icon_hint = _("External files") + cssClasses = {'td': 'action extfiles nowrap'} + url = 'extfile-links.html' modal_target = True @@ -151,7 +198,14 @@ def renderCell(self, item): if not IExtFileLinksContainerTarget.providedBy(item): return '' - return super(ParagraphContainerExtFileLinksColumn, self).renderCell(item) + action = '{action} {{count}}'.format( + action=super(ParagraphContainerExtFileLinksColumn, self).renderCell(item)) + length = len(IExtFileLinksContainer(item).files or ()) + if length: + action = action.format(count='({0})'.format(length)) + else: + action = action.format(count='') + return action @adapter_config(name='links', context=(IParagraphContainerTarget, IPyAMSLayer, ParagraphContainerTable), @@ -162,6 +216,8 @@ icon_class = 'fa fa-fw fa-link' icon_hint = _("Useful links") + cssClasses = {'td': 'action links nowrap'} + url = 'link-links.html' modal_target = True @@ -170,7 +226,14 @@ def renderCell(self, item): if not ILinkLinksContainerTarget.providedBy(item): return '' - return super(ParagraphContainerLinkLinksColumn, self).renderCell(item) + action = '{action} {{count}}'.format( + action=super(ParagraphContainerLinkLinksColumn, self).renderCell(item)) + length = len(ILinkLinksContainer(item).links or ()) + if length: + action = action.format(count='({0})'.format(length)) + else: + action = action.format(count='') + return action @adapter_config(name='gallery', context=(IParagraphContainerTarget, IPyAMSLayer, ParagraphContainerTable), @@ -181,6 +244,8 @@ icon_class = 'fa fa-fw fa-picture-o' icon_hint = _("Images galleries") + cssClasses = {'td': 'action galleries nowrap'} + url = 'gallery-links.html' modal_target = True @@ -189,7 +254,14 @@ def renderCell(self, item): if not IGalleryLinksContainerTarget.providedBy(item): return '' - return super(ParagraphContainerGalleryLinksColumn, self).renderCell(item) + action = '{action} {{count}}'.format( + action=super(ParagraphContainerGalleryLinksColumn, self).renderCell(item)) + length = len(IGalleryLinksContainer(item).galleries or ()) + if length: + action = action.format(count='({0})'.format(length)) + else: + action = action.format(count='') + return action @adapter_config(name='name', context=(IParagraphContainerTarget, IPyAMSLayer, ParagraphContainerTable), @@ -201,6 +273,25 @@ weight = 50 + def renderHeadCell(self): + return '' \ + ' ' \ + ' '.format( + title=self.request.localizer.translate(_("Click to open/close all paragraphs editors"))) + \ + super(ParagraphContainerTitleColumn, self).renderHeadCell() + + def renderCell(self, item): + return '
' \ + ' ' \ + ' '.format( + title=self.request.localizer.translate(_("Click to open/close paragraph editor"))) + \ + '{0}'.format(super(ParagraphContainerTitleColumn, self).renderCell(item)) + \ + '
' + def getValue(self, obj): return II18n(obj).query_attribute('title', request=self.request) or '--' @@ -237,3 +328,50 @@ order = list(map(str, json.loads(request.params.get('names')))) container.updateOrder(order) return {'status': 'success'} + + +@view_config(name='set-paragraph-visibility.json', context=IParagraphContainer, request_type=IPyAMSLayer, + permission=MANAGE_CONTENT_PERMISSION, renderer='json', xhr=True) +def set_paragraph_visibility(request): + """Set paragraph visibility""" + container = IParagraphContainer(request.context) + paragraph = container.get(str(request.params.get('object_name'))) + if paragraph is None: + raise NotFound() + paragraph = IBaseParagraph(paragraph) + paragraph.visible = not paragraph.visible + return {'visible': paragraph.visible} + + +@view_config(name='get-paragraph-editor.json', context=IParagraphContainer, request_type=IPyAMSLayer, + permission=VIEW_SYSTEM_PERMISSION, renderer='json', xhr=True) +def get_paragraph_editor(request): + """Get paragraph editor""" + container = IParagraphContainer(request.context) + paragraph = container.get(str(request.params.get('object_name'))) + if paragraph is None: + raise NotFound() + registry = request.registry + editor = registry.queryMultiAdapter((paragraph, request), IParagraphInnerEditor) + if editor is None: + editor = registry.queryAdapter(paragraph, IParagraphInnerEditor) + if editor is not None: + editor.update() + return editor.render() + + +@view_config(name='get-paragraphs-editors.json', context=IParagraphContainer, request_type=IPyAMSLayer, + permission=VIEW_SYSTEM_PERMISSION, renderer='json', xhr=True) +def get_paragraphs_editors(request): + """Get all paragraphs inner editors""" + container = IParagraphContainer(request.context) + registry = request.registry + result = {} + for key, paragraph in container.items(): + editor = registry.queryMultiAdapter((paragraph, request), IParagraphInnerEditor) + if editor is None: + editor = registry.queryAdapter(paragraph, IParagraphInnerEditor) + if editor is not None: + editor.update() + result[key] = editor.render() + return result diff -r b952eda9bb42 -r cbc55162b64e src/pyams_content/component/paragraph/zmi/html.py --- a/src/pyams_content/component/paragraph/zmi/html.py Thu Oct 15 15:42:01 2015 +0200 +++ b/src/pyams_content/component/paragraph/zmi/html.py Mon Jan 18 16:08:07 2016 +0100 @@ -9,8 +9,6 @@ # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # -from pyams_content.interfaces import MANAGE_CONTENT_PERMISSION -from pyams_template.template import template_config, ViewTemplate, get_view_template __docformat__ = 'restructuredtext' @@ -19,25 +17,32 @@ # import interfaces from pyams_content.component.paragraph.interfaces import IParagraphContainerTarget, IHTMLParagraph, \ - IParagraphContainer, IBaseParagraph, IParagraphSummary + IParagraphContainer, IParagraphSummary +from pyams_content.component.paragraph.zmi.interfaces import IParagraphInnerEditor +from pyams_content.interfaces import MANAGE_CONTENT_PERMISSION from pyams_content.shared.common.interfaces import IWfSharedContent +from pyams_form.interfaces.form import IInnerForm, IEditFormButtons from pyams_i18n.interfaces import II18n from pyams_skin.interfaces.viewlet import IToolbarAddingMenu from pyams_skin.layer import IPyAMSLayer +from z3c.form.interfaces import INPUT_MODE # import packages from pyams_content.component.paragraph.html import HTMLParagraph +from pyams_content.component.paragraph.zmi import BaseParagraphAJAXEditForm from pyams_content.component.paragraph.zmi.container import ParagraphContainerView -from pyams_form.form import AJAXAddForm, AJAXEditForm +from pyams_form.form import AJAXAddForm from pyams_form.security import ProtectedFormObjectMixin from pyams_pagelet.pagelet import pagelet_config from pyams_skin.viewlet.toolbar import ToolbarMenuItem +from pyams_template.template import template_config, get_view_template from pyams_utils.adapter import adapter_config, ContextRequestAdapter from pyams_utils.traversing import get_parent -from pyams_viewlet.viewlet import viewlet_config, ContentProvider +from pyams_viewlet.viewlet import viewlet_config from pyams_zmi.form import AdminDialogAddForm, AdminDialogEditForm from pyramid.view import view_config -from z3c.form import field +from z3c.form import field, button +from zope.interface import implementer from pyams_content import _ @@ -111,25 +116,38 @@ fields = field.Fields(IHTMLParagraph).omit('__parent__', '__name__') ajax_handler = 'properties.json' - edit_permission = 'pyams.ManageContent' + edit_permission = MANAGE_CONTENT_PERMISSION def updateWidgets(self, prefix=None): super(HTMLParagraphPropertiesEditForm, self).updateWidgets(prefix) + for lang in self.widgets['body'].langs: + widget = self.widgets['body'].widgets[lang] + widget.id = '{id}_{name}'.format(id=widget.id, name=self.context.__name__) self.widgets['body'].label_css_class = 'textarea' +@adapter_config(context=(IHTMLParagraph, IPyAMSLayer), provides=IParagraphInnerEditor) +@implementer(IInnerForm) +class HTMLParagraphInnerEditForm(HTMLParagraphPropertiesEditForm): + """HTML paragraph inner edit form""" + + legend = None + main_group_legend = _("HTML paragraph properties") + main_group_class = 'inner' + + @property + def buttons(self): + if self.mode == INPUT_MODE: + return button.Buttons(IEditFormButtons) + else: + return button.Buttons() + + @view_config(name='properties.json', context=IHTMLParagraph, request_type=IPyAMSLayer, permission=MANAGE_CONTENT_PERMISSION, renderer='json', xhr=True) -class HTMLParagraphPropertiesAJAXEditForm(AJAXEditForm, HTMLParagraphPropertiesEditForm): +class HTMLParagraphPropertiesAJAXEditForm(BaseParagraphAJAXEditForm, HTMLParagraphPropertiesEditForm): """HTML paragraph properties edit form, JSON renderer""" - def get_ajax_output(self, changes): - if 'title' in changes.get(IBaseParagraph, ()): - return {'status': 'reload', - 'location': '#paragraphs.html'} - else: - return super(HTMLParagraphPropertiesAJAXEditForm, self).get_ajax_output(changes) - # # HTML paragraph summary diff -r b952eda9bb42 -r cbc55162b64e src/pyams_content/component/paragraph/zmi/illustration.py --- a/src/pyams_content/component/paragraph/zmi/illustration.py Thu Oct 15 15:42:01 2015 +0200 +++ b/src/pyams_content/component/paragraph/zmi/illustration.py Mon Jan 18 16:08:07 2016 +0100 @@ -9,25 +9,6 @@ # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # -from pyramid.view import view_config -from pyams_content.component.paragraph.illustration import Illustration -from pyams_content.component.paragraph.interfaces import IParagraphContainerTarget, IIllustrationParagraph, \ - IParagraphContainer, IBaseParagraph, IParagraphSummary, IIllustrationRenderer -from pyams_content.component.paragraph.zmi.container import ParagraphContainerView -from pyams_content.interfaces import MANAGE_CONTENT_PERMISSION -from pyams_content.shared.common.interfaces import IWfSharedContent -from pyams_form.form import AJAXAddForm, AJAXEditForm -from pyams_form.security import ProtectedFormObjectMixin -from pyams_i18n.interfaces import II18n -from pyams_pagelet.pagelet import pagelet_config -from pyams_skin.interfaces.viewlet import IToolbarAddingMenu -from pyams_skin.layer import IPyAMSLayer -from pyams_skin.viewlet.toolbar import ToolbarMenuItem -from pyams_template.template import template_config, get_view_template -from pyams_utils.adapter import ContextRequestAdapter, adapter_config -from pyams_utils.traversing import get_parent -from pyams_viewlet.viewlet import viewlet_config -from pyams_zmi.form import AdminDialogAddForm, AdminDialogEditForm __docformat__ = 'restructuredtext' @@ -35,9 +16,33 @@ # import standard library # import interfaces +from pyams_content.component.paragraph.interfaces import IParagraphContainerTarget, IIllustrationParagraph, \ + IParagraphContainer, IParagraphSummary, IIllustrationRenderer +from pyams_content.component.paragraph.zmi.interfaces import IParagraphInnerEditor +from pyams_content.interfaces import MANAGE_CONTENT_PERMISSION +from pyams_content.shared.common.interfaces import IWfSharedContent +from pyams_form.interfaces.form import IInnerForm, IEditFormButtons +from pyams_i18n.interfaces import II18n +from pyams_skin.interfaces.viewlet import IToolbarAddingMenu +from pyams_skin.layer import IPyAMSLayer +from z3c.form.interfaces import INPUT_MODE # import packages -from z3c.form import field +from pyams_content.component.paragraph.illustration import Illustration +from pyams_content.component.paragraph.zmi import BaseParagraphAJAXEditForm +from pyams_content.component.paragraph.zmi.container import ParagraphContainerView +from pyams_form.form import AJAXAddForm +from pyams_form.security import ProtectedFormObjectMixin +from pyams_pagelet.pagelet import pagelet_config +from pyams_skin.viewlet.toolbar import ToolbarMenuItem +from pyams_template.template import template_config, get_view_template +from pyams_utils.adapter import ContextRequestAdapter, adapter_config +from pyams_utils.traversing import get_parent +from pyams_viewlet.viewlet import viewlet_config +from pyams_zmi.form import AdminDialogAddForm, AdminDialogEditForm +from pyramid.view import view_config +from z3c.form import field, button +from zope.interface import implementer from pyams_content import _ @@ -106,18 +111,28 @@ edit_permission = MANAGE_CONTENT_PERMISSION +@adapter_config(context=(IIllustrationParagraph, IPyAMSLayer), provides=IParagraphInnerEditor) +@implementer(IInnerForm) +class IllustrationInnerEditForm(IllustrationPropertiesEditForm): + """Illustration inner edit form""" + + legend = None + main_group_legend = _("Illustration properties") + main_group_class = 'inner' + + @property + def buttons(self): + if self.mode == INPUT_MODE: + return button.Buttons(IEditFormButtons) + else: + return button.Buttons() + + @view_config(name='properties.json', context=IIllustrationParagraph, request_type=IPyAMSLayer, permission=MANAGE_CONTENT_PERMISSION, renderer='json', xhr=True) -class IllustrationPropertiesAJAXEditForm(AJAXEditForm, IllustrationPropertiesEditForm): +class IllustrationPropertiesAJAXEditForm(BaseParagraphAJAXEditForm, IllustrationPropertiesEditForm): """HTML paragraph properties edit form, JSON renderer""" - def get_ajax_output(self, changes): - if 'title' in changes.get(IBaseParagraph, ()): - return {'status': 'reload', - 'location': '#paragraphs.html'} - else: - return super(IllustrationPropertiesAJAXEditForm, self).get_ajax_output(changes) - # # Illustration summary diff -r b952eda9bb42 -r cbc55162b64e src/pyams_content/component/paragraph/zmi/interfaces.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_content/component/paragraph/zmi/interfaces.py Mon Jan 18 16:08:07 2016 +0100 @@ -0,0 +1,25 @@ +# +# Copyright (c) 2008-2015 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 standard library + +# import interfaces +from pyams_form.interfaces.form import IInnerForm + +# import packages + + +class IParagraphInnerEditor(IInnerForm): + """Paragraph inner editor form interface""" diff -r b952eda9bb42 -r cbc55162b64e src/pyams_content/component/paragraph/zmi/summary.py --- a/src/pyams_content/component/paragraph/zmi/summary.py Thu Oct 15 15:42:01 2015 +0200 +++ b/src/pyams_content/component/paragraph/zmi/summary.py Mon Jan 18 16:08:07 2016 +0100 @@ -9,18 +9,6 @@ # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # -from pyams_content.component.paragraph.interfaces import IParagraphContainerTarget, IParagraphContainer, \ - IParagraphSummary -from pyams_content.shared.common.interfaces.zmi import IInnerSummaryView -from pyams_content.shared.common.zmi.summary import SharedContentSummaryForm -from pyams_form.form import InnerDisplayForm -from pyams_form.interfaces.form import IInnerTabForm -from pyams_i18n.interfaces import II18nManager -from pyams_pagelet.pagelet import pagelet_config -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 __docformat__ = 'restructuredtext' @@ -28,8 +16,20 @@ # import standard library # import interfaces +from pyams_content.component.paragraph.interfaces import IParagraphContainerTarget, IParagraphContainer, \ + IParagraphSummary +from pyams_content.shared.common.interfaces.zmi import IInnerSummaryView +from pyams_form.interfaces.form import IInnerTabForm +from pyams_i18n.interfaces import II18nManager +from pyams_skin.layer import IPyAMSLayer # import packages +from pyams_content.shared.common.zmi.summary import SharedContentSummaryForm +from pyams_pagelet.pagelet import pagelet_config +from pyams_template.template import template_config +from pyams_utils.adapter import adapter_config +from pyams_utils.interfaces import VIEW_SYSTEM_PERMISSION +from pyams_zmi.form import InnerAdminDisplayForm from z3c.form import field from zope.interface import implementer, Interface @@ -39,7 +39,7 @@ @adapter_config(name='paragraphs-summary', context=(IParagraphContainerTarget, IPyAMSLayer, SharedContentSummaryForm), provides=IInnerTabForm) -class ParagraphsContainerSummary(InnerDisplayForm): +class ParagraphsContainerSummary(InnerAdminDisplayForm): """Paragraphs container summary""" weight = 20 diff -r b952eda9bb42 -r cbc55162b64e src/pyams_content/component/theme/interfaces/__init__.py --- a/src/pyams_content/component/theme/interfaces/__init__.py Thu Oct 15 15:42:01 2015 +0200 +++ b/src/pyams_content/component/theme/interfaces/__init__.py Mon Jan 18 16:08:07 2016 +0100 @@ -46,3 +46,14 @@ class IThemesTarget(Interface): """Themes target interface""" + + +PORTLET_SETTINGS_THEMES_KEY = 'pyams_content.themes.settings' + + +class IPortletThemesSettings(Interface): + """Interface for portlet settings managing themes""" + + +class IPortletThemesSettingsTarget(Interface): + """Marker interface for portlet settings managing themes""" diff -r b952eda9bb42 -r cbc55162b64e src/pyams_content/component/theme/portlet.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_content/component/theme/portlet.py Mon Jan 18 16:08:07 2016 +0100 @@ -0,0 +1,53 @@ +# +# Copyright (c) 2008-2015 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 standard library + +# import interfaces +from pyams_content.component.theme.interfaces import IPortletThemesSettings, IPortletThemesSettingsTarget, \ + PORTLET_SETTINGS_THEMES_KEY +from zope.annotation.interfaces import IAnnotations +from zope.traversing.interfaces import ITraversable + +# import packages +from persistent import Persistent +from pyams_utils.adapter import adapter_config, ContextAdapter +from zope.container.contained import Contained +from zope.interface import implementer +from zope.location import locate + + +@implementer(IPortletThemesSettings) +class PortletThemesSettings(Persistent, Contained): + """Portlet themes settings""" + + +@adapter_config(context=IPortletThemesSettingsTarget, provides=IPortletThemesSettings) +def PortletThemesSettingsFactory(context): + """Portlet themes settings adapter""" + annotations = IAnnotations(context) + settings = annotations.get(PORTLET_SETTINGS_THEMES_KEY) + if settings is None: + settings = annotations[PORTLET_SETTINGS_THEMES_KEY] = PortletThemesSettings() + locate(settings, context, '++themes++') + return settings + + +@adapter_config(name='themes', context=IPortletThemesSettingsTarget, provides=ITraversable) +class ThemesPortletsSettingsTraverser(ContextAdapter): + """++themes++ portlet settings adapter""" + + def traverse(self, name, furtherpath=None): + return IPortletThemesSettings(self.context) diff -r b952eda9bb42 -r cbc55162b64e src/pyams_content/component/theme/zmi/portlet.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_content/component/theme/zmi/portlet.py Mon Jan 18 16:08:07 2016 +0100 @@ -0,0 +1,44 @@ +# +# Copyright (c) 2008-2015 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 standard library + +# import interfaces +from pyams_content.component.theme.interfaces import IPortletThemesSettingsTarget +from pyams_form.interfaces.form import IInnerTabForm +from pyams_skin.layer import IPyAMSLayer + +# import packages +from pyams_portal.zmi.portlet import PortletSettingsEditor +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='themes', context=(IPortletThemesSettingsTarget, IPyAMSLayer, PortletSettingsEditor), + provides=IInnerTabForm) +class PortletSettingsThemesEditor(InnerAdminEditForm): + """Portlet settings for themes""" + + id = 'themes_form' + tab_label = _("Themes") + legend = None + + fields = field.Fields(Interface) + + weight = 50