--- a/src/pyams_content/component/paragraph/zmi/container.py Mon Sep 11 14:53:15 2017 +0200
+++ b/src/pyams_content/component/paragraph/zmi/container.py Mon Sep 11 14:54:30 2017 +0200
@@ -9,6 +9,7 @@
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
+from pyams_content.component.association.zmi import AssociationsContainerView
__docformat__ = 'restructuredtext'
@@ -18,9 +19,9 @@
# import interfaces
from pyams_content.interfaces import MANAGE_CONTENT_PERMISSION
-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.association.interfaces import IAssociationContainer
+from pyams_content.component.extfile.interfaces import IExtFileContainerTarget, IExtFile
+from pyams_content.component.links.interfaces import ILinkContainerTarget, IBaseLink
from pyams_content.component.paragraph.interfaces import IParagraphContainerTarget, IParagraphContainer, IBaseParagraph
from pyams_content.component.paragraph.zmi.interfaces import IParagraphInnerEditor, IParagraphTitleToolbar
from pyams_form.interfaces.form import IFormSecurityContext
@@ -38,7 +39,7 @@
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, JsActionColumn
+from pyams_skin.table import BaseTable, I18nColumn, TrashColumn, JsActionColumn, SorterColumn, ImageColumn
from pyams_skin.viewlet.menu import MenuItem
from pyams_template.template import template_config
from pyams_utils.adapter import adapter_config, ContextRequestViewAdapter
@@ -131,21 +132,9 @@
@adapter_config(name='sorter', context=(IParagraphContainerTarget, IPyAMSLayer, ParagraphContainerTable),
provides=IColumn)
-class ParagraphContainerSorterColumn(ProtectedFormObjectMixin, ActionColumn):
+class ParagraphContainerSorterColumn(ProtectedFormObjectMixin, SorterColumn):
"""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
-
- def get_url(self, item):
- return '#'
-
@adapter_config(name='show-hide', context=(IParagraphContainerTarget, IPyAMSLayer, ParagraphContainerTable),
provides=IColumn)
@@ -176,6 +165,20 @@
return super(ParagraphContainerShowHideColumn, self).renderCell(item)
+@adapter_config(name='pictogram', context=(IParagraphContainerTarget, IPyAMSLayer, ParagraphContainerTable),
+ provides=IColumn)
+class ParagraphContainerPictogramColumn(ImageColumn):
+ """Paragraph container pictogram column"""
+
+ weight = 6
+
+ def get_icon_class(self, item):
+ return item.icon_class
+
+ def get_icon_hint(self, item):
+ return self.request.localizer.translate(item.icon_hint)
+
+
@adapter_config(context=ParagraphContainerShowHideColumn, provides=IFormSecurityContext)
def ShowHideColumnSecurityContextFactory(column):
"""Show/hide column security context factory"""
@@ -190,58 +193,14 @@
"""Paragraph title toolbar viewlet manager"""
-@viewlet_config(name='files', context=IExtFileLinksContainerTarget, layer=IPyAMSLayer, view=ParagraphContainerTable,
- manager=IParagraphTitleToolbar, permission=VIEW_SYSTEM_PERMISSION, weight=10)
-@template_config(template='templates/paragraph-title-icon.pt', layer=IPyAMSLayer)
-class ParagraphContainerExtFileLinksAction(Viewlet):
- """Paragraph container external files links column"""
-
- action_class = 'action extfiles nowrap width-40'
- icon_class = 'fa fa-fw fa-file-text-o'
- icon_hint = _("External files")
-
- url = 'extfile-links.html'
- modal_target = True
-
- @property
- def count(self):
- return len(IExtFileLinksContainer(self.context).files or ())
-
-
-@viewlet_config(name='links', context=ILinkLinksContainerTarget, layer=IPyAMSLayer, view=ParagraphContainerTable,
- manager=IParagraphTitleToolbar, permission=VIEW_SYSTEM_PERMISSION, weight=20)
-@template_config(template='templates/paragraph-title-icon.pt', layer=IPyAMSLayer)
-class ParagraphContainerLinkLinksAction(Viewlet):
- """Paragraph container links links column"""
-
- action_class = 'action links nowrap width-40'
- icon_class = 'fa fa-fw fa-link'
- icon_hint = _("Useful links")
-
- url = 'link-links.html'
- modal_target = True
-
- @property
- def count(self):
- return len(ILinkLinksContainer(self.context).links or ())
-
-
-@viewlet_config(name='gallery', context=IGalleryLinksContainerTarget, layer=IPyAMSLayer, view=ParagraphContainerTable,
- manager=IParagraphTitleToolbar, permission=VIEW_SYSTEM_PERMISSION, weight=30)
-@template_config(template='templates/paragraph-title-icon.pt', layer=IPyAMSLayer)
-class ParagraphContainerGalleryLinksAction(Viewlet):
- """Paragraph container gallery links column"""
-
- action_class = 'action galleries nowrap width-40'
- icon_class = 'fa fa-fw fa-picture-o'
- icon_hint = _("Images galleries")
-
- url = 'gallery-links.html'
- modal_target = True
-
- @property
- def count(self):
- return len(IGalleryLinksContainer(self.context).galleries or ())
+def getParagraphTitleHints(item, request, table):
+ """Get paragraphs column title hints"""
+ registry = request.registry
+ provider = registry.queryMultiAdapter((item, request, table), IContentProvider,
+ name='pyams_paragraph.title_toolbar')
+ if provider is not None:
+ provider.update()
+ return provider.render()
@adapter_config(name='name', context=(IParagraphContainerTarget, IPyAMSLayer, ParagraphContainerTable),
@@ -249,7 +208,7 @@
class ParagraphContainerTitleColumn(I18nColumn, WfModifiedContentColumnMixin, GetAttrColumn):
"""Paragraph container title column"""
- _header = _("Title")
+ _header = _("Show/hide all paragraphs")
weight = 50
@@ -258,30 +217,24 @@
' data-ams-stop-propagation="true"' \
' data-ams-click-handler="PyAMS_content.paragraphs.switchAllEditors">' \
' <i class="fa fa-plus-square-o"></i>' \
- '</span> '.format(
+ '</span> '.format(
title=self.request.localizer.translate(_("Click to open/close all paragraphs editors"))) + \
super(ParagraphContainerTitleColumn, self).renderHeadCell()
def renderCell(self, item):
- registry = self.request.registry
- provider = registry.queryMultiAdapter((item, self.request, self.table), IContentProvider,
- name='pyams_paragraph.title_toolbar')
- if provider is not None:
- provider.update()
- provider = provider.render()
- else:
- provider = ''
+ provider = getParagraphTitleHints(item, self.request, self.table) or ''
return '<div>{provider}<span class="small hint" title="{title}" data-ams-hint-gravity="e"' \
' data-ams-stop-propagation="true" ' \
' data-ams-click-handler="PyAMS_content.paragraphs.switchEditor">' \
' <i class="fa fa-plus-square-o"></i>' \
- '</span> '.format(provider=provider,
- title=self.request.localizer.translate(_("Click to open/close paragraph editor"))) + \
+ '</span> '.format(
+ provider=provider,
+ title=self.request.localizer.translate(_("Click to open/close paragraph editor"))) + \
'<span class="title">{0}</span>'.format(super(ParagraphContainerTitleColumn, self).renderCell(item)) + \
'</div><div class="inner-table-form editor margin-x-10 margin-bottom-0"></div>'
def getValue(self, obj):
- return II18n(obj).query_attribute('title', request=self.request) or '--'
+ return II18n(obj).query_attribute('title', request=self.request) or ' - - - - - - - -'
@adapter_config(name='trash', context=(IParagraphContainerTarget, IPyAMSLayer, ParagraphContainerTable),
@@ -304,17 +257,47 @@
"""Paragraphs container header adapter"""
back_url = '#properties.html'
-
icon_class = 'fa fa-fw fa-paragraph'
-@view_config(name='set-paragraphs-order.json', context=IParagraphContainerTarget, request_type=IPyAMSLayer,
+@viewlet_config(name='links', context=ILinkContainerTarget, layer=IPyAMSLayer, view=ParagraphContainerTable,
+ manager=IParagraphTitleToolbar, permission=VIEW_SYSTEM_PERMISSION, weight=10)
+@template_config(template='templates/paragraph-title-icon.pt', layer=IPyAMSLayer)
+class ParagraphContainerLinksCounter(Viewlet):
+ """Paragraph container external links count column"""
+
+ action_class = 'action links nowrap width-40'
+ icon_class = 'fa fa-fw fa-link'
+ icon_hint = _("Links")
+
+ @property
+ def count(self):
+ return len([file for file in IAssociationContainer(self.context).values()
+ if IBaseLink.providedBy(file)])
+
+
+@viewlet_config(name='files', context=IExtFileContainerTarget, layer=IPyAMSLayer, view=ParagraphContainerTable,
+ manager=IParagraphTitleToolbar, permission=VIEW_SYSTEM_PERMISSION, weight=10)
+@template_config(template='templates/paragraph-title-icon.pt', layer=IPyAMSLayer)
+class ParagraphContainerExtFileCounter(Viewlet):
+ """Paragraph container external files count column"""
+
+ action_class = 'action extfiles nowrap width-40'
+ icon_class = 'fa fa-fw fa-file-text-o'
+ icon_hint = _("External files")
+
+ @property
+ def count(self):
+ return len([file for file in IAssociationContainer(self.context).values()
+ if IExtFile.providedBy(file)])
+
+
+@view_config(name='set-paragraphs-order.json', context=IParagraphContainer, request_type=IPyAMSLayer,
permission=MANAGE_CONTENT_PERMISSION, renderer='json', xhr=True)
def set_paragraphs_order(request):
"""Update paragraphs order"""
- container = IParagraphContainer(request.context)
order = list(map(str, json.loads(request.params.get('names'))))
- container.updateOrder(order)
+ request.context.updateOrder(order)
return {'status': 'success'}
@@ -363,3 +346,44 @@
editor.update()
result[key] = editor.render()
return result
+
+
+#
+# Paragraphs associations view
+#
+
+@viewlet_config(name='paragraphs-associations.menu', context=IParagraphContainerTarget, layer=IAdminLayer,
+ manager=IPropertiesMenu, permission=VIEW_SYSTEM_PERMISSION, weight=101)
+class ParagraphsAssociationsMenu(MenuItem):
+ """Paragraphs associations container menu"""
+
+ label = _("Associations...")
+ icon_class = 'fa-link'
+ url = '#paragraphs-associations.html'
+
+
+@pagelet_config(name='paragraphs-associations.html', context=IParagraphContainerTarget, layer=IPyAMSLayer,
+ permission=VIEW_SYSTEM_PERMISSION)
+@template_config(template='templates/associations.pt', layer=IPyAMSLayer)
+@implementer(IInnerPage)
+class ParagraphsAssociationsView(AdminView):
+ """Paragraphs associations view"""
+
+ title = _("Paragraphs associations")
+
+ @reify
+ def associations(self):
+ result = []
+ for paragraph in IParagraphContainer(self.context).values():
+ associations = IAssociationContainer(paragraph, None)
+ if associations is not None:
+ view = AssociationsContainerView(paragraph, self.request)
+ view.widget_icon_class = 'fa fa-fw {0}'.format(paragraph.icon_class)
+ view.title = II18n(paragraph).query_attribute('title', request=self.request) or ' - - - - - - - -'
+ result.append(view)
+ return result
+
+ def update(self):
+ super(ParagraphsAssociationsView, self).update()
+ for association in self.associations:
+ association.update()