src/pyams_content/shared/common/zmi/dashboard.py
changeset 1394 ed31bfceddda
parent 1330 cad3e22cc2bd
equal deleted inserted replaced
1393:9479901b53a5 1394:ed31bfceddda
     8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
     9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
    10 # FOR A PARTICULAR PURPOSE.
    10 # FOR A PARTICULAR PURPOSE.
    11 #
    11 #
    12 
    12 
    13 __docformat__ = 'restructuredtext'
       
    14 
       
    15 from hypatia.catalog import CatalogQuery
    13 from hypatia.catalog import CatalogQuery
    16 from hypatia.interfaces import ICatalog
    14 from hypatia.interfaces import ICatalog
    17 from hypatia.query import And, Or, Eq, Any
    15 from hypatia.query import And, Any, Eq, Or
    18 from z3c.table.column import GetAttrColumn
    16 from z3c.table.column import GetAttrColumn
    19 from z3c.table.interfaces import IValues, IColumn
    17 from z3c.table.interfaces import IColumn, IValues
    20 from zope.dublincore.interfaces import IZopeDublinCore
    18 from zope.dublincore.interfaces import IZopeDublinCore
    21 from zope.interface import implementer, Interface
    19 from zope.interface import Interface, implementer
    22 from zope.intid.interfaces import IIntIds
    20 from zope.intid.interfaces import IIntIds
    23 
    21 
    24 from pyams_catalog.query import CatalogResultSet
    22 from pyams_catalog.query import CatalogResultSet
    25 from pyams_content.interfaces import MANAGE_SITE_ROOT_PERMISSION, PUBLISH_CONTENT_PERMISSION
    23 from pyams_content.interfaces import MANAGE_SITE_ROOT_PERMISSION, PUBLISH_CONTENT_PERMISSION
    26 from pyams_content.profile.interfaces import IAdminProfile
    24 from pyams_content.profile.interfaces import IAdminProfile
    27 from pyams_content.shared.common import CONTENT_TYPES
    25 from pyams_content.shared.common import CONTENT_TYPES
    28 from pyams_content.shared.common.interfaces import IBaseSharedTool, IWfSharedContent, IManagerRestrictions
    26 from pyams_content.shared.common.interfaces import IBaseSharedTool, IManagerRestrictions, \
    29 from pyams_content.shared.common.interfaces.types import IWfTypedSharedContent
    27     ISharedTool, IWfSharedContent
    30 from pyams_content.shared.common.interfaces.zmi import IDashboardTable, ISharedToolDashboardTable, \
    28 from pyams_content.shared.common.interfaces.zmi import IDashboardSearchHeader, IDashboardTable, \
    31     IDashboardSearchHeader
    29     IDashboardTypeColumnValue, ISharedToolDashboardTable
    32 from pyams_content.zmi import pyams_content
    30 from pyams_content.zmi import pyams_content
    33 from pyams_content.zmi.interfaces import IDashboardMenu, IMyDashboardMenu, IAllContentsMenu
    31 from pyams_content.zmi.interfaces import IAllContentsMenu, IDashboardMenu, IMyDashboardMenu
    34 from pyams_i18n.interfaces import II18n
    32 from pyams_i18n.interfaces import II18n
    35 from pyams_pagelet.pagelet import pagelet_config
    33 from pyams_pagelet.pagelet import pagelet_config
    36 from pyams_security.interfaces import ISecurityManager
    34 from pyams_security.interfaces import ISecurityManager
    37 from pyams_sequence.interfaces import ISequentialIdInfo, ISequentialIdTarget, ISequentialIntIds
    35 from pyams_sequence.interfaces import ISequentialIdInfo, ISequentialIdTarget, ISequentialIntIds
    38 from pyams_skin.container import ContainerView
    36 from pyams_skin.container import ContainerView
    39 from pyams_skin.interfaces import IPageHeader
    37 from pyams_skin.interfaces import IPageHeader
    40 from pyams_skin.interfaces.container import ITableElementName
    38 from pyams_skin.interfaces.container import ITableElementName
    41 from pyams_skin.layer import IPyAMSLayer
    39 from pyams_skin.layer import IPyAMSLayer
    42 from pyams_skin.page import DefaultPageHeaderAdapter
    40 from pyams_skin.page import DefaultPageHeaderAdapter
    43 from pyams_skin.table import BaseTable, I18nColumn, NameColumn, JsActionColumn
    41 from pyams_skin.table import BaseTable, I18nColumn, JsActionColumn, NameColumn
    44 from pyams_skin.viewlet.menu import MenuItem
    42 from pyams_skin.viewlet.menu import MenuItem
    45 from pyams_template.template import template_config
    43 from pyams_template.template import template_config
    46 from pyams_utils.adapter import adapter_config, ContextRequestViewAdapter
    44 from pyams_utils.adapter import ContextRequestViewAdapter, adapter_config
    47 from pyams_utils.date import format_datetime, SH_DATETIME_FORMAT
    45 from pyams_utils.date import SH_DATETIME_FORMAT, format_datetime
    48 from pyams_utils.fanstatic import get_resource_path
    46 from pyams_utils.fanstatic import get_resource_path
    49 from pyams_utils.interfaces import VIEW_SYSTEM_PERMISSION
    47 from pyams_utils.interfaces import VIEW_SYSTEM_PERMISSION
    50 from pyams_utils.list import unique_iter
    48 from pyams_utils.list import unique_iter
    51 from pyams_utils.property import cached_property
    49 from pyams_utils.property import cached_property
    52 from pyams_utils.registry import get_utility
    50 from pyams_utils.registry import get_utility
    53 from pyams_utils.timezone import tztime
    51 from pyams_utils.timezone import tztime
    54 from pyams_utils.traversing import get_parent
    52 from pyams_utils.traversing import get_parent
    55 from pyams_viewlet.manager import viewletmanager_config
    53 from pyams_viewlet.manager import viewletmanager_config
    56 from pyams_viewlet.viewlet import viewlet_config
    54 from pyams_viewlet.viewlet import viewlet_config
    57 from pyams_workflow.interfaces import IWorkflowState, IWorkflow, IWorkflowVersions, IWorkflowPublicationInfo
    55 from pyams_workflow.interfaces import IWorkflow, IWorkflowPublicationInfo, IWorkflowState, \
       
    56     IWorkflowVersions
    58 from pyams_zmi.interfaces.menu import IContentManagementMenu
    57 from pyams_zmi.interfaces.menu import IContentManagementMenu
    59 from pyams_zmi.layer import IAdminLayer
    58 from pyams_zmi.layer import IAdminLayer
    60 from pyams_zmi.view import InnerAdminView
    59 from pyams_zmi.view import InnerAdminView
       
    60 
       
    61 
       
    62 __docformat__ = 'restructuredtext'
    61 
    63 
    62 from pyams_content import _
    64 from pyams_content import _
    63 
    65 
    64 
    66 
    65 #
    67 #
   100 
   102 
   101 @adapter_config(name='type', context=(Interface, IPyAMSLayer, IDashboardTable), provides=IColumn)
   103 @adapter_config(name='type', context=(Interface, IPyAMSLayer, IDashboardTable), provides=IColumn)
   102 class SharedToolDashboardTypeColumn(I18nColumn, GetAttrColumn):
   104 class SharedToolDashboardTypeColumn(I18nColumn, GetAttrColumn):
   103     """Shared tool dashboard type column"""
   105     """Shared tool dashboard type column"""
   104 
   106 
       
   107     _header = _("Content type")
       
   108     weight = 9
       
   109 
       
   110     def getValue(self, obj):
       
   111         value = self.request.registry.queryMultiAdapter((obj, self.request, self.table),
       
   112                                                         IDashboardTypeColumnValue)
       
   113         return value or '--'
       
   114 
       
   115 
       
   116 @adapter_config(name='type', context=(ISharedTool, IPyAMSLayer, ISharedToolDashboardTable),
       
   117                 provides=IColumn)
       
   118 class SharedContentDashboardTypeColumn(SharedToolDashboardTypeColumn):
       
   119     """Shared tool dashboard type column"""
       
   120 
   105     _header = _("Type")
   121     _header = _("Type")
   106     weight = 9
       
   107 
       
   108     def getValue(self, obj):
       
   109         content = IWfTypedSharedContent(obj, None)
       
   110         if content is not None:
       
   111             data_type = content.get_data_type()
       
   112             if data_type is not None:
       
   113                 return II18n(data_type).query_attribute('navigation_label', request=self.request) or \
       
   114                        II18n(data_type).query_attribute('label', request=self.request)
       
   115         return '--'
       
   116 
   122 
   117 
   123 
   118 @adapter_config(name='name', context=(Interface, IPyAMSLayer, IDashboardTable), provides=IColumn)
   124 @adapter_config(name='name', context=(Interface, IPyAMSLayer, IDashboardTable), provides=IColumn)
   119 class SharedToolDashboardNameColumn(NameColumn):
   125 class SharedToolDashboardNameColumn(NameColumn):
   120     """Shared tool dashboard name column"""
   126     """Shared tool dashboard name column"""
   121 
   127 
   122     _header = _("Title")
   128     _header = _("Title")
   123 
   129 
   124 
   130 
   125 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, IDashboardTable), provides=ITableElementName)
   131 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, IDashboardTable),
       
   132                 provides=ITableElementName)
   126 class SharedToolDashboardNameAdapter(ContextRequestViewAdapter):
   133 class SharedToolDashboardNameAdapter(ContextRequestViewAdapter):
   127     """Shared tool dashboard name adapter"""
   134     """Shared tool dashboard name adapter"""
   128 
   135 
   129     @property
   136     @property
   130     def name(self):
   137     def name(self):
   131         return II18n(self.context).query_attribute('title', request=self.request)
   138         return II18n(self.context).query_attribute('title', request=self.request)
   132 
   139 
   133 
   140 
   134 @adapter_config(context=(IWfSharedContent, IPyAMSLayer, IDashboardTable), provides=ITableElementName)
   141 @adapter_config(context=(IWfSharedContent, IPyAMSLayer, IDashboardTable),
       
   142                 provides=ITableElementName)
   135 class SharedToolDashboardContentNameAdapter(ContextRequestViewAdapter):
   143 class SharedToolDashboardContentNameAdapter(ContextRequestViewAdapter):
   136     """Shared tool dashboard content name adapter"""
   144     """Shared tool dashboard content name adapter"""
   137 
   145 
   138     @property
   146     @property
   139     def name(self):
   147     def name(self):
   140         return II18n(self.context).query_attribute('title', request=self.request)
   148         return II18n(self.context).query_attribute('title', request=self.request)
   141 
   149 
   142 
   150 
   143 @adapter_config(name='sequence', context=(Interface, IPyAMSLayer, IDashboardTable), provides=IColumn)
   151 @adapter_config(name='sequence', context=(Interface, IPyAMSLayer, IDashboardTable),
       
   152                 provides=IColumn)
   144 class SharedToolDashboardSequenceColumn(I18nColumn, GetAttrColumn):
   153 class SharedToolDashboardSequenceColumn(I18nColumn, GetAttrColumn):
   145     """Shared tool dashboard sequence ID column"""
   154     """Shared tool dashboard sequence ID column"""
   146 
   155 
   147     _header = _("Unique ID")
   156     _header = _("Unique ID")
   148     weight = 15
   157     weight = 15
   158                 return '--'
   167                 return '--'
   159         else:
   168         else:
   160             return '--'
   169             return '--'
   161 
   170 
   162 
   171 
   163 @adapter_config(name='status', context=(Interface, IPyAMSLayer, IDashboardTable), provides=IColumn)
   172 @adapter_config(name='status', context=(Interface, IPyAMSLayer, IDashboardTable),
       
   173                 provides=IColumn)
   164 class SharedToolDashboardStatusColumn(I18nColumn, GetAttrColumn):
   174 class SharedToolDashboardStatusColumn(I18nColumn, GetAttrColumn):
   165     """Shared tool dashboard status column"""
   175     """Shared tool dashboard status column"""
   166 
   176 
   167     _header = _("Status")
   177     _header = _("Status")
   168     cssClasses = {'td': 'nowrap'}
   178     cssClasses = {'td': 'nowrap'}
   185             return result
   195             return result
   186         else:
   196         else:
   187             return '--'
   197             return '--'
   188 
   198 
   189 
   199 
   190 @adapter_config(name='status_date', context=(Interface, IPyAMSLayer, IDashboardTable), provides=IColumn)
   200 @adapter_config(name='status_date', context=(Interface, IPyAMSLayer, IDashboardTable),
       
   201                 provides=IColumn)
   191 class SharedToolDashboardStatusDateColumn(I18nColumn, GetAttrColumn):
   202 class SharedToolDashboardStatusDateColumn(I18nColumn, GetAttrColumn):
   192     """Shared tool dashboard status date column"""
   203     """Shared tool dashboard status date column"""
   193 
   204 
   194     _header = _("Status date")
   205     _header = _("Status date")
   195     cssClasses = {'th': 'col-xs-hide col-sm-hide',
   206     cssClasses = {'th': 'col-xs-hide col-sm-hide',
   202             return format_datetime(state.state_date, SH_DATETIME_FORMAT, request=self.request)
   213             return format_datetime(state.state_date, SH_DATETIME_FORMAT, request=self.request)
   203         else:
   214         else:
   204             return '--'
   215             return '--'
   205 
   216 
   206 
   217 
   207 @adapter_config(name='version', context=(Interface, IPyAMSLayer, IDashboardTable), provides=IColumn)
   218 @adapter_config(name='version', context=(Interface, IPyAMSLayer, IDashboardTable),
       
   219                 provides=IColumn)
   208 class SharedToolDashboardVersionColumn(I18nColumn, GetAttrColumn):
   220 class SharedToolDashboardVersionColumn(I18nColumn, GetAttrColumn):
   209     """Shared tool dashboard version column"""
   221     """Shared tool dashboard version column"""
   210 
   222 
   211     _header = _("Version")
   223     _header = _("Version")
   212     weight = 25
   224     weight = 25
   217             return str(state.version_id)
   229             return str(state.version_id)
   218         else:
   230         else:
   219             return '--'
   231             return '--'
   220 
   232 
   221 
   233 
   222 @adapter_config(name='status_principal', context=(Interface, IPyAMSLayer, IDashboardTable), provides=IColumn)
   234 @adapter_config(name='status_principal', context=(Interface, IPyAMSLayer, IDashboardTable),
       
   235                 provides=IColumn)
   223 class SharedToolDashboardStatusPrincipalColumn(I18nColumn, GetAttrColumn):
   236 class SharedToolDashboardStatusPrincipalColumn(I18nColumn, GetAttrColumn):
   224     """Shared tool dashboard status principal column"""
   237     """Shared tool dashboard status principal column"""
   225 
   238 
   226     _header = _("Status principal")
   239     _header = _("Status principal")
   227     cssClasses = {'th': 'col-xs-hide',
   240     cssClasses = {'th': 'col-xs-hide',
   235             return manager.get_principal(state.state_principal).title
   248             return manager.get_principal(state.state_principal).title
   236         else:
   249         else:
   237             return '--'
   250             return '--'
   238 
   251 
   239 
   252 
   240 @adapter_config(name='owner', context=(Interface, IPyAMSLayer, IDashboardTable), provides=IColumn)
   253 @adapter_config(name='owner', context=(Interface, IPyAMSLayer, IDashboardTable),
       
   254                 provides=IColumn)
   241 class SharedToolDashboardOwnerColumn(I18nColumn, GetAttrColumn):
   255 class SharedToolDashboardOwnerColumn(I18nColumn, GetAttrColumn):
   242     """Shared tool dashboard owner column"""
   256     """Shared tool dashboard owner column"""
   243 
   257 
   244     _header = _("Owner")
   258     _header = _("Owner")
   245     cssClasses = {'th': 'col-xs-hide',
   259     cssClasses = {'th': 'col-xs-hide',
   257                 return manager.get_principal(next(iter(owner))).title
   271                 return manager.get_principal(next(iter(owner))).title
   258             else:
   272             else:
   259                 return '--'
   273                 return '--'
   260 
   274 
   261 
   275 
   262 @adapter_config(name='modified', context=(Interface, IPyAMSLayer, IDashboardTable), provides=IColumn)
   276 @adapter_config(name='modified', context=(Interface, IPyAMSLayer, IDashboardTable),
       
   277                 provides=IColumn)
   263 class SharedToolDashboardModifiedColumn(I18nColumn, GetAttrColumn):
   278 class SharedToolDashboardModifiedColumn(I18nColumn, GetAttrColumn):
   264     """Shared tool dashboard modified column"""
   279     """Shared tool dashboard modified column"""
   265 
   280 
   266     _header = _("Last modification")
   281     _header = _("Last modification")
   267     cssClasses = {'td': 'nowrap'}
   282     cssClasses = {'td': 'nowrap'}
   289     label = _("Dashboard")
   304     label = _("Dashboard")
   290     icon_class = 'fa-line-chart'
   305     icon_class = 'fa-line-chart'
   291     url = '#dashboard.html'
   306     url = '#dashboard.html'
   292 
   307 
   293 
   308 
   294 @pagelet_config(name='dashboard.html', context=IBaseSharedTool, layer=IPyAMSLayer, permission=VIEW_SYSTEM_PERMISSION)
   309 @pagelet_config(name='dashboard.html', context=IBaseSharedTool, layer=IPyAMSLayer,
       
   310                 permission=VIEW_SYSTEM_PERMISSION)
   295 @template_config(template='templates/dashboard.pt', layer=IAdminLayer)
   311 @template_config(template='templates/dashboard.pt', layer=IAdminLayer)
   296 class SharedToolDashboardView(InnerAdminView):
   312 class SharedToolDashboardView(InnerAdminView):
   297     """Shared tool dashboard view"""
   313     """Shared tool dashboard view"""
   298 
   314 
   299     title = _("Contents dashboard")
   315     title = _("Contents dashboard")
   312         [table.update() for table in self.tables]
   328         [table.update() for table in self.tables]
   313 
   329 
   314     @property
   330     @property
   315     def header_title(self):
   331     def header_title(self):
   316         registry = self.request.registry
   332         registry = self.request.registry
   317         adapter = registry.queryMultiAdapter((self.context, self.request, self), IDashboardSearchHeader)
   333         adapter = registry.queryMultiAdapter((self.context, self.request, self),
       
   334                                              IDashboardSearchHeader)
   318         if adapter is not None:
   335         if adapter is not None:
   319             return adapter.title
   336             return adapter.title
   320         else:
   337         else:
   321             translate = self.request.localizer.translate
   338             translate = self.request.localizer.translate
   322             return translate(_("SEARCH - Between all contents of type « {type} »")).format(
   339             return translate(_("SEARCH - Between all contents of type "
       
   340                                "« {type} »")).format(
   323                 type=II18n(self.context).query_attribute('title', request=self.request)
   341                 type=II18n(self.context).query_attribute('title', request=self.request)
   324             )
   342             )
   325 
   343 
   326 
   344 
   327 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolDashboardView), provides=IPageHeader)
   345 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolDashboardView),
       
   346                 provides=IPageHeader)
   328 class SharedToolDashboardHeaderAdapter(DefaultPageHeaderAdapter):
   347 class SharedToolDashboardHeaderAdapter(DefaultPageHeaderAdapter):
   329     """Shared tool properties header adapter"""
   348     """Shared tool properties header adapter"""
   330 
   349 
   331     back_url = '/admin#dashboard.html'
   350     back_url = '/admin#dashboard.html'
   332     back_target = None
   351     back_target = None
   344 
   363 
   345     _single_title = _("MANAGER - {0} content waiting for your action")
   364     _single_title = _("MANAGER - {0} content waiting for your action")
   346     _plural_title = _("MANAGER - {0} contents waiting for your action")
   365     _plural_title = _("MANAGER - {0} contents waiting for your action")
   347 
   366 
   348 
   367 
   349 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolDashboardManagerWaitingTable), provides=IValues)
   368 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolDashboardManagerWaitingTable),
       
   369                 provides=IValues)
   350 class SharedToolDashboardManagerWaitingValues(ContextRequestViewAdapter):
   370 class SharedToolDashboardManagerWaitingValues(ContextRequestViewAdapter):
   351     """Shared tool dashboard waiting values adapter"""
   371     """Shared tool dashboard waiting values adapter"""
   352 
   372 
   353     @property
   373     @property
   354     def values(self):
   374     def values(self):
   357         workflow = get_utility(IWorkflow, name=self.context.shared_content_workflow)
   377         workflow = get_utility(IWorkflow, name=self.context.shared_content_workflow)
   358         params = Eq(catalog['parents'], intids.register(self.context)) & \
   378         params = Eq(catalog['parents'], intids.register(self.context)) & \
   359                  Any(catalog['content_type'], CONTENT_TYPES.keys()) & \
   379                  Any(catalog['content_type'], CONTENT_TYPES.keys()) & \
   360                  Any(catalog['workflow_state'], workflow.waiting_states)
   380                  Any(catalog['workflow_state'], workflow.waiting_states)
   361         yield from filter(self.check_access,
   381         yield from filter(self.check_access,
   362                           unique_iter(map(lambda x: sorted(IWorkflowVersions(x).get_versions(IWorkflowState(x).state),
   382                           unique_iter(map(lambda x: sorted(
   363                                                            key=lambda y: IZopeDublinCore(y).modified, reverse=True)[0],
   383                               IWorkflowVersions(x).get_versions(IWorkflowState(x).state),
       
   384                               key=lambda y: IZopeDublinCore(y).modified, reverse=True)[0],
   364                                           CatalogResultSet(CatalogQuery(catalog).query(params,
   385                                           CatalogResultSet(CatalogQuery(catalog).query(params,
   365                                                                                        sort_index='modified_date')))))
   386                                                                                        sort_index='modified_date')))))
   366 
   387 
   367     def check_access(self, content):
   388     def check_access(self, content):
   368         if self.request.has_permission(MANAGE_SITE_ROOT_PERMISSION, context=content):
   389         if self.request.has_permission(MANAGE_SITE_ROOT_PERMISSION, context=content):
   388     _plural_title = _("CONTRIBUTOR - {0} contents waiting for action")
   409     _plural_title = _("CONTRIBUTOR - {0} contents waiting for action")
   389 
   410 
   390     dt_sort_order = 'asc'
   411     dt_sort_order = 'asc'
   391 
   412 
   392 
   413 
   393 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolDashboardOwnerWaitingTable), provides=IValues)
   414 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolDashboardOwnerWaitingTable),
       
   415                 provides=IValues)
   394 class SharedToolDashboardOwnerWaitingValues(ContextRequestViewAdapter):
   416 class SharedToolDashboardOwnerWaitingValues(ContextRequestViewAdapter):
   395     """Shared tool dashboard waiting owned contents values adapter"""
   417     """Shared tool dashboard waiting owned contents values adapter"""
   396 
   418 
   397     @property
   419     @property
   398     def values(self):
   420     def values(self):
   401         workflow = get_utility(IWorkflow, name=self.context.shared_content_workflow)
   423         workflow = get_utility(IWorkflow, name=self.context.shared_content_workflow)
   402         params = Eq(catalog['parents'], intids.register(self.context)) & \
   424         params = Eq(catalog['parents'], intids.register(self.context)) & \
   403                  Any(catalog['content_type'], CONTENT_TYPES.keys()) & \
   425                  Any(catalog['content_type'], CONTENT_TYPES.keys()) & \
   404                  Any(catalog['workflow_state'], workflow.waiting_states) & \
   426                  Any(catalog['workflow_state'], workflow.waiting_states) & \
   405                  Eq(catalog['workflow_principal'], self.request.principal.id)
   427                  Eq(catalog['workflow_principal'], self.request.principal.id)
   406         yield from unique_iter(map(lambda x: sorted(IWorkflowVersions(x).get_versions(IWorkflowState(x).state),
   428         yield from unique_iter(
   407                                                     key=lambda y: IZopeDublinCore(y).modified, reverse=True)[0],
   429             map(lambda x: sorted(IWorkflowVersions(x).get_versions(IWorkflowState(x).state),
   408                                    CatalogResultSet(CatalogQuery(catalog).query(params,
   430                                  key=lambda y: IZopeDublinCore(y).modified, reverse=True)[0],
   409                                                                                 sort_index='modified_date'))))
   431                 CatalogResultSet(CatalogQuery(catalog).query(params,
       
   432                                                              sort_index='modified_date'))))
   410 
   433 
   411 
   434 
   412 #
   435 #
   413 # Last owned modified contents
   436 # Last owned modified contents
   414 #
   437 #
   425             return _("CONTRIBUTOR - {0} modified contents")
   448             return _("CONTRIBUTOR - {0} modified contents")
   426         else:
   449         else:
   427             return _("CONTRIBUTOR - Last {0} modified contents")
   450             return _("CONTRIBUTOR - Last {0} modified contents")
   428 
   451 
   429 
   452 
   430 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolDashboardOwnerModifiedTable), provides=IValues)
   453 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolDashboardOwnerModifiedTable),
       
   454                 provides=IValues)
   431 class SharedToolDashboardOwnerModifiedValues(ContextRequestViewAdapter):
   455 class SharedToolDashboardOwnerModifiedValues(ContextRequestViewAdapter):
   432     """Shared tool dashboard waiting owned contents values adapter"""
   456     """Shared tool dashboard waiting owned contents values adapter"""
   433 
   457 
   434     @property
   458     @property
   435     def values(self):
   459     def values(self):
   437         catalog = get_utility(ICatalog)
   461         catalog = get_utility(ICatalog)
   438         params = And(Eq(catalog['parents'], intids.register(self.context)),
   462         params = And(Eq(catalog['parents'], intids.register(self.context)),
   439                      Any(catalog['content_type'], CONTENT_TYPES.keys()),
   463                      Any(catalog['content_type'], CONTENT_TYPES.keys()),
   440                      Or(Eq(catalog['role:owner'], self.request.principal.id),
   464                      Or(Eq(catalog['role:owner'], self.request.principal.id),
   441                         Eq(catalog['role:contributor'], self.request.principal.id)))
   465                         Eq(catalog['role:contributor'], self.request.principal.id)))
   442         yield from unique_iter(map(lambda x: sorted(IWorkflowVersions(x).get_versions(IWorkflowState(x).state),
   466         yield from unique_iter(
   443                                                     key=lambda y: IZopeDublinCore(y).modified, reverse=True)[0],
   467             map(lambda x: sorted(IWorkflowVersions(x).get_versions(IWorkflowState(x).state),
   444                                    CatalogResultSet(CatalogQuery(catalog).query(params,
   468                                  key=lambda y: IZopeDublinCore(y).modified, reverse=True)[0],
   445                                                                                 limit=50,
   469                 CatalogResultSet(CatalogQuery(catalog).query(params,
   446                                                                                 sort_index='modified_date',
   470                                                              limit=50,
   447                                                                                 reverse=True))))
   471                                                              sort_index='modified_date',
       
   472                                                              reverse=True))))
   448 
   473 
   449 
   474 
   450 #
   475 #
   451 # All my contents menu
   476 # All my contents menu
   452 #
   477 #
   538                                    CatalogResultSet(CatalogQuery(catalog).query(params,
   563                                    CatalogResultSet(CatalogQuery(catalog).query(params,
   539                                                                                 sort_index='modified_date',
   564                                                                                 sort_index='modified_date',
   540                                                                                 reverse=True))))
   565                                                                                 reverse=True))))
   541 
   566 
   542 
   567 
   543 @pagelet_config(name='my-favorites.html', context=IBaseSharedTool, layer=IPyAMSLayer, permission=VIEW_SYSTEM_PERMISSION)
   568 @pagelet_config(name='my-favorites.html', context=IBaseSharedTool, layer=IPyAMSLayer,
       
   569                 permission=VIEW_SYSTEM_PERMISSION)
   544 class SharedToolFavoritesView(InnerAdminView, ContainerView):
   570 class SharedToolFavoritesView(InnerAdminView, ContainerView):
   545     """Shared tool favorites view"""
   571     """Shared tool favorites view"""
   546 
   572 
   547     table_class = SharedToolFavoritesTable
   573     table_class = SharedToolFavoritesTable
   548 
   574 
   549 
   575 
   550 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolFavoritesView), provides=IPageHeader)
   576 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolFavoritesView),
       
   577                 provides=IPageHeader)
   551 class SharedToolFavoritesHeaderAdapter(DefaultPageHeaderAdapter):
   578 class SharedToolFavoritesHeaderAdapter(DefaultPageHeaderAdapter):
   552     """Shared tool favorites header adapter"""
   579     """Shared tool favorites header adapter"""
   553 
   580 
   554     back_url = '#dashboard.html'
   581     back_url = '#dashboard.html'
   555     icon_class = 'fa fa-fw fa-user'
   582     icon_class = 'fa fa-fw fa-user'
   582 
   609 
   583     _single_title = _("CONTRIBUTOR - {0} content in preparation")
   610     _single_title = _("CONTRIBUTOR - {0} content in preparation")
   584     _plural_title = _("CONTRIBUTOR - {0} contents in preparation")
   611     _plural_title = _("CONTRIBUTOR - {0} contents in preparation")
   585 
   612 
   586 
   613 
   587 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolPreparationsTable), provides=IValues)
   614 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolPreparationsTable),
       
   615                 provides=IValues)
   588 class SharedToolPreparationsValues(ContextRequestViewAdapter):
   616 class SharedToolPreparationsValues(ContextRequestViewAdapter):
   589     """Shared tool preparations values adapter"""
   617     """Shared tool preparations values adapter"""
   590 
   618 
   591     @property
   619     @property
   592     def values(self):
   620     def values(self):
   609     """Shared tool preparations view"""
   637     """Shared tool preparations view"""
   610 
   638 
   611     table_class = SharedToolPreparationsTable
   639     table_class = SharedToolPreparationsTable
   612 
   640 
   613 
   641 
   614 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolPreparationsView), provides=IPageHeader)
   642 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolPreparationsView),
       
   643                 provides=IPageHeader)
   615 class SharedToolPreparationsHeaderAdapter(DefaultPageHeaderAdapter):
   644 class SharedToolPreparationsHeaderAdapter(DefaultPageHeaderAdapter):
   616     """Shared tool preparations header adapter"""
   645     """Shared tool preparations header adapter"""
   617 
   646 
   618     back_url = '#dashboard.html'
   647     back_url = '#dashboard.html'
   619     icon_class = 'fa fa-fw fa-user'
   648     icon_class = 'fa fa-fw fa-user'
   646 
   675 
   647     _single_title = _("CONTRIBUTOR - {0} submitted content")
   676     _single_title = _("CONTRIBUTOR - {0} submitted content")
   648     _plural_title = _("CONTRIBUTOR - {0} submitted contents")
   677     _plural_title = _("CONTRIBUTOR - {0} submitted contents")
   649 
   678 
   650 
   679 
   651 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolSubmissionsTable), provides=IValues)
   680 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolSubmissionsTable),
       
   681                 provides=IValues)
   652 class SharedToolSubmissionsValues(ContextRequestViewAdapter):
   682 class SharedToolSubmissionsValues(ContextRequestViewAdapter):
   653     """Shared tool submissions values adapter"""
   683     """Shared tool submissions values adapter"""
   654 
   684 
   655     @property
   685     @property
   656     def values(self):
   686     def values(self):
   673     """Shared tool submissions view"""
   703     """Shared tool submissions view"""
   674 
   704 
   675     table_class = SharedToolSubmissionsTable
   705     table_class = SharedToolSubmissionsTable
   676 
   706 
   677 
   707 
   678 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolSubmissionsView), provides=IPageHeader)
   708 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolSubmissionsView),
       
   709                 provides=IPageHeader)
   679 class SharedToolSubmissionsHeaderAdapter(DefaultPageHeaderAdapter):
   710 class SharedToolSubmissionsHeaderAdapter(DefaultPageHeaderAdapter):
   680     """Shared tool submissions header adapter"""
   711     """Shared tool submissions header adapter"""
   681 
   712 
   682     back_url = '#dashboard.html'
   713     back_url = '#dashboard.html'
   683     icon_class = 'fa fa-fw fa-user'
   714     icon_class = 'fa fa-fw fa-user'
   710 
   741 
   711     _single_title = _("CONTRIBUTOR - {0} published content")
   742     _single_title = _("CONTRIBUTOR - {0} published content")
   712     _plural_title = _("CONTRIBUTOR - {0} published contents")
   743     _plural_title = _("CONTRIBUTOR - {0} published contents")
   713 
   744 
   714 
   745 
   715 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolPublicationsTable), provides=IValues)
   746 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolPublicationsTable),
       
   747                 provides=IValues)
   716 class SharedToolPublicationsValues(ContextRequestViewAdapter):
   748 class SharedToolPublicationsValues(ContextRequestViewAdapter):
   717     """Shared tool publications values adapter"""
   749     """Shared tool publications values adapter"""
   718 
   750 
   719     @property
   751     @property
   720     def values(self):
   752     def values(self):
   737     """Shared tool publications view"""
   769     """Shared tool publications view"""
   738 
   770 
   739     table_class = SharedToolPublicationsTable
   771     table_class = SharedToolPublicationsTable
   740 
   772 
   741 
   773 
   742 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolPublicationsView), provides=IPageHeader)
   774 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolPublicationsView),
       
   775                 provides=IPageHeader)
   743 class SharedToolPublicationsHeaderAdapter(DefaultPageHeaderAdapter):
   776 class SharedToolPublicationsHeaderAdapter(DefaultPageHeaderAdapter):
   744     """Shared tool publications header adapter"""
   777     """Shared tool publications header adapter"""
   745 
   778 
   746     back_url = '#dashboard.html'
   779     back_url = '#dashboard.html'
   747     icon_class = 'fa fa-fw fa-user'
   780     icon_class = 'fa fa-fw fa-user'
   774 
   807 
   775     _single_title = _("CONTRIBUTOR - {0} retired content")
   808     _single_title = _("CONTRIBUTOR - {0} retired content")
   776     _plural_title = _("CONTRIBUTOR - {0} retired contents")
   809     _plural_title = _("CONTRIBUTOR - {0} retired contents")
   777 
   810 
   778 
   811 
   779 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolRetiredContentsTable), provides=IValues)
   812 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolRetiredContentsTable),
       
   813                 provides=IValues)
   780 class SharedToolRetiredContentsValues(ContextRequestViewAdapter):
   814 class SharedToolRetiredContentsValues(ContextRequestViewAdapter):
   781     """Shared tool retired contents values adapter"""
   815     """Shared tool retired contents values adapter"""
   782 
   816 
   783     @property
   817     @property
   784     def values(self):
   818     def values(self):
   801     """Shared tool retired contents view"""
   835     """Shared tool retired contents view"""
   802 
   836 
   803     table_class = SharedToolRetiredContentsTable
   837     table_class = SharedToolRetiredContentsTable
   804 
   838 
   805 
   839 
   806 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolRetiredContentsView), provides=IPageHeader)
   840 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolRetiredContentsView),
       
   841                 provides=IPageHeader)
   807 class SharedToolRetiredContentsHeaderAdapter(DefaultPageHeaderAdapter):
   842 class SharedToolRetiredContentsHeaderAdapter(DefaultPageHeaderAdapter):
   808     """Shared tool retired contents header adapter"""
   843     """Shared tool retired contents header adapter"""
   809 
   844 
   810     back_url = '#dashboard.html'
   845     back_url = '#dashboard.html'
   811     icon_class = 'fa fa-fw fa-user'
   846     icon_class = 'fa fa-fw fa-user'
   838 
   873 
   839     _single_title = _("CONTRIBUTOR - {0} archived content")
   874     _single_title = _("CONTRIBUTOR - {0} archived content")
   840     _plural_title = _("CONTRIBUTOR - {0} archived contents")
   875     _plural_title = _("CONTRIBUTOR - {0} archived contents")
   841 
   876 
   842 
   877 
   843 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolArchivedContentsTable), provides=IValues)
   878 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolArchivedContentsTable),
       
   879                 provides=IValues)
   844 class SharedToolArchivedContentsValues(ContextRequestViewAdapter):
   880 class SharedToolArchivedContentsValues(ContextRequestViewAdapter):
   845     """Shared tool archived contents values adapter"""
   881     """Shared tool archived contents values adapter"""
   846 
   882 
   847     @property
   883     @property
   848     def values(self):
   884     def values(self):
   871     """Shared tool archived contents view"""
   907     """Shared tool archived contents view"""
   872 
   908 
   873     table_class = SharedToolArchivedContentsTable
   909     table_class = SharedToolArchivedContentsTable
   874 
   910 
   875 
   911 
   876 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolArchivedContentsView), provides=IPageHeader)
   912 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolArchivedContentsView),
       
   913                 provides=IPageHeader)
   877 class SharedToolArchivedContentsHeaderAdapter(DefaultPageHeaderAdapter):
   914 class SharedToolArchivedContentsHeaderAdapter(DefaultPageHeaderAdapter):
   878     """Shared tool archived contents header adapter"""
   915     """Shared tool archived contents header adapter"""
   879 
   916 
   880     back_url = '#dashboard.html'
   917     back_url = '#dashboard.html'
   881     icon_class = 'fa fa-fw fa-user'
   918     icon_class = 'fa fa-fw fa-user'
   930             return _("CONTRIBUTORS - Last {0} published contents")
   967             return _("CONTRIBUTORS - Last {0} published contents")
   931         else:
   968         else:
   932             return _("CONTRIBUTORS - Last published contents (in the limit of 50)")
   969             return _("CONTRIBUTORS - Last published contents (in the limit of 50)")
   933 
   970 
   934 
   971 
   935 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolAllPublicationsTable), provides=IValues)
   972 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolAllPublicationsTable),
       
   973                 provides=IValues)
   936 class SharedToolAllPublicationsValues(ContextRequestViewAdapter):
   974 class SharedToolAllPublicationsValues(ContextRequestViewAdapter):
   937     """Shared tool published contents values adapter"""
   975     """Shared tool published contents values adapter"""
   938 
   976 
   939     @property
   977     @property
   940     def values(self):
   978     def values(self):
   956     """Shared tool published contents view"""
   994     """Shared tool published contents view"""
   957 
   995 
   958     table_class = SharedToolAllPublicationsTable
   996     table_class = SharedToolAllPublicationsTable
   959 
   997 
   960 
   998 
   961 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolAllPublicationsView), provides=IPageHeader)
   999 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolAllPublicationsView),
       
  1000                 provides=IPageHeader)
   962 class SharedToolAllPublicationsHeaderAdapter(DefaultPageHeaderAdapter):
  1001 class SharedToolAllPublicationsHeaderAdapter(DefaultPageHeaderAdapter):
   963     """Shared tool published contents header adapter"""
  1002     """Shared tool published contents header adapter"""
   964 
  1003 
   965     back_url = '#dashboard.html'
  1004     back_url = '#dashboard.html'
   966     icon_class = 'fa fa-fw fa-pencil-square'
  1005     icon_class = 'fa fa-fw fa-pencil-square'
   999             return _("CONTRIBUTORS - Last {0} updated contents")
  1038             return _("CONTRIBUTORS - Last {0} updated contents")
  1000         else:
  1039         else:
  1001             return _("CONTRIBUTORS - Last updated contents (in the limit of 50)")
  1040             return _("CONTRIBUTORS - Last updated contents (in the limit of 50)")
  1002 
  1041 
  1003 
  1042 
  1004 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolAllUpdatesTable), provides=IValues)
  1043 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolAllUpdatesTable),
       
  1044                 provides=IValues)
  1005 class SharedToolAllUpdatesValues(ContextRequestViewAdapter):
  1045 class SharedToolAllUpdatesValues(ContextRequestViewAdapter):
  1006     """Shared tool updated contents values adapter"""
  1046     """Shared tool updated contents values adapter"""
  1007 
  1047 
  1008     @property
  1048     @property
  1009     def values(self):
  1049     def values(self):
  1023     """Shared tool updated contents view"""
  1063     """Shared tool updated contents view"""
  1024 
  1064 
  1025     table_class = SharedToolAllUpdatesTable
  1065     table_class = SharedToolAllUpdatesTable
  1026 
  1066 
  1027 
  1067 
  1028 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolAllUpdatesView), provides=IPageHeader)
  1068 @adapter_config(context=(IBaseSharedTool, IPyAMSLayer, SharedToolAllUpdatesView),
       
  1069                 provides=IPageHeader)
  1029 class SharedToolAllUpdatesHeaderAdapter(DefaultPageHeaderAdapter):
  1070 class SharedToolAllUpdatesHeaderAdapter(DefaultPageHeaderAdapter):
  1030     """Shared tool updated contents header adapter"""
  1071     """Shared tool updated contents header adapter"""
  1031 
  1072 
  1032     back_url = '#dashboard.html'
  1073     back_url = '#dashboard.html'
  1033     icon_class = 'fa fa-fw fa-pencil-square'
  1074     icon_class = 'fa fa-fw fa-pencil-square'