improve display of rows in work items listing
git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@3106 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
be71f62a6e
commit
ed35bcf5af
7 changed files with 147 additions and 21 deletions
17
CHANGES.txt
17
CHANGES.txt
|
@ -3,6 +3,23 @@ Change Log
|
|||
|
||||
$Id$
|
||||
|
||||
1.0
|
||||
---
|
||||
|
||||
New features
|
||||
|
||||
- work items (work in progress): activate by adding option
|
||||
``action.portlet:createWorkitem`` to type; work items listing is shown
|
||||
automatically in standard concept view.
|
||||
- my work items: a query view (``userworkitems.html``); assign the query
|
||||
to the person as a standard child
|
||||
|
||||
Bug fixes
|
||||
|
||||
- external collection: now works correctly (without creating empty files
|
||||
in the var directory); resource type of generated object controlled by
|
||||
mime type; automatically executes transformation steps on media assets
|
||||
|
||||
0.9
|
||||
---
|
||||
|
||||
|
|
|
@ -235,6 +235,10 @@ class BaseView(GenericView, I18NView):
|
|||
def typePredicate(self):
|
||||
return self.conceptManager.getTypePredicate()
|
||||
|
||||
@Lazy
|
||||
def defaultPredicate(self):
|
||||
return self.conceptManager.getDefaultPredicate()
|
||||
|
||||
@Lazy
|
||||
def url(self):
|
||||
return absoluteURL(self.context, self.request)
|
||||
|
|
|
@ -80,6 +80,11 @@ table.listing td.checkbox {
|
|||
padding-right: 2px;
|
||||
}
|
||||
|
||||
table.listing td.headline {
|
||||
font-weight: bold;
|
||||
border: 1px solid lightgrey;
|
||||
}
|
||||
|
||||
table.listing-details td {
|
||||
white-space: normal;
|
||||
border: 1px solid lightgrey;
|
||||
|
|
|
@ -196,6 +196,17 @@ class TrackDetails(BaseView):
|
|||
self.view = view
|
||||
self.track = track
|
||||
|
||||
@Lazy
|
||||
def month(self):
|
||||
ts = datetime.fromtimestamp(self.track.timeStamp)
|
||||
return formatAsMonth(date(ts.year, ts.month, 1))
|
||||
|
||||
@property
|
||||
def monthChanged(self):
|
||||
result = self.view.lastMonth != self.month
|
||||
self.view.lastMonth = self.month
|
||||
return result
|
||||
|
||||
@Lazy
|
||||
def authentication(self):
|
||||
return component.getUtility(IAuthentication)
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#
|
||||
|
||||
"""
|
||||
View class(es) for change tracks.
|
||||
View class(es) for work items.
|
||||
|
||||
$Id$
|
||||
"""
|
||||
|
@ -33,6 +33,7 @@ from zope.traversing.api import getName
|
|||
from cybertools.browser.action import actions
|
||||
from cybertools.organize.interfaces import IWorkItems
|
||||
from loops.browser.action import DialogAction
|
||||
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
|
||||
|
@ -45,18 +46,35 @@ from loops.util import _
|
|||
work_macros = ViewPageTemplateFile('work_macros.pt')
|
||||
|
||||
|
||||
class WorkItemsView(NodeView):
|
||||
# work item collections
|
||||
|
||||
class BaseWorkItemsView(object):
|
||||
|
||||
columns = set(['Task', 'User', 'Title', 'Start', 'End', 'Duration'])
|
||||
|
||||
lastMonth = None
|
||||
|
||||
def __init__(self, context, request):
|
||||
self.context = context
|
||||
self.request = request
|
||||
|
||||
@Lazy
|
||||
def work_macros(self):
|
||||
return work_macros.macros
|
||||
|
||||
@Lazy
|
||||
def workItems(self):
|
||||
ts = self.loopsRoot.getRecordManager().get('work')
|
||||
if ts is not None:
|
||||
return IWorkItems(ts)
|
||||
|
||||
|
||||
class WorkItemsView(BaseWorkItemsView, NodeView):
|
||||
""" Standard view for showing work items for a node's target.
|
||||
"""
|
||||
|
||||
columns = set(['User', 'Title', 'Start', 'End', 'Duration'])
|
||||
|
||||
@Lazy
|
||||
def allWorkItems(self):
|
||||
result = []
|
||||
|
@ -69,7 +87,33 @@ class WorkItemsView(NodeView):
|
|||
return result
|
||||
|
||||
|
||||
class UserWorkItems(BaseWorkItemsView, ConceptView):
|
||||
""" A query view showing work items for a person, the query's parent.
|
||||
"""
|
||||
|
||||
columns = set(['Task', 'Title', 'Start', 'End', 'Duration'])
|
||||
|
||||
@property
|
||||
def macro(self):
|
||||
return self.work_macros['userworkitems']
|
||||
|
||||
@Lazy
|
||||
def allWorkItems(self):
|
||||
workItems = self.workItems
|
||||
if self.workItems is None:
|
||||
return []
|
||||
result = []
|
||||
for target in self.context.getParents([self.defaultPredicate]):
|
||||
for wi in workItems.query(userName=util.getUidForObject(target)):
|
||||
result.append(WorkItemDetails(self, wi))
|
||||
return result
|
||||
|
||||
|
||||
# single work items
|
||||
|
||||
class WorkItemDetails(TrackDetails):
|
||||
""" Render a single work item.
|
||||
"""
|
||||
|
||||
@Lazy
|
||||
def description(self):
|
||||
|
@ -81,13 +125,30 @@ class WorkItemDetails(TrackDetails):
|
|||
|
||||
@Lazy
|
||||
def end(self):
|
||||
return self.formatTimeStamp(self.track.end)[-5:]
|
||||
ts = self.formatTimeStamp(self.track.end)
|
||||
return ts and ts[-5:] or ''
|
||||
|
||||
@Lazy
|
||||
def duration(self):
|
||||
return self.formatTimeDelta(self.track.duration)
|
||||
|
||||
@Lazy
|
||||
def effort(self):
|
||||
return self.formatTimeDelta(self.track.effort)
|
||||
|
||||
def formatTimeDelta(self, value):
|
||||
if not value:
|
||||
return ''
|
||||
h, m = divmod(int(value) / 60, 60)
|
||||
return '%02i:%02i' % (h, m)
|
||||
|
||||
|
||||
class WorkItemView(BaseTrackView):
|
||||
""" Show a single work item in the management view.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
# forms and form controllers
|
||||
|
||||
class CreateWorkItemForm(ObjectForm, BaseTrackView):
|
||||
|
||||
|
|
|
@ -28,6 +28,14 @@
|
|||
class="loops.organize.work.browser.WorkItemsView"
|
||||
permission="zope.View" />
|
||||
|
||||
<zope:adapter
|
||||
name="userworkitems.html"
|
||||
for="loops.interfaces.IConcept
|
||||
zope.publisher.interfaces.browser.IBrowserRequest"
|
||||
provides="zope.interface.Interface"
|
||||
factory="loops.organize.work.browser.UserWorkItems"
|
||||
permission="zope.View" />
|
||||
|
||||
<browser:page
|
||||
name="create_workitem.html"
|
||||
for="loops.interfaces.INode"
|
||||
|
|
|
@ -2,37 +2,57 @@
|
|||
<!-- $Id$ -->
|
||||
|
||||
|
||||
<!-- listings -->
|
||||
|
||||
<metal:work define-macro="workitems"
|
||||
tal:define="workItems nocall:view/workItems"
|
||||
tal:condition="workItems/allWorkItems">
|
||||
tal:define="work nocall:view/workItems"
|
||||
tal:condition="work/allWorkItems">
|
||||
<br />
|
||||
<h2 i18n:translate="">Work Items</h2>
|
||||
<metal:workitems define-macro="workitems_listing"
|
||||
tal:define="workItems nocall:workItems|nocall:view/workItems;">
|
||||
tal:define="work nocall:work|nocall:view/workItems;">
|
||||
<table class="listing">
|
||||
<tr>
|
||||
<th i18n:translate="">Title</th>
|
||||
<th i18n:translate="">User</th>
|
||||
<th i18n:translate="">Start</th>
|
||||
<th i18n:translate="">End</th>
|
||||
<tal:colheader repeat="column python:
|
||||
('Start', 'End', 'Duration', 'Task', 'User', 'Title')">
|
||||
<th tal:condition="python: column in work.columns"
|
||||
tal:content="column"
|
||||
i18n:translate="">Task</th>
|
||||
</tal:colheader>
|
||||
</tr>
|
||||
<tal:workitem tal:repeat="workItem workItems/allWorkItems">
|
||||
<tal:workitem tal:repeat="row work/allWorkItems">
|
||||
<tr tal:condition="row/monthChanged">
|
||||
<td class="headline"
|
||||
tal:attributes="colspan python: len(work.columns)"
|
||||
tal:content="row/month">2009-01</td></tr>
|
||||
<tr tal:attributes="class python:
|
||||
repeat['workItem'].odd() and 'even' or 'odd'">
|
||||
<td>
|
||||
<span tal:content="workItem/track/title">Title</span></td>
|
||||
<td>
|
||||
<span tal:replace="workItem/user/title">John</span></td>
|
||||
<td class="nowrap">
|
||||
<span tal:replace="workItem/start">2007-03-30</span></td>
|
||||
<td class="nowrap">
|
||||
<span tal:replace="workItem/end">2007-03-30</span></td>
|
||||
repeat['row'].odd() and 'even' or 'odd'">
|
||||
<td class="nowrap center" tal:content="row/start">2007-03-30</td>
|
||||
<td class="nowrap center" tal:content="row/end">2007-03-30</td>
|
||||
<td class="nowrap center" tal:content="row/duration">2:30</td>
|
||||
<td tal:condition="python: 'Task' in work.columns">
|
||||
<a tal:attributes="href row/objectData/url"
|
||||
tal:content="row/objectData/title">Task</a></td>
|
||||
<td tal:condition="python: 'User' in work.columns">
|
||||
<a tal:attributes="href row/user/url"
|
||||
tal:content="row/user/title">John</a></td>
|
||||
<td tal:content="row/track/title"
|
||||
tal:attributes="title row/track/description">Title</td>
|
||||
</tr>
|
||||
</tal:workitem>
|
||||
</table>
|
||||
</metal:workitems>
|
||||
</metal:work>
|
||||
|
||||
<metal:work define-macro="userworkitems"
|
||||
tal:define="work nocall:item">
|
||||
<br />
|
||||
<h2 i18n:translate="" tal:content="item/title">Work Items</h2>
|
||||
<metal:workitems use-macro="item/work_macros/workitems_listing" />
|
||||
</metal:work>
|
||||
|
||||
|
||||
<!-- forms -->
|
||||
|
||||
<metal:block define-macro="create_workitem">
|
||||
<form method="post" id="addWorkitem_form" class="dialog"
|
||||
|
|
Loading…
Add table
Reference in a new issue