[Zope3-checkins] CVS: Zope3/src/zope/app/browser/workflow/stateful - definition_edit.pt:1.1 testobject.zcml:1.1 configure.zcml:1.4 definition.py:1.5 instance.py:1.6 instance_manage.pt:1.4
Stephan Richter
srichter@cosmos.phy.tufts.edu
Thu, 31 Jul 2003 11:02:03 -0400
Update of /cvs-repository/Zope3/src/zope/app/browser/workflow/stateful
In directory cvs.zope.org:/tmp/cvs-serv10755/src/zope/app/browser/workflow/stateful
Modified Files:
configure.zcml definition.py instance.py instance_manage.pt
Added Files:
definition_edit.pt testobject.zcml
Log Message:
Implemented relevant data for Processes (read workflows). You can specify
a schema which contains the fields that should be available as relevant
data. Once the schema is set, you are able to specify "get" and "set"
permissions for each field. That;s it for the setup.
When you then create a Content Object that uses the process definition for
which you declared the schema, you will see that there is a form in the
'Workflows' tab of this content object that allows you to manipulate the
releavant data.
I also enhanced the XML Import/Export to support relevant data and their
permissions.
The easiest way to check all this functionality out is to uncomment the
include directives in browser/workflow/stateful/configure.zcml and
workflow/stateful/configure.zcml (both at the end of the file).
This completes my code and status review of the workflow package, which I
think is now ready for the beta.
=== Added File Zope3/src/zope/app/browser/workflow/stateful/definition_edit.pt ===
<html metal:use-macro="views/standard_macros/page">
<head>
<title>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>Map permissions to Schema fields</h3>
<tal:block repeat="widget widgets">
<h5 tal:content="string:${widget/fieldName} (${widget/fieldName})">
FieldName (Field Title)
</h5>
<div class="row" tal:replace="structure widget/getter/row">
<div class="label">Get Permission</div>
<div class="field">
</div>
</div>
<div class="row" tal:replace="structure widget/setter/row">
<div class="label">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" />
</div>
</div>
</tal:block>
</form>
</div></body>
</html>
=== Added File Zope3/src/zope/app/browser/workflow/stateful/testobject.zcml ===
<zopeConfigure
xmlns="http://namespaces.zope.org/zope"
xmlns:browser="http://namespaces.zope.org/browser">
<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"/>
<browser: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" />
</zopeConfigure>
=== Zope3/src/zope/app/browser/workflow/stateful/configure.zcml 1.3 => 1.4 ===
--- Zope3/src/zope/app/browser/workflow/stateful/configure.zcml:1.3 Tue Jul 29 20:00:16 2003
+++ Zope3/src/zope/app/browser/workflow/stateful/configure.zcml Thu Jul 31 11:01:26 2003
@@ -19,21 +19,22 @@
"zope.app.browser.workflow.stateful.definition.StatefulProcessDefinitionView"
permission="zope.ManageServices">
- <browser:page name="index.html" template="definition_index.pt" />
+ <browser:page name="index.html" template="definition_index.pt"/>
</browser:pages>
<browser:editform
schema="zope.app.interfaces.workflow.stateful.IStatefulProcessDefinition"
name="edit.html"
- menu="zmi_views"
- label="Edit a Stateful ProcessDefinition"
+ template="definition_edit.pt"
+ class=".definition.RelevantDataSchemaEdit"
+ menu="zmi_views" title="Relevant Data Schema"
permission="zope.workflow.ManageProcessDefinitions"
/>
<browser:menuItems
- for="zope.app.interfaces.workflow.stateful.IStatefulProcessDefinition"
- menu="zmi_actions">
+ for="zope.app.interfaces.workflow.stateful.IStatefulProcessDefinition"
+ menu="zmi_actions">
<browser:menuItem
title="Manage States" action="states/contents.html" />
@@ -162,17 +163,11 @@
permission="zope.workflow.UseProcessInstances"
class="zope.app.browser.workflow.stateful.instance.ManagementView">
- <browser:page name="workflows.html" attribute="contents" />
+ <browser:page name="workflows.html" template="instance_manage.pt"
+ menu="zmi_views" title="Workflows"/>
<browser:page name="fireTransition.html" attribute="fireTransition" />
</browser:pages>
-<browser:menuItem
- for="zope.app.interfaces.workflow.IProcessInstanceContainerAdaptable"
- menu="zmi_views"
- title="Workflows"
- action="workflows.html"
- />
-
<browser:pages
for="zope.app.interfaces.container.IContentContainer"
@@ -183,12 +178,14 @@
</browser:pages>
-<!-- uhm .. this seems to be to generic in its definition
- and not really nice as well .. -->
+<!-- uhm ... this seems to be too generic in its definition
+ and not really nice as well. -->
<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"/-->
</zopeConfigure>
=== Zope3/src/zope/app/browser/workflow/stateful/definition.py 1.4 => 1.5 ===
--- Zope3/src/zope/app/browser/workflow/stateful/definition.py:1.4 Sat Jun 21 17:22:08 2003
+++ Zope3/src/zope/app/browser/workflow/stateful/definition.py Thu Jul 31 11:01:27 2003
@@ -21,18 +21,22 @@
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.
- """
+ """Custom adding view for StatesContainer objects."""
menu_id = "add_stateful_states"
class TransitionsContainerAdding(Adding):
- """Custom adding view for TransitionsContainer objects.
- """
+ """Custom adding view for TransitionsContainer objects."""
menu_id = "add_stateful_transitions"
def getProcessDefinition(self):
@@ -41,14 +45,13 @@
# 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)
-
+ return super(StateAddFormHelper, self).__call__(template_usage,
+ *args, **kw)
class StatefulProcessDefinitionView(BrowserView):
@@ -57,6 +60,69 @@
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').getData()
+ setPerm = getattr(self, name+'_set_perm_widget').getData()
+ 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):
@@ -68,6 +134,7 @@
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())
=== Zope3/src/zope/app/browser/workflow/stateful/instance.py 1.5 => 1.6 ===
--- Zope3/src/zope/app/browser/workflow/stateful/instance.py:1.5 Tue Jun 3 18:46:18 2003
+++ Zope3/src/zope/app/browser/workflow/stateful/instance.py Thu Jul 31 11:01:27 2003
@@ -17,6 +17,8 @@
"""
__metaclass__ = type
+from zope.app.browser.form.submit import Update
+from zope.app.form.utility import setUpWidget, applyWidgetsChanges
from zope.app.interfaces.dublincore import IZopeDublinCore
from zope.app.interfaces.workflow import IProcessInstanceContainer
from zope.app.interfaces.workflow import IProcessInstanceContainerAdaptable
@@ -26,11 +28,24 @@
from zope.context import getWrapperData
from zope.proxy import removeAllProxies
from zope.publisher.browser import BrowserView
+from zope.security.proxy import trustedRemoveSecurityProxy
+from zope.schema import getFields
class ManagementView(BrowserView):
__used_for__ = IProcessInstanceContainerAdaptable
+ def __init__(self, context, request):
+ super(ManagementView, self).__init__(context, request)
+ workflow = self._getSelWorkflow()
+ 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 = {}
@@ -43,9 +58,6 @@
return map(self._extractContentInfo,
getAdapter(self.context, IProcessInstanceContainer).items())
- contents = ViewPageTemplateFile('instance_manage.pt')
- contentsMacros = contents
-
def getWorkflowTitle(self):
pi = self._getSelWorkflow()
if pi is None:
@@ -59,7 +71,6 @@
if pi is None:
return info
-
pd = self._getProcessDefinition(pi)
clean_pd = removeAllProxies(pd)
@@ -114,3 +125,22 @@
return ws.getProcessDefinition(processInstance.processDefinitionName)
+ def widgets(self):
+ schema = self._getSelWorkflow().data.getSchema()
+ return [getattr(self, name+'_widget')
+ for name in getFields(schema).keys()]
+
+
+ def update(self):
+ status = ''
+
+ if Update in self.request:
+ workflow = self._getSelWorkflow()
+ schema = trustedRemoveSecurityProxy(workflow.data.getSchema())
+ changed = applyWidgetsChanges(
+ self, workflow.data, schema, names=getFields(schema).keys(),
+ exclude_readonly=True)
+ if changed:
+ status = u'Updated Workflow Data.'
+
+ return status
=== Zope3/src/zope/app/browser/workflow/stateful/instance_manage.pt 1.3 => 1.4 ===
--- Zope3/src/zope/app/browser/workflow/stateful/instance_manage.pt:1.3 Wed Jun 25 17:18:57 2003
+++ Zope3/src/zope/app/browser/workflow/stateful/instance_manage.pt Thu Jul 31 11:01:27 2003
@@ -4,11 +4,14 @@
</head>
<body>
<div metal:fill-slot="body">
+ <h3>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"
+ <form name="containerContentsForm" method="get"
+ action="@@workflows.html"
tal:define="container_contents view/listContentInfo"
tal:condition="container_contents">
Workflow:
@@ -17,7 +20,7 @@
tal:attributes="value workflow/id"
tal:content="workflow/name"></option>
</select>
- <input type="submit" value="choose" />
+ <input type="submit" value="Choose" />
</form>
</div>
<div tal:condition="workflow" tal:omit-tag="">
@@ -46,9 +49,33 @@
tal:attributes="value trans/name"/>
<span tal:replace="trans/title"/><br />
</div>
- <input type="submit" value="do it" />
+ <input type="submit" value="Make Transition" />
</form>
</div>
+
+ <h3>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">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>