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:
parent
88dea1544d
commit
3cc50cccff
3 changed files with 91 additions and 20 deletions
|
@ -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
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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):
|
||||||
|
|
Loading…
Add table
Reference in a new issue