forked from shaba/openuds
advancing on a reporting system compatible with python2 & python3
This commit is contained in:
parent
a9844fc8b4
commit
225bf75770
@ -49,19 +49,6 @@ logger = logging.getLogger(__name__)
|
||||
__updated__ = '2018-02-07'
|
||||
|
||||
|
||||
# url fetcher for weasyprint
|
||||
def report_fetcher(url):
|
||||
logger.debug('Getting url for weasyprint {}'.format(url))
|
||||
if url.startswith('stock://'):
|
||||
imagePath = stock.getStockImagePath(url[8:])
|
||||
with open(imagePath, 'rb') as f:
|
||||
image = f.read()
|
||||
return dict(string=image,
|
||||
mime_type='image/png')
|
||||
else:
|
||||
return default_url_fetcher(url)
|
||||
|
||||
|
||||
class Report(UserInterface):
|
||||
mime_type = 'application/pdf' # Report returns pdfs by default, but could be anything else
|
||||
name = _('Base Report') # Report name
|
||||
@ -99,11 +86,30 @@ class Report(UserInterface):
|
||||
return cls.uuid
|
||||
|
||||
@staticmethod
|
||||
def asPDF(html, header=None, water=None):
|
||||
def asPDF(html, header=None, water=None, images=None):
|
||||
"""
|
||||
Renders an html as PDF.
|
||||
Uses the "report.css" as stylesheet
|
||||
"""
|
||||
|
||||
# url fetcher for weasyprint
|
||||
def report_fetcher(url):
|
||||
logger.debug('Getting url for weasyprint {}'.format(url))
|
||||
if url.startswith('stock://'):
|
||||
imagePath = stock.getStockImagePath(url[8:])
|
||||
with open(imagePath, 'rb') as f:
|
||||
image = f.read()
|
||||
return dict(string=image,
|
||||
mime_type='image/png')
|
||||
elif url.startswith('image://'):
|
||||
if isinstance(images, dict):
|
||||
logger.debug('Getting image {} --> {}'.format(url[8:], images.get(url[8:])))
|
||||
img = images.get(url[8:])
|
||||
return dict(string=img,
|
||||
mime_type='image/png')
|
||||
else:
|
||||
return default_url_fetcher(url)
|
||||
|
||||
with open(stock.getStockCssPath('report.css'), 'r') as f:
|
||||
css = f.read()
|
||||
|
||||
@ -121,13 +127,13 @@ class Report(UserInterface):
|
||||
return h.write_pdf(stylesheets=[c])
|
||||
|
||||
@staticmethod
|
||||
def templateAsPDF(templateName, dct, header=None, water=None):
|
||||
def templateAsPDF(templateName, dct, header=None, water=None, images=None):
|
||||
"""
|
||||
Renders a template as PDF
|
||||
"""
|
||||
t = loader.get_template(templateName)
|
||||
|
||||
return Report.asPDF(t.render(dct), header, water)
|
||||
return Report.asPDF(t.render(dct), header=header, water=water, images=images)
|
||||
|
||||
def __init__(self, values=None):
|
||||
"""
|
||||
|
@ -3,7 +3,9 @@
|
||||
@top-center {
|
||||
content: "{header}";
|
||||
vertical-align: bottom;
|
||||
border-bottom: 0.5pt solid
|
||||
border-bottom: 0.5pt solid;
|
||||
font-weight: bolder;
|
||||
|
||||
}
|
||||
@top-right {
|
||||
content: "{page} " counter(page)
|
||||
@ -17,7 +19,7 @@
|
||||
}
|
||||
@left-top {
|
||||
content: "{water}"; font: .5cm/1.5 Fontin Sans;
|
||||
background: #005a9c; color: #fff; text-align: right;
|
||||
background: #557891; color: #fff; text-align: right;
|
||||
padding-right: 2em; height: 1.5em; width: 10cm;
|
||||
transform-origin: 100% 0;
|
||||
transform: rotate(-90deg);
|
||||
@ -38,6 +40,13 @@ body {
|
||||
h1 { bookmark-level: none; }
|
||||
|
||||
tbody tr:nth-child(odd) {
|
||||
background-color: #4C8BF5;
|
||||
color: #fff;
|
||||
background-color: rgb(199, 222, 241);
|
||||
/*color: #fff; */
|
||||
}
|
||||
|
||||
img.center {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
/* width: 50%; */
|
||||
}
|
@ -81,7 +81,10 @@ class ListReportUsers(ListReport):
|
||||
|
||||
return self.templateAsPDF(
|
||||
'uds/reports/lists/users.html',
|
||||
dct={'users': users},
|
||||
dct={
|
||||
'users': users,
|
||||
'auth': auth.name,
|
||||
},
|
||||
header=ugettext('Users List for {}').format(auth.name),
|
||||
water=ugettext('UDS Report of users in {}'.format(auth.name))
|
||||
)
|
||||
|
@ -32,7 +32,7 @@
|
||||
"""
|
||||
|
||||
# from .usage import StatsReportUsage
|
||||
# from .login import StatsReportLogin, StatsReportLoginCSV
|
||||
from .login import StatsReportLogin, StatsReportLoginCSV
|
||||
# from .pool_performance import PoolPerformanceReport
|
||||
# from .usage_by_pool import UsageByPool
|
||||
# from .pools_usage import CountersPoolAssigned
|
||||
|
@ -35,12 +35,11 @@ from __future__ import unicode_literals
|
||||
from django.utils.translation import ugettext_noop as _
|
||||
from uds.core import reports
|
||||
|
||||
|
||||
__updated__ = '2015-06-21'
|
||||
__updated__ = '2018-02-07'
|
||||
|
||||
|
||||
class StatsReport(reports.Report):
|
||||
"""
|
||||
Base report por stats reports
|
||||
Base report for statistics reports
|
||||
"""
|
||||
group = _('Statistics') # So we can make submenus with reports
|
||||
|
@ -36,7 +36,6 @@ from django.utils.translation import ugettext, ugettext_lazy as _
|
||||
import django.template.defaultfilters as filters
|
||||
|
||||
from uds.core.ui.UserInterface import gui
|
||||
from uds.core.reports.tools import UDSImage, UDSGeraldoReport
|
||||
from uds.core.util.stats import events
|
||||
|
||||
import csv
|
||||
@ -48,11 +47,6 @@ import pycha.bar
|
||||
from .base import StatsReport
|
||||
|
||||
from uds.core.util import tools
|
||||
from geraldo.generators.pdf import PDFGenerator
|
||||
from geraldo import ReportBand, ObjectValue, BAND_WIDTH, Label, SubReport
|
||||
from reportlab.lib.units import cm, mm
|
||||
from reportlab.lib.enums import TA_RIGHT, TA_CENTER
|
||||
from PIL import Image as PILImage
|
||||
|
||||
import datetime
|
||||
import six
|
||||
@ -60,65 +54,10 @@ import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
__updated__ = '2017-05-04'
|
||||
__updated__ = '2018-02-07'
|
||||
|
||||
# several constants as Width height, margins, ..
|
||||
WIDTH, HEIGHT = 1800, 1000
|
||||
GERALDO_WIDTH = 120 * mm
|
||||
GERALDO_HEIGHT = GERALDO_WIDTH * HEIGHT / WIDTH
|
||||
|
||||
|
||||
class AccessReport(UDSGeraldoReport):
|
||||
header_elements = []
|
||||
|
||||
class band_detail(ReportBand):
|
||||
height = 400 * mm # Height bigger than a page, so a new page is launched
|
||||
# auto_expand_height = True
|
||||
elements = (
|
||||
Label(text=_('Users access by date'), top=0.6 * cm, left=0, width=BAND_WIDTH,
|
||||
style={'fontName': 'Helvetica-Bold', 'fontSize': 10, 'alignment': TA_CENTER}),
|
||||
UDSImage(left=4 * cm, top=1 * cm,
|
||||
width=GERALDO_WIDTH, height=GERALDO_HEIGHT,
|
||||
get_image=lambda x: x.instance['image']),
|
||||
|
||||
Label(text=_('Users access by day of week'), top=GERALDO_HEIGHT + 1.2 * cm, left=0, width=BAND_WIDTH,
|
||||
style={'fontName': 'Helvetica-Bold', 'fontSize': 10, 'alignment': TA_CENTER}),
|
||||
UDSImage(left=4 * cm, top=GERALDO_HEIGHT + 1.6 * cm,
|
||||
width=GERALDO_WIDTH, height=GERALDO_HEIGHT,
|
||||
get_image=lambda x: x.instance['image2']),
|
||||
|
||||
Label(text=_('Users access by hour'), top=2 * GERALDO_HEIGHT + 2 * cm, left=0, width=BAND_WIDTH,
|
||||
style={'fontName': 'Helvetica-Bold', 'fontSize': 10, 'alignment': TA_CENTER}),
|
||||
UDSImage(left=4 * cm, top=2 * GERALDO_HEIGHT + 2.4 * cm,
|
||||
width=GERALDO_WIDTH, height=GERALDO_HEIGHT,
|
||||
get_image=lambda x: x.instance['image3']),
|
||||
)
|
||||
|
||||
subreports = [
|
||||
SubReport(
|
||||
queryset_string='%(object)s["data"]',
|
||||
band_header=ReportBand(
|
||||
height=1 * cm,
|
||||
auto_expand_height=True,
|
||||
elements=(
|
||||
Label(text=_('Users access by date'), top=0.2 * cm, left=0, width=BAND_WIDTH,
|
||||
style={'fontName': 'Helvetica-Bold', 'fontSize': 12, 'alignment': TA_CENTER}),
|
||||
Label(text=_('Date range'), top=1.0 * cm, left=1.2 * cm,
|
||||
style={'fontName': 'Helvetica-Bold', 'fontSize': 10}),
|
||||
Label(text=_('Users'), top=1.0 * cm, left=14 * cm,
|
||||
style={'fontName': 'Helvetica-Bold', 'fontSize': 10}),
|
||||
),
|
||||
# borders={'bottom': True}
|
||||
),
|
||||
band_detail=ReportBand(
|
||||
height=0.5 * cm,
|
||||
elements=(
|
||||
ObjectValue(attribute_name='date', top=0, left=1.2 * cm, width=12 * cm, style={'fontName': 'Helvetica', 'fontSize': 9}),
|
||||
ObjectValue(attribute_name='users', top=0, left=14 * cm, style={'fontName': 'Helvetica', 'fontSize': 9}),
|
||||
)
|
||||
),
|
||||
)
|
||||
]
|
||||
# several constants as Width height
|
||||
WIDTH, HEIGHT = 1920, 1080
|
||||
|
||||
|
||||
class StatsReportLogin(StatsReport):
|
||||
@ -180,7 +119,7 @@ class StatsReportLogin(StatsReport):
|
||||
|
||||
samplingIntervals = []
|
||||
prevVal = None
|
||||
for val in range(start, end, (end - start) / (samplingPoints + 1)):
|
||||
for val in range(start, end, int((end - start) / (samplingPoints + 1))):
|
||||
if prevVal is None:
|
||||
prevVal = val
|
||||
continue
|
||||
@ -232,6 +171,9 @@ class StatsReportLogin(StatsReport):
|
||||
#
|
||||
# User access by date graph
|
||||
#
|
||||
graph1 = six.BytesIO()
|
||||
graph2 = six.BytesIO()
|
||||
graph3 = six.BytesIO()
|
||||
|
||||
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT) # @UndefinedVariable
|
||||
|
||||
@ -242,7 +184,7 @@ class StatsReportLogin(StatsReport):
|
||||
'axis': {
|
||||
'x': {
|
||||
'ticks': [
|
||||
dict(v=i, label=filters.date(datetime.datetime.fromtimestamp(i), xLabelFormat)) for i in range(start, end, (end - start) / 11)
|
||||
dict(v=i, label=filters.date(datetime.datetime.fromtimestamp(i), xLabelFormat)) for i in range(start, end, int((end - start) / 11))
|
||||
],
|
||||
'range': (start, end),
|
||||
'showLines': True,
|
||||
@ -259,7 +201,7 @@ class StatsReportLogin(StatsReport):
|
||||
'lineColor': '#187FF2'
|
||||
},
|
||||
'colorScheme': {
|
||||
'name': 'gradient',
|
||||
'name': 'rainbow',
|
||||
'args': {
|
||||
'initialColor': '#B8CA16',
|
||||
},
|
||||
@ -285,7 +227,12 @@ class StatsReportLogin(StatsReport):
|
||||
chart.addDataset(dataset)
|
||||
chart.render()
|
||||
|
||||
img = PILImage.frombuffer("RGBA", (surface.get_width(), surface.get_height()), surface.get_data(), "raw", "BGRA", 0, 1)
|
||||
surface.write_to_png(graph1)
|
||||
|
||||
del chart
|
||||
del surface # calls finish, flushing to SVG
|
||||
|
||||
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT) # @UndefinedVariable
|
||||
|
||||
#
|
||||
# User access by day of week
|
||||
@ -313,8 +260,12 @@ class StatsReportLogin(StatsReport):
|
||||
chart.addDataset(dataset)
|
||||
chart.render()
|
||||
|
||||
img2 = PILImage.frombuffer("RGBA", (surface.get_width(), surface.get_height()), surface.get_data(), "raw", "BGRA", 0, 1)
|
||||
surface.write_to_png(graph2)
|
||||
|
||||
del chart
|
||||
del surface # calls finish, flushing to SVG
|
||||
|
||||
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT) # @UndefinedVariable
|
||||
|
||||
# Hourly chart
|
||||
dataset = ((ugettext('Users access to UDS'), [(i, dataHour[i]) for i in range(0, 24)]),)
|
||||
@ -338,25 +289,26 @@ class StatsReportLogin(StatsReport):
|
||||
chart.addDataset(dataset)
|
||||
chart.render()
|
||||
|
||||
img3 = PILImage.frombuffer("RGBA", (surface.get_width(), surface.get_height()), surface.get_data(), "raw", "BGRA", 0, 1)
|
||||
surface.write_to_png(graph3)
|
||||
|
||||
output = six.StringIO()
|
||||
del chart
|
||||
del surface # calls finish, flushing to SVG
|
||||
|
||||
queryset = [
|
||||
{'image': img, 'image2': img2, 'image3': img3, 'data': reportData}
|
||||
]
|
||||
with open('/home/dkmaster/kk/g1.svg', 'wb') as f:
|
||||
f.write(graph1.getvalue())
|
||||
|
||||
logger.debug(queryset)
|
||||
|
||||
try:
|
||||
report = AccessReport(queryset=queryset)
|
||||
report.title = ugettext('Users access to UDS')
|
||||
# report = UsersReport(queryset=users)
|
||||
report.generate_by(PDFGenerator, filename=output)
|
||||
return output.getvalue()
|
||||
except Exception:
|
||||
logger.exception('Errool')
|
||||
return None
|
||||
return self.templateAsPDF(
|
||||
'uds/reports/stats/user-access.html',
|
||||
dct={
|
||||
'data': reportData,
|
||||
'begining': self.startDate.date(),
|
||||
'ending': self.endDate.date(),
|
||||
'intervals': self.samplingPoints.num(),
|
||||
},
|
||||
header=ugettext('Users access to UDS'),
|
||||
water=ugettext('UDS Report for users access'),
|
||||
images={'graph1': graph1.getvalue(), 'graph2': graph2.getvalue(), 'graph3': graph3.getvalue()},
|
||||
)
|
||||
|
||||
|
||||
class StatsReportLoginCSV(StatsReportLogin):
|
||||
@ -373,7 +325,7 @@ class StatsReportLoginCSV(StatsReportLogin):
|
||||
samplingPoints = StatsReportLogin.samplingPoints
|
||||
|
||||
def generate(self):
|
||||
output = StringIO.StringIO()
|
||||
output = six.StringIO()
|
||||
writer = csv.writer(output)
|
||||
|
||||
reportData = self.getRangeData()[2]
|
||||
|
@ -2,6 +2,10 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Users Report</title>
|
||||
<meta name="author" content="UDS">
|
||||
<meta name="description" content="List of UDS users of {{ auth }}">
|
||||
<meta name="keywords" content="uds,report,users,list">
|
||||
<meta name="generator" content="UDS Reporting">
|
||||
</head>
|
||||
<body>
|
||||
<table style="width: 100%; font-size: 0.8em;">
|
||||
|
47
server/src/uds/templates/uds/reports/stats/user-access.html
Normal file
47
server/src/uds/templates/uds/reports/stats/user-access.html
Normal file
@ -0,0 +1,47 @@
|
||||
{% load l10n i18n %}
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Users Access Report</title>
|
||||
<meta name="author" content="UDS">
|
||||
<meta name="description" content="List of UDS accesses from {{ begining }} to {{ ending }} with {{ interval }} intervals">
|
||||
<meta name="keywords" content="uds,report,access">
|
||||
<meta name="generator" content="UDS Reporting">
|
||||
</head>
|
||||
<body>
|
||||
<p style="text-align: center">
|
||||
{% trans "Users Access by date" %}
|
||||
</p>
|
||||
<img src="image://graph1" class="center" style="height: 7.2cm;">
|
||||
<p style="text-align: center">
|
||||
{% trans "Users Access by day of week" %}
|
||||
</p>
|
||||
<img src="image://graph2" class="center" style="height: 7.2cm;">
|
||||
<p style="text-align: center">
|
||||
{% trans "Users Access by hour" %}
|
||||
</p>
|
||||
<img src="image://graph3" class="center" style="height: 7.2cm;">
|
||||
|
||||
<p style="page-break-before: always; text-align: center;">
|
||||
{% trans "Users Access by date" %}
|
||||
</p>
|
||||
<table style="width: 100%; font-size: 0.8em;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 70%">{% trans 'Date range' %}</th>
|
||||
<th style="width: 30%">{% trans 'Users' %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for d in data %}
|
||||
<tr>
|
||||
<td>{{ d.date }}</td>
|
||||
<td>{{ d.users }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<!-- <p style="page-break-before: always">
|
||||
This is a new page
|
||||
</p> -->
|
||||
</body>
|
||||
</html>
|
Loading…
x
Reference in New Issue
Block a user