diff --git a/organize/work/README.txt b/organize/work/README.txt index 1f4409d..b4ec648 100644 --- a/organize/work/README.txt +++ b/organize/work/README.txt @@ -99,6 +99,9 @@ by calling the form controller's update method 'created': ..., 'creator': '33', 'start': 1230487200, 'duration': 4500, 'effort': 900}>] +Work items views +---------------- + >>> from loops.organize.work.browser import WorkItemView, WorkItemsView >>> wi01 = workItems['0000001'] >>> view = WorkItemView(wi01, TestRequest()) @@ -112,6 +115,34 @@ by calling the form controller's update method >>> view.day, view.start, view.end (u'08/12/28', u'19:00', u'20:15') +Work items life cycle +--------------------- + +Let's create another work item, now in state planned. + + >>> input = {u'form.action': u'create_workitem', u'workitem.action': u'plan', + ... u'title': u'Install Zope', + ... u'start_date': u'2009-01-19', u'start_time': u'T09:00:00'} + >>> request = TestRequest(form=input) + >>> request.setPrincipal(pJohn) + >>> nodeView = NodeView(home, request) + >>> cwiController = CreateWorkItem(nodeView, request) + >>> cwiController.update() + False + +If we now open another form, providing the identifier of the newly created +work item, the form will be pre-filled with some of the item's data. + + >>> form = CreateWorkItemForm(home, TestRequest(form=dict(id='0000002'))) + >>> form.title + u'Install Zope' + + >>> form.actions + [{'name': 'plan', 'title': 'plan'}, {'name': 'accept', 'title': 'accept'}, + {'name': 'start', 'title': 'start working'}, {'name': 'work', 'title': 'work'}, + {'name': 'finish', 'title': 'finish'}, {'name': 'cancel', 'title': 'cancel'}, + {'name': 'modify', 'title': 'modify'}] + Fin de partie ============= diff --git a/organize/work/browser.py b/organize/work/browser.py index f45a25a..2fc1a4e 100644 --- a/organize/work/browser.py +++ b/organize/work/browser.py @@ -33,6 +33,7 @@ from zope.traversing.api import getName from cybertools.ajax import innerHtml from cybertools.browser.action import actions from cybertools.organize.interfaces import IWorkItems +from cybertools.tracking.btree import getTimeStamp from loops.browser.action import DialogAction from loops.browser.concept import ConceptView from loops.browser.form import ObjectForm, EditObject @@ -41,6 +42,7 @@ from loops.organize.party import getPersonForUser from loops.organize.stateful.browser import StateAction from loops.organize.tracking.browser import BaseTrackView from loops.organize.tracking.report import TrackDetails +from loops.organize.work.base import WorkItem from loops import util from loops.util import _ @@ -163,10 +165,7 @@ class WorkItemDetails(TrackDetails): return self.formatTimeStamp(self.track.created, 'dateTime') def formatTimeDelta(self, value): - if not value: - return '' - h, m = divmod(int(value) / 60, 60) - return '%02i:%02i' % (h, m) + return formatTimeDelta(value) @Lazy def isLastInRun(self): @@ -243,22 +242,58 @@ class CreateWorkItemForm(ObjectForm, BaseTrackView): if id is not None: workItems = self.loopsRoot.getRecordManager()['work'] return workItems.get(id) + return WorkItem(None, 0, None, {}) @Lazy def title(self): - return self.track is not None and self.track.title or u'' + return self.track.title or u'' @Lazy def description(self): - return self.track is not None and self.track.description or u'' + return self.track.description or u'' @Lazy - def defaultDate(self): - return time.strftime('%Y-%m-%d') + def date(self): + ts = self.track.start or getTimeStamp() + return time.strftime('%Y-%m-%d', time.localtime(ts)) @Lazy - def defaultTime(self): - return time.strftime('%Y-%m-%dT%H:%M') + def startTime(self): + ts = self.track.start or getTimeStamp() + return time.strftime('%Y-%m-%dT%H:%M', time.localtime(ts)) + + @Lazy + def endTime(self): + if self.state == 'running': + ts = getTimeStamp() + else: + ts = self.track.end or getTimeStamp() + return time.strftime('%Y-%m-%dT%H:%M', time.localtime(ts)) + + @Lazy + def state(self): + return self.track.state + + @Lazy + def actions(self): + return [dict(name=t.name, title=t.title) + for t in self.track.getAvailableTransitions()] + + @Lazy + def duration(self): + if self.state == 'running': + return u'' + return formatTimeDelta(self.track.duration) + + @Lazy + def effort(self): + if self.state == 'running': + return u'' + return formatTimeDelta(self.track.effort) + + @Lazy + def comment(self): + return self.track.comment or u'' class CreateWorkItem(EditObject, BaseTrackView): @@ -368,3 +403,10 @@ def parseDate(s): if not s: return None return int(time.mktime(time.strptime(s, '%Y-%m-%d'))) + +def formatTimeDelta(value): + if not value: + return u'' + h, m = divmod(int(value) / 60, 60) + return u'%02i:%02i' % (h, m) + diff --git a/organize/work/work_macros.pt b/organize/work/work_macros.pt index a2e25e7..579e0df 100644 --- a/organize/work/work_macros.pt +++ b/organize/work/work_macros.pt @@ -64,7 +64,7 @@
- +
Add Work Item
@@ -82,34 +82,45 @@ dojoType="dijit.form.SimpleTextarea" style="width: 60em" tal:content="view/description"> +
+ + +
+ tal:attributes="value view/date" /> - + tal:attributes="value view/startTime" /> -
+ tal:attributes="value view/endTime" />
/ + regexp="[0-9]{1,2}(:[0-5][0-9]){0,1}" + tal:attributes="value view/duration" /> /
+ regexp="[0-9]{1,2}(:[0-5][0-9]){0,1}" + tal:attributes="value view/effort" />
+ style="width: 60em" + tal:content="view/comment">