--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_content/shared/common/zmi/dashboard.py Thu Oct 08 13:37:29 2015 +0200
@@ -0,0 +1,759 @@
+#
+# Copyright (c) 2008-2015 Thierry Florac <tflorac AT ulthar.net>
+# 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 hypatia.interfaces import ICatalog
+from pyams_content.interfaces import MANAGE_SITE_ROOT_PERMISSION, PUBLISH_CONTENT_PERMISSION
+from pyams_content.profile.interfaces import IAdminProfile
+from pyams_content.shared.common.interfaces import ISharedTool, IWfSharedContent, IManagerRestrictions
+from pyams_content.shared.common.interfaces.zmi import ISharedToolDashboardTable
+from pyams_content.zmi.interfaces import IDashboardMenu, IMyDashboardMenu, IAllContentsMenu
+from pyams_i18n.interfaces import II18n
+from pyams_security.interfaces import ISecurityManager
+from pyams_sequence.interfaces import ISequentialIdInfo, ISequentialIdTarget, ISequentialIntIds
+from pyams_skin.interfaces import IInnerPage, IPageHeader
+from pyams_skin.interfaces.container import ITableElementName
+from pyams_skin.layer import IPyAMSLayer
+from pyams_utils.interfaces import VIEW_SYSTEM_PERMISSION
+from pyams_workflow.interfaces import IWorkflowState, IWorkflow, IWorkflowVersions
+from pyams_zmi.interfaces.menu import IContentManagementMenu
+from pyams_zmi.layer import IAdminLayer
+from z3c.table.interfaces import IValues, IColumn
+from zope.dublincore.interfaces import IZopeDublinCore
+
+# import packages
+from hypatia.catalog import CatalogQuery
+from hypatia.query import And, Or, Eq, Any
+from pyams_catalog.query import CatalogResultSet
+from pyams_pagelet.pagelet import pagelet_config
+from pyams_skin.container import ContainerView
+from pyams_skin.page import DefaultPageHeaderAdapter
+from pyams_skin.table import BaseTable, I18nColumn, ActionColumn
+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.date import format_datetime, SH_DATETIME_FORMAT
+from pyams_utils.list import unique
+from pyams_utils.property import cached_property
+from pyams_utils.registry import get_utility
+from pyams_utils.timezone import tztime
+from pyams_utils.traversing import get_parent
+from pyams_viewlet.manager import viewletmanager_config
+from pyams_viewlet.viewlet import viewlet_config
+from pyams_zmi.view import AdminView
+from z3c.table.column import GetAttrColumn
+from zope.interface import implementer, Interface
+
+from pyams_content import _
+
+
+#
+# Shared tools common adapters
+#
+
+@implementer(ISharedToolDashboardTable)
+class BaseDashboardTable(BaseTable):
+ """Base dashboard table"""
+
+ _title = '{0} contents'
+
+ sortOn = None
+ dt_sort_order = 'desc'
+
+ @property
+ def title(self):
+ return self.request.localizer.translate(self._title).format(len(self.values))
+
+ @property
+ def data_attributes(self):
+ attributes = super(BaseDashboardTable, self).data_attributes
+ attributes['table'] = {'data-ams-datatable-sorting': "{0},{1}".format(len(self.columns)-1,
+ self.dt_sort_order),
+ 'data-ams-datatable-display-length':
+ IAdminProfile(self.request.principal).table_page_length}
+ return attributes
+
+ @cached_property
+ def values(self):
+ return tuple(super(BaseDashboardTable, self).values)
+
+
+@adapter_config(context=(IWfSharedContent, IPyAMSLayer, ISharedToolDashboardTable), provides=ITableElementName)
+class SharedToolDashboardContentNameAdapter(ContextRequestViewAdapter):
+ """Shared tool dashboard content name adapter"""
+
+ @property
+ def name(self):
+ return II18n(self.context).query_attribute('short_name', request=self.request)
+
+
+@adapter_config(name='sequence', context=(Interface, IPyAMSLayer, ISharedToolDashboardTable), provides=IColumn)
+class SharedToolDashboardSequenceColumn(I18nColumn, GetAttrColumn):
+ """Shared tool dashboard sequence ID column"""
+
+ _header = _("Unique ID")
+ weight = 14
+
+ def getValue(self, obj):
+ target = get_parent(obj, ISequentialIdTarget)
+ sequence = get_utility(ISequentialIntIds, name=target.sequence_name)
+ return sequence.get_short_oid(ISequentialIdInfo(obj).oid, target.sequence_prefix)
+
+
+@adapter_config(name='version', context=(Interface, IPyAMSLayer, ISharedToolDashboardTable), provides=IColumn)
+class SharedToolDashboardVersionColumn(I18nColumn, GetAttrColumn):
+ """Shared tool dashboard version column"""
+
+ _header = _("Version")
+ weight = 15
+
+ def getValue(self, obj):
+ return str(IWorkflowState(obj).version_id)
+
+
+@adapter_config(name='urgency', context=(Interface, IPyAMSLayer, ISharedToolDashboardTable), provides=IColumn)
+class SharedToolDashboardUrgencyColumn(ActionColumn):
+ """Shared tool dashboard urgency column"""
+
+ icon_class = 'fa fa-fw fa-exclamation-triangle txt-color-red'
+ icon_hint = _("Urgent request !")
+
+ url = '#'
+ weight = 19
+
+ def renderCell(self, item):
+ state = IWorkflowState(item)
+ if not state.state_urgency:
+ return ''
+ else:
+ return super(SharedToolDashboardUrgencyColumn, self).renderCell(item)
+
+ def get_url(self, item):
+ return self.url
+
+
+@adapter_config(name='status', context=(Interface, IPyAMSLayer, ISharedToolDashboardTable), provides=IColumn)
+class SharedToolDashboardStatusColumn(I18nColumn, GetAttrColumn):
+ """Shared tool dashboard status column"""
+
+ _header = _("Status")
+ weight = 20
+
+ def getValue(self, obj):
+ workflow = IWorkflow(obj)
+ state = IWorkflowState(obj)
+ return self.request.localizer.translate(workflow.get_state_label(state.state))
+
+
+@adapter_config(name='status_date', context=(Interface, IPyAMSLayer, ISharedToolDashboardTable), provides=IColumn)
+class SharedToolDashboardStatusDateColumn(I18nColumn, GetAttrColumn):
+ """Shared tool dashboard status date column"""
+
+ _header = _("Status date")
+ weight = 21
+
+ def getValue(self, obj):
+ state = IWorkflowState(obj)
+ return format_datetime(state.state_date, SH_DATETIME_FORMAT, request=self.request)
+
+
+@adapter_config(name='status_principal', context=(Interface, IPyAMSLayer, ISharedToolDashboardTable), provides=IColumn)
+class SharedToolDashboardStatusPrincipalColumn(I18nColumn, GetAttrColumn):
+ """Shared tool dashboard status principal column"""
+
+ _header = _("Status principal")
+ weight = 22
+
+ def getValue(self, obj):
+ state = IWorkflowState(obj)
+ manager = get_utility(ISecurityManager)
+ return manager.get_principal(state.state_principal).title
+
+
+@adapter_config(name='owner', context=(Interface, IPyAMSLayer, ISharedToolDashboardTable), provides=IColumn)
+class SharedToolDashboardOwnerColumn(I18nColumn, GetAttrColumn):
+ """Shared tool dashboard owner column"""
+
+ _header = _("Owner")
+ weight = 30
+
+ def getValue(self, obj):
+ manager = get_utility(ISecurityManager)
+ return manager.get_principal(next(iter(obj.owner))).title
+
+
+@adapter_config(name='modified', context=(Interface, IPyAMSLayer, ISharedToolDashboardTable), provides=IColumn)
+class SharedToolDashboardModifiedColumn(I18nColumn, GetAttrColumn):
+ """Shared tool dashboard modified column"""
+
+ _header = _("Last modification")
+ weight = 40
+
+ def getValue(self, obj):
+ return format_datetime(tztime(IZopeDublinCore(obj).modified), SH_DATETIME_FORMAT, request=self.request)
+
+
+#
+# Shared tool control panel
+#
+
+@viewlet_config(name='dashboard.menu', context=ISharedTool, layer=IAdminLayer,
+ manager=IContentManagementMenu, permission=VIEW_SYSTEM_PERMISSION, weight=1)
+@viewletmanager_config(name='dashboard.menu', layer=IAdminLayer, provides=IDashboardMenu)
+@implementer(IDashboardMenu)
+class SharedToolDashboardMenu(MenuItem):
+ """Shared tool dashboard menu"""
+
+ label = _("Dashboard")
+ icon_class = 'fa-line-chart'
+ url = '#dashboard.html'
+
+
+@pagelet_config(name='dashboard.html', context=ISharedTool, layer=IPyAMSLayer, permission=VIEW_SYSTEM_PERMISSION)
+@template_config(template='templates/dashboard.pt', layer=IAdminLayer)
+@implementer(IInnerPage)
+class SharedToolDashboardView(AdminView):
+ """Shared tool dashboard view"""
+
+ title = _("Contents dashboard")
+
+ def __init__(self, context, request):
+ super(SharedToolDashboardView, self).__init__(context, request)
+ self.tables = []
+ self.tables.append(SharedToolDashboardManagerWaitingTable(self.context, self.request))
+ self.tables.append(SharedToolDashboardOwnerWaitingTable(self.context, self.request))
+ self.tables.append(SharedToolDashboardOwnerModifiedTable(self.context, self.request))
+ for table in self.tables:
+ table.hide_toolbar = True
+
+ def update(self):
+ super(SharedToolDashboardView, self).update()
+ [table.update() for table in self.tables]
+
+
+@adapter_config(context=(ISharedTool, IPyAMSLayer, SharedToolDashboardView), provides=IPageHeader)
+class SharedToolDashboardHeaderAdapter(DefaultPageHeaderAdapter):
+ """Shared tool properties header adapter"""
+
+ back_url = '/admin.html#dashboard.html'
+ back_target = None
+
+ icon_class = 'fa fa-fw fa-line-chart'
+
+
+#
+# Contents waiting for manager action
+#
+
+@implementer(ISharedToolDashboardTable)
+class SharedToolDashboardManagerWaitingTable(BaseDashboardTable):
+ """Shared tool dashboard waiting table"""
+
+ _title = _("MANAGER - {0} content(s) waiting for your action")
+
+ dt_sort_order = 'asc'
+
+
+@adapter_config(context=(ISharedTool, IPyAMSLayer, SharedToolDashboardManagerWaitingTable), provides=IValues)
+class SharedToolDashboardManagerWaitingValues(ContextRequestViewAdapter):
+ """Shared tool dashboard waiting values adapter"""
+
+ @property
+ def values(self):
+ catalog = get_utility(ICatalog)
+ workflow = get_utility(IWorkflow, name=self.context.shared_content_workflow)
+ params = Eq(catalog['content_type'], self.context.shared_content_type) & \
+ Any(catalog['workflow_state'], workflow.waiting_states)
+ return filter(self.check_access,
+ unique(map(lambda x: sorted(IWorkflowVersions(x).get_versions(IWorkflowState(x).state),
+ key=lambda y: IZopeDublinCore(y).modified, reverse=True)[0],
+ CatalogResultSet(CatalogQuery(catalog).query(params,
+ sort_index='modified_date')))))
+
+ def check_access(self, content):
+ if self.request.has_permission(MANAGE_SITE_ROOT_PERMISSION, context=content):
+ return True
+ if self.request.principal.id in content.managers:
+ return True
+ restrictions = IManagerRestrictions(content).get_restrictions(self.request.principal)
+ if restrictions is not None:
+ return restrictions.check_access(content, PUBLISH_CONTENT_PERMISSION, self.request)
+ else:
+ return False
+
+
+#
+# Last owned contents waiting for action
+#
+
+@implementer(ISharedToolDashboardTable)
+class SharedToolDashboardOwnerWaitingTable(BaseDashboardTable):
+ """Shared tool dashboard waiting owned contents table"""
+
+ _title = _("CONTRIBUTOR - Your {0} content(s) waiting for action")
+
+ dt_sort_order = 'asc'
+
+
+@adapter_config(context=(ISharedTool, IPyAMSLayer, SharedToolDashboardOwnerWaitingTable), provides=IValues)
+class SharedToolDashboardOwnerWaitingValues(ContextRequestViewAdapter):
+ """Shared tool dashboard waiting owned contents values adapter"""
+
+ @property
+ def values(self):
+ catalog = get_utility(ICatalog)
+ workflow = get_utility(IWorkflow, name=self.context.shared_content_workflow)
+ params = Eq(catalog['content_type'], self.context.shared_content_type) & \
+ Any(catalog['workflow_state'], workflow.waiting_states) & \
+ Eq(catalog['workflow_principal'], self.request.principal.id)
+ return unique(map(lambda x: sorted(IWorkflowVersions(x).get_versions(IWorkflowState(x).state),
+ key=lambda y: IZopeDublinCore(y).modified, reverse=True)[0],
+ CatalogResultSet(CatalogQuery(catalog).query(params,
+ sort_index='modified_date'))))
+
+
+#
+# Last owned modified contents
+#
+
+@implementer(ISharedToolDashboardTable)
+class SharedToolDashboardOwnerModifiedTable(BaseDashboardTable):
+ """Shared tool dashboard owned modified contents table"""
+
+ _title = _("CONTRIBUTOR - Your last modified contents (limited to {0})")
+
+
+@adapter_config(context=(ISharedTool, IPyAMSLayer, SharedToolDashboardOwnerModifiedTable), provides=IValues)
+class SharedToolDashboardOwnerModifiedValues(ContextRequestViewAdapter):
+ """Shared tool dashboard waiting owned contents values adapter"""
+
+ @property
+ def values(self):
+ catalog = get_utility(ICatalog)
+ params = And(Eq(catalog['content_type'], self.context.shared_content_type),
+ Or(Eq(catalog['role:owner'], self.request.principal.id),
+ Eq(catalog['role:contributor'], self.request.principal.id)))
+ return unique(map(lambda x: sorted(IWorkflowVersions(x).get_versions(IWorkflowState(x).state),
+ key=lambda y: IZopeDublinCore(y).modified, reverse=True)[0],
+ CatalogResultSet(CatalogQuery(catalog).query(params,
+ limit=IAdminProfile(self.request.principal).table_page_length,
+ sort_index='modified_date',
+ reverse=True))))
+
+
+#
+# All my contents menu
+#
+
+@viewlet_config(name='my-contents.menu', context=ISharedTool, layer=IAdminLayer,
+ manager=IContentManagementMenu, permission=VIEW_SYSTEM_PERMISSION, weight=5)
+@viewletmanager_config(name='my-contents.menu', layer=IAdminLayer, provides=IMyDashboardMenu)
+@implementer(IMyDashboardMenu)
+class SharedToolMyDashboardMenu(MenuItem):
+ """Shared tool 'my contents' dashboard menu"""
+
+ label = _("My contents")
+ icon_class = 'fa-user'
+ url = '#'
+
+
+#
+# My preparations
+# Dashboard of owned and modified contents which can be updated
+#
+
+@viewlet_config(name='my-preparations.menu', context=ISharedTool, layer=IAdminLayer,
+ manager=IMyDashboardMenu, permission=VIEW_SYSTEM_PERMISSION, weight=5)
+class SharedToolPreparationsMenu(MenuItem):
+ """Site root preparations dashboard menu"""
+
+ label = _("My preparations")
+ icon_class = None
+ url = '#my-preparations.html'
+
+
+@implementer(ISharedToolDashboardTable)
+class SharedToolPreparationsTable(BaseDashboardTable):
+ """Site root preparations table"""
+
+ _title = _("CONTRIBUTOR - Your {0} prepared contents")
+
+
+@adapter_config(context=(ISharedTool, IPyAMSLayer, SharedToolPreparationsTable), provides=IValues)
+class SharedToolPreparationsValues(ContextRequestViewAdapter):
+ """Site root preparations values adapter"""
+
+ @property
+ def values(self):
+ catalog = get_utility(ICatalog)
+ workflow = get_utility(IWorkflow, name=self.context.shared_content_workflow)
+ params = And(Eq(catalog['content_type'], self.context.shared_content_type),
+ Or(Eq(catalog['role:owner'], self.request.principal.id),
+ Eq(catalog['role:contributor'], self.request.principal.id)),
+ Any(catalog['workflow_state'], workflow.update_states))
+ return unique(CatalogResultSet(CatalogQuery(catalog).query(params,
+ sort_index='modified_date',
+ reverse=True)))
+
+
+@pagelet_config(name='my-preparations.html', context=ISharedTool, layer=IPyAMSLayer, permission=VIEW_SYSTEM_PERMISSION)
+@implementer(IInnerPage)
+class SharedToolPreparationsView(AdminView, ContainerView):
+ """Site root preparations view"""
+
+ table_class = SharedToolPreparationsTable
+
+
+@adapter_config(context=(ISharedTool, IPyAMSLayer, SharedToolPreparationsView), provides=IPageHeader)
+class SharedToolPreparationsHeaderAdapter(DefaultPageHeaderAdapter):
+ """Site root preparations header adapter"""
+
+ back_url = '#dashboard.html'
+ icon_class = 'fa fa-fw fa-user'
+
+ @property
+ def title(self):
+ return II18n(self.context).query_attribute('title', request=self.request)
+
+ subtitle = _("Your prepared contents")
+
+
+#
+# My publications
+# Dashboard of owned and modified contents which are published
+#
+
+@viewlet_config(name='my-publications.menu', context=ISharedTool, layer=IAdminLayer,
+ manager=IMyDashboardMenu, permission=VIEW_SYSTEM_PERMISSION, weight=10)
+class SharedToolPublicationsMenu(MenuItem):
+ """Shared tool publications dashboard menu"""
+
+ label = _("My publications")
+ icon_class = None
+ url = '#my-publications.html'
+
+
+@implementer(ISharedToolDashboardTable)
+class SharedToolPublicationsTable(BaseDashboardTable):
+ """Shared tool publications table"""
+
+ _title = _("CONTRIBUTOR - Your {0} published contents")
+
+
+@adapter_config(context=(ISharedTool, IPyAMSLayer, SharedToolPublicationsTable), provides=IValues)
+class SharedToolPublicationsValues(ContextRequestViewAdapter):
+ """Shared tool publications values adapter"""
+
+ @property
+ def values(self):
+ catalog = get_utility(ICatalog)
+ workflow = get_utility(IWorkflow, name=self.context.shared_content_workflow)
+ params = And(Eq(catalog['content_type'], self.context.shared_content_type),
+ Or(Eq(catalog['role:owner'], self.request.principal.id),
+ Eq(catalog['role:contributor'], self.request.principal.id)),
+ Any(catalog['workflow_state'], workflow.published_states))
+ return unique(CatalogResultSet(CatalogQuery(catalog).query(params,
+ sort_index='modified_date',
+ reverse=True)))
+
+
+@pagelet_config(name='my-publications.html', context=ISharedTool, layer=IPyAMSLayer, permission=VIEW_SYSTEM_PERMISSION)
+@implementer(IInnerPage)
+class SharedToolPublicationsView(AdminView, ContainerView):
+ """Shared tool publications view"""
+
+ table_class = SharedToolPublicationsTable
+
+
+@adapter_config(context=(ISharedTool, IPyAMSLayer, SharedToolPublicationsView), provides=IPageHeader)
+class SharedToolPublicationsHeaderAdapter(DefaultPageHeaderAdapter):
+ """Shared tool publications header adapter"""
+
+ back_url = '#dashboard.html'
+ icon_class = 'fa fa-fw fa-user'
+
+ @property
+ def title(self):
+ return II18n(self.context).query_attribute('title', request=self.request)
+
+ subtitle = _("Your published contents")
+
+
+#
+# My retired contents
+# Dashboard of owned and modified contents which are retired
+#
+
+@viewlet_config(name='my-retired-contents.menu', context=ISharedTool, layer=IAdminLayer,
+ manager=IMyDashboardMenu, permission=VIEW_SYSTEM_PERMISSION, weight=15)
+class SharedToolRetiredMenu(MenuItem):
+ """Shared tool retired contents dashboard menu"""
+
+ label = _("My retired contents")
+ icon_class = None
+ url = '#my-retired-contents.html'
+
+
+@implementer(ISharedToolDashboardTable)
+class SharedToolRetiredContentsTable(BaseDashboardTable):
+ """Shared tool retired contents table"""
+
+ _title = _("CONTRIBUTOR - Your {0} retired contents")
+
+
+@adapter_config(context=(ISharedTool, IPyAMSLayer, SharedToolRetiredContentsTable), provides=IValues)
+class SharedToolRetiredContentsValues(ContextRequestViewAdapter):
+ """Shared tool retired contents values adapter"""
+
+ @property
+ def values(self):
+ catalog = get_utility(ICatalog)
+ workflow = get_utility(IWorkflow, name=self.context.shared_content_workflow)
+ params = And(Eq(catalog['content_type'], self.context.shared_content_type),
+ Or(Eq(catalog['role:owner'], self.request.principal.id),
+ Eq(catalog['role:contributor'], self.request.principal.id)),
+ Any(catalog['workflow_state'], workflow.retired_states))
+ return unique(CatalogResultSet(CatalogQuery(catalog).query(params,
+ sort_index='modified_date',
+ reverse=True)))
+
+
+@pagelet_config(name='my-retired-contents.html', context=ISharedTool, layer=IPyAMSLayer,
+ permission=VIEW_SYSTEM_PERMISSION)
+@implementer(IInnerPage)
+class SharedToolRetiredContentsView(AdminView, ContainerView):
+ """Shared tool retired contents view"""
+
+ table_class = SharedToolRetiredContentsTable
+
+
+@adapter_config(context=(ISharedTool, IPyAMSLayer, SharedToolRetiredContentsView), provides=IPageHeader)
+class SharedToolRetiredContentsHeaderAdapter(DefaultPageHeaderAdapter):
+ """Shared tool retired contents header adapter"""
+
+ back_url = '#dashboard.html'
+ icon_class = 'fa fa-fw fa-user'
+
+ @property
+ def title(self):
+ return II18n(self.context).query_attribute('title', request=self.request)
+
+ subtitle = _("Your retired contents")
+
+
+#
+# My archived contents
+# Dashboard of owned and modified contents which are archived
+#
+
+@viewlet_config(name='my-archived-contents.menu', context=ISharedTool, layer=IAdminLayer,
+ manager=IMyDashboardMenu, permission=VIEW_SYSTEM_PERMISSION, weight=20)
+class SharedToolArchivedMenu(MenuItem):
+ """Shared tool archived contents dashboard menu"""
+
+ label = _("My archived contents")
+ icon_class = None
+ url = '#my-archived-contents.html'
+
+
+@implementer(ISharedToolDashboardTable)
+class SharedToolArchivedContentsTable(BaseDashboardTable):
+ """Shared tool archived contents table"""
+
+ _title = _("CONTRIBUTOR - Your {0} archived contents")
+
+
+@adapter_config(context=(ISharedTool, IPyAMSLayer, SharedToolArchivedContentsTable), provides=IValues)
+class SharedToolArchivedContentsValues(ContextRequestViewAdapter):
+ """Shared tool archived contents values adapter"""
+
+ @property
+ def values(self):
+ catalog = get_utility(ICatalog)
+ principal_id = self.request.principal.id
+ workflow = get_utility(IWorkflow, name=self.context.shared_content_workflow)
+ params = And(Eq(catalog['content_type'], self.context.shared_content_type),
+ Or(Eq(catalog['role:owner'], principal_id),
+ Eq(catalog['role:contributor'], principal_id)),
+ Any(catalog['workflow_state'], workflow.readonly_states))
+ return unique(map(lambda x: sorted((version for version in
+ IWorkflowVersions(x).get_versions(IWorkflow(x).readonly_states)
+ if principal_id in (version.owner | version.contributors)),
+ key=lambda x: IWorkflowState(x).version_id,
+ reverse=True)[0],
+ CatalogResultSet(CatalogQuery(catalog).query(params,
+ sort_index='modified_date',
+ reverse=True))))
+
+
+@pagelet_config(name='my-archived-contents.html', context=ISharedTool, layer=IPyAMSLayer,
+ permission=VIEW_SYSTEM_PERMISSION)
+@implementer(IInnerPage)
+class SharedToolArchivedContentsView(AdminView, ContainerView):
+ """Shared tool archived contents view"""
+
+ table_class = SharedToolArchivedContentsTable
+
+
+@adapter_config(context=(ISharedTool, IPyAMSLayer, SharedToolArchivedContentsView), provides=IPageHeader)
+class SharedToolArchivedContentsHeaderAdapter(DefaultPageHeaderAdapter):
+ """Shared tool archived contents header adapter"""
+
+ back_url = '#dashboard.html'
+ icon_class = 'fa fa-fw fa-user'
+
+ @property
+ def title(self):
+ return II18n(self.context).query_attribute('title', request=self.request)
+
+ subtitle = _("Your archived contents")
+
+
+#
+# All interventions
+#
+
+@viewlet_config(name='all-interventions.menu', context=ISharedTool, layer=IAdminLayer,
+ manager=IContentManagementMenu, permission=VIEW_SYSTEM_PERMISSION, weight=10)
+@viewletmanager_config(name='all-interventions.menu', layer=IAdminLayer, provides=IAllContentsMenu)
+@implementer(IAllContentsMenu)
+class SharedToolAllContentsMenu(MenuItem):
+ """Shared tool 'all contents' dashboard menu"""
+
+ label = _("Other interventions")
+ icon_class = 'fa-pencil-square'
+ url = '#'
+
+
+#
+# Last publications
+# Dashboard of all published contents
+#
+
+@viewlet_config(name='all-publications.menu', context=ISharedTool, layer=IAdminLayer,
+ manager=IAllContentsMenu, permission=VIEW_SYSTEM_PERMISSION, weight=10)
+class SharedToolAllPublicationsMenu(MenuItem):
+ """Shared tool published contents dashboard menu"""
+
+ label = _("Last publications")
+ icon_class = None
+ url = '#all-publications.html'
+
+
+@implementer(ISharedToolDashboardTable)
+class SharedToolAllPublicationsTable(BaseDashboardTable):
+ """Shared tool published contents table"""
+
+ _title = _("CONTRIBUTORS - Last published contents (in the limit of 50)")
+
+
+@adapter_config(context=(ISharedTool, IPyAMSLayer, SharedToolAllPublicationsTable), provides=IValues)
+class SharedToolAllPublicationsValues(ContextRequestViewAdapter):
+ """Shared tool published contents values adapter"""
+
+ @property
+ def values(self):
+ catalog = get_utility(ICatalog)
+ workflow = get_utility(IWorkflow, name=self.context.shared_content_workflow)
+ params = And(Eq(catalog['content_type'], self.context.shared_content_type),
+ Any(catalog['workflow_state'], workflow.published_states))
+ return unique(CatalogResultSet(CatalogQuery(catalog).query(params,
+ limit=50,
+ sort_index='modified_date',
+ reverse=True)))
+
+
+@pagelet_config(name='all-publications.html', context=ISharedTool, layer=IPyAMSLayer,
+ permission=VIEW_SYSTEM_PERMISSION)
+@implementer(IInnerPage)
+class SharedToolAllPublicationsView(AdminView, ContainerView):
+ """Shared tool published contents view"""
+
+ table_class = SharedToolAllPublicationsTable
+
+
+@adapter_config(context=(ISharedTool, IPyAMSLayer, SharedToolAllPublicationsView), provides=IPageHeader)
+class SharedToolAllPublicationsHeaderAdapter(DefaultPageHeaderAdapter):
+ """Shared tool published contents header adapter"""
+
+ back_url = '#dashboard.html'
+ icon_class = 'fa fa-fw fa-pencil-square'
+
+ @property
+ def title(self):
+ return II18n(self.context).query_attribute('title', request=self.request)
+
+ subtitle = _("Last published contents")
+
+
+#
+# Last updates
+# Dashboard of all updated contents
+#
+
+@viewlet_config(name='all-updates.menu', context=ISharedTool, layer=IAdminLayer,
+ manager=IAllContentsMenu, permission=VIEW_SYSTEM_PERMISSION, weight=20)
+class SharedToolAllUpdatesMenu(MenuItem):
+ """Shared tool updated contents dashboard menu"""
+
+ label = _("Last updates")
+ icon_class = None
+ url = '#all-updates.html'
+
+
+@implementer(ISharedToolDashboardTable)
+class SharedToolAllUpdatesTable(BaseDashboardTable):
+ """Shared tool updated contents table"""
+
+ _title = _("CONTRIBUTORS - Last updated contents (in the limit of 50)")
+
+
+@adapter_config(context=(ISharedTool, IPyAMSLayer, SharedToolAllUpdatesTable), provides=IValues)
+class SharedToolAllUpdatesValues(ContextRequestViewAdapter):
+ """Shared tool updated contents values adapter"""
+
+ @property
+ def values(self):
+ catalog = get_utility(ICatalog)
+ params = Eq(catalog['content_type'], self.context.shared_content_type)
+ return unique(CatalogResultSet(CatalogQuery(catalog).query(params,
+ limit=50,
+ sort_index='modified_date',
+ reverse=True)))
+
+
+@pagelet_config(name='all-updates.html', context=ISharedTool, layer=IPyAMSLayer,
+ permission=VIEW_SYSTEM_PERMISSION)
+@implementer(IInnerPage)
+class SharedToolAllUpdatesView(AdminView, ContainerView):
+ """Shared tool updated contents view"""
+
+ table_class = SharedToolAllUpdatesTable
+
+
+@adapter_config(context=(ISharedTool, IPyAMSLayer, SharedToolAllUpdatesView), provides=IPageHeader)
+class SharedToolAllUpdatesHeaderAdapter(DefaultPageHeaderAdapter):
+ """Shared tool updated contents header adapter"""
+
+ back_url = '#dashboard.html'
+ icon_class = 'fa fa-fw fa-pencil-square'
+
+ @property
+ def title(self):
+ return II18n(self.context).query_attribute('title', request=self.request)
+
+ subtitle = _("Last updated contents")