diff --git a/browser/concept.py b/browser/concept.py
index 01084b0..c4bf3e6 100644
--- a/browser/concept.py
+++ b/browser/concept.py
@@ -276,7 +276,8 @@ class ConceptView(BaseView):
if r.order != pos:
r.order = pos
- def getChildren(self, topLevelOnly=True, sort=True, noDuplicates=True):
+ def getChildren(self, topLevelOnly=True, sort=True, noDuplicates=True,
+ useFilter=True):
form = self.request.form
#if form.get('loops.viewName') == 'index.html' and self.editable:
if self.editable:
@@ -311,11 +312,13 @@ class ConceptView(BaseView):
break
if skip:
continue
- options = IOptions(adapted(r.predicate), None)
- if options is not None and options('hide_children'):
- continue
- if fv.check(r.context):
- yield r
+ if useFilter:
+ options = IOptions(adapted(r.predicate), None)
+ if options is not None and options('hide_children'):
+ continue
+ if not fv.check(r.context):
+ continue
+ yield r
def checkCriteria(self, relation, criteria):
result = True
@@ -347,9 +350,10 @@ class ConceptView(BaseView):
return result
def isHidden(self, pr):
- if (getName(pr.second.conceptType) in
- IOptions(adapted(pr.predicate))('hide_parents_for', [])):
- #IOptions(pr.predicate)('hide_parents_for', [])):
+ predOptions = IOptions(adapted(pr.predicate))
+ if predOptions('hide_parents'):
+ return True
+ if (getName(pr.second.conceptType) in predOptions('hide_parents_for', [])):
return True
hideRoles = None
options = component.queryAdapter(adapted(pr.first), IOptions)
diff --git a/browser/concept_related.pt b/browser/concept_related.pt
index 1348617..0b680d0 100644
--- a/browser/concept_related.pt
+++ b/browser/concept_related.pt
@@ -23,7 +23,8 @@
>> from loops.expert.browser.base import BaseQueryView
+Reports
+=======
+
+ >>> from loops.expert.report import IReport, Report
+ >>> component.provideAdapter(Report, provides=IReport)
+
+ >>> report = Report(None)
+
+ >>> from loops.expert.report import IReportInstance, DefaultConceptReportInstance
+ >>> component.provideAdapter(DefaultConceptReportInstance,
+ ... provides=IReportInstance,
+ ... name='default_concept_report')
+
+ >>> from loops.expert.report import ReportTypeSourceList
+ >>> source = ReportTypeSourceList(report)
+ >>> list(source)
+ [(u'default_concept_report', u'Default Concept Report')]
+
+
Fin de partie
=============
diff --git a/expert/browser/configure.zcml b/expert/browser/configure.zcml
index 4d71dfa..2014a46 100644
--- a/expert/browser/configure.zcml
+++ b/expert/browser/configure.zcml
@@ -54,4 +54,25 @@
factory="loops.expert.browser.search.ActionExecutor"
permission="zope.ManageContent" />
+
+
+
+
+
+
+
+
diff --git a/expert/browser/report.pt b/expert/browser/report.pt
new file mode 100644
index 0000000..e1237dd
--- /dev/null
+++ b/expert/browser/report.pt
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
diff --git a/expert/browser/report.py b/expert/browser/report.py
new file mode 100644
index 0000000..b8f5f9b
--- /dev/null
+++ b/expert/browser/report.py
@@ -0,0 +1,107 @@
+#
+# Copyright (c) 2011 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 reporting.
+"""
+
+from urllib import urlencode
+from zope import interface, component
+from zope.app.pagetemplate import ViewPageTemplateFile
+from zope.cachedescriptors.property import Lazy
+from zope.traversing.api import getName, getParent
+
+from cybertools.browser.form import FormController
+from loops.browser.concept import ConceptView
+from loops.browser.node import NodeView
+from loops.common import adapted, AdapterBase
+from loops.expert.report import IReportInstance
+from loops.organize.personal.browser.filter import FilterView
+from loops.security.common import canWriteObject, checkPermission
+from loops import util
+from loops.util import _
+
+
+report_template = ViewPageTemplateFile('report.pt')
+results_template = ViewPageTemplateFile('results.pt')
+
+
+class ReportView(ConceptView):
+
+ @Lazy
+ def report_macros(self):
+ return self.controller.getTemplateMacros('report', report_template)
+
+ @Lazy
+ def macro(self):
+ return self.report_macros['main']
+
+ @Lazy
+ def dynamicParams(self):
+ return self.request.form
+
+
+class ResultsView(NodeView):
+
+ @Lazy
+ def result_macros(self):
+ return self.controller.getTemplateMacros('results', results_template)
+
+ @Lazy
+ def macro(self):
+ return self.result_macros['main']
+
+ @Lazy
+ def item(self):
+ return self
+
+ @Lazy
+ def params(self):
+ params = dict(self.request.form)
+ if 'report_execute' in params:
+ del params['report_execute']
+ return params
+
+ @Lazy
+ def report(self):
+ return adapted(self.virtualTargetObject)
+
+ @Lazy
+ def reportInstance(self):
+ instance = component.getAdapter(self.report, IReportInstance,
+ name=self.report.reportType)
+ instance.request = self.request
+ return instance
+
+ #@Lazy
+ def results(self):
+ return self.reportInstance.getResults(self.params)
+
+ @Lazy
+ def resultsRenderer(self):
+ return self.reportInstance.getResultsRenderer('results', self.result_macros)
+
+ @Lazy
+ def reportUrl(self):
+ url = self.virtualTargetUrl
+ return '?'.join((url, urlencode(self.params)))
+
+ @Lazy
+ def displayedColumns(self):
+ return self.reportInstance.getActiveOutputFields()
+
diff --git a/expert/browser/results.pt b/expert/browser/results.pt
new file mode 100644
index 0000000..9c892ad
--- /dev/null
+++ b/expert/browser/results.pt
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+ Default Results Listing
+
+
+
+
diff --git a/expert/configure.zcml b/expert/configure.zcml
index 3eff3c3..03543ad 100644
--- a/expert/configure.zcml
+++ b/expert/configure.zcml
@@ -16,6 +16,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/expert/report.py b/expert/report.py
new file mode 100644
index 0000000..fdcef10
--- /dev/null
+++ b/expert/report.py
@@ -0,0 +1,143 @@
+#
+# Copyright (c) 2011 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
+#
+
+"""
+Report type, report concept adapter, and other reporting stuff.
+"""
+
+from zope import schema, component
+from zope.component import adapts
+from zope.interface import Interface, Attribute, implements
+from zope.cachedescriptors.property import Lazy
+from zope.security.proxy import removeSecurityProxy
+
+from cybertools.composer.report.base import Report as BaseReport
+from cybertools.composer.report.base import LeafQueryCriteria, CompoundQueryCriteria
+from cybertools.composer.report.interfaces import IReport as IBaseReport
+from cybertools.composer.report.result import ResultSet, Row
+from cybertools.util.jeep import Jeep
+from loops.common import AdapterBase
+from loops.interfaces import ILoopsAdapter
+from loops.type import TypeInterfaceSourceList
+from loops import util
+from loops.util import _
+
+
+# interfaces
+
+class IReport(ILoopsAdapter):
+ """ The report adapter for the persistent object (concept) that stores
+ the report in the concept map.
+ """
+
+ reportType = schema.Choice(
+ title=_(u'Report Type'),
+ description=_(u'The type of the report.'),
+ default=None,
+ source='loops.expert.reportTypeSource',
+ required=True)
+
+
+class IReportSchema(IBaseReport, IReport):
+ """ All report attributes - use for security declarations.
+ """
+
+
+class IReportInstance(Interface):
+ """ The report-type-specific object (an adapter on the report) that
+ does the real report execution stuff.
+ """
+
+ label = Attribute('The user-friendly label of the report type specified '
+ 'by this instance class.')
+
+
+# report concept adapter and instances
+
+class Report(AdapterBase):
+
+ implements(IReport)
+
+ _contextAttributes = list(IReport)
+
+TypeInterfaceSourceList.typeInterfaces += (IReport,)
+
+
+class ReportInstance(BaseReport):
+
+ implements(IReportInstance)
+ adapts(IReport)
+
+ rowFactory = Row
+
+ def __init__(self, context):
+ self.context = context
+
+ def getResultsRenderer(self, name, macros):
+ return macros[name]
+
+ def getResults(self, dynaParams=None):
+ crit = self.queryCriteria
+ if crit is None:
+ return []
+ for k, v in dynaParams.items():
+ if k in crit.parts.keys():
+ crit.parts[k].value = v
+ parts = Jeep(crit.parts)
+ result = list(self.selectObjects(parts)) # may modify parts
+ qc = CompoundQueryCriteria(parts)
+ return ResultSet(self, result, rowFactory=self.rowFactory,
+ sortCriteria=self.getSortCriteria(), queryCriteria=qc)
+
+ def selectObjects(self, parts):
+ return []
+
+
+class ReportTypeSourceList(object):
+
+ implements(schema.interfaces.IIterableSource)
+
+ def __init__(self, context):
+ self.context = context
+
+ def __iter__(self):
+ return iter(self.reportTypes)
+
+ def __contains__(self, value):
+ return value in [item[0] for item in self]
+
+ @Lazy
+ def reportTypes(self):
+ result = []
+ for item in component.getAdapters([self.context], IReportInstance):
+ name, adapter = item
+ adapter = removeSecurityProxy(adapter)
+ label = getattr(adapter, 'label', name)
+ result.append((name, label,))
+ return result
+
+ def __len__(self):
+ return len(self.reportTypes)
+
+
+# default concept report
+
+class DefaultConceptReportInstance(ReportInstance):
+
+ label = u'Default Concept Report'
+
diff --git a/organize/work/README.txt b/organize/work/README.txt
index 85d6bc0..2946e1e 100644
--- a/organize/work/README.txt
+++ b/organize/work/README.txt
@@ -180,6 +180,16 @@ So we use the PersonWorkItems view, assigning john to the query.
'creator': '33'}>]
+Work Reports
+============
+
+ >>> from loops.organize.work.report import WorkReportInstance
+ >>> from loops.expert.report import IReportInstance
+ >>> component.provideAdapter(WorkReportInstance,
+ ... provides=IReportInstance,
+ ... name='work_report')
+
+
Fin de partie
=============
diff --git a/organize/work/configure.zcml b/organize/work/configure.zcml
index b48b04c..ccd434f 100644
--- a/organize/work/configure.zcml
+++ b/organize/work/configure.zcml
@@ -73,6 +73,19 @@
class="loops.organize.work.browser.WorkItemInfo"
permission="zope.View" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Work Items Listing
+
+
+
+ Task |
+
+
+
+
+ 2009-01 |
+
+ 2007-03-30 |
+ 17:30 |
+ 20:00 |
+ 2:30 |
+
+ Task |
+
+ John |
+ Title |
+
+
+
+
+
+
+