work in progress: task management with work items
git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@3091 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
429f1d33c4
commit
92bacf05d4
5 changed files with 151 additions and 33 deletions
81
organize/work/README.txt
Normal file
81
organize/work/README.txt
Normal file
|
@ -0,0 +1,81 @@
|
|||
===============================================================
|
||||
loops - Linked Objects for Organization and Processing Services
|
||||
===============================================================
|
||||
|
||||
($Id$)
|
||||
|
||||
Let's do some basic setup
|
||||
|
||||
>>> from zope.app.testing.setup import placefulSetUp, placefulTearDown
|
||||
>>> site = placefulSetUp(True)
|
||||
>>> from zope import component, interface
|
||||
>>> from zope.publisher.browser import TestRequest
|
||||
|
||||
and set up a simple loops site with a concept manager and some concepts
|
||||
(with all the type machinery, what in real life is done via standard
|
||||
ZCML setup):
|
||||
|
||||
>>> from loops.organize.setup import SetupManager
|
||||
>>> component.provideAdapter(SetupManager, name='organize')
|
||||
>>> from loops.organize.work.setup import SetupManager
|
||||
>>> component.provideAdapter(SetupManager, name='organize.work')
|
||||
|
||||
>>> from loops.tests.setup import TestSite
|
||||
>>> t = TestSite(site)
|
||||
>>> concepts, resources, views = t.setup()
|
||||
|
||||
|
||||
Work Items - Plannning and Recording Activities for Tasks
|
||||
=========================================================
|
||||
|
||||
>>> loopsRoot = concepts.getLoopsRoot()
|
||||
>>> records = loopsRoot.getRecordManager()
|
||||
|
||||
More setup
|
||||
----------
|
||||
|
||||
In order to be able to login and store favorites and other personal data
|
||||
we have to prepare our environment. We need some basic adapter registrations,
|
||||
and a pluggable authentication utility with a principal folder.
|
||||
|
||||
>>> from loops.organize.tests import setupObjectsForTesting
|
||||
>>> setupData = setupObjectsForTesting(site, concepts)
|
||||
>>> johnC = setupData.johnC
|
||||
|
||||
We also assign a task as a target to the home node so that we are able
|
||||
to assign work items to this task.
|
||||
|
||||
>>> tTask = concepts['task']
|
||||
>>> home = views['home']
|
||||
>>> from loops.concept import Concept
|
||||
>>> from loops.setup import addAndConfigureObject
|
||||
>>> task01 = addAndConfigureObject(concepts, Concept, 'loops_dev',
|
||||
... title=u'loops Development', conceptType=tTask)
|
||||
>>> home.target = task01
|
||||
|
||||
Forms for adding and editing work items
|
||||
---------------------------------------
|
||||
|
||||
New work items are created using a CreateWorkItemForm.
|
||||
|
||||
>>> from loops.organize.work.browser import CreateWorkItemForm, CreateWorkItem
|
||||
>>> form = CreateWorkItemForm(home, TestRequest())
|
||||
|
||||
When this form is submitted, a form controller is automatically created
|
||||
for the view on the currently shown node. The data from the form is processed
|
||||
by calling the form controller's update method
|
||||
|
||||
>>> input = {'form.action': 'create_workitem', 'workitem.action': 'finish'}
|
||||
>>> request = TestRequest(form=input)
|
||||
>>> from loops.browser.node import NodeView
|
||||
>>> view = NodeView(home, request)
|
||||
>>> cwiController = CreateWorkItem(view, request)
|
||||
|
||||
>>> cwiController.update()
|
||||
False
|
||||
|
||||
|
||||
Fin de partie
|
||||
=============
|
||||
|
||||
>>> placefulTearDown()
|
|
@ -31,11 +31,11 @@ from zope.traversing.browser import absoluteURL
|
|||
from zope.traversing.api import getName
|
||||
|
||||
from cybertools.browser.action import actions
|
||||
from cybertools.tracking.browser import TrackView
|
||||
from loops.browser.action import DialogAction
|
||||
from loops.browser.form import ObjectForm, EditObject
|
||||
from loops.organize.tracking.browser import BaseTrackView
|
||||
from loops import util
|
||||
from loops.util import _
|
||||
|
||||
|
||||
work_macros = ViewPageTemplateFile('work_macros.pt')
|
||||
|
@ -46,7 +46,7 @@ class WorkItemView(BaseTrackView):
|
|||
pass
|
||||
|
||||
|
||||
class CreateWorkItemForm(ObjectForm):
|
||||
class CreateWorkItemForm(ObjectForm, BaseTrackView):
|
||||
|
||||
template = work_macros
|
||||
|
||||
|
@ -63,6 +63,14 @@ class CreateWorkItemForm(ObjectForm):
|
|||
return time.strftime('%Y-%m-%dT%H:%M')
|
||||
|
||||
|
||||
class CreateWorkItem(EditObject, BaseTrackView):
|
||||
|
||||
def update(self):
|
||||
url = self.view.virtualTargetUrl + '?version=this'
|
||||
self.request.response.redirect(url)
|
||||
return False
|
||||
|
||||
|
||||
# actions
|
||||
|
||||
actions.register('createWorkitem', 'portlet', DialogAction,
|
||||
|
|
|
@ -28,6 +28,15 @@
|
|||
class="loops.organize.work.browser.CreateWorkItemForm"
|
||||
permission="zope.ManageContent" />
|
||||
|
||||
<zope:adapter
|
||||
name="create_workitem"
|
||||
for="loops.browser.node.NodeView
|
||||
zope.publisher.interfaces.browser.IBrowserRequest"
|
||||
factory="loops.organize.work.browser.CreateWorkItem"
|
||||
permission="zope.View" />
|
||||
|
||||
<!-- setup -->
|
||||
|
||||
<zope:adapter factory="loops.organize.work.setup.SetupManager"
|
||||
name="organize.work" />
|
||||
|
||||
|
|
22
organize/work/tests.py
Executable file
22
organize/work/tests.py
Executable file
|
@ -0,0 +1,22 @@
|
|||
# $Id$
|
||||
|
||||
import unittest, doctest
|
||||
from zope.testing.doctestunit import DocFileSuite
|
||||
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
"Basic tests for the loops.organize.work package."
|
||||
|
||||
def testBasics(self):
|
||||
pass
|
||||
|
||||
|
||||
def test_suite():
|
||||
flags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
|
||||
return unittest.TestSuite((
|
||||
unittest.makeSuite(Test),
|
||||
DocFileSuite('README.txt', optionflags=flags),
|
||||
))
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(defaultTest='test_suite')
|
|
@ -7,6 +7,7 @@
|
|||
id="addWorkitem_form" class="dialog"
|
||||
dojoType="dijit.form.Form">
|
||||
<input type="hidden" name="form.action" value="create_workitem" />
|
||||
<input type="hidden" name="workitem.action" value="finish" />
|
||||
<div class="heading" i18n:translate="">Add Work Item</div>
|
||||
<div>
|
||||
<label i18n:translate=""
|
||||
|
@ -17,34 +18,33 @@
|
|||
style="width: 60em"></textarea></div>
|
||||
</div>
|
||||
<div>
|
||||
<label i18n:translate=""
|
||||
for="start-end">Start - End</label>
|
||||
<div id="start-end">
|
||||
<input type="text" name="field" style="width: 8em"
|
||||
dojoType="dijit.form.DateTextBox"
|
||||
name="start_date" required="true"
|
||||
tal:attributes="value view/defaultDate" />
|
||||
<input type="text" name="field" style="width: 6em"
|
||||
dojoType="dijit.form.TimeTextBox"
|
||||
name="start_time" required="true"
|
||||
tal:attributes="value view/defaultTime" /> -
|
||||
<input type="text" name="field" style="width: 6em"
|
||||
dojoType="dijit.form.TimeTextBox"
|
||||
name="end_time" required="true"
|
||||
tal:attributes="value view/defaultTime" />
|
||||
</div>
|
||||
<label i18n:translate=""
|
||||
for="duration-effort">Duration / Effort (hh:mm)</label>
|
||||
<div id="duration-effort">
|
||||
<input type="text" style="width: 5em"
|
||||
dojoType="dijit.form.ValidationTextBox"
|
||||
regexp="[0-9]{1,2}(:[0-5][0-9]){0,1}"
|
||||
name="duration" /> /
|
||||
<input type="text" style="width: 5em"
|
||||
dojoType="dijit.form.ValidationTextBox"
|
||||
regexp="[0-9]{1,2}(:[0-5][0-9]){0,1}"
|
||||
name="effort" />
|
||||
</div>
|
||||
<label i18n:translate=""
|
||||
for="start-end">Start - End</label>
|
||||
<div id="start-end">
|
||||
<input type="text" style="width: 8em"
|
||||
dojoType="dijit.form.DateTextBox"
|
||||
name="start_date" required="true"
|
||||
tal:attributes="value view/defaultDate" />
|
||||
<input type="text" style="width: 6em"
|
||||
dojoType="dijit.form.TimeTextBox"
|
||||
name="start_time" required="true"
|
||||
tal:attributes="value view/defaultTime" /> -
|
||||
<input type="text" style="width: 6em"
|
||||
dojoType="dijit.form.TimeTextBox"
|
||||
name="end_time" required="true"
|
||||
tal:attributes="value view/defaultTime" /></div>
|
||||
<label i18n:translate=""
|
||||
for="duration-effort">Duration / Effort (hh:mm)</label>
|
||||
<div id="duration-effort">
|
||||
<input type="text" style="width: 5em"
|
||||
dojoType="dijit.form.ValidationTextBox"
|
||||
regexp="[0-9]{1,2}(:[0-5][0-9]){0,1}"
|
||||
name="duration" /> /
|
||||
<input type="text" style="width: 5em"
|
||||
dojoType="dijit.form.ValidationTextBox"
|
||||
regexp="[0-9]{1,2}(:[0-5][0-9]){0,1}"
|
||||
name="effort" /></div>
|
||||
</div>
|
||||
<div>
|
||||
<label i18n:translate=""
|
||||
for="comment">Comment</label>
|
||||
|
@ -53,15 +53,13 @@
|
|||
dojoType="dijit.form.SimpleTextarea"
|
||||
style="width: 60em"></textarea></div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="buttons">
|
||||
<input value="Save" type="submit"
|
||||
onClick="return closeDialog(true)"
|
||||
i18n:attributes="value">
|
||||
<input type="button" value="Cancel"
|
||||
onClick="return closeDialog(false)"
|
||||
i18n:attributes="value">
|
||||
</div>
|
||||
i18n:attributes="value"></div>
|
||||
</form>
|
||||
</metal:block>
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue