provide a comments overview listing, e.g. for moderation of comments
This commit is contained in:
parent
f34dc4a59c
commit
2d2240244e
8 changed files with 175 additions and 38 deletions
|
@ -16,6 +16,7 @@
|
|||
<div metal:use-macro="item/report_macros/params" />
|
||||
<div metal:define-macro="buttons">
|
||||
<input type="submit" name="report_execute" value="Execute Report"
|
||||
tal:condition="item/queryFields"
|
||||
i18n:attributes="value" />
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -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
|
||||
# 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.stateful.interfaces import IStateful, IStatesDefinition
|
||||
from cybertools.util.date import timeStamp2Date
|
||||
from cybertools.util.format import formatDate
|
||||
from loops.common import baseObject
|
||||
from loops.expert.report import ReportInstance
|
||||
from loops import util
|
||||
|
@ -209,6 +210,41 @@ class TargetField(RelationField):
|
|||
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
|
||||
|
||||
class SubReport(ReportInstance):
|
||||
|
|
|
@ -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
|
||||
# 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.cachedescriptors.property import Lazy
|
||||
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 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 IReportParams
|
||||
from cybertools.composer.report.result import ResultSet, Row
|
||||
|
@ -53,6 +55,8 @@ class IReport(ILoopsAdapter, IReportParams):
|
|||
source='loops.expert.reportTypeSource',
|
||||
required=True)
|
||||
|
||||
name = Attribute('The name of the report.')
|
||||
|
||||
|
||||
class IReportInstance(IBaseReport):
|
||||
""" The report-type-specific object (an adapter on the report) that
|
||||
|
@ -68,6 +72,10 @@ class Report(AdapterBase):
|
|||
|
||||
_contextAttributes = list(IReport)
|
||||
|
||||
@Lazy
|
||||
def name(self):
|
||||
return getName(self.context)
|
||||
|
||||
TypeInterfaceSourceList.typeInterfaces += (IReport,)
|
||||
|
||||
|
||||
|
@ -79,9 +87,11 @@ class ReportInstance(BaseReport):
|
|||
rowFactory = Row
|
||||
|
||||
view = None # set upon creation
|
||||
#headerRowFactory = Row
|
||||
|
||||
def __init__(self, context):
|
||||
self.context = context
|
||||
self.name = self.type
|
||||
|
||||
def getResultsRenderer(self, name, macros):
|
||||
return macros[name]
|
||||
|
@ -105,6 +115,8 @@ class ReportInstance(BaseReport):
|
|||
if k in crit.parts.keys():
|
||||
crit.parts[k].comparisonValue = v
|
||||
parts = Jeep(crit.parts)
|
||||
if getattr(self, 'limitsCount', ''):
|
||||
limits = None
|
||||
result = list(self.selectObjects(parts)) # may modify parts
|
||||
qc = CompoundQueryCriteria(parts)
|
||||
return ResultSet(self, result, rowFactory=self.rowFactory,
|
||||
|
@ -161,3 +173,15 @@ class DefaultConceptReportInstance(ReportInstance):
|
|||
|
||||
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)
|
||||
|
||||
|
||||
|
|
|
@ -78,6 +78,12 @@ Viewing comments
|
|||
('My comment', u'... ...', u'john')
|
||||
|
||||
|
||||
Reporting
|
||||
=========
|
||||
|
||||
>>> from loops.organize.comment.report import CommentsOverview
|
||||
|
||||
|
||||
Fin de partie
|
||||
=============
|
||||
|
||||
|
|
|
@ -37,4 +37,26 @@
|
|||
factory="loops.organize.comment.browser.CreateComment"
|
||||
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>
|
||||
|
|
6
organize/comment/loops_comment_de.dmp
Normal file
6
organize/comment/loops_comment_de.dmp
Normal 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')
|
75
organize/comment/report.py
Normal file
75
organize/comment/report.py
Normal 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()
|
|
@ -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
|
||||
# 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.organize.interfaces import IWorkItems
|
||||
from cybertools.util.date import timeStamp2Date, timeStamp2ISO
|
||||
from cybertools.util.format import formatDate
|
||||
from cybertools.util.jeep import Jeep
|
||||
from loops.common import adapted, baseObject
|
||||
from loops.expert.browser.report import ReportConceptView
|
||||
from loops.expert.field import Field, TargetField, DateField, StateField, \
|
||||
TextField, HtmlTextField, UrlField
|
||||
from loops.expert.field import SubReport, SubReportField
|
||||
from loops.expert.field import TrackDateField, TrackTimeField
|
||||
from loops.expert.report import ReportInstance
|
||||
from loops import util
|
||||
|
||||
|
@ -50,39 +50,6 @@ class WorkStatementView(ReportConceptView):
|
|||
|
||||
# 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):
|
||||
|
||||
cssClass = 'right'
|
||||
|
|
Loading…
Add table
Reference in a new issue