[MERGE]Merge lp:~openerp-dev/openobject-addons/trunk-website-al.
bzr revid: bth@tinyerp.com-20131022111724-327ql1yk8s5ivfvv
This commit is contained in:
commit
2c77c2c78a
|
@ -22,9 +22,9 @@
|
|||
import openerp
|
||||
from openerp import SUPERUSER_ID
|
||||
from openerp import tools
|
||||
from openerp.osv import osv, fields
|
||||
from openerp.osv import orm, fields
|
||||
|
||||
class decimal_precision(osv.osv):
|
||||
class decimal_precision(orm.Model):
|
||||
_name = 'decimal.precision'
|
||||
_columns = {
|
||||
'name': fields.char('Usage', size=50, select=True, required=True),
|
||||
|
@ -71,4 +71,29 @@ def get_precision(application):
|
|||
return (16, res)
|
||||
return change_digit
|
||||
|
||||
class DecimalPrecisionFloat(orm.AbstractModel):
|
||||
""" Override qweb.field.float to add a `decimal_precision` domain option
|
||||
and use that instead of the column's own value if it is specified
|
||||
"""
|
||||
_inherit = 'ir.qweb.field.float'
|
||||
|
||||
|
||||
def precision(self, cr, uid, column, options=None, context=None):
|
||||
dp = options and options.get('decimal_precision')
|
||||
if dp:
|
||||
return self.pool['decimal.precision'].precision_get(
|
||||
cr, uid, dp)
|
||||
|
||||
return super(DecimalPrecisionFloat, self).precision(
|
||||
cr, uid, column, options=options, context=context)
|
||||
|
||||
class DecimalPrecisionTestModel(orm.Model):
|
||||
_name = 'decimal.precision.test'
|
||||
|
||||
_columns = {
|
||||
'float': fields.float(),
|
||||
'float_2': fields.float(digits=(16, 2)),
|
||||
'float_4': fields.float(digits=(16, 4)),
|
||||
}
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import test_qweb_float
|
||||
|
||||
checks = [
|
||||
test_qweb_float
|
||||
]
|
|
@ -0,0 +1,66 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from openerp.tests import common
|
||||
|
||||
class TestFloatExport(common.TransactionCase):
|
||||
def setUp(self):
|
||||
super(TestFloatExport, self).setUp()
|
||||
self.Model = self.registry('decimal.precision.test')
|
||||
|
||||
def get_converter(self, name):
|
||||
converter = self.registry('ir.qweb.field.float')
|
||||
column = self.Model._all_columns[name].column
|
||||
|
||||
return lambda value, options=None: converter.value_to_html(
|
||||
self.cr, self.uid, value, column, options=options, context=None)
|
||||
|
||||
def test_basic_float(self):
|
||||
converter = self.get_converter('float')
|
||||
self.assertEqual(
|
||||
converter(42.0),
|
||||
"42.0")
|
||||
self.assertEqual(
|
||||
converter(42.12345),
|
||||
"42.12345")
|
||||
|
||||
converter = self.get_converter('float_2')
|
||||
self.assertEqual(
|
||||
converter(42.0),
|
||||
"42.00")
|
||||
self.assertEqual(
|
||||
converter(42.12345),
|
||||
"42.12")
|
||||
|
||||
converter = self.get_converter('float_4')
|
||||
self.assertEqual(
|
||||
converter(42.0),
|
||||
'42.0000')
|
||||
self.assertEqual(
|
||||
converter(42.12345),
|
||||
'42.1234')
|
||||
|
||||
def test_precision_domain(self):
|
||||
DP = self.registry('decimal.precision')
|
||||
DP.create(self.cr, self.uid, {
|
||||
'name': 'A',
|
||||
'digits': 2,
|
||||
})
|
||||
DP.create(self.cr, self.uid, {
|
||||
'name': 'B',
|
||||
'digits': 6,
|
||||
})
|
||||
|
||||
converter = self.get_converter('float')
|
||||
self.assertEqual(
|
||||
converter(42.0, {'decimal_precision': 'A'}),
|
||||
'42.00')
|
||||
self.assertEqual(
|
||||
converter(42.0, {'decimal_precision': 'B'}),
|
||||
'42.000000')
|
||||
|
||||
converter = self.get_converter('float_4')
|
||||
self.assertEqual(
|
||||
converter(42.12345, {'decimal_precision': 'A'}),
|
||||
'42.12')
|
||||
self.assertEqual(
|
||||
converter(42.12345, {'decimal_precision': 'B'}),
|
||||
'42.123450')
|
|
@ -39,12 +39,12 @@ class Field(orm.AbstractModel):
|
|||
_inherit = 'ir.qweb.field'
|
||||
|
||||
def attributes(self, cr, uid, field_name, record, options,
|
||||
source_element, g_att, t_att, qweb_context):
|
||||
source_element, g_att, t_att, qweb_context, context=None):
|
||||
column = record._model._all_columns[field_name].column
|
||||
return itertools.chain(
|
||||
super(Field, self).attributes(cr, uid, field_name, record, options,
|
||||
source_element, g_att, t_att,
|
||||
qweb_context),
|
||||
qweb_context, context=context),
|
||||
[('data-oe-translate', 1 if column.translate else 0)]
|
||||
)
|
||||
|
||||
|
@ -67,7 +67,27 @@ class Float(orm.AbstractModel):
|
|||
_name = 'website.qweb.field.float'
|
||||
_inherit = ['website.qweb.field', 'ir.qweb.field.float']
|
||||
|
||||
value_from_string = float
|
||||
def from_html(self, cr, uid, model, column, element, context=None):
|
||||
lang = self.user_lang(cr, uid, context=context)
|
||||
|
||||
value = element.text_content().strip()
|
||||
|
||||
return float(value.replace(lang.thousands_sep, '')
|
||||
.replace(lang.decimal_point, '.'))
|
||||
|
||||
class Date(orm.AbstractModel):
|
||||
_name = 'website.qweb.field.date'
|
||||
_inherit = ['website.qweb.field', 'ir.qweb.field.date']
|
||||
|
||||
def from_html(self, cr, uid, model, column, element, context=None):
|
||||
raise NotImplementedError("Can not parse and save localized dates")
|
||||
|
||||
class DateTime(orm.AbstractModel):
|
||||
_name = 'website.qweb.field.datetime'
|
||||
_inherit = ['website.qweb.field', 'ir.qweb.field.datetime']
|
||||
|
||||
def from_html(self, cr, uid, model, column, element, context=None):
|
||||
raise NotImplementedError("Can not parse and save localized datetimes")
|
||||
|
||||
class Text(orm.AbstractModel):
|
||||
_name = 'website.qweb.field.text'
|
||||
|
@ -127,7 +147,7 @@ class Image(orm.AbstractModel):
|
|||
_inherit = ['website.qweb.field', 'ir.qweb.field.image']
|
||||
|
||||
def to_html(self, cr, uid, field_name, record, options,
|
||||
source_element, t_att, g_att, qweb_context):
|
||||
source_element, t_att, g_att, qweb_context, context=None):
|
||||
assert source_element.nodeName != 'img',\
|
||||
"Oddly enough, the root tag of an image field can not be img. " \
|
||||
"That is because the image goes into the tag, or it gets the " \
|
||||
|
@ -135,9 +155,9 @@ class Image(orm.AbstractModel):
|
|||
|
||||
return super(Image, self).to_html(
|
||||
cr, uid, field_name, record, options,
|
||||
source_element, t_att, g_att, qweb_context)
|
||||
source_element, t_att, g_att, qweb_context, context=context)
|
||||
|
||||
def record_to_html(self, cr, uid, field_name, record, column, options=None):
|
||||
def record_to_html(self, cr, uid, field_name, record, column, options=None, context=None):
|
||||
cls = ''
|
||||
if 'class' in options:
|
||||
cls = ' class="%s"' % werkzeug.utils.escape(options['class'])
|
||||
|
@ -183,4 +203,9 @@ class Monetary(orm.AbstractModel):
|
|||
_inherit = ['website.qweb.field', 'ir.qweb.field.monetary']
|
||||
|
||||
def from_html(self, cr, uid, model, column, element, context=None):
|
||||
return float(element.find('span').text)
|
||||
lang = self.user_lang(cr, uid, context=context)
|
||||
|
||||
value = element.find('span').text.strip()
|
||||
|
||||
return float(value.replace(lang.thousands_sep, '')
|
||||
.replace(lang.decimal_point, '.'))
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
from lxml import etree, html
|
||||
from openerp.osv import osv, fields
|
||||
from urlparse import urlparse
|
||||
|
||||
|
||||
class view(osv.osv):
|
||||
|
@ -91,6 +92,23 @@ class view(osv.osv):
|
|||
arch = previous_arch
|
||||
return arch
|
||||
|
||||
def _normalize_urls(self, element):
|
||||
attr = None
|
||||
if element.tag == 'form':
|
||||
attr = 'action' if 'action' in element.attrib else None
|
||||
elif element.tag in ['a', 'link']:
|
||||
attr = 'href' if 'href' in element.attrib else None
|
||||
elif element.tag in ['frame', 'iframe', 'img', 'input', 'script']:
|
||||
attr = 'src' if 'src' in element.attrib else None
|
||||
if attr:
|
||||
value = element.attrib[attr]
|
||||
if not urlparse(value).scheme:
|
||||
element.attrib.pop(attr)
|
||||
element.attrib['t-' + attr] = value
|
||||
for el in list(element):
|
||||
self._normalize_urls(el)
|
||||
return element
|
||||
|
||||
def save(self, cr, uid, res_id, value, xpath=None, context=None):
|
||||
""" Update a view section. The view section may embed fields to write
|
||||
|
||||
|
@ -103,6 +121,8 @@ class view(osv.osv):
|
|||
arch_section = html.fromstring(
|
||||
value, parser=html.HTMLParser(encoding='utf-8'))
|
||||
|
||||
self._normalize_urls(arch_section)
|
||||
|
||||
if xpath is None:
|
||||
# value is an embedded field on its own, not a view section
|
||||
self.save_embedded_field(cr, uid, arch_section, context=context)
|
||||
|
|
|
@ -5,7 +5,10 @@ access_website_converter_test,access_website_converter_test,model_website_conver
|
|||
access_website_converter_test_sub,access_website_converter_test_sub,model_website_converter_test_sub,,1,1,1,1
|
||||
access_website_qweb,access_website_qweb,model_website_qweb,,0,0,0,0
|
||||
access_website_qweb_field,access_website_qweb_field,model_website_qweb_field,,0,0,0,0
|
||||
access_website_qweb_field_integer,access_website_qweb_field_integer,model_website_qweb_field_integer,,0,0,0,0
|
||||
access_website_qweb_field_float,access_website_qweb_field_float,model_website_qweb_field_float,,0,0,0,0
|
||||
access_website_qweb_field_date,access_website_qweb_field_date,model_website_qweb_field_date,,0,0,0,0
|
||||
access_website_qweb_field_datetime,access_website_qweb_field_datetime,model_website_qweb_field_datetime,,0,0,0,0
|
||||
access_website_qweb_field_text,access_website_qweb_field_text,model_website_qweb_field_text,,0,0,0,0
|
||||
access_website_qweb_field_selection,access_website_qweb_field_selection,model_website_qweb_field_selection,,0,0,0,0
|
||||
access_website_qweb_field_many2one,access_website_qweb_field_many2one,model_website_qweb_field_many2one,,0,0,0,0
|
||||
|
|
|
|
@ -608,7 +608,6 @@ table.editorbar-panel td.selected {
|
|||
right: 0;
|
||||
z-index: 1000;
|
||||
height: 100%;
|
||||
width: 720px;
|
||||
}
|
||||
.oe_ace_view_editor .oe_ace_view_editor_title {
|
||||
width: 100%;
|
||||
|
@ -637,11 +636,13 @@ table.editorbar-panel td.selected {
|
|||
right: 0;
|
||||
bottom: 51px;
|
||||
left: 0;
|
||||
width: 720px;
|
||||
}
|
||||
.oe_ace_view_editor .ace_editor .ace_gutter {
|
||||
cursor: ew-resize;
|
||||
}
|
||||
.oe_ace_view_editor.oe_ace_open {
|
||||
filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100);
|
||||
opacity: 1;
|
||||
filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=97);
|
||||
opacity: 0.97;
|
||||
}
|
||||
.oe_ace_view_editor.oe_ace_closed {
|
||||
z-index: -1000;
|
||||
|
|
|
@ -466,7 +466,6 @@ $highlighted_text_color: #ffffff
|
|||
|
||||
/* ---- ACE EDITOR ---- */
|
||||
|
||||
$ace_width: 720px
|
||||
$editorbar_height: 30px
|
||||
// TODO Fix => might break with themes
|
||||
$navbar_height: 51px
|
||||
|
@ -481,7 +480,6 @@ $navbar_height: 51px
|
|||
right: 0
|
||||
z-index: 1000
|
||||
height: 100%
|
||||
width: $ace_width
|
||||
.oe_ace_view_editor_title
|
||||
width: 100%
|
||||
padding-top: 0
|
||||
|
@ -502,9 +500,10 @@ $navbar_height: 51px
|
|||
right: 0
|
||||
bottom: $navbar_height
|
||||
left: 0
|
||||
width: $ace_width
|
||||
.ace_gutter
|
||||
cursor: ew-resize
|
||||
&.oe_ace_open
|
||||
+opacity(1)
|
||||
+opacity(0.97)
|
||||
&.oe_ace_closed
|
||||
z-index: -1000
|
||||
+opacity(0)
|
||||
|
|
|
@ -100,6 +100,13 @@
|
|||
self.aceEditor.resize();
|
||||
self.$el.width(width);
|
||||
}
|
||||
function storeEditorWidth() {
|
||||
window.localStorage.setItem('ace_editor_width', self.$el.width());
|
||||
}
|
||||
function readEditorWidth() {
|
||||
var width = window.localStorage.getItem('ace_editor_width');
|
||||
return parseInt(width || 720, 10);
|
||||
}
|
||||
function startResizing (e) {
|
||||
self.refX = e.pageX;
|
||||
self.resizing = true;
|
||||
|
@ -113,16 +120,23 @@
|
|||
var width = self.$el.width() - offset;
|
||||
self.refX = e.pageX;
|
||||
resizeEditor(width);
|
||||
storeEditorWidth();
|
||||
}
|
||||
}
|
||||
document.body.addEventListener('mouseup', stopResizing, true);
|
||||
self.$('.ace_gutter').mouseup(stopResizing).mousedown(startResizing).click(stopResizing);
|
||||
$(document).mousemove(updateWidth);
|
||||
$('button[data-action=edit]').click(function () {
|
||||
self.close();
|
||||
});
|
||||
resizeEditor(readEditorWidth());
|
||||
},
|
||||
loadViews: function (views) {
|
||||
var self = this;
|
||||
var activeViews = _.filter(views, function (view) {
|
||||
var activeViews = _.uniq(_.filter(views, function (view) {
|
||||
return view.active;
|
||||
}), false, function (view) {
|
||||
return view.id;
|
||||
});
|
||||
var $viewList = self.$('#ace-view-list');
|
||||
_.each(activeViews, function (view) {
|
||||
|
|
|
@ -341,13 +341,13 @@
|
|||
});
|
||||
},
|
||||
stop: function(ev, ui){
|
||||
if (action === 'insert' && ! dropped) {
|
||||
var el = $('.oe_drop_zone').nearest({x: ui.position.left, y: ui.position.top}).first()
|
||||
if (el) {
|
||||
el.after($toInsert)
|
||||
dropped = true;
|
||||
}
|
||||
}
|
||||
if (action === 'insert' && ! dropped) {
|
||||
var el = $('.oe_drop_zone').nearest({x: ui.position.left, y: ui.position.top}).first()
|
||||
if (el) {
|
||||
el.after($toInsert)
|
||||
dropped = true;
|
||||
}
|
||||
}
|
||||
|
||||
$('.oe_drop_zone').droppable('destroy').remove();
|
||||
if (dropped) {
|
||||
|
@ -1077,14 +1077,6 @@
|
|||
self.$target.carousel();
|
||||
});
|
||||
|
||||
this.$target.on('dblclick', '.item.active .carousel-image img', function (event) {
|
||||
var $img = $(event.currentTarget);
|
||||
var editor = new website.editor.ImageDialog();
|
||||
editor.on('start', self, function (o) {o.url = $img.attr("src");});
|
||||
editor.on('save', self, function (o) {$img.attr("src", o.url);});
|
||||
editor.appendTo($('body'));
|
||||
});
|
||||
|
||||
this.rebind_event();
|
||||
},
|
||||
// rebind event to active carousel on edit mode
|
||||
|
|
|
@ -0,0 +1,161 @@
|
|||
(function () {
|
||||
'use strict';
|
||||
|
||||
var website = openerp.website;
|
||||
|
||||
var render = website.tour.render;
|
||||
|
||||
website.EditorBasicTour = website.EditorTour.extend({
|
||||
id: 'add_banner_tour',
|
||||
name: "Insert a banner",
|
||||
init: function (editor) {
|
||||
var self = this;
|
||||
self.steps = [
|
||||
{
|
||||
stepId: 'welcome',
|
||||
orphan: true,
|
||||
backdrop: true,
|
||||
title: "Welcome to your website!",
|
||||
content: "This tutorial will guide you to build your first page. We will start by adding a banner.",
|
||||
template: render('website.tour_popover', { next: "Start Tutorial", end: "Skip It" }),
|
||||
},
|
||||
{
|
||||
stepId: 'edit-page',
|
||||
element: 'button[data-action=edit]',
|
||||
placement: 'bottom',
|
||||
reflex: true,
|
||||
title: "Edit this page",
|
||||
content: "Every page of your website can be modified through the <i>Edit</i> button.",
|
||||
template: render('website.tour_popover'),
|
||||
},
|
||||
{
|
||||
stepId: 'add-block',
|
||||
element: 'button[data-action=snippet]',
|
||||
placement: 'bottom',
|
||||
title: "Insert building blocks",
|
||||
content: "To add content in a page, you can insert building blocks.",
|
||||
template: render('website.tour_popover'),
|
||||
onShow: function () {
|
||||
function refreshAddBlockStep () {
|
||||
self.tour.showStep(self.indexOfStep('add-block'));
|
||||
editor.off('rte:ready', editor, refreshAddBlockStep);
|
||||
}
|
||||
editor.on('rte:ready', editor, refreshAddBlockStep);
|
||||
$('button[data-action=snippet]').click(function () {
|
||||
self.movetoStep('drag-banner');
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
stepId: 'drag-banner',
|
||||
element: '#website-top-navbar [data-snippet-id=carousel].ui-draggable',
|
||||
placement: 'bottom',
|
||||
title: "Drag & Drop a Banner",
|
||||
content: "Drag the <em>Banner</em> block and drop it in your page. <p class='text-muted'>Tip: release the mouse button when you are in a valid zone, with a preview of the banner.</p>",
|
||||
template: render('website.tour_popover'),
|
||||
onShow: function () {
|
||||
function beginDrag () {
|
||||
$('.popover.tour').remove();
|
||||
$('body').off('mousedown', beginDrag);
|
||||
function goToNextStep () {
|
||||
$('#oe_snippets').hide();
|
||||
self.movetoStep('edit-title');
|
||||
$('body').off('mouseup', goToNextStep);
|
||||
}
|
||||
$('body').on('mouseup', goToNextStep);
|
||||
}
|
||||
$('body').on('mousedown', beginDrag);
|
||||
},
|
||||
},
|
||||
{
|
||||
stepId: 'edit-title',
|
||||
element: '#wrap [data-snippet-id=carousel]:first .carousel-caption',
|
||||
placement: 'left',
|
||||
title: "Customize banner's text",
|
||||
content: "Click in the text and start editing it. Click continue once it's done.",
|
||||
template: render('website.tour_popover', { next: "Continue" }),
|
||||
onHide: function () {
|
||||
var $banner = $("#wrap [data-snippet-id=carousel]:first");
|
||||
if ($banner.length) {
|
||||
$banner.click();
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
stepId: 'customize-banner',
|
||||
element: '.oe_overlay_options .oe_options',
|
||||
placement: 'left',
|
||||
title: "Customize the banner",
|
||||
content: "You can customize components of your page through the <em>Customize</em> menu. Try to change the background of your banner.",
|
||||
template: render('website.tour_popover', { next: "Continue" }),
|
||||
onShow: function () {
|
||||
$('.dropdown-menu [name=carousel-background]').click(function () {
|
||||
self.movetoStep('save-changes');
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
stepId: 'save-changes',
|
||||
element: 'button[data-action=save]',
|
||||
placement: 'right',
|
||||
reflex: true,
|
||||
title: "Save your modifications",
|
||||
content: "Once you click on save, your website page is updated.",
|
||||
template: render('website.tour_popover'),
|
||||
onHide: function () {
|
||||
self.saveStep('part-2');
|
||||
},
|
||||
|
||||
},
|
||||
{
|
||||
stepId: 'part-2',
|
||||
orphan: true,
|
||||
title: "Congratulation!",
|
||||
content: "Your homepage have been updated. Now, we suggest you to insert others building blocks like texts and images to structure your page.",
|
||||
template: render('website.tour_popover', { next: "Continue" }),
|
||||
},
|
||||
{
|
||||
stepId: 'show-tutorials',
|
||||
element: '#help-menu-button',
|
||||
placement: 'left',
|
||||
title: "Help is always available",
|
||||
content: "But you can always click here if you want more tutorials.",
|
||||
template: render('website.tour_popover', { end: "Close" }),
|
||||
},
|
||||
];
|
||||
return this._super();
|
||||
},
|
||||
startOfPart2: function () {
|
||||
var currentStepIndex = this.currentStepIndex();
|
||||
var secondPartIndex = this.indexOfStep('part-2');
|
||||
var showTutorialsIndex = this.indexOfStep('show-tutorials');
|
||||
return (currentStepIndex === secondPartIndex || currentStepIndex === showTutorialsIndex) && !this.tour.ended();
|
||||
},
|
||||
canResume: function () {
|
||||
return this.startOfPart2() || this._super();
|
||||
},
|
||||
});
|
||||
|
||||
website.EditorBar.include({
|
||||
start: function () {
|
||||
var menu = $('#help-menu');
|
||||
var basicTour = new website.EditorBasicTour(this);
|
||||
var $menuItem = $($.parseHTML('<li><a href="#">'+basicTour.name+'</a></li>'));
|
||||
$menuItem.click(function () {
|
||||
basicTour.reset();
|
||||
basicTour.start();
|
||||
});
|
||||
menu.append($menuItem);
|
||||
var url = new website.UrlParser(window.location.href);
|
||||
if (url.search.indexOf('?tutorial=true') === 0 || basicTour.startOfPart2()) {
|
||||
basicTour.start();
|
||||
}
|
||||
$('.tour-backdrop').click(function (e) {
|
||||
e.stopImmediatePropagation();
|
||||
e.preventDefault();
|
||||
});
|
||||
return this._super();
|
||||
},
|
||||
});
|
||||
|
||||
}());
|
|
@ -4,9 +4,11 @@
|
|||
var website = openerp.website;
|
||||
website.templates.push('/website/static/src/xml/website.tour.xml');
|
||||
|
||||
function render (template, dict) {
|
||||
return openerp.qweb.render(template, dict);
|
||||
}
|
||||
website.tour = {
|
||||
render: function render (template, dict) {
|
||||
return openerp.qweb.render(template, dict);
|
||||
}
|
||||
};
|
||||
|
||||
website.EditorTour = openerp.Class.extend({
|
||||
tour: undefined,
|
||||
|
@ -19,7 +21,7 @@
|
|||
keyboard: false,
|
||||
});
|
||||
this.tour.addSteps(_.map(this.steps, function (step) {
|
||||
step.title = render('website.tour_popover_title', { title: step.title });
|
||||
step.title = website.tour.render('website.tour_popover_title', { title: step.title });
|
||||
return step;
|
||||
}));
|
||||
this.monkeyPatchTour();
|
||||
|
@ -81,137 +83,6 @@
|
|||
},
|
||||
});
|
||||
|
||||
website.EditorBasicTour = website.EditorTour.extend({
|
||||
id: 'add_banner_tour',
|
||||
name: "Insert a banner",
|
||||
init: function (editor) {
|
||||
var self = this;
|
||||
self.steps = [
|
||||
{
|
||||
stepId: 'welcome',
|
||||
orphan: true,
|
||||
backdrop: true,
|
||||
title: "Welcome to your website!",
|
||||
content: "This tutorial will guide you to build your first page. We will start by adding a banner.",
|
||||
template: render('website.tour_popover', { next: "Start Tutorial", end: "Skip It" }),
|
||||
},
|
||||
{
|
||||
stepId: 'edit-page',
|
||||
element: 'button[data-action=edit]',
|
||||
placement: 'bottom',
|
||||
reflex: true,
|
||||
title: "Edit this page",
|
||||
content: "Every page of your website can be modified through the <i>Edit</i> button.",
|
||||
template: render('website.tour_popover'),
|
||||
},
|
||||
{
|
||||
stepId: 'add-block',
|
||||
element: 'button[data-action=snippet]',
|
||||
placement: 'bottom',
|
||||
title: "Insert building blocks",
|
||||
content: "To add content in a page, you can insert building blocks.",
|
||||
template: render('website.tour_popover'),
|
||||
onShow: function () {
|
||||
function refreshAddBlockStep () {
|
||||
self.tour.showStep(self.indexOfStep('add-block'));
|
||||
editor.off('rte:ready', editor, refreshAddBlockStep);
|
||||
}
|
||||
editor.on('rte:ready', editor, refreshAddBlockStep);
|
||||
$('button[data-action=snippet]').click(function () {
|
||||
self.movetoStep('drag-banner');
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
stepId: 'drag-banner',
|
||||
element: '#website-top-navbar [data-snippet-id=carousel].ui-draggable',
|
||||
placement: 'bottom',
|
||||
title: "Drag & Drop a Banner",
|
||||
content: "Drag the <em>Banner</em> block and drop it in your page. <p class='text-muted'>Tip: release the mouse button when you are in a valid zone, with a preview of the banner.</p>",
|
||||
template: render('website.tour_popover'),
|
||||
onShow: function () {
|
||||
function beginDrag () {
|
||||
$('.popover.tour').remove();
|
||||
$('body').off('mousedown', beginDrag);
|
||||
function goToNextStep () {
|
||||
$('#oe_snippets').hide();
|
||||
self.movetoStep('edit-title');
|
||||
$('body').off('mouseup', goToNextStep);
|
||||
}
|
||||
$('body').on('mouseup', goToNextStep);
|
||||
}
|
||||
$('body').on('mousedown', beginDrag);
|
||||
},
|
||||
},
|
||||
{
|
||||
stepId: 'edit-title',
|
||||
element: '#wrap [data-snippet-id=carousel]:first .carousel-caption',
|
||||
placement: 'left',
|
||||
title: "Customize banner's text",
|
||||
content: "Click in the text and start editing it. Click continue once it's done.",
|
||||
template: render('website.tour_popover', { next: "Continue" }),
|
||||
onHide: function () {
|
||||
var $banner = $("#wrap [data-snippet-id=carousel]:first");
|
||||
if ($banner.length) {
|
||||
$banner.click();
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
stepId: 'customize-banner',
|
||||
element: '.oe_overlay_options .oe_options',
|
||||
placement: 'left',
|
||||
title: "Customize the banner",
|
||||
content: "You can customize components of your page through the <em>Customize</em> menu. Try to change the background of your banner.",
|
||||
template: render('website.tour_popover', { next: "Continue" }),
|
||||
onShow: function () {
|
||||
$('.dropdown-menu [name=carousel-background]').click(function () {
|
||||
self.movetoStep('save-changes');
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
stepId: 'save-changes',
|
||||
element: 'button[data-action=save]',
|
||||
placement: 'right',
|
||||
reflex: true,
|
||||
title: "Save your modifications",
|
||||
content: "Once you click on save, your website page is updated.",
|
||||
template: render('website.tour_popover'),
|
||||
onHide: function () {
|
||||
self.saveStep('part-2');
|
||||
},
|
||||
|
||||
},
|
||||
{
|
||||
stepId: 'part-2',
|
||||
orphan: true,
|
||||
title: "Congratulation!",
|
||||
content: "Your homepage have been updated. Now, we suggest you to insert others building blocks like texts and images to structure your page.",
|
||||
template: render('website.tour_popover', { next: "Continue" }),
|
||||
},
|
||||
{
|
||||
stepId: 'show-tutorials',
|
||||
element: '#help-menu-button',
|
||||
placement: 'left',
|
||||
title: "Help is always available",
|
||||
content: "But you can always click here if you want more tutorials.",
|
||||
template: render('website.tour_popover', { end: "Close" }),
|
||||
},
|
||||
];
|
||||
return this._super();
|
||||
},
|
||||
startOfPart2: function () {
|
||||
var currentStepIndex = this.currentStepIndex();
|
||||
var secondPartIndex = this.indexOfStep('part-2');
|
||||
var showTutorialsIndex = this.indexOfStep('show-tutorials');
|
||||
return (currentStepIndex === secondPartIndex || currentStepIndex === showTutorialsIndex) && !this.tour.ended();
|
||||
},
|
||||
canResume: function () {
|
||||
return this.startOfPart2() || this._super();
|
||||
},
|
||||
});
|
||||
|
||||
website.UrlParser = openerp.Class.extend({
|
||||
init: function (url) {
|
||||
var a = document.createElement('a');
|
||||
|
@ -227,30 +98,4 @@
|
|||
},
|
||||
});
|
||||
|
||||
website.EditorBar.include({
|
||||
start: function () {
|
||||
website.tutorials = {
|
||||
basic: new website.EditorBasicTour(this),
|
||||
};
|
||||
var menu = $('#help-menu');
|
||||
_.each(website.tutorials, function (tutorial) {
|
||||
var $menuItem = $($.parseHTML('<li><a href="#">'+tutorial.name+'</a></li>'));
|
||||
$menuItem.click(function () {
|
||||
tutorial.reset();
|
||||
tutorial.start();
|
||||
});
|
||||
menu.append($menuItem);
|
||||
});
|
||||
var url = new website.UrlParser(window.location.href);
|
||||
if (url.search.indexOf('?tutorial=true') === 0 || website.tutorials.basic.startOfPart2()) {
|
||||
website.tutorials.basic.start();
|
||||
}
|
||||
$('.tour-backdrop').click(function (e) {
|
||||
e.stopImmediatePropagation();
|
||||
e.preventDefault();
|
||||
});
|
||||
return this._super();
|
||||
},
|
||||
});
|
||||
|
||||
}());
|
||||
|
|
|
@ -28,7 +28,7 @@ class TestConvertBack(common.TransactionCase):
|
|||
e.setAttribute('t-field', field_value)
|
||||
|
||||
rendered = self.registry('website.qweb').render_tag_field(
|
||||
e, {'field': field_value}, '', ir_qweb.QWebContext({
|
||||
e, {'field': field_value}, '', ir_qweb.QWebContext(self.cr, self.uid, {
|
||||
'record': record,
|
||||
}))
|
||||
element = html.fromstring(
|
||||
|
@ -53,6 +53,7 @@ class TestConvertBack(common.TransactionCase):
|
|||
|
||||
def test_float(self):
|
||||
self.field_roundtrip('float', 42.567890)
|
||||
self.field_roundtrip('float', 324542.567890)
|
||||
|
||||
def test_numeric(self):
|
||||
self.field_roundtrip('numeric', 42.77)
|
||||
|
|
|
@ -73,6 +73,7 @@
|
|||
<script type="text/javascript" src="/website/static/src/js/website.mobile.js"></script>
|
||||
<script type="text/javascript" src="/website/static/src/js/website.seo.js"></script>
|
||||
<script type="text/javascript" src="/website/static/src/js/website.tour.js"></script>
|
||||
<script type="text/javascript" src="/website/static/src/js/website.tour.basic.js"></script>
|
||||
<script t-if="not translatable" type="text/javascript" src="/website/static/src/js/website.snippets.js"></script>
|
||||
<script t-if="not translatable" type="text/javascript" src="/website/static/src/js/website.ace.js"></script>
|
||||
<script t-if="translatable" type="text/javascript" src="/website/static/src/js/website.translator.js"></script>
|
||||
|
@ -258,7 +259,7 @@
|
|||
</t>
|
||||
</template>
|
||||
|
||||
<template id="pager">
|
||||
<template id="pager" name="Pager">
|
||||
<ul t-if="pager['page_count'] > 1" t-attf-class="#{ classname or '' } pagination">
|
||||
<li t-att-class=" 'disabled' if pager['page']['num'] == 1 else '' ">
|
||||
<a t-att-href=" pager['page_start']['url'] if pager['page']['num'] != 1 else '' ">Prev</a>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<template id="website.layout" inherit_id="website.layout">
|
||||
<template id="website.layout" name="Mail customization" inherit_id="website.layout">
|
||||
<!-- Load stylesheets before scripts to avoid blocking -->
|
||||
<xpath expr="//head/link" position="after">
|
||||
<link rel='stylesheet' href='/website_mail/static/src/css/website_mail.css'/>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
<!-- List of categories -->
|
||||
|
||||
<template id="categories_recursive">
|
||||
<template id="categories_recursive" name="Category list">
|
||||
<li t-att-class="category.id == search.get('category') and 'active' or ''">
|
||||
<a t-att-class="category.id not in categ[1] and 'unpublish' or ''" t-href="/shop/?category=#{ category.id }" t-field="category.name" t-keep-query="search,facettes"></a>
|
||||
<ul t-if="category.child_id" class="nav nav-pills nav-stacked nav-hierarchy">
|
||||
|
@ -32,9 +32,9 @@
|
|||
</li>
|
||||
</template>
|
||||
|
||||
<!-- Product list -->
|
||||
<!-- Product list -->
|
||||
|
||||
<template id="products_cart">
|
||||
<template id="products_cart" name="Shopping cart">
|
||||
<div class="ribbon-wrapper">
|
||||
<div class="ribbon">Promo</div>
|
||||
</div>
|
||||
|
@ -65,7 +65,7 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<template id="products" page="True">
|
||||
<template id="products" name="Products" page="True">
|
||||
<t t-call="website.layout">
|
||||
<t t-set="head">
|
||||
<script type="text/javascript" src="/website_sale/static/src/js/website_sale.js"></script>
|
||||
|
@ -108,7 +108,7 @@
|
|||
t-attf-class="oe_product oe-height-#{td_product['y']*2} #{ td_product['class'] }">
|
||||
|
||||
<div class="oe_product_cart" t-att-data-publish="product.website_published and 'on' or 'off'">
|
||||
|
||||
|
||||
<div class="css_options" t-ignore="true" t-if="editable">
|
||||
<div t-attf-class="dropdown js_options" t-att-data-id="product.id">
|
||||
<a class="btn btn-default" t-att-id="'dopprod-%s' % product.id" role="button" data-toggle="dropdown">Options <span class="caret"></span></a>
|
||||
|
@ -215,7 +215,7 @@
|
|||
</template>
|
||||
|
||||
|
||||
<!-- product -->
|
||||
<!-- product -->
|
||||
|
||||
<template id="product" name="Product">
|
||||
<t t-call="website.layout">
|
||||
|
@ -287,7 +287,7 @@
|
|||
<div class="product_price mt16">
|
||||
<h4>
|
||||
<b><span class="oe_price" t-esc="product.product_variant_ids[0].price" /> €</b>
|
||||
|
||||
|
||||
<t t-if="product.product_variant_ids[0].lst_price != product.product_variant_ids[0].price">
|
||||
<span class="text-danger" style="text-decoration: line-through;">
|
||||
<t t-esc="product.product_variant_ids[0].lst_price" /> €
|
||||
|
@ -338,7 +338,7 @@
|
|||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- Page Shop my cart -->
|
||||
<!-- Page Shop my cart -->
|
||||
|
||||
<template id="mycart" name="Your Cart" page="True">
|
||||
<t t-call="website.layout">
|
||||
|
@ -419,7 +419,7 @@
|
|||
</a>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
@ -478,7 +478,7 @@
|
|||
</t>
|
||||
</template>
|
||||
|
||||
<!-- Page Shop -->
|
||||
<!-- Page Shop -->
|
||||
|
||||
<template id="products_categories" inherit_option_id="website_sale.products" name="Product Categories">
|
||||
<xpath expr="//div[@id='products_grid']" position="before">
|
||||
|
@ -622,7 +622,7 @@
|
|||
<div class="row">
|
||||
<div class="col-md-8 oe_mycart">
|
||||
<h3 class="page-header mt16">Set Billing Information
|
||||
<small t-if="user_id.id == website.public_user.id"> or
|
||||
<small t-if="user_id.id == website.public_user.id"> or
|
||||
<a t-if="not partner" t-attf-href="/web#action=redirect&url=#{ request.httprequest.host_url }/shop/checkout/">sign in</a>
|
||||
</small>
|
||||
</h3>
|
||||
|
|
Loading…
Reference in New Issue