[MERGE] Merge parents

bzr revid: rim@openerp.com-20131217102008-1ds3byarhyc86f8c
bzr revid: rim@openerp.com-20131217145121-v4s89fx8vsncmv4p
This commit is contained in:
Richard Mathot (OpenERP) 2013-12-17 15:51:21 +01:00
commit 96a86525a4
12 changed files with 278 additions and 140 deletions

View File

@ -13,4 +13,5 @@
'data/transfer.xml',
],
'installable': True,
'auto_install': True,
}

View File

@ -99,6 +99,22 @@ class Website(openerp.addons.web.controllers.main.Home):
return request.registry['ir.http']._handle_exception(e, 404)
return request.website.render(page, values)
@website.route('/website/reset_templates', type='http', auth='user', methods=['POST'])
def reset_template(self, templates, redirect='/'):
templates = request.httprequest.form.getlist('templates')
modules_to_update = []
for temp_id in templates:
view = request.registry['ir.ui.view'].browse(request.cr, request.uid, int(temp_id), context=request.context)
view.model_data_id.write({
'noupdate': False
})
if view.model_data_id.module not in modules_to_update:
modules_to_update.append(view.model_data_id.module)
module_obj = request.registry['ir.module.module']
module_ids = module_obj.search(request.cr, request.uid, [('name', 'in', modules_to_update)], context=request.context)
module_obj.button_immediate_upgrade(request.cr, request.uid, module_ids, context=request.context)
return request.redirect(redirect)
@website.route('/website/customize_template_toggle', type='json', auth='user')
def customize_template_set(self, view_id):
view_obj = request.registry.get("ir.ui.view")

View File

@ -99,6 +99,11 @@ class ir_http(orm.AbstractModel):
)
if code == 500:
logger.error("500 Internal Server Error:\n\n%s", values['traceback'])
if values['qweb_template']:
view = request.registry.get("ir.ui.view")
views = view._views_get(request.cr, request.uid, values['qweb_template'], request.context)
to_reset = [view for view in views if view.model_data_id.noupdate == True]
values['views'] = to_reset
elif code == 403:
logger.warn("403 Forbidden:\n\n%s", values['traceback'])

View File

@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
import copy
from urlparse import urlparse
from lxml import etree, html
@ -84,19 +85,24 @@ class view(osv.osv):
return out
def replace_arch_section(self, cr, uid, view_id, section_xpath, replacement, context=None):
# remove branding from replacement section
for att in ir.ir_ui_view.MOVABLE_BRANDING:
replacement.attrib.pop(att, None)
# the root of the arch section shouldn't actually be replaced as it's
# not really editable itself, only the content truly is editable.
[view] = self.browse(cr, uid, [view_id], context=context)
arch = etree.fromstring(view.arch.encode('utf-8'))
# => get the replacement root
if not section_xpath:
# replace all of the arch, not just a fragment
arch = replacement
root = arch
else:
arch = etree.fromstring(self.browse(cr, uid, view_id, context=context).arch.encode('utf-8'))
# ensure there's only one match
[previous_section] = arch.xpath(section_xpath)
[root] = arch.xpath(section_xpath)
previous_section.getparent().replace(previous_section, replacement)
root.text = replacement.text
root.tail = replacement.tail
# replace all children
del root[:]
for child in replacement:
root.append(copy.deepcopy(child))
return arch

View File

@ -1,4 +1,3 @@
@charset "utf-8";
/* ---- CKEditor Minimal Reset ---- */
.navbar.navbar-inverse .cke_chrome {
border: none;
@ -173,7 +172,7 @@ ul.oe_menu_editor .disclose {
}
/* ---- RTE ---- */
.oe_editable .btn {
.oe_editable .btn, .btn.oe_editable {
-webkit-user-select: auto;
-moz-user-select: auto;
user-select: auto;

View File

@ -141,8 +141,8 @@ ul.oe_menu_editor
// bootstrap makes .btn elements unselectable -> RTE double-click can't know
// about them either
.oe_editable .btn
@include user-select(auto)
.oe_editable .btn, .btn.oe_editable
+user-select(auto)
.modal-dialog.select-image
width: 80%

View File

@ -1,4 +1,3 @@
@charset "utf-8";
/* THIS CSS FILE IS FOR WEBSITE THEMING CUSTOMIZATION ONLY
*
* css for editor buttons, openerp widget included in the website and other
@ -203,7 +202,7 @@ html, body, #wrapwrap {
width: 100%;
}
header, #wrap, footer {
header, main, footer {
display: table-row;
}
@ -504,3 +503,53 @@ address .fa.fa-file-text-o {
span[data-oe-type="monetary"] {
white-space: nowrap;
}
.oe_template_fallback {
-webkit-column-count: 3;
-moz-column-count: 3;
-ms-column-count: 3;
-o-column-count: 3;
column-count: 3;
}
.bs-callout {
margin: 20px 0;
padding: 20px;
border-left: 3px solid #eeeeee;
}
.bs-callout h4 {
margin-top: 0;
margin-bottom: 5px;
}
.bs-callout p:last-child {
margin-bottom: 0;
}
.bs-callout-danger {
background-color: #fdf7f7;
border-color: #eed3d7;
}
.bs-callout-danger h4 {
color: #b94a48;
}
.bs-callout-warning {
background-color: #faf8f0;
border-color: #faebcc;
}
.bs-callout-warning h4 {
color: #8a6d3b;
}
.bs-callout-info {
background-color: #f4f8fa;
border-color: #bce8f1;
}
.bs-callout-info h4 {
color: #34789a;
}

View File

@ -127,7 +127,7 @@ html,body, #wrapwrap
display: table
width: 100%
header, #wrap, footer
header, main, footer
display: table-row
footer
@ -377,4 +377,35 @@ address
margin-right: 1px
span[data-oe-type="monetary"]
white-space: nowrap
white-space: nowrap
.oe_template_fallback
@include column-count(3)
// ---- Callouts from bootstrap doc ---- {{{
.bs-callout
margin: 20px 0
padding: 20px
border-left: 3px solid #eee
.bs-callout h4
margin-top: 0
margin-bottom: 5px
.bs-callout p:last-child
margin-bottom: 0
.bs-callout-danger
background-color: #fdf7f7
border-color: #eed3d7
.bs-callout-danger h4
color: #b94a48
.bs-callout-warning
background-color: #faf8f0
border-color: #faebcc
.bs-callout-warning h4
color: #8a6d3b
.bs-callout-info
background-color: #f4f8fa
border-color: #bce8f1
.bs-callout-info h4
color: #34789a
// }}}

View File

@ -11,145 +11,139 @@
});
website.BannerTour = website.Tour.extend({
id: 'banner',
id: 'banner',
name: "Insert a banner",
startPath: '/page/website.homepage',
path: '/page/website.homepage',
init: function (editor) {
var self = this;
self.steps = [
{
stepId: 'welcome',
title: "Welcome to your website!",
content: "This tutorial will guide you to build your home page. We will start by adding a banner.",
stepId: 'welcome',
title: "Welcome to your website!",
content: "This tutorial will guide you to build your home page. We will start by adding a banner.",
template: self.popover({ next: "Start Tutorial", end: "Skip It" }),
backdrop: true,
},
{
stepId: 'edit-page',
element: 'button[data-action=edit]',
stepId: 'edit-page',
element: 'button[data-action=edit]',
placement: 'bottom',
title: "Edit this page",
content: "Every page of your website can be modified through the <i>Edit</i> button.",
title: "Edit this page",
content: "Every page of your website can be modified through the <i>Edit</i> button.",
trigger: {
id: 'rte:ready',
type: 'openerp',
emitter: editor,
type: 'openerp',
id: 'rte:ready',
},
},
{
stepId: 'add-banner',
element: 'button[data-action=snippet]',
stepId: 'add-banner',
element: 'button[data-action=snippet]',
placement: 'bottom',
title: "Insert building blocks",
content: "To add content in a page, you can insert building blocks.",
trigger: 'click',
title: "Insert building blocks",
content: "To add content in a page, you can insert building blocks.",
trigger: 'click',
},
{
stepId: 'drag-banner',
snippet: 'carousel',
stepId: 'drag-banner',
snippet: 'carousel',
placement: 'bottom',
title: "Drag & Drop a Banner",
content: "Drag the Banner block and drop it in your page.",
trigger: 'drag',
title: "Drag & Drop a Banner",
content: "Drag the Banner block and drop it in your page.",
trigger: 'drag',
},
{
stepId: 'edit-title',
element: '#wrap [data-snippet-id=carousel]:first .carousel-caption',
stepId: 'edit-title',
element: '#wrap [data-snippet-id=carousel]:first .carousel-caption',
placement: 'top',
title: "Customize banner's text",
content: "Click in the text and start editing it. Click continue once it's done.",
template: self.popover({ next: "Continue" }),
onStart: function () {
var $banner = $("#wrap [data-snippet-id=carousel]:first");
if ($banner.length) {
$banner.click();
}
},
title: "Customize banner's text",
content: "Click in the text and start editing it. Click continue once it's done.",
template: self.popover({ next: "Continue" }),
},
{
stepId: 'customize-banner',
element: '.oe_overlay_options .oe_options',
stepId: 'customize-banner',
element: '.oe_overlay_options .oe_options',
placement: 'left',
title: "Customize the banner",
content: "Customize any block through this menu. Try to change the background of the banner.",
template: self.popover({ next: "Continue" }),
title: "Customize the banner",
content: "Customize any block through this menu. Try to change the background of the banner.",
template: self.popover({ next: "Continue" }),
},
{
stepId: 'add-three-cols',
element: 'button[data-action=snippet]',
stepId: 'add-three-cols',
element: 'button[data-action=snippet]',
placement: 'bottom',
title: "Add Another Block",
content: "Let's add another building block to your page.",
trigger: 'click',
title: "Add Another Block",
content: "Let's add another building block to your page.",
trigger: 'click',
},
{
stepId: 'drag-three-columns',
snippet: 'three-columns',
stepId: 'drag-three-columns',
snippet: 'three-columns',
placement: 'bottom',
title: "Drag & Drop a Block",
content: "Drag the <em>'3 Columns'</em> block and drop it below the banner.",
trigger: 'drag',
title: "Drag & Drop a Block",
content: "Drag the <em>'3 Columns'</em> block and drop it below the banner.",
trigger: 'drag',
},
{
stepId: 'activate-text-block-title',
element: '#wrap [data-snippet-id=three-columns] .text-center[data-snippet-id=colmd]',
stepId: 'activate-text-block-title',
element: '#wrap [data-snippet-id=three-columns] .text-center[data-snippet-id=colmd]',
placement: 'top',
title: "Edit an Area",
content: "Select any area of the page to modify it. Click on this subtitle.",
title: "Edit an Area",
content: "Select any area of the page to modify it. Click on this subtitle.",
trigger: {
id: 'snippet-activated',
emitter: '#wrap [data-snippet-id=three-columns] .text-center[data-snippet-id=colmd]',
id: 'snippet-activated',
},
},
{
stepId: 'remove-text-block-title',
element: '.oe_active .oe_snippet_remove',
stepId: 'remove-text-block-title',
element: '.oe_active .oe_snippet_remove',
placement: 'top',
title: "Delete the Title",
content: "From this toolbar you can move, duplicate or delete the selected zone. Click on the trash can to delete the title.",
trigger: 'click',
title: "Delete the Title",
content: "From this toolbar you can move, duplicate or delete the selected zone. Click on the trash can to delete the title.",
trigger: 'click',
},
{
stepId: 'save-changes',
element: 'button[data-action=save]',
stepId: 'save-changes',
element: 'button[data-action=save]',
placement: 'right',
title: "Save your modifications",
content: "Publish your page by clicking on the <em>'Save'</em> button.",
trigger: 'click',
title: "Save your modifications",
content: "Publish your page by clicking on the <em>'Save'</em> button.",
trigger: 'click',
},
{
stepId: 'part-2',
title: "Congratulation!",
content: "Your homepage has been updated.",
template: self.popover({ next: "Continue" }),
stepId: 'part-2',
title: "Congratulation!",
content: "Your homepage has been updated.",
template: self.popover({ next: "Continue" }),
},
{
stepId: 'show-mobile',
element: 'a[data-action=show-mobile-preview]',
stepId: 'show-mobile',
element: 'a[data-action=show-mobile-preview]',
placement: 'bottom',
title: "Test Your Mobile Version",
content: "Let's check how your homepage looks like on mobile devices.",
title: "Test Your Mobile Version",
content: "Let's check how your homepage looks like on mobile devices.",
trigger: {
id: 'shown.bs.modal',
emitter: $(document),
id: 'shown.bs.modal',
},
},
{
stepId: 'show-mobile-close',
element: 'button[data-dismiss=modal]',
stepId: 'show-mobile-close',
element: 'button[data-dismiss=modal]',
placement: 'right',
title: "Close Mobile Preview",
content: "Scroll in the mobile preview to test the rendering. Once it's ok, close this dialog.",
trigger: 'click',
title: "Close Mobile Preview",
content: "Scroll in the mobile preview to test the rendering. Once it's ok, close this dialog.",
trigger: 'click',
},
{
stepId: 'show-tutorials',
element: '#help-menu-button',
stepId: 'show-tutorials',
element: '#help-menu-button',
placement: 'left',
title: "More Tutorials",
content: "Get more tutorials through this <em>'Help'</em> menu or click on the left <em>'Edit'</em> button to continue modifying this page.",
template: self.popover({ end: "Close Tutorial" }),
trigger: 'click',
title: "More Tutorials",
content: "Get more tutorials through this <em>'Help'</em> menu or click on the left <em>'Edit'</em> button to continue modifying this page.",
template: self.popover({ end: "Close Tutorial" }),
trigger: 'click',
}
];
return this._super();

View File

@ -139,7 +139,7 @@
},
redirect: function (url) {
url = url || new website.UrlParser(window.location.href);
var path = (this.startPath && url.pathname !== this.startPath) ? this.startPath : url.pathname;
var path = (this.path && url.pathname !== this.path) ? this.path : url.pathname;
var search = url.activateTutorial(this.id);
var newUrl = path + search;
window.location.replace(newUrl);
@ -333,9 +333,9 @@
}
}
var url = new website.UrlParser(window.location.href);
if (tour.startPath && url.pathname !== tour.startPath) {
if (tour.path && url.pathname !== tour.path) {
window.localStorage.setItem(testId, actionSteps[0].stepId);
window.location.href = tour.startPath;
window.location.href = tour.path;
} else {
var lastStepId = window.localStorage.getItem(testId);
var currentStep = actionSteps.shift();

View File

@ -92,10 +92,17 @@ class TestViewSaving(common.TransactionCase):
self.eq(View.to_field_ref(self.cr, self.uid, embedded, context=None),
h.SPAN({'t-field': 'bob', 'class': 'foo bar', 'id': 'whop'}))
def test_replace_arch(self):
replacement = h.P("Wheee")
result = self.registry('ir.ui.view').replace_arch_section(
self.cr, self.uid, self.view_id, None, replacement)
self.eq(result, h.DIV("Wheee"))
def test_replace_arch_2(self):
replacement = h.DIV(h.P("Wheee"))
result = self.registry('ir.ui.view').replace_arch_section(
self.cr, self.uid, self.view_id, None, replacement)
@ -110,7 +117,7 @@ class TestViewSaving(common.TransactionCase):
self.eq(result, h.DIV(
h.DIV(
h.H1("I am the greatest title alive!"),
h.H3("I am the greatest title alive!"),
h.UL(
h.LI("Item 1"),
h.LI("Item 2"),

View File

@ -115,7 +115,9 @@
</div>
</div>
</header>
<t t-raw="0"/>
<main>
<t t-raw="0"/>
</main>
<footer>
<div class="container" id="footer_container">
<div class="row">
@ -460,18 +462,18 @@
<template id="403">
<t t-call="website.layout">
<div id="wrap">
<t t-raw="0"/>
<div class="oe_structure oe_empty">
<div class="container">
<h1 class="mt32">403: Forbidden!</h1>
<p>Access Denied.</p>
<p>Maybe you were looking for one of these popular pages ?</p>
<ul>
<li><a href="/">Homepage</a></li>
<li><a href="/page/website.contactus/">Contact Us</a></li>
</ul>
</div>
<div class="container">
<h1 class="mt32">403: Forbidden</h1>
<p>The page you were looking for could not be authorized.</p>
<p>Maybe you were looking for one of these popular pages ?</p>
<ul>
<li><a href="/">Homepage</a></li>
<li><a href="/page/website.contactus/">Contact Us</a></li>
</ul>
</div>
<t t-if="editable or request.debug">
<t t-call="website.http_error_debug"/>
</t>
</div>
</t>
</template>
@ -504,32 +506,60 @@
</template>
<template id="500">
<t t-call="website.http_error"/>
</template>
<!-- This template should not use any variable except those provided by website.ir_http._handle_exception -->
<html>
<head>
<title t-esc="status_message">Internal Server Error</title>
<link rel='stylesheet' href='/web/static/lib/fontawesome/css/font-awesome.css'/>
<link rel='stylesheet' href='/web/static/lib/bootstrap/css/bootstrap.css'/>
<link rel='stylesheet' href='/website/static/src/css/website.css'/>
<script type="text/javascript" src="/web/static/lib/jquery/jquery.js"></script>
<script type="text/javascript" src="/web/static/lib/bootstrap/js/bootstrap.js"></script>
</head>
<body>
<div id="wrapwrap">
<div class="navbar navbar-default navbar-static-top">
<div class="container">
<div class="collapse navbar-collapse navbar-top-collapse">
<ul class="nav navbar-nav">
<li><a href="/">Home</a></li>
<li><a href="javascript: window.history.back()">Back</a></li>
</ul>
</div>
</div>
</div>
<div class="mb32">
<div class="oe_structure">
<h1 class="container mt32"><t t-esc="status_code"/>: <t t-esc="status_message"/></h1>
</div>
<template id="403">
<t t-call="website.layout">
<div id="wrap">
<div class="container">
<h1 class="mt32">403: Forbidden</h1>
<p>
The page you were looking for could not be
authorized.
</p>
<p>
Maybe you were looking for one of these
popular pages ?
</p>
<ul>
<li><a href="/">Homepage</a></li>
<li><a href="/page/website.contactus/">Contact Us</a></li>
</ul>
</div>
<t t-if="editable or request.debug">
<t t-call="website.http_error_debug"/>
</t>
</div>
</t>
<div class="container" t-if="views">
<div class="bs-callout bs-callout-danger" t-if="qweb_template and editable">
<h4>Template fallback</h4>
<p>An error occured while rendering the template <code t-esc="qweb_template"/>.</p>
<p>If this error is caused by a change of yours in the templates, you have the possibility to reset one or more templates to their <strong>factory settings</strong>.</p>
<form action="/website/reset_templates" method="post">
<ul class="oe_template_fallback">
<li t-foreach="views" t-as="view">
<label>
<input type="checkbox" name="templates" t-att-value="view.id" t-att-checked="'checked' if view_first else None"/>
<t t-esc="view.name"/>
</label>
</li>
</ul>
<input type="hidden" name="redirect" t-att-value="request.httprequest.path"/>
<input type="submit" value="Reset selected templates"/>
</form>
</div>
</div>
<t t-if="editable or request.debug">
<t t-call="website.http_error_debug"/>
</t>
</div>
</div>
</body>
</html>
</template>
<template id="robots">