provide work item infos: icon with link, info popup
git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@3149 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
b5b4270f58
commit
6ff94ad004
7 changed files with 198 additions and 26 deletions
|
@ -101,7 +101,7 @@
|
|||
<span tal:replace="related/title">Resource Title</span>
|
||||
</a>
|
||||
</td>
|
||||
<td><span tal:content="related/typeTitle"
|
||||
<td class="center"><span tal:content="related/typeTitle"
|
||||
i18n:translate="">Type</span></td>
|
||||
<td><span tal:replace="related/modified">Type</span></td>
|
||||
<td><span tal:replace="related/creators">Type</span></td>
|
||||
|
@ -162,7 +162,8 @@
|
|||
<div tal:content="related/title">Resource Title</div>
|
||||
</a>
|
||||
</td>
|
||||
<td><span tal:replace="related/longTypeTitle">Type</span></td>
|
||||
<td class="center">
|
||||
<span tal:replace="related/longTypeTitle">Type</span></td>
|
||||
<tal:version tal:condition="view/useVersioning">
|
||||
<td class="center"
|
||||
tal:define="versionId related/versionId">
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -49,6 +49,12 @@
|
|||
factory="loops.organize.work.browser.CreateWorkItem"
|
||||
permission="zope.View" />
|
||||
|
||||
<browser:page
|
||||
name="workitem_info.html"
|
||||
for="loops.interfaces.INode"
|
||||
class="loops.organize.work.browser.WorkItemInfo"
|
||||
permission="zope.View" />
|
||||
|
||||
<!-- setup -->
|
||||
|
||||
<zope:adapter factory="loops.organize.work.setup.SetupManager"
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
<!-- listings -->
|
||||
|
||||
<metal:work define-macro="workitems"
|
||||
tal:define="work nocall:view/workItems"
|
||||
tal:condition="work/allWorkItems">
|
||||
tal:define="work nocall:view/workItems"
|
||||
tal:condition="work/allWorkItems">
|
||||
<br />
|
||||
<h2 i18n:translate="">Work Items</h2>
|
||||
<metal:workitems define-macro="workitems_listing"
|
||||
|
@ -14,7 +14,7 @@
|
|||
<table class="listing">
|
||||
<tr>
|
||||
<tal:colheader repeat="column python:
|
||||
('Day', 'Start', 'End', 'Duration', 'Task', 'User', 'Title')">
|
||||
('Day', 'Start', 'End', 'Duration', 'Task', 'User', 'Title', 'Info')">
|
||||
<th tal:condition="python: column in work.columns"
|
||||
tal:content="column"
|
||||
i18n:translate="">Task</th>
|
||||
|
@ -39,6 +39,11 @@
|
|||
tal:content="row/user/title">John</a></td>
|
||||
<td tal:content="row/track/title"
|
||||
tal:attributes="title row/track/description">Title</td>
|
||||
<td class="nowrap">
|
||||
<tal:actions repeat="action row/actions">
|
||||
<metal:action use-macro="action/macro" />
|
||||
</tal:actions>
|
||||
</td>
|
||||
</tr>
|
||||
</tal:workitem>
|
||||
</table>
|
||||
|
@ -60,20 +65,22 @@
|
|||
dojoType="dijit.form.Form">
|
||||
<input type="hidden" name="form.action" value="create_workitem" />
|
||||
<input type="hidden" name="workitem.action" value="finish" />
|
||||
<input type="hidden" name="id"
|
||||
tal:attributes="value request/form/id|nothing" />
|
||||
<div class="heading" i18n:translate="">Add Work Item</div>
|
||||
<div>
|
||||
<label i18n:translate="" for="title">Title</label>
|
||||
<div>
|
||||
<input name="title" id="title"
|
||||
<input name="title" id="title" style="width: 60em"
|
||||
dojoType="dijit.form.ValidationTextBox" required
|
||||
style="width: 60em" /></div>
|
||||
tal:attributes="value view/title" /></div>
|
||||
</div>
|
||||
<div>
|
||||
<label i18n:translate="" for="description">Description</label>
|
||||
<div>
|
||||
<textarea name="description" cols="80" rows="4" id="description"
|
||||
dojoType="dijit.form.SimpleTextarea"
|
||||
style="width: 60em"></textarea></div>
|
||||
dojoType="dijit.form.SimpleTextarea" style="width: 60em"
|
||||
tal:content="view/description"></textarea></div>
|
||||
</div>
|
||||
<div>
|
||||
<label i18n:translate="" for="start-end">Start - End</label>
|
||||
|
@ -115,4 +122,61 @@
|
|||
</metal:block>
|
||||
|
||||
|
||||
<metal:info define-macro="workitem_info"
|
||||
tal:define="item nocall:view/track">
|
||||
<table class="object_info" width="400">
|
||||
<tr>
|
||||
<td colspan="2"><h2 i18n:translate="">Work Item Information</h2><br /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span i18n:translate="">Title</span>:</td>
|
||||
<td tal:content="item/track/title"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><span i18n:translate="">Description</span>:</td>
|
||||
<td tal:content="item/description"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span i18n:translate="">Party</span>:</td>
|
||||
<td tal:content="item/user/title"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span i18n:translate="">Task</span>:</td>
|
||||
<td tal:content="item/object/title"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span i18n:translate="">Start - End</span>:</td>
|
||||
<td><span tal:content="item/startDay" />
|
||||
<span tal:content="item/start" /> -
|
||||
<span tal:content="item/end" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span i18n:translate="">Duration/Effort</span>:</td>
|
||||
<td><span tal:content="item/duration" /> /
|
||||
<span tal:content="item/effort" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><span i18n:translate="">Comment</span>:</td>
|
||||
<td tal:content="item/track/comment"></td>
|
||||
</tr>
|
||||
<tr tal:define="state item/track/getStateObject">
|
||||
<td><span i18n:translate="">State</span>:</td>
|
||||
<td tal:content="state/title"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span i18n:translate="">Created</span>:</td>
|
||||
<td><span tal:content="item/created" />
|
||||
(<span tal:content="python:
|
||||
item.getUserForUserName(item.track.creator)['title']" />)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"><br />
|
||||
<input type="button" value="Close" onclick="closeDialog()"
|
||||
i18n:attributes="value" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</metal:info>
|
||||
|
||||
|
||||
</html>
|
||||
|
|
|
@ -80,10 +80,10 @@
|
|||
tal:attributes="src icon/src" />
|
||||
<div tal:content="row/title" /></a>
|
||||
</td>
|
||||
<td i18n:translate=""
|
||||
<td i18n:translate="" class="center"
|
||||
tal:content="row/longTypeTitle|row/typeTitle">Type</td>
|
||||
<tal:version condition="view/useVersioning">
|
||||
<td style="text-align: center"
|
||||
<td class="center"
|
||||
tal:define="versionId row/versionId|string:">
|
||||
<a href="#"
|
||||
tal:content="versionId"
|
||||
|
@ -91,12 +91,12 @@
|
|||
tal:attributes="href string:${view/url}/.target${row/uniqueId}?loops.viewName=listversions">1.1</a>
|
||||
</td>
|
||||
</tal:version>
|
||||
<td style="text-align: right; white-space: nowrap">
|
||||
<td class="nowrap number">
|
||||
<span tal:replace="row/context/sizeForDisplay|string:">Size</span>
|
||||
</td>
|
||||
<td><span tal:replace="row/modified">modified</span></td>
|
||||
<td><span tal:replace="row/creators">John</span></td>
|
||||
<td style="white-space: nowrap"
|
||||
<td class="nowrap center"
|
||||
tal:define="target nocall:row;
|
||||
style nothing"
|
||||
tal:condition="view/showObjectActions">
|
||||
|
|
Loading…
Add table
Reference in a new issue