provide a comments overview listing, e.g. for moderation of comments

This commit is contained in:
Helmut Merz 2014-04-19 10:48:45 +02:00
parent f34dc4a59c
commit 2d2240244e
8 changed files with 175 additions and 38 deletions

View file

@ -16,6 +16,7 @@
<div metal:use-macro="item/report_macros/params" /> <div metal:use-macro="item/report_macros/params" />
<div metal:define-macro="buttons"> <div metal:define-macro="buttons">
<input type="submit" name="report_execute" value="Execute Report" <input type="submit" name="report_execute" value="Execute Report"
tal:condition="item/queryFields"
i18n:attributes="value" /> i18n:attributes="value" />
</div> </div>
</form> </form>

View file

@ -1,5 +1,5 @@
# #
# Copyright (c) 2013 Helmut Merz helmutm@cy55.de # Copyright (c) 2014 Helmut Merz helmutm@cy55.de
# #
# This program is free software; you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@ -29,6 +29,7 @@ from cybertools.composer.report.field import Field as BaseField
from cybertools.composer.report.result import ResultSet from cybertools.composer.report.result import ResultSet
from cybertools.stateful.interfaces import IStateful, IStatesDefinition from cybertools.stateful.interfaces import IStateful, IStatesDefinition
from cybertools.util.date import timeStamp2Date from cybertools.util.date import timeStamp2Date
from cybertools.util.format import formatDate
from loops.common import baseObject from loops.common import baseObject
from loops.expert.report import ReportInstance from loops.expert.report import ReportInstance
from loops import util from loops import util
@ -209,6 +210,41 @@ class TargetField(RelationField):
return util.getObjectForUid(value) return util.getObjectForUid(value)
# track fields
class TrackDateField(Field):
fieldType = 'date'
part = 'date'
format = 'short'
cssClass = 'right'
def getValue(self, row):
value = self.getRawValue(row)
if not value:
return None
return timeStamp2Date(value)
def getDisplayValue(self, row):
value = self.getValue(row)
if value:
view = row.parent.context.view
return formatDate(value, self.part, self.format,
view.languageInfo.language)
return u''
def getSelectValue(self, row):
value = self.getRawValue(row)
if not value:
return ''
return timeStamp2ISO(value)[:10]
class TrackTimeField(TrackDateField):
part = 'time'
# sub-report stuff # sub-report stuff
class SubReport(ReportInstance): class SubReport(ReportInstance):

View file

@ -1,5 +1,5 @@
# #
# Copyright (c) 2012 Helmut Merz helmutm@cy55.de # Copyright (c) 2014 Helmut Merz helmutm@cy55.de
# #
# This program is free software; you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@ -25,9 +25,11 @@ from zope.component import adapts
from zope.interface import Interface, Attribute, implements from zope.interface import Interface, Attribute, implements
from zope.cachedescriptors.property import Lazy from zope.cachedescriptors.property import Lazy
from zope.security.proxy import removeSecurityProxy from zope.security.proxy import removeSecurityProxy
from zope.traversing.api import getName
from cybertools.composer.report.base import Report as BaseReport from cybertools.composer.report.base import Report as BaseReport
from cybertools.composer.report.base import LeafQueryCriteria, CompoundQueryCriteria from cybertools.composer.report.base import LeafQueryCriteria
from cybertools.composer.report.base import CompoundQueryCriteria
from cybertools.composer.report.interfaces import IReport as IBaseReport from cybertools.composer.report.interfaces import IReport as IBaseReport
from cybertools.composer.report.interfaces import IReportParams from cybertools.composer.report.interfaces import IReportParams
from cybertools.composer.report.result import ResultSet, Row from cybertools.composer.report.result import ResultSet, Row
@ -53,6 +55,8 @@ class IReport(ILoopsAdapter, IReportParams):
source='loops.expert.reportTypeSource', source='loops.expert.reportTypeSource',
required=True) required=True)
name = Attribute('The name of the report.')
class IReportInstance(IBaseReport): class IReportInstance(IBaseReport):
""" The report-type-specific object (an adapter on the report) that """ The report-type-specific object (an adapter on the report) that
@ -68,6 +72,10 @@ class Report(AdapterBase):
_contextAttributes = list(IReport) _contextAttributes = list(IReport)
@Lazy
def name(self):
return getName(self.context)
TypeInterfaceSourceList.typeInterfaces += (IReport,) TypeInterfaceSourceList.typeInterfaces += (IReport,)
@ -79,9 +87,11 @@ class ReportInstance(BaseReport):
rowFactory = Row rowFactory = Row
view = None # set upon creation view = None # set upon creation
#headerRowFactory = Row
def __init__(self, context): def __init__(self, context):
self.context = context self.context = context
self.name = self.type
def getResultsRenderer(self, name, macros): def getResultsRenderer(self, name, macros):
return macros[name] return macros[name]
@ -105,6 +115,8 @@ class ReportInstance(BaseReport):
if k in crit.parts.keys(): if k in crit.parts.keys():
crit.parts[k].comparisonValue = v crit.parts[k].comparisonValue = v
parts = Jeep(crit.parts) parts = Jeep(crit.parts)
if getattr(self, 'limitsCount', ''):
limits = None
result = list(self.selectObjects(parts)) # may modify parts result = list(self.selectObjects(parts)) # may modify parts
qc = CompoundQueryCriteria(parts) qc = CompoundQueryCriteria(parts)
return ResultSet(self, result, rowFactory=self.rowFactory, return ResultSet(self, result, rowFactory=self.rowFactory,
@ -161,3 +173,15 @@ class DefaultConceptReportInstance(ReportInstance):
label = u'Default Concept Report' label = u'Default Concept Report'
# specialized rows
class TrackRow(Row):
@staticmethod
def getContextAttr(obj, attr):
if attr in obj.context.metadata_attributes:
return getattr(obj.context, attr)
return obj.context.data.get(attr)

View file

@ -78,6 +78,12 @@ Viewing comments
('My comment', u'... ...', u'john') ('My comment', u'... ...', u'john')
Reporting
=========
>>> from loops.organize.comment.report import CommentsOverview
Fin de partie Fin de partie
============= =============

View file

@ -37,4 +37,26 @@
factory="loops.organize.comment.browser.CreateComment" factory="loops.organize.comment.browser.CreateComment"
permission="zope.View" /> permission="zope.View" />
<!-- reporting -->
<zope:adapter
name="list_comments.html"
for="loops.interfaces.IConcept
zope.publisher.interfaces.browser.IBrowserRequest"
provides="zope.interface.Interface"
factory="loops.organize.comment.report.CommentsOverview"
permission="zope.View" />
<zope:adapter
name="comments_overview"
factory="loops.organize.comment.report.CommentsReportInstance"
provides="loops.expert.report.IReportInstance"
trusted="True" />
<zope:class class="loops.organize.comment.report.CommentsReportInstance">
<require permission="zope.View"
interface="loops.expert.report.IReportInstance" />
<require permission="zope.ManageContent"
set_schema="loops.expert.report.IReportInstance" />
</zope:class>
</configure> </configure>

View file

@ -0,0 +1,6 @@
type(u'report', u'Report', options=u'',
typeInterface='loops.expert.report.IReport', viewName=u'')
concept(u'comments_overview', u'\xdcbersicht Kommentare', u'report',
reportType=u'comments_overview')
concept(u'comments', u'Kommentare', u'query', options=u'',
viewName=u'list_comments.html')

View file

@ -0,0 +1,75 @@
#
# 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
#
"""
Report views and definitions for comments listings and similar stuff.
"""
from cybertools.util.jeep import Jeep
from loops.expert.browser.report import ReportConceptView
from loops.expert.field import Field, StateField, TargetField
from loops.expert.field import TrackDateField
from loops.expert.report import ReportInstance, TrackRow
class CommentsOverview(ReportConceptView):
reportName = 'comments_overview'
timeStamp = TrackDateField('timeStamp', u'Timestamp',
description=u'The date and time the comment was posted.',
part='dateTime',
executionSteps=['sort', 'output'])
target = TargetField('taskId', u'Target',
description=u'The resource or concept the comment was posted at.',
executionSteps=['output'])
name = Field('name', u'Name',
description=u'The name addres of the poster.',
executionSteps=['output'])
email = Field('email', u'E-Mail Address',
description=u'The email addres of the poster.',
executionSteps=['output'])
subject = Field('subject', u'Subject',
description=u'The subject of the comment.',
executionSteps=['output'])
state = StateField('state', u'State',
description=u'The state of the comment.',
cssClass='center',
statesDefinition='organize.commentStates',
executionSteps=['query', 'sort', 'output'])
class CommentsRow(TrackRow):
pass
class CommentsReportInstance(ReportInstance):
type = "comments_overview"
label = u'Comments Overview'
rowFactory = CommentsRow
fields = Jeep((timeStamp, target, name, email, subject, state))
defaultOutputFields = fields
defaultSortCriteria = (state, timeStamp)
def selectObjects(self, parts):
return self.recordManager['comments'].values()

View file

@ -1,5 +1,5 @@
# #
# Copyright (c) 2013 Helmut Merz helmutm@cy55.de # Copyright (c) 2014 Helmut Merz helmutm@cy55.de
# #
# This program is free software; you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@ -30,13 +30,13 @@ from cybertools.composer.report.field import CalculatedField
from cybertools.composer.report.result import ResultSet, Row as BaseRow from cybertools.composer.report.result import ResultSet, Row as BaseRow
from cybertools.organize.interfaces import IWorkItems from cybertools.organize.interfaces import IWorkItems
from cybertools.util.date import timeStamp2Date, timeStamp2ISO from cybertools.util.date import timeStamp2Date, timeStamp2ISO
from cybertools.util.format import formatDate
from cybertools.util.jeep import Jeep from cybertools.util.jeep import Jeep
from loops.common import adapted, baseObject from loops.common import adapted, baseObject
from loops.expert.browser.report import ReportConceptView from loops.expert.browser.report import ReportConceptView
from loops.expert.field import Field, TargetField, DateField, StateField, \ from loops.expert.field import Field, TargetField, DateField, StateField, \
TextField, HtmlTextField, UrlField TextField, HtmlTextField, UrlField
from loops.expert.field import SubReport, SubReportField from loops.expert.field import SubReport, SubReportField
from loops.expert.field import TrackDateField, TrackTimeField
from loops.expert.report import ReportInstance from loops.expert.report import ReportInstance
from loops import util from loops import util
@ -50,39 +50,6 @@ class WorkStatementView(ReportConceptView):
# fields # fields
class TrackDateField(Field):
fieldType = 'date'
part = 'date'
format = 'short'
cssClass = 'right'
def getValue(self, row):
value = self.getRawValue(row)
if not value:
return None
return timeStamp2Date(value)
def getDisplayValue(self, row):
value = self.getValue(row)
if value:
view = row.parent.context.view
return formatDate(value, self.part, self.format,
view.languageInfo.language)
return u''
def getSelectValue(self, row):
value = self.getRawValue(row)
if not value:
return ''
return timeStamp2ISO(value)[:10]
class TrackTimeField(TrackDateField):
part = 'time'
class DurationField(Field): class DurationField(Field):
cssClass = 'right' cssClass = 'right'