diff --git a/browser/concept_macros.pt b/browser/concept_macros.pt
index 9113abc..d48f238 100644
--- a/browser/concept_macros.pt
+++ b/browser/concept_macros.pt
@@ -101,7 +101,7 @@
Resource Title
-
diff --git a/browser/node.py b/browser/node.py
index df2180f..794f646 100644
--- a/browser/node.py
+++ b/browser/node.py
@@ -117,6 +117,7 @@ class NodeView(BaseView):
if not IUnauthenticatedPrincipal.providedBy(self.request.principal):
mi = self.controller.memberInfo
title = mi.title.value or _(u'Personal Informations')
+ url=None
obj = mi.get('object')
if obj is not None:
query = self.conceptManager.get('personal_info')
@@ -125,11 +126,11 @@ class NodeView(BaseView):
url = self.getUrlForTarget(obj.value)
else:
url = self.getUrlForTarget(query)
- cm.register('portlet_right', 'personal', title=title,
- subMacro=node_macros.macros['personal'],
- icon='cybertools.icons/user.png',
- url=url,
- priority=10)
+ cm.register('portlet_right', 'personal', title=title,
+ subMacro=node_macros.macros['personal'],
+ icon='cybertools.icons/user.png',
+ url=url,
+ priority=10)
# force early portlet registrations by target by setting up target view
self.virtualTarget
diff --git a/organize/tracking/report.py b/organize/tracking/report.py
index 4fef072..c547c7f 100644
--- a/organize/tracking/report.py
+++ b/organize/tracking/report.py
@@ -269,7 +269,9 @@ class TrackDetails(BaseView):
@Lazy
def user(self):
- userName = self.track.userName
+ return self.getUserForUserName(self.track.userName)
+
+ def getUserForUserName(self, userName):
obj = util.getObjectForUid(userName)
if obj is None:
try:
@@ -292,9 +294,6 @@ class TrackDetails(BaseView):
@Lazy
def timeStamp(self):
return self.formatTimeStamp(self.track.timeStamp)
- #value = datetime.fromtimestamp(self.track.timeStamp)
- #return format.formatDate(value, 'dateTime', self.timeStampFormat,
- # self.view.languageInfo.language)
def formatTimeStamp(self, ts, f='dateTime'):
if not ts:
diff --git a/organize/work/browser.py b/organize/work/browser.py
index c2a8d7e..f45a25a 100644
--- a/organize/work/browser.py
+++ b/organize/work/browser.py
@@ -30,6 +30,7 @@ from zope.app.pagetemplate import ViewPageTemplateFile
from zope.traversing.browser import absoluteURL
from zope.traversing.api import getName
+from cybertools.ajax import innerHtml
from cybertools.browser.action import actions
from cybertools.organize.interfaces import IWorkItems
from loops.browser.action import DialogAction
@@ -37,6 +38,7 @@ from loops.browser.concept import ConceptView
from loops.browser.form import ObjectForm, EditObject
from loops.browser.node import NodeView
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 import util
@@ -50,7 +52,7 @@ work_macros = ViewPageTemplateFile('work_macros.pt')
class BaseWorkItemsView(object):
- columns = set(['Task', 'User', 'Title', 'Start', 'End', 'Duration'])
+ columns = set(['Task', 'User', 'Title', 'Start', 'End', 'Duration', 'Info'])
lastMonth = lastDay = None
@@ -85,7 +87,7 @@ class WorkItemsView(BaseWorkItemsView, NodeView):
""" Standard view for showing work items for a node's target.
"""
- columns = set(['User', 'Title', 'Day', 'Start', 'End', 'Duration'])
+ columns = set(['User', 'Title', 'Day', 'Start', 'End', 'Duration', 'Info'])
@Lazy
def allWorkItems(self):
@@ -105,7 +107,7 @@ class UserWorkItems(BaseWorkItemsView, ConceptView):
""" A query view showing work items for a person, the query's parent.
"""
- columns = set(['Task', 'Title', 'Day', 'Start', 'End', 'Duration'])
+ columns = set(['Task', 'Title', 'Day', 'Start', 'End', 'Duration', 'Info'])
@property
def macro(self):
@@ -152,12 +154,73 @@ class WorkItemDetails(TrackDetails):
def effort(self):
return self.formatTimeDelta(self.track.effort)
+ @Lazy
+ def startDay(self):
+ return self.formatTimeStamp(self.track.timeStamp, 'date')
+
+ @Lazy
+ def created(self):
+ 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)
+ @Lazy
+ def isLastInRun(self):
+ currentWorkItems = list(self.view.workItems.query(runId=self.track.runId))
+ return self.track == currentWorkItems[-1]
+
+ def actions(self):
+ info = DialogAction(self.view,
+ description=_(u'Information about this work item.'),
+ viewName='workitem_info.html',
+ dialogName='',
+ icon='cybertools.icons/info.png',
+ cssClass='icon-action',
+ page=self.view.nodeView,
+ target=self.object,
+ addParams=dict(id=self.track.__name__))
+ actions = [info, WorkItemStateAction(self)]
+ if self.isLastInRun:
+ self.view.registerDojoDateWidget()
+ self.view.registerDojoNumberWidget()
+ actions.append(DialogAction(self.view,
+ description=_(u'Create a work item.'),
+ viewName='create_workitem.html',
+ dialogName='',
+ icon='edit.gif',
+ cssClass='icon-action',
+ page=self.view.nodeView,
+ target=self.object,
+ addParams=dict(id=self.track.__name__)))
+ return actions
+
+
+class WorkItemInfo(NodeView):
+ """ Provides info box.
+ """
+
+ __call__ = innerHtml
+
+ @property
+ def macro(self):
+ return work_macros.macros['workitem_info']
+
+ @Lazy
+ def dialog_name(self):
+ return self.request.get('dialog', 'workitem_info')
+
+ @Lazy
+ def track(self):
+ id = self.request.form.get('id')
+ if id is not None:
+ workItems = self.loopsRoot.getRecordManager()['work']
+ track = workItems.get(id)
+ return WorkItemDetails(self, track)
+
class WorkItemView(BaseTrackView):
""" Show a single work item in the management view.
@@ -174,6 +237,21 @@ class CreateWorkItemForm(ObjectForm, BaseTrackView):
def macro(self):
return self.template.macros['create_workitem']
+ @Lazy
+ def track(self):
+ id = self.request.form.get('id')
+ if id is not None:
+ workItems = self.loopsRoot.getRecordManager()['work']
+ return workItems.get(id)
+
+ @Lazy
+ def title(self):
+ return self.track is not None and self.track.title or u''
+
+ @Lazy
+ def description(self):
+ return self.track is not None and self.track.description or u''
+
@Lazy
def defaultDate(self):
return time.strftime('%Y-%m-%d')
@@ -185,6 +263,13 @@ class CreateWorkItemForm(ObjectForm, BaseTrackView):
class CreateWorkItem(EditObject, BaseTrackView):
+ @Lazy
+ def track(self):
+ id = self.request.form.get('id')
+ if id is not None:
+ workItems = self.loopsRoot.getRecordManager()['work']
+ return workItems.get(id)
+
@Lazy
def personId(self):
p = getPersonForUser(self.context, self.request)
@@ -229,7 +314,10 @@ class CreateWorkItem(EditObject, BaseTrackView):
action, data = self.processForm()
if not action:
return True
- wi = workItems.add(util.getUidForObject(self.object), self.personId)
+ if self.track is not None:
+ wi = self.track
+ else:
+ wi = workItems.add(util.getUidForObject(self.object), self.personId)
wi.doAction(action, self.personId, **data)
url = self.view.virtualTargetUrl + '?version=this'
self.request.response.redirect(url)
@@ -247,6 +335,19 @@ actions.register('createWorkitem', 'portlet', DialogAction,
)
+class WorkItemStateAction(StateAction):
+
+ cssClass = 'icon-action'
+
+ @Lazy
+ def stateful(self):
+ return self.view.track
+
+ @Lazy
+ def description(self):
+ return _(self.stateObject.title)
+
+
# auxiliary functions
def parseTime(s):
diff --git a/organize/work/configure.zcml b/organize/work/configure.zcml
index 0b19ec6..78b95a3 100644
--- a/organize/work/configure.zcml
+++ b/organize/work/configure.zcml
@@ -49,6 +49,12 @@
factory="loops.organize.work.browser.CreateWorkItem"
permission="zope.View" />
+
+
+ tal:define="work nocall:view/workItems"
+ tal:condition="work/allWorkItems">
Work Items
+ ('Day', 'Start', 'End', 'Duration', 'Task', 'User', 'Title', 'Info')">
Task |
@@ -39,6 +39,11 @@
tal:content="row/user/title">John
Title |
+
+
+
+
+ |
@@ -60,20 +65,22 @@
dojoType="dijit.form.Form">
+
Add Work Item
+ dojoType="dijit.form.SimpleTextarea" style="width: 60em"
+ tal:content="view/description">
@@ -115,4 +122,61 @@
+
+
+
+
+
|