improve queries: make configurable via query options

git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@3181 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2009-01-27 12:04:57 +00:00
parent 8ef18c8b59
commit 466f05e5a8
4 changed files with 113 additions and 51 deletions

View file

@ -102,16 +102,15 @@ by calling the form controller's update method
Work items views
----------------
>>> from loops.organize.work.browser import WorkItemView, WorkItemsView
>>> from loops.organize.work.browser import WorkItemView, TaskWorkItems
>>> wi01 = workItems['0000001']
>>> view = WorkItemView(wi01, TestRequest())
>>> view.taskUrl
'http://127.0.0.1/loops/concepts/loops_dev/@@SelectedManagementView.html'
>>> itemsView = WorkItemsView(home, request)
>>> work = TaskWorkItems(task01, request)
>>> from loops.organize.work.browser import WorkItemDetails
>>> view = WorkItemDetails(itemsView, wi01)
>>> view = WorkItemDetails(work, wi01)
>>> view.day, view.start, view.end
(u'08/12/28', u'19:00', u'20:15')
@ -144,6 +143,39 @@ work item, the form will be pre-filled with some of the item's data.
{'name': 'modify', 'title': 'modify'}]
Work Item Queries
=================
>>> from loops.common import adapted
>>> from loops.expert.concept import IQueryConcept
>>> from loops.organize.work.browser import UserWorkItems, PersonWorkItems
>>> tQuery = addAndConfigureObject(concepts, Concept, 'query',
... title=u'Query', conceptType=concepts.getTypeConcept(),
... typeInterface=IQueryConcept)
>>> query = addAndConfigureObject(concepts, Concept, 'userworkitems',
... conceptType=tQuery)
The UserWorkItems view does not give any results because there is no current
user (principal) available in our test setting.
>>> work = UserWorkItems(query, TestRequest())
>>> work.listWorkItems()
So we use the PersonWorkItems view, assigning john to the query.
>>> query.assignParent(johnC)
>>> adapted(query).options = ['wi_from:2009-01-01', 'wi_to:today']
>>> input = dict()
>>> work = PersonWorkItems(query, TestRequest(form=input))
>>> work.listWorkItems()
[<WorkItem ['36', 2, '33', '2009-01-19 08:00', 'planned']:
{'start': 1232352000, 'created': ..., 'title': u'Install Zope',
'creator': '33'}>]
Fin de partie
=============

View file

@ -22,6 +22,7 @@ View class(es) for work items.
$Id$
"""
from datetime import date
import time
from zope import component
from zope.app.security.interfaces import IAuthentication, PrincipalLookupError
@ -165,6 +166,10 @@ class BaseWorkItemsView(object):
def work_macros(self):
return work_macros.macros
@property
def macro(self):
return self.work_macros['workitems_query']
@Lazy
def workItems(self):
rm = self.loopsRoot.getRecordManager()
@ -177,15 +182,21 @@ class BaseWorkItemsView(object):
def baseCriteria(self):
result = {}
form = self.request.form
start = parseDate(form.get('wi_start'))
end = parseDate(form.get('wi_end'))
if end:
end += 3600 * 24 # include full end date
if start or end:
result['timeFromTo'] = (start, end)
state = form.get('wi_state')
if state is not None:
result['state'] = state
tsFrom = parseDate(form.get('wi_from') or self.options.wi_from)
tsTo = parseDate(form.get('wi_to') or self.options.wi_to)
if tsTo:
tsTo += 3600 * 24 # include full end date
if tsFrom or tsTo:
result['timeFromTo'] = (tsFrom, tsTo)
state = form.get('wi_state') or self.options.wi_state
if not state:
result['state'] = ['planned', 'accepted', 'running', 'done', 'done_x',
'finished', 'delegated']
else:
if state == 'all':
del result['state']
else:
result['state'] = state
return result
def query(self, **criteria):
@ -195,17 +206,15 @@ class BaseWorkItemsView(object):
for wi in self.workItems.query(**criteria)]
class WorkItemsView(BaseWorkItemsView, NodeView):
class TaskWorkItems(BaseWorkItemsView, ConceptView):
""" Standard view for showing work items for a node's target.
"""
columns = set(['User', 'Title', 'Day', 'Start', 'End', 'Duration', 'Info'])
@Lazy
def listWorkItems(self):
target = self.virtualTargetObject
criteria = self.baseCriteria
criteria['task'] = util.getUidForObject(target)
criteria['task'] = util.getUidForObject(self.context)
return sorted(self.query(**criteria), key=lambda x: x.track.timeStamp)
@ -215,22 +224,9 @@ class PersonWorkItems(BaseWorkItemsView, ConceptView):
columns = set(['Task', 'Title', 'Day', 'Start', 'End', 'Duration', 'Info'])
@property
def macro(self):
return self.work_macros['userworkitems']
def getCriteria(self):
crit = self.baseCriteria
tft = crit.get('timeFromTo') or (None, None)
if not tft[0]:
tft = (getTimeStamp() - (3 * 24 * 3600), tft[1])
crit['timeFromTo'] = tft
if not crit.get('state'):
crit['state'] = ['planned', 'accepted', 'running', 'done', 'done_x',
'finished', 'delegated']
return crit
return self.baseCriteria
@Lazy
def listWorkItems(self):
criteria = self.getCriteria()
for target in self.context.getParents([self.defaultPredicate]):
@ -239,6 +235,16 @@ class PersonWorkItems(BaseWorkItemsView, ConceptView):
return sorted(self.query(**criteria), key=lambda x: x.track.timeStamp)
class UserWorkItems(PersonWorkItems):
def listWorkItems(self):
criteria = self.getCriteria()
p = getPersonForUser(self.context, self.request)
if p is not None:
criteria['userName'] = util.getUidForObject(p)
return sorted(self.query(**criteria), key=lambda x: x.track.timeStamp)
# forms and form controllers
class CreateWorkItemForm(ObjectForm, BaseTrackView):
@ -344,19 +350,15 @@ class CreateWorkItem(EditObject, BaseTrackView):
for k in ('title', 'description', 'comment'):
setValue(k)
startDate = form.get('start_date', '').strip()
startTime = form.get('start_time', '').strip().replace('T', '')
endTime = form.get('end_time', '').strip().replace('T', '')
startTime = form.get('start_time', '').strip().replace('T', '') or '00:00:00'
endTime = form.get('end_time', '').strip().replace('T', '') or '00:00:00'
#print '***', startDate, startTime, endTime
if startDate and startTime:
#if startDate and startTime:
if startDate:
result['start'] = parseDateTime('T'.join((startDate, startTime)))
if startDate and endTime:
result['end'] = parseDateTime('T'.join((startDate, endTime)))
duration = form.get('duration')
if duration:
result['duration'] = parseTime(duration)
effort = form.get('effort')
if effort:
result['effort'] = parseTime(effort)
result['duration'] = parseTime(form.get('duration'))
result['effort'] = parseTime(form.get('effort'))
return action, result
def update(self):
@ -403,6 +405,9 @@ class WorkItemStateAction(StateAction):
# auxiliary functions
specialDays = ['yesterday', 'today', 'tomorrow']
weekDays = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday']
def parseTime(s):
if not s:
return None
@ -420,6 +425,20 @@ def parseDateTime(s):
def parseDate(s):
if not s:
return None
if isinstance(s, (list, tuple)):
s = s[0]
if s[0] in ('-', '+') or s.isdigit():
delta = int(s) * 3600 * 24
return int(time.mktime(date.today().timetuple())) + delta
elif s in specialDays:
delta = (specialDays.index(s) - 1) * 3600 * 24
return int(time.mktime(date.today().timetuple())) + delta
elif s in weekDays:
wd = weekDays.index(s)
today = date.today()
todayWd = today.weekday
delta = (wd + 8 - todayWd) % 8
return int(time.mktime(today.timetuple())) + delta
return int(time.mktime(time.strptime(s, '%Y-%m-%d')))
def formatTimeDelta(value):

View file

@ -22,11 +22,13 @@
<!-- application views -->
<browser:page
name="workitems.html"
for="loops.interfaces.INode"
class="loops.organize.work.browser.WorkItemsView"
permission="zope.View" />
<zope:adapter
name="taskworkitems.html"
for="loops.interfaces.IConcept
zope.publisher.interfaces.browser.IBrowserRequest"
provides="zope.interface.Interface"
factory="loops.organize.work.browser.TaskWorkItems"
permission="zope.View" />
<zope:adapter
name="personworkitems.html"
@ -36,6 +38,14 @@
factory="loops.organize.work.browser.PersonWorkItems"
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"

View file

@ -6,7 +6,7 @@
<metal:work define-macro="workitems"
tal:define="work nocall:view/workItems"
tal:condition="work/listWorkItems">
tal:condition="work/listWorkItems|nothing">
<br />
<h2 i18n:translate="">Work Items</h2>
<metal:workitems define-macro="workitems_listing"
@ -49,10 +49,11 @@
</metal:workitems>
</metal:work>
<metal:work define-macro="userworkitems"
<metal:work define-macro="workitems_query"
tal:define="work nocall:item">
<br />
<h2 i18n:translate="" tal:content="item/title">Work Items</h2>
<metal:block use-macro="view/concept_macros/concepttitle" />
<metal:workitems use-macro="item/work_macros/workitems_listing" />
</metal:work>
@ -106,11 +107,11 @@
<div id="duration-effort">
<input type="text" name="duration" style="width: 5em"
dojoType="dijit.form.ValidationTextBox"
regexp="[0-9]{1,2}(:[0-5][0-9]){0,1}"
regexp="-{0,1}[0-9]{1,2}(:[0-5][0-9]){0,1}"
tal:attributes="value view/duration" /> /
<input type="text" name="effort" style="width: 5em"
dojoType="dijit.form.ValidationTextBox"
regexp="[0-9]{1,2}(:[0-5][0-9]){0,1}"
regexp="-{0,1}[0-9]{1,2}(:[0-5][0-9]){0,1}"
tal:attributes="value view/effort" /></div>
</div>
<div>