[IMP] base: assets now directly use /web/content url
This commit is contained in:
committed by
Christophe Simonis
parent
952b03e32d
commit
522fcacb21
@@ -1,10 +1,22 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from openerp import http, _
|
||||
from openerp.http import request
|
||||
from openerp.addons.base.ir.ir_qweb import AssetsBundle
|
||||
from openerp.addons.web.controllers.main import binary_content
|
||||
import base64
|
||||
|
||||
|
||||
class LivechatController(http.Controller):
|
||||
|
||||
@http.route('/im_livechat/external_lib.<any(css,js):ext>', type='http', auth='none')
|
||||
def livechat_lib(self, xmlid, ext, **kwargs):
|
||||
asset = AssetsBundle("im_livechat.external_lib")
|
||||
# can't use /web/content directly because we don't have attachment ids (attachments must be created)
|
||||
status, headers, content = binary_content(id=getattr(asset, ext)().id, unique=asset.checksum)
|
||||
content_base64 = base64.b64decode(content)
|
||||
headers.append(('Content-Length', len(content_base64)))
|
||||
return request.make_response(content_base64, headers)
|
||||
|
||||
@http.route('/im_livechat/support/<int:channel_id>', type='http', auth='public')
|
||||
def support_page(self, channel_id, **kwargs):
|
||||
channel = request.env['im_livechat.channel'].sudo().browse(channel_id)
|
||||
|
||||
@@ -87,9 +87,9 @@
|
||||
-->
|
||||
<template id="external_loader" name="Livechat : external_script field of livechat channel">
|
||||
<!-- css style -->
|
||||
<link t-att-href="'%s/web/css/im_livechat.external_lib' % (url)" rel="stylesheet"/>
|
||||
<link t-att-href="'%s/im_livechat/external_lib.css' % (url)" rel="stylesheet"/>
|
||||
<!-- js of all the required lib (internal and external) -->
|
||||
<script t-att-src="'%s/web/js/im_livechat.external_lib' % (url)" type="text/javascript"/>
|
||||
<script t-att-src="'%s/im_livechat/external_lib.js' % (url)" type="text/javascript" />
|
||||
<!-- the loader -->
|
||||
<script t-att-src="'%s/im_livechat/loader/%i' % (url, channel_id)" type="text/javascript"/>
|
||||
</template>
|
||||
|
||||
@@ -121,11 +121,10 @@
|
||||
<div class="oe_kanban_global_click">
|
||||
<div class="oe_kanban_vignette">
|
||||
<div class="oe_attachment">
|
||||
<div t-if="!record.url.value">
|
||||
<div class="o_image" t-att-data-mimetype="record.mimetype.value" t-attf-data-src="/web/image/#{record.id}/100x80"/>
|
||||
</div>
|
||||
<div t-if="record.url.value">
|
||||
<img t-att-src="record.url.value"/>
|
||||
<div>
|
||||
<t t-set="webimage" t-value="new RegExp('image.*(gif|jpe|jpg|png)').test(record.mimetype.value)"/>
|
||||
<div t-if="!webimage" class="o_image" t-att-data-mimetype="record.mimetype.value"/>
|
||||
<img t-if="webimage" t-att-src="record.url.value"/>
|
||||
</div>
|
||||
<div class="oe_name">
|
||||
<field name="name"/>
|
||||
|
||||
@@ -480,7 +480,7 @@ def binary_content(xmlid=None, model='ir.attachment', id=None, field='datas', un
|
||||
|
||||
# mimetype
|
||||
if not mimetype:
|
||||
if 'mimetype' in obj and obj.mimetype:
|
||||
if 'mimetype' in obj and obj.mimetype and obj.mimetype != 'application/octet-stream':
|
||||
mimetype = obj.mimetype
|
||||
elif filename:
|
||||
mimetype = mimetypes.guess_type(filename)[0]
|
||||
@@ -570,33 +570,6 @@ class Home(http.Controller):
|
||||
return werkzeug.utils.redirect('/', 303)
|
||||
return login_and_redirect(db, login, key, redirect_url=redirect)
|
||||
|
||||
@http.route([
|
||||
'/web/js/<xmlid>',
|
||||
'/web/js/<xmlid>/<version>',
|
||||
], type='http', auth='public')
|
||||
def js_bundle(self, xmlid, version=None, **kw):
|
||||
try:
|
||||
bundle = AssetsBundle(xmlid)
|
||||
except QWebTemplateNotFound:
|
||||
return request.not_found()
|
||||
|
||||
response = request.make_response(bundle.js(), [('Content-Type', 'application/javascript')])
|
||||
return make_conditional(response, bundle.last_modified, max_age=BUNDLE_MAXAGE)
|
||||
|
||||
@http.route([
|
||||
'/web/css/<xmlid>',
|
||||
'/web/css/<xmlid>/<version>',
|
||||
'/web/css.<int:page>/<xmlid>/<version>',
|
||||
], type='http', auth='public')
|
||||
def css_bundle(self, xmlid, version=None, page=None, **kw):
|
||||
try:
|
||||
bundle = AssetsBundle(xmlid)
|
||||
except QWebTemplateNotFound:
|
||||
return request.not_found()
|
||||
|
||||
response = request.make_response(bundle.css(page), [('Content-Type', 'text/css')])
|
||||
return make_conditional(response, bundle.last_modified, max_age=BUNDLE_MAXAGE)
|
||||
|
||||
class WebClient(http.Controller):
|
||||
|
||||
@http.route('/web/webclient/csslist', type='json', auth="none")
|
||||
@@ -1064,6 +1037,8 @@ class Binary(http.Controller):
|
||||
'/web/content/<string:xmlid>/<string:filename>',
|
||||
'/web/content/<int:id>',
|
||||
'/web/content/<int:id>/<string:filename>',
|
||||
'/web/content/<int:id>-<string:unique>',
|
||||
'/web/content/<int:id>-<string:unique>/<string:filename>',
|
||||
'/web/content/<string:model>/<int:id>/<string:field>',
|
||||
'/web/content/<string:model>/<int:id>/<string:field>/<string:filename>'], type='http', auth="public")
|
||||
def content_common(self, xmlid=None, model='ir.attachment', id=None, field='datas', filename=None, filename_field='datas_fname', unique=None, mimetype=None, download=None, data=None, token=None):
|
||||
@@ -1085,14 +1060,18 @@ class Binary(http.Controller):
|
||||
'/web/image/<string:xmlid>/<string:filename>',
|
||||
'/web/image/<string:xmlid>/<int:width>x<int:height>',
|
||||
'/web/image/<string:xmlid>/<int:width>x<int:height>/<string:filename>',
|
||||
'/web/image/<int:id>',
|
||||
'/web/image/<int:id>/<string:filename>',
|
||||
'/web/image/<string:model>/<int:id>/<string:field>',
|
||||
'/web/image/<string:model>/<int:id>/<string:field>/<string:filename>',
|
||||
'/web/image/<string:model>/<int:id>/<string:field>/<int:width>x<int:height>',
|
||||
'/web/image/<string:model>/<int:id>/<string:field>/<int:width>x<int:height>/<string:filename>',
|
||||
'/web/image/<int:id>',
|
||||
'/web/image/<int:id>/<string:filename>',
|
||||
'/web/image/<int:id>/<int:width>x<int:height>',
|
||||
'/web/image/<int:id>/<int:width>x<int:height>/<string:filename>',
|
||||
'/web/image/<string:model>/<int:id>/<string:field>/<int:width>x<int:height>',
|
||||
'/web/image/<string:model>/<int:id>/<string:field>/<int:width>x<int:height>/<string:filename>'], type='http', auth="public")
|
||||
'/web/image/<int:id>-<string:unique>',
|
||||
'/web/image/<int:id>-<string:unique>/<string:filename>',
|
||||
'/web/image/<int:id>-<string:unique>/<int:width>x<int:height>',
|
||||
'/web/image/<int:id>-<string:unique>/<int:width>x<int:height>/<string:filename>'], type='http', auth="public")
|
||||
def content_image(self, xmlid=None, model='ir.attachment', id=None, field='datas', filename_field='datas_fname', unique=None, filename=None, mimetype=None, download=None, width=0, height=0):
|
||||
status, headers, content = binary_content(xmlid=xmlid, model=model, id=id, field=field, unique=unique, filename=filename, filename_field=filename_field, download=download, mimetype=mimetype, default_mimetype='image/png')
|
||||
if status == 304:
|
||||
|
||||
@@ -476,7 +476,7 @@
|
||||
'data-disable' (optional) to unchecked one or more HTML ids, or list separate by comma
|
||||
'data-reload="/"' (optional) force the reloading of the page if the url match with
|
||||
the string ( = regexp).
|
||||
Otherwise, only the '/web/css/website.assets_frontend' is reloaded
|
||||
Otherwise, only the '/web/content/website.assets_frontend' is reloaded
|
||||
|
||||
For the sets (data-enable and/or data-disable without data-xmlid), the set is
|
||||
automatically checked if:
|
||||
|
||||
@@ -451,11 +451,3 @@ class ir_attachment(osv.osv):
|
||||
def action_get(self, cr, uid, context=None):
|
||||
return self.pool.get('ir.actions.act_window').for_xml_id(
|
||||
cr, uid, 'base', 'action_attachment', context=context)
|
||||
|
||||
def invalidate_bundle(self, cr, uid, type='%', xmlid=None, context=None):
|
||||
assert type in ('%', 'css', 'js'), "Unhandled bundle type"
|
||||
xmlid = '%' if xmlid is None else xmlid + '%'
|
||||
domain = [('url', '=like', '/web/%s/%s/%%' % (type, xmlid))]
|
||||
ids = self.search(cr, uid, domain, context=context)
|
||||
if ids:
|
||||
self.unlink(cr, uid, ids, context=context)
|
||||
|
||||
@@ -1166,7 +1166,7 @@ class AssetsBundle(object):
|
||||
raise NotImplementedError
|
||||
|
||||
def can_aggregate(self, url):
|
||||
return not urlparse(url).netloc and not url.startswith(('/web/css', '/web/js'))
|
||||
return not urlparse(url).netloc and not url.startswith('/web/content')
|
||||
|
||||
def to_html(self, sep=None, css=True, js=True, debug=False, async=False):
|
||||
if sep is None:
|
||||
@@ -1186,16 +1186,10 @@ class AssetsBundle(object):
|
||||
else:
|
||||
url_for = self.context.get('url_for', lambda url: url)
|
||||
if css and self.stylesheets:
|
||||
suffix = ''
|
||||
if request:
|
||||
ua = request.httprequest.user_agent
|
||||
if ua.browser == "msie" and int((ua.version or '0').split('.')[0]) < 10:
|
||||
suffix = '.0'
|
||||
href = '/web/css%s/%s/%s' % (suffix, self.xmlid, self.version)
|
||||
response.append('<link href="%s" rel="stylesheet"/>' % url_for(href))
|
||||
if js:
|
||||
src = '/web/js/%s/%s' % (self.xmlid, self.version)
|
||||
response.append('<script %s type="text/javascript" src="%s"></script>' % (async and 'async="async"' or '', url_for(src)))
|
||||
for attachment in self.css():
|
||||
response.append('<link href="%s" rel="stylesheet"/>' % url_for(attachment.url))
|
||||
if js and self.javascripts:
|
||||
response.append('<script %s type="text/javascript" src="%s"></script>' % (async and 'async="async"' or '', url_for(self.js().url)))
|
||||
response.extend(self.remains)
|
||||
return sep + sep.join(response)
|
||||
|
||||
@@ -1220,53 +1214,69 @@ class AssetsBundle(object):
|
||||
check = self.html + str(self.last_modified)
|
||||
return hashlib.sha1(check).hexdigest()
|
||||
|
||||
def clean_attachments(self, type):
|
||||
ira = self.registry['ir.attachment']
|
||||
domain = ['&', '!', ('url', '=like', '/web/content/%%-%s/%%' % self.version), ('url', '=like', '/web/content/%%-%%/%s%%.%s' % (self.xmlid, type))]
|
||||
attachment_ids = ira.search(self.cr, openerp.SUPERUSER_ID, domain, context=self.context)
|
||||
return ira.unlink(self.cr, openerp.SUPERUSER_ID, attachment_ids, context=self.context)
|
||||
|
||||
def get_attachments(self, type, inc=None):
|
||||
ira = self.registry['ir.attachment']
|
||||
domain = [('url', '=like', '/web/content/%%-%s/%s%s.%s' % (self.version, self.xmlid, ('%%' if inc is None else '.%s' % inc), type))]
|
||||
attachment_ids = ira.search(self.cr, openerp.SUPERUSER_ID, domain, context=self.context)
|
||||
return ira.browse(self.cr, openerp.SUPERUSER_ID, attachment_ids, context=self.context)
|
||||
|
||||
def save_attachment(self, type, content, inc=None):
|
||||
ira = self.registry['ir.attachment']
|
||||
self.clean_attachments(type)
|
||||
attachments = self.get_attachments(type, inc)
|
||||
values = {}
|
||||
|
||||
if not attachments:
|
||||
values["name"] = "/web/content/%s" % type
|
||||
values["datas_fname"] = '%s%s.%s' % (self.xmlid, ('' if inc is None else '.%s' % inc), type)
|
||||
values["res_model"] = 'ir.ui.view'
|
||||
values["type"] = 'binary'
|
||||
attachment_id = ira.create(self.cr, openerp.SUPERUSER_ID, values, context=self.context)
|
||||
url = '/web/content/%s-%s/%s' % (attachment_id, self.version, values["datas_fname"])
|
||||
values["name"] = url
|
||||
values["url"] = url
|
||||
else:
|
||||
attachment_id = attachments[0].id
|
||||
|
||||
values["datas"] = content.encode('utf8').encode('base64')
|
||||
ira.write(self.cr, openerp.SUPERUSER_ID, attachment_id, values, context=self.context)
|
||||
|
||||
return ira.browse(self.cr, openerp.SUPERUSER_ID, attachment_id, context=self.context)
|
||||
|
||||
def js(self):
|
||||
content = self.get_cache('js')
|
||||
if content is None:
|
||||
attachments = self.get_attachments(type)
|
||||
if not attachments or attachments[0].__last_update < max([asset.last_modified for asset in self.javascripts]):
|
||||
content = ';\n'.join(asset.minify() for asset in self.javascripts)
|
||||
self.set_cache('js', content)
|
||||
return content
|
||||
|
||||
def css(self, page_number=None):
|
||||
"""Generate css content from given bundle"""
|
||||
if page_number is not None:
|
||||
return self.css_page(page_number)
|
||||
|
||||
content = self.get_cache('css')
|
||||
if content is None:
|
||||
content = self.preprocess_css()
|
||||
return self.save_attachment('js', content)
|
||||
return attachments[0]
|
||||
|
||||
def css(self):
|
||||
ira = self.registry['ir.attachment']
|
||||
attachments = self.get_attachments('css')
|
||||
if not attachments:
|
||||
# get css content
|
||||
css = self.preprocess_css()
|
||||
if self.css_errors:
|
||||
msg = '\n'.join(self.css_errors)
|
||||
content += self.css_message(msg)
|
||||
css += self.css_message(msg)
|
||||
|
||||
# move up all @import rules to the top
|
||||
matches = []
|
||||
def push(matchobj):
|
||||
matches.append(matchobj.group(0))
|
||||
return ''
|
||||
css = re.sub(self.rx_css_import, lambda matchobj: matches.append(matchobj.group(0)) and '', css)
|
||||
matches.append(css)
|
||||
css = u'\n'.join(matches)
|
||||
|
||||
content = re.sub(self.rx_css_import, push, content)
|
||||
|
||||
matches.append(content)
|
||||
content = u'\n'.join(matches)
|
||||
if not self.css_errors:
|
||||
self.set_cache('css', content)
|
||||
content = content.encode('utf-8')
|
||||
|
||||
return content
|
||||
|
||||
def css_page(self, page_number):
|
||||
content = self.get_cache('css.%d' % (page_number,))
|
||||
if page_number:
|
||||
return content
|
||||
if content is None:
|
||||
css = self.css().decode('utf-8')
|
||||
# split for browser max file size and browser max expression
|
||||
re_rules = '([^{]+\{(?:[^{}]|\{[^{}]*\})*\})'
|
||||
re_selectors = '()(?:\s*@media\s*[^{]*\{)?(?:\s*(?:[^,{]*(?:,|\{(?:[^}]*\}))))'
|
||||
css_url = '@import url(\'/web/css.%%d/%s/%s\');' % (self.xmlid, self.version)
|
||||
pages = [[]]
|
||||
page = pages[0]
|
||||
page = []
|
||||
pages = [page]
|
||||
page_selectors = 0
|
||||
for rule in re.findall(re_rules, css):
|
||||
selectors = len(re.findall(re_selectors, rule))
|
||||
@@ -1277,38 +1287,11 @@ class AssetsBundle(object):
|
||||
pages.append([rule])
|
||||
page = pages[-1]
|
||||
page_selectors = selectors
|
||||
if len(pages) == 1:
|
||||
pages = []
|
||||
for idx, page in enumerate(pages):
|
||||
self.set_cache("css.%d" % (idx+1), ''.join(page))
|
||||
content = '\n'.join(css_url % i for i in range(1,len(pages)+1))
|
||||
self.set_cache("css.0", content)
|
||||
if not content:
|
||||
return self.css()
|
||||
return content
|
||||
|
||||
def get_cache(self, type):
|
||||
content = None
|
||||
domain = [('url', '=', '/web/%s/%s/%s' % (type, self.xmlid, self.version))]
|
||||
bundle = self.registry['ir.attachment'].search_read(self.cr, openerp.SUPERUSER_ID, domain, ['datas'], context=self.context)
|
||||
if bundle and bundle[0]['datas']:
|
||||
content = bundle[0]['datas'].decode('base64')
|
||||
return content
|
||||
|
||||
def set_cache(self, type, content):
|
||||
ira = self.registry['ir.attachment']
|
||||
url = '/web/%s/%s/%s' % (type, self.xmlid, self.version)
|
||||
try:
|
||||
with self.cr.savepoint():
|
||||
ira.invalidate_bundle(self.cr, openerp.SUPERUSER_ID, type=type, xmlid=self.xmlid)
|
||||
ira.create(self.cr, openerp.SUPERUSER_ID, dict(
|
||||
datas=content.encode('utf8').encode('base64'),
|
||||
type='binary',
|
||||
name=url,
|
||||
url=url,
|
||||
), context=self.context)
|
||||
except psycopg2.Error:
|
||||
pass
|
||||
attachments |= self.save_attachment("css", ' '.join(page), inc=idx)
|
||||
elif len(attachments) > 1:
|
||||
attachments = attachments[1:]
|
||||
return attachments
|
||||
|
||||
def css_message(self, message):
|
||||
# '\A' == css content carriage return
|
||||
|
||||
Reference in New Issue
Block a user