src/pyams_content/shared/common/zmi/workflow.py
changeset 0 7c0001cacf8e
child 14 234db8f05928
equal deleted inserted replaced
-1:000000000000 0:7c0001cacf8e
       
     1 #
       
     2 # Copyright (c) 2008-2015 Thierry Florac <tflorac AT ulthar.net>
       
     3 # All Rights Reserved.
       
     4 #
       
     5 # This software is subject to the provisions of the Zope Public License,
       
     6 # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
       
     7 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
       
     8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
       
     9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
       
    10 # FOR A PARTICULAR PURPOSE.
       
    11 #
       
    12 from pyams_utils.text import text_to_html
       
    13 
       
    14 __docformat__ = 'restructuredtext'
       
    15 
       
    16 
       
    17 # import standard library
       
    18 from datetime import datetime
       
    19 
       
    20 # import interfaces
       
    21 from pyams_content.shared.common.interfaces import IWfSharedContent, ISharedTool, ISharedContent
       
    22 from pyams_form.interfaces.form import IInnerTabForm, IFormPrefixViewletsManager, IWidgetsPrefixViewletsManager, \
       
    23     IFormSuffixViewletsManager
       
    24 from pyams_security.interfaces import ISecurityManager
       
    25 from pyams_skin.interfaces import IInnerPage
       
    26 from pyams_skin.layer import IPyAMSLayer
       
    27 from pyams_workflow.interfaces import IWorkflowInfo, IWorkflowTransitionInfo, IWorkflowPublicationInfo, \
       
    28     IWorkflowCommentInfo, IWorkflowVersions, IWorkflowState, IWorkflowManagedContent, IWorkflow, IWorkflowStateLabel, \
       
    29     IWorkflowRequestUrgencyInfo, SYSTEM, MANUAL
       
    30 from z3c.form.interfaces import IDataExtractedEvent
       
    31 
       
    32 # import packages
       
    33 from pyams_content.shared.common.zmi.summary import SharedContentSummaryForm
       
    34 from pyams_content.workflow import DRAFT, DELETED
       
    35 from pyams_form.form import AJAXAddForm, InnerDisplayForm
       
    36 from pyams_form.schema import CloseButton
       
    37 from pyams_pagelet.pagelet import pagelet_config
       
    38 from pyams_template.template import template_config
       
    39 from pyams_utils.adapter import adapter_config
       
    40 from pyams_utils.date import format_datetime
       
    41 from pyams_utils.registry import get_utility
       
    42 from pyams_utils.timezone import tztime
       
    43 from pyams_utils.traversing import get_parent
       
    44 from pyams_utils.url import absolute_url
       
    45 from pyams_viewlet.viewlet import viewlet_config, Viewlet
       
    46 from pyams_workflow.zmi.transition import WorkflowContentTransitionForm, WorkflowContentTransitionAJAXForm
       
    47 from pyramid.events import subscriber
       
    48 from pyramid.view import view_config
       
    49 from z3c.form import field, button
       
    50 from zope.interface import implementer, Interface, Invalid
       
    51 
       
    52 from pyams_content import _
       
    53 
       
    54 
       
    55 #
       
    56 # Workflow summary view
       
    57 #
       
    58 
       
    59 @adapter_config(name='workflow-summary',
       
    60                 context=(IWfSharedContent, IPyAMSLayer, SharedContentSummaryForm),
       
    61                 provides=IInnerTabForm)
       
    62 class WfSharedContentWorkflowSummary(InnerDisplayForm):
       
    63     """Shared content workflow summary"""
       
    64 
       
    65     weight = 10
       
    66     tab_label = _("Workflow")
       
    67     tab_target = 'workflow-summary.html'
       
    68 
       
    69     fields = field.Fields(Interface)
       
    70 
       
    71 
       
    72 @pagelet_config(name='workflow-summary.html', context=IWfSharedContent, layer=IPyAMSLayer)
       
    73 @implementer(IInnerPage, IInnerTabForm)
       
    74 class WorkflowSummaryDisplayForm(InnerDisplayForm):
       
    75     """Workflow summary display form"""
       
    76 
       
    77     @property
       
    78     def fields(self):
       
    79         fields = field.Fields(IWorkflowState).omit('history') + \
       
    80                  field.Fields(IWorkflowPublicationInfo)
       
    81         workflow = IWorkflow(self.context)
       
    82         if IWorkflowState(self.context).state not in workflow.waiting_states:
       
    83             fields = fields.omit('state_urgency')
       
    84         return fields
       
    85 
       
    86     def updateWidgets(self, prefix=None):
       
    87         super(WorkflowSummaryDisplayForm, self).updateWidgets(prefix)
       
    88         state = IWorkflowState(self.context)
       
    89         content = get_parent(self.context, IWorkflowManagedContent)
       
    90         workflow = get_utility(IWorkflow, name=content.workflow_name)
       
    91         self.widgets['state'].value = self.request.localizer.translate(workflow.get_state_label(state.state))
       
    92         self.widgets['state_date'].value = format_datetime(tztime(state.state_date))
       
    93         info = IWorkflowPublicationInfo(self.context)
       
    94         if info.publication_date:
       
    95             self.widgets['publication_date'].value = format_datetime(tztime(info.publication_date))
       
    96         if info.first_publication_date:
       
    97             self.widgets['first_publication_date'].value = format_datetime(tztime(info.first_publication_date))
       
    98         if info.publication_effective_date:
       
    99             self.widgets['publication_effective_date'].value = format_datetime(tztime(info.publication_effective_date))
       
   100         if info.publication_expiration_date:
       
   101             self.widgets['publication_expiration_date'].value = format_datetime((tztime(info.publication_expiration_date)))
       
   102 
       
   103 
       
   104 #
       
   105 # Generic transition info
       
   106 #
       
   107 
       
   108 @viewlet_config(name='wf-transition-info', context=IWfSharedContent, layer=IPyAMSLayer,
       
   109                 view=WorkflowContentTransitionForm, manager=IFormSuffixViewletsManager, weight=10)
       
   110 @template_config(template='templates/wf-transition-info.pt')
       
   111 class WorkflowContentTransitionFormInfo(Viewlet):
       
   112     """Publication request form info message"""
       
   113 
       
   114     @property
       
   115     def previous_step(self):
       
   116         translate = self.request.localizer.translate
       
   117         workflow = IWorkflow(self.context)
       
   118         state = IWorkflowState(self.context)
       
   119         adapter = self.request.registry.queryAdapter(workflow, IWorkflowStateLabel,
       
   120                                                      name=state.state)
       
   121         if adapter is None:
       
   122             adapter = self.request.registry.queryAdapter(workflow, IWorkflowStateLabel)
       
   123         if adapter is not None:
       
   124             state_label = adapter.get_label(self.context, request=self.request)
       
   125         else:
       
   126             security = get_utility(ISecurityManager)
       
   127             state_label = translate(_("{state} by {principal}")).format(
       
   128                 state=translate(workflow.get_state_label(state.state)),
       
   129                 principal=security.get_principal(state.state_principal).title)
       
   130         return translate(_("{state} {date}")).format(state=state_label,
       
   131                                                      date=format_datetime(state.state_date, request=self.request))
       
   132 
       
   133     @property
       
   134     def previous_message(self):
       
   135         workflow = IWorkflow(self.context)
       
   136         state = IWorkflowState(self.context)
       
   137         position = 0
       
   138         history_item = None
       
   139         trigger = SYSTEM
       
   140         while trigger != MANUAL:
       
   141             position -= 1
       
   142             history_item = state.history[position]
       
   143             if history_item.transition_id:
       
   144                 trigger = workflow.get_transition_by_id(history_item.transition_id).trigger
       
   145             else:
       
   146                 break
       
   147         if history_item:
       
   148             return text_to_html((history_item.comment or '').strip())
       
   149 
       
   150     @property
       
   151     def next_step(self):
       
   152         transition = self.__parent__.transition
       
   153         return self.request.localizer.translate(transition.user_data.get('next_step')) \
       
   154             if 'next_step' in transition.user_data else None
       
   155 
       
   156 
       
   157 #
       
   158 # Request publication form
       
   159 #
       
   160 
       
   161 class IPublicationRequestButtons(Interface):
       
   162     """Shared content publication request buttons"""
       
   163 
       
   164     close = CloseButton(name='close', title=_("Cancel"))
       
   165     action = button.Button(name='action', title=_("Request publication"))
       
   166 
       
   167 
       
   168 @pagelet_config(name='wf-propose.html', context=IWfSharedContent, layer=IPyAMSLayer, permission='pyams.ManageContent')
       
   169 class PublicationRequestForm(WorkflowContentTransitionForm):
       
   170     """Shared content publication request form"""
       
   171 
       
   172     fields = field.Fields(IWorkflowTransitionInfo) + \
       
   173              field.Fields(IWorkflowPublicationInfo).select('publication_effective_date',
       
   174                                                            'publication_expiration_date') + \
       
   175              field.Fields(IWorkflowRequestUrgencyInfo) + \
       
   176              field.Fields(IWorkflowCommentInfo)
       
   177     buttons = button.Buttons(IPublicationRequestButtons)
       
   178     ajax_handler = 'wf-propose.json'
       
   179 
       
   180     def updateWidgets(self, prefix=None):
       
   181         super(PublicationRequestForm, self).updateWidgets(prefix)
       
   182         self.widgets['publication_effective_date'].required = True
       
   183         self.widgets['publication_effective_date'].value = datetime.now().strftime('%d/%m/%y %H:%M')
       
   184         self.widgets['comment'].required = True
       
   185 
       
   186     def createAndAdd(self, data):
       
   187         pub_info = IWorkflowPublicationInfo(self.context)
       
   188         pub_info.publication_effective_date = data.get('publication_effective_date')
       
   189         pub_info.publication_expiration_date = data.get('publication_expiration_date')
       
   190         return super(PublicationRequestForm, self).createAndAdd(data)
       
   191 
       
   192 
       
   193 @view_config(name='wf-propose.json', context=IWfSharedContent, request_type=IPyAMSLayer,
       
   194              permission='pyams.ManageContent', renderer='json', xhr=True)
       
   195 class PublicationRequestAJAXForm(WorkflowContentTransitionAJAXForm, PublicationRequestForm):
       
   196     """Shared content publication request form, JSON renderer"""
       
   197 
       
   198 
       
   199 @subscriber(IDataExtractedEvent, form_selector=PublicationRequestForm)
       
   200 def handle_publication_request_form_data_extraction(event):
       
   201     """Handle publication request form data extraction"""
       
   202     if not event.data.get('publication_effective_date'):
       
   203         event.form.widgets.errors += (Invalid(_("Publication start date is required")), )
       
   204     comment = (event.data.get('comment') or '').strip()
       
   205     if not comment:
       
   206         event.form.widgets.errors += (Invalid(_("A comment is required")), )
       
   207 
       
   208 
       
   209 @viewlet_config(name='wf-propose-owner-warning', context=IWfSharedContent, layer=IPyAMSLayer,
       
   210                 view=PublicationRequestForm, manager=IFormPrefixViewletsManager, weight=10)
       
   211 @template_config(template='templates/wf-owner-warning.pt')
       
   212 class PublicationRequestFormWarning(Viewlet):
       
   213     """Publication request form warning message"""
       
   214 
       
   215     def __new__(cls, context, request, view, manager):
       
   216         if request.principal.id in context.owner:
       
   217             return None
       
   218         return Viewlet.__new__(cls)
       
   219 
       
   220 
       
   221 @viewlet_config(name='wf-propose-message', context=IWfSharedContent, layer=IPyAMSLayer, view=PublicationRequestForm,
       
   222                 manager=IWidgetsPrefixViewletsManager, weight=20)
       
   223 @template_config(template='templates/wf-propose-message.pt')
       
   224 class PublicationRequestFormMessage(Viewlet):
       
   225     """Publication request form info message"""
       
   226 
       
   227 
       
   228 #
       
   229 # Cancel publication request form
       
   230 #
       
   231 
       
   232 class IPublicationRequestCancelButtons(Interface):
       
   233     """Shared content publication request cancel buttons"""
       
   234 
       
   235     close = CloseButton(name='close', title=_("Cancel"))
       
   236     action = button.Button(name='action', title=_("Cancel publication request"))
       
   237 
       
   238 
       
   239 @pagelet_config(name='wf-cancel-propose.html', context=IWfSharedContent, layer=IPyAMSLayer,
       
   240                 permission='pyams.ManageContent')
       
   241 class PublicationRequestCancelForm(WorkflowContentTransitionForm):
       
   242     """Shared content publication request cancel form"""
       
   243 
       
   244     buttons = button.Buttons(IPublicationRequestCancelButtons)
       
   245     ajax_handler = 'wf-cancel-propose.json'
       
   246 
       
   247 
       
   248 @view_config(name='wf-cancel-propose.json', context=IWfSharedContent, request_type=IPyAMSLayer,
       
   249              permission='pyams.ManageContent', renderer='json', xhr=True)
       
   250 class PublicationRequestCancelAJAXForm(WorkflowContentTransitionAJAXForm, PublicationRequestCancelForm):
       
   251     """Shared content publication request cancel form, JSON renderer"""
       
   252 
       
   253 
       
   254 @viewlet_config(name='wf-cancel-propose-owner-warning', context=IWfSharedContent, layer=IPyAMSLayer,
       
   255                 view=PublicationRequestCancelForm, manager=IFormPrefixViewletsManager, weight=10)
       
   256 @template_config(template='templates/wf-owner-warning.pt')
       
   257 class PublicationRequestCancelFormWarning(Viewlet):
       
   258     """Publication request cancel form warning message"""
       
   259 
       
   260     def __new__(cls, context, request, view, manager):
       
   261         if request.principal.id in context.owner:
       
   262             return None
       
   263         return Viewlet.__new__(cls)
       
   264 
       
   265 
       
   266 @viewlet_config(name='wf-cancel-propose-message', context=IWfSharedContent, layer=IPyAMSLayer,
       
   267                 view=PublicationRequestCancelForm, manager=IWidgetsPrefixViewletsManager, weight=20)
       
   268 @template_config(template='templates/wf-cancel-propose-message.pt')
       
   269 class PublicationRequestCancelFormMessage(Viewlet):
       
   270     """Publication request cancel form info message"""
       
   271 
       
   272 
       
   273 #
       
   274 # Refuse publication form
       
   275 #
       
   276 
       
   277 class IPublicationRequestRefuseButtons(Interface):
       
   278     """Shared content publication request refuse buttons"""
       
   279 
       
   280     close = CloseButton(name='close', title=_("Cancel"))
       
   281     action = button.Button(name='action', title=_("Refuse publication request"))
       
   282 
       
   283 
       
   284 @pagelet_config(name='wf-refuse.html', context=IWfSharedContent, layer=IPyAMSLayer,
       
   285                 permission='pyams.PublishContent')
       
   286 class PublicationRequestRefuseForm(WorkflowContentTransitionForm):
       
   287     """Shared content publication request refuse form"""
       
   288 
       
   289     buttons = button.Buttons(IPublicationRequestRefuseButtons)
       
   290     ajax_handler = 'wf-refuse.json'
       
   291 
       
   292     def updateWidgets(self, prefix=None):
       
   293         super(PublicationRequestRefuseForm, self).updateWidgets(prefix)
       
   294         self.widgets['comment'].required = True
       
   295 
       
   296 
       
   297 @view_config(name='wf-refuse.json', context=IWfSharedContent, request_type=IPyAMSLayer,
       
   298              permission='pyams.PublishContent', renderer='json', xhr=True)
       
   299 class PublicationRequestRefuseAJAXForm(WorkflowContentTransitionAJAXForm, PublicationRequestRefuseForm):
       
   300     """Shared content publication request refuse form, JSON renderer"""
       
   301 
       
   302 
       
   303 @subscriber(IDataExtractedEvent, form_selector=PublicationRequestRefuseForm)
       
   304 def handle_publication_request_refuse_form_data_extraction(event):
       
   305     """Handle publication request refuse form data extraction"""
       
   306     comment = (event.data.get('comment') or '').strip()
       
   307     if not comment:
       
   308         event.form.widgets.errors += (Invalid(_("A comment is required")), )
       
   309 
       
   310 
       
   311 @viewlet_config(name='wf-refuse-operator-warning', context=IWfSharedContent, layer=IPyAMSLayer,
       
   312                 view=PublicationRequestRefuseForm, manager=IFormPrefixViewletsManager, weight=10)
       
   313 @template_config(template='templates/wf-operator-warning.pt')
       
   314 class PublicationRequestRefuseFormWarning(Viewlet):
       
   315     """Publication request refuse form warning message"""
       
   316 
       
   317     def __new__(cls, context, request, view, manager):
       
   318         state = IWorkflowState(context)
       
   319         if state.state_principal in context.owner:
       
   320             return None
       
   321         return Viewlet.__new__(cls)
       
   322 
       
   323 
       
   324 @viewlet_config(name='wf-refuse-message', context=IWfSharedContent, layer=IPyAMSLayer,
       
   325                 view=PublicationRequestRefuseForm, manager=IWidgetsPrefixViewletsManager, weight=20)
       
   326 @template_config(template='templates/wf-refuse-propose-message.pt')
       
   327 class PublicationRequestRefuseFormMessage(Viewlet):
       
   328     """Publication request refuse form info message"""
       
   329 
       
   330 
       
   331 #
       
   332 # Publish form
       
   333 #
       
   334 
       
   335 class IPublicationButtons(Interface):
       
   336     """Shared content publication buttons"""
       
   337 
       
   338     close = CloseButton(name='close', title=_("Cancel"))
       
   339     action = button.Button(name='action', title=_("Publish"))
       
   340 
       
   341 
       
   342 @pagelet_config(name='wf-publish.html', context=IWfSharedContent, layer=IPyAMSLayer, permission='pyams.PublishContent')
       
   343 class PublicationForm(WorkflowContentTransitionForm):
       
   344     """Shared content publication form"""
       
   345 
       
   346     fields = field.Fields(IWorkflowTransitionInfo) + \
       
   347              field.Fields(IWorkflowPublicationInfo).select('publication_effective_date',
       
   348                                                            'publication_expiration_date') + \
       
   349              field.Fields(IWorkflowCommentInfo)
       
   350     buttons = button.Buttons(IPublicationButtons)
       
   351     ajax_handler = 'wf-publish.json'
       
   352 
       
   353     def updateWidgets(self, prefix=None):
       
   354         super(PublicationForm, self).updateWidgets(prefix)
       
   355         pub_info = IWorkflowPublicationInfo(self.context)
       
   356         self.widgets['publication_effective_date'].required = True
       
   357         if ('publication_effective_date' in self.widgets) and pub_info.publication_effective_date:
       
   358             self.widgets['publication_effective_date'].value = \
       
   359                 tztime(pub_info.publication_effective_date).strftime('%d/%m/%y %H:%M')
       
   360         if ('publication_expiration_date' in self.widgets) and pub_info.publication_expiration_date:
       
   361             self.widgets['publication_expiration_date'].value = \
       
   362                 tztime(pub_info.publication_expiration_date).strftime('%d/%m/%y %H:%M')
       
   363 
       
   364     def createAndAdd(self, data):
       
   365         pub_info = IWorkflowPublicationInfo(self.context)
       
   366         pub_info.publication_effective_date = data.get('publication_effective_date')
       
   367         pub_info.publication_expiration_date = data.get('publication_expiration_date')
       
   368         return super(PublicationForm, self).createAndAdd(data)
       
   369 
       
   370 
       
   371 @view_config(name='wf-publish.json', context=IWfSharedContent, request_type=IPyAMSLayer,
       
   372              permission='pyams.PublishContent', renderer='json', xhr=True)
       
   373 class PublicationAJAXForm(WorkflowContentTransitionAJAXForm, PublicationForm):
       
   374     """Shared content publication form, JSON renderer"""
       
   375 
       
   376 
       
   377 @subscriber(IDataExtractedEvent, form_selector=PublicationForm)
       
   378 def handle_publication_form_data_extraction(event):
       
   379     """Handle publication form data extraction"""
       
   380     if not event.data.get('publication_effective_date'):
       
   381         event.form.widgets.errors += (Invalid(_("Publication start date is required")), )
       
   382 
       
   383 
       
   384 @viewlet_config(name='wf-publish-operator-warning', context=IWfSharedContent, layer=IPyAMSLayer,
       
   385                 view=PublicationForm, manager=IFormPrefixViewletsManager, weight=10)
       
   386 @template_config(template='templates/wf-operator-warning.pt')
       
   387 class PublicationFormWarning(Viewlet):
       
   388     """Shared content publication form warning message"""
       
   389 
       
   390     def __new__(cls, context, request, view, manager):
       
   391         state = IWorkflowState(context)
       
   392         if state.state_principal in context.owner:
       
   393             return None
       
   394         return Viewlet.__new__(cls)
       
   395 
       
   396 
       
   397 @viewlet_config(name='wf-publish-message', context=IWfSharedContent, layer=IPyAMSLayer,
       
   398                 view=PublicationForm, manager=IWidgetsPrefixViewletsManager, weight=20)
       
   399 @template_config(template='templates/wf-publish-message.pt')
       
   400 class PublicationFormMessage(Viewlet):
       
   401     """Shared content publication form info message"""
       
   402 
       
   403 
       
   404 #
       
   405 # Publication retire request form
       
   406 #
       
   407 
       
   408 class IPublicationRetireRequestButtons(Interface):
       
   409     """Shared content publication retire request buttons"""
       
   410 
       
   411     close = CloseButton(name='close', title=_("Cancel"))
       
   412     action = button.Button(name='action', title=_("Request retire"))
       
   413 
       
   414 
       
   415 @pagelet_config(name='wf-retiring.html', context=IWfSharedContent, layer=IPyAMSLayer,
       
   416                 permission='pyams.ManageContent')
       
   417 class PublicationRetireRequestForm(WorkflowContentTransitionForm):
       
   418     """Shared content publication request refuse form"""
       
   419 
       
   420     fields = field.Fields(IWorkflowTransitionInfo) + \
       
   421              field.Fields(IWorkflowRequestUrgencyInfo) + \
       
   422              field.Fields(IWorkflowCommentInfo)
       
   423     buttons = button.Buttons(IPublicationRetireRequestButtons)
       
   424     ajax_handler = 'wf-retiring.json'
       
   425 
       
   426     def updateWidgets(self, prefix=None):
       
   427         super(PublicationRetireRequestForm, self).updateWidgets(prefix)
       
   428         self.widgets['comment'].required = True
       
   429 
       
   430 
       
   431 @view_config(name='wf-retiring.json', context=IWfSharedContent, request_type=IPyAMSLayer,
       
   432              permission='pyams.ManageContent', renderer='json', xhr=True)
       
   433 class PublicationRetireRequestAJAXForm(WorkflowContentTransitionAJAXForm, PublicationRetireRequestForm):
       
   434     """Shared content publication retire request form, JSON renderer"""
       
   435 
       
   436 
       
   437 @subscriber(IDataExtractedEvent, form_selector=PublicationRetireRequestForm)
       
   438 def handle_publication_retire_request_form_data_extraction(event):
       
   439     """Handle publication retire request form data extraction"""
       
   440     comment = (event.data.get('comment') or '').strip()
       
   441     if not comment:
       
   442         event.form.widgets.errors += (Invalid(_("A comment is required")), )
       
   443 
       
   444 
       
   445 @viewlet_config(name='wf-retiring-owner-warning', context=IWfSharedContent, layer=IPyAMSLayer,
       
   446                 view=PublicationRetireRequestForm, manager=IFormPrefixViewletsManager, weight=10)
       
   447 @template_config(template='templates/wf-owner-warning.pt')
       
   448 class PublicationRetireRequestFormWarning(Viewlet):
       
   449     """Publication retire request form warning message"""
       
   450 
       
   451     def __new__(cls, context, request, view, manager):
       
   452         if request.principal.id in context.owner:
       
   453             return None
       
   454         return Viewlet.__new__(cls)
       
   455 
       
   456 
       
   457 @viewlet_config(name='wf-retiring-message', context=IWfSharedContent, layer=IPyAMSLayer,
       
   458                 view=PublicationRetireRequestForm, manager=IWidgetsPrefixViewletsManager, weight=20)
       
   459 @template_config(template='templates/wf-retiring-message.pt')
       
   460 class PublicationRetireRequestFormMessage(Viewlet):
       
   461     """Publication retire request form info message"""
       
   462 
       
   463 
       
   464 #
       
   465 # Publication retire cancel form
       
   466 #
       
   467 
       
   468 class IPublicationRetireCancelButtons(Interface):
       
   469     """Shared content publication retire request cancel buttons"""
       
   470 
       
   471     close = CloseButton(name='close', title=_("Cancel"))
       
   472     action = button.Button(name='action', title=_("Cancel retire request"))
       
   473 
       
   474 
       
   475 @pagelet_config(name='wf-cancel-retiring.html', context=IWfSharedContent, layer=IPyAMSLayer,
       
   476                 permission='pyams.ManageContent')
       
   477 class PublicationRetireCancelForm(WorkflowContentTransitionForm):
       
   478     """Shared content publication retire request cancel form"""
       
   479 
       
   480     buttons = button.Buttons(IPublicationRetireCancelButtons)
       
   481     ajax_handler = 'wf-cancel-retiring.json'
       
   482 
       
   483 
       
   484 @view_config(name='wf-cancel-retiring.json', context=IWfSharedContent, request_type=IPyAMSLayer,
       
   485              permission='pyams.ManageContent', renderer='json', xhr=True)
       
   486 class PublicationRetireCancelAJAXForm(WorkflowContentTransitionAJAXForm, PublicationRetireCancelForm):
       
   487     """Shared content publication retire request cancel form, JSON renderer"""
       
   488 
       
   489 
       
   490 @viewlet_config(name='wf-cancel-retiring-owner-warning', context=IWfSharedContent, layer=IPyAMSLayer,
       
   491                 view=PublicationRetireCancelForm, manager=IFormPrefixViewletsManager, weight=10)
       
   492 @template_config(template='templates/wf-owner-warning.pt')
       
   493 class PublicationRetireCancelFormWarning(Viewlet):
       
   494     """Publication retire request cancel form warning message"""
       
   495 
       
   496     def __new__(cls, context, request, view, manager):
       
   497         if request.principal.id in context.owner:
       
   498             return None
       
   499         return Viewlet.__new__(cls)
       
   500 
       
   501 
       
   502 @viewlet_config(name='wf-cancel-retiring-message', context=IWfSharedContent, layer=IPyAMSLayer,
       
   503                 view=PublicationRetireCancelForm, manager=IWidgetsPrefixViewletsManager, weight=20)
       
   504 @template_config(template='templates/wf-cancel-retiring-message.pt')
       
   505 class PublicationRetireCancelFormMessage(Viewlet):
       
   506     """Publication retire request form info message"""
       
   507 
       
   508 
       
   509 #
       
   510 # Publication retire form
       
   511 #
       
   512 
       
   513 class IPublicationRetireButtons(Interface):
       
   514     """Shared content publication retire buttons"""
       
   515 
       
   516     close = CloseButton(name='close', title=_("Cancel"))
       
   517     action = button.Button(name='action', title=_("Retire"))
       
   518 
       
   519 
       
   520 @pagelet_config(name='wf-retire.html', context=IWfSharedContent, layer=IPyAMSLayer,
       
   521                 permission='pyams.PublishContent')
       
   522 class PublicationRetireForm(WorkflowContentTransitionForm):
       
   523     """Shared content publication retire form"""
       
   524 
       
   525     buttons = button.Buttons(IPublicationRetireButtons)
       
   526     ajax_handler = 'wf-retire.json'
       
   527 
       
   528 
       
   529 @view_config(name='wf-retire.json', context=IWfSharedContent, request_type=IPyAMSLayer,
       
   530              permission='pyams.PublishContent', renderer='json', xhr=True)
       
   531 class PublicationRetireAJAXForm(WorkflowContentTransitionAJAXForm, PublicationRetireForm):
       
   532     """Shared content publication retire form, JSON renderer"""
       
   533 
       
   534 
       
   535 @viewlet_config(name='wf-retire-operator-warning', context=IWfSharedContent, layer=IPyAMSLayer,
       
   536                 view=PublicationRetireForm, manager=IFormPrefixViewletsManager, weight=10)
       
   537 @template_config(template='templates/wf-operator-warning.pt')
       
   538 class PublicationRetireFormWarning(Viewlet):
       
   539     """Publication retire form warning message"""
       
   540 
       
   541     def __new__(cls, context, request, view, manager):
       
   542         state = IWorkflowState(context)
       
   543         if state.state_principal in context.owner:
       
   544             return None
       
   545         return Viewlet.__new__(cls)
       
   546 
       
   547 
       
   548 @viewlet_config(name='wf-retire-message', context=IWfSharedContent, layer=IPyAMSLayer,
       
   549                 view=PublicationRetireForm, manager=IWidgetsPrefixViewletsManager, weight=20)
       
   550 @template_config(template='templates/wf-retire-message.pt')
       
   551 class PublicationRetireFormMessage(Viewlet):
       
   552     """Publication retire form info message"""
       
   553 
       
   554 
       
   555 #
       
   556 # Publication archive request form
       
   557 #
       
   558 
       
   559 class IPublicationArchiveRequestButtons(Interface):
       
   560     """Shared content publication archive request buttons"""
       
   561 
       
   562     close = CloseButton(name='close', title=_("Cancel"))
       
   563     action = button.Button(name='action', title=_("Request archive"))
       
   564 
       
   565 
       
   566 @pagelet_config(name='wf-archiving.html', context=IWfSharedContent, layer=IPyAMSLayer,
       
   567                 permission='pyams.ManageContent')
       
   568 class PublicationArchiveRequestForm(WorkflowContentTransitionForm):
       
   569     """Shared content publication request archive form"""
       
   570 
       
   571     fields = field.Fields(IWorkflowTransitionInfo) + \
       
   572              field.Fields(IWorkflowRequestUrgencyInfo) + \
       
   573              field.Fields(IWorkflowCommentInfo)
       
   574     buttons = button.Buttons(IPublicationArchiveRequestButtons)
       
   575     ajax_handler = 'wf-archiving.json'
       
   576 
       
   577     def updateWidgets(self, prefix=None):
       
   578         super(PublicationArchiveRequestForm, self).updateWidgets(prefix)
       
   579         self.widgets['comment'].required = True
       
   580 
       
   581 
       
   582 @view_config(name='wf-archiving.json', context=IWfSharedContent, request_type=IPyAMSLayer,
       
   583              permission='pyams.ManageContent', renderer='json', xhr=True)
       
   584 class PublicationArchiveRequestAJAXForm(WorkflowContentTransitionAJAXForm, PublicationArchiveRequestForm):
       
   585     """Shared content publication archive request form, JSON renderer"""
       
   586 
       
   587 
       
   588 @subscriber(IDataExtractedEvent, form_selector=PublicationArchiveRequestForm)
       
   589 def handle_archive_request_form_data_extraction(event):
       
   590     """Handle archive request form data extraction"""
       
   591     comment = (event.data.get('comment') or '').strip()
       
   592     if not comment:
       
   593         event.form.widgets.errors += (Invalid(_("A comment is required")), )
       
   594 
       
   595 
       
   596 @viewlet_config(name='wf-archiving-owner-warning', context=IWfSharedContent, layer=IPyAMSLayer,
       
   597                 view=PublicationArchiveRequestForm, manager=IFormPrefixViewletsManager, weight=10)
       
   598 @template_config(template='templates/wf-owner-warning.pt')
       
   599 class PublicationArchiveRequestFormWarning(Viewlet):
       
   600     """Publication archive request form warning message"""
       
   601 
       
   602     def __new__(cls, context, request, view, manager):
       
   603         if request.principal.id in context.owner:
       
   604             return None
       
   605         return Viewlet.__new__(cls)
       
   606 
       
   607 
       
   608 @viewlet_config(name='wf-archiving-message', context=IWfSharedContent, layer=IPyAMSLayer,
       
   609                 view=PublicationArchiveRequestForm, manager=IWidgetsPrefixViewletsManager, weight=20)
       
   610 @template_config(template='templates/wf-archiving-message.pt')
       
   611 class PublicationArchiveRequestFormMessage(Viewlet):
       
   612     """Publication archive request form info message"""
       
   613 
       
   614 
       
   615 #
       
   616 # Publication archive cancel form
       
   617 #
       
   618 
       
   619 class IPublicationArchiveCancelButtons(Interface):
       
   620     """Shared content publication archive request cancel buttons"""
       
   621 
       
   622     close = CloseButton(name='close', title=_("Cancel"))
       
   623     action = button.Button(name='action', title=_("Cancel archive request"))
       
   624 
       
   625 
       
   626 @pagelet_config(name='wf-cancel-archiving.html', context=IWfSharedContent, layer=IPyAMSLayer,
       
   627                 permission='pyams.ManageContent')
       
   628 class PublicationArchiveCancelForm(WorkflowContentTransitionForm):
       
   629     """Shared content publication archive request cancel form"""
       
   630 
       
   631     buttons = button.Buttons(IPublicationArchiveCancelButtons)
       
   632     ajax_handler = 'wf-cancel-archiving.json'
       
   633 
       
   634 
       
   635 @view_config(name='wf-cancel-archiving.json', context=IWfSharedContent, request_type=IPyAMSLayer,
       
   636              permission='pyams.ManageContent', renderer='json', xhr=True)
       
   637 class PublicationArchiveCancelAJAXForm(WorkflowContentTransitionAJAXForm, PublicationArchiveCancelForm):
       
   638     """Shared content publication archive request cancel form, JSON renderer"""
       
   639 
       
   640 
       
   641 @viewlet_config(name='wf-cancel-archiving-owner-warning', context=IWfSharedContent, layer=IPyAMSLayer,
       
   642                 view=PublicationArchiveCancelForm, manager=IFormPrefixViewletsManager, weight=10)
       
   643 @template_config(template='templates/wf-owner-warning.pt')
       
   644 class PublicationArchiveCancelFormWarning(Viewlet):
       
   645     """Publication archive cancel form warning message"""
       
   646 
       
   647     def __new__(cls, context, request, view, manager):
       
   648         if request.principal.id in context.owner:
       
   649             return None
       
   650         return Viewlet.__new__(cls)
       
   651 
       
   652 
       
   653 @viewlet_config(name='wf-cancel-archiving-message', context=IWfSharedContent, layer=IPyAMSLayer,
       
   654                 view=PublicationArchiveCancelForm, manager=IWidgetsPrefixViewletsManager, weight=20)
       
   655 @template_config(template='templates/wf-cancel-archiving-message.pt')
       
   656 class PublicationArchiveCancelFormMessage(Viewlet):
       
   657     """Publication archive cancel form info message"""
       
   658 
       
   659 
       
   660 #
       
   661 # Publication archive form
       
   662 #
       
   663 
       
   664 class IPublicationArchiveButtons(Interface):
       
   665     """Shared content publication archive buttons"""
       
   666 
       
   667     close = CloseButton(name='close', title=_("Cancel"))
       
   668     action = button.Button(name='action', title=_("Archive"))
       
   669 
       
   670 
       
   671 @pagelet_config(name='wf-archive.html', context=IWfSharedContent, layer=IPyAMSLayer,
       
   672                 permission='pyams.PublishContent')
       
   673 class PublicationArchiveForm(WorkflowContentTransitionForm):
       
   674     """Shared content publication archive form"""
       
   675 
       
   676     buttons = button.Buttons(IPublicationArchiveButtons)
       
   677     ajax_handler = 'wf-archive.json'
       
   678 
       
   679 
       
   680 @view_config(name='wf-archive.json', context=IWfSharedContent, request_type=IPyAMSLayer,
       
   681              permission='pyams.PublishContent', renderer='json', xhr=True)
       
   682 class PublicationArchiveAJAXForm(WorkflowContentTransitionAJAXForm, PublicationArchiveForm):
       
   683     """Shared content publication archive form, JSON renderer"""
       
   684 
       
   685 
       
   686 @viewlet_config(name='wf-archive-operator-warning', context=IWfSharedContent, layer=IPyAMSLayer,
       
   687                 view=PublicationArchiveForm, manager=IFormPrefixViewletsManager, weight=10)
       
   688 @template_config(template='templates/wf-operator-warning.pt')
       
   689 class PublicationArchiveFormWarning(Viewlet):
       
   690     """Publication archive form warning message"""
       
   691 
       
   692     def __new__(cls, context, request, view, manager):
       
   693         state = IWorkflowState(context)
       
   694         if state.state_principal in context.owner:
       
   695             return None
       
   696         return Viewlet.__new__(cls)
       
   697 
       
   698 
       
   699 @viewlet_config(name='wf-archive-message', context=IWfSharedContent, layer=IPyAMSLayer,
       
   700                 view=PublicationArchiveForm, manager=IWidgetsPrefixViewletsManager, weight=20)
       
   701 @template_config(template='templates/wf-archive-message.pt')
       
   702 class PublicationArchiveFormMessage(Viewlet):
       
   703     """Publication archive form info message"""
       
   704 
       
   705 
       
   706 #
       
   707 # Clone form
       
   708 #
       
   709 
       
   710 class ISharedContentCloneButtons(Interface):
       
   711     """Shared content clone buttons"""
       
   712 
       
   713     close = CloseButton(name='close', title=_("Cancel"))
       
   714     action = button.Button(name='action', title=_("Create new version"))
       
   715 
       
   716 
       
   717 @pagelet_config(name='wf-clone.html', context=IWfSharedContent, layer=IPyAMSLayer, permission='pyams.CreateContent')
       
   718 class SharedContentCloneForm(WorkflowContentTransitionForm):
       
   719     """Shared content clone form"""
       
   720 
       
   721     buttons = button.Buttons(ISharedContentCloneButtons)
       
   722     ajax_handler = 'wf-clone.json'
       
   723 
       
   724     def createAndAdd(self, data):
       
   725         info = IWorkflowInfo(self.context)
       
   726         return info.fire_transition_toward(DRAFT, comment=data.get('comment'))
       
   727 
       
   728 
       
   729 @view_config(name='wf-clone.json', context=IWfSharedContent, request_type=IPyAMSLayer,
       
   730              permission='pyams.CreateContent', renderer='json', xhr=True)
       
   731 class SharedContentCloneAJAXForm(AJAXAddForm, SharedContentCloneForm):
       
   732     """Shared content clone form, JSON rendener"""
       
   733 
       
   734     def get_ajax_output(self, changes):
       
   735         return {'status': 'redirect',
       
   736                 'location': absolute_url(changes, self.request, 'admin.html#properties.html')}
       
   737 
       
   738 
       
   739 @viewlet_config(name='wf-clone-owner-warning', context=IWfSharedContent, layer=IPyAMSLayer,
       
   740                 view=SharedContentCloneForm, manager=IFormPrefixViewletsManager, weight=10)
       
   741 @template_config(template='templates/wf-owner-warning.pt')
       
   742 class SharedContentCloneFormWarning(Viewlet):
       
   743     """Shared content clone form warning message"""
       
   744 
       
   745     def __new__(cls, context, request, view, manager):
       
   746         if request.principal.id in context.owner:
       
   747             return None
       
   748         return Viewlet.__new__(cls)
       
   749 
       
   750 
       
   751 @viewlet_config(name='wf-clone-message', context=IWfSharedContent, layer=IPyAMSLayer,
       
   752                 view=SharedContentCloneForm, manager=IWidgetsPrefixViewletsManager, weight=20)
       
   753 @template_config(template='templates/wf-clone-message.pt')
       
   754 class SharedContentCloneFormMessage(Viewlet):
       
   755     """Shared content clone form info message"""
       
   756 
       
   757 
       
   758 #
       
   759 # Delete form
       
   760 #
       
   761 
       
   762 class ISharedContentDeleteButtons(Interface):
       
   763     """Shared content delete form buttons"""
       
   764 
       
   765     close = CloseButton(name='close', title=_("Cancel"))
       
   766     action = button.Button(name='action', title=_("Delete version"))
       
   767 
       
   768 
       
   769 @pagelet_config(name='wf-delete.html', context=IWfSharedContent, layer=IPyAMSLayer, permission='pyams.ManageContent')
       
   770 class SharedContentDeleteForm(WorkflowContentTransitionForm):
       
   771     """Shared content delete form"""
       
   772 
       
   773     buttons = button.Buttons(ISharedContentDeleteButtons)
       
   774     ajax_handler = 'wf-delete.json'
       
   775 
       
   776     def createAndAdd(self, data):
       
   777         state = IWorkflowState(self.context)
       
   778         if state.version_id == 1:  # remove the first and only version => remove all
       
   779             content = get_parent(self.context, ISharedContent)
       
   780             self.__target = get_parent(content, ISharedTool)
       
   781             del content.__parent__[content.__name__]
       
   782         else:
       
   783             self.__target = get_parent(self.context, ISharedTool)
       
   784             IWorkflowVersions(self.context).remove_version(state.version_id, state=DELETED, comment=data.get('comment'))
       
   785 
       
   786 
       
   787 @view_config(name='wf-delete.json', context=IWfSharedContent, request_type=IPyAMSLayer,
       
   788              permission='pyams.ManageContent', renderer='json', xhr=True)
       
   789 class SharedContentDeleteAJAXForm(AJAXAddForm, SharedContentDeleteForm):
       
   790     """Shared content delete form, JSON rendener"""
       
   791 
       
   792     def get_ajax_output(self, changes):
       
   793         return {'status': 'redirect',
       
   794                 'location': absolute_url(self._SharedContentDeleteForm__target, self.request, 'admin.html')}
       
   795 
       
   796 
       
   797 @viewlet_config(name='wf-delete-owner-warning', context=IWfSharedContent, layer=IPyAMSLayer,
       
   798                 view=SharedContentDeleteForm, manager=IFormPrefixViewletsManager, weight=10)
       
   799 @template_config(template='templates/wf-owner-warning.pt')
       
   800 class SharedContentDeleteFormWarning(Viewlet):
       
   801     """Shared content delete form warning message"""
       
   802 
       
   803     def __new__(cls, context, request, view, manager):
       
   804         if request.principal.id in context.owner:
       
   805             return None
       
   806         return Viewlet.__new__(cls)
       
   807 
       
   808 
       
   809 @viewlet_config(name='wf-delete-message', context=IWfSharedContent, layer=IPyAMSLayer,
       
   810                 view=SharedContentDeleteForm, manager=IWidgetsPrefixViewletsManager, weight=20)
       
   811 @template_config(template='templates/wf-delete-message.pt')
       
   812 class SharedContentDeleteFormMessage(Viewlet):
       
   813     """Shared content delete form info message"""