forked from shaba/openuds
Removing geraldo reports/reportlabs in favor of weasyprint
This commit is contained in:
parent
c9bea9cf78
commit
766786715d
@ -109,13 +109,16 @@ class Reports(model.BaseModelHandler):
|
|||||||
logger.debug('Report: {}'.format(report))
|
logger.debug('Report: {}'.format(report))
|
||||||
result = report.generateEncoded()
|
result = report.generateEncoded()
|
||||||
|
|
||||||
return {
|
data = {
|
||||||
'mime_type': report.mime_type,
|
'mime_type': report.mime_type,
|
||||||
'encoded': report.encoded,
|
'encoded': report.encoded,
|
||||||
'filename': report.filename,
|
'filename': report.filename,
|
||||||
'data': result
|
'data': result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.debug('Data: {}'.format(data))
|
||||||
|
|
||||||
|
return data
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception('Generating report')
|
logger.exception('Generating report')
|
||||||
return self.invalidRequestException(six.text_type(e))
|
return self.invalidRequestException(six.text_type(e))
|
||||||
|
@ -33,17 +33,20 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.utils.translation import ugettext, ugettext_noop as _
|
from django.utils.translation import ugettext, ugettext_noop as _
|
||||||
|
from django.template import loader
|
||||||
|
|
||||||
from uds.core.ui.UserInterface import UserInterface
|
from uds.core.ui.UserInterface import UserInterface
|
||||||
from uds.core.util import encoders
|
from uds.core.util import encoders
|
||||||
|
from . import stock
|
||||||
|
|
||||||
import datetime
|
|
||||||
import six
|
import six
|
||||||
|
from weasyprint import HTML, CSS
|
||||||
|
from datetime import datetime
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
__updated__ = '2017-11-15'
|
__updated__ = '2018-02-07'
|
||||||
|
|
||||||
|
|
||||||
class Report(UserInterface):
|
class Report(UserInterface):
|
||||||
@ -82,6 +85,46 @@ class Report(UserInterface):
|
|||||||
raise Exception('Class does not includes an uuid!!!: {}'.format(cls))
|
raise Exception('Class does not includes an uuid!!!: {}'.format(cls))
|
||||||
return cls.uuid
|
return cls.uuid
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def asPDF(html, header=None, water=None):
|
||||||
|
"""
|
||||||
|
Renders an html as PDF.
|
||||||
|
Uses the "report.css" as stylesheet
|
||||||
|
"""
|
||||||
|
with open(stock.getStockCssPath('report.css'), 'r') as f:
|
||||||
|
css = f.read()
|
||||||
|
|
||||||
|
css = (
|
||||||
|
css.replace("{header}", _('Report') if header is None else header)
|
||||||
|
.replace('{page}', _('Page'))
|
||||||
|
.replace('{of}', _('of'))
|
||||||
|
.replace('{water}', 'UDS Enterprise' if water is None else water)
|
||||||
|
.replace('{printed}', _('Printed in {now:%Y, %b %d} at {now:%H:%M}').format(now=datetime.now()))
|
||||||
|
)
|
||||||
|
|
||||||
|
h = HTML(string=html)
|
||||||
|
c = CSS(string=css)
|
||||||
|
|
||||||
|
pdf = h.write_pdf(stylesheets=[c])
|
||||||
|
|
||||||
|
with open('/home/dkmaster/kk/kk.pdf', 'wb') as f:
|
||||||
|
f.write(pdf)
|
||||||
|
|
||||||
|
return pdf
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def templateAsPDF(templateName, dct, header=None, water=None):
|
||||||
|
"""
|
||||||
|
Renders a template as PDF
|
||||||
|
"""
|
||||||
|
t = loader.get_template(templateName)
|
||||||
|
|
||||||
|
renderedHtml = t.render(dct)
|
||||||
|
|
||||||
|
logger.debug('HTML: {}'.format(renderedHtml))
|
||||||
|
|
||||||
|
return Report.asPDF(renderedHtml, header, water)
|
||||||
|
|
||||||
def __init__(self, values=None):
|
def __init__(self, values=None):
|
||||||
"""
|
"""
|
||||||
Do not forget to invoke this in your derived class using
|
Do not forget to invoke this in your derived class using
|
||||||
@ -127,10 +170,14 @@ class Report(UserInterface):
|
|||||||
Basically calls generate and encodes resuslt as base64
|
Basically calls generate and encodes resuslt as base64
|
||||||
"""
|
"""
|
||||||
data = self.generate()
|
data = self.generate()
|
||||||
|
with open('/home/dkmaster/kk/kk2.pdf', 'wb') as f:
|
||||||
|
f.write(data)
|
||||||
if self.encoded:
|
if self.encoded:
|
||||||
return encoders.encode(data, 'base64', asText=True).replace('\n', '')
|
data = encoders.encode(data, 'base64', asText=True).replace('\n', '')
|
||||||
else:
|
with open('/home/dkmaster/kk/kk2.base64', 'w') as f:
|
||||||
return data
|
f.write(data)
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return 'Report {} with uuid {}'.format(self.name, self.uuid)
|
return 'Report {} with uuid {}'.format(self.name, self.uuid)
|
||||||
|
32
server/src/uds/core/reports/css/report.css
Normal file
32
server/src/uds/core/reports/css/report.css
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
@page {
|
||||||
|
margin: 3cm 2cm; padding-left: 1.5cm;
|
||||||
|
@top-center {
|
||||||
|
content: "{header}";
|
||||||
|
vertical-align: bottom;
|
||||||
|
border-bottom: 0.5pt solid
|
||||||
|
}
|
||||||
|
@top-right {
|
||||||
|
content: "{page} " counter(page)
|
||||||
|
" {of} " counter(pages)
|
||||||
|
}
|
||||||
|
@bottom-left {
|
||||||
|
content: "Generated by UDS"
|
||||||
|
}
|
||||||
|
@bottom-right {
|
||||||
|
content: '{printed}'
|
||||||
|
}
|
||||||
|
@left-top {
|
||||||
|
content: "{water}"; font: .5cm/1.5 Fontin Sans;
|
||||||
|
background: #005a9c; color: #fff; text-align: right;
|
||||||
|
padding-right: 2em; height: 1.5em; width: 10cm;
|
||||||
|
transform-origin: 100% 0;
|
||||||
|
transform: rotate(-90deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
body { text-align: justify }
|
||||||
|
h1 { bookmark-level: none }
|
||||||
|
|
||||||
|
tbody tr:nth-child(odd) {
|
||||||
|
background-color: #4C8BF5;
|
||||||
|
color: #fff;
|
||||||
|
}
|
@ -39,10 +39,19 @@ import logging
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
__updated__ = '2015-04-29'
|
__updated__ = '2018-02-07'
|
||||||
|
|
||||||
LOGO = 'logo-512.png'
|
LOGO = 'logo-512.png'
|
||||||
|
CSS = 'report.css'
|
||||||
|
|
||||||
|
|
||||||
def getStockImagePath(stockImg):
|
def getStockImagePath(stockImg=None):
|
||||||
|
if stockImg is None:
|
||||||
|
stockImg = LOGO
|
||||||
return tools.packageRelativeFile(__name__, 'stock_images/' + stockImg)
|
return tools.packageRelativeFile(__name__, 'stock_images/' + stockImg)
|
||||||
|
|
||||||
|
|
||||||
|
def getStockCssPath(css=None):
|
||||||
|
if css is None:
|
||||||
|
css = CSS
|
||||||
|
return tools.packageRelativeFile(__name__, 'css/' + css)
|
||||||
|
@ -46,8 +46,7 @@ import logging
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
__updated__ = '2017-05-10'
|
__updated__ = '2018-02-07'
|
||||||
|
|
||||||
|
|
||||||
availableReports = []
|
availableReports = []
|
||||||
|
|
||||||
@ -78,10 +77,10 @@ def __init__():
|
|||||||
# Dinamycally import children of this package. The __init__.py files must import classes
|
# Dinamycally import children of this package. The __init__.py files must import classes
|
||||||
pkgpath = os.path.dirname(sys.modules[__name__].__file__)
|
pkgpath = os.path.dirname(sys.modules[__name__].__file__)
|
||||||
# TODO: Make this work with python3 also!!! (look for alternative, we have time...)
|
# TODO: Make this work with python3 also!!! (look for alternative, we have time...)
|
||||||
if six.PY2:
|
for _, name, _ in pkgutil.iter_modules([pkgpath]):
|
||||||
for _, name, _ in pkgutil.iter_modules([pkgpath]):
|
__import__(name, globals(), locals(), [], 1)
|
||||||
__import__(name, globals(), locals(), [], 1)
|
|
||||||
|
|
||||||
recursiveAdd(reports.Report)
|
recursiveAdd(reports.Report)
|
||||||
|
|
||||||
|
|
||||||
__init__()
|
__init__()
|
||||||
|
@ -34,7 +34,6 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
from django.utils.translation import ugettext, ugettext_lazy as _
|
from django.utils.translation import ugettext, ugettext_lazy as _
|
||||||
from uds.core.ui.UserInterface import gui
|
from uds.core.ui.UserInterface import gui
|
||||||
from uds.core.reports import stock
|
|
||||||
from uds.models import Authenticator
|
from uds.models import Authenticator
|
||||||
|
|
||||||
import six
|
import six
|
||||||
@ -42,62 +41,11 @@ import csv
|
|||||||
|
|
||||||
from .base import ListReport
|
from .base import ListReport
|
||||||
|
|
||||||
from geraldo.generators.pdf import PDFGenerator
|
|
||||||
from geraldo import Report, landscape, ReportBand, ObjectValue, SystemField, BAND_WIDTH, Label, Image
|
|
||||||
from reportlab.lib.pagesizes import A4
|
|
||||||
from reportlab.lib.units import cm
|
|
||||||
from reportlab.lib.enums import TA_RIGHT, TA_CENTER
|
|
||||||
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
__updated__ = '2015-06-21'
|
__updated__ = '2018-02-07'
|
||||||
|
|
||||||
|
|
||||||
class UsersReport(Report):
|
|
||||||
title = ''
|
|
||||||
author = 'UDS'
|
|
||||||
|
|
||||||
print_if_empty = True
|
|
||||||
page_size = A4
|
|
||||||
margin_left = 2 * cm
|
|
||||||
margin_top = 0.5 * cm
|
|
||||||
margin_right = 0.5 * cm
|
|
||||||
margin_bottom = 0.5 * cm
|
|
||||||
|
|
||||||
class band_detail(ReportBand):
|
|
||||||
height = 0.5 * cm
|
|
||||||
elements = (
|
|
||||||
ObjectValue(attribute_name='name', left=0.5 * cm, style={'fontName': 'Helvetica', 'fontSize': 8}),
|
|
||||||
ObjectValue(attribute_name='real_name', left=6 * cm, style={'fontName': 'Helvetica', 'fontSize': 8}),
|
|
||||||
ObjectValue(attribute_name='last_access', left=15 * cm, style={'fontName': 'Helvetica', 'fontSize': 8}),
|
|
||||||
)
|
|
||||||
|
|
||||||
class band_page_header(ReportBand):
|
|
||||||
height = 2.0 * cm
|
|
||||||
elements = [
|
|
||||||
SystemField(expression='%(report_title)s', top=0.5 * cm, left=0, width=BAND_WIDTH,
|
|
||||||
style={'fontName': 'Helvetica-Bold', 'fontSize': 14, 'alignment': TA_CENTER}),
|
|
||||||
|
|
||||||
Label(text=_('User ID'), top=1.5 * cm, left=0.5 * cm),
|
|
||||||
Label(text=_('Real Name'), top=1.5 * cm, left=6 * cm),
|
|
||||||
Label(text=_('Last access'), top=1.5 * cm, left=15 * cm),
|
|
||||||
SystemField(expression=_('Page %(page_number)d of %(page_count)d'), top=0.1 * cm,
|
|
||||||
width=BAND_WIDTH, style={'alignment': TA_RIGHT}),
|
|
||||||
Image(filename=stock.getStockImagePath(stock.LOGO), left=0.1 * cm, top=0.0 * cm, width=2 * cm, height=2 * cm),
|
|
||||||
]
|
|
||||||
borders = {'bottom': True}
|
|
||||||
|
|
||||||
class band_page_footer(ReportBand):
|
|
||||||
height = 0.5 * cm
|
|
||||||
elements = [
|
|
||||||
Label(text='Generated by UDS', top=0.1 * cm),
|
|
||||||
SystemField(expression=_('Printed in %(now:%Y, %b %d)s at %(now:%H:%M)s'), top=0.1 * cm,
|
|
||||||
width=BAND_WIDTH, style={'alignment': TA_RIGHT}),
|
|
||||||
]
|
|
||||||
borders = {'top': True}
|
|
||||||
|
|
||||||
|
|
||||||
class ListReportUsers(ListReport):
|
class ListReportUsers(ListReport):
|
||||||
@ -131,12 +79,12 @@ class ListReportUsers(ListReport):
|
|||||||
auth = Authenticator.objects.get(uuid=self.authenticator.value)
|
auth = Authenticator.objects.get(uuid=self.authenticator.value)
|
||||||
users = auth.users.order_by('name')
|
users = auth.users.order_by('name')
|
||||||
|
|
||||||
output = six.StringIO()
|
return self.templateAsPDF(
|
||||||
|
'uds/reports/lists/users.html',
|
||||||
report = UsersReport(queryset=users)
|
dct={'users': users},
|
||||||
report.title = _('Users List for {}').format(auth.name)
|
header=ugettext('Users List for {}').format(auth.name),
|
||||||
report.generate_by(PDFGenerator, filename=output)
|
water=auth.name
|
||||||
return output.getvalue()
|
)
|
||||||
|
|
||||||
|
|
||||||
class ListReportsUsersCSV(ListReportUsers):
|
class ListReportsUsersCSV(ListReportUsers):
|
||||||
@ -154,7 +102,7 @@ class ListReportsUsersCSV(ListReportUsers):
|
|||||||
self.filename = auth.name + '.csv'
|
self.filename = auth.name + '.csv'
|
||||||
|
|
||||||
def generate(self):
|
def generate(self):
|
||||||
output = StringIO.StringIO()
|
output = six.StringIO()
|
||||||
writer = csv.writer(output)
|
writer = csv.writer(output)
|
||||||
auth = Authenticator.objects.get(uuid=self.authenticator.value)
|
auth = Authenticator.objects.get(uuid=self.authenticator.value)
|
||||||
users = auth.users.order_by('name')
|
users = auth.users.order_by('name')
|
||||||
|
@ -31,10 +31,10 @@
|
|||||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from .usage import StatsReportUsage
|
# from .usage import StatsReportUsage
|
||||||
from .login import StatsReportLogin, StatsReportLoginCSV
|
# from .login import StatsReportLogin, StatsReportLoginCSV
|
||||||
from .pool_performance import PoolPerformanceReport
|
# from .pool_performance import PoolPerformanceReport
|
||||||
from .usage_by_pool import UsageByPool
|
# from .usage_by_pool import UsageByPool
|
||||||
from .pools_usage import CountersPoolAssigned
|
# from .pools_usage import CountersPoolAssigned
|
||||||
from .usage_summary_pool import UsageSummaryByPool
|
# from .usage_summary_pool import UsageSummaryByPool
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# jshint strict: true
|
# jshint strict: true
|
||||||
gui.reports = new GuiElement(api.reports, "reports")
|
gui.reports = new GuiElement(api.reports, "reports")
|
||||||
gui.reports.link = (event) ->
|
gui.reports.link = (event) ->
|
||||||
"use strict"
|
"use strict"
|
||||||
@ -9,7 +9,7 @@ gui.reports.link = (event) ->
|
|||||||
reports: "reports-placeholder"
|
reports: "reports-placeholder"
|
||||||
)
|
)
|
||||||
gui.setLinksEvents()
|
gui.setLinksEvents()
|
||||||
|
|
||||||
tableId = gui.reports.table(
|
tableId = gui.reports.table(
|
||||||
icon: 'reports'
|
icon: 'reports'
|
||||||
container: "reports-placeholder"
|
container: "reports-placeholder"
|
||||||
@ -43,14 +43,18 @@ gui.reports.link = (event) ->
|
|||||||
closeFnc()
|
closeFnc()
|
||||||
gui.doLog data
|
gui.doLog data
|
||||||
if data.encoded
|
if data.encoded
|
||||||
|
gui.doLog('Data is encoded')
|
||||||
content = base64.decode(data.data)
|
content = base64.decode(data.data)
|
||||||
|
gui.doLog('Length: ' + content.length)
|
||||||
else
|
else
|
||||||
content = data.data
|
content = data.data
|
||||||
setTimeout( (()->
|
setTimeout( (()->
|
||||||
|
byteContent = new Uint8Array(content.length)
|
||||||
|
byteContent[i] = content.charCodeAt(i) for i in [0..content.length-1]
|
||||||
|
|
||||||
|
blob = new Blob([byteContent], type: data.content_type)
|
||||||
saveAs(
|
saveAs(
|
||||||
new Blob([content],
|
blob,
|
||||||
type: data.content_type
|
|
||||||
),
|
|
||||||
data.filename
|
data.filename
|
||||||
)
|
)
|
||||||
), 100)
|
), 100)
|
||||||
@ -83,4 +87,4 @@ gui.reports.link = (event) ->
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
false
|
false
|
||||||
|
49
server/src/uds/templates/uds/reports/lists/users.html
Normal file
49
server/src/uds/templates/uds/reports/lists/users.html
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>Report test</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="content">
|
||||||
|
<table style="width: 100%">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Age</th>
|
||||||
|
<th>Parent</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>name of person</td>
|
||||||
|
<td>123</td>
|
||||||
|
<td>his</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>name of person 2</td>
|
||||||
|
<td>123 2</td>
|
||||||
|
<td>his 2</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>name of person 3</td>
|
||||||
|
<td>123 3</td>
|
||||||
|
<td>his </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>name of person 4</td>
|
||||||
|
<td>123 4</td>
|
||||||
|
<td>his 4</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>name of person 5</td>
|
||||||
|
<td>123 5</td>
|
||||||
|
<td>his 5</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p style="page-break-before: always">
|
||||||
|
This is a new page
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
x
Reference in New Issue
Block a user