107 lines
5.0 KiB
Python
107 lines
5.0 KiB
Python
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
import re
|
|
from urllib.parse import quote
|
|
from werkzeug.exceptions import BadRequest
|
|
|
|
from odoo.http import request, route, STATIC_CACHE_LONG
|
|
from odoo.addons.documents.controllers.documents import ShareRoute
|
|
from odoo.addons.spreadsheet.utils.json import extend_serialized_json
|
|
from odoo.tools import replace_exceptions
|
|
|
|
# ends with .osheet.json or .osheet (6).json
|
|
SPREADSHEET_RE = re.compile(r'\.osheet(\s?\(\d+\))?\.json$')
|
|
|
|
class SpreadsheetShareRoute(ShareRoute):
|
|
def _documents_render_public_view(self, document_sudo):
|
|
if document_sudo.handler in ("spreadsheet", "frozen_spreadsheet"):
|
|
return self._documents_render_portal_view(document_sudo)
|
|
|
|
return super()._documents_render_public_view(document_sudo)
|
|
|
|
def _documents_render_portal_view(self, document):
|
|
if document.handler not in ("spreadsheet", "frozen_spreadsheet"):
|
|
return super()._documents_render_portal_view(document)
|
|
|
|
# check if the spreadsheet contains "live data", if yes the rendering will fail
|
|
if document._contains_live_data():
|
|
return request.render("documents_spreadsheet.documents_error_live_data")
|
|
|
|
return request.render(
|
|
"spreadsheet.public_spreadsheet_layout",
|
|
{
|
|
"spreadsheet_name": document.name,
|
|
"share": document,
|
|
"is_frozen": document.handler == "frozen_spreadsheet",
|
|
"session_info": request.env["ir.http"].session_info(),
|
|
"props": {
|
|
"dataUrl": f"/documents/spreadsheet/{quote(document.access_token, safe='')}",
|
|
"downloadExcelUrl": "",
|
|
},
|
|
},
|
|
)
|
|
|
|
def _documents_content_stream(self, document_sudo):
|
|
"""
|
|
Use the ``excel_export`` field instead of ``raw`` when
|
|
downloading frozen spreadsheets.
|
|
"""
|
|
if document_sudo.handler == 'frozen_spreadsheet':
|
|
return request.env['ir.binary']._get_stream_from(document_sudo, 'excel_export')
|
|
elif document_sudo.handler == 'spreadsheet':
|
|
raise ValueError("non-frozen spreadsheets have no content")
|
|
return super()._documents_content_stream(document_sudo)
|
|
|
|
@route('/documents/spreadsheet/<access_token>', type='http', auth='public', readonly=True)
|
|
def documents_spreadsheet(self, access_token):
|
|
"""Download the spreadsheet data for the readonly view."""
|
|
document_sudo = self._from_access_token(access_token, skip_log=True)
|
|
if not document_sudo:
|
|
raise request.not_found()
|
|
|
|
# handcraft the json response body, avoiding the need for parsing and re-serializing
|
|
# the spreadsheet file and the revisions, which can be expensive for large files.
|
|
spreadsheet_data = document_sudo._get_spreadsheet_serialized_snapshot()
|
|
serialized_revisions = ','.join(document_sudo._get_spreadsheet_serialized_revisions())
|
|
body = extend_serialized_json(spreadsheet_data, [('revisions', '[%s]' % serialized_revisions)])
|
|
headers = [
|
|
('Content-Length', len(body)),
|
|
('Content-Type', 'application/json; charset=utf-8'),
|
|
]
|
|
return request.make_response(body, headers)
|
|
|
|
def _documents_upload_create_write(self, *args, **kwargs):
|
|
"""Set the correct handler when uploading a spreadsheet"""
|
|
document_sudo = super()._documents_upload_create_write(*args, **kwargs)
|
|
if (document_sudo.name
|
|
and SPREADSHEET_RE.search(document_sudo.name)
|
|
and document_sudo.mimetype == 'application/json'
|
|
):
|
|
document_sudo.handler = 'spreadsheet'
|
|
document_sudo._check_spreadsheet_data()
|
|
return document_sudo
|
|
|
|
@route(['/documents/display_thumbnail/<access_token>',
|
|
'/documents/display_thumbnail/<access_token>/<int:width>x<int:height>'],
|
|
type='http', auth='public', readonly=True)
|
|
def documents_display_thumbnail(self, access_token, width='0', height='0', unique=''):
|
|
"""Show the thumbnail of the document, or a placeholder.
|
|
|
|
:param access_token: the access token to the document record
|
|
:param width: resize the thumbnail to this maximum width
|
|
:param height: resize the thumbnail to this maximum height
|
|
:param unique: force storing the file in the browser cache, best
|
|
used with the checksum of the attachment
|
|
"""
|
|
with replace_exceptions(ValueError, by=BadRequest):
|
|
width = int(width)
|
|
height = int(height)
|
|
send_file_kwargs = {}
|
|
if unique:
|
|
send_file_kwargs['immutable'] = True
|
|
send_file_kwargs['max_age'] = STATIC_CACHE_LONG
|
|
spreadsheet_sudo = self._from_access_token(access_token, skip_log=True)
|
|
return request.env['ir.binary']._get_image_stream_from(
|
|
spreadsheet_sudo, 'display_thumbnail', width=width, height=height
|
|
).get_response(as_attachment=False, **send_file_kwargs)
|