diff --git a/expert/browser/export.py b/expert/browser/export.py
new file mode 100644
index 0000000..8c06e21
--- /dev/null
+++ b/expert/browser/export.py
@@ -0,0 +1,77 @@
+#
+# Copyright (c) 2015 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.
+"""
+
+import csv
+from cStringIO import StringIO
+from zope.i18n import translate
+
+from loops.expert.browser.report import ReportConceptView
+from loops.interfaces import ILoopsObject
+from loops.util import _
+
+
+class ReportConceptCSVExport(ReportConceptView):
+
+ isToplevel = True
+ reportMode = 'export'
+
+ delimiter = ';'
+ encoding = 'UTF-8'
+
+ def getFileName(self):
+ return 'output'
+
+ def getColumnTitle(self, field):
+ lang = self.languageInfo.language
+ return translate(_(field.title), target_language=lang)
+
+ def __call__(self):
+ fields = self.displayedColumns
+ fieldNames = [f.name for f in fields]
+ output = StringIO()
+ writer = csv.DictWriter(output, fieldNames, delimiter=self.delimiter)
+ output.write(self.delimiter.join(
+ [self.getColumnTitle(f) for f in fields]) + '\n')
+ results = self.reportInstance.getResults()
+ for row in results:
+ data = {}
+ for f in fields:
+ value = f.getValue(row)
+ if ILoopsObject.providedBy(value):
+ value = value.title
+ if isinstance(value, unicode):
+ value = value.encode(self.encoding)
+ data[f.name] = value
+ writer.writerow(data)
+ text = output.getvalue()
+ self.setDownloadHeader(text)
+ return text
+
+ def setDownloadHeader(self, text):
+ response = self.request.response
+ response.setHeader('Content-Disposition',
+ 'attachment; filename=%s.csv' %
+ self.getFileName())
+ response.setHeader('Cache-Control', '')
+ response.setHeader('Pragma', '')
+ response.setHeader('Content-Type', 'text/csv')
+ response.setHeader('Content-Length', len(text))
diff --git a/expert/field.py b/expert/field.py
index e54d998..2263b84 100644
--- a/expert/field.py
+++ b/expert/field.py
@@ -22,6 +22,7 @@ Field definitions for reports.
from zope.app.form.browser.interfaces import ITerms
from zope import component
+from zope.i18n import translate
from zope.i18n.locales import locales
from zope.schema.interfaces import IVocabularyFactory, IContextSourceBinder
@@ -92,6 +93,11 @@ class DateField(Field):
format = ('date', 'short')
cssClass = 'center'
+ def getValue(self, row):
+ if getattr(row.parent.context.view, 'reportMode', None) == 'export':
+ return self.getDisplayValue(row)
+ super(DateField, self).getValue(row)
+
def getDisplayValue(self, row):
value = self.getRawValue(row)
if not value:
@@ -132,6 +138,15 @@ class WorkItemStateField(Field):
statesDefinition = 'workItemStates'
renderer = 'workitem_state'
+ def getValue(self, row):
+ view = row.parent.context.view
+ if getattr(view, 'reportMode', None) == 'export':
+ stateObject = row.context.getStateObject()
+ lang = view.languageInfo.language
+ return translate(util._(stateObject.title), target_language=lang)
+ return super(WorkItemStateField, self).getValue(row)
+
+
def getDisplayValue(self, row):
if row.context is None:
return None
@@ -241,14 +256,18 @@ class TrackDateField(Field):
cssClass = 'right'
def getValue(self, row):
+ reportMode = getattr(row.parent.context.view, 'reportMode', None)
+ if reportMode == 'export':
+ return self.getDisplayValue(row)
value = self.getRawValue(row)
if not value:
return None
return timeStamp2Date(value)
def getDisplayValue(self, row):
- value = self.getValue(row)
+ value = self.getRawValue(row)
if value:
+ value = timeStamp2Date(value)
view = row.parent.context.view
return formatDate(value, self.part, self.format,
view.languageInfo.language)
diff --git a/knowledge/qualification/browser.py b/knowledge/qualification/browser.py
index 9d5b619..186642f 100644
--- a/knowledge/qualification/browser.py
+++ b/knowledge/qualification/browser.py
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2014 Helmut Merz helmutm@cy55.de
+# Copyright (c) 2015 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
@@ -26,6 +26,7 @@ from zope.app.pagetemplate import ViewPageTemplateFile
from zope.cachedescriptors.property import Lazy
from loops.browser.concept import ConceptView
+from loops.expert.browser.export import ReportConceptCSVExport
from loops.expert.browser.report import ResultsConceptView
from loops.organize.party import getPersonForUser
from loops.util import _
@@ -35,3 +36,8 @@ class Qualifications(ResultsConceptView):
reportName = 'qualification_overview'
+
+class QualificationsCSVExport(ReportConceptCSVExport):
+
+ reportName = 'qualification_overview'
+
diff --git a/knowledge/qualification/configure.zcml b/knowledge/qualification/configure.zcml
index e4f02c9..b6a1a5e 100644
--- a/knowledge/qualification/configure.zcml
+++ b/knowledge/qualification/configure.zcml
@@ -23,6 +23,12 @@
factory="loops.knowledge.qualification.browser.Qualifications"
permission="zope.View" />
+
+
>> results.totals.data
{'effort': 900}
+Export of work data
+-------------------
+
+ >>> from loops.organize.work.report import WorkStatementCSVExport
+ >>> reportView = WorkStatementCSVExport(task01, TestRequest())
+ >>> reportView.nodeView = nodeView
+
+ >>> output = reportView()
+ >>> print output
+ Day;Start;End;Task;Party;Title;Duration;Effort;State
+ 08/12/28;19:00;20:15;loops Development;john;;1.25;0.25;finished
+
Meeting Minutes
===============
diff --git a/organize/work/configure.zcml b/organize/work/configure.zcml
index 17dac6c..d4eab19 100644
--- a/organize/work/configure.zcml
+++ b/organize/work/configure.zcml
@@ -101,6 +101,12 @@
class="loops.organize.work.report.WorkStatementView"
permission="zope.View" />
+
+