diff --git a/addons/delivery/__openerp__.py b/addons/delivery/__openerp__.py
index 5c4aac8513d..1ee6bf413ec 100644
--- a/addons/delivery/__openerp__.py
+++ b/addons/delivery/__openerp__.py
@@ -32,7 +32,7 @@ You can define your own carrier and delivery grids for prices. When creating
invoices from picking, OpenERP is able to add and compute the shipping line.
""",
'author': 'OpenERP SA',
- 'depends': ['sale', 'stock'],
+ 'depends': ['sale_stock'],
'data': [
'security/ir.model.access.csv',
'delivery_report.xml',
diff --git a/addons/event/event_demo.xml b/addons/event/event_demo.xml
index ffc4be3a77c..3788ca8435d 100644
--- a/addons/event/event_demo.xml
+++ b/addons/event/event_demo.xml
@@ -160,10 +160,10 @@
5-days Technical Training
Course summary:
- This course is dedicated to partners, integrators and developers who need to grasp knowledge of the business applications development process. This course is for new developers or for IT professionals eager to learn more about technical aspects.
+ This course is dedicated to partners, integrators and developers who need to grasp knowledge about the business applications development process and for new developers or for IT professionals eager to learn more about technical aspects.
Objectives:
- Having attended this course, participants should be able to:
+ Having attended this course, participants should be able to:
- Understand the development concepts and architecture;
- Install and administer your own server;
@@ -176,7 +176,7 @@
- training material.
- Requirements:
+ Requirements
- Bring your own laptop.
- Participants are expected to have some knowledge in programming. A basic knowledge of the Python programming is recommended.
diff --git a/addons/membership/membership_demo.xml b/addons/membership/membership_demo.xml
index 7775050fb9e..86fb055de22 100644
--- a/addons/membership/membership_demo.xml
+++ b/addons/membership/membership_demo.xml
@@ -7,7 +7,7 @@
True
- Golden Membership
+ Gold Membership
180
service
diff --git a/addons/mrp/report/price.py b/addons/mrp/report/price.py
index 5afd6b3ee49..d5a3c32646c 100644
--- a/addons/mrp/report/price.py
+++ b/addons/mrp/report/price.py
@@ -34,7 +34,6 @@ class report_custom(report_rml):
registry = openerp.registry(cr.dbname)
product_pool = registry.get('product.product')
product_uom_pool = registry.get('product.uom')
- supplier_info_pool = registry.get('product.supplierinfo')
workcenter_pool = registry.get('mrp.workcenter')
user_pool = registry.get('res.users')
bom_pool = registry.get('mrp.bom')
diff --git a/addons/payment_acquirer_adyen/controllers/main.py b/addons/payment_acquirer_adyen/controllers/main.py
index 2ea9fb00c51..706b26e163d 100644
--- a/addons/payment_acquirer_adyen/controllers/main.py
+++ b/addons/payment_acquirer_adyen/controllers/main.py
@@ -19,7 +19,7 @@ class AdyenController(http.Controller):
@website.route([
'/payment/adyen/return/',
- ], type='http', auth='public')
+ ], type='http', auth='public', methods=['POST'])
def adyen_return(self, **post):
""" Paypal IPN. """
_logger.info('Beginning Adyen form_feedback with post data %s', pprint.pformat(post)) # debug
diff --git a/addons/product/pricelist.py b/addons/product/pricelist.py
index 2f53d67760c..279f921f6c9 100644
--- a/addons/product/pricelist.py
+++ b/addons/product/pricelist.py
@@ -172,9 +172,7 @@ class product_pricelist(osv.osv):
products = map(lambda x: x[0], products_by_qty_by_partner)
currency_obj = self.pool.get('res.currency')
product_obj = self.pool.get('product.product')
- product_category_obj = self.pool.get('product.category')
product_uom_obj = self.pool.get('product.uom')
- supplierinfo_obj = self.pool.get('product.supplierinfo')
price_type_obj = self.pool.get('product.price.type')
version = False
@@ -278,8 +276,6 @@ class product_pricelist(osv.osv):
break
if price:
- # FP Note: what's this?
- # results['item_id'] = res.id
if 'uom' in context and not uom_price_already_computed:
product = products_dict[product.id]
uom = product.uos_id or product.uom_id
@@ -292,7 +288,6 @@ class product_pricelist(osv.osv):
product = self.pool.get('product.product').browse(cr, uid, prod_id, context=context)
res_multi = self.price_get_multi(cr, uid, pricelist_ids=ids, products_by_qty_by_partner=[(product, qty, partner)], context=context)
res = res_multi[prod_id]
- res.update({'item_id': {ids[-1]: res_multi.get('item_id', ids[-1])}})
return res
diff --git a/addons/product/product.py b/addons/product/product.py
index 2a1b20860fc..e73486c2e13 100644
--- a/addons/product/product.py
+++ b/addons/product/product.py
@@ -410,7 +410,7 @@ class product_template(osv.osv):
help='Coefficient to convert default Unit of Measure to Unit of Sale\n'
' uos = uom * coeff'),
'mes_type': fields.selection((('fixed', 'Fixed'), ('variable', 'Variable')), 'Measure Type'),
- 'seller_ids': fields.one2many('product.supplierinfo', 'product_id', 'Supplier'),
+ 'seller_ids': fields.one2many('product.supplierinfo', 'product_tmpl_id', 'Supplier'),
'company_id': fields.many2one('res.company', 'Company', select=1),
# image: all image fields are base64 encoded and PIL-supported
'image': fields.binary("Image",
@@ -657,8 +657,8 @@ class product_product(osv.osv):
'virtual_available': fields.function(_product_virtual_available, type='float', string='Quantity Available'),
'incoming_qty': fields.function(_product_incoming_qty, type='float', string='Incoming'),
'outgoing_qty': fields.function(_product_outgoing_qty, type='float', string='Outgoing'),
- 'price': fields.function(_product_price, type='float', string='Price', digits_compute=dp.get_precision('Product Price')),
- 'lst_price' : fields.function(_product_lst_price, fnct_inv=_save_product_lst_price, type='float', string='Public Price', digits_compute=dp.get_precision('Product Price')),
+ 'price': fields.function(_product_price, fnct_inv=_save_product_lst_price, type='float', string='Price', digits_compute=dp.get_precision('Product Price')),
+ 'lst_price' : fields.function(_product_lst_price, fnct_inv=_save_product_lst_price, type='float', string='Public Price', digits_compute=dp.get_precision('Product Price')),
'code': fields.function(_product_code, type='char', string='Internal Reference'),
'partner_ref' : fields.function(_product_partner_ref, type='char', string='Customer ref'),
'default_code' : fields.char('Internal Reference', size=64, select=True),
@@ -928,7 +928,6 @@ class product_supplierinfo(osv.osv):
_description = "Information about a product supplier"
def _calc_qty(self, cr, uid, ids, fields, arg, context=None):
result = {}
- product_uom_pool = self.pool.get('product.uom')
for supplier_info in self.browse(cr, uid, ids, context=context):
for field in fields:
result[supplier_info.id] = {field:False}
@@ -941,10 +940,10 @@ class product_supplierinfo(osv.osv):
'product_name': fields.char('Supplier Product Name', size=128, help="This supplier's product name will be used when printing a request for quotation. Keep empty to use the internal one."),
'product_code': fields.char('Supplier Product Code', size=64, help="This supplier's product code will be used when printing a request for quotation. Keep empty to use the internal one."),
'sequence' : fields.integer('Sequence', help="Assigns the priority to the list of product supplier."),
- 'product_uom': fields.related('product_id', 'uom_po_id', type='many2one', relation='product.uom', string="Supplier Unit of Measure", readonly="1", help="This comes from the product form."),
+ 'product_uom': fields.related('product_tmpl_id', 'uom_po_id', type='many2one', relation='product.uom', string="Supplier Unit of Measure", readonly="1", help="This comes from the product form."),
'min_qty': fields.float('Minimal Quantity', required=True, help="The minimal quantity to purchase to this supplier, expressed in the supplier Product Unit of Measure if not empty, in the default unit of measure of the product otherwise."),
'qty': fields.function(_calc_qty, store=True, type='float', string='Quantity', multi="qty", help="This is a quantity which is converted into Default Unit of Measure."),
- 'product_id' : fields.many2one('product.template', 'Product', required=True, ondelete='cascade', select=True),
+ 'product_tmpl_id' : fields.many2one('product.template', 'Product Template', required=True, ondelete='cascade', select=True),
'delay' : fields.integer('Delivery Lead Time', required=True, help="Lead time in days between the confirmation of the purchase order and the reception of the products in your warehouse. Used by the scheduler for automatic computation of the purchase order planning."),
'pricelist_ids': fields.one2many('pricelist.partnerinfo', 'suppinfo_id', 'Supplier Pricelist'),
'company_id':fields.many2one('res.company','Company',select=1),
@@ -970,10 +969,11 @@ class product_supplierinfo(osv.osv):
pricelist_pool = self.pool.get('product.pricelist')
currency_pool = self.pool.get('res.currency')
currency_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.currency_id.id
+ # Compute price from standard price of product
+ product_price = product_pool.price_get(cr, uid, [product_id], 'standard_price', context=context)[product_id]
+ product = product_pool.browse(cr, uid, product_id, context=context)
for supplier in partner_pool.browse(cr, uid, supplier_ids, context=context):
- # Compute price from standard price of product
- price = product_pool.price_get(cr, uid, [product_id], 'standard_price', context=context)[product_id]
-
+ price = product_price
# Compute price from Purchase pricelist of supplier
pricelist_id = supplier.property_product_pricelist_purchase.id
if pricelist_id:
@@ -981,7 +981,7 @@ class product_supplierinfo(osv.osv):
price = currency_pool.compute(cr, uid, pricelist_pool.browse(cr, uid, pricelist_id).currency_id.id, currency_id, price)
# Compute price from supplier pricelist which are in Supplier Information
- supplier_info_ids = self.search(cr, uid, [('name','=',supplier.id),('product_id','=',product_id)])
+ supplier_info_ids = self.search(cr, uid, [('name','=',supplier.id),('product_tmpl_id','=',product.product_tmpl_id.id)])
if supplier_info_ids:
cr.execute('SELECT * ' \
'FROM pricelist_partnerinfo ' \
diff --git a/addons/product/product_demo.xml b/addons/product/product_demo.xml
index 39be1635d1a..a309a1f8b88 100644
--- a/addons/product/product_demo.xml
+++ b/addons/product/product_demo.xml
@@ -995,322 +995,322 @@ QWERTY keyboard
-->
-
+
3
1
-
+
3
1
-
+
3
1
-
+
3
1
-
+
2
5
-
+
4
1
-
+
2
1
-
+
2
1
-
+
5
1
-
+
5
1
-
+
5
1
-
+
1
1
-
+
1
1
-
+
3
1
-
+
3
1
-
+
4
5
-
+
3
1
-
+
2
1
-
+
3
1
-
+
3
1
-
+
3
1
-
+
8
1
-
+
8
1
-
+
4
1
-
+
5
1
-
+
2
12
-
+
2
12
-
+
2
5
-
+
2
12
-
+
2
5
-
+
2
1
-
+
2
1
-
+
4
1
-
+
4
1
-
+
5
1
-
+
5
1
-
+
7
1
-
+
4
1
-
+
4
0
-
+
5
0
-
+
2
0
-
+
4
0
-
+
10
0
-
+
3
0
-
+
5
0
diff --git a/addons/product_visible_discount/product_visible_discount.py b/addons/product_visible_discount/product_visible_discount.py
index bd43028b36a..605a71e8b80 100644
--- a/addons/product_visible_discount/product_visible_discount.py
+++ b/addons/product_visible_discount/product_visible_discount.py
@@ -48,12 +48,6 @@ class sale_order_line(osv.osv):
product_obj = self.pool.get('product.product')
field_name = 'list_price'
- if res_dict.get('item_id',False) and res_dict['item_id'].get(pricelist,False):
- item = res_dict['item_id'].get(pricelist,False)
- item_base = item_obj.read(cr, uid, [item], ['base'])[0]['base']
- if item_base > 0:
- field_name = price_type_obj.browse(cr, uid, item_base).field
-
product = product_obj.browse(cr, uid, product_id, context)
product_read = product_obj.read(cr, uid, product_id, [field_name], context=context)
diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py
index 75f6856709b..88ac7c635c7 100644
--- a/addons/purchase/purchase.py
+++ b/addons/purchase/purchase.py
@@ -958,7 +958,6 @@ class purchase_order_line(osv.osv):
product_product = self.pool.get('product.product')
product_uom = self.pool.get('product.uom')
res_partner = self.pool.get('res.partner')
- product_supplierinfo = self.pool.get('product.supplierinfo')
product_pricelist = self.pool.get('product.pricelist')
account_fiscal_position = self.pool.get('account.fiscal.position')
account_tax = self.pool.get('account.tax')
diff --git a/addons/purchase_requisition/purchase_requisition.py b/addons/purchase_requisition/purchase_requisition.py
index 3f31837e38e..5ce57dab811 100644
--- a/addons/purchase_requisition/purchase_requisition.py
+++ b/addons/purchase_requisition/purchase_requisition.py
@@ -96,7 +96,6 @@ class purchase_requisition(osv.osv):
def _seller_details(self, cr, uid, requisition_line, supplier, context=None):
product_uom = self.pool.get('product.uom')
pricelist = self.pool.get('product.pricelist')
- supplier_info = self.pool.get("product.supplierinfo")
product = requisition_line.product_id
default_uom_po_id = product.uom_po_id.id
qty = product_uom._compute_qty(cr, uid, requisition_line.product_uom_id.id, requisition_line.product_qty, default_uom_po_id)
diff --git a/addons/purchase_requisition/wizard/purchase_requisition_partner.py b/addons/purchase_requisition/wizard/purchase_requisition_partner.py
index 0fee8745931..8776bba2bf8 100644
--- a/addons/purchase_requisition/wizard/purchase_requisition_partner.py
+++ b/addons/purchase_requisition/wizard/purchase_requisition_partner.py
@@ -19,9 +19,7 @@
#
##############################################################################
-import time
from openerp.osv import fields, osv
-from openerp.osv.orm import browse_record, browse_null
from openerp.tools.translate import _
class purchase_requisition_partner(osv.osv_memory):
diff --git a/addons/stock/test/shipment.yml b/addons/stock/test/shipment.yml
index 5f2f4686621..0a4f8cd9842 100644
--- a/addons/stock/test/shipment.yml
+++ b/addons/stock/test/shipment.yml
@@ -66,6 +66,8 @@
-
!python {model: stock.partial.picking}: |
context.update({'active_model': 'stock.picking', 'active_id': ref('incomming_shipment'), 'active_ids': [ref('incomming_shipment')]})
+-
+ I make a partial picking and moves done.
-
!python {model: stock.partial.picking}: |
partial = []
diff --git a/addons/website/controllers/main.py b/addons/website/controllers/main.py
index b6d8ac62c91..0171429dd1b 100644
--- a/addons/website/controllers/main.py
+++ b/addons/website/controllers/main.py
@@ -119,15 +119,12 @@ class Website(openerp.addons.web.controllers.main.Home):
view_model, view_theme_id = imd.get_object_reference(
request.cr, request.uid, 'website', 'theme')
- view_secure_layout = imd.get_object_reference(
- request.cr, request.uid, 'website', 'secure_layout')[1]
-
view = request.registry.get("ir.ui.view")
views = view._views_get(request.cr, request.uid, xml_id, request.context)
done = {}
result = []
for v in views:
- if v.id != view_secure_layout and (v.inherit_option_id and v.inherit_option_id.id != view_theme_id or not optional):
+ if v.inherit_option_id and v.inherit_option_id.id != view_theme_id or not optional:
if v.inherit_option_id.id not in done:
result.append({
'name': v.inherit_option_id.name,
diff --git a/addons/website/data/website_data.xml b/addons/website/data/website_data.xml
index d1d9c0b6cb5..9e33a43b5d2 100644
--- a/addons/website/data/website_data.xml
+++ b/addons/website/data/website_data.xml
@@ -72,7 +72,7 @@
Website With Tutorial
- /?banner-tutorial=true
+ /?tutorial.banner=true
self
diff --git a/addons/website/models/website.py b/addons/website/models/website.py
index b1df178e8ed..611b582d9ce 100644
--- a/addons/website/models/website.py
+++ b/addons/website/models/website.py
@@ -535,8 +535,8 @@ class website_menu(osv.osv):
'new_window': False,
}
_parent_store = True
- _parent_order = 'sequence, name'
- _order = "parent_left"
+ _parent_order = 'sequence'
+ _order = "sequence"
# would be better to take a menu_id as argument
def get_tree(self, cr, uid, website_id, context=None):
diff --git a/addons/website/static/src/css/editor.css b/addons/website/static/src/css/editor.css
index eaf1fdbe96b..af5519cae2c 100644
--- a/addons/website/static/src/css/editor.css
+++ b/addons/website/static/src/css/editor.css
@@ -1,3 +1,4 @@
+@charset "utf-8";
/* ---- CKEditor Minimal Reset ---- */
.navbar.navbar-inverse .cke_chrome {
border: none;
@@ -190,6 +191,10 @@ ul.oe_menu_editor .disclose {
margin-bottom: 0.5em;
}
+.modal-footer {
+ text-align: left;
+}
+
.modal.nosave .modal-footer button.save {
display: none;
}
@@ -220,7 +225,7 @@ ul.oe_menu_editor .disclose {
position: absolute;
top: 0;
left: 0;
- z-index: 42;
+ z-index: 1000;
}
/* ---- SNIPPET EDITOR ---- */
diff --git a/addons/website/static/src/css/editor.sass b/addons/website/static/src/css/editor.sass
index 885b1c9372c..c2bc7a43dfa 100644
--- a/addons/website/static/src/css/editor.sass
+++ b/addons/website/static/src/css/editor.sass
@@ -154,6 +154,9 @@ ul.oe_menu_editor
.modal .image-preview
margin-bottom: 0.5em
+.modal-footer
+ text-align: left
+
.modal.nosave .modal-footer
button.save
display: none
@@ -182,7 +185,8 @@ ul.oe_menu_editor
position: absolute
top: 0
left: 0
- z-index: 42
+ // This z-index is due to .navbar of bootstrap
+ z-index: 1000
/* ---- SNIPPET EDITOR ---- */
diff --git a/addons/website/static/src/css/website.css b/addons/website/static/src/css/website.css
index 5d0f452863f..8f5b72fd31a 100644
--- a/addons/website/static/src/css/website.css
+++ b/addons/website/static/src/css/website.css
@@ -199,12 +199,11 @@ html, body, #wrapwrap {
}
#wrapwrap {
- display: table;
width: 100%;
}
header, #wrap, footer {
- display: table-row;
+ margin: 0 auto;
}
footer {
@@ -224,6 +223,10 @@ footer {
width: 100%;
}
+.row {
+ min-height: 32px;
+}
+
/* ---- HACK FOR COVERING UP CK EDITOR BOGUS P INSERTION --- */
.oe_structure.oe_editable.oe_empty:empty, .oe_editable[data-oe-type=html]:empty, .oe_structure.oe_editable.oe_empty > .oe_drop_zone.oe_insert:only-child, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child {
background-image: url("/website/static/src/img/drag_here.png");
@@ -283,12 +286,12 @@ ul.nav-stacked > li > a {
}
/* ---- PUBLISH ---- */
-.css_unpublish, .css_publish {
+.css_published .btn-danger, .css_published .css_publish {
display: none;
}
-.css_published .css_unpublish, .css_unpublished .css_publish {
- display: block;
+.css_unpublished .btn-success, .css_unpublished .css_unpublish {
+ display: none;
}
[data-publish='off'] {
@@ -345,23 +348,7 @@ ul.nav-stacked > li > a {
.carousel.oe_big .carousel-inner {
height: 450px;
}
-.carousel .carousel-caption h1, .carousel .carousel-caption h2, .carousel .carousel-caption h3 {
- margin-top: 10px;
- margin-bottom: 10px;
-}
-.carousel .carousel-image {
- right: 10%;
- left: 50%;
- top: 5%;
- bottom: 5%;
- position: absolute;
- text-align: center;
-}
-.carousel .carousel-image img {
- height: 100%;
- margin: 0 auto;
-}
-.carousel .item.text_image .carousel-caption {
+.carousel .carousel-caption {
left: auto;
right: auto;
bottom: 10%;
@@ -369,6 +356,19 @@ ul.nav-stacked > li > a {
padding: 20px;
background: rgba(0, 0, 0, 0.4);
}
+.carousel .carousel-caption h1, .carousel .carousel-caption h2, .carousel .carousel-caption h3 {
+ margin-top: 10px;
+ margin-bottom: 10px;
+}
+.carousel .carousel-image {
+ right: 50%;
+ left: 50%;
+ top: 5%;
+ bottom: 5%;
+ position: absolute;
+ max-height: 90%;
+ margin: 0 auto;
+}
.carousel .item.text_only .carousel-image {
display: none !important;
}
@@ -376,18 +376,14 @@ ul.nav-stacked > li > a {
left: 10%;
right: 10%;
top: 10%;
+ bottom: auto;
text-align: center;
+ background: transparent;
}
.carousel .item.image_text .carousel-caption {
- left: auto;
- text-align: left;
right: 10%;
- bottom: 10%;
- padding: 20px;
- background: rgba(0, 0, 0, 0.4);
}
.carousel .item.image_text .carousel-image {
- right: 50%;
left: 10%;
}
.carousel .carousel-control {
@@ -503,3 +499,7 @@ address .fa.fa-mobile-phone {
address .fa.fa-file-text-o {
margin-right: 1px;
}
+
+span[data-oe-type="monetary"] {
+ white-space: nowrap;
+}
diff --git a/addons/website/static/src/css/website.sass b/addons/website/static/src/css/website.sass
index a08aee8cfd1..9b1d1957066 100644
--- a/addons/website/static/src/css/website.sass
+++ b/addons/website/static/src/css/website.sass
@@ -124,11 +124,10 @@ html,body, #wrapwrap
height: 100%
#wrapwrap
- display: table
width: 100%
header, #wrap, footer
- display: table-row
+ margin: 0 auto
footer
height: 100%
@@ -145,6 +144,9 @@ footer
float: left
width: 100%
+.row
+ min-height: 32px
+
/* ---- HACK FOR COVERING UP CK EDITOR BOGUS P INSERTION --- */
.oe_structure.oe_editable.oe_empty:empty, .oe_editable[data-oe-type=html]:empty, .oe_structure.oe_editable.oe_empty > .oe_drop_zone.oe_insert:only-child, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child
@@ -202,10 +204,12 @@ ul.nav-stacked > li > a
text-transform: uppercase
/* ---- PUBLISH ---- */
-.css_unpublish, .css_publish
- display: none
-.css_published .css_unpublish, .css_unpublished .css_publish
- display: block
+.css_published
+ .btn-danger, .css_publish
+ display: none
+.css_unpublished
+ .btn-success, .css_unpublish
+ display: none
[data-publish='off']
+opacity(0.5)
@@ -250,27 +254,23 @@ ul.nav-stacked > li > a
&.oe_big .carousel-inner
height: 450px
.carousel-caption
+ left: auto
+ right: auto
+ bottom: 10%
+ text-align: left
+ padding: 20px
+ background: rgba(0, 0, 0, 0.4)
h1, h2, h3
margin-top: 10px
margin-bottom: 10px
.carousel-image
- right: 10%
+ right: 50%
left: 50%
top: 5%
bottom: 5%
position: absolute
- text-align: center
- img
- height: 100%
- margin: 0 auto
- .item.text_image
- .carousel-caption
- left: auto
- right: auto
- bottom: 10%
- text-align: left
- padding: 20px
- background: rgba(0, 0, 0, 0.4)
+ max-height: 90%
+ margin: 0 auto
.item.text_only
.carousel-image
display: none !important
@@ -278,17 +278,13 @@ ul.nav-stacked > li > a
left: 10%
right: 10%
top: 10%
+ bottom: auto
text-align: center
+ background: transparent
.item.image_text
.carousel-caption
- left: auto
- text-align: left
right: 10%
- bottom: 10%
- padding: 20px
- background: rgba(0, 0, 0, 0.4)
.carousel-image
- right: 50%
left: 10%
.carousel-control
cursor: pointer
@@ -378,3 +374,6 @@ address
margin: 0 3px 0 2px
.fa.fa-file-text-o
margin-right: 1px
+
+span[data-oe-type="monetary"]
+ white-space: nowrap
\ No newline at end of file
diff --git a/addons/website/static/src/js/website.ace.js b/addons/website/static/src/js/website.ace.js
index 1156ac5165e..7108fd9ded7 100644
--- a/addons/website/static/src/js/website.ace.js
+++ b/addons/website/static/src/js/website.ace.js
@@ -160,7 +160,7 @@
});
_.each(index, function (view) {
var parentId = view.inherit_id;
- if (parentId) {
+ if (parentId && index[parentId]) {
index[parentId].children.push(view);
} else {
roots.push(view);
diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js
index f88a876d82f..92556be0c98 100644
--- a/addons/website/static/src/js/website.editor.js
+++ b/addons/website/static/src/js/website.editor.js
@@ -366,7 +366,7 @@
events: {
'click button[data-action=edit]': 'edit',
'click button[data-action=save]': 'save',
- 'click button[data-action=cancel]': 'cancel',
+ 'click a[data-action=cancel]': 'cancel',
'click a[data-action=new_page]': 'new_page',
},
container: 'body',
diff --git a/addons/website/static/src/js/website.js b/addons/website/static/src/js/website.js
index 79d5f6b9d57..64767d95171 100644
--- a/addons/website/static/src/js/website.js
+++ b/addons/website/static/src/js/website.js
@@ -266,12 +266,11 @@
/* ----- PUBLISHING STUFF ---- */
$(document).on('click', '.js_publish_management .js_publish_btn', function () {
- var $data = $(this).parent(".js_publish_management");
- var self=this;
+ var $data = $(this).parents(".js_publish_management:first");
+ var self=this;
openerp.jsonRpc($data.data('controller') || '/website/publish', 'call', {'id': +$data.data('id'), 'object': $data.data('object')})
.then(function (result) {
$data.toggleClass("css_unpublished css_published");
- $(self).toggleClass("btn-success btn-danger");
$data.parents("[data-publish]").attr("data-publish", +result ? 'on' : 'off');
}).fail(function (err, data) {
website.error(data, '/web#return_label=Website&model='+$data.data('object')+'&id='+$data.data('id'));
diff --git a/addons/website/static/src/js/website.snippets.editor.js b/addons/website/static/src/js/website.snippets.editor.js
index ef4c029280e..4cf49bb962b 100644
--- a/addons/website/static/src/js/website.snippets.editor.js
+++ b/addons/website/static/src/js/website.snippets.editor.js
@@ -246,6 +246,9 @@
this.snippet_focus($snippet);
}
$("#oe_snippets").trigger('snippet-activated', $snippet);
+ if ($snippet) {
+ $snippet.trigger('snippet-activated', $snippet);
+ }
},
create_overlay: function ($snippet) {
if (typeof $snippet.data("snippet-editor") === 'undefined') {
@@ -670,7 +673,7 @@
});
- website.snippet.styleRegistry['size'] = website.snippet.StyleEditor.extend({
+ website.snippet.styleRegistry.size = website.snippet.StyleEditor.extend({
select: function(event, np) {
this._super(event, np);
this.parent.parent.cover_target(this.$overlay, this.$target);
@@ -1111,9 +1114,13 @@
this.$target.addClass("col-md-offset-" + this.$target.prevAll(".oe_drop_to_remove").length);
this._super();
},
+ hide_remove_button: function() {
+ this.$overlay.find('.oe_snippet_remove').toggleClass("hidden",
+ !this.$target.siblings().length && this.$target.parents("[data-snippet-id]:first").find("[data-snippet-id='colmd']").length > 1);
+ },
onFocus : function () {
this._super();
- this.$overlay.find('.oe_snippet_remove').toggleClass("hidden", !this.$target.siblings().length);
+ this.hide_remove_button();
},
on_clone: function () {
var $clone = this.$target.clone(false);
@@ -1121,13 +1128,21 @@
_class += ' col-md-1';
$clone.attr("class", _class);
this.$target.after($clone);
+ this.hide_remove_button();
return false;
},
on_remove: function () {
- if (!this.$target.siblings().length){
- return false;
+ if (!this.$target.siblings().length) {
+ var $parent = this.$target.parents("[data-snippet-id]:first");
+ if($parent.find("[data-snippet-id='colmd']").length > 1) {
+ return false;
+ } else {
+ $parent.data("snippet-editor").on_remove();
+ }
}
- return this._super();
+ this._super();
+ this.hide_remove_button();
+ return false;
},
on_resize: function (compass, beginClass, current) {
if (compass !== 'w')
@@ -1171,7 +1186,7 @@
self.$target.carousel(+$(this).data('slide-to')); });
this.$target.attr('contentEditable', 'false');
- this.$target.find('.oe_structure, blockquote').attr('contentEditable', 'true');
+ this.$target.find('.oe_structure, .content>.row').attr('contentEditable', 'true');
this.$target.carousel('pause');
},
@@ -1256,7 +1271,6 @@
this._super();
this.$target.css("background-image", "");
this.$target.removeClass(this._class);
- this.$target.find('.content, .carousel-image img').attr('contentEditable', 'true');
},
start : function () {
var self = this;
@@ -1311,7 +1325,7 @@
this.$target.find('.carousel-control').off('click').on('click', function () {
self.$target.carousel( $(this).data('slide')); });
- this.$target.find('.carousel-image img, .content').attr('contentEditable', 'true');
+ this.$target.find('.carousel-image, .content').attr('contentEditable', 'true');
this._super();
},
});
diff --git a/addons/website/static/src/js/website.tour.banner.js b/addons/website/static/src/js/website.tour.banner.js
index 70c5dd9dc38..f0b9043f20f 100644
--- a/addons/website/static/src/js/website.tour.banner.js
+++ b/addons/website/static/src/js/website.tour.banner.js
@@ -46,7 +46,7 @@
},
{
stepId: 'drag-banner',
- element: '#website-top-navbar [data-snippet-id=carousel].ui-draggable',
+ snippet: 'carousel',
placement: 'bottom',
title: "Drag & Drop a Banner",
content: "Drag the Banner block and drop it in your page.",
@@ -84,7 +84,7 @@
},
{
stepId: 'drag-three-columns',
- element: '#website-top-navbar [data-snippet-id=three-columns].ui-draggable',
+ snippet: 'three-columns',
placement: 'bottom',
title: "Drag & Drop a Block",
content: "Drag the '3 Columns' block and drop it below the banner.",
@@ -92,17 +92,18 @@
},
{
stepId: 'activate-text-block-title',
- element: '#wrap [data-snippet-id=three-columns]:first .text-center[data-snippet-id=colmd]',
+ 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.",
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: '.ui-draggable.oe_active .oe_snippet_remove',
+ 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.",
diff --git a/addons/website/static/src/js/website.tour.js b/addons/website/static/src/js/website.tour.js
index 90f2f8a3d21..942c3d79f58 100644
--- a/addons/website/static/src/js/website.tour.js
+++ b/addons/website/static/src/js/website.tour.js
@@ -27,6 +27,9 @@
if (!step.element) {
step.orphan = true;
}
+ if (step.snippet) {
+ step.element = '#oe_snippets div.oe_snippet[data-snippet-id="'+step.snippet+'"] .oe_snippet_thumbnail';
+ }
if (step.trigger) {
if (step.trigger === 'click') {
step.triggers = function (callback) {
@@ -48,8 +51,8 @@
};
} else {
step.triggers = function (callback) {
- var emitter = step.trigger.emitter || $(step.element);
- emitter.one(step.trigger.id, function customHandler () {
+ var emitter = _.isString(step.trigger.emitter) ? $(step.trigger.emitter) : (step.trigger.emitter || $(step.element));
+ emitter.on(step.trigger.id, function () {
(callback || self.moveToNextStep).apply(self, arguments);
});
};
@@ -144,7 +147,7 @@
},
resume: function () {
// Override if necessary
- return !this.ended();
+ return this.tourStorage.getItem(this.id+'_current_step') && !this.ended();
},
trigger: function (url) {
// Override if necessary
@@ -164,7 +167,7 @@
$('.popover.tour').remove();
function advance () {
if (_.isFunction(callback)) {
- callback.call(self);
+ callback.apply(self);
}
}
$(document.body).one('mouseup', advance);
@@ -214,12 +217,52 @@
},
});
- var TestConsole = website.TestConsole = {
- tests: []
- };
+ var TestConsole = openerp.Class.extend({
+ tests: [],
+ editor: null,
+ init: function (editor) {
+ if (!editor) {
+ throw new Error("Editor cannot be null or undefined");
+ }
+ this.editor = editor;
+ },
+ test: function (id) {
+ return _.find(this.tests, function (tour) {
+ return tour.id === id;
+ });
+ },
+ snippetSelector: function (snippetId) {
+ return '#oe_snippets div.oe_snippet[data-snippet-id="'+snippetId+'"] .oe_snippet_thumbnail';
+ },
+ snippetThumbnail: function (snippetId) {
+ return $(this.snippetSelector(snippetId)).first();
+ },
+ dragAndDropSnippet: function (snippetId) {
+ function actualDragAndDrop ($thumbnail) {
+ var thumbnailPosition = $thumbnail.position();
+ $thumbnail.trigger($.Event("mousedown", { which: 1, pageX: thumbnailPosition.left, pageY: thumbnailPosition.top }));
+ $thumbnail.trigger($.Event("mousemove", { which: 1, pageX: thumbnailPosition.left, pageY: thumbnailPosition.top+500 }));
+ var $dropZone = $(".oe_drop_zone").first();
+ var dropPosition = $dropZone.position();
+ $dropZone.trigger($.Event("mouseup", { which: 1, pageX: dropPosition.left, pageY: dropPosition.top }));
+ }
+ if (this.snippetThumbnail(snippetId).length === 0) {
+ this.editor.on('rte:ready', this, function () {
+ actualDragAndDrop(this.snippetThumbnail(snippetId));
+ });
+ } else {
+ actualDragAndDrop(this.snippetThumbnail(snippetId));
+ }
+ },
+ });
website.EditorBar.include({
tours: [],
+ init: function () {
+ var result = this._super();
+ website.TestConsole = new TestConsole(this);
+ return result;
+ },
start: function () {
$('.tour-backdrop').click(function (e) {
e.stopImmediatePropagation();
@@ -242,25 +285,72 @@
return this._super();
},
registerTour: function (tour) {
+ var testId = 'test_'+tour.id+'_tour';
this.tours.push(tour);
- TestConsole.tests.push({
+ var test = {
id: tour.id,
- run: function runTest () {
- var actionSteps = _.filter(tour.steps, function (step) {
- return step.triggers;
- });
- var currentIndex = 0;
- function executeStep (step) {
- var $element = $(step.element);
- step.triggers(function () {
- currentIndex = currentIndex + 1;
- executeStep(actionSteps[currentIndex]);
- });
- $element.click();
+ run: function (force) {
+ if (force === true) {
+ this.reset();
+ }
+ var actionSteps = _.filter(tour.steps, function (step) {
+ return step.trigger;
+ });
+ function executeStep (step) {
+ window.localStorage.setItem(testId, step.stepId);
+ step.triggers(function () {
+ var nextStep = actionSteps.shift();
+ if (nextStep) {
+ // Ensure the previous step has been fully propagated
+ setTimeout(function () {
+ setTimeout(function () {
+ executeStep(nextStep);
+ }, 0);
+ }, 0);
+ } else {
+ window.localStorage.removeItem(testId);
+ }
+ });
+ var $element = $(step.element);
+ if (step.snippet && step.trigger === 'drag') {
+ website.TestConsole.dragAndDropSnippet(step.snippet);
+ } else if (step.trigger.id === 'change') {
+ var currentValue = $element.val();
+ var options = $element[0].options;
+ // FIXME: It may be necessary to set a particular value
+ var newValue = _.find(options, function (option) {
+ return option.value !== currentValue;
+ }).value;
+ $element.val(newValue).trigger($.Event("change"));
+ } else {
+ $element.trigger($.Event("click", { srcElement: $element }));
+ }
+ }
+ var url = new website.UrlParser(window.location.href);
+ if (tour.startPath && url.pathname !== tour.startPath) {
+ window.localStorage.setItem(testId, actionSteps[0].stepId);
+ window.location.href = tour.startPath;
+ } else {
+ var lastStepId = window.localStorage.getItem(testId);
+ var currentStep = actionSteps.shift();
+ if (lastStepId) {
+ while (currentStep && lastStepId !== currentStep.stepId) {
+ currentStep = actionSteps.shift();
+ }
+ }
+ setTimeout(function () {
+ executeStep(currentStep);
+ }, 0);
}
- executeStep(actionSteps[currentIndex]);
},
- });
+ reset: function () {
+ window.localStorage.removeItem(testId);
+ },
+ };
+ website.TestConsole.tests.push(test);
+ if (window.localStorage.getItem(testId)) {
+ test.run();
+ }
},
});
diff --git a/addons/website/static/src/xml/website.editor.xml b/addons/website/static/src/xml/website.editor.xml
index be80e71afc0..15f1fec8bbd 100644
--- a/addons/website/static/src/xml/website.editor.xml
+++ b/addons/website/static/src/xml/website.editor.xml
@@ -2,11 +2,11 @@
@@ -138,7 +139,7 @@
@@ -187,7 +188,8 @@
diff --git a/addons/website/static/src/xml/website.seo.xml b/addons/website/static/src/xml/website.seo.xml
index 676a4c7760e..be9414ca37f 100644
--- a/addons/website/static/src/xml/website.seo.xml
+++ b/addons/website/static/src/xml/website.seo.xml
@@ -57,7 +57,8 @@
-->
diff --git a/addons/website/views/snippets.xml b/addons/website/views/snippets.xml
index abd419fcd85..2f2d1a23c33 100644
--- a/addons/website/views/snippets.xml
+++ b/addons/website/views/snippets.xml
@@ -40,9 +40,7 @@
Contact us
-
-

-
+
@@ -304,10 +302,10 @@
-
+
- Write here a quote from one of your customer. Quotes are are
- great way to give confidence in your products or services.
+ Write a quote here from one of your customers. Quotes are a
+ great way to build confidence in your products or services.
Author of this quote
@@ -322,7 +320,7 @@
-
+
OpenERP provides essential platform for our project management.
Things are better organized and more visible with it.
@@ -349,7 +347,7 @@
Well
- Explain the benefit you offer. Don't write about products or
+ Explain the benefits you offer. Don't write about products or
services here, write about solutions.
@@ -362,8 +360,8 @@
- Write here a quote from one of your customer. Quotes are are
- great way to give confidence in your products or services.
+ Write a quote here from one of your customers. Quotes are a
+ great way to build confidence in your products or services.
Author of this quote
@@ -380,9 +378,8 @@
Feature Title
- Panels are great to compare offers or to emphasize on
- key features. To compare products, use panels inside
- columns.
+ Panels are a great tool to compare offers or to emphasize on
+ key features. To compare products, use the inside columns.
@@ -656,8 +653,8 @@
- Write here a quote from one of your customer. Quotes are are
- great way to give confidence in your products or services.
+ Write a quote here from one of your customers. Quotes are a
+ great way to build confidence in your products or services.
Author of this quote
@@ -741,12 +738,12 @@
-
-
- Write here a quote from one of your customer. Quotes are are
- great way to give confidence in your products or services.
-
- Author of this quote
+
+
+ Write a quote here from one of your customers. Quotes are a
+ great way to build confidence in your products or services.
+
+ Author of this quote
@@ -759,12 +756,12 @@
-
-
- OpenERP provides essential platform for our project management.
- Things are better organized and more visible with it.
-
- John Doe, CEO
+
+
+ OpenERP provides essential platform for our project management.
+ Things are better organized and more visible with it.
+
+ John Doe, CEO
@@ -790,7 +787,7 @@