--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_content/shared/common/zmi/workflow.py Thu Oct 08 13:37:29 2015 +0200
@@ -0,0 +1,813 @@
+#
+# 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.
+#
+from pyams_utils.text import text_to_html
+
+__docformat__ = 'restructuredtext'
+
+
+# import standard library
+from datetime import datetime
+
+# import interfaces
+from pyams_content.shared.common.interfaces import IWfSharedContent, ISharedTool, ISharedContent
+from pyams_form.interfaces.form import IInnerTabForm, IFormPrefixViewletsManager, IWidgetsPrefixViewletsManager, \
+ IFormSuffixViewletsManager
+from pyams_security.interfaces import ISecurityManager
+from pyams_skin.interfaces import IInnerPage
+from pyams_skin.layer import IPyAMSLayer
+from pyams_workflow.interfaces import IWorkflowInfo, IWorkflowTransitionInfo, IWorkflowPublicationInfo, \
+ IWorkflowCommentInfo, IWorkflowVersions, IWorkflowState, IWorkflowManagedContent, IWorkflow, IWorkflowStateLabel, \
+ IWorkflowRequestUrgencyInfo, SYSTEM, MANUAL
+from z3c.form.interfaces import IDataExtractedEvent
+
+# import packages
+from pyams_content.shared.common.zmi.summary import SharedContentSummaryForm
+from pyams_content.workflow import DRAFT, DELETED
+from pyams_form.form import AJAXAddForm, InnerDisplayForm
+from pyams_form.schema import CloseButton
+from pyams_pagelet.pagelet import pagelet_config
+from pyams_template.template import template_config
+from pyams_utils.adapter import adapter_config
+from pyams_utils.date import format_datetime
+from pyams_utils.registry import get_utility
+from pyams_utils.timezone import tztime
+from pyams_utils.traversing import get_parent
+from pyams_utils.url import absolute_url
+from pyams_viewlet.viewlet import viewlet_config, Viewlet
+from pyams_workflow.zmi.transition import WorkflowContentTransitionForm, WorkflowContentTransitionAJAXForm
+from pyramid.events import subscriber
+from pyramid.view import view_config
+from z3c.form import field, button
+from zope.interface import implementer, Interface, Invalid
+
+from pyams_content import _
+
+
+#
+# Workflow summary view
+#
+
+@adapter_config(name='workflow-summary',
+ context=(IWfSharedContent, IPyAMSLayer, SharedContentSummaryForm),
+ provides=IInnerTabForm)
+class WfSharedContentWorkflowSummary(InnerDisplayForm):
+ """Shared content workflow summary"""
+
+ weight = 10
+ tab_label = _("Workflow")
+ tab_target = 'workflow-summary.html'
+
+ fields = field.Fields(Interface)
+
+
+@pagelet_config(name='workflow-summary.html', context=IWfSharedContent, layer=IPyAMSLayer)
+@implementer(IInnerPage, IInnerTabForm)
+class WorkflowSummaryDisplayForm(InnerDisplayForm):
+ """Workflow summary display form"""
+
+ @property
+ def fields(self):
+ fields = field.Fields(IWorkflowState).omit('history') + \
+ field.Fields(IWorkflowPublicationInfo)
+ workflow = IWorkflow(self.context)
+ if IWorkflowState(self.context).state not in workflow.waiting_states:
+ fields = fields.omit('state_urgency')
+ return fields
+
+ def updateWidgets(self, prefix=None):
+ super(WorkflowSummaryDisplayForm, self).updateWidgets(prefix)
+ state = IWorkflowState(self.context)
+ content = get_parent(self.context, IWorkflowManagedContent)
+ workflow = get_utility(IWorkflow, name=content.workflow_name)
+ self.widgets['state'].value = self.request.localizer.translate(workflow.get_state_label(state.state))
+ self.widgets['state_date'].value = format_datetime(tztime(state.state_date))
+ info = IWorkflowPublicationInfo(self.context)
+ if info.publication_date:
+ self.widgets['publication_date'].value = format_datetime(tztime(info.publication_date))
+ if info.first_publication_date:
+ self.widgets['first_publication_date'].value = format_datetime(tztime(info.first_publication_date))
+ if info.publication_effective_date:
+ self.widgets['publication_effective_date'].value = format_datetime(tztime(info.publication_effective_date))
+ if info.publication_expiration_date:
+ self.widgets['publication_expiration_date'].value = format_datetime((tztime(info.publication_expiration_date)))
+
+
+#
+# Generic transition info
+#
+
+@viewlet_config(name='wf-transition-info', context=IWfSharedContent, layer=IPyAMSLayer,
+ view=WorkflowContentTransitionForm, manager=IFormSuffixViewletsManager, weight=10)
+@template_config(template='templates/wf-transition-info.pt')
+class WorkflowContentTransitionFormInfo(Viewlet):
+ """Publication request form info message"""
+
+ @property
+ def previous_step(self):
+ translate = self.request.localizer.translate
+ workflow = IWorkflow(self.context)
+ state = IWorkflowState(self.context)
+ adapter = self.request.registry.queryAdapter(workflow, IWorkflowStateLabel,
+ name=state.state)
+ if adapter is None:
+ adapter = self.request.registry.queryAdapter(workflow, IWorkflowStateLabel)
+ if adapter is not None:
+ state_label = adapter.get_label(self.context, request=self.request)
+ else:
+ security = get_utility(ISecurityManager)
+ state_label = translate(_("{state} by {principal}")).format(
+ state=translate(workflow.get_state_label(state.state)),
+ principal=security.get_principal(state.state_principal).title)
+ return translate(_("{state} {date}")).format(state=state_label,
+ date=format_datetime(state.state_date, request=self.request))
+
+ @property
+ def previous_message(self):
+ workflow = IWorkflow(self.context)
+ state = IWorkflowState(self.context)
+ position = 0
+ history_item = None
+ trigger = SYSTEM
+ while trigger != MANUAL:
+ position -= 1
+ history_item = state.history[position]
+ if history_item.transition_id:
+ trigger = workflow.get_transition_by_id(history_item.transition_id).trigger
+ else:
+ break
+ if history_item:
+ return text_to_html((history_item.comment or '').strip())
+
+ @property
+ def next_step(self):
+ transition = self.__parent__.transition
+ return self.request.localizer.translate(transition.user_data.get('next_step')) \
+ if 'next_step' in transition.user_data else None
+
+
+#
+# Request publication form
+#
+
+class IPublicationRequestButtons(Interface):
+ """Shared content publication request buttons"""
+
+ close = CloseButton(name='close', title=_("Cancel"))
+ action = button.Button(name='action', title=_("Request publication"))
+
+
+@pagelet_config(name='wf-propose.html', context=IWfSharedContent, layer=IPyAMSLayer, permission='pyams.ManageContent')
+class PublicationRequestForm(WorkflowContentTransitionForm):
+ """Shared content publication request form"""
+
+ fields = field.Fields(IWorkflowTransitionInfo) + \
+ field.Fields(IWorkflowPublicationInfo).select('publication_effective_date',
+ 'publication_expiration_date') + \
+ field.Fields(IWorkflowRequestUrgencyInfo) + \
+ field.Fields(IWorkflowCommentInfo)
+ buttons = button.Buttons(IPublicationRequestButtons)
+ ajax_handler = 'wf-propose.json'
+
+ def updateWidgets(self, prefix=None):
+ super(PublicationRequestForm, self).updateWidgets(prefix)
+ self.widgets['publication_effective_date'].required = True
+ self.widgets['publication_effective_date'].value = datetime.now().strftime('%d/%m/%y %H:%M')
+ self.widgets['comment'].required = True
+
+ def createAndAdd(self, data):
+ pub_info = IWorkflowPublicationInfo(self.context)
+ pub_info.publication_effective_date = data.get('publication_effective_date')
+ pub_info.publication_expiration_date = data.get('publication_expiration_date')
+ return super(PublicationRequestForm, self).createAndAdd(data)
+
+
+@view_config(name='wf-propose.json', context=IWfSharedContent, request_type=IPyAMSLayer,
+ permission='pyams.ManageContent', renderer='json', xhr=True)
+class PublicationRequestAJAXForm(WorkflowContentTransitionAJAXForm, PublicationRequestForm):
+ """Shared content publication request form, JSON renderer"""
+
+
+@subscriber(IDataExtractedEvent, form_selector=PublicationRequestForm)
+def handle_publication_request_form_data_extraction(event):
+ """Handle publication request form data extraction"""
+ if not event.data.get('publication_effective_date'):
+ event.form.widgets.errors += (Invalid(_("Publication start date is required")), )
+ comment = (event.data.get('comment') or '').strip()
+ if not comment:
+ event.form.widgets.errors += (Invalid(_("A comment is required")), )
+
+
+@viewlet_config(name='wf-propose-owner-warning', context=IWfSharedContent, layer=IPyAMSLayer,
+ view=PublicationRequestForm, manager=IFormPrefixViewletsManager, weight=10)
+@template_config(template='templates/wf-owner-warning.pt')
+class PublicationRequestFormWarning(Viewlet):
+ """Publication request form warning message"""
+
+ def __new__(cls, context, request, view, manager):
+ if request.principal.id in context.owner:
+ return None
+ return Viewlet.__new__(cls)
+
+
+@viewlet_config(name='wf-propose-message', context=IWfSharedContent, layer=IPyAMSLayer, view=PublicationRequestForm,
+ manager=IWidgetsPrefixViewletsManager, weight=20)
+@template_config(template='templates/wf-propose-message.pt')
+class PublicationRequestFormMessage(Viewlet):
+ """Publication request form info message"""
+
+
+#
+# Cancel publication request form
+#
+
+class IPublicationRequestCancelButtons(Interface):
+ """Shared content publication request cancel buttons"""
+
+ close = CloseButton(name='close', title=_("Cancel"))
+ action = button.Button(name='action', title=_("Cancel publication request"))
+
+
+@pagelet_config(name='wf-cancel-propose.html', context=IWfSharedContent, layer=IPyAMSLayer,
+ permission='pyams.ManageContent')
+class PublicationRequestCancelForm(WorkflowContentTransitionForm):
+ """Shared content publication request cancel form"""
+
+ buttons = button.Buttons(IPublicationRequestCancelButtons)
+ ajax_handler = 'wf-cancel-propose.json'
+
+
+@view_config(name='wf-cancel-propose.json', context=IWfSharedContent, request_type=IPyAMSLayer,
+ permission='pyams.ManageContent', renderer='json', xhr=True)
+class PublicationRequestCancelAJAXForm(WorkflowContentTransitionAJAXForm, PublicationRequestCancelForm):
+ """Shared content publication request cancel form, JSON renderer"""
+
+
+@viewlet_config(name='wf-cancel-propose-owner-warning', context=IWfSharedContent, layer=IPyAMSLayer,
+ view=PublicationRequestCancelForm, manager=IFormPrefixViewletsManager, weight=10)
+@template_config(template='templates/wf-owner-warning.pt')
+class PublicationRequestCancelFormWarning(Viewlet):
+ """Publication request cancel form warning message"""
+
+ def __new__(cls, context, request, view, manager):
+ if request.principal.id in context.owner:
+ return None
+ return Viewlet.__new__(cls)
+
+
+@viewlet_config(name='wf-cancel-propose-message', context=IWfSharedContent, layer=IPyAMSLayer,
+ view=PublicationRequestCancelForm, manager=IWidgetsPrefixViewletsManager, weight=20)
+@template_config(template='templates/wf-cancel-propose-message.pt')
+class PublicationRequestCancelFormMessage(Viewlet):
+ """Publication request cancel form info message"""
+
+
+#
+# Refuse publication form
+#
+
+class IPublicationRequestRefuseButtons(Interface):
+ """Shared content publication request refuse buttons"""
+
+ close = CloseButton(name='close', title=_("Cancel"))
+ action = button.Button(name='action', title=_("Refuse publication request"))
+
+
+@pagelet_config(name='wf-refuse.html', context=IWfSharedContent, layer=IPyAMSLayer,
+ permission='pyams.PublishContent')
+class PublicationRequestRefuseForm(WorkflowContentTransitionForm):
+ """Shared content publication request refuse form"""
+
+ buttons = button.Buttons(IPublicationRequestRefuseButtons)
+ ajax_handler = 'wf-refuse.json'
+
+ def updateWidgets(self, prefix=None):
+ super(PublicationRequestRefuseForm, self).updateWidgets(prefix)
+ self.widgets['comment'].required = True
+
+
+@view_config(name='wf-refuse.json', context=IWfSharedContent, request_type=IPyAMSLayer,
+ permission='pyams.PublishContent', renderer='json', xhr=True)
+class PublicationRequestRefuseAJAXForm(WorkflowContentTransitionAJAXForm, PublicationRequestRefuseForm):
+ """Shared content publication request refuse form, JSON renderer"""
+
+
+@subscriber(IDataExtractedEvent, form_selector=PublicationRequestRefuseForm)
+def handle_publication_request_refuse_form_data_extraction(event):
+ """Handle publication request refuse form data extraction"""
+ comment = (event.data.get('comment') or '').strip()
+ if not comment:
+ event.form.widgets.errors += (Invalid(_("A comment is required")), )
+
+
+@viewlet_config(name='wf-refuse-operator-warning', context=IWfSharedContent, layer=IPyAMSLayer,
+ view=PublicationRequestRefuseForm, manager=IFormPrefixViewletsManager, weight=10)
+@template_config(template='templates/wf-operator-warning.pt')
+class PublicationRequestRefuseFormWarning(Viewlet):
+ """Publication request refuse form warning message"""
+
+ def __new__(cls, context, request, view, manager):
+ state = IWorkflowState(context)
+ if state.state_principal in context.owner:
+ return None
+ return Viewlet.__new__(cls)
+
+
+@viewlet_config(name='wf-refuse-message', context=IWfSharedContent, layer=IPyAMSLayer,
+ view=PublicationRequestRefuseForm, manager=IWidgetsPrefixViewletsManager, weight=20)
+@template_config(template='templates/wf-refuse-propose-message.pt')
+class PublicationRequestRefuseFormMessage(Viewlet):
+ """Publication request refuse form info message"""
+
+
+#
+# Publish form
+#
+
+class IPublicationButtons(Interface):
+ """Shared content publication buttons"""
+
+ close = CloseButton(name='close', title=_("Cancel"))
+ action = button.Button(name='action', title=_("Publish"))
+
+
+@pagelet_config(name='wf-publish.html', context=IWfSharedContent, layer=IPyAMSLayer, permission='pyams.PublishContent')
+class PublicationForm(WorkflowContentTransitionForm):
+ """Shared content publication form"""
+
+ fields = field.Fields(IWorkflowTransitionInfo) + \
+ field.Fields(IWorkflowPublicationInfo).select('publication_effective_date',
+ 'publication_expiration_date') + \
+ field.Fields(IWorkflowCommentInfo)
+ buttons = button.Buttons(IPublicationButtons)
+ ajax_handler = 'wf-publish.json'
+
+ def updateWidgets(self, prefix=None):
+ super(PublicationForm, self).updateWidgets(prefix)
+ pub_info = IWorkflowPublicationInfo(self.context)
+ self.widgets['publication_effective_date'].required = True
+ if ('publication_effective_date' in self.widgets) and pub_info.publication_effective_date:
+ self.widgets['publication_effective_date'].value = \
+ tztime(pub_info.publication_effective_date).strftime('%d/%m/%y %H:%M')
+ if ('publication_expiration_date' in self.widgets) and pub_info.publication_expiration_date:
+ self.widgets['publication_expiration_date'].value = \
+ tztime(pub_info.publication_expiration_date).strftime('%d/%m/%y %H:%M')
+
+ def createAndAdd(self, data):
+ pub_info = IWorkflowPublicationInfo(self.context)
+ pub_info.publication_effective_date = data.get('publication_effective_date')
+ pub_info.publication_expiration_date = data.get('publication_expiration_date')
+ return super(PublicationForm, self).createAndAdd(data)
+
+
+@view_config(name='wf-publish.json', context=IWfSharedContent, request_type=IPyAMSLayer,
+ permission='pyams.PublishContent', renderer='json', xhr=True)
+class PublicationAJAXForm(WorkflowContentTransitionAJAXForm, PublicationForm):
+ """Shared content publication form, JSON renderer"""
+
+
+@subscriber(IDataExtractedEvent, form_selector=PublicationForm)
+def handle_publication_form_data_extraction(event):
+ """Handle publication form data extraction"""
+ if not event.data.get('publication_effective_date'):
+ event.form.widgets.errors += (Invalid(_("Publication start date is required")), )
+
+
+@viewlet_config(name='wf-publish-operator-warning', context=IWfSharedContent, layer=IPyAMSLayer,
+ view=PublicationForm, manager=IFormPrefixViewletsManager, weight=10)
+@template_config(template='templates/wf-operator-warning.pt')
+class PublicationFormWarning(Viewlet):
+ """Shared content publication form warning message"""
+
+ def __new__(cls, context, request, view, manager):
+ state = IWorkflowState(context)
+ if state.state_principal in context.owner:
+ return None
+ return Viewlet.__new__(cls)
+
+
+@viewlet_config(name='wf-publish-message', context=IWfSharedContent, layer=IPyAMSLayer,
+ view=PublicationForm, manager=IWidgetsPrefixViewletsManager, weight=20)
+@template_config(template='templates/wf-publish-message.pt')
+class PublicationFormMessage(Viewlet):
+ """Shared content publication form info message"""
+
+
+#
+# Publication retire request form
+#
+
+class IPublicationRetireRequestButtons(Interface):
+ """Shared content publication retire request buttons"""
+
+ close = CloseButton(name='close', title=_("Cancel"))
+ action = button.Button(name='action', title=_("Request retire"))
+
+
+@pagelet_config(name='wf-retiring.html', context=IWfSharedContent, layer=IPyAMSLayer,
+ permission='pyams.ManageContent')
+class PublicationRetireRequestForm(WorkflowContentTransitionForm):
+ """Shared content publication request refuse form"""
+
+ fields = field.Fields(IWorkflowTransitionInfo) + \
+ field.Fields(IWorkflowRequestUrgencyInfo) + \
+ field.Fields(IWorkflowCommentInfo)
+ buttons = button.Buttons(IPublicationRetireRequestButtons)
+ ajax_handler = 'wf-retiring.json'
+
+ def updateWidgets(self, prefix=None):
+ super(PublicationRetireRequestForm, self).updateWidgets(prefix)
+ self.widgets['comment'].required = True
+
+
+@view_config(name='wf-retiring.json', context=IWfSharedContent, request_type=IPyAMSLayer,
+ permission='pyams.ManageContent', renderer='json', xhr=True)
+class PublicationRetireRequestAJAXForm(WorkflowContentTransitionAJAXForm, PublicationRetireRequestForm):
+ """Shared content publication retire request form, JSON renderer"""
+
+
+@subscriber(IDataExtractedEvent, form_selector=PublicationRetireRequestForm)
+def handle_publication_retire_request_form_data_extraction(event):
+ """Handle publication retire request form data extraction"""
+ comment = (event.data.get('comment') or '').strip()
+ if not comment:
+ event.form.widgets.errors += (Invalid(_("A comment is required")), )
+
+
+@viewlet_config(name='wf-retiring-owner-warning', context=IWfSharedContent, layer=IPyAMSLayer,
+ view=PublicationRetireRequestForm, manager=IFormPrefixViewletsManager, weight=10)
+@template_config(template='templates/wf-owner-warning.pt')
+class PublicationRetireRequestFormWarning(Viewlet):
+ """Publication retire request form warning message"""
+
+ def __new__(cls, context, request, view, manager):
+ if request.principal.id in context.owner:
+ return None
+ return Viewlet.__new__(cls)
+
+
+@viewlet_config(name='wf-retiring-message', context=IWfSharedContent, layer=IPyAMSLayer,
+ view=PublicationRetireRequestForm, manager=IWidgetsPrefixViewletsManager, weight=20)
+@template_config(template='templates/wf-retiring-message.pt')
+class PublicationRetireRequestFormMessage(Viewlet):
+ """Publication retire request form info message"""
+
+
+#
+# Publication retire cancel form
+#
+
+class IPublicationRetireCancelButtons(Interface):
+ """Shared content publication retire request cancel buttons"""
+
+ close = CloseButton(name='close', title=_("Cancel"))
+ action = button.Button(name='action', title=_("Cancel retire request"))
+
+
+@pagelet_config(name='wf-cancel-retiring.html', context=IWfSharedContent, layer=IPyAMSLayer,
+ permission='pyams.ManageContent')
+class PublicationRetireCancelForm(WorkflowContentTransitionForm):
+ """Shared content publication retire request cancel form"""
+
+ buttons = button.Buttons(IPublicationRetireCancelButtons)
+ ajax_handler = 'wf-cancel-retiring.json'
+
+
+@view_config(name='wf-cancel-retiring.json', context=IWfSharedContent, request_type=IPyAMSLayer,
+ permission='pyams.ManageContent', renderer='json', xhr=True)
+class PublicationRetireCancelAJAXForm(WorkflowContentTransitionAJAXForm, PublicationRetireCancelForm):
+ """Shared content publication retire request cancel form, JSON renderer"""
+
+
+@viewlet_config(name='wf-cancel-retiring-owner-warning', context=IWfSharedContent, layer=IPyAMSLayer,
+ view=PublicationRetireCancelForm, manager=IFormPrefixViewletsManager, weight=10)
+@template_config(template='templates/wf-owner-warning.pt')
+class PublicationRetireCancelFormWarning(Viewlet):
+ """Publication retire request cancel form warning message"""
+
+ def __new__(cls, context, request, view, manager):
+ if request.principal.id in context.owner:
+ return None
+ return Viewlet.__new__(cls)
+
+
+@viewlet_config(name='wf-cancel-retiring-message', context=IWfSharedContent, layer=IPyAMSLayer,
+ view=PublicationRetireCancelForm, manager=IWidgetsPrefixViewletsManager, weight=20)
+@template_config(template='templates/wf-cancel-retiring-message.pt')
+class PublicationRetireCancelFormMessage(Viewlet):
+ """Publication retire request form info message"""
+
+
+#
+# Publication retire form
+#
+
+class IPublicationRetireButtons(Interface):
+ """Shared content publication retire buttons"""
+
+ close = CloseButton(name='close', title=_("Cancel"))
+ action = button.Button(name='action', title=_("Retire"))
+
+
+@pagelet_config(name='wf-retire.html', context=IWfSharedContent, layer=IPyAMSLayer,
+ permission='pyams.PublishContent')
+class PublicationRetireForm(WorkflowContentTransitionForm):
+ """Shared content publication retire form"""
+
+ buttons = button.Buttons(IPublicationRetireButtons)
+ ajax_handler = 'wf-retire.json'
+
+
+@view_config(name='wf-retire.json', context=IWfSharedContent, request_type=IPyAMSLayer,
+ permission='pyams.PublishContent', renderer='json', xhr=True)
+class PublicationRetireAJAXForm(WorkflowContentTransitionAJAXForm, PublicationRetireForm):
+ """Shared content publication retire form, JSON renderer"""
+
+
+@viewlet_config(name='wf-retire-operator-warning', context=IWfSharedContent, layer=IPyAMSLayer,
+ view=PublicationRetireForm, manager=IFormPrefixViewletsManager, weight=10)
+@template_config(template='templates/wf-operator-warning.pt')
+class PublicationRetireFormWarning(Viewlet):
+ """Publication retire form warning message"""
+
+ def __new__(cls, context, request, view, manager):
+ state = IWorkflowState(context)
+ if state.state_principal in context.owner:
+ return None
+ return Viewlet.__new__(cls)
+
+
+@viewlet_config(name='wf-retire-message', context=IWfSharedContent, layer=IPyAMSLayer,
+ view=PublicationRetireForm, manager=IWidgetsPrefixViewletsManager, weight=20)
+@template_config(template='templates/wf-retire-message.pt')
+class PublicationRetireFormMessage(Viewlet):
+ """Publication retire form info message"""
+
+
+#
+# Publication archive request form
+#
+
+class IPublicationArchiveRequestButtons(Interface):
+ """Shared content publication archive request buttons"""
+
+ close = CloseButton(name='close', title=_("Cancel"))
+ action = button.Button(name='action', title=_("Request archive"))
+
+
+@pagelet_config(name='wf-archiving.html', context=IWfSharedContent, layer=IPyAMSLayer,
+ permission='pyams.ManageContent')
+class PublicationArchiveRequestForm(WorkflowContentTransitionForm):
+ """Shared content publication request archive form"""
+
+ fields = field.Fields(IWorkflowTransitionInfo) + \
+ field.Fields(IWorkflowRequestUrgencyInfo) + \
+ field.Fields(IWorkflowCommentInfo)
+ buttons = button.Buttons(IPublicationArchiveRequestButtons)
+ ajax_handler = 'wf-archiving.json'
+
+ def updateWidgets(self, prefix=None):
+ super(PublicationArchiveRequestForm, self).updateWidgets(prefix)
+ self.widgets['comment'].required = True
+
+
+@view_config(name='wf-archiving.json', context=IWfSharedContent, request_type=IPyAMSLayer,
+ permission='pyams.ManageContent', renderer='json', xhr=True)
+class PublicationArchiveRequestAJAXForm(WorkflowContentTransitionAJAXForm, PublicationArchiveRequestForm):
+ """Shared content publication archive request form, JSON renderer"""
+
+
+@subscriber(IDataExtractedEvent, form_selector=PublicationArchiveRequestForm)
+def handle_archive_request_form_data_extraction(event):
+ """Handle archive request form data extraction"""
+ comment = (event.data.get('comment') or '').strip()
+ if not comment:
+ event.form.widgets.errors += (Invalid(_("A comment is required")), )
+
+
+@viewlet_config(name='wf-archiving-owner-warning', context=IWfSharedContent, layer=IPyAMSLayer,
+ view=PublicationArchiveRequestForm, manager=IFormPrefixViewletsManager, weight=10)
+@template_config(template='templates/wf-owner-warning.pt')
+class PublicationArchiveRequestFormWarning(Viewlet):
+ """Publication archive request form warning message"""
+
+ def __new__(cls, context, request, view, manager):
+ if request.principal.id in context.owner:
+ return None
+ return Viewlet.__new__(cls)
+
+
+@viewlet_config(name='wf-archiving-message', context=IWfSharedContent, layer=IPyAMSLayer,
+ view=PublicationArchiveRequestForm, manager=IWidgetsPrefixViewletsManager, weight=20)
+@template_config(template='templates/wf-archiving-message.pt')
+class PublicationArchiveRequestFormMessage(Viewlet):
+ """Publication archive request form info message"""
+
+
+#
+# Publication archive cancel form
+#
+
+class IPublicationArchiveCancelButtons(Interface):
+ """Shared content publication archive request cancel buttons"""
+
+ close = CloseButton(name='close', title=_("Cancel"))
+ action = button.Button(name='action', title=_("Cancel archive request"))
+
+
+@pagelet_config(name='wf-cancel-archiving.html', context=IWfSharedContent, layer=IPyAMSLayer,
+ permission='pyams.ManageContent')
+class PublicationArchiveCancelForm(WorkflowContentTransitionForm):
+ """Shared content publication archive request cancel form"""
+
+ buttons = button.Buttons(IPublicationArchiveCancelButtons)
+ ajax_handler = 'wf-cancel-archiving.json'
+
+
+@view_config(name='wf-cancel-archiving.json', context=IWfSharedContent, request_type=IPyAMSLayer,
+ permission='pyams.ManageContent', renderer='json', xhr=True)
+class PublicationArchiveCancelAJAXForm(WorkflowContentTransitionAJAXForm, PublicationArchiveCancelForm):
+ """Shared content publication archive request cancel form, JSON renderer"""
+
+
+@viewlet_config(name='wf-cancel-archiving-owner-warning', context=IWfSharedContent, layer=IPyAMSLayer,
+ view=PublicationArchiveCancelForm, manager=IFormPrefixViewletsManager, weight=10)
+@template_config(template='templates/wf-owner-warning.pt')
+class PublicationArchiveCancelFormWarning(Viewlet):
+ """Publication archive cancel form warning message"""
+
+ def __new__(cls, context, request, view, manager):
+ if request.principal.id in context.owner:
+ return None
+ return Viewlet.__new__(cls)
+
+
+@viewlet_config(name='wf-cancel-archiving-message', context=IWfSharedContent, layer=IPyAMSLayer,
+ view=PublicationArchiveCancelForm, manager=IWidgetsPrefixViewletsManager, weight=20)
+@template_config(template='templates/wf-cancel-archiving-message.pt')
+class PublicationArchiveCancelFormMessage(Viewlet):
+ """Publication archive cancel form info message"""
+
+
+#
+# Publication archive form
+#
+
+class IPublicationArchiveButtons(Interface):
+ """Shared content publication archive buttons"""
+
+ close = CloseButton(name='close', title=_("Cancel"))
+ action = button.Button(name='action', title=_("Archive"))
+
+
+@pagelet_config(name='wf-archive.html', context=IWfSharedContent, layer=IPyAMSLayer,
+ permission='pyams.PublishContent')
+class PublicationArchiveForm(WorkflowContentTransitionForm):
+ """Shared content publication archive form"""
+
+ buttons = button.Buttons(IPublicationArchiveButtons)
+ ajax_handler = 'wf-archive.json'
+
+
+@view_config(name='wf-archive.json', context=IWfSharedContent, request_type=IPyAMSLayer,
+ permission='pyams.PublishContent', renderer='json', xhr=True)
+class PublicationArchiveAJAXForm(WorkflowContentTransitionAJAXForm, PublicationArchiveForm):
+ """Shared content publication archive form, JSON renderer"""
+
+
+@viewlet_config(name='wf-archive-operator-warning', context=IWfSharedContent, layer=IPyAMSLayer,
+ view=PublicationArchiveForm, manager=IFormPrefixViewletsManager, weight=10)
+@template_config(template='templates/wf-operator-warning.pt')
+class PublicationArchiveFormWarning(Viewlet):
+ """Publication archive form warning message"""
+
+ def __new__(cls, context, request, view, manager):
+ state = IWorkflowState(context)
+ if state.state_principal in context.owner:
+ return None
+ return Viewlet.__new__(cls)
+
+
+@viewlet_config(name='wf-archive-message', context=IWfSharedContent, layer=IPyAMSLayer,
+ view=PublicationArchiveForm, manager=IWidgetsPrefixViewletsManager, weight=20)
+@template_config(template='templates/wf-archive-message.pt')
+class PublicationArchiveFormMessage(Viewlet):
+ """Publication archive form info message"""
+
+
+#
+# Clone form
+#
+
+class ISharedContentCloneButtons(Interface):
+ """Shared content clone buttons"""
+
+ close = CloseButton(name='close', title=_("Cancel"))
+ action = button.Button(name='action', title=_("Create new version"))
+
+
+@pagelet_config(name='wf-clone.html', context=IWfSharedContent, layer=IPyAMSLayer, permission='pyams.CreateContent')
+class SharedContentCloneForm(WorkflowContentTransitionForm):
+ """Shared content clone form"""
+
+ buttons = button.Buttons(ISharedContentCloneButtons)
+ ajax_handler = 'wf-clone.json'
+
+ def createAndAdd(self, data):
+ info = IWorkflowInfo(self.context)
+ return info.fire_transition_toward(DRAFT, comment=data.get('comment'))
+
+
+@view_config(name='wf-clone.json', context=IWfSharedContent, request_type=IPyAMSLayer,
+ permission='pyams.CreateContent', renderer='json', xhr=True)
+class SharedContentCloneAJAXForm(AJAXAddForm, SharedContentCloneForm):
+ """Shared content clone form, JSON rendener"""
+
+ def get_ajax_output(self, changes):
+ return {'status': 'redirect',
+ 'location': absolute_url(changes, self.request, 'admin.html#properties.html')}
+
+
+@viewlet_config(name='wf-clone-owner-warning', context=IWfSharedContent, layer=IPyAMSLayer,
+ view=SharedContentCloneForm, manager=IFormPrefixViewletsManager, weight=10)
+@template_config(template='templates/wf-owner-warning.pt')
+class SharedContentCloneFormWarning(Viewlet):
+ """Shared content clone form warning message"""
+
+ def __new__(cls, context, request, view, manager):
+ if request.principal.id in context.owner:
+ return None
+ return Viewlet.__new__(cls)
+
+
+@viewlet_config(name='wf-clone-message', context=IWfSharedContent, layer=IPyAMSLayer,
+ view=SharedContentCloneForm, manager=IWidgetsPrefixViewletsManager, weight=20)
+@template_config(template='templates/wf-clone-message.pt')
+class SharedContentCloneFormMessage(Viewlet):
+ """Shared content clone form info message"""
+
+
+#
+# Delete form
+#
+
+class ISharedContentDeleteButtons(Interface):
+ """Shared content delete form buttons"""
+
+ close = CloseButton(name='close', title=_("Cancel"))
+ action = button.Button(name='action', title=_("Delete version"))
+
+
+@pagelet_config(name='wf-delete.html', context=IWfSharedContent, layer=IPyAMSLayer, permission='pyams.ManageContent')
+class SharedContentDeleteForm(WorkflowContentTransitionForm):
+ """Shared content delete form"""
+
+ buttons = button.Buttons(ISharedContentDeleteButtons)
+ ajax_handler = 'wf-delete.json'
+
+ def createAndAdd(self, data):
+ state = IWorkflowState(self.context)
+ if state.version_id == 1: # remove the first and only version => remove all
+ content = get_parent(self.context, ISharedContent)
+ self.__target = get_parent(content, ISharedTool)
+ del content.__parent__[content.__name__]
+ else:
+ self.__target = get_parent(self.context, ISharedTool)
+ IWorkflowVersions(self.context).remove_version(state.version_id, state=DELETED, comment=data.get('comment'))
+
+
+@view_config(name='wf-delete.json', context=IWfSharedContent, request_type=IPyAMSLayer,
+ permission='pyams.ManageContent', renderer='json', xhr=True)
+class SharedContentDeleteAJAXForm(AJAXAddForm, SharedContentDeleteForm):
+ """Shared content delete form, JSON rendener"""
+
+ def get_ajax_output(self, changes):
+ return {'status': 'redirect',
+ 'location': absolute_url(self._SharedContentDeleteForm__target, self.request, 'admin.html')}
+
+
+@viewlet_config(name='wf-delete-owner-warning', context=IWfSharedContent, layer=IPyAMSLayer,
+ view=SharedContentDeleteForm, manager=IFormPrefixViewletsManager, weight=10)
+@template_config(template='templates/wf-owner-warning.pt')
+class SharedContentDeleteFormWarning(Viewlet):
+ """Shared content delete form warning message"""
+
+ def __new__(cls, context, request, view, manager):
+ if request.principal.id in context.owner:
+ return None
+ return Viewlet.__new__(cls)
+
+
+@viewlet_config(name='wf-delete-message', context=IWfSharedContent, layer=IPyAMSLayer,
+ view=SharedContentDeleteForm, manager=IWidgetsPrefixViewletsManager, weight=20)
+@template_config(template='templates/wf-delete-message.pt')
+class SharedContentDeleteFormMessage(Viewlet):
+ """Shared content delete form info message"""