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:
parent
8ef18c8b59
commit
466f05e5a8
4 changed files with 113 additions and 51 deletions
|
@ -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
|
||||
=============
|
||||
|
||||
|
|
|
@ -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,14 +182,20 @@ 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:
|
||||
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
|
||||
|
||||
|
@ -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):
|
||||
|
|
|
@ -22,10 +22,12 @@
|
|||
|
||||
<!-- application views -->
|
||||
|
||||
<browser:page
|
||||
name="workitems.html"
|
||||
for="loops.interfaces.INode"
|
||||
class="loops.organize.work.browser.WorkItemsView"
|
||||
<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
|
||||
|
@ -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"
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Add table
Reference in a new issue