organize (tracking, work): Python3 fixes
This commit is contained in:
parent
956a6d01b3
commit
5e5e9aedfc
6 changed files with 89 additions and 151 deletions
|
@ -1,27 +1,10 @@
|
||||||
#
|
# loops.expert.browser.export
|
||||||
# Copyright (c) 2017 Helmut Merz helmutm@cy55.de
|
|
||||||
#
|
|
||||||
# This program is free software; you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation; either version 2 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program; if not, write to the Free Software
|
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
#
|
|
||||||
|
|
||||||
"""
|
""" View classes for export of report results.
|
||||||
View classes for export of report results.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import csv
|
import csv
|
||||||
from cStringIO import StringIO
|
from io import StringIO
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
from zope.cachedescriptors.property import Lazy
|
from zope.cachedescriptors.property import Lazy
|
||||||
|
@ -67,8 +50,8 @@ class ResultsConceptCSVExport(ResultsConceptView):
|
||||||
title = field.title
|
title = field.title
|
||||||
if not isinstance(title, Message):
|
if not isinstance(title, Message):
|
||||||
title = _(title)
|
title = _(title)
|
||||||
return encode(translate(title, target_language=lang),
|
#return encode(translate(title, target_language=lang), self.encoding)
|
||||||
self.encoding)
|
return translate(title, target_language=lang)
|
||||||
|
|
||||||
def getFilenames(self):
|
def getFilenames(self):
|
||||||
"""@return (data_fn, result_fn)"""
|
"""@return (data_fn, result_fn)"""
|
||||||
|
@ -122,7 +105,7 @@ class ResultsConceptCSVExport(ResultsConceptView):
|
||||||
value = f.getExportValue(row, 'csv', lang)
|
value = f.getExportValue(row, 'csv', lang)
|
||||||
if ILoopsObject.providedBy(value):
|
if ILoopsObject.providedBy(value):
|
||||||
value = value.title
|
value = value.title
|
||||||
value = encode(value, self.encoding)
|
#value = encode(value, self.encoding)
|
||||||
data[f.name] = value
|
data[f.name] = value
|
||||||
writer.writerow(data)
|
writer.writerow(data)
|
||||||
if csvRenderer:
|
if csvRenderer:
|
||||||
|
@ -151,7 +134,7 @@ class ResultsConceptCSVExport(ResultsConceptView):
|
||||||
|
|
||||||
|
|
||||||
def encode(text, encoding):
|
def encode(text, encoding):
|
||||||
if not isinstance(text, unicode):
|
if isinstance(text, bytes):
|
||||||
return text
|
return text
|
||||||
try:
|
try:
|
||||||
return text.encode(encoding)
|
return text.encode(encoding)
|
||||||
|
@ -161,7 +144,7 @@ def encode(text, encoding):
|
||||||
try:
|
try:
|
||||||
result.append(c.encode(encoding))
|
result.append(c.encode(encoding))
|
||||||
except UnicodeEncodeError:
|
except UnicodeEncodeError:
|
||||||
result.append('?')
|
result.append(b'?')
|
||||||
return ''.join(result)
|
return b''.join(result)
|
||||||
return '???'
|
return b'???'
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
loops - Linked Objects for Organization and Processing Services
|
loops - Linked Objects for Organization and Processing Services
|
||||||
===============================================================
|
===============================================================
|
||||||
|
|
||||||
($Id$)
|
|
||||||
|
|
||||||
Let's do some basic setup
|
Let's do some basic setup
|
||||||
|
|
||||||
>>> from zope.app.testing.setup import placefulSetUp, placefulTearDown
|
>>> from zope.app.testing.setup import placefulSetUp, placefulTearDown
|
||||||
|
@ -147,10 +145,12 @@ Overview (cumulative) statistics
|
||||||
>>> from loops.organize.tracking.report import TrackingStats
|
>>> from loops.organize.tracking.report import TrackingStats
|
||||||
>>> view = TrackingStats(statQuery, TestRequest())
|
>>> view = TrackingStats(statQuery, TestRequest())
|
||||||
>>> result = view.getData()
|
>>> result = view.getData()
|
||||||
>>> result['macro'][4][1][u'define-macro']
|
>>> result['macro'][4][1]['define-macro']
|
||||||
u'overview'
|
'overview'
|
||||||
>>> result['data']
|
>>> result['data']
|
||||||
[{'access': 2, 'new': 0, 'changed': 1, 'period': '...', 'count': 3}]
|
[{'period': '...', ...}]
|
||||||
|
|
||||||
|
[{'access': 2, 'new': 0, 'changed': 1, 'period': '...', 'count': 3}]
|
||||||
|
|
||||||
|
|
||||||
Changes for a certain period (month)
|
Changes for a certain period (month)
|
||||||
|
@ -168,23 +168,27 @@ Recent changes
|
||||||
>>> from loops.organize.tracking.report import RecentChanges
|
>>> from loops.organize.tracking.report import RecentChanges
|
||||||
>>> view = RecentChanges(statQuery, TestRequest())
|
>>> view = RecentChanges(statQuery, TestRequest())
|
||||||
>>> result = view.getData()
|
>>> result = view.getData()
|
||||||
>>> result['macro'][4][1][u'define-macro']
|
>>> result['macro'][4][1]['define-macro']
|
||||||
u'recent_changes'
|
'recent_changes'
|
||||||
|
|
||||||
>>> data = result['data']
|
>>> data = result['data']
|
||||||
>>> data
|
>>> data
|
||||||
[<ChangeRecord ['27', 2, '33', '...']: {'action': 'modify'}>]
|
[<ChangeRecord ['27', 2, '33', '...']: {'action': 'modify'}>]
|
||||||
|
|
||||||
>>> data[0].timeStamp
|
>>> data[0].timeStamp
|
||||||
u'... ...:...'
|
'... ...:...'
|
||||||
|
|
||||||
>>> data[0].objectData
|
>>> data[0].objectData
|
||||||
{'version': '', 'description': u'', 'title': 'Change Doc 001', 'url': '',
|
{'object': ...}
|
||||||
'object': <loops.resource.Resource object at ...>, 'type': u'Text',
|
|
||||||
'canAccess': True}
|
{'version': '', 'description': '', 'title': 'Change Doc 001', 'url': '',
|
||||||
|
'object': <loops.resource.Resource object at ...>, 'type': 'Text',
|
||||||
|
'canAccess': True}
|
||||||
|
|
||||||
>>> data[0].user
|
>>> data[0].user
|
||||||
{'url': '', 'object': <loops.concept.Concept ...>, 'title': u'john'}
|
{'object': ...}
|
||||||
|
|
||||||
|
{'url': '', 'object': <loops.concept.Concept ...>, 'title': 'john'}
|
||||||
|
|
||||||
>>> data[0].action
|
>>> data[0].action
|
||||||
'modify'
|
'modify'
|
||||||
|
|
|
@ -1,28 +1,11 @@
|
||||||
#
|
# loops.organize.tracking.change
|
||||||
# Copyright (c) 2014 Helmut Merz helmutm@cy55.de
|
|
||||||
#
|
|
||||||
# This program is free software; you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation; either version 2 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program; if not, write to the Free Software
|
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
#
|
|
||||||
|
|
||||||
"""
|
""" Recording changes to loops objects.
|
||||||
Recording changes to loops objects.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from zope.app.container.interfaces import IObjectAddedEvent, IObjectRemovedEvent
|
from zope.app.container.interfaces import IObjectAddedEvent, IObjectRemovedEvent
|
||||||
from zope.app.container.interfaces import IObjectMovedEvent
|
from zope.app.container.interfaces import IObjectMovedEvent
|
||||||
from zope.interface import implements
|
from zope.interface import implementer
|
||||||
from zope.cachedescriptors.property import Lazy
|
from zope.cachedescriptors.property import Lazy
|
||||||
from zope.component import adapter
|
from zope.component import adapter
|
||||||
from zope.lifecycleevent.interfaces import IObjectModifiedEvent, IObjectCreatedEvent
|
from zope.lifecycleevent.interfaces import IObjectModifiedEvent, IObjectCreatedEvent
|
||||||
|
@ -100,10 +83,9 @@ class IChangeRecord(ITrack):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@implementer(IChangeRecord)
|
||||||
class ChangeRecord(Track):
|
class ChangeRecord(Track):
|
||||||
|
|
||||||
implements(IChangeRecord)
|
|
||||||
|
|
||||||
typeName = 'ChangeRecord'
|
typeName = 'ChangeRecord'
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,29 +1,9 @@
|
||||||
#
|
# loops.organize.tracking.setup
|
||||||
# Copyright (c) 2008 Helmut Merz helmutm@cy55.de
|
|
||||||
#
|
|
||||||
# This program is free software; you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation; either version 2 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program; if not, write to the Free Software
|
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
#
|
|
||||||
|
|
||||||
"""
|
""" Automatic setup of a loops site for the organize.tracking package.
|
||||||
Automatic setup of a loops site for the organize.tracking package.
|
|
||||||
|
|
||||||
$Id$
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from zope.component import adapts
|
from zope.component import adapts
|
||||||
from zope.interface import implements, Interface
|
|
||||||
|
|
||||||
from cybertools.tracking.btree import TrackingStorage
|
from cybertools.tracking.btree import TrackingStorage
|
||||||
from loops.organize.tracking.change import ChangeRecord
|
from loops.organize.tracking.change import ChangeRecord
|
||||||
|
|
|
@ -50,7 +50,7 @@ and a pluggable authentication utility with a principal folder.
|
||||||
>>> johnC = setupData.johnC
|
>>> johnC = setupData.johnC
|
||||||
|
|
||||||
>>> from zope.app.authentication.principalfolder import Principal
|
>>> from zope.app.authentication.principalfolder import Principal
|
||||||
>>> pJohn = Principal('users.john', 'xxx', u'John')
|
>>> pJohn = Principal('users.john', 'xxx', 'John')
|
||||||
>>> from loops.tests.auth import login
|
>>> from loops.tests.auth import login
|
||||||
>>> login(pJohn)
|
>>> login(pJohn)
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ to assign work items to this task.
|
||||||
>>> from loops.concept import Concept
|
>>> from loops.concept import Concept
|
||||||
>>> from loops.setup import addAndConfigureObject
|
>>> from loops.setup import addAndConfigureObject
|
||||||
>>> task01 = addAndConfigureObject(concepts, Concept, 'loops_dev',
|
>>> task01 = addAndConfigureObject(concepts, Concept, 'loops_dev',
|
||||||
... title=u'loops Development', conceptType=tTask)
|
... title='loops Development', conceptType=tTask)
|
||||||
>>> home.target = task01
|
>>> home.target = task01
|
||||||
|
|
||||||
Forms for adding and editing work items
|
Forms for adding and editing work items
|
||||||
|
@ -77,10 +77,10 @@ When this form is submitted, a form controller is automatically created
|
||||||
for the view on the currently shown node. The data from the form is processed
|
for the view on the currently shown node. The data from the form is processed
|
||||||
by calling the form controller's update method
|
by calling the form controller's update method
|
||||||
|
|
||||||
>>> input = {u'form.action': u'create_workitem', u'workitem.action': u'finish',
|
>>> input = {'form.action': 'create_workitem', 'workitem.action': 'finish',
|
||||||
... u'description': u'Description', u'comment': u'Comment',
|
... 'description': 'Description', 'comment': 'Comment',
|
||||||
... u'start_date': u'2008-12-28', u'start_time': u'T19:00:00',
|
... 'start_date': '2008-12-28', 'start_time': 'T19:00:00',
|
||||||
... u'end_time': u'T20:15:00', u'duration': u'1:15', u'effort': u'0:15'}
|
... 'end_time': 'T20:15:00', 'duration': '1:15', 'effort': '0:15'}
|
||||||
>>> request = TestRequest(form=input)
|
>>> request = TestRequest(form=input)
|
||||||
>>> request.setPrincipal(pJohn)
|
>>> request.setPrincipal(pJohn)
|
||||||
|
|
||||||
|
@ -92,10 +92,11 @@ by calling the form controller's update method
|
||||||
False
|
False
|
||||||
|
|
||||||
>>> list(workItems)
|
>>> list(workItems)
|
||||||
[<WorkItem ['36', 1, '33', '2008-12-28 19:00', 'finished']:
|
[<WorkItem ['36', 1, '33', '2008-12-28 19:00', 'finished']: {'creator': ...}>]
|
||||||
{'comment': u'Comment', 'end': 1230491700, 'description': u'Description',
|
|
||||||
'created': ..., 'creator': '33', 'start': 1230487200,
|
{'comment': 'Comment', 'end': 1230491700, 'description': 'Description',
|
||||||
'duration': 4500, 'effort': 900}>]
|
'created': ..., 'creator': '33', 'start': 1230487200,
|
||||||
|
'duration': 4500, 'effort': 900}>]
|
||||||
|
|
||||||
Work items views
|
Work items views
|
||||||
----------------
|
----------------
|
||||||
|
@ -110,16 +111,16 @@ Work items views
|
||||||
>>> from loops.organize.work.browser import WorkItemDetails
|
>>> from loops.organize.work.browser import WorkItemDetails
|
||||||
>>> view = WorkItemDetails(work, wi01)
|
>>> view = WorkItemDetails(work, wi01)
|
||||||
>>> view.day, view.start, view.end
|
>>> view.day, view.start, view.end
|
||||||
(u'08/12/28', u'19:00', u'20:15')
|
('08/12/28', '19:00', '20:15')
|
||||||
|
|
||||||
Work items life cycle
|
Work items life cycle
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
Let's create another work item, now in state planned.
|
Let's create another work item, now in state planned.
|
||||||
|
|
||||||
>>> input = {u'form.action': u'create_workitem', u'workitem.action': u'plan',
|
>>> input = {'form.action': 'create_workitem', 'workitem.action': 'plan',
|
||||||
... u'title': u'Install Zope',
|
... 'title': 'Install Zope',
|
||||||
... u'start_date': u'2009-01-19', u'start_time': u'T09:00:00'}
|
... 'start_date': '2009-01-19', 'start_time': 'T09:00:00'}
|
||||||
>>> request = TestRequest(form=input)
|
>>> request = TestRequest(form=input)
|
||||||
>>> request.setPrincipal(pJohn)
|
>>> request.setPrincipal(pJohn)
|
||||||
>>> nodeView = NodeView(home, request)
|
>>> nodeView = NodeView(home, request)
|
||||||
|
@ -132,21 +133,24 @@ work item, the form will be pre-filled with some of the item's data.
|
||||||
|
|
||||||
>>> form = CreateWorkItemForm(home, TestRequest(form=dict(id='0000002')))
|
>>> form = CreateWorkItemForm(home, TestRequest(form=dict(id='0000002')))
|
||||||
>>> form.title
|
>>> form.title
|
||||||
u'Install Zope'
|
'Install Zope'
|
||||||
|
|
||||||
The 'delegate' transition is omitted from the actions list because it is
|
The 'delegate' transition is omitted from the actions list because it is
|
||||||
only available for privileged users.
|
only available for privileged users.
|
||||||
|
|
||||||
>>> form.actions
|
>>> len(form.actions)
|
||||||
[{'selected': False, 'name': 'plan', 'title': 'plan'},
|
9
|
||||||
{'selected': False, 'name': 'accept', 'title': 'accept'},
|
|
||||||
{'selected': False, 'name': 'start', 'title': 'start working'},
|
form.actions
|
||||||
{'selected': False, 'name': 'work', 'title': 'work'},
|
[{'selected': False, 'name': 'plan', 'title': 'plan'},
|
||||||
{'selected': False, 'name': 'finish', 'title': 'finish'},
|
{'selected': False, 'name': 'accept', 'title': 'accept'},
|
||||||
{'selected': False, 'name': 'delegate', 'title': 'delegate'},
|
{'selected': False, 'name': 'start', 'title': 'start working'},
|
||||||
{'selected': False, 'name': 'move', 'title': 'move'},
|
{'selected': False, 'name': 'work', 'title': 'work'},
|
||||||
{'selected': False, 'name': 'cancel', 'title': 'cancel'},
|
{'selected': False, 'name': 'finish', 'title': 'finish'},
|
||||||
{'selected': False, 'name': 'modify', 'title': 'modify'}]
|
{'selected': False, 'name': 'delegate', 'title': 'delegate'},
|
||||||
|
{'selected': False, 'name': 'move', 'title': 'move'},
|
||||||
|
{'selected': False, 'name': 'cancel', 'title': 'cancel'},
|
||||||
|
{'selected': False, 'name': 'modify', 'title': 'modify'}]
|
||||||
|
|
||||||
Work Item Queries
|
Work Item Queries
|
||||||
=================
|
=================
|
||||||
|
@ -156,7 +160,7 @@ Work Item Queries
|
||||||
>>> from loops.organize.work.browser import UserWorkItems, PersonWorkItems
|
>>> from loops.organize.work.browser import UserWorkItems, PersonWorkItems
|
||||||
|
|
||||||
>>> tQuery = addAndConfigureObject(concepts, Concept, 'query',
|
>>> tQuery = addAndConfigureObject(concepts, Concept, 'query',
|
||||||
... title=u'Query', conceptType=concepts.getTypeConcept(),
|
... title='Query', conceptType=concepts.getTypeConcept(),
|
||||||
... typeInterface=IQueryConcept)
|
... typeInterface=IQueryConcept)
|
||||||
|
|
||||||
>>> query = addAndConfigureObject(concepts, Concept, 'userworkitems',
|
>>> query = addAndConfigureObject(concepts, Concept, 'userworkitems',
|
||||||
|
@ -176,9 +180,10 @@ So we use the PersonWorkItems view, assigning john to the query.
|
||||||
>>> input = dict()
|
>>> input = dict()
|
||||||
>>> work = PersonWorkItems(query, TestRequest(form=input))
|
>>> work = PersonWorkItems(query, TestRequest(form=input))
|
||||||
>>> work.listWorkItems()
|
>>> work.listWorkItems()
|
||||||
[<WorkItem ['36', 2, '33', '2009-01-19 09:00', 'planned']:
|
[<WorkItem ['36', 2, '33', '2009-01-19 09:00', 'planned']: {'creator': ...}>]
|
||||||
{'title': u'Install Zope', 'created': ..., 'end': 1232352000,
|
|
||||||
'start': 1232352000, 'creator': '33'}>]
|
{'title': 'Install Zope', 'created': ..., 'end': 1232352000,
|
||||||
|
'start': 1232352000, 'creator': '33'}>]
|
||||||
|
|
||||||
|
|
||||||
Work Reports
|
Work Reports
|
||||||
|
@ -190,10 +195,10 @@ In addition we need a predicate that connects one or more tasks with a report.
|
||||||
>>> from loops.expert.report import IReport, Report
|
>>> from loops.expert.report import IReport, Report
|
||||||
>>> component.provideAdapter(Report, provides=IReport)
|
>>> component.provideAdapter(Report, provides=IReport)
|
||||||
>>> tReport = addAndConfigureObject(concepts, Concept, 'report',
|
>>> tReport = addAndConfigureObject(concepts, Concept, 'report',
|
||||||
... title=u'Report', conceptType=concepts.getTypeConcept(),
|
... title='Report', conceptType=concepts.getTypeConcept(),
|
||||||
... typeInterface=IReport)
|
... typeInterface=IReport)
|
||||||
>>> hasReport = addAndConfigureObject(concepts, Concept, 'hasreport',
|
>>> hasReport = addAndConfigureObject(concepts, Concept, 'hasreport',
|
||||||
... title=u'has Report', conceptType=concepts.getPredicateType())
|
... title='has Report', conceptType=concepts.getPredicateType())
|
||||||
|
|
||||||
Work statement report
|
Work statement report
|
||||||
---------------------
|
---------------------
|
||||||
|
@ -202,7 +207,7 @@ Now we can create a report and register it as the report for the task
|
||||||
used above.
|
used above.
|
||||||
|
|
||||||
>>> workStatement = addAndConfigureObject(concepts, Concept, 'work_statement',
|
>>> workStatement = addAndConfigureObject(concepts, Concept, 'work_statement',
|
||||||
... title=u'Work Statement', conceptType=tReport,
|
... title='Work Statement', conceptType=tReport,
|
||||||
... reportType='work_report')
|
... reportType='work_report')
|
||||||
>>> workStatement.assignChild(task01, hasReport)
|
>>> workStatement.assignChild(task01, hasReport)
|
||||||
|
|
||||||
|
@ -228,12 +233,13 @@ The user interface is a ReportConceptView subclass that is directly associated w
|
||||||
|
|
||||||
>>> for row in results:
|
>>> for row in results:
|
||||||
... for col in reportView.displayedColumns:
|
... for col in reportView.displayedColumns:
|
||||||
... print col.getDisplayValue(row),
|
... print(col.getDisplayValue(row), end=' ')
|
||||||
... print
|
... print()
|
||||||
08/12/28 19:00 20:15
|
08/12/28 19:00 20:15 {'title': ...}
|
||||||
{'url': '.../home/.36', 'title': u'loops Development'}
|
|
||||||
{'url': '.../home/.33', 'title': u'john'} 00:15
|
{'url': '.../home/.36', 'title': 'loops Development'}
|
||||||
{'actions': [...]}
|
{'url': '.../home/.33', 'title': 'john'} 00:15
|
||||||
|
{'actions': [...]}
|
||||||
|
|
||||||
>>> results.totals.data
|
>>> results.totals.data
|
||||||
{'effort': 900.0}
|
{'effort': 900.0}
|
||||||
|
@ -246,7 +252,7 @@ Export of work data
|
||||||
>>> reportView.nodeView = nodeView
|
>>> reportView.nodeView = nodeView
|
||||||
|
|
||||||
>>> output = reportView()
|
>>> output = reportView()
|
||||||
>>> print output
|
>>> print(output)
|
||||||
Day;Start;End;Task;Party;Title;LA;Effort;State
|
Day;Start;End;Task;Party;Title;LA;Effort;State
|
||||||
08/12/28;19:00;20:15;loops Development;john;;;15;finished
|
08/12/28;19:00;20:15;loops Development;john;;;15;finished
|
||||||
|
|
||||||
|
@ -261,16 +267,16 @@ Let's start with creating an a event and assigning it a task.
|
||||||
|
|
||||||
>>> from loops.organize.interfaces import IEvent, IAgendaItem
|
>>> from loops.organize.interfaces import IEvent, IAgendaItem
|
||||||
>>> tEvent = addAndConfigureObject(concepts, Concept, 'event',
|
>>> tEvent = addAndConfigureObject(concepts, Concept, 'event',
|
||||||
... title=u'Event', conceptType=concepts.getTypeConcept(),
|
... title='Event', conceptType=concepts.getTypeConcept(),
|
||||||
... typeInterface=IEvent)
|
... typeInterface=IEvent)
|
||||||
>>> tAgendaItem = addAndConfigureObject(concepts, Concept, 'agendaitem',
|
>>> tAgendaItem = addAndConfigureObject(concepts, Concept, 'agendaitem',
|
||||||
... title=u'AgendaItem', conceptType=concepts.getTypeConcept(),
|
... title='AgendaItem', conceptType=concepts.getTypeConcept(),
|
||||||
... typeInterface=IAgendaItem)
|
... typeInterface=IAgendaItem)
|
||||||
|
|
||||||
>>> ev01 = addAndConfigureObject(concepts, Concept, 'ev01',
|
>>> ev01 = addAndConfigureObject(concepts, Concept, 'ev01',
|
||||||
... title=u'loops Meeting', conceptType=tEvent)
|
... title='loops Meeting', conceptType=tEvent)
|
||||||
>>> aitem01 = addAndConfigureObject(concepts, Concept, 'aitem01',
|
>>> aitem01 = addAndConfigureObject(concepts, Concept, 'aitem01',
|
||||||
... title=u'Documentation of Features', conceptType=tAgendaItem)
|
... title='Documentation of Features', conceptType=tAgendaItem)
|
||||||
>>> ev01.assignChild(aitem01)
|
>>> ev01.assignChild(aitem01)
|
||||||
|
|
||||||
Now we create the meeting minutes report. We assign the event type as a
|
Now we create the meeting minutes report. We assign the event type as a
|
||||||
|
@ -282,7 +288,7 @@ report is available.
|
||||||
... name='meeting_minutes')
|
... name='meeting_minutes')
|
||||||
|
|
||||||
>>> meetingMinutes = addAndConfigureObject(concepts, Concept,
|
>>> meetingMinutes = addAndConfigureObject(concepts, Concept,
|
||||||
... 'meeting_minutes', title=u'Meeting Minutes', conceptType=tReport,
|
... 'meeting_minutes', title='Meeting Minutes', conceptType=tReport,
|
||||||
... reportType='meeting_minutes')
|
... reportType='meeting_minutes')
|
||||||
>>> meetingMinutes.assignChild(tEvent, hasReport)
|
>>> meetingMinutes.assignChild(tEvent, hasReport)
|
||||||
|
|
||||||
|
@ -297,10 +303,10 @@ We can now access the report using a corresponding report-based view.
|
||||||
1
|
1
|
||||||
>>> for row in results:
|
>>> for row in results:
|
||||||
... for col in reportView.displayedColumns:
|
... for col in reportView.displayedColumns:
|
||||||
... print col.getDisplayValue(row),
|
... print(col.getDisplayValue(row), end=' ')
|
||||||
... print
|
... print()
|
||||||
{'url': 'http://127.0.0.1/loops/views/home/.58',
|
{'title': 'Documentation of Features',
|
||||||
'title': u'Documentation of Features'}
|
'url': 'http://127.0.0.1/loops/views/home/.58'}
|
||||||
<cybertools.composer.report.result.ResultSet object ...>
|
<cybertools.composer.report.result.ResultSet object ...>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,27 +1,10 @@
|
||||||
#
|
# loops.organize.work.report
|
||||||
# Copyright (c) 2018 Helmut Merz helmutm@cy55.de
|
|
||||||
#
|
|
||||||
# This program is free software; you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation; either version 2 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program; if not, write to the Free Software
|
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
#
|
|
||||||
|
|
||||||
"""
|
""" Work report definitions.
|
||||||
Work report definitions.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from datetime import date, timedelta
|
from datetime import date, timedelta
|
||||||
from zope.app.pagetemplate import ViewPageTemplateFile
|
from zope.browserpage import ViewPageTemplateFile
|
||||||
from zope.cachedescriptors.property import Lazy
|
from zope.cachedescriptors.property import Lazy
|
||||||
from zope.component import adapter, getAdapter
|
from zope.component import adapter, getAdapter
|
||||||
from zope.i18n.locales import locales
|
from zope.i18n.locales import locales
|
||||||
|
|
Loading…
Add table
Reference in a new issue