work in progress: cybertools.reporter

git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@1748 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2007-05-20 17:07:17 +00:00
parent 36f0f335ce
commit a0a52ab055
7 changed files with 170 additions and 105 deletions

View file

@ -1,19 +1,54 @@
Quickstart Instructions ====================================
======================= A Basic API for Reports and Listings
====================================
($Id$) ($Id$)
TO DO... TO DO...
>>> from zope.app import zapi >>> from zope import component
>>> from zope.app.testing import ztapi
>>> from zope.interface import directlyProvides >>> from zope.interface import directlyProvides
A Basic API for Reports and Listings
==================================== Listings
========
>>> from cybertools.reporter.data import DataSource
>>> from cybertools.reporter.resultset import ResultSet
>>> from cybertools.reporter.interfaces import IResultSet
Let's start with the Person class from the cybertools.organize package - we will
then provide a listing of persons...
>>> from cybertools.organize.party import Person
>>> from datetime import date
>>> pdata = ((u'John', u'Smith', '1956-08-01'),
... (u'David', u'Waters', '1972-12-24'),
... (u'Carla', u'Myers', '1981-10-11'))
>>> persons = DataSource([Person(f, s, date(*[int(d) for d in b.split('-')]))
... for f, s, b in pdata])
>>> component.provideAdapter(ResultSet)
>>> rset = IResultSet(persons)
>>> len(list(rset.rows))
3
For the browser presentation we can also use a browser view providing
the result set with extended attributes:
>>> #rsView = component.getMultiAdapter((context, TestRequest()), IBrowserView)
The reporter package also includes facilities for sorting the rows in a
result set and splitting a result into batches.
Sorting
-------
Batching Batching
-------- ========
We'll use a fairly simple Iterable: We'll use a fairly simple Iterable:
@ -48,43 +83,4 @@ We are now ready to use the corresponding browser view:
'navOnClick': "dojo.io.updateNode(...); return false;", 'navOnClick': "dojo.io.updateNode(...); return false;",
'title': 5} 'title': 5}
The real reporting stuff
------------------------
>>> from cybertools.reporter.data import DataSource
>>> from cybertools.reporter.interfaces import IResultSet
>>> from cybertools.reporter.example.interfaces import IContactsDataSource
>>> from cybertools.reporter.example.contact import Contacts
Let's start with the Person class from the example package - we will
then provide a listing of persons...
>>> from cybertools.organize.party import Person
>>> from datetime import date
>>> pdata = ((u'John', u'Smith', '1956-08-01'),
... (u'David', u'Waters', '1972-12-24'),
... (u'Carla', u'Myers', '1981-10-11'))
>>> persons = DataSource([Person(f, s, date(*[int(d) for d in b.split('-')]))
... for f, s, b in pdata])
>>> directlyProvides(persons, IContactsDataSource)
>>> ztapi.provideAdapter(IContactsDataSource, IResultSet, Contacts)
>>> rset = IResultSet(persons)
>>> len(rset)
3
For the browser presentation we can also use a browser view providing
the result set with extended attributes:
>>> #rsView = zapi.getMultiAdapter((context, TestRequest()), IBrowserView)
The reporter package also includes facilities for sorting the rows in a
result set and splitting a result into batches.
Sorting
-------

View file

@ -0,0 +1,41 @@
<!-- $Id$ -->
<metal:detail define-macro="detail">
<h2 tal:content="item/title">Something</h2><br />
<table>
<tr tal:repeat="cell item/cells">
<td><span tal:content="cell/title"
i18n:translate="" />Fieldname:</td>
<td tal:content="cell/text">Value</td>
</tr>
</table>
</metal:detail>
<metal:listing define-macro="listing"
tal:define="result item/resultSet">
<h2 tal:content="item/title">Something</h2><br />
<table class="listing">
<tr>
<th tal:repeat="field result/schema"
tal:content="field/title"
i18n:translate="">Fieldname</th>
</tr>
<tal:items repeat="row result/rows">
<tal:item define="class python: repeat['row'].odd() and 'even' or 'odd'">
<tr tal:attributes="class class">
<td valign="top"
repeat="cell row/cells">
<a href="#"
tal:omit-tag="not: cell/url"
tal:attributes="href cell/url;
title cell/urlTitle">
<span tal:replace="cell/text">Value</span>
</a>
</td>
</tr>
</tal:item>
</tal:items>
</table>
</metal:listing>

View file

@ -0,0 +1,65 @@
#
# Copyright (c) 2007 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 reports.
$Id$
"""
from zope import interface, component
from zope.app.pagetemplate import ViewPageTemplateFile
from zope.cachedescriptors.property import Lazy
from loops.browser.common import BaseView
reportMacros = ViewPageTemplateFile('macros.pt')
class DetailView(BaseView):
template = reportMacros
@Lazy
def macro(self):
return self.template.macros('detail')
@Lazy
def resultSet(self):
result = ResultSet()
return result
@Lazy
def cells(self):
return self.resultSet.rows.next()
class ListingView(BaseView):
template = reportMacros
@Lazy
def macro(self):
return self.template.macros('listing')
@Lazy
def resultSet(self):
result = ResultSet()
return result

View file

@ -1,4 +0,0 @@
"""
$Id$
"""

View file

@ -1,31 +0,0 @@
#
# Copyright (c) 2006 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
#
"""
Interfaces for an example for the cybertools.reporter package. This is
based on the cybertools.contact package
$Id$
"""
from zope.interface import Interface
class IContactsDataSource(Interface):
""" A data source marker interface for a collection of contacts.
"""

View file

@ -36,7 +36,7 @@ class IBatch(Interface):
iterable = Attribute(u'The iterable this batch belongs to') iterable = Attribute(u'The iterable this batch belongs to')
start = Attribute(u'The current start index of the batch in the parent iterable') start = Attribute(u'The current start index of the batch in the parent iterable')
def __getitem__(idx): def __getitem__(idx):
""" Return the item at index idx on the current page. """ Return the item at index idx on the current page.
""" """
@ -74,38 +74,37 @@ class IResultSet(Interface):
(fields, cells). (fields, cells).
""" """
schema = zope.schema.Iterable(title=u'Schema', schema = Attribute(u'Collection of field specifications from zope.schema.')
description=u'Collection of field specifications based ' rows = Attribute(u'Sequence of row objects.')
'on the interfaces defined by zope.schema.')
rows = zope.schema.Iterable(title=u'Rows', view = Attribute(u'The view the result set was created for.')
description=u'Sequence of row objects')
class IRow(Interface): class IRow(Interface):
""" A sequence of cells containing the real data objects. """ A sequence of cells containing the real data objects.
""" """
cells = zope.schema.Dict(zope.schema.ASCIILine(), cells = Attribute(u'Mapping of data elements addressed by field names.')
title=u'Cells',
description=u'Mapping of data elements addressed by a name ' value = Attribute(u'The object that is the base of this row.')
'that is the key to the mapping.')
resultSet = Attribute('The result set this row belongs to.') resultSet = Attribute('The result set this row belongs to.')
schema = Attribute(u'The schema of the result set this row belongs to')
class ICell(Interface): class ICell(Interface):
""" A single cell of a listing or table. """ A single cell of a listing or table.
""" """
text = zope.schema.Text(title=u'Text', text = Attribute(u'Text to be displayed.')
description=u'Text to be displayed') value = Attribute(u'The real object, often identical to text.')
value = zope.schema.Object(Interface, token = Attribute(u'May be used to identify a cell within '
title=u'Value', 'the result set, e.g. in forms.')
description=u'The real object, often identical to text.') url = Attribute(u'An optional URL for a link to place on the cell.')
token = zope.schema.ASCIILine(title=u'Token', # string:${view/url}/.target${row/uniqueId}
description=u'May be used to identify a cell within' urlTitle = Attribute(u'Optional title for this link.')
'the result set, e.g. in forms')
title = Attribute('The title of the schema field this cell belongs to.')
row = Attribute('The row this cell belongs to.') row = Attribute('The row this cell belongs to.')
def sortKey(): def sortKey():

View file

@ -27,8 +27,8 @@ $Id$
from zope.component import adapts from zope.component import adapts
from zope.interface import implements from zope.interface import implements
from cybertools.reporter.interfaces import IDataSource
from cybertools.reporter.interfaces import IResultSet, IRow, ICell from cybertools.reporter.interfaces import IResultSet, IRow, ICell
from cybertools.reporter.example.interfaces import IContactsDataSource
class Cell(object): class Cell(object):
@ -69,10 +69,10 @@ class Row(object):
for f in schema.fields]) for f in schema.fields])
class Contacts(object): class ResultSet(object):
implements(IResultSet) implements(IResultSet)
adapts(IContactsDataSource) adapts(IDataSource)
def __init__(self, context): def __init__(self, context):
self.context = context self.context = context
@ -84,7 +84,6 @@ class Contacts(object):
@property @property
def rows(self): def rows(self):
return [Row(o, self) for o in iter(self.context)] for o in iter(self.context):
yield Row(o, self)
def __len__(self):
return len(self.rows)