tracking stats: period details

git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@3123 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2009-01-07 09:28:13 +00:00
parent 88dea1544d
commit 3cc50cccff
3 changed files with 91 additions and 20 deletions

View file

@ -151,6 +151,16 @@ Overview (cumulative) statistics
>>> result['data'] >>> result['data']
[{'access': 2, 'new': 0, 'changed': 1, 'period': '...', 'count': 3}] [{'access': 2, 'new': 0, 'changed': 1, 'period': '...', 'count': 3}]
Changes for a certain period (month)
------------------------------------
>>> input = dict(period='2009-01', select='access')
>>> view = TrackingStats(statQuery, TestRequest(form=input))
>>> result = view.getData()
>>> result['data']
[...]
Recent changes Recent changes
-------------- --------------

View file

@ -21,12 +21,18 @@
<tr tal:repeat="row info/data" <tr tal:repeat="row info/data"
tal:attributes="class python: repeat['row'].odd() and 'even' or 'odd'"> tal:attributes="class python: repeat['row'].odd() and 'even' or 'odd'">
<td tal:content="row/period"></td> <td tal:content="row/period"></td>
<td class="number" <td class="number">
tal:content="row/access"></td> <a tal:omit-tag="python: row['access'] == 0"
<td class="number" tal:attributes="href string:?period=${row/period}&select=access"
tal:content="row/changed"></td> tal:content="row/access" /></td>
<td class="number" <td class="number">
tal:content="row/new"></td> <a tal:omit-tag="python: row['changed'] == 0"
tal:attributes="href string:?period=${row/period}&select=changes"
tal:content="row/changed" /></td>
<td class="number">
<a tal:omit-tag="python: row['new'] == 0"
tal:attributes="href string:?period=${row/period}&select=new"
tal:content="row/new" /></td>
<td class="number" <td class="number"
tal:content="row/count"></td> tal:content="row/count"></td>
</tr> </tr>
@ -34,7 +40,22 @@
</metal:overview> </metal:overview>
<metal:recent define-macro="period">
<h2 i18n:translate="">
Period <span i18n:name="period" tal:content="request/period" />,
<span i18n:name="select" tal:content="request/select" /></h2>
<p><a tal:attributes="href python: request.URL[-1]">
Back to overview</a></p>
<metal:listing use-macro="item/macros/listing" />
</metal:recent>
<metal:recent define-macro="recent_changes"> <metal:recent define-macro="recent_changes">
<metal:listing use-macro="item/macros/listing" />
</metal:recent>
<metal:recent define-macro="listing">
<table class="listing"> <table class="listing">
<tr> <tr>
<th i18n:translate="">Title</th> <th i18n:translate="">Title</th>
@ -43,7 +64,8 @@
tal:condition="view/useVersioning">V</th> tal:condition="view/useVersioning">V</th>
<th i18n:translate="">User</th> <th i18n:translate="">User</th>
<th i18n:translate="">Date/Time</th> <th i18n:translate="">Date/Time</th>
<th i18n:translate="">New</th> <th i18n:translate=""
tal:condition="info/showNewColumn">New</th>
</tr> </tr>
<tr tal:repeat="row info/data" <tr tal:repeat="row info/data"
tal:attributes="class python: repeat['row'].odd() and 'even' or 'odd'"> tal:attributes="class python: repeat['row'].odd() and 'even' or 'odd'">
@ -68,6 +90,7 @@
tal:content="row/user/title" /></td> tal:content="row/user/title" /></td>
<td tal:content="row/timeStamp"></td> <td tal:content="row/timeStamp"></td>
<td class="center" <td class="center"
tal:condition="info/showNewColumn"
tal:content="row/markNew"></td> tal:content="row/markNew"></td>
</tal:row> </tal:row>
</tr> </tr>

View file

@ -23,6 +23,7 @@ $Id$
""" """
from datetime import date, datetime from datetime import date, datetime
import time
from zope import component from zope import component
from zope.app.pagetemplate import ViewPageTemplateFile from zope.app.pagetemplate import ViewPageTemplateFile
from zope.app.security.interfaces import IAuthentication, PrincipalLookupError from zope.app.security.interfaces import IAuthentication, PrincipalLookupError
@ -65,13 +66,21 @@ class TrackingStats(BaseView):
def typeNames(self): def typeNames(self):
return self.options('types') or ['resource:*'] return self.options('types') or ['resource:*']
@Lazy
def accessContainer(self):
return self.loopsRoot.getRecordManager()['access']
@Lazy
def changesContainer(self):
return self.loopsRoot.getRecordManager()['changes']
@Lazy @Lazy
def accessRecords(self): def accessRecords(self):
return self.filter(reversed(self.loopsRoot.getRecordManager()['access'].values())) return self.filter(reversed(self.accessContainer.values()))
@Lazy @Lazy
def changeRecords(self): def changeRecords(self):
return self.filter(reversed(self.loopsRoot.getRecordManager()['changes'].values())) return self.filter(reversed(self.changesContainer.values()))
def filter(self, tracks): def filter(self, tracks):
for tr in tracks: for tr in tracks:
@ -109,17 +118,19 @@ class TrackingStats(BaseView):
form = self.request.form form = self.request.form
period = form.get('period') period = form.get('period')
uid = form.get('id') uid = form.get('id')
if period is not None: select = form.get('select') or 'changes'
result = self.getPeriodDetails(period) if uid is not None:
macroName = 'period' result = self.getObjectDetails(uid, period, select)
elif uid is not None:
result = self.getObjectDetails(uid)
macroName = 'object' macroName = 'object'
elif period is not None:
result = self.getPeriodDetails(period, select)
macroName = 'period'
else: else:
result = self.getOverview() result = self.getOverview()
macroName = 'overview' macroName = 'overview'
macro = self.macros[macroName] macro = self.macros[macroName]
return dict(data=result, macro=macro) return dict(data=result, macro=macro,
showNewColumn=(select in ('changes', 'new')))
def getOverview(self): def getOverview(self):
""" Period-based (monthly) listing of the numbers of object accesses, new, """ Period-based (monthly) listing of the numbers of object accesses, new,
@ -148,12 +159,30 @@ class TrackingStats(BaseView):
num = num - data['new'] num = num - data['new']
return result return result
def getPeriodDetails(period): def getPeriodDetails(self, period, select='changes'):
""" Listing of accessed, new, changed, [deleted] objects during """ Listing of accessed, new, changed, [deleted] objects during
the period given. the period given.
""" """
parts = [int(x) for x in period.split('-')]
parts.append(1)
start = date(*parts)
if parts[1] == 12:
end = date(parts[0] + 1, 1, 1)
else:
end = date(parts[0], parts[1] + 1, 1)
start = int(time.mktime(start.timetuple()))
end = int(time.mktime(end.timetuple()))
if select in ('changes', 'new'):
data = reversed(list(self.filter(
self.changesContainer.query(timeFromTo=(start, end)))))
if select == 'new':
data = [tr for tr in data if tr.data['action'] == 'add']
if select == 'access':
data = reversed(list(self.filter(
self.accessContainer.query(timeFromTo=(start, end)))))
return [TrackDetails(self, tr) for tr in data]
def getObjectDetails(uid, period=None): def getObjectDetails(self, uid, period=None, select='changes'):
""" Listing of (last n?) accesses and changes of the object specified by """ Listing of (last n?) accesses and changes of the object specified by
the uid given, optionally limited to the period (month) given. the uid given, optionally limited to the period (month) given.
""" """
@ -185,7 +214,8 @@ class RecentChanges(TrackingStats):
result.append(track) result.append(track)
continue continue
return dict(data=[TrackDetails(self, tr) for tr in result], return dict(data=[TrackDetails(self, tr) for tr in result],
macro=self.macros['recent_changes']) macro=self.macros['recent_changes'],
showNewColumn=True)
class TrackDetails(BaseView): class TrackDetails(BaseView):
@ -207,6 +237,14 @@ class TrackDetails(BaseView):
self.view.lastMonth = self.month self.view.lastMonth = self.month
return result return result
@Lazy
def day(self):
value = self.formatTimeStamp(self.track.timeStamp, 'date')
if value == self.view.lastDay:
return u''
self.view.lastDay = value
return value
@Lazy @Lazy
def authentication(self): def authentication(self):
return component.getUtility(IAuthentication) return component.getUtility(IAuthentication)
@ -258,11 +296,11 @@ class TrackDetails(BaseView):
#return format.formatDate(value, 'dateTime', self.timeStampFormat, #return format.formatDate(value, 'dateTime', self.timeStampFormat,
# self.view.languageInfo.language) # self.view.languageInfo.language)
def formatTimeStamp(self, ts): def formatTimeStamp(self, ts, f='dateTime'):
if not ts: if not ts:
return u'' return u''
value = datetime.fromtimestamp(ts) value = datetime.fromtimestamp(ts)
return format.formatDate(value, 'dateTime', self.timeStampFormat, return format.formatDate(value, f, self.timeStampFormat,
self.view.languageInfo.language) self.view.languageInfo.language)
def __repr__(self): def __repr__(self):