src/pyams_content/component/paragraph/zmi/container.py
changeset 0 7c0001cacf8e
child 7 cbc55162b64e
equal deleted inserted replaced
-1:000000000000 0:7c0001cacf8e
       
     1 #
       
     2 # Copyright (c) 2008-2015 Thierry Florac <tflorac AT ulthar.net>
       
     3 # All Rights Reserved.
       
     4 #
       
     5 # This software is subject to the provisions of the Zope Public License,
       
     6 # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
       
     7 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
       
     8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
       
     9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
       
    10 # FOR A PARTICULAR PURPOSE.
       
    11 #
       
    12 
       
    13 __docformat__ = 'restructuredtext'
       
    14 
       
    15 
       
    16 # import standard library
       
    17 import json
       
    18 
       
    19 # import interfaces
       
    20 from pyams_content.interfaces import MANAGE_CONTENT_PERMISSION
       
    21 from pyams_content.component.extfile.interfaces import IExtFileLinksContainerTarget
       
    22 from pyams_content.component.gallery.interfaces import IGalleryLinksContainerTarget
       
    23 from pyams_content.component.links.interfaces import ILinkLinksContainerTarget
       
    24 from pyams_content.component.paragraph.interfaces import IParagraphContainerTarget, IParagraphContainer
       
    25 from pyams_i18n.interfaces import II18n
       
    26 from pyams_skin.interfaces import IInnerPage, IPageHeader
       
    27 from pyams_skin.layer import IPyAMSLayer
       
    28 from pyams_utils.interfaces import VIEW_SYSTEM_PERMISSION
       
    29 from pyams_zmi.interfaces.menu import IPropertiesMenu
       
    30 from pyams_zmi.layer import IAdminLayer
       
    31 from z3c.table.interfaces import IColumn, IValues
       
    32 
       
    33 # import packages
       
    34 from pyams_content.shared.common.zmi import WfModifiedContentColumnMixin
       
    35 from pyams_form.security import ProtectedFormObjectMixin
       
    36 from pyams_pagelet.pagelet import pagelet_config
       
    37 from pyams_skin.page import DefaultPageHeaderAdapter
       
    38 from pyams_skin.table import BaseTable, I18nColumn, TrashColumn, ActionColumn
       
    39 from pyams_skin.viewlet.menu import MenuItem
       
    40 from pyams_template.template import template_config
       
    41 from pyams_utils.adapter import adapter_config, ContextRequestViewAdapter
       
    42 from pyams_utils.url import absolute_url
       
    43 from pyramid.view import view_config
       
    44 from pyams_viewlet.viewlet import viewlet_config
       
    45 from pyams_zmi.view import AdminView
       
    46 from pyramid.decorator import reify
       
    47 from z3c.table.column import GetAttrColumn
       
    48 from zope.interface import implementer
       
    49 
       
    50 from pyams_content import _
       
    51 
       
    52 
       
    53 @viewlet_config(name='paragraphs.menu', context=IParagraphContainerTarget, layer=IAdminLayer,
       
    54                 manager=IPropertiesMenu, permission=VIEW_SYSTEM_PERMISSION, weight=100)
       
    55 class ParagraphsContainerMenu(MenuItem):
       
    56     """Paragraphs container menu"""
       
    57 
       
    58     label = _("Paragraphs...")
       
    59     icon_class = 'fa-paragraph'
       
    60     url = '#paragraphs.html'
       
    61 
       
    62 
       
    63 #
       
    64 # Paragraphs container view
       
    65 #
       
    66 
       
    67 @pagelet_config(name='paragraphs.html', context=IParagraphContainerTarget, layer=IPyAMSLayer, permission=VIEW_SYSTEM_PERMISSION)
       
    68 @template_config(template='templates/container.pt', layer=IPyAMSLayer)
       
    69 @implementer(IInnerPage)
       
    70 class ParagraphContainerView(AdminView):
       
    71     """Paragraphs container view"""
       
    72 
       
    73     title = _("Paragraphs list")
       
    74 
       
    75     def __init__(self, context, request):
       
    76         super(ParagraphContainerView, self).__init__(context, request)
       
    77         self.table = ParagraphContainerTable(context, request, self)
       
    78 
       
    79     def update(self):
       
    80         super(ParagraphContainerView, self).update()
       
    81         self.table.update()
       
    82 
       
    83 
       
    84 class ParagraphContainerTable(ProtectedFormObjectMixin, BaseTable):
       
    85     """Paragraphs container table"""
       
    86 
       
    87     id = 'paragraphs_list'
       
    88     hide_header = True
       
    89     sortOn = None
       
    90 
       
    91     def __init__(self, context, request, view):
       
    92         super(ParagraphContainerTable, self).__init__(context, request)
       
    93         self.view = view
       
    94 
       
    95     @property
       
    96     def cssClasses(self):
       
    97         classes = ['table', 'table-bordered', 'table-striped', 'table-hover', 'table-tight']
       
    98         permission = self.permission
       
    99         if (not permission) or self.request.has_permission(permission, self.context):
       
   100             classes.append('table-dnd')
       
   101         return {'table': ' '.join(classes)}
       
   102 
       
   103     @property
       
   104     def data_attributes(self):
       
   105         attributes = super(ParagraphContainerTable, self).data_attributes
       
   106         del attributes['tr']['data-ams-url']
       
   107         del attributes['tr']['data-toggle']
       
   108         attributes['table'] = {'id': self.id,
       
   109                                'data-ams-location': absolute_url(IParagraphContainer(self.context), self.request),
       
   110                                'data-ams-tablednd-drop-target': 'set-paragraphs-order.json'}
       
   111         return attributes
       
   112 
       
   113     @reify
       
   114     def values(self):
       
   115         return list(super(ParagraphContainerTable, self).values)
       
   116 
       
   117     def render(self):
       
   118         if not self.values:
       
   119             translate = self.request.localizer.translate
       
   120             return translate(_("No currently defined paragraph."))
       
   121         return super(ParagraphContainerTable, self).render()
       
   122 
       
   123 
       
   124 @adapter_config(name='properties', context=(IParagraphContainerTarget, IPyAMSLayer, ParagraphContainerTable),
       
   125                 provides=IColumn)
       
   126 class ParagraphContainerPropertiesColumn(ActionColumn):
       
   127     """Paragraphs container properties column"""
       
   128 
       
   129     icon_class = 'fa fa-fw fa-edit'
       
   130     icon_hint = _("Paragraph properties")
       
   131 
       
   132     url = 'properties.html'
       
   133     modal_target = True
       
   134 
       
   135     weight = 5
       
   136 
       
   137 
       
   138 @adapter_config(name='files', context=(IParagraphContainerTarget, IPyAMSLayer, ParagraphContainerTable),
       
   139                 provides=IColumn)
       
   140 class ParagraphContainerExtFileLinksColumn(ActionColumn):
       
   141     """Paragraphs container external files links column"""
       
   142 
       
   143     icon_class = 'fa fa-fw fa-file-text-o'
       
   144     icon_hint = _("External files")
       
   145 
       
   146     url = 'extfile-links.html'
       
   147     modal_target = True
       
   148 
       
   149     weight = 10
       
   150 
       
   151     def renderCell(self, item):
       
   152         if not IExtFileLinksContainerTarget.providedBy(item):
       
   153             return ''
       
   154         return super(ParagraphContainerExtFileLinksColumn, self).renderCell(item)
       
   155 
       
   156 
       
   157 @adapter_config(name='links', context=(IParagraphContainerTarget, IPyAMSLayer, ParagraphContainerTable),
       
   158                 provides=IColumn)
       
   159 class ParagraphContainerLinkLinksColumn(ActionColumn):
       
   160     """Paragraphs container links links column"""
       
   161 
       
   162     icon_class = 'fa fa-fw fa-link'
       
   163     icon_hint = _("Useful links")
       
   164 
       
   165     url = 'link-links.html'
       
   166     modal_target = True
       
   167 
       
   168     weight = 15
       
   169 
       
   170     def renderCell(self, item):
       
   171         if not ILinkLinksContainerTarget.providedBy(item):
       
   172             return ''
       
   173         return super(ParagraphContainerLinkLinksColumn, self).renderCell(item)
       
   174 
       
   175 
       
   176 @adapter_config(name='gallery', context=(IParagraphContainerTarget, IPyAMSLayer, ParagraphContainerTable),
       
   177                 provides=IColumn)
       
   178 class ParagraphContainerGalleryLinksColumn(ActionColumn):
       
   179     """Paragraphs container gallery links column"""
       
   180 
       
   181     icon_class = 'fa fa-fw fa-picture-o'
       
   182     icon_hint = _("Images galleries")
       
   183 
       
   184     url = 'gallery-links.html'
       
   185     modal_target = True
       
   186 
       
   187     weight = 20
       
   188 
       
   189     def renderCell(self, item):
       
   190         if not IGalleryLinksContainerTarget.providedBy(item):
       
   191             return ''
       
   192         return super(ParagraphContainerGalleryLinksColumn, self).renderCell(item)
       
   193 
       
   194 
       
   195 @adapter_config(name='name', context=(IParagraphContainerTarget, IPyAMSLayer, ParagraphContainerTable),
       
   196                 provides=IColumn)
       
   197 class ParagraphContainerTitleColumn(I18nColumn, WfModifiedContentColumnMixin, GetAttrColumn):
       
   198     """Paragraph container title column"""
       
   199 
       
   200     _header = _("Title")
       
   201 
       
   202     weight = 50
       
   203 
       
   204     def getValue(self, obj):
       
   205         return II18n(obj).query_attribute('title', request=self.request) or '--'
       
   206 
       
   207 
       
   208 @adapter_config(name='trash', context=(IParagraphContainerTarget, IPyAMSLayer, ParagraphContainerTable),
       
   209                 provides=IColumn)
       
   210 class ParagraphContainerTrashColumn(ProtectedFormObjectMixin, TrashColumn):
       
   211     """Paragraphs container trash column"""
       
   212 
       
   213 
       
   214 @adapter_config(context=(IParagraphContainerTarget, IPyAMSLayer, ParagraphContainerTable), provides=IValues)
       
   215 class ParagraphContainerValues(ContextRequestViewAdapter):
       
   216     """Paragraphs container values"""
       
   217 
       
   218     @property
       
   219     def values(self):
       
   220         return IParagraphContainer(self.context).values()
       
   221 
       
   222 
       
   223 @adapter_config(context=(IParagraphContainerTarget, IPyAMSLayer, ParagraphContainerView), provides=IPageHeader)
       
   224 class ParagraphHeaderAdapter(DefaultPageHeaderAdapter):
       
   225     """Paragraphs container header adapter"""
       
   226 
       
   227     back_url = '#properties.html'
       
   228 
       
   229     icon_class = 'fa fa-fw fa-paragraph'
       
   230 
       
   231 
       
   232 @view_config(name='set-paragraphs-order.json', context=IParagraphContainerTarget, request_type=IPyAMSLayer,
       
   233              permission=MANAGE_CONTENT_PERMISSION, renderer='json', xhr=True)
       
   234 def set_paragraphs_order(request):
       
   235     """Update paragraphs order"""
       
   236     container = IParagraphContainer(request.context)
       
   237     order = list(map(str, json.loads(request.params.get('names'))))
       
   238     container.updateOrder(order)
       
   239     return {'status': 'success'}