[Zope3-checkins] CVS: Zope3/src/zope/app/workflow/browser/stateful - __init__.py:1.1 add.pt:1.1 addstate.pt:1.1 addtransition.pt:1.1 configure.zcml:1.1 content_filter.py:1.1 contentworkflow.py:1.1 contentworkflow_index.pt:1.1 contentworkflow_registry.pt:1.1 definition.py:1.1 definition_edit.pt:1.1 definition_index.pt:1.1 definition_states.pt:1.1 definition_transitions.pt:1.1 filterTest.pt:1.1 filteradapter.py:1.1 instance.py:1.1 instance_manage.pt:1.1 interfaces.py:1.1 published_content.pt:1.1 testobject.zcml:1.1

Philipp von Weitershausen philikon at philikon.de
Fri Feb 27 11:50:40 EST 2004


Update of /cvs-repository/Zope3/src/zope/app/workflow/browser/stateful
In directory cvs.zope.org:/tmp/cvs-serv22977/workflow/browser/stateful

Added Files:
	__init__.py add.pt addstate.pt addtransition.pt configure.zcml 
	content_filter.py contentworkflow.py contentworkflow_index.pt 
	contentworkflow_registry.pt definition.py definition_edit.pt 
	definition_index.pt definition_states.pt 
	definition_transitions.pt filterTest.pt filteradapter.py 
	instance.py instance_manage.pt interfaces.py 
	published_content.pt testobject.zcml 
Log Message:
Centralized the workflow interfaces and browser views in
zope.app.workflow.


=== Added File Zope3/src/zope/app/workflow/browser/stateful/__init__.py ===
# make this directory a package


=== Added File Zope3/src/zope/app/workflow/browser/stateful/add.pt ===
<html metal:use-macro="views/standard_macros/dialog">
<body>
<div metal:fill-slot="body">

  <form action="action.html" method="post">
    <table class="TypeListing" cellpadding="3">

      <caption i18n:translate="">Add Content</caption>

        <tbody tal:repeat="info view/addingInfo">

        <tr>

          <td class="Selector">
            <input type="radio" name="type_name"
                   tal:attributes="value info/action; id info/action" />
          </td>

          <td class="TypeName">
            <label style="font-weight: bold;"
                   tal:attributes="for info/action">
              <span tal:replace="info/title" >Folder</span>
            </label>
            <div class="TypeDescription" tal:content="info/description">
              Folders are generic containers for content, including other
              folders.
            </div>
          </td>
        </tr>

      </tbody>

      <tbody tal:condition="nothing">

        <tr>

          <td class="Selector">
            <input type="radio" name="type_name" value="" />
                   
          </td>

          <td class="TypeName">
            <img alt="Folder" src="../../ZMI/www/document_icon.gif" />
            Document
          </td>

        </tr>

        <tr>
          <td class="Selector"><br /></td>
          <td class="TypeDescription">
              Documents are simple textual content.
          </td>
        </tr>

      </tbody>

      <tr>
        <td><br /></td>
        <td>
            <input type="text" name="id"
                   tal:condition="view/namesAccepted"
                   tal:attributes="value request/id | nothing"
            />
            <input type="submit" value="Add" 
                   i18n:attributes="value add-button"/>
        </td>
      </tr>

    </table>
  </form>

</div>
</body>
</html>


=== Added File Zope3/src/zope/app/workflow/browser/stateful/addstate.pt ===
<html metal:use-macro="views/standard_macros/page">
<head>
  <title metal:fill-slot="title" i18n:translate="">Add State</title>
</head>

<body>
<div metal:fill-slot="body">

  <form action="." method="post" enctype="multipart/form-data">

    <div class="row">
      <div class="label" i18n:translate="">Id</div>
      <div class="field">
        <input type="text" name="id" size="40" value="" />
      </div>
    </div>

    <div class="row">
      <div class="controls">
        <input type="submit" name="action.html:method" value="Add"
            i18n:attributes="value add-button"/>
      </div>
    </div>

  </form>

</div> 
</body>
</html>

=== Added File Zope3/src/zope/app/workflow/browser/stateful/addtransition.pt ===
<html metal:use-macro="views/standard_macros/page">
<head>
  <title metal:fill-slot="title" i18n:translate="">Add Transition</title>
</head>

<body>
<div metal:fill-slot="body">
 
  <form action="." method="post" enctype="multipart/form-data">

    <div class="row">
      <div class="label" i18n:translate="">Id</div>
      <div class="field">
        <input type="text" name="id" size="40" value="" />
      </div>
    </div>

    <div class="row">
      <div class="label" i18n:translate="">Source Satte</div>
      <div class="field">
        <select name="source">
          <option tal:repeat="state states"
                  tal:content="state" />
        </select>
      </div>
    </div>

    <div class="row">
      <div class="label" i18n:translate="">Destination Satte</div>
      <div class="field">
        <select name="destination">
          <option tal:repeat="state states"
                  tal:content="state" />
        </select>
      </div>
    </div>

    <div class="row">
      <div class="label" i18n:translate="">Condition</div>
      <div class="field">
        <input type="text" name="condition" size="40" value="" />
      </div>
    </div>

    <div class="row">
      <div class="label" i18n:translate="">Permission</div>
      <div class="field">
        <!-- XXX: This should be really a Permission widget --> 
        <input type="text" name="permission" size="40" value="" />
      </div>
    </div>

    <div class="row">
      <div class="controls">
        <input type="submit" name="action.html:method" value="Add"
            i18n:attributes="value add-button"/>
      </div>
    </div>

  </form>
 
</div> 
</body>
</html>

=== Added File Zope3/src/zope/app/workflow/browser/stateful/configure.zcml ===
<zope:configure
   xmlns:zope="http://namespaces.zope.org/zope"
   xmlns="http://namespaces.zope.org/browser">

<!-- Stateful Workflow Process Definition -->

  <menuItem
      menu="add_component"
      for="zope.app.interfaces.container.IAdding"
      action="StatefulProcessDefinition"
      title="Stateful Process Definition"
      description="A stateful workflow process definition" />

  <page
      for="zope.app.workflow.interfaces.stateful.IStatefulProcessDefinition"
      name="index.html"
      class=".definition.StatefulProcessDefinitionView"
      permission="zope.ManageServices"
      template="definition_index.pt" />

  <editform
      schema="zope.app.workflow.interfaces.stateful.IStatefulProcessDefinition"
      name="edit.html"
      template="definition_edit.pt"
      class=".definition.RelevantDataSchemaEdit"
      menu="zmi_views" title="Relevant Data Schema"
      permission="zope.workflow.ManageProcessDefinitions"/>

  <menuItems
      for="zope.app.workflow.interfaces.stateful.IStatefulProcessDefinition"
      menu="zmi_actions">

    <menuItem
        title="Manage States" action="states/contents.html" />
    <menuItem
        title="Manage Transitions" action="transitions/contents.html" />

  </menuItems>


<!-- States/Transitions Container Adding Menus -->
  <menu id="add_stateful_states" title="State Items"
        usage="addingdialog"/>
  <menu id="add_stateful_transitions" title="Transition Items"
        usage="addingdialog" />


<!-- States Container -->

  <view
      for="zope.app.workflow.interfaces.stateful.IStatefulStatesContainer"
      name="+"
      menu="zmi_actions" title="Add"
      class=".definition.StatesContainerAdding"
      permission="zope.workflow.ManageProcessDefinitions"
      allowed_attributes="addingInfo">

    <page name="index.html"  template="add.pt" />
    <page name="action.html" attribute="action" />

  </view>


<!-- State -->
  <!-- nothing to edit yet
  <editform
      schema="zope.app.workflow.interfaces.stateful.IState"
      name="edit.html"
      menu="zmi_views"
      label="Edit a State"
      permission="zope.workflow.ManageProcessDefinitions" />
  -->

  <addform
      name="AddState"
      menu="add_stateful_states" title="Stateful State"
      schema="zope.app.workflow.interfaces.stateful.IState"
      class=".definition.StateAddFormHelper"
      permission="zope.workflow.ManageProcessDefinitions"
      content_factory="zope.app.workflow.stateful.definition.State"
      arguments=""
      fields="" />


<!-- Transitions Container -->

  <view
      for="zope.app.workflow.interfaces.stateful.IStatefulTransitionsContainer"
      name="+"
      menu="zmi_actions" title="Add"
      class=".definition.TransitionsContainerAdding"
      permission="zope.workflow.ManageProcessDefinitions"
      allowed_attributes="addingInfo">

    <page name="index.html"  template="add.pt" />
    <page name="action.html" attribute="action" />

  </view>



<!-- Transition -->
  <editform
      schema="zope.app.workflow.interfaces.stateful.ITransition"
      name="edit.html"
      menu="zmi_views"
      label="Edit a Transition"
      permission="zope.workflow.ManageProcessDefinitions" />

  <addform
      name="AddTransition"
      menu="add_stateful_transitions" title="Stateful Transition"
      schema="zope.app.workflow.interfaces.stateful.ITransition"
      permission="zope.workflow.ManageProcessDefinitions"
      content_factory="zope.app.workflow.stateful.definition.Transition"
      arguments="sourceState destinationState"
      keyword_arguments="condition script permission triggerMode"
      fields="sourceState destinationState condition script
              permission triggerMode"/>


<!-- ContentWorkflowsUtility -->
  <menuItem
      menu="add_component"
      for="zope.app.interfaces.container.IAdding"
      action="ContentWorkflowsManager"
      title="Content Workflows Manager"
      description="An utility to manage content and workflow interaction." />

  <page
      name="index.html"
      for="zope.app.workflow.interfaces.stateful.IContentWorkflowsManager"
      class=".contentworkflow.ContentWorkflowsManagerView"
      permission="zope.ManageServices"
      template="contentworkflow_index.pt"
      menu="zmi_views" title="Overview"/>

  <page
      name="registry.html"
      for="zope.app.workflow.interfaces.stateful.IContentWorkflowsManager"
      class=".contentworkflow.ManageContentProcessRegistry"
      permission="zope.ManageServices"
      template="contentworkflow_registry.pt"
      menu="zmi_views" title="Content/Process Registry"/>


<!-- ProcessInstanceContainerAdaptable -->
  <pages
      for="zope.app.workflow.interfaces.IProcessInstanceContainerAdaptable"
      permission="zope.workflow.UseProcessInstances"
      class=".instance.ManagementView">

    <page name="workflows.html" template="instance_manage.pt"
          menu="zmi_views" title="Workflows"/>
    <page name="fireTransition.html" attribute="fireTransition" />
  </pages>


  <page
      for="zope.app.interfaces.container.IContentContainer"
      permission="zope.View"
      class="zope.app.workflow.browser.stateful.content_filter.FilterList"
      name="published_content.html"
      attribute="published_content" />

<!-- uhm ... this seems to be too generic in its definition
     and not really nice as well. -->
  <zope:adapter
      factory=".filteradapter.FilterAdapter"
      provides=".interfaces.IContentFilterAdapter"
      for="zope.app.interfaces.annotation.IAttributeAnnotatable"
      permission="zope.View" /> <!-- XXX is this permission right? -->

  <!--include file="testobject.zcml"/-->

</zope:configure>


=== Added File Zope3/src/zope/app/workflow/browser/stateful/content_filter.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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.
#
##############################################################################
"""filtering view for ProcessInstances of a stateful workflow
 
$Id: content_filter.py,v 1.1 2004/02/27 16:50:38 philikon Exp $
"""
from zope.component import queryAdapter
from zope.app.pagetemplate.viewpagetemplatefile import ViewPageTemplateFile
from zope.app.browser.container.contents import Contents
from zope.app.workflow.interfaces import IProcessInstanceContainerAdaptable
from zope.app.workflow.interfaces import IProcessInstanceContainer

__metaclass__ = type

class FilterList(Contents):

    __used_for__ = IProcessInstanceContainerAdaptable


    def filterByState(self, objList, state, workflow='default'):
        """Filter a list of objects according to given workflow and state

        objList  ... list of objects
        state    ... name of a state (of the given workflow) in which the result
                      objects must be
        workflow ... name of a workflow to which result objects must be attached
        """
        res = []

        for obj in objList:
            adapter = queryAdapter(obj['object'], IProcessInstanceContainer)
            if adapter:
                for item in adapter.values():
                    if item.processDefinitionName != workflow:
                        continue
                    if item.status == state:
                        res.append(obj)
                        break

        return res


    published_content = ViewPageTemplateFile('published_content.pt')

    # XXX: This method assumes you have a publishing workflow (SR) 
    def listPublishedItems(self):
        return self.filterByState(self.listContentInfo(), 'published')



=== Added File Zope3/src/zope/app/workflow/browser/stateful/contentworkflow.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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.
#
##############################################################################
"""ContentWorkflow Manager views
 
$Id: contentworkflow.py,v 1.1 2004/02/27 16:50:38 philikon Exp $
"""
from zope.app.introspector import interfaceToName, nameToInterface
from zope.app.component.interfacefield import InterfaceField
from zope.app.i18n import ZopeMessageIDFactory as _
from zope.app.form.utility import setUpWidgets
from zope.app.services.servicenames import Workflows
from zope.component import getService
from zope.interface import Interface
from zope.publisher.browser import BrowserView
from zope.schema.vocabulary import VocabularyListField
from zope.security.proxy import trustedRemoveSecurityProxy 

__metaclass__ = type
 

class ContentWorkflowsManagerView:
 
    def getName(self):
        return """I'm a ContentWorkflows Utility"""


class IContentProcessMapping(Interface):

    iface = InterfaceField(
        title=u"Content Interface",
        description=u"Specifies the interface that characterizes a particular "
                    u"content type. Select one interface at a time.",
        required=True)
    
    name = VocabularyListField(
        title = u"Process Definition Name",
        description = u"The name of the process that will be available for "
                      u"this content type. Feel free to select several at "
                      u"once.",
        required = True,
        vocabulary = "ProcessDefinitions")


class ManageContentProcessRegistry(BrowserView):

    def __init__(self, *args):
        super(ManageContentProcessRegistry, self).__init__(*args)
        setUpWidgets(self, IContentProcessMapping)
        self.process_based = int(self.request.get('process_based', '1'))

    def getProcessInterfacesMapping(self):
        mapping = []
        wf = getService(self.context, Workflows)
        for name in wf.getProcessDefinitionNames():
            ifaces = self.context.getInterfacesForProcessName(name)
            ifaces = map(lambda i: interfaceToName(self.context, i), ifaces)
            if ifaces:
                mapping.append({'name': name, 'ifaces': ifaces})
        return mapping

    def getInterfaceProcessesMapping(self):
        mapping = []
        # Nothing bad here; we just read the registry data
        registry = trustedRemoveSecurityProxy(self.context)._registry
        for iface, names in registry.items(): 
            mapping.append({'iface': interfaceToName(self.context, iface),
                            'names': names})
        return mapping

    def update(self):
        status = ''
        if 'ADD' in self.request:
            for name in self.name_widget.getInputValue():
                self.context.register(self.iface_widget.getInputValue(), name)
            status = _('Mapping(s) added.')
        elif 'REMOVE' in self.request:
            mappings = self.request.get('mappings', [])
            for entry in mappings:
                split = entry.rfind(':')
                name = entry[:split]
                iface = nameToInterface(self.context, entry[split+1:])
                self.context.unregister(iface, name)
            status = _('Mapping(s) removed.')
        elif 'SWITCH' in self.request:
            self.request.response.setCookie('process_based',
                                            self.request.get('other_view'))
            self.process_based = int(self.request.get('other_view'))

        return status


=== Added File Zope3/src/zope/app/workflow/browser/stateful/contentworkflow_index.pt ===
<html metal:use-macro="views/standard_macros/page">
 <head>
  <title metal:fill-slot="title" i18n:translate="">
    Registration "Service" Control Page
  </title>
</head>

<body>
<div metal:fill-slot="body">
 
  <h1 i18n:translate="">Subscription control</h1>

  <!-- XXX: Too much logic for a template --> 
  <span tal:condition="request/callSubscribe|nothing" tal:omit-tag="">
    <span tal:define="dummy context/subscribe" tal:omit-tag=""/>
  </span>
  <span tal:condition="request/callUnsubscribe|nothing" tal:omit-tag="">
    <span tal:define="dummy context/unsubscribe" tal:omit-tag=""/>
  </span>

  <form action="" method="post">
    <span tal:condition="context/isSubscribed" tal:omit-tag="">
      <span i18n:translate="">Subscription state: ON</span>
      <input type="submit" value="Unsubscribe" name="callUnsubscribe" 
             i18n:attributes="value unsubscribe-button"/>
     </span>
     <span tal:condition="not:context/isSubscribed" tal:omit-tag="">
       <span i18n:translate="">Subscription state: OFF</span>
       <input type="submit" value="Subscribe" name="callSubscribe"
              i18n:attributes="value unsubscribe-button"/>
     </span>
  </form>
 
</div>
</body>
</html>

=== Added File Zope3/src/zope/app/workflow/browser/stateful/contentworkflow_registry.pt ===
<html metal:use-macro="views/standard_macros/page">
 <head>
  <title metal:fill-slot="title" i18n:translate="">
    Process Definition <-> Content Type Registry
  </title>
</head>
 
<body>
<div metal:fill-slot="body">
 
  <p tal:define="status view/update"
     tal:condition="status"
     tal:content="status" />

  <p i18n:translate="">
    This screen let's you specify which content types (by interface) can
    receive which workflows (process definitions).</p>

  <form action="./@@registry.html" method="POST">
    <h3 i18n:translate="">Available Mappings</h3>
     
    <ul tal:condition="view/process_based">
      <input type="hidden" name="other_view" value="0"/>
      <li tal:repeat="process view/getProcessInterfacesMapping">
        <b tal:content="process/name" /><br/>
        <tal:block repeat="iface process/ifaces">
          <input type="checkbox" name="mappings:list"
            tal:attributes="value string:${process/name}:${iface}">
          <d tal:replace="iface"/><br/>
        </tal:block>
      </li>
    </ul>

    <ul tal:condition="not: view/process_based">
      <input type="hidden" name="other_view" value="1"/>
      <li tal:repeat="iface view/getInterfaceProcessesMapping">
        <b tal:content="iface/iface" /><br/>
        <tal:block repeat="name iface/names">
          <input type="checkbox" name="mappings:list"
            tal:attributes="value string:${name}:${iface/iface}">
          <d tal:replace="name"/><br/>
        </tal:block>
      </li>
    </ul>

    <div class="row">
      <div class="controls" style="width: 100%"> 
         <input type="submit" value="Switch View" name="SWITCH" 
                i18n:attributes="value switch-view-button" />
         <input type="submit" value="Remove Mappings" name="REMOVE"
                i18n:attributes="value remove-mappings-button" />
       </div>
    </div>

    <h3 i18n:translate="">Add new Mapping</h3>
    <div class="row" 
         tal:content="structure view/iface_widget/row" />
    <div class="row" 
         tal:content="structure view/name_widget/row" />
    <div class="row">
      <div class="controls"> 
         <input type="submit" value="Add Mappings" name="ADD"
                i18n:attributes="value add-mappings-button" />
       </div>
    </div>
  </form>
 
</div>
</body> 
</html>

=== Added File Zope3/src/zope/app/workflow/browser/stateful/definition.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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.
#
##############################################################################
"""ProcessDefinition registration adding view

$Id: definition.py,v 1.1 2004/02/27 16:50:38 philikon Exp $
"""
__metaclass__ = type

from zope.proxy import removeAllProxies
from zope.publisher.browser import BrowserView
from zope.app.browser.container.adding import Adding
from zope.app.browser.form.submit import Update
from zope.app.browser.form.editview import EditView
from zope.app.workflow.stateful.definition import State, Transition
from zope.schema import getFields

from zope.app.security.permission import PermissionField
from zope.security.checker import CheckerPublic
from zope.security.proxy import trustedRemoveSecurityProxy
from zope.app.form.utility import setUpWidget

class StatesContainerAdding(Adding):
    """Custom adding view for StatesContainer objects."""
    menu_id = "add_stateful_states"


class TransitionsContainerAdding(Adding):
    """Custom adding view for TransitionsContainer objects."""
    menu_id = "add_stateful_transitions"

    def getProcessDefinition(self):
        return self.context.getProcessDefinition()


# XXX Temporary ...
class StateAddFormHelper:
    # XXX Hack to prevent from displaying an empty addform
    def __call__(self, template_usage=u'', *args, **kw):
        if not len(self.fieldNames):
            self.request.form[Update] = 'submitted'
            return self.update()
        return super(StateAddFormHelper, self).__call__(template_usage,
                                                        *args, **kw)


class StatefulProcessDefinitionView(BrowserView):

    def getName(self):
        return """I'm a stateful ProcessInstance"""


class RelevantDataSchemaEdit(EditView):

    def __init__(self, context, request):
        super(RelevantDataSchemaEdit, self).__init__(context, request)
        self.buildPermissionWidgets()

    def buildPermissionWidgets(self):
        schema = self.context.relevantDataSchema
        if schema is not None:
            for name, field in getFields(schema).items():
                # Try to get current settings
                if self.context.schemaPermissions.has_key(name):
                    get_perm, set_perm = self.context.schemaPermissions[name]
                else:
                    get_perm, set_perm = None, None

                # Create the Accessor Permission Widget for this field
                permField = PermissionField(
                    __name__=name+'_get_perm',
                    title=u"Accessor Permission",
                    default=CheckerPublic,
                    required=False)
                setUpWidget(self, name+'_get_perm', permField, value=get_perm)

                # Create the Mutator Permission Widget for this field
                permField = PermissionField(
                    __name__=name+'_set_perm',
                    title=u"Mutator Permission",
                    default=CheckerPublic,
                    required=False)
                setUpWidget(self, name+'_set_perm', permField, value=set_perm)

    def update(self):
        status = ''

        if Update in self.request:
            status = super(RelevantDataSchemaEdit, self).update()
            self.buildPermissionWidgets()
        elif 'CHANGE' in self.request:
            schema = self.context.relevantDataSchema
            perms = trustedRemoveSecurityProxy(self.context.schemaPermissions)
            for name, field in getFields(schema).items():
                getPerm = getattr(
                    self, name+'_get_perm_widget').getInputValue()
                setPerm = getattr(
                    self, name+'_set_perm_widget').getInputValue()
                perms[name] = (getPerm, setPerm)
            status = 'Fields permissions mapping updated.'

        return status

    def getPermissionWidgets(self):
        schema = self.context.relevantDataSchema
        if schema is None:
            return None
        info = []
        for name, field in getFields(schema).items():
            field = trustedRemoveSecurityProxy(field)
            info.append(
                {'fieldName': name,
                 'fieldTitle': field.title,
                 'getter': getattr(self, name+'_get_perm_widget'),
                 'setter': getattr(self, name+'_set_perm_widget')} )
        return info


class AddState(BrowserView):

    def action(self, id):
        state = State()
        self.context[id] = state
        return self.request.response.redirect(self.request.URL[-2])


class AddTransition(BrowserView):

    # XXX This could and should be handled by a Vocabulary Field/Widget
    def getStateNames(self):
        pd = self.context.getProcessDefinition()
        states = removeAllProxies(pd.getStateNames())
        states.sort()
        return states

    def action(self, id, source, destination, condition=None, permission=None):
        condition = condition or None
        permission = permission or None
        transition = Transition(source, destination, condition, permission)
        self.context[id] = transition
        return self.request.response.redirect(self.request.URL[-2])


=== Added File Zope3/src/zope/app/workflow/browser/stateful/definition_edit.pt ===
<html metal:use-macro="views/standard_macros/page">
 <head>
  <title metal:fill-slot="title" i18n:translate="">
    Process Definition <-> Content Type Registry
  </title>
</head>

<body>
<div metal:fill-slot="body">

  <p tal:define="status view/update"
     tal:condition="status"
     tal:content="status" />

  <form action="./@@edit.html" method="POST">
    <h3>Set Workflow-Relevant Data Schema</h3>
    <div class="row"
         tal:content="structure view/relevantDataSchema_widget/row" />
    <div class="row">
      <div class="controls" style="width: 100%">
        <input type="submit" value="Refresh"
            i18n:attributes="value refresh-button" />
        <input type="submit" value="Set Schema" name="UPDATE_SUBMIT" />
       </div>
    </div>

    <tal:block define="widgets view/getPermissionWidgets"
               condition="widgets">
      <h3 i18n:translate="">Map permissions to Schema fields</h3>

      <tal:block repeat="widget widgets">
        <h5 tal:content="string:${widget/fieldTitle} (${widget/fieldName})">
          FieldName (Field Title)
        </h5>
        <div class="row" tal:replace="structure widget/getter/row">
          <div class="label" i18n:translate="">Get Permission</div>
          <div class="field">

          </div>
        </div>
        <div class="row" tal:replace="structure widget/setter/row">
          <div class="label" i18n:translate="">Set Permission</div>
          <div class="field">

          </div>
        </div>
      </tal:block>
      <div class="row">
        <div class="controls" style="width: 100%">
          <input type="submit" value="Refresh"
                 i18n:attributes="value refresh-button" />
          <input type="submit" value="Change" name="CHANGE"
                 i18n:attributes="value change-button" />
         </div>
      </div>
    </tal:block>

  </form>

</div>
</body>
</html>

=== Added File Zope3/src/zope/app/workflow/browser/stateful/definition_index.pt ===
<html metal:use-macro="views/standard_macros/page">
 <head>
  <title metal:fill-slot="title" i18n:translate="">
    Process Definition
  </title>
</head>

<body>
<div metal:fill-slot="body">

  <p i18n:translate="">
    Process Definition: 
    <tal:block tal:replace="view/getName" i18n:name="name"/>
  </p>
 
</div> 
</body>
</html>

=== Added File Zope3/src/zope/app/workflow/browser/stateful/definition_states.pt ===
<html metal:use-macro="views/standard_macros/page">
<head>
  <title metal:fill-slot="title" i18n:translate="">
    Process Definition States
  </title>
</head>
<body>
<div metal:fill-slot="body">

  <p i18n:translate="">States</p>
 
</div> 
</body>
</html>


=== Added File Zope3/src/zope/app/workflow/browser/stateful/definition_transitions.pt ===
<html metal:use-macro="views/standard_macros/page">
<head>
  <title metal:fill-slot="title" i18n:translate="">
    Process Definition Transitions
  </title>
</head>
<body>
<div metal:fill-slot="body">

  <p i18n:translate="">Transitions</p>
 
</div> 
</body>
</html>


=== Added File Zope3/src/zope/app/workflow/browser/stateful/filterTest.pt ===
<html metal:use-macro="views/standard_macros/page">
<body>
<div metal:fill-slot="body">

  <div tal:repeat="obj view/filterTest"
       tal:omit-tag="">

    <div tal:replace="obj"/><br />

  </div>

</div>
</body>
</html>






=== Added File Zope3/src/zope/app/workflow/browser/stateful/filteradapter.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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.
#
##############################################################################
"""filtering view for ProcessInstances of a stateful workflow
 
$Id: filteradapter.py,v 1.1 2004/02/27 16:50:38 philikon Exp $
"""
from zope.interface import implements
from zope.component import queryAdapter 
from zope.app.workflow.interfaces import IProcessInstanceContainerAdaptable
from zope.app.workflow.interfaces import IProcessInstanceContainer

from interfaces import IContentFilterAdapter

__metaclass__ = type


class FilterAdapter:
    
    __used_for__ = IProcessInstanceContainerAdaptable
    implements(IContentFilterAdapter)

    def __init__(self, context):
        self.context = context

    def filterListByState(self, objList, state, workflow='default'):
        """See IContentFilterAdapter"""
        res = []

        for obj in objList:
            if self.filterObjectByState(obj, state, workflow):
                res.append(obj)

        return res

    def filterObjectByState(self, object, state, workflow='default'):
        """See IContentFilterAdapter"""
        adapter = queryAdapter(object, IProcessInstanceContainer)
        if not adapter:
            return False
            
        for item in adapter.values():
            if item.processDefinitionName != workflow:
                continue
            if item.status == state:
                return True

        return False                


=== Added File Zope3/src/zope/app/workflow/browser/stateful/instance.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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.
#
##############################################################################
"""ProcessInstance views for a stateful workflow
 
$Id: instance.py,v 1.1 2004/02/27 16:50:38 philikon Exp $
"""
from zope.component import getAdapter, getService
from zope.proxy import removeAllProxies
from zope.publisher.browser import BrowserView
from zope.security.proxy import trustedRemoveSecurityProxy
from zope.schema import getFields

from zope.app.browser.form.submit import Update
from zope.app.form.utility import setUpWidget, applyWidgetsChanges
from zope.app.i18n import ZopeMessageIDFactory as _
from zope.app.interfaces.dublincore import IZopeDublinCore
from zope.app.services.servicenames import Workflows

from zope.app.workflow.interfaces import IProcessInstanceContainer
from zope.app.workflow.interfaces import IProcessInstanceContainerAdaptable

__metaclass__ = type

 
class ManagementView(BrowserView):

    __used_for__ = IProcessInstanceContainerAdaptable

    def __init__(self, context, request):
        super(ManagementView, self).__init__(context, request)
        workflow = self._getSelWorkflow() 
        if workflow.data is None:
            return
        schema = workflow.data.getSchema()
        for name, field in getFields(schema).items():
            # setUpWidget() does not mutate the field, so it is ok.
            field = trustedRemoveSecurityProxy(field)
            setUpWidget(self, name, field,
                        value=getattr(workflow.data, name))
        
    def _extractContentInfo(self, item):
        id, processInstance = item
        info = {}
        info['id']  = id
        info['name'] = self._getTitle(
            self._getProcessDefinition(processInstance))
        return info

    def listContentInfo(self):
        return map(self._extractContentInfo,
                   getAdapter(self.context, IProcessInstanceContainer).items())

    def getWorkflowTitle(self):
        pi = self._getSelWorkflow()
        if pi is None:
            return None
        
        return self._getTitle(self._getProcessDefinition(pi))

    def getTransitions(self):
        info = {}
        pi   = self._getSelWorkflow()
        if pi is None:
            return info

        pd = self._getProcessDefinition(pi)
        clean_pd = removeAllProxies(pd)

        current_state = clean_pd.getState(pi.status)
        adapter = getAdapter(current_state, IZopeDublinCore)
        info['status'] = adapter.title or pi.status

        transition_names = pi.getOutgoingTransitions()
        trans_info = []
        for name in transition_names:
            transition = clean_pd.getTransition(name)
            adapter = getAdapter(transition, IZopeDublinCore)
            trans_info.append({'name':name,
                               'title': adapter.title or name})
        info['transitions'] = trans_info
        return info

    def fireTransition(self):
        pi    = self._getSelWorkflow()
        if pi is None:
            return

        trans = self.request.get('selTransition', None)
        self.request.response.redirect('@@workflows.html?workflow=%s'
                                       % pi.processDefinitionName)
        if pi and trans:
            pi.fireTransition(trans)


    def _getTitle(self, obj):
        return (getAdapter(obj, IZopeDublinCore).title or obj.__name___)

 
    def _getSelWorkflow(self):
        reqWorkflow = self.request.get('workflow', u'')
        pi_container = getAdapter(self.context, IProcessInstanceContainer)
        if reqWorkflow is u'':
            available_instances = pi_container.keys()
            if len(available_instances) > 0:
                pi = pi_container[available_instances[0]]
            else:
                pi = None
        else:
            pi = pi_container[reqWorkflow]
        
        return pi


    def _getProcessDefinition(self, processInstance):
        ws = getService(self.context, Workflows)
        return ws.getProcessDefinition(processInstance.processDefinitionName)


    def widgets(self):
        if self._getSelWorkflow().data is None:
            return []
        schema = self._getSelWorkflow().data.getSchema()
        return [getattr(self, name+'_widget')
                for name in getFields(schema).keys()]

    
    def update(self):
        status = ''
        workflow = self._getSelWorkflow() 

        if Update in self.request and workflow.data is not None:
            schema = trustedRemoveSecurityProxy(workflow.data.getSchema())
            changed = applyWidgetsChanges(
                self, workflow.data, schema, names=getFields(schema).keys(),
                exclude_readonly=True)
            if changed:
                status = _('Updated Workflow Data.')

        return status


=== Added File Zope3/src/zope/app/workflow/browser/stateful/instance_manage.pt ===
<html metal:use-macro="views/standard_macros/page">
<body>
<div metal:fill-slot="body">

  <h3 i18n:translate="">Workflow Options</h3>
  <br/>

  <div metal:define-macro="contents">
    <div metal:define-macro="contents_selectWorkflow"
         tal:define="workflow request/workflow | nothing">
      <div tal:condition="not:workflow" tal:omit-tag="">
        <form name="containerContentsForm" method="get" 
              action="@@workflows.html" 
              tal:define="container_contents view/listContentInfo"
              tal:condition="container_contents">
          <span i18n:translate="">Workflow:</span> 
          <select name="workflow" size="1">
            <option tal:repeat="workflow container_contents" 
                    tal:attributes="value workflow/id"
                    tal:content="workflow/name"></option>
          </select>
          &nbsp;<input type="submit" value="Choose" 
                       i18n:attributes="value choose-button"/>
        </form>
      </div>
      <div tal:condition="workflow" tal:omit-tag="" i18n:translate="">
        Workflow: 
        <div tal:replace="view/getWorkflowTitle" 
             i18n:name="wf_title"/>
      </div>
    </div>
    <div metal:define-macro="contents_changeState">
    </div>
    
  </div>
  <br />
  <div metal:define-macro="contents_transitions"
       tal:define="info view/getTransitions"
       tal:condition="info">
      <div i18n:translate="">
        Current Status: 
        <div tal:replace="info/status"/>
      </div>
      <br />
      <span i18n:translate="">Possible State Changes:</span>
      <form action="@@fireTransition.html" method="get">
      <input type="hidden" name="workflow"
             tal:attributes="value request/workflow | nothing" />
        <div tal:repeat="trans info/transitions" 
             tal:condition="info/transitions | nothing"
             tal:omit-tag="">
          <input type="radio"
                 name="selTransition"
                 tal:attributes="value trans/name"/>
          <span tal:replace="trans/title"/><br />
        </div>
        <input type="submit" value="Make Transition" 
               i18n:attributes="value make-transition-button"/>
        </form>
  </div>
 
  <h3 i18n:translate="">Workflow-relevant Data</h3>

  <p tal:define="status view/update"
     tal:condition="status"
     tal:content="status" />

  <form name="." method="POST"> 
    <div class="row" tal:repeat="widget view/widgets"
        tal:content="structure widget/row">
      <div class="label" i18n:translate="">Name</div>
      <div class="field"><input type="text" style="width:100%" /></div>
    </div>

    <div class="row">
      <div class="controls">
        <input type="submit" value="Refresh" 
            i18n:attributes="value refresh-button" />
        <input type="submit" name="UPDATE_SUBMIT" value="Submit" 
            i18n:attributes="value submit-button"/>
      </div>
    </div>
  </form> 

</div>
</body>
</html>


=== Added File Zope3/src/zope/app/workflow/browser/stateful/interfaces.py ===
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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.
#
##############################################################################
"""Interfaces for stateful workflow.

$Id: interfaces.py,v 1.1 2004/02/27 16:50:38 philikon Exp $
"""
from zope.interface import Interface

class IContentFilterAdapter(Interface):

    def filterListByState(objList, state, workflow='default'):
        """Filter a list of objects according to given workflow and state

        objList  ... list of objects
        state    ... name of a state (of the given workflow) in which the result
                      objects must be
        workflow ... name of a workflow to which result objects must be attached
        """

    def filterObjectByState(object, state, workflow='default'):
        """Filter an object according to the given workflow and state."""




=== Added File Zope3/src/zope/app/workflow/browser/stateful/published_content.pt ===
<html metal:use-macro="views/standard_macros/page">
<body>
<div metal:fill-slot="body">

  <div tal:repeat="obj view/listPublishedItems" tal:omit-tag="">
    <div tal:content="obj/url"/><br />
  </div>

</div>
</body>
</html>






=== Added File Zope3/src/zope/app/workflow/browser/stateful/testobject.zcml ===
<zope:configure 
   xmlns:zope="http://namespaces.zope.org/zope"
   xmlns="http://namespaces.zope.org/browser">

  <addform
      label="Add Test Object"
      name="AddTestObject"
      schema="zope.app.workflow.stateful.testobject.ITestObject"
      content_factory="zope.app.workflow.stateful.testobject.TestObject"
      permission="zope.ManageContent"
      menu="add_content" title="Test Object"/>

  <editform
      schema="zope.app.workflow.stateful.testobject.ITestObject"
      for="zope.app.workflow.stateful.testobject.ITestObject"
      label="Change Test Object"
      name="edit.html"
      permission="zope.ManageContent"
      menu="zmi_views" title="Edit" />

</zope:configure>




More information about the Zope3-Checkins mailing list