add activity field to report, is also used as query field with vocabulary

This commit is contained in:
Helmut Merz 2016-03-18 15:57:26 +01:00
parent 354dfeda7f
commit 17f15429c8
6 changed files with 92 additions and 30 deletions

View file

@ -262,6 +262,12 @@ table.records th, table.records td {
border: 1px solid lightgrey;
}
table.report {
position: relative;
z-index: 99;
background: white;
}
table.report th {
border-bottom: 1px solid #bbbbbb;
font-weight: bold;

View file

@ -141,7 +141,14 @@
<metal:field define-macro="selection">
<metal:use use-macro="item/report_macros/textline" />
<select tal:attributes="name name">
<option />
<option tal:repeat="opt python:field.getVocabularyItems(
context=item.adapted, request=request)"
tal:attributes="value opt/token;
selected python:value == opt['token']"
tal:content="opt/title" />
</select>
</metal:field>

View file

@ -119,7 +119,7 @@ class IntegerField(Field):
class DateField(Field):
fieldType='date',
fieldType='date'
format = ('date', 'short')
renderer = cssClass = 'center'
dbtype = 'date'
@ -192,6 +192,8 @@ class WorkItemStateField(Field):
class VocabularyField(Field):
vocabulary = None
sourceList = None
fieldType = 'selection'
def getDisplayValue(self, row):
value = self.getRawValue(row)
@ -202,8 +204,10 @@ class VocabularyField(Field):
if str(item['token']) == str(value):
return item['title']
def getVocabularyItems(self, row):
def getVocabularyItems(self, row=None, context=None, request=None):
if context is None:
context = row.context
if request is None:
request = row.parent.context.view.request
voc = self.vocabulary
if isinstance(voc, basestring):
@ -213,7 +217,10 @@ class VocabularyField(Field):
voc = voc.splitlines()
return [dict(token=t, title=t) for t in voc if t.strip()]
elif IContextSourceBinder.providedBy(voc):
if row is not None:
source = voc(row.parent.context)
else:
source = voc(context)
terms = component.queryMultiAdapter((source, request), ITerms)
if terms is not None:
termsList = [terms.getTerm(value) for value in source]

View file

@ -232,7 +232,7 @@ The user interface is a ReportConceptView subclass that is directly associated w
... print
08/12/28 19:00 20:15
{'url': '.../home/.36', 'title': u'loops Development'}
{'url': '.../home/.33', 'title': u'john'} 01:15 00:15
{'url': '.../home/.33', 'title': u'john'} 00:15
{'actions': [...]}
>>> results.totals.data
@ -247,8 +247,8 @@ Export of work data
>>> output = reportView()
>>> print output
Day;Start;End;Task;Party;Title;Duration;Effort;State
08/12/28;19:00;20:15;loops Development;john;;1.2500;0.2500;finished
Day;Start;End;Task;Party;Title;LA;Effort;State
08/12/28;19:00;20:15;loops Development;john;;;0.2500;finished
Meeting Minutes

View file

@ -39,11 +39,13 @@ from loops.common import adapted, baseObject
from loops.expert.browser.export import ResultsConceptCSVExport
from loops.expert.browser.report import ReportConceptView
from loops.expert.field import Field, TargetField, DateField, StateField, \
StringField, TextField, HtmlTextField, UrlField
StringField, TextField, HtmlTextField, \
UrlField, VocabularyField
from loops.expert.field import SubReport, SubReportField
from loops.expert.field import TrackDateField, TrackTimeField, TrackDateTimeField
from loops.expert.field import WorkItemStateField
from loops.expert.report import ReportInstance
from loops.table import DataTableSourceBinder, DataTableSourceListByValue
from loops import util
@ -114,6 +116,28 @@ class PartyStateField(StateField):
return None
class ActivityField(VocabularyField):
tableName = 'organize.work.activities'
vocabulary = DataTableSourceBinder(tableName,
sourceList=DataTableSourceListByValue)
def getDisplayValue(self, row):
if row.context is None:
return u'-'
value = row.context.data.get('activity', '')#[:3]
if not value:
return u''
dt = row.parent.context.view.conceptManager.get(self.tableName)
if dt is None:
return u''
for row in adapted(dt).data.values():
if row[0] == value:
value = row[3]
break
return value
def daysAgoByOption(context):
days = 7
opt = context.view.typeOptions('workitem_dayfrom_default')
@ -193,7 +217,10 @@ partyState = PartyStateField('partyState', u'Party State',
cssClass='center',
statesDefinition='contact_states',
executionSteps=['query', 'output'])
# activity
activity = ActivityField('activity', u'LA',
description=u'The activity assigned to the work item.',
fieldType='selection',
executionSteps=['query', 'sort', 'output'])
# process
@ -233,7 +260,7 @@ class WorkRow(BaseRow):
attributeHandlers = dict(day=getDay,
dayStart=getStart, dayEnd=getEnd,
dayFrom=getDay, dayTo=getDay,
duration=getDuration, effort=getEffort,)
duration=getDuration, effort=getEffort)
class WorkReportInstance(ReportInstance):
@ -246,9 +273,11 @@ class WorkReportInstance(ReportInstance):
fields = Jeep((dayFrom, dayTo, tasks,
day, timeStart, timeEnd, task, party, workTitle,
#description,
duration, effort, state))
activity,
#duration,
effort, state))
userSettings = (dayFrom, dayTo, party)
userSettings = (dayFrom, dayTo, party, activity)
defaultOutputFields = fields
defaultSortCriteria = (day, timeStart,)
defaultStates = ('done', 'done_x', 'finished')

View file

@ -138,22 +138,6 @@ def getRowValue(k, v):
def getRowValueWithKey(k, v):
return u' '.join((unicode(k), v[0]))
class DataTableSourceBinder(object):
implements(IContextSourceBinder)
def __init__(self, tableName, valueProvider=getRowValue):
self.tableName = tableName
self.valueProvider = valueProvider
def __call__(self, instance):
if IInstance.providedBy(instance):
context = instance.view.nodeView.context
else:
context = baseObject(instance.context)
dt = context.getLoopsRoot().getConceptManager()[self.tableName]
return DataTableSourceList(adapted(dt), self.valueProvider)
class DataTableSourceList(object):
@ -170,3 +154,32 @@ class DataTableSourceList(object):
def __len__(self):
return len(self.context.data)
class DataTableSourceListByValue(DataTableSourceList):
def __iter__(self):
items = [(k, v[0], v[1])
for k, v in self.context.data.items()]
items.sort()
return iter([(i[1], i[2]) for i in items])
class DataTableSourceBinder(object):
implements(IContextSourceBinder)
def __init__(self, tableName, valueProvider=getRowValue,
sourceList=None):
self.tableName = tableName
self.valueProvider = valueProvider
self.sourceList = sourceList or DataTableSourceList
def __call__(self, instance):
if IInstance.providedBy(instance):
context = instance.view.nodeView.context
else:
context = baseObject(instance.context)
dt = context.getLoopsRoot().getConceptManager()[self.tableName]
return self.sourceList(adapted(dt), self.valueProvider)