# HG changeset patch # User Thierry Florac # Date 1499853177 -7200 # Node ID dfa050606268777402aee419fab162a7110284a6 # Parent 9911354377986a869cc87f2dcd1f45d5a9121f88 Added workflow "push end date" attribute and checks on publication effective and expiration dates diff -r 991135437798 -r dfa050606268 src/pyams_content/shared/common/zmi/workflow.py --- a/src/pyams_content/shared/common/zmi/workflow.py Wed Jul 12 11:52:02 2017 +0200 +++ b/src/pyams_content/shared/common/zmi/workflow.py Wed Jul 12 11:52:57 2017 +0200 @@ -19,24 +19,21 @@ # import interfaces from pyams_content.interfaces import PUBLISH_CONTENT_PERMISSION, CREATE_CONTENT_PERMISSION, MANAGE_CONTENT_PERMISSION from pyams_content.shared.common.interfaces import IWfSharedContent, ISharedTool, ISharedContent -from pyams_form.interfaces.form import IInnerTabForm, IFormPrefixViewletsManager, IWidgetsPrefixViewletsManager, \ +from pyams_form.interfaces.form import 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, \ + IWorkflowCommentInfo, IWorkflowVersions, IWorkflowState, 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 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.text import text_to_html @@ -45,68 +42,15 @@ from pyams_utils.url import absolute_url from pyams_viewlet.viewlet import viewlet_config, Viewlet from pyams_workflow.zmi.transition import WorkflowContentTransitionForm, WorkflowContentTransitionAJAXForm -from pyams_zmi.form import InnerAdminDisplayForm 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 zope.interface import Interface, Invalid from pyams_content import _ # -# Workflow summary view -# - -@adapter_config(name='workflow-summary', - context=(IWfSharedContent, IPyAMSLayer, SharedContentSummaryForm), - provides=IInnerTabForm) -class WfSharedContentWorkflowSummary(InnerAdminDisplayForm): - """Shared content workflow summary""" - - weight = 990 - 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(InnerAdminDisplayForm): - """Workflow summary display form""" - - legend = _("Workflow details") - - @property - def fields(self): - fields = field.Fields(IWorkflowState).omit('history') + \ - field.Fields(IWorkflowPublicationInfo).omit('publication_date', 'publisher') - workflow = IWorkflow(self.context) - state = IWorkflowState(self.context).state - if state not in workflow.published_states: - fields = fields.omit('publication') - if 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.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 # @@ -179,7 +123,7 @@ """Shared content publication request form""" fields = field.Fields(IWorkflowTransitionInfo) + \ - field.Fields(IWorkflowPublicationInfo).select('publication_effective_date', + field.Fields(IWorkflowPublicationInfo).select('publication_effective_date', 'push_end_date', 'publication_expiration_date') + \ field.Fields(IWorkflowRequestUrgencyInfo) + \ field.Fields(IWorkflowCommentInfo) @@ -188,13 +132,24 @@ 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 + pub_info = IWorkflowPublicationInfo(self.context) + if 'publication_effective_date' in self.widgets: + widget = self.widgets['publication_effective_date'] + widget.required = True + widget_date = pub_info.publication_effective_date or datetime.now() + widget.value = widget_date.strftime('%d/%m/%y %H:%M') + if ('push_end_date' in self.widgets) and pub_info.push_end_date: + self.widgets['push_end_date'].value = tztime(pub_info.push_end_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') + if 'comment' in self.widgets: + 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.push_end_date = data.get('push_end_date') pub_info.publication_expiration_date = data.get('publication_expiration_date') return super(PublicationRequestForm, self).createAndAdd(data) @@ -208,11 +163,14 @@ @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'): + data = event.data + if not data.get('publication_effective_date'): event.form.widgets.errors += (Invalid(_("Publication start date is required")), ) - comment = (event.data.get('comment') or '').strip() + comment = (data.get('comment') or '').strip() if not comment: event.form.widgets.errors += (Invalid(_("A comment is required")), ) + if data.get('publication_expiration_date') and not data.get('push_end_date'): + data['push_end_date'] = data['publication_expiration_date'] @viewlet_config(name='wf-propose-message', context=IWfSharedContent, layer=IPyAMSLayer, view=PublicationRequestForm, @@ -354,7 +312,7 @@ """Shared content publication form""" fields = field.Fields(IWorkflowTransitionInfo) + \ - field.Fields(IWorkflowPublicationInfo).select('publication_effective_date', + field.Fields(IWorkflowPublicationInfo).select('publication_effective_date', 'push_end_date', 'publication_expiration_date') + \ field.Fields(IWorkflowCommentInfo) buttons = button.Buttons(IPublicationButtons) @@ -363,10 +321,14 @@ 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_effective_date' in self.widgets: + self.widgets['publication_effective_date'].required = True + if pub_info.publication_effective_date: + self.widgets['publication_effective_date'].value = \ + tztime(pub_info.publication_effective_date).strftime('%d/%m/%y %H:%M') + if ('push_end_date' in self.widgets) and pub_info.push_end_date: + self.widgets['push_end_date'].value = \ + tztime(pub_info.push_end_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') @@ -374,6 +336,7 @@ def createAndAdd(self, data): pub_info = IWorkflowPublicationInfo(self.context) pub_info.publication_effective_date = data.get('publication_effective_date') + pub_info.push_end_date = data.get('push_end_date') pub_info.publication_expiration_date = data.get('publication_expiration_date') return super(PublicationForm, self).createAndAdd(data) @@ -387,8 +350,11 @@ @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'): + data = event.data + if not data.get('publication_effective_date'): event.form.widgets.errors += (Invalid(_("Publication start date is required")), ) + if data.get('publication_expiration_date') and not data.get('push_end_date'): + data['push_end_date'] = data['publication_expiration_date'] @viewlet_config(name='wf-publish-operator-warning', context=IWfSharedContent, layer=IPyAMSLayer, @@ -584,10 +550,6 @@ 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=MANAGE_CONTENT_PERMISSION, renderer='json', xhr=True) @@ -595,14 +557,6 @@ """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-message', context=IWfSharedContent, layer=IPyAMSLayer, view=PublicationArchiveRequestForm, manager=IWidgetsPrefixViewletsManager, weight=20) @template_config(template='templates/wf-archiving-message.pt') @@ -785,6 +739,22 @@ buttons = button.Buttons(ISharedContentDeleteButtons) ajax_handler = 'wf-delete.json' + @property + def fields(self): + fields = super(SharedContentDeleteForm, self).fields + state = IWorkflowState(self.context) + if state.version_id == 1: # content deletion + fields = fields.omit('comment') + return fields + + @property + def legend(self): + state = IWorkflowState(self.context) + if state.version_id == 1: # content deletion + return self.request.localizer.translate(_("Delete content")) + else: + return super(SharedContentDeleteForm, self).legend + def updateActions(self): super(SharedContentDeleteForm, self).updateActions() if 'action' in self.actions: @@ -820,6 +790,11 @@ class SharedContentDeleteFormMessage(Viewlet): """Shared content delete form info message""" + @property + def version_id(self): + state = IWorkflowState(self.context) + return state.version_id + @viewlet_config(name='wf-delete-owner-warning', context=IWfSharedContent, layer=IPyAMSLayer, view=SharedContentDeleteForm, manager=IWidgetsPrefixViewletsManager, weight=30)