src/pyams_content/shared/site/zmi/container.py
changeset 300 49e8f3cef75a
parent 294 8742c8ac126c
child 322 c28fc1fdcc3f
--- a/src/pyams_content/shared/site/zmi/container.py	Tue Nov 28 17:26:34 2017 +0100
+++ b/src/pyams_content/shared/site/zmi/container.py	Tue Nov 28 17:27:24 2017 +0100
@@ -17,13 +17,13 @@
 import json
 
 # import interfaces
-from pyams_content.interfaces import MANAGE_SITE_PERMISSION
-from pyams_content.shared.common.interfaces import ISharedContent
+from pyams_content.interfaces import MANAGE_SITE_PERMISSION, MANAGE_CONTENT_PERMISSION
+from pyams_content.shared.common.interfaces import ISharedContent, IWfSharedContent
 from pyams_content.shared.common.interfaces.zmi import IDashboardTable
-from pyams_content.shared.site.interfaces import ISiteContainer, ISiteManager
+from pyams_content.shared.site.interfaces import ISiteContainer, ISiteManager, IContentLink
 from pyams_content.zmi.interfaces import IUserAddingsMenuLabel, ISiteTreeMenu, ISiteTreeTable
 from pyams_i18n.interfaces import II18n
-from pyams_sequence.interfaces import ISequentialIdInfo
+from pyams_sequence.interfaces import ISequentialIdInfo, ISequentialIntIds
 from pyams_skin.interfaces import IInnerPage, IPageHeader
 from pyams_skin.interfaces.container import ITableElementEditor, ITableElementName, ITableWithActions
 from pyams_skin.interfaces.viewlet import IBreadcrumbItem, ITableItemColumnActionsMenu
@@ -43,7 +43,7 @@
 from pyams_skin.container import ContainerView
 from pyams_skin.page import DefaultPageHeaderAdapter
 from pyams_skin.table import BaseTable, TrashColumn, DefaultElementEditorAdapter, NameColumn, SorterColumn, \
-    ActionColumn, I18nColumn
+    I18nColumn, JsActionColumn
 from pyams_skin.viewlet.breadcrumb import BreadcrumbItem
 from pyams_skin.viewlet.menu import MenuItem
 from pyams_skin.viewlet.toolbar import ToolbarMenuItem
@@ -56,11 +56,13 @@
 from pyams_viewlet.viewlet import viewlet_config
 from pyams_zmi.form import AdminDialogEditForm
 from pyams_zmi.view import AdminView
+from pyramid.exceptions import NotFound
 from pyramid.location import lineage
 from pyramid.view import view_config
 from z3c.form import field
 from z3c.table.column import GetAttrColumn
 from zope.interface import implementer
+from zope.lifecycleevent import ObjectMovedEvent
 
 from pyams_content import _
 
@@ -236,7 +238,7 @@
 
 
 @adapter_config(name='visible', context=(ISiteContainer, IPyAMSLayer, ISiteTreeTable), provides=IColumn)
-class SiteContainerTreeVisibleColumn(ActionColumn):
+class SiteContainerTreeVisibleColumn(JsActionColumn):
     """Site container tree visible column"""
 
     cssClasses = {'th': 'action',
@@ -245,26 +247,38 @@
     icon_class = 'fa fa-fw fa-eye'
     icon_hint = _("Visible element?")
 
-    weight = 5
+    url = 'PyAMS_content.site.switchVisibility'
+    permission = MANAGE_CONTENT_PERMISSION
 
-    def renderCell(self, item):
-        return self.get_icon(item)
+    weight = 5
 
     def get_icon(self, item):
-        if ISharedContent.providedBy(item):
-            item = IWorkflowVersions(item).get_last_versions(count=1)[-1]
-        info = IWorkflowPublicationInfo(item, None)
-        if info is None:
-            return ''
+        if IContentLink.providedBy(item):
+            icon_class = 'fa-eye' if item.visible else 'fa-eye-slash'
+            if not IWorkflowPublicationInfo(item.__parent__).is_published():
+                icon_class += ' text-danger'
+            return '<i class="fa fa-fw {icon_class}"></i>'.format(icon_class=icon_class)
         else:
-            if info.is_published():
-                icon_class = 'fa-eye opacity-75'
+            if ISharedContent.providedBy(item):
+                item = IWorkflowVersions(item).get_last_versions(count=1)[-1]
+            info = IWorkflowPublicationInfo(item, None)
+            if info is None:
+                return ''
             else:
-                icon_class = 'fa-eye-slash text-danger opaque'
+                if info.is_published():
+                    icon_class = 'fa-eye opacity-75'
+                else:
+                    icon_class = 'fa-eye-slash text-danger opaque'
             return '<i class="fa fa-fw {icon_class} hint align-base" title="{title}" data-ams-hint-gravity="e"></i>'.format(
                 icon_class=icon_class,
                 title=self.request.localizer.translate(self.icon_hint))
 
+    def renderCell(self, item):
+        if IContentLink.providedBy(item) and self.request.has_permission(self.permission, context=item):
+            return super(SiteContainerTreeVisibleColumn, self).renderCell(item)
+        else:
+            return self.get_icon(item)
+
 
 @adapter_config(name='name', context=(ISiteContainer, IPyAMSLayer, ISiteTreeTable), provides=IColumn)
 class SiteContainerTreeNameColumn(NameColumn):
@@ -310,14 +324,18 @@
     weight = 70
 
     def getValue(self, obj):
-        sequence = ISequentialIdInfo(obj, None)
-        if sequence is None:
-            return '--'
+        if IContentLink.providedBy(obj):
+            sequence = get_utility(ISequentialIntIds)
+            return '&raquo; {0}'.format(sequence.get_base_oid(sequence.get_internal_id(obj.reference)))
         else:
-            try:
-                return sequence.get_short_oid()
-            except TypeError:
+            sequence = ISequentialIdInfo(obj, None)
+            if sequence is None:
                 return '--'
+            else:
+                try:
+                    return sequence.get_base_oid()
+                except TypeError:
+                    return '--'
 
 
 @adapter_config(name='state', context=(ISiteContainer, IPyAMSLayer, ISiteTreeTable), provides=IColumn)
@@ -328,10 +346,16 @@
     weight = 80
 
     def getValue(self, obj):
-        if not ISharedContent.providedBy(obj):
-            return '--'
-        version = IWorkflowVersions(obj).get_last_versions()[-1]
-        return self.request.localizer.translate(IWorkflow(version).get_state_label(IWorkflowState(version).state))
+        target = obj.get_target() if IContentLink.providedBy(obj) else obj
+        if ISharedContent.providedBy(target):
+            target = IWorkflowVersions(target).get_last_versions()[-1]
+        if IWfSharedContent.providedBy(target):
+            result = self.request.localizer.translate(IWorkflow(target).get_state_label(IWorkflowState(target).state))
+        else:
+            result = '--'
+        if IContentLink.providedBy(obj):
+            result = '({0})'.format(result)
+        return result
 
 
 @adapter_config(name='version', context=(ISiteContainer, IPyAMSLayer, ISiteTreeTable), provides=IColumn)
@@ -356,9 +380,9 @@
     permission = MANAGE_SITE_PERMISSION
 
     def has_permission(self, item):
-        if (not ISiteContainer.providedBy(item)) or (item in lineage(self.context)):
+        if item in lineage(self.context):
             return False
-        return super(SiteContainerTreeTrashColumn, self).has_permission(item)
+        return super(SiteContainerTreeTrashColumn, self).has_permission(item) and item.is_deletable()
 
 
 @adapter_config(context=(ISiteContainer, IPyAMSLayer, ISiteTreeTable), provides=IValues)
@@ -446,37 +470,51 @@
 def set_site_order(request):
     """Set site elements order"""
     intids = get_utility(IIntIds)
-    parent = intids.queryObject(int(request.params.get('parent')))
+    new_parent = intids.queryObject(int(request.params.get('parent')))
     # check for changing parent
     if request.params.get('action') == 'reparent':
         child = intids.queryObject(int(request.params.get('child')))
         old_parent = child.__parent__
         new_name = old_name = child.__name__
-        if old_name in parent:
+        if old_name in new_parent:
             index = 1
             new_name = '{name}-{index:02}'.format(name=old_name, index=index)
-            while new_name in parent:
+            while new_name in new_parent:
                 index += 1
                 new_name = '{name}-{index:02}'.format(name=old_name, index=index)
-        parent[new_name] = child
         del old_parent[old_name]
+        new_parent[new_name] = child
+        request.registry.notify(ObjectMovedEvent(child, old_parent, old_name, new_parent, new_name))
     # Re-define order
     names = [child.__name__ for child in [intids.queryObject(oid)
                                           for oid in map(int, json.loads(request.params.get('order')))]
-             if child.__parent__ is parent]
-    parent.updateOrder(names)
+             if child.__parent__ is new_parent]
+    new_parent.updateOrder(names)
     # get all new parent child
     table = SiteContainerTreeTable(request.context, request,
                                    can_sort=json.loads(request.params.get('can_sort', 'false')),
                                    rows_state='plus')
     table.update()
     result = []
-    for item in parent.values():
+    for item in new_parent.values():
         row = table.setUpRow(item)
         result.append(table.renderRow(row).strip())
     return result
     
 
+@view_config(name='set-content-visibility.json', context=ISiteContainer, request_type=IPyAMSLayer,
+             permission=MANAGE_CONTENT_PERMISSION, renderer='json', xhr=True)
+def set_content_visibility(request):
+    """Set content link visibility"""
+    container = ISiteContainer(request.context)
+    content = container.get(str(request.params.get('object_name')))
+    if not IContentLink.providedBy(content):
+        raise NotFound()
+    content.visible = not content.visible
+    return {'visible': content.visible,
+            'published': IWorkflowPublicationInfo(content.__parent__).is_published()}
+
+
 @view_config(name='delete-site-item.json', context=ISiteContainer, request_type=IPyAMSLayer,
              permission=MANAGE_SITE_PERMISSION, renderer='json', xhr=True)
 def delete_site_item(request):