[MERGE] with lp:~openerp-dev/openobject-addons/trunk-website-al.
bzr revid: dka@tinyerp.com-20140113130212-4f17b0inc4u3s5k3 bzr revid: dka@tinyerp.com-20140115052550-15ulprts5fo6s30r
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_decimal_precision_config,decimal.precision configuration,model_decimal_precision,base.group_system,1,1,1,1
|
||||
access_decimal_precision_all,decimal.precision,model_decimal_precision,,1,0,0,0
|
||||
access_decimal_precision_test_all,decimal.precision.test,model_decimal_precision_test,,1,1,1,1
|
||||
|
||||
|
@@ -237,7 +237,7 @@ class test_message_compose(TestMail):
|
||||
email_template.send_mail(cr, uid, email_template_id, self.group_pigs_id, force_send=True, context=context)
|
||||
sent_emails = self._build_email_kwargs_list
|
||||
email_to_lst = [
|
||||
['b@b.b', 'c@c.c'], ['"Followers of Pigs" <admin@example.com>'],
|
||||
['b@b.b', 'c@c.c'], ['"Followers of Pigs" <admin@yourcompany.example.com>'],
|
||||
['"Followers of Pigs" <raoul@raoul.fr>'], ['"Followers of Pigs" <bert@bert.fr>']]
|
||||
self.assertEqual(len(sent_emails), 4, 'email_template: send_mail: 3 valid email recipients + email_to -> should send 4 emails')
|
||||
for email in sent_emails:
|
||||
|
||||
@@ -272,21 +272,6 @@ class event_event(osv.osv):
|
||||
}
|
||||
return {'value': dic}
|
||||
|
||||
def on_change_address_id(self, cr, uid, ids, address_id, context=None):
|
||||
values = {}
|
||||
if not address_id:
|
||||
return values
|
||||
address = self.pool.get('res.partner').browse(cr, uid, address_id, context=context)
|
||||
values.update({
|
||||
'street' : address.street,
|
||||
'street2' : address.street2,
|
||||
'city' : address.city,
|
||||
'country_id' : address.country_id and address.country_id.id or False,
|
||||
'state_id' : address.state_id and address.state_id.id or False,
|
||||
'zip' : address.zip,
|
||||
})
|
||||
return {'value' : values}
|
||||
|
||||
def onchange_start_date(self, cr, uid, ids, date_begin=False, date_end=False, context=None):
|
||||
res = {'value':{}}
|
||||
if date_end:
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
</div>
|
||||
<group name="main_field_group">
|
||||
<group>
|
||||
<field name="address_id" on_change="on_change_address_id(address_id)" context="{'show_address': 1}" options='{"always_reload": True}'/>
|
||||
<field name="address_id" context="{'show_address': 1}" options='{"always_reload": True}'/>
|
||||
<field name="organizer_id"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</group>
|
||||
|
||||
@@ -74,8 +74,6 @@
|
||||
<field name="deadline" eval="(DateTime.today() + timedelta(60)).strftime('%Y-%m-%d')"/>
|
||||
<field name="price">1500.0</field>
|
||||
<field name="register_max">10</field>
|
||||
<field name="description_sale">Cathering for breakfast and lunch
|
||||
VIP Parking access</field>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -105,8 +103,6 @@ VIP Parking access</field>
|
||||
<field name="deadline" eval="(DateTime.today() + timedelta(60)).strftime('%Y-%m-%d')"/>
|
||||
<field name="price">1500.0</field>
|
||||
<field name="register_max">5</field>
|
||||
<field name="description_sale">Cathering for breakfast and lunch
|
||||
VIP Parking access</field>
|
||||
</record>
|
||||
|
||||
<record id="event_3_ticket_1" model="event.event.ticket">
|
||||
@@ -125,8 +121,6 @@ VIP Parking access</field>
|
||||
<field name="deadline" eval="(DateTime.today() + timedelta(60)).strftime('%Y-%m-%d')"/>
|
||||
<field name="price">1500.0</field>
|
||||
<field name="register_max">5</field>
|
||||
<field name="description_sale">Cathering for breakfast and lunch
|
||||
VIP Parking access</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
|
||||
@@ -94,87 +94,6 @@
|
||||
Resource: product.product
|
||||
-->
|
||||
|
||||
<record id="product.product_product_2" model="product.product">
|
||||
<field name="company_id" ref="res_company_oerp_editor"/>
|
||||
</record>
|
||||
<record id="product.product_product_1" model="product.product">
|
||||
<field name="company_id" ref="res_company_oerp_editor"/>
|
||||
</record>
|
||||
<record id="product.product_product_3" model="product.product">
|
||||
<field name="company_id" ref="res_company_oerp_editor"/>
|
||||
</record>
|
||||
<record id="product.product_product_4" model="product.product">
|
||||
<field name="company_id" ref="res_company_oerp_editor"/>
|
||||
</record>
|
||||
<record id="product.product_product_5" model="product.product">
|
||||
<field name="company_id" ref="res_company_oerp_editor"/>
|
||||
</record>
|
||||
<record id="product.product_product_6" model="product.product">
|
||||
<field name="company_id" ref="res_company_oerp_editor"/>
|
||||
</record>
|
||||
<record id="product.product_product_7" model="product.product">
|
||||
<field name="company_id" ref="res_company_oerp_editor"/>
|
||||
</record>
|
||||
<record id="product.product_product_6" model="product.product">
|
||||
<field name="company_id" ref="res_company_oerp_editor"/>
|
||||
</record>
|
||||
<record id="product.product_product_9" model="product.product">
|
||||
<field name="company_id" ref="res_company_oerp_editor"/>
|
||||
</record>
|
||||
<record id="product.product_product_10" model="product.product">
|
||||
<field name="company_id" ref="res_company_oerp_editor"/>
|
||||
</record>
|
||||
<record id="product.product_product_11" model="product.product">
|
||||
<field name="company_id" ref="res_company_oerp_editor"/>
|
||||
</record>
|
||||
<record id="product.product_product_12" model="product.product">
|
||||
<field name="company_id" ref="res_company_oerp_editor"/>
|
||||
</record>
|
||||
<record id="product.product_product_13" model="product.product">
|
||||
<field name="company_id" ref="res_company_oerp_editor"/>
|
||||
</record>
|
||||
<record id="product.product_product_14" model="product.product">
|
||||
<field name="company_id" ref="res_company_oerp_editor"/>
|
||||
</record>
|
||||
<record id="product.product_product_15" model="product.product">
|
||||
<field name="company_id" ref="res_company_oerp_editor"/>
|
||||
</record>
|
||||
<record id="product.product_product_16" model="product.product">
|
||||
<field name="company_id" ref="res_company_oerp_editor"/>
|
||||
</record>
|
||||
<record id="product.product_product_17" model="product.product">
|
||||
<field name="company_id" ref="res_company_oerp_editor"/>
|
||||
</record>
|
||||
<record id="product.product_product_18" model="product.product">
|
||||
<field name="company_id" ref="res_company_oerp_editor"/>
|
||||
</record>
|
||||
<record id="product.product_product_19" model="product.product">
|
||||
<field name="company_id" ref="res_company_oerp_editor"/>
|
||||
</record>
|
||||
<record id="product.product_product_27" model="product.product">
|
||||
<field name="company_id" ref="res_company_oerp_editor"/>
|
||||
</record>
|
||||
<record id="product.product_product_20" model="product.product">
|
||||
<field name="company_id" ref="res_company_oerp_editor"/>
|
||||
</record>
|
||||
<record id="product.product_product_21" model="product.product">
|
||||
<field name="company_id" ref="res_company_oerp_editor"/>
|
||||
</record>
|
||||
<record id="product.product_product_22" model="product.product">
|
||||
<field name="company_id" ref="res_company_oerp_editor"/>
|
||||
</record>
|
||||
<record id="product.product_product_23" model="product.product">
|
||||
<field name="company_id" ref="res_company_oerp_editor"/>
|
||||
</record>
|
||||
<record id="product.product_product_24" model="product.product">
|
||||
<field name="company_id" ref="res_company_oerp_editor"/>
|
||||
</record>
|
||||
<record id="product.product_product_25" model="product.product">
|
||||
<field name="company_id" ref="res_company_oerp_editor"/>
|
||||
</record>
|
||||
<record id="product.product_product_26" model="product.product">
|
||||
<field name="company_id" ref="res_company_oerp_editor"/>
|
||||
</record>
|
||||
<record id="Odoo1" model="product.category">
|
||||
<field name="parent_id" ref="product.product_category_all"/>
|
||||
<field name="name">Odoo Offers</field>
|
||||
|
||||
@@ -20,8 +20,9 @@ class AdyenController(http.Controller):
|
||||
@website.route([
|
||||
'/payment/adyen/return/',
|
||||
], type='http', auth='public')
|
||||
def adyen_return(self, **post):
|
||||
""" Paypal IPN. """
|
||||
def adyen_return(self, pspReference, **post):
|
||||
""" Paypal IPN."""
|
||||
post["pspReference"] = pspReference
|
||||
_logger.info('Beginning Adyen form_feedback with post data %s', pprint.pformat(post)) # debug
|
||||
request.registry['payment.transaction'].form_feedback(request.cr, request.uid, post, 'adyen', context=request.context)
|
||||
return_url = post.pop('return_url', '')
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
<field name="env">test</field>
|
||||
<field name="message"><![CDATA[
|
||||
<p>You will be redirected to the Paypal website after cliking on the payment button.</p>]]></field>
|
||||
<field name="paypal_tx_url">https://www.sandbox.paypal.com/cgi-bin/webscr</field>
|
||||
<field name="paypal_email_id">dummy</field>
|
||||
<field name="paypal_seller_id">dummy</field>
|
||||
<field name="paypal_api_username">dummy</field>
|
||||
|
||||
@@ -24,7 +24,9 @@ import re
|
||||
|
||||
from _common import rounding
|
||||
from lxml import etree
|
||||
|
||||
from openerp.osv.orm import setup_modifiers
|
||||
from openerp import SUPERUSER_ID
|
||||
from openerp import tools
|
||||
from openerp.osv import osv, fields
|
||||
from openerp.tools.translate import _
|
||||
@@ -828,8 +830,13 @@ class product_product(osv.osv):
|
||||
|
||||
partner_id = context.get('partner_id', False)
|
||||
|
||||
# all user don't have access to seller and partner
|
||||
# check access and use superuser
|
||||
self.check_access_rights(cr, user, "read")
|
||||
self.check_access_rule(cr, user, ids, "read", context=context)
|
||||
|
||||
result = []
|
||||
for product in self.browse(cr, user, ids, context=context):
|
||||
for product in self.browse(cr, SUPERUSER_ID, ids, context=context):
|
||||
sellers = filter(lambda x: x.name.id == partner_id, product.seller_ids)
|
||||
if sellers:
|
||||
for s in sellers:
|
||||
|
||||
@@ -431,7 +431,7 @@
|
||||
<field name="name">product.public.category.form</field>
|
||||
<field name="model">product.public.category</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Product Categories" version="7.0">
|
||||
<form string="Pos/Public Categories" version="7.0">
|
||||
<sheet>
|
||||
<field name="image_medium" widget='image' class="oe_avatar oe_right"/>
|
||||
<div class="oe_left">
|
||||
@@ -457,7 +457,7 @@
|
||||
</field>
|
||||
</record>
|
||||
<record id="product_public_category_action" model="ir.actions.act_window">
|
||||
<field name="name">Public Categories</field>
|
||||
<field name="name">Pos/Public Product Categories</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">product.public.category</field>
|
||||
<field name="view_type">form</field>
|
||||
@@ -476,7 +476,7 @@
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
<menuitem action="product_public_category_action" id="menu_product_public_category" parent="base.menu_product" sequence="10" />
|
||||
<menuitem action="product_public_category_action" id="menu_product_public_category" parent="prod_config_main" sequence="10" />
|
||||
<!-- END -->
|
||||
|
||||
<!-- Unit of Measure -->
|
||||
|
||||
@@ -183,7 +183,7 @@ class Text(orm.AbstractModel):
|
||||
_inherit = ['website.qweb.field', 'ir.qweb.field.text']
|
||||
|
||||
def from_html(self, cr, uid, model, column, element, context=None):
|
||||
return element.text_content()
|
||||
return html_to_text(element)
|
||||
|
||||
class Selection(orm.AbstractModel):
|
||||
_name = 'website.qweb.field.selection'
|
||||
@@ -211,7 +211,8 @@ class ManyToOne(orm.AbstractModel):
|
||||
M2O = self.pool[column._obj]
|
||||
field = element.get('data-oe-field')
|
||||
id = int(element.get('data-oe-id'))
|
||||
value = element.text_content().strip()
|
||||
# FIXME: weird things are going to happen for char-type _rec_name
|
||||
value = html_to_text(element)
|
||||
|
||||
# if anything blows up, just ignore it and bail
|
||||
try:
|
||||
@@ -419,3 +420,102 @@ class Contact(orm.AbstractModel):
|
||||
}, engine='website.qweb', context=context)
|
||||
|
||||
return ir_qweb.HTMLSafe(html)
|
||||
|
||||
def html_to_text(element):
|
||||
""" Converts HTML content with HTML-specified line breaks (br, p, div, ...)
|
||||
in roughly equivalent textual content.
|
||||
|
||||
Used to replace and fixup the roundtripping of text and m2o: when using
|
||||
libxml 2.8.0 (but not 2.9.1) and parsing HTML with lxml.html.fromstring
|
||||
whitespace text nodes (text nodes composed *solely* of whitespace) are
|
||||
stripped out with no recourse, and fundamentally relying on newlines
|
||||
being in the text (e.g. inserted during user edition) is probably poor form
|
||||
anyway.
|
||||
|
||||
-> this utility function collapses whitespace sequences and replaces
|
||||
nodes by roughly corresponding linebreaks
|
||||
* p are pre-and post-fixed by 2 newlines
|
||||
* br are replaced by a single newline
|
||||
* block-level elements not already mentioned are pre- and post-fixed by
|
||||
a single newline
|
||||
|
||||
ought be somewhat similar (but much less high-tech) to aaronsw's html2text.
|
||||
the latter produces full-blown markdown, our text -> html converter only
|
||||
replaces newlines by <br> elements at this point so we're reverting that,
|
||||
and a few more newline-ish elements in case the user tried to add
|
||||
newlines/paragraphs into the text field
|
||||
|
||||
:param element: lxml.html content
|
||||
:returns: corresponding pure-text output
|
||||
"""
|
||||
|
||||
# output is a list of str | int. Integers are padding requests (in minimum
|
||||
# number of newlines). When multiple padding requests, fold them into the
|
||||
# biggest one
|
||||
output = []
|
||||
_wrap(element, output)
|
||||
|
||||
# remove any leading or tailing whitespace, replace sequences of
|
||||
# (whitespace)\n(whitespace) by a single newline, where (whitespace) is a
|
||||
# non-newline whitespace in this case
|
||||
return re.sub(
|
||||
r'[ \t\r\f]*\n[ \t\r\f]*',
|
||||
'\n',
|
||||
''.join(_realize_padding(output)).strip())
|
||||
|
||||
_PADDED_BLOCK = set('p h1 h2 h3 h4 h5 h6'.split())
|
||||
# https://developer.mozilla.org/en-US/docs/HTML/Block-level_elements minus p
|
||||
_MISC_BLOCK = set((
|
||||
'address article aside audio blockquote canvas dd dl div figcaption figure'
|
||||
' footer form header hgroup hr ol output pre section tfoot ul video'
|
||||
).split())
|
||||
|
||||
def _collapse_whitespace(text):
|
||||
""" Collapses sequences of whitespace characters in ``text`` to a single
|
||||
space
|
||||
"""
|
||||
return re.sub('\s+', ' ', text)
|
||||
def _realize_padding(it):
|
||||
""" Fold and convert padding requests: integers in the output sequence are
|
||||
requests for at least n newlines of padding. Runs thereof can be collapsed
|
||||
into the largest requests and converted to newlines.
|
||||
"""
|
||||
padding = None
|
||||
for item in it:
|
||||
if isinstance(item, int):
|
||||
padding = max(padding, item)
|
||||
continue
|
||||
|
||||
if padding:
|
||||
yield '\n' * padding
|
||||
padding = None
|
||||
|
||||
yield item
|
||||
# leftover padding irrelevant as the output will be stripped
|
||||
|
||||
def _wrap(element, output, wrapper=u''):
|
||||
""" Recursively extracts text from ``element`` (via _element_to_text), and
|
||||
wraps it all in ``wrapper``. Extracted text is added to ``output``
|
||||
|
||||
:type wrapper: basestring | int
|
||||
"""
|
||||
output.append(wrapper)
|
||||
if element.text:
|
||||
output.append(_collapse_whitespace(element.text))
|
||||
for child in element:
|
||||
_element_to_text(child, output)
|
||||
output.append(wrapper)
|
||||
|
||||
def _element_to_text(e, output):
|
||||
if e.tag == 'br':
|
||||
output.append(u'\n')
|
||||
elif e.tag in _PADDED_BLOCK:
|
||||
_wrap(e, output, 2)
|
||||
elif e.tag in _MISC_BLOCK:
|
||||
_wrap(e, output, 1)
|
||||
else:
|
||||
# inline
|
||||
_wrap(e, output)
|
||||
|
||||
if e.tail:
|
||||
output.append(_collapse_whitespace(e.tail))
|
||||
|
||||
@@ -624,7 +624,7 @@ class res_company(osv.osv):
|
||||
partner = self.browse(cr, openerp.SUPERUSER_ID, ids[0], context=context).partner_id
|
||||
return partner and partner.google_map_link(zoom, context=context) or None
|
||||
|
||||
class base_language_install(osv.osv):
|
||||
class base_language_install(osv.osv_memory):
|
||||
_inherit = "base.language.install"
|
||||
_columns = {
|
||||
'website_ids': fields.many2many('website', string='Websites to translate'),
|
||||
|
||||
@@ -81,6 +81,10 @@
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
.css_editable_display {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.css_non_editable_mode_hidden {
|
||||
display: none;
|
||||
}
|
||||
@@ -103,6 +107,14 @@
|
||||
top: 2px;
|
||||
}
|
||||
|
||||
.oe_structure.oe_empty:empty, [data-oe-type=html]:empty, .oe_structure.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/edit_here.png") !important;
|
||||
}
|
||||
|
||||
.oe_structure.oe_empty:empty:before, [data-oe-type=html]:empty:before, .oe_structure.oe_empty > .oe_drop_zone.oe_insert:only-child:before, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child:before {
|
||||
content: "Press The Top-Left Edit Button" !important;
|
||||
}
|
||||
|
||||
/* ---- EDITOR BAR ---- {{{ */
|
||||
table.editorbar-panel {
|
||||
cursor: pointer;
|
||||
@@ -432,6 +444,10 @@ ul.oe_menu_editor .disclose {
|
||||
}
|
||||
|
||||
/* ---- SNIPPET MANIPULATOR ---- {{{ */
|
||||
.resize_editor_busy {
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.oe_overlay {
|
||||
display: none;
|
||||
position: absolute;
|
||||
@@ -514,16 +530,28 @@ ul.oe_menu_editor .disclose {
|
||||
.oe_overlay .oe_handle.e:before {
|
||||
content: "\F061";
|
||||
}
|
||||
.oe_overlay .oe_handle.s {
|
||||
.oe_overlay .oe_handle.s, .oe_overlay .oe_handle.size {
|
||||
top: auto;
|
||||
left: 2px;
|
||||
width: 100%;
|
||||
bottom: -4px;
|
||||
cursor: n-resize;
|
||||
}
|
||||
.oe_overlay .oe_handle.s:before {
|
||||
.oe_overlay .oe_handle.s:before, .oe_overlay .oe_handle.size:before {
|
||||
content: "\F063";
|
||||
}
|
||||
.oe_overlay .oe_handle.size {
|
||||
border-style: dashed;
|
||||
border-width: 0 0 1px 0;
|
||||
border-color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
.oe_overlay .oe_handle.size:before {
|
||||
content: "Resize";
|
||||
width: 64px;
|
||||
text-align: center;
|
||||
margin-left: -32px;
|
||||
margin-top: -4px;
|
||||
}
|
||||
.oe_overlay .oe_handle.w {
|
||||
top: 2px;
|
||||
height: 100%;
|
||||
|
||||
@@ -67,6 +67,9 @@
|
||||
.oe_editable:focus
|
||||
outline: none !important
|
||||
|
||||
.css_editable_display
|
||||
display: block !important
|
||||
|
||||
.css_non_editable_mode_hidden
|
||||
display: none
|
||||
|
||||
@@ -85,6 +88,12 @@
|
||||
position: relative !important
|
||||
top: +2px
|
||||
|
||||
.oe_structure.oe_empty:empty, [data-oe-type=html]:empty, .oe_structure.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/edit_here.png') !important
|
||||
|
||||
.oe_structure.oe_empty:empty:before, [data-oe-type=html]:empty:before, .oe_structure.oe_empty > .oe_drop_zone.oe_insert:only-child:before, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child:before
|
||||
content: 'Press The Top-Left Edit Button' !important
|
||||
|
||||
// }}}
|
||||
|
||||
/* ---- EDITOR BAR ---- {{{ */
|
||||
@@ -349,6 +358,8 @@ ul.oe_menu_editor
|
||||
|
||||
/* ---- SNIPPET MANIPULATOR ---- {{{ */
|
||||
|
||||
.resize_editor_busy
|
||||
background-color: rgba(0,0,0,0.3)
|
||||
.oe_overlay
|
||||
display: none
|
||||
position: absolute
|
||||
@@ -403,7 +414,7 @@ ul.oe_menu_editor
|
||||
cursor: w-resize
|
||||
&:before
|
||||
content: "\F061"
|
||||
.oe_handle.s
|
||||
.oe_handle.s, .oe_handle.size
|
||||
top: auto
|
||||
left: 2px
|
||||
width: 100%
|
||||
@@ -411,6 +422,16 @@ ul.oe_menu_editor
|
||||
cursor: n-resize
|
||||
&:before
|
||||
content: "\F063"
|
||||
.oe_handle.size
|
||||
border-style: dashed
|
||||
border-width: 0 0 1px 0
|
||||
border-color: rgba(0, 0, 0, 0.5)
|
||||
&:before
|
||||
content: "Resize"
|
||||
width: 64px
|
||||
text-align: center
|
||||
margin-left: -32px
|
||||
margin-top: -4px
|
||||
.oe_handle.w
|
||||
top: 2px
|
||||
height: 100%
|
||||
|
||||
@@ -78,95 +78,6 @@
|
||||
margin-bottom: 0px !important;
|
||||
}
|
||||
|
||||
.pt128 {
|
||||
padding-top: 128px !important;
|
||||
}
|
||||
|
||||
.pt92 {
|
||||
padding-top: 92px !important;
|
||||
}
|
||||
|
||||
.pt64 {
|
||||
padding-top: 64px !important;
|
||||
}
|
||||
|
||||
.pt48 {
|
||||
padding-top: 48px !important;
|
||||
}
|
||||
|
||||
.pt32 {
|
||||
padding-top: 32px !important;
|
||||
}
|
||||
|
||||
.pt16 {
|
||||
padding-top: 16px !important;
|
||||
}
|
||||
|
||||
.pt8 {
|
||||
padding-top: 8px !important;
|
||||
}
|
||||
|
||||
.pt4 {
|
||||
padding-top: 4px !important;
|
||||
}
|
||||
|
||||
.pt0 {
|
||||
padding-top: 0px !important;
|
||||
}
|
||||
|
||||
.pb128 {
|
||||
padding-bottom: 128px !important;
|
||||
}
|
||||
|
||||
.pb92 {
|
||||
padding-bottom: 92px !important;
|
||||
}
|
||||
|
||||
.pb64 {
|
||||
padding-bottom: 64px !important;
|
||||
}
|
||||
|
||||
.pb48 {
|
||||
padding-bottom: 48px !important;
|
||||
}
|
||||
|
||||
.pb32 {
|
||||
padding-bottom: 32px !important;
|
||||
}
|
||||
|
||||
.pb16 {
|
||||
padding-bottom: 16px !important;
|
||||
}
|
||||
|
||||
.pb8 {
|
||||
padding-bottom: 8px !important;
|
||||
}
|
||||
|
||||
.pb4 {
|
||||
padding-bottom: 4px !important;
|
||||
}
|
||||
|
||||
.pb0 {
|
||||
padding-bottom: 0px !important;
|
||||
}
|
||||
|
||||
/* Grid of unequally tall elements */
|
||||
.grid > [class*="col-md"] {
|
||||
display: inline-block;
|
||||
float: none;
|
||||
vertical-align: top;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.grid > [class*="col-md"].grid-align-top > [class*="col-md"] {
|
||||
vertical-align: top;
|
||||
}
|
||||
.grid > [class*="col-md"].grid-align-middle > [class*="col-md"] {
|
||||
vertical-align: middle;
|
||||
}
|
||||
.grid > [class*="col-md"].grid-align-bottom > [class*="col-md"] {
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
/* Extra Styles */
|
||||
img.shadow {
|
||||
-webkit-border-radius: 3px;
|
||||
@@ -185,9 +96,14 @@ h1.text-muted, h2.text-muted, h3.text-muted {
|
||||
}
|
||||
|
||||
/* ----- BOOTSTRAP HACK FOR HEADER NAV BAR ----- */
|
||||
.navbar.navbar-default.navbar-static-top {
|
||||
.navbar.navbar-static-top {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.navbar.navbar-static-top ul.nav > li.divider {
|
||||
margin-top: 15px;
|
||||
padding-top: 20px;
|
||||
border-right: 1px solid grey;
|
||||
}
|
||||
|
||||
/* ----- BOOTSTRAP HACK FOR STICKY FOOTER ----- */
|
||||
html, body, #wrapwrap {
|
||||
@@ -209,7 +125,7 @@ header, main, footer {
|
||||
footer {
|
||||
height: 100%;
|
||||
background: #eff8f8;
|
||||
background: rgba(100, 200, 200, 0.1);
|
||||
background: rgba(200, 200, 200, 0.1);
|
||||
}
|
||||
|
||||
#footer_container {
|
||||
@@ -233,7 +149,7 @@ footer {
|
||||
}
|
||||
|
||||
.oe_structure.oe_empty:empty, [data-oe-type=html]:empty, .oe_structure.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/edit_here.png");
|
||||
background-image: url("/website/static/src/img/under_construction.png");
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
height: 220px !important;
|
||||
@@ -244,7 +160,7 @@ footer {
|
||||
}
|
||||
|
||||
.oe_structure.oe_empty:empty:before, [data-oe-type=html]:empty:before, .oe_structure.oe_empty > .oe_drop_zone.oe_insert:only-child:before, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child:before {
|
||||
content: "Press The Top-Left Edit Button";
|
||||
content: "This page is under construction";
|
||||
text-align: center;
|
||||
display: block;
|
||||
padding-top: 160px;
|
||||
@@ -257,6 +173,10 @@ footer {
|
||||
content: "Drag Building Blocks Here";
|
||||
}
|
||||
|
||||
.css_editable_display {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* ---- HACK FOR COVERING UP CK EDITOR BOGUS P INSERTION --- */
|
||||
.navbar .nav > li > p {
|
||||
margin-bottom: 0px;
|
||||
@@ -334,20 +254,23 @@ ul.nav-stacked > li > a {
|
||||
}
|
||||
|
||||
/* ---- SNIPPETS --- */
|
||||
[data-snippet-id], .colmd, .hr, .blockquote {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@media (max-width: 400px) {
|
||||
[data-snippet-id] {
|
||||
height: auto !important;
|
||||
}
|
||||
}
|
||||
.carousel-inner {
|
||||
height: 100%;
|
||||
}
|
||||
.carousel-inner .item {
|
||||
height: 100%;
|
||||
background-size: 100%;
|
||||
}
|
||||
|
||||
.carousel.oe_small .carousel-inner {
|
||||
height: 200px;
|
||||
}
|
||||
.carousel.oe_medium .carousel-inner {
|
||||
height: 300px;
|
||||
}
|
||||
.carousel.oe_big .carousel-inner {
|
||||
height: 450px;
|
||||
}
|
||||
.carousel .carousel-caption {
|
||||
left: auto;
|
||||
right: auto;
|
||||
@@ -434,7 +357,7 @@ div.carousel[data-snippet-id="slider"] .carousel-indicators .active {
|
||||
/* Background */
|
||||
.oe_dark {
|
||||
background: #eff8f8;
|
||||
background: rgba(100, 200, 200, 0.14);
|
||||
background: rgba(200, 200, 200, 0.14);
|
||||
-webkit-box-shadow: 0px 5px 9px -7px rgba(0, 0, 255, 0.5) inset, 0px -3px 9px -7px rgba(0, 0, 255, 0.5) inset;
|
||||
-moz-box-shadow: 0px 5px 9px -7px rgba(0, 0, 255, 0.5) inset, 0px -3px 9px -7px rgba(0, 0, 255, 0.5) inset;
|
||||
box-shadow: 0px 5px 9px -7px rgba(0, 0, 255, 0.5) inset, 0px -3px 9px -7px rgba(0, 0, 255, 0.5) inset;
|
||||
@@ -442,16 +365,55 @@ div.carousel[data-snippet-id="slider"] .carousel-indicators .active {
|
||||
|
||||
.oe_black {
|
||||
background-color: rgba(0, 0, 0, 0.9);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.oe_green {
|
||||
background-color: rgba(0, 128, 0, 0.8);
|
||||
background-color: #51d466;
|
||||
color: white;
|
||||
}
|
||||
.oe_green .text-muted {
|
||||
color: #dddddd;
|
||||
}
|
||||
|
||||
.oe_blue_light {
|
||||
background-color: #4791d2;
|
||||
color: white;
|
||||
}
|
||||
.oe_blue_light .text-muted {
|
||||
color: #dddddd;
|
||||
}
|
||||
|
||||
.oe_blue {
|
||||
background-color: #34495e;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.oe_orange {
|
||||
background-color: #e67e22;
|
||||
color: white;
|
||||
}
|
||||
.oe_orange .text-muted {
|
||||
color: #dddddd;
|
||||
}
|
||||
|
||||
.oe_purple {
|
||||
background-color: #b163a3;
|
||||
color: white;
|
||||
}
|
||||
.oe_purple .text-muted {
|
||||
color: #dddddd;
|
||||
}
|
||||
|
||||
.oe_red {
|
||||
background-color: rgba(255, 0, 0, 0.8);
|
||||
background-color: #f75353;
|
||||
color: white;
|
||||
}
|
||||
.oe_red .text-muted {
|
||||
color: #dddddd;
|
||||
}
|
||||
|
||||
/* Misc */
|
||||
.oe_img_bg {
|
||||
background-size: 100%;
|
||||
}
|
||||
@@ -511,45 +473,3 @@ span[data-oe-type="monetary"] {
|
||||
-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;
|
||||
}
|
||||
|
||||
@@ -51,57 +51,6 @@
|
||||
.mb0
|
||||
margin-bottom: 0px !important
|
||||
|
||||
.pt128
|
||||
padding-top: 128px !important
|
||||
.pt92
|
||||
padding-top: 92px !important
|
||||
.pt64
|
||||
padding-top: 64px !important
|
||||
.pt48
|
||||
padding-top: 48px !important
|
||||
.pt32
|
||||
padding-top: 32px !important
|
||||
.pt16
|
||||
padding-top: 16px !important
|
||||
.pt8
|
||||
padding-top: 8px !important
|
||||
.pt4
|
||||
padding-top: 4px !important
|
||||
.pt0
|
||||
padding-top: 0px !important
|
||||
|
||||
.pb128
|
||||
padding-bottom: 128px !important
|
||||
.pb92
|
||||
padding-bottom: 92px !important
|
||||
.pb64
|
||||
padding-bottom: 64px !important
|
||||
.pb48
|
||||
padding-bottom: 48px !important
|
||||
.pb32
|
||||
padding-bottom: 32px !important
|
||||
.pb16
|
||||
padding-bottom: 16px !important
|
||||
.pb8
|
||||
padding-bottom: 8px !important
|
||||
.pb4
|
||||
padding-bottom: 4px !important
|
||||
.pb0
|
||||
padding-bottom: 0px !important
|
||||
|
||||
/* Grid of unequally tall elements */
|
||||
.grid > [class*="col-md"]
|
||||
display: inline-block
|
||||
float: none
|
||||
vertical-align: top
|
||||
box-sizing: border-box
|
||||
&.grid-align-top > [class*="col-md"]
|
||||
vertical-align: top
|
||||
&.grid-align-middle > [class*="col-md"]
|
||||
vertical-align: middle
|
||||
&.grid-align-bottom > [class*="col-md"]
|
||||
vertical-align: bottom
|
||||
|
||||
/* Extra Styles */
|
||||
|
||||
img.shadow
|
||||
@@ -114,8 +63,13 @@ h1.text-muted, h2.text-muted, h3.text-muted
|
||||
|
||||
/* ----- BOOTSTRAP HACK FOR HEADER NAV BAR ----- */
|
||||
|
||||
.navbar.navbar-default.navbar-static-top
|
||||
.navbar.navbar-static-top
|
||||
margin-bottom: 0
|
||||
ul.nav
|
||||
> li.divider
|
||||
margin-top: 15px
|
||||
padding-top: 20px
|
||||
border-right: 1px solid grey
|
||||
|
||||
/* ----- BOOTSTRAP HACK FOR STICKY FOOTER ----- */
|
||||
|
||||
@@ -133,7 +87,7 @@ header, main, footer
|
||||
footer
|
||||
height: 100%
|
||||
background: rgb(239, 248, 248)
|
||||
background: rgba(100, 200, 200, 0.1)
|
||||
background: rgba(200, 200, 200, 0.1)
|
||||
|
||||
#footer_container
|
||||
padding-top: 24px
|
||||
@@ -154,7 +108,7 @@ footer
|
||||
background-image: url('/website/static/src/img/drag_here.png')
|
||||
|
||||
.oe_structure.oe_empty:empty, [data-oe-type=html]:empty, .oe_structure.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/edit_here.png')
|
||||
background-image: url('/website/static/src/img/under_construction.png')
|
||||
background-repeat: no-repeat
|
||||
background-position: center
|
||||
height: 220px !important
|
||||
@@ -163,7 +117,7 @@ footer
|
||||
position: static
|
||||
|
||||
.oe_structure.oe_empty:empty:before, [data-oe-type=html]:empty:before, .oe_structure.oe_empty > .oe_drop_zone.oe_insert:only-child:before, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child:before
|
||||
content: 'Press The Top-Left Edit Button'
|
||||
content: 'This page is under construction'
|
||||
text-align: center
|
||||
display: block
|
||||
padding-top: 160px
|
||||
@@ -174,6 +128,9 @@ footer
|
||||
.oe_structure.oe_editable.oe_empty:empty:before, .oe_editable[data-oe-type=html]:empty:before, .oe_structure.oe_editable.oe_empty > .oe_drop_zone.oe_insert:only-child:before, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child:before
|
||||
content: 'Drag Building Blocks Here'
|
||||
|
||||
.css_editable_display
|
||||
display: none
|
||||
|
||||
/* ---- HACK FOR COVERING UP CK EDITOR BOGUS P INSERTION --- */
|
||||
|
||||
.navbar .nav > li > p
|
||||
@@ -242,18 +199,19 @@ ul.nav-stacked > li > a
|
||||
color: white
|
||||
|
||||
/* ---- SNIPPETS --- */
|
||||
[data-snippet-id],.colmd,.hr,.blockquote
|
||||
overflow: hidden
|
||||
|
||||
.carousel-inner .item
|
||||
@media (max-width: 400px)
|
||||
[data-snippet-id]
|
||||
height: auto !important
|
||||
|
||||
.carousel-inner
|
||||
height: 100%
|
||||
background-size: 100%
|
||||
|
||||
.item
|
||||
height: 100%
|
||||
background-size: 100%
|
||||
.carousel
|
||||
&.oe_small .carousel-inner
|
||||
height: 200px
|
||||
&.oe_medium .carousel-inner
|
||||
height: 300px
|
||||
&.oe_big .carousel-inner
|
||||
height: 450px
|
||||
.carousel-caption
|
||||
left: auto
|
||||
right: auto
|
||||
@@ -326,17 +284,52 @@ div.carousel[data-snippet-id="slider"]
|
||||
padding: 32px 0
|
||||
|
||||
/* Background */
|
||||
|
||||
|
||||
.oe_dark
|
||||
background: #eff8f8
|
||||
background: rgba(100, 200, 200, 0.14)
|
||||
background: rgba(200, 200, 200, 0.14)
|
||||
+box-shadow(0px 5px 9px -7px rgba(0, 0, 255, 0.5) inset, 0px -3px 9px -7px rgba(0, 0, 255, 0.5) inset)
|
||||
|
||||
.oe_black
|
||||
background-color: rgba(0, 0, 0, 0.9)
|
||||
color: white
|
||||
|
||||
.oe_green
|
||||
background-color: rgba(0, 128, 0, 0.8)
|
||||
background-color: #51d466
|
||||
color: white
|
||||
.text-muted
|
||||
color: #ddd
|
||||
|
||||
.oe_blue_light
|
||||
background-color: #4791d2
|
||||
color: white
|
||||
.text-muted
|
||||
color: #ddd
|
||||
|
||||
.oe_blue
|
||||
background-color: #34495e
|
||||
color: white
|
||||
|
||||
.oe_orange
|
||||
background-color: #e67e22
|
||||
color: white
|
||||
.text-muted
|
||||
color: #ddd
|
||||
|
||||
.oe_purple
|
||||
background-color: #b163a3
|
||||
color: white
|
||||
.text-muted
|
||||
color: #ddd
|
||||
|
||||
.oe_red
|
||||
background-color: rgba(255, 0, 0, 0.8)
|
||||
background-color: #f75353
|
||||
color: white
|
||||
.text-muted
|
||||
color: #ddd
|
||||
|
||||
/* Misc */
|
||||
|
||||
.oe_img_bg
|
||||
background-size: 100%
|
||||
|
||||
@@ -382,30 +375,3 @@ span[data-oe-type="monetary"]
|
||||
.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
|
||||
// }}}
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 6.4 KiB |
@@ -94,6 +94,11 @@
|
||||
}).then(function (views) {
|
||||
self.loadViews.call(self, views);
|
||||
self.open.call(self);
|
||||
// cf. fp's direct request
|
||||
if (views.length >= 2) {
|
||||
var mainTemplate = views[1];
|
||||
self.$('#ace-view-list').val(mainTemplate.id).trigger('change');
|
||||
}
|
||||
});
|
||||
|
||||
var $editor = self.$('.ace_editor');
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
}
|
||||
});
|
||||
}
|
||||
$.getJSON("http://seo.eu01.aws.af.cm/suggest/"+encodeURIComponent(this.root + " "), addSuggestions);
|
||||
$.getJSON("http://suggest.hp.af.cm/suggest/"+encodeURIComponent(this.root + " "), addSuggestions);
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -126,6 +126,9 @@
|
||||
self.make_active(false);
|
||||
self.$el.toggleClass("hidden");
|
||||
});
|
||||
$("#wrapwrap").click(function () {
|
||||
self.$el.addClass("hidden");
|
||||
});
|
||||
|
||||
this.fetch_snippet_templates();
|
||||
|
||||
@@ -181,6 +184,7 @@
|
||||
'top': pos.top - mt,
|
||||
'left': pos.left
|
||||
});
|
||||
$el.find(".oe_handle.size").css("bottom", mb+'px');
|
||||
},
|
||||
show: function () {
|
||||
this.$el.removeClass("hidden");
|
||||
@@ -678,17 +682,6 @@
|
||||
});
|
||||
|
||||
|
||||
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);
|
||||
},
|
||||
preview: function (event, np) {
|
||||
this._super(event, np);
|
||||
this.parent.parent.cover_target(this.$overlay, this.$target);
|
||||
}
|
||||
});
|
||||
|
||||
website.snippet.styleRegistry.background = website.snippet.StyleEditor.extend({
|
||||
_get_bg: function () {
|
||||
return this.$target.css("background-image").replace(/url\(['"]*|['"]*\)|^none$/g, "");
|
||||
@@ -879,7 +872,7 @@
|
||||
}
|
||||
var Editor = website.snippet.styleRegistry[val['snippet-style-id']] || website.snippet.StyleEditor;
|
||||
var editor = new Editor(self, self.$target, val['snippet-style-id']);
|
||||
$ul.prepend(editor.$el);
|
||||
$ul.prepend(editor.$el.addClass("snippet-style-" + val['snippet-style-id']));
|
||||
});
|
||||
|
||||
if ($ul.find("li").length) {
|
||||
@@ -973,96 +966,121 @@
|
||||
if (!resize_values.s) $box.find(".oe_handle.s").remove();
|
||||
if (!resize_values.e) $box.find(".oe_handle.e").remove();
|
||||
if (!resize_values.w) $box.find(".oe_handle.w").remove();
|
||||
if (!resize_values.size) $box.find(".oe_handle.size").remove();
|
||||
|
||||
this.$overlay.append($box.find(".oe_handles").html());
|
||||
|
||||
this.$overlay.find(".oe_handle").on('mousedown', function (event){
|
||||
event.preventDefault();
|
||||
event.preventDefault();
|
||||
|
||||
var $handle = $(this);
|
||||
var $handle = $(this);
|
||||
|
||||
var resize_values = self.getSize();
|
||||
var compass = false;
|
||||
var XY = false;
|
||||
if ($handle.hasClass('n')) {
|
||||
compass = 'n';
|
||||
XY = 'Y';
|
||||
}
|
||||
else if ($handle.hasClass('s')) {
|
||||
compass = 's';
|
||||
XY = 'Y';
|
||||
}
|
||||
else if ($handle.hasClass('e')) {
|
||||
compass = 'e';
|
||||
XY = 'X';
|
||||
}
|
||||
else if ($handle.hasClass('w')) {
|
||||
compass = 'w';
|
||||
XY = 'X';
|
||||
}
|
||||
var resize_values = self.getSize();
|
||||
var compass = false;
|
||||
var XY = false;
|
||||
if ($handle.hasClass('n')) {
|
||||
compass = 'n';
|
||||
XY = 'Y';
|
||||
}
|
||||
else if ($handle.hasClass('s')) {
|
||||
compass = 's';
|
||||
XY = 'Y';
|
||||
}
|
||||
else if ($handle.hasClass('e')) {
|
||||
compass = 'e';
|
||||
XY = 'X';
|
||||
}
|
||||
else if ($handle.hasClass('w')) {
|
||||
compass = 'w';
|
||||
XY = 'X';
|
||||
}
|
||||
else if ($handle.hasClass('size')) {
|
||||
compass = 'size';
|
||||
XY = 'Y';
|
||||
}
|
||||
|
||||
var resize = resize_values[compass];
|
||||
if (!resize) return;
|
||||
var resize = resize_values[compass];
|
||||
if (!resize) return;
|
||||
|
||||
|
||||
if (compass === 'size') {
|
||||
var grid = resize[0];
|
||||
var offset = self.$target.offset().top;
|
||||
if (self.$target.css("background").match(/rgba\(0, 0, 0, 0\)/)) {
|
||||
self.$target.addClass("resize_editor_busy");
|
||||
}
|
||||
} else {
|
||||
var xy = event['page'+XY];
|
||||
var current = resize[2] || 0;
|
||||
_.each(resize[0], function (val, key) {
|
||||
if (self.$target.hasClass(val)) {
|
||||
current = key;
|
||||
}
|
||||
});
|
||||
|
||||
self.parent.editor_busy = true;
|
||||
|
||||
var xy = event['page'+XY];
|
||||
var begin = current;
|
||||
var beginClass = self.$target.attr("class");
|
||||
var regClass = new RegExp("\\s*" + resize[0][begin].replace(/[-]*[0-9]+/, '[-]*[0-9]+'), 'g');
|
||||
}
|
||||
|
||||
var cursor = $handle.css("cursor")+'-important';
|
||||
var $body = $(document.body);
|
||||
$body.addClass(cursor);
|
||||
self.parent.editor_busy = true;
|
||||
|
||||
var body_mousemove = function (event){
|
||||
event.preventDefault();
|
||||
var dd = event['page'+XY] - xy + resize[1][begin];
|
||||
var next = current+1 === resize[1].length ? current : (current+1);
|
||||
var prev = current ? (current-1) : 0;
|
||||
var cursor = $handle.css("cursor")+'-important';
|
||||
var $body = $(document.body);
|
||||
$body.addClass(cursor);
|
||||
|
||||
var change = false;
|
||||
if (dd > (2*resize[1][next] + resize[1][current])/3) {
|
||||
self.$target.attr("class", (self.$target.attr("class")||'').replace(regClass, ''));
|
||||
self.$target.addClass(resize[0][next]);
|
||||
current = next;
|
||||
change = true;
|
||||
}
|
||||
if (prev != current && dd < (2*resize[1][prev] + resize[1][current])/3) {
|
||||
self.$target.attr("class", (self.$target.attr("class")||'').replace(regClass, ''));
|
||||
self.$target.addClass(resize[0][prev]);
|
||||
current = prev;
|
||||
change = true;
|
||||
}
|
||||
var body_mousemove = function (event){
|
||||
event.preventDefault();
|
||||
if (compass === 'size') {
|
||||
var dy = event.pageY-offset;
|
||||
dy = dy - dy%resize[0];
|
||||
if (dy <= 0) dy = resize[0];
|
||||
self.$target.css("height", dy+"px");
|
||||
self.on_resize(compass, beginClass, current);
|
||||
self.parent.cover_target(self.$overlay, self.$target);
|
||||
return;
|
||||
}
|
||||
var dd = event['page'+XY] - xy + resize[1][begin];
|
||||
var next = current+1 === resize[1].length ? current : (current+1);
|
||||
var prev = current ? (current-1) : 0;
|
||||
|
||||
if (change) {
|
||||
self.on_resize(compass, beginClass, current);
|
||||
self.parent.cover_target(self.$overlay, self.$target);
|
||||
}
|
||||
};
|
||||
var change = false;
|
||||
if (dd > (2*resize[1][next] + resize[1][current])/3) {
|
||||
self.$target.attr("class", (self.$target.attr("class")||'').replace(regClass, ''));
|
||||
self.$target.addClass(resize[0][next]);
|
||||
current = next;
|
||||
change = true;
|
||||
}
|
||||
if (prev != current && dd < (2*resize[1][prev] + resize[1][current])/3) {
|
||||
self.$target.attr("class", (self.$target.attr("class")||'').replace(regClass, ''));
|
||||
self.$target.addClass(resize[0][prev]);
|
||||
current = prev;
|
||||
change = true;
|
||||
}
|
||||
|
||||
var body_mouseup = function(){
|
||||
$body.unbind('mousemove', body_mousemove);
|
||||
$body.unbind('mouseup', body_mouseup);
|
||||
$body.removeClass(cursor);
|
||||
self.parent.editor_busy = false;
|
||||
};
|
||||
$body.mousemove(body_mousemove);
|
||||
$body.mouseup(body_mouseup);
|
||||
});
|
||||
if (change) {
|
||||
self.on_resize(compass, beginClass, current);
|
||||
self.parent.cover_target(self.$overlay, self.$target);
|
||||
}
|
||||
};
|
||||
|
||||
var body_mouseup = function(){
|
||||
$body.unbind('mousemove', body_mousemove);
|
||||
$body.unbind('mouseup', body_mouseup);
|
||||
$body.removeClass(cursor);
|
||||
self.parent.editor_busy = false;
|
||||
self.$target.removeClass("resize_editor_busy");
|
||||
};
|
||||
$body.mousemove(body_mousemove);
|
||||
$body.mouseup(body_mouseup);
|
||||
});
|
||||
},
|
||||
getSize: function () {
|
||||
var grid = [0,4,8,16,32,48,64,92,128];
|
||||
this.grid = {
|
||||
// list of class (Array), grid (Array), default value (INT)
|
||||
n: [_.map(grid, function (v) {return 'mt'+v;}), grid],
|
||||
s: [_.map(grid, function (v) {return 'mb'+v;}), grid]
|
||||
s: [_.map(grid, function (v) {return 'mb'+v;}), grid],
|
||||
size: [8]
|
||||
};
|
||||
return this.grid;
|
||||
},
|
||||
@@ -1089,6 +1107,8 @@
|
||||
var grid = [-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11];
|
||||
this.grid.w = [_.map(grid, function (v) {return 'col-md-offset-'+v;}), _.map(grid, function (v) {return width/12*v;}), 12];
|
||||
|
||||
this.grid.s = null;
|
||||
|
||||
return this.grid;
|
||||
},
|
||||
_drag_and_drop_after_insert_dropzone: function(){
|
||||
@@ -1277,6 +1297,10 @@
|
||||
this.$target.css("background-image", "");
|
||||
this.$target.removeClass(this._class);
|
||||
},
|
||||
load_style_options : function () {
|
||||
this._super();
|
||||
$(".snippet-style-size li[data-class='']").remove();
|
||||
},
|
||||
start : function () {
|
||||
var self = this;
|
||||
this._super();
|
||||
|
||||
@@ -291,7 +291,7 @@
|
||||
var self = this;
|
||||
var testId = 'test_'+tour.id+'_tour';
|
||||
this.tours.push(tour);
|
||||
var stepDelay = 500; //ms
|
||||
var defaultDelay = 500; //ms
|
||||
var test = {
|
||||
id: tour.id,
|
||||
run: function (force) {
|
||||
@@ -299,31 +299,33 @@
|
||||
this.reset();
|
||||
}
|
||||
var actionSteps = _.filter(tour.steps, function (step) {
|
||||
return step.trigger;
|
||||
return step.trigger || step.sampleText;
|
||||
});
|
||||
function executeStep (step) {
|
||||
window.localStorage.setItem(testId, step.stepId);
|
||||
step.triggers(function () {
|
||||
function next () {
|
||||
var nextStep = actionSteps.shift();
|
||||
if (nextStep) {
|
||||
// Ensure the previous step has been fully propagated
|
||||
setTimeout(function () {
|
||||
setTimeout(function () {
|
||||
executeStep(nextStep);
|
||||
}, stepDelay);
|
||||
}, 0);
|
||||
executeStep(nextStep);
|
||||
} 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') {
|
||||
$element.trigger($.Event("change", { srcElement: $element }));
|
||||
} else {
|
||||
$element.trigger($.Event("click", { srcElement: $element }));
|
||||
}
|
||||
setTimeout(function () {
|
||||
if (step.triggers) step.triggers(next);
|
||||
var $element = $(step.element);
|
||||
if (step.snippet && step.trigger === 'drag') {
|
||||
website.TestConsole.dragAndDropSnippet(step.snippet);
|
||||
} else if (step.trigger && step.trigger.id === 'change') {
|
||||
$element.trigger($.Event("change", { srcElement: $element }));
|
||||
} else if (step.sampleText) {
|
||||
$element.val(step.sampleText);
|
||||
$element.trigger($.Event("change", { srcElement: $element }));
|
||||
} else if ($element.is(":visible")) { // Click by default
|
||||
$element.trigger($.Event("click", { srcElement: $element }));
|
||||
}
|
||||
if (!step.triggers) next();
|
||||
}, step.delay || defaultDelay);
|
||||
}
|
||||
var url = new website.UrlParser(window.location.href);
|
||||
if (tour.path && url.pathname !== tour.path) {
|
||||
@@ -342,11 +344,7 @@
|
||||
executeStep(currentStep);
|
||||
});
|
||||
} else {
|
||||
setTimeout(function () {
|
||||
setTimeout(function () {
|
||||
executeStep(currentStep);
|
||||
}, stepDelay);
|
||||
}, 0);
|
||||
executeStep(currentStep);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -86,6 +86,7 @@
|
||||
<div class='oe_handle n'></div>
|
||||
<div class='oe_handle e'></div>
|
||||
<div class='oe_handle w'></div>
|
||||
<div class='oe_handle size'></div>
|
||||
<div class='oe_handle s'></div>
|
||||
</div>
|
||||
<div class='oe_snippet_thumbnail'>Margin resize</div>
|
||||
|
||||
@@ -1,15 +1,120 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from functools import partial
|
||||
import textwrap
|
||||
import unittest2
|
||||
from xml.dom.minidom import getDOMImplementation
|
||||
|
||||
from lxml import html
|
||||
from lxml.builder import E
|
||||
|
||||
from openerp.tests import common
|
||||
from openerp.addons.base.ir import ir_qweb
|
||||
from openerp.addons.website.models.ir_qweb import html_to_text
|
||||
|
||||
impl = getDOMImplementation()
|
||||
document = impl.createDocument(None, None, None)
|
||||
|
||||
class TestHTMLToText(unittest2.TestCase):
|
||||
def test_rawstring(self):
|
||||
self.assertEqual(
|
||||
"foobar",
|
||||
html_to_text(E.div("foobar")))
|
||||
|
||||
def test_br(self):
|
||||
self.assertEqual(
|
||||
"foo\nbar",
|
||||
html_to_text(E.div("foo", E.br(), "bar")))
|
||||
|
||||
self.assertEqual(
|
||||
"foo\n\nbar\nbaz",
|
||||
html_to_text(E.div(
|
||||
"foo", E.br(), E.br(),
|
||||
"bar", E.br(),
|
||||
"baz")))
|
||||
|
||||
def test_p(self):
|
||||
self.assertEqual(
|
||||
"foo\n\nbar\n\nbaz",
|
||||
html_to_text(E.div(
|
||||
"foo",
|
||||
E.p("bar"),
|
||||
"baz")))
|
||||
|
||||
self.assertEqual(
|
||||
"foo",
|
||||
html_to_text(E.div(E.p("foo"))))
|
||||
|
||||
self.assertEqual(
|
||||
"foo\n\nbar",
|
||||
html_to_text(E.div("foo", E.p("bar"))))
|
||||
self.assertEqual(
|
||||
"foo\n\nbar",
|
||||
html_to_text(E.div(E.p("foo"), "bar")))
|
||||
|
||||
self.assertEqual(
|
||||
"foo\n\nbar\n\nbaz",
|
||||
html_to_text(E.div(
|
||||
E.p("foo"),
|
||||
E.p("bar"),
|
||||
E.p("baz"),
|
||||
)))
|
||||
|
||||
def test_div(self):
|
||||
self.assertEqual(
|
||||
"foo\nbar\nbaz",
|
||||
html_to_text(E.div(
|
||||
"foo",
|
||||
E.div("bar"),
|
||||
"baz"
|
||||
)))
|
||||
|
||||
self.assertEqual(
|
||||
"foo",
|
||||
html_to_text(E.div(E.div("foo"))))
|
||||
|
||||
self.assertEqual(
|
||||
"foo\nbar",
|
||||
html_to_text(E.div("foo", E.div("bar"))))
|
||||
self.assertEqual(
|
||||
"foo\nbar",
|
||||
html_to_text(E.div(E.div("foo"), "bar")))
|
||||
|
||||
self.assertEqual(
|
||||
"foo\nbar\nbaz",
|
||||
html_to_text(E.div(
|
||||
"foo",
|
||||
E.div("bar"),
|
||||
E.div("baz")
|
||||
)))
|
||||
|
||||
def test_other_block(self):
|
||||
self.assertEqual(
|
||||
"foo\nbar\nbaz",
|
||||
html_to_text(E.div(
|
||||
"foo",
|
||||
E.section("bar"),
|
||||
"baz"
|
||||
)))
|
||||
|
||||
def test_inline(self):
|
||||
self.assertEqual(
|
||||
"foobarbaz",
|
||||
html_to_text(E.div("foo", E.span("bar"), "baz")))
|
||||
|
||||
def test_whitespace(self):
|
||||
self.assertEqual(
|
||||
"foo bar\nbaz",
|
||||
html_to_text(E.div(
|
||||
"foo\nbar",
|
||||
E.br(),
|
||||
"baz")
|
||||
))
|
||||
|
||||
self.assertEqual(
|
||||
"foo bar\nbaz",
|
||||
html_to_text(E.div(
|
||||
E.div(E.span("foo"), " bar"),
|
||||
"baz")))
|
||||
|
||||
class TestConvertBack(common.TransactionCase):
|
||||
def setUp(self):
|
||||
super(TestConvertBack, self).setUp()
|
||||
@@ -70,7 +175,7 @@ class TestConvertBack(common.TransactionCase):
|
||||
self.field_roundtrip('selection_str', 'B')
|
||||
|
||||
def test_text(self):
|
||||
self.field_roundtrip('text', """
|
||||
self.field_roundtrip('text', textwrap.dedent("""\
|
||||
You must obey the dance commander
|
||||
Givin' out the order for fun
|
||||
You must obey the dance commander
|
||||
@@ -88,8 +193,7 @@ class TestConvertBack(common.TransactionCase):
|
||||
Let's start the show
|
||||
Because you never know
|
||||
You never know
|
||||
You never know until you go
|
||||
""")
|
||||
You never know until you go"""))
|
||||
|
||||
def test_m2o(self):
|
||||
""" the M2O field conversion (from html) is markedly different from
|
||||
|
||||
@@ -4,21 +4,20 @@ import os
|
||||
import select
|
||||
import time
|
||||
import json
|
||||
from openerp import tools
|
||||
from openerp import sql_db, tools
|
||||
|
||||
# avoid "ValueError: too many values to unpack"
|
||||
def _exc_info_to_string(err, test):
|
||||
return err
|
||||
|
||||
# TODO according to al this should be one line of Python
|
||||
class LineReader:
|
||||
class Stream:
|
||||
def __init__(self, file_descriptor):
|
||||
self._file_descriptor = file_descriptor
|
||||
self._buffer = ''
|
||||
|
||||
def fileno(self):
|
||||
return self._file_descriptor
|
||||
|
||||
# TODO Rewrite & fix
|
||||
def readlines(self):
|
||||
data = os.read(self._file_descriptor, 4096)
|
||||
if not data: # EOF
|
||||
@@ -50,6 +49,9 @@ class WebsiteUiSuite(unittest.TestSuite):
|
||||
return iter([self])
|
||||
|
||||
def run(self, result):
|
||||
# clean slate
|
||||
if sql_db._Pool is not None:
|
||||
sql_db._Pool.close_all(sql_db.dsn(tools.config['db_name']))
|
||||
# check for PhantomJS...
|
||||
try:
|
||||
subprocess.call([ 'phantomjs', '-v' ], stdout=open(os.devnull, 'w'), stderr=subprocess.STDOUT)
|
||||
@@ -74,7 +76,6 @@ class WebsiteUiSuite(unittest.TestSuite):
|
||||
self._options['timeout'] = self._timeout
|
||||
self._options['port'] = tools.config.get('xmlrpc_port', 80)
|
||||
self._options['db'] = tools.config.get('db_name', '')
|
||||
# TODO use correct key from tools if exists (I could not find it --ddm)
|
||||
self._options['user'] = 'admin'
|
||||
self._options['password'] = tools.config.get('admin_passwd', 'admin')
|
||||
|
||||
@@ -84,7 +85,7 @@ class WebsiteUiSuite(unittest.TestSuite):
|
||||
json.dumps(self._options)
|
||||
], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
|
||||
readable = [LineReader(phantom.stdout.fileno())]
|
||||
readable = [Stream(phantom.stdout.fileno())]
|
||||
|
||||
try:
|
||||
output = []
|
||||
@@ -138,7 +139,7 @@ def full_path(filename):
|
||||
return os.path.join(os.path.join(os.path.dirname(__file__), 'ui_suite'), filename)
|
||||
|
||||
def load_tests(loader, base, _):
|
||||
base.addTest(WebsiteUiSuite(full_path('dummy_test.js'), {}))
|
||||
base.addTest(WebsiteUiSuite(full_path('dummy_test.js'), {}, 5.0))
|
||||
base.addTest(WebsiteUiSuite(full_path('simple_dom_test.js'), { 'action': 'website.action_website_homepage' }, 60.0))
|
||||
base.addTest(WebsiteUiSuite(full_path('homepage_test.js'), { 'action': 'website.action_website_homepage' }, 60.0))
|
||||
return base
|
||||
|
||||
@@ -43,7 +43,7 @@ function run (test) {
|
||||
|
||||
var page = require('webpage').create();
|
||||
|
||||
page.viewportSize = { width: 1920, height: 1080 };
|
||||
page.viewportSize = { width: 1440, height: 900 };
|
||||
|
||||
page.onError = function(message, trace) {
|
||||
console.log('{ "event": "error", "message": "'+message+'"}');
|
||||
@@ -64,13 +64,17 @@ function run (test) {
|
||||
test(page, timeout);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var maxRetries = 10;
|
||||
var retryDelay = 1000; // ms
|
||||
var tries = 0;
|
||||
page.open(url, function openPage (status) {
|
||||
if (status !== 'success') {
|
||||
tries++;
|
||||
if (tries < 5) {
|
||||
page.open(url, openPage);
|
||||
if (tries < maxRetries) {
|
||||
setTimeout(function () {
|
||||
page.open(url, openPage);
|
||||
}, retryDelay);
|
||||
} else {
|
||||
console.log('{ "event": "error", "message": "'+url+' failed to load '+tries+' times ('+status+')"}');
|
||||
phantom.exit(1);
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<img class="oe_snippet_thumbnail_img" src="/website/static/src/img/blocks/block_banner.png"/>
|
||||
<span class="oe_snippet_thumbnail_title">Banner</span>
|
||||
</div>
|
||||
<div id="myCarousel" class="oe_snippet_body carousel slide oe_medium mb32">
|
||||
<div id="myCarousel" class="oe_snippet_body carousel slide mb32" style="height: 320px;">
|
||||
<!-- Indicators -->
|
||||
<ol class="carousel-indicators hidden">
|
||||
<li data-target="#myCarousel" data-slide-to="0" class="active"></li>
|
||||
@@ -68,8 +68,8 @@
|
||||
and give it to them.
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-6 mt16 mb16">
|
||||
<img class="img img-responsive shadow" src="/website/static/src/img/text_image.png"/>
|
||||
<div class="col-md-6 mt16">
|
||||
<img class="img img-responsive shadow mb16" src="/website/static/src/img/text_image.png"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -85,8 +85,8 @@
|
||||
<section class="oe_snippet_body">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-6 mt16 mb16">
|
||||
<img class="img img-responsive shadow" src="/website/static/src/img/image_text.jpg"/>
|
||||
<div class="col-md-6 mt16">
|
||||
<img class="img img-responsive shadow mb16" src="/website/static/src/img/image_text.jpg"/>
|
||||
</div>
|
||||
<div class="col-md-6 mt16">
|
||||
<h3>A Section Subtitle</h3>
|
||||
@@ -277,7 +277,7 @@
|
||||
<img class="oe_snippet_thumbnail_img" src="/website/static/src/img/blocks/block_quotes_slider.png"/>
|
||||
<span class="oe_snippet_thumbnail_title">Quotes Slider</span>
|
||||
</div>
|
||||
<div id="myQuoteCarousel" class="oe_snippet_body carousel slide oe_small mb0">
|
||||
<div id="myQuoteCarousel" class="oe_snippet_body carousel slide mb0" style="height: 240px;">
|
||||
<!-- Indicators -->
|
||||
<ol class="carousel-indicators mb0">
|
||||
<li data-target="#myQuoteCarousel" data-slide-to="0" class="active"></li>
|
||||
@@ -676,6 +676,118 @@
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div data-snippet-id="features" data-selector-children=".oe_structure, [data-oe-type=html]">
|
||||
<div class="oe_snippet_thumbnail">
|
||||
<img class="oe_snippet_thumbnail_img" src="/website/static/src/img/blocks/block_features.png"/>
|
||||
<span class="oe_snippet_thumbnail_title">Features</span>
|
||||
</div>
|
||||
<section class="oe_snippet_body mb16">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12 text-center mb16">
|
||||
<h2>List of Features</h2>
|
||||
<h4 class="text-muted">Add a great slogan</h4>
|
||||
</div>
|
||||
<div class="col-md-3 text-center">
|
||||
<span class="fa fa-suitcase fa-5x"></span>
|
||||
<h3 class="mt8 mb0">First Feature</h3>
|
||||
<p class="text-muted">Tell what's the value for the customer for this feature.</p>
|
||||
<p><a class="btn btn-primary">Learn More</a></p>
|
||||
</div>
|
||||
<div class="col-md-3 text-center">
|
||||
<span class="fa fa-lock fa-5x"></span>
|
||||
<h3 class="mt8 mb0">Second Feature</h3>
|
||||
<p class="text-muted">Talk about what the customer would like to know, not what you want to show.</p>
|
||||
<p><a class="btn btn-success">Take Tour</a></p>
|
||||
</div>
|
||||
<div class="col-md-3 text-center">
|
||||
<span class="fa fa-heart fa-5x"></span>
|
||||
<h3 class="mt8 mb0">Third Feature</h3>
|
||||
<p class="text-muted">A small explanation of this great feature, in clear words.</p>
|
||||
<p><a class="btn btn-info">Buy Now</a></p>
|
||||
</div>
|
||||
<div class="col-md-3 text-center">
|
||||
<span class="fa fa-credit-card fa-5x"></span>
|
||||
<h3 class="mt8 mb0">Fourth Feature</h3>
|
||||
<p class="text-muted">A small explanation of this great feature on two lines.</p>
|
||||
<p><a class="btn btn-danger">Buy Now</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div data-snippet-id="features-list" data-selector-children=".oe_structure, [data-oe-type=html]">
|
||||
<div class="oe_snippet_thumbnail">
|
||||
<img class="oe_snippet_thumbnail_img" src="/website/static/src/img/blocks/block_features.png"/>
|
||||
<span class="oe_snippet_thumbnail_title">Feature Grid</span>
|
||||
</div>
|
||||
<section class="oe_snippet_body mb16">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-5 text-center mb16">
|
||||
<h2>List of Features</h2>
|
||||
<h4 class="text-muted">Add a great slogan</h4>
|
||||
</div>
|
||||
<div class="col-md-5 text-center mb16 col-md-offset-2">
|
||||
<h2>Second List</h2>
|
||||
<h4 class="text-muted">Add a great slogan</h4>
|
||||
</div>
|
||||
</div><div class="row">
|
||||
<div class="col-md-5">
|
||||
<ul class="list-unstyled">
|
||||
<li>
|
||||
<span style="min-width: 45px" class="fa fa-3x fa-comment pull-left mb16"></span>
|
||||
<h3 class="mb0">Blog</h3>
|
||||
<p>OpenERP includes a full features enterprise blog to promote your messages.</p>
|
||||
</li>
|
||||
<li>
|
||||
<span style="min-width: 45px" class="fa fa-3x fa-columns pull-left mb16"></span>
|
||||
<h3 class="mb0">Pricing Tables</h3>
|
||||
<p>Use building blocks to use pricing tables to display your products or services.</p>
|
||||
</li>
|
||||
<li>
|
||||
<span style="min-width: 45px" class="fa fa-3x fa-user pull-left mb16"></span>
|
||||
<h3 class="mb0">Log In & Signup</h3>
|
||||
<p>Clean & simple Log In, Signup & Forgot Your Password forms.</p>
|
||||
</li>
|
||||
<li>
|
||||
<span style="min-width: 45px" class="fa fa-3x fa-envelope pull-left mb16"></span>
|
||||
<h3 class="mb0">Contact</h3>
|
||||
<p>User-friendly contact form with Google Map integration.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
<div class="col-md-5 col-md-offset-2">
|
||||
<ul class="list-unstyled">
|
||||
<li>
|
||||
<span style="min-width: 45px" class="fa fa-3x fa-magic pull-left mb16"></span>
|
||||
<h3 class="mb0">Bootstrap</h3>
|
||||
<p>Uses Twitter Bootstrap's sleek, intuitive, and powerful front-end framework.</p>
|
||||
</li>
|
||||
<li>
|
||||
<span style="min-width: 45px" class="fa fa-3x fa-font pull-left mb16"></span>
|
||||
<h3 class="mb0">Google Web Fonts</h3>
|
||||
<p>Royalty free, open source fonts for the people, by the people!</p>
|
||||
</li>
|
||||
<li>
|
||||
<span style="min-width: 45px" class="fa fa-3x fa-bolt pull-left mb16"></span>
|
||||
<h3 class="mb0">Powerful & slick jQuery</h3>
|
||||
<p>Fantastic jQuery plugins such as Isotope and Bootstrap's inbuilt features.</p>
|
||||
</li>
|
||||
<li>
|
||||
<span style="min-width: 45px" class="fa fa-3x fa-picture-o pull-left mb16"></span>
|
||||
<h3 class="mb0">Sample images</h3>
|
||||
<p>Fantastic sample images fully licensed for use.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="snippet_effect" class="tab-pane fade">
|
||||
@@ -696,8 +808,8 @@
|
||||
<li data-value="1.7"><a>Very Fast</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<section class="oe_snippet_body parallax oe_medium"
|
||||
style="background-image: url('/website/static/src/img/banner/mountains.jpg')"
|
||||
<section class="oe_snippet_body parallax"
|
||||
style="height: 320px; background-image: url('/website/static/src/img/banner/mountains.jpg')"
|
||||
data-scroll-background-ratio="0.3">
|
||||
<div><div class="oe_structure"/></div>
|
||||
</section>
|
||||
@@ -708,12 +820,12 @@
|
||||
<img class="oe_snippet_thumbnail_img" src="/website/static/src/img/blocks/block_quotes_slider.png"/>
|
||||
<span class="oe_snippet_thumbnail_title">Parallax Slider</span>
|
||||
</div>
|
||||
<section class="oe_snippet_body parallax oe_medium" data-snippet-id="parallax"
|
||||
style="background-image: url('/website/static/src/img/parallax/quote.png')"
|
||||
<section class="oe_snippet_body parallax" data-snippet-id="parallax"
|
||||
style="height: 320px; background-image: url('/website/static/src/img/parallax/quote.png')"
|
||||
data-scroll-background-ratio="0.3">
|
||||
<div>
|
||||
<div class="oe_structure">
|
||||
<div id="myQuoteCarousel" class="carousel slide oe_small mb0" data-snippet-id="slider">
|
||||
<div id="myQuoteCarousel" class="carousel slide mb0" style="height: 240px;" data-snippet-id="slider">
|
||||
<!-- Indicators -->
|
||||
<ol class="carousel-indicators mb0">
|
||||
<li data-target="#myQuoteCarousel" data-slide-to="0" class="active"></li>
|
||||
@@ -786,18 +898,6 @@
|
||||
</li>
|
||||
</div>
|
||||
|
||||
<div data-snippet-style-id='size' data-selector="section[data-snippet-id='parallax'], div[data-snippet-id='carousel'], div[data-snippet-id='slider']">
|
||||
<li class="dropdown-submenu" data-required="true">
|
||||
<a tabindex="-1" href="#">Size</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li data-class='oe_small'><a>Small</a></li>
|
||||
<li data-class='oe_medium'><a>Medium</a></li>
|
||||
<li data-class='oe_big'><a>Big</a></li>
|
||||
<li data-class=''><a>Auto</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</div>
|
||||
|
||||
<div data-snippet-style-id='background' data-selector="section, section[data-snippet-id='parallax'], div[data-snippet-id='carousel']">
|
||||
<li class="dropdown-submenu">
|
||||
<a tabindex="-1" href="#">Background</a>
|
||||
@@ -808,6 +908,10 @@
|
||||
<li data-class='oe_dark'><a>Darken</a></li>
|
||||
<li data-class='oe_green'><a>Green</a></li>
|
||||
<li data-class='oe_red'><a>Red</a></li>
|
||||
<li data-class='oe_blue_light'><a>Light Blue</a></li>
|
||||
<li data-class='oe_blue'><a>Dark Blue</a></li>
|
||||
<li data-class='oe_orange'><a>Orange</a></li>
|
||||
<li data-class='oe_purple'><a>Purple</a></li>
|
||||
<li data-class='oe_black'><a>Black</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
@@ -96,12 +96,13 @@
|
||||
<t t-foreach="website.menu_id.child_id" t-as="submenu">
|
||||
<t t-call="website.submenu"/>
|
||||
</t>
|
||||
<li class="divider"/>
|
||||
<li class="dropdown" t-ignore="true" t-if="user_id.id != website.public_user.id">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
||||
<span class="badge">
|
||||
<b>
|
||||
<span t-esc="user_id.name"/>
|
||||
<span class="caret"></span>
|
||||
</span>
|
||||
</b>
|
||||
</a>
|
||||
<ul class="dropdown-menu js_usermenu" role="menu">
|
||||
<li><a href="/web" role="menuitem">Administration</a></li>
|
||||
@@ -235,7 +236,7 @@
|
||||
<xpath expr="//ul[@id='top_menu']" position="inside">
|
||||
<li t-if="user_id.id == website.public_user.id">
|
||||
<a t-attf-href="/web#redirect=#{ quote_plus(url_for('', keep_query='*')) }">
|
||||
<span class="badge">Sign in</span>
|
||||
<b>Sign in</b>
|
||||
</a>
|
||||
</li>
|
||||
</xpath>
|
||||
@@ -533,7 +534,7 @@
|
||||
</div>
|
||||
|
||||
<div class="container" t-if="views">
|
||||
<div class="bs-callout bs-callout-danger" t-if="qweb_template and editable">
|
||||
<div class="alert alert-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>
|
||||
|
||||
@@ -23,6 +23,7 @@ from openerp.addons.web import http
|
||||
from openerp.addons.web.http import request
|
||||
from openerp.addons.website.models import website
|
||||
from openerp.tools.translate import _
|
||||
from openerp import SUPERUSER_ID
|
||||
|
||||
import werkzeug
|
||||
|
||||
@@ -218,16 +219,23 @@ class WebsiteBlog(http.Controller):
|
||||
}
|
||||
return request.website.render("website_blog.blog_post_complete", values)
|
||||
|
||||
@website.route(['/blogpost/<int:blog_post_id>/comment'], type='http', auth="public")
|
||||
def blog_post_comment(self, blog_post_id, **post):
|
||||
@website.route(['/blogpost/comment'], type='http', auth="public", methods=['POST'])
|
||||
def blog_post_comment(self, blog_post_id=0, **post):
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
if post.get('comment'):
|
||||
request.registry['blog.post'].message_post(
|
||||
cr, uid, blog_post_id,
|
||||
body=post.get('comment'),
|
||||
type='comment',
|
||||
subtype='mt_comment',
|
||||
context=dict(context, mail_create_nosubcribe=True))
|
||||
user = request.registry['res.users'].browse(cr, SUPERUSER_ID, uid, context=context)
|
||||
group_ids = user.groups_id
|
||||
group_id = request.registry["ir.model.data"].get_object_reference(cr, uid, 'website_mail', 'group_comment')[1]
|
||||
if group_id in [group.id for group in group_ids]:
|
||||
blog_post = request.registry['blog.post']
|
||||
blog_post.check_access_rights(cr, uid, 'read')
|
||||
blog_post.message_post(
|
||||
cr, SUPERUSER_ID, int(blog_post_id),
|
||||
body=post.get('comment'),
|
||||
type='comment',
|
||||
subtype='mt_comment',
|
||||
author_id=user.partner_id.id,
|
||||
context=dict(context, mail_create_nosubcribe=True))
|
||||
return werkzeug.utils.redirect(request.httprequest.referrer + "#comments")
|
||||
|
||||
@website.route('/blogpost/new', type='http', auth="public", multilang=True)
|
||||
|
||||
@@ -148,6 +148,7 @@
|
||||
title: "Publish Your Post",
|
||||
content: "Your blog post is not yet published. You can update this draft version and publish it once you are ready.",
|
||||
trigger: 'click',
|
||||
delay: 5000,
|
||||
},
|
||||
{
|
||||
stepId: 'end-tutorial',
|
||||
|
||||
@@ -6,5 +6,5 @@ def full_path(filename):
|
||||
return os.path.join(os.path.join(os.path.dirname(__file__), 'ui_suite'), filename)
|
||||
|
||||
def load_tests(loader, base, _):
|
||||
base.addTest(test_ui.WebsiteUiSuite(full_path('post_test.js'), { 'action': 'website.action_website_homepage' }, 120.0))
|
||||
base.addTest(test_ui.WebsiteUiSuite(full_path('post_test.js'), { 'action': 'website.action_website_homepage' }, 60.0))
|
||||
return base
|
||||
@@ -2,7 +2,7 @@ var testRunner = require('../../../website/tests/ui_suite/ui_test_runner.js');
|
||||
|
||||
var waitFor = testRunner.waitFor;
|
||||
|
||||
testRunner.run(function homepageTest (page, timeout) {
|
||||
testRunner.run(function blogTest (page, timeout) {
|
||||
page.evaluate(function () { localStorage.clear(); });
|
||||
waitFor(function clientReady () {
|
||||
return page.evaluate(function () {
|
||||
@@ -22,9 +22,6 @@ testRunner.run(function homepageTest (page, timeout) {
|
||||
};
|
||||
});
|
||||
var result = after && (after.image === 1) && (after.text === 1);
|
||||
if (!result && window.location.href.indexOf('/blogpost/') > 0) {
|
||||
window.location.reload();
|
||||
}
|
||||
return result;
|
||||
}, function finish () {
|
||||
console.log('{ "event": "success" }');
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
<!-- Options: Blog Post Summary: hide author -->
|
||||
<template id="opt_blog_post_short_author" name="Author"
|
||||
inherit_option_id="website_blog.blog_post_short">
|
||||
<xpath expr="//span[@class*='oe_date']" position="after">
|
||||
<xpath expr="//span[@class='fa fa-calendar oe_date']" position="after">
|
||||
<span class="fa fa-user"> By <span t-field="blog_post.create_uid"/> &nbsp;</span>
|
||||
</xpath>
|
||||
</template>
|
||||
@@ -182,7 +182,7 @@
|
||||
|
||||
<h1 class="text-center" t-field="blog_post.name"/>
|
||||
<p class="post-meta text-muted text-center" name="blog_post_data">
|
||||
<span class="fa fa-calendar"> <span t-field="blog_post.create_date"/> &nbsp;</span>
|
||||
<span class="fa fa-calendar oe_date"> <span t-field="blog_post.create_date"/> &nbsp;</span>
|
||||
<span t-if="len(blog_post.message_ids) > 0" class="fa fa-comment-o"> With
|
||||
<a t-attf-href="#comments">
|
||||
<t t-if="len(blog_post.message_ids) <= 1" ><t t-esc="len(blog_post.message_ids)"/> comment</t>
|
||||
@@ -218,10 +218,10 @@
|
||||
<template id="opt_blog_post_complete_comment" name="Allow Comments"
|
||||
inherit_option_id="website_blog.blog_post_complete" inherit_id="website_blog.blog_post_complete"
|
||||
groups="website_mail.group_comment">
|
||||
<xpath expr="//ul[@id='comments-list']" position="after">
|
||||
<xpath expr="//ul[@id='comments-list']" position="before">
|
||||
<section class="mb32 css_editable_mode_hidden">
|
||||
<form id="comment" t-attf-action="/blogpost/#{blog_post.id}/comment"
|
||||
method="POST">
|
||||
<form id="comment" t-attf-action="/blogpost/comment" method="POST">
|
||||
<input name="blog_post_id" t-att-value="blog_post.id" type="hidden"/>
|
||||
<img class="img pull-left img-rounded" t-att-src="'/website/image?model=res.partner&field=image_small&id='+str(user_id.partner_id.id)" style="width: 50px; margin-right: 10px;"/>
|
||||
<div class="pull-left mb32" style="width: 75%%">
|
||||
<textarea rows="3" name="comment" class="form-control" placeholder="Write a comment..."></textarea>
|
||||
@@ -236,7 +236,7 @@
|
||||
<!-- Options: Blog Post: hide author -->
|
||||
<template id="opt_blog_post_complete_author" name="Authors"
|
||||
inherit_option_id="website_blog.blog_post_complete">
|
||||
<xpath expr="//span[@class*='oe_date']" position="after">
|
||||
<xpath expr="//span[@class='fa fa-calendar oe_date']" position="after">
|
||||
<span class="fa fa-user"> By <span t-field="blog_post.create_uid"/> &nbsp;</span>
|
||||
</xpath>
|
||||
</template>
|
||||
@@ -244,7 +244,7 @@
|
||||
<!-- Options: Blog Post: show category -->
|
||||
<template id="opt_blog_post_complete_category" name="Blog Category"
|
||||
inherit_option_id="website_blog.blog_post_complete">
|
||||
<xpath expr="//span[@class*='oe_date']" position="after">
|
||||
<xpath expr="//span[@class='fa fa-calendar oe_date']" position="after">
|
||||
<span class="fa fa-folder-open"> In <span t-field="blog_post.category_id"/> &nbsp;</span>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
@@ -49,10 +49,19 @@
|
||||
{
|
||||
stepId: 'choose-name',
|
||||
element: '.modal input',
|
||||
sampleText: 'Advanced Technical Training',
|
||||
placement: 'right',
|
||||
title: "Create an Event Name",
|
||||
content: "Create a name for your new event and click <em>'Continue'</em>. e.g: Technical Training",
|
||||
},
|
||||
{
|
||||
stepId: 'continue-name',
|
||||
element: '.modal button.btn-primary',
|
||||
placement: 'right',
|
||||
title: "Create Event",
|
||||
content: "Click <em>Continue</em> to create the event.",
|
||||
trigger: 'click',
|
||||
},
|
||||
{
|
||||
stepId: 'event-page',
|
||||
title: "New Event Created",
|
||||
@@ -137,6 +146,7 @@
|
||||
title: "Publish your event",
|
||||
content: "Click to publish your event.",
|
||||
trigger: 'click',
|
||||
delay: 5000,
|
||||
},
|
||||
{
|
||||
stepId: 'customize-event',
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
|
||||
from openerp.addons.website_blog.tests import test_controllers
|
||||
|
||||
import test_ui
|
||||
|
||||
checks = [
|
||||
test_controllers,
|
||||
]
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import os
|
||||
|
||||
import openerp.addons.website.tests.test_ui as test_ui
|
||||
|
||||
def full_path(filename):
|
||||
return os.path.join(os.path.join(os.path.dirname(__file__), 'ui_suite'), filename)
|
||||
|
||||
def load_tests(loader, base, _):
|
||||
base.addTest(test_ui.WebsiteUiSuite(full_path('event_test.js'), { 'action': 'website.action_website_homepage' }, 60.0))
|
||||
return base
|
||||
@@ -0,0 +1,32 @@
|
||||
var testRunner = require('../../../website/tests/ui_suite/ui_test_runner.js');
|
||||
|
||||
var waitFor = testRunner.waitFor;
|
||||
|
||||
testRunner.run(function eventTest (page, timeout) {
|
||||
page.evaluate(function () { localStorage.clear(); });
|
||||
waitFor(function clientReady () {
|
||||
return page.evaluate(function () {
|
||||
return window.$ && window.openerp && window.openerp.website
|
||||
&& window.openerp.website.TestConsole
|
||||
&& window.openerp.website.TestConsole.test('event');
|
||||
});
|
||||
}, function executeTest () {
|
||||
page.evaluate(function () {
|
||||
window.openerp.website.TestConsole.test('event').run(true);
|
||||
});
|
||||
waitFor(function testExecuted () {
|
||||
var after = page.evaluate(function () {
|
||||
return window.$ && $('button[data-action=edit]').is(":visible") && {
|
||||
banner: $('#wrap [data-snippet-id=carousel]').length,
|
||||
text: $('#wrap [data-snippet-id=text-block]').length,
|
||||
image: $('#wrap [data-snippet-id=three-columns]').length,
|
||||
};
|
||||
});
|
||||
var result = after && (after.banner === 1) && (after.text === 1) && (after.image === 1);
|
||||
return result;
|
||||
}, function finish () {
|
||||
console.log('{ "event": "success" }');
|
||||
phantom.exit();
|
||||
}, 4*timeout/5);
|
||||
}, timeout/5);
|
||||
});
|
||||
@@ -136,7 +136,7 @@
|
||||
<ul class="nav nav-pills nav-stacked">
|
||||
<t t-foreach="dates" t-as="date">
|
||||
<li t-att-class="searches.get('date') == date[0] and 'active' or ''" t-if="date[3] or (date[0] in ('old','all'))">
|
||||
<a t-href="/event/#{ search_path }&date=#{ date[0] }"><t t-esc="date[1]"/>
|
||||
<a t-href="/event/?date=#{ date[0] }" t-keep-query="country,type"><t t-esc="date[1]"/>
|
||||
<span t-if="date[3]" class="badge pull-right"><t t-esc="date[3]"/></span>
|
||||
</a>
|
||||
</li>
|
||||
@@ -151,7 +151,7 @@
|
||||
<ul class="nav nav-pills nav-stacked mt32">
|
||||
<t t-foreach="types">
|
||||
<li t-if="type" t-att-class="searches.get('type') == str(type and type[0]) and 'active' or ''">
|
||||
<a t-href="/event/#{ search_path }&type=#{ type[0] }"><t t-esc="type[1]"/>
|
||||
<a t-href="/event/?type=#{ type[0] }" t-keep-query="country,date"><t t-esc="type[1]"/>
|
||||
<span class="badge pull-right"><t t-esc="type_count"/></span>
|
||||
</a>
|
||||
</li>
|
||||
@@ -164,7 +164,7 @@
|
||||
<ul class="nav nav-pills nav-stacked mt32">
|
||||
<t t-foreach="countries">
|
||||
<li t-if="country_id" t-att-class="searches.get('country') == str(country_id and country_id[0]) and 'active' or ''">
|
||||
<a t-href="/event/#{ search_path }&country=#{ country_id[0] }"><t t-esc="country_id[1]"/>
|
||||
<a t-href="/event/?country=#{ country_id[0] }" t-keep-query="type,date"><t t-esc="country_id[1]"/>
|
||||
<span class="badge pull-right"><t t-esc="country_id_count"/></span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
@@ -35,7 +35,7 @@ class WebsiteMail(http.Controller):
|
||||
if email and email != u'false': # post contains stringified booleans
|
||||
partner_ids = partner_obj.search(request.cr, SUPERUSER_ID, [("email", "=", email)], context=request.context)
|
||||
if not partner_ids:
|
||||
partner_ids = [partner_obj.name_create(request.cr, SUPERUSER_ID, email, request.context)]
|
||||
partner_ids = [partner_obj.name_create(request.cr, SUPERUSER_ID, email, request.context)[0]]
|
||||
else:
|
||||
partner_ids = [user_obj.browse(request.cr, request.uid, request.uid, request.context).partner_id.id]
|
||||
return partner_ids
|
||||
@@ -54,5 +54,6 @@ class WebsiteMail(http.Controller):
|
||||
_object.check_access_rule(request.cr, request.uid, [_id], 'read', request.context)
|
||||
_object.message_subscribe(request.cr, SUPERUSER_ID, [_id], partner_ids, context=request.context)
|
||||
obj = _object.browse(request.cr, request.uid, _id)
|
||||
follower_ids = [p.id for p in obj.message_follower_ids]
|
||||
|
||||
return obj.message_is_follower and 1 or 0
|
||||
return partner_ids[0] in follower_ids and 1 or 0
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
.js_follow[data-follow='on'] .js_follow_btn ,
|
||||
.js_follow[data-follow='off'] .js_unfollow_btn {
|
||||
display: none;
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
$(document).ready(function () {
|
||||
|
||||
$(document).on('click', '.js_follow_btn', function (ev) {
|
||||
$(document).on('click', '.js_follow_btn, .js_unfollow_btn', function (ev) {
|
||||
ev.preventDefault();
|
||||
|
||||
var self = this;
|
||||
var self = this;
|
||||
var $data = $(this).parents("div.js_follow");
|
||||
var $email = $(".js_follow_email", $data);
|
||||
var message_is_follower = $data.attr("data-follow");
|
||||
var $email = $data.find(".js_follow_email");
|
||||
var message_is_follower = $data.attr("data-follow") || "off";
|
||||
$data.attr("data-follow", message_is_follower == 'off' ? 'on' : 'off');
|
||||
|
||||
openerp.jsonRpc('/website_mail/follow', 'call', {
|
||||
@@ -15,12 +15,10 @@ $(document).ready(function () {
|
||||
'message_is_follower': message_is_follower,
|
||||
'email': $email && $email.val() || false,
|
||||
}).then(function (result) {
|
||||
if (result) {
|
||||
$data.html('<div class="alert alert-success mb0">Thanks for your subscription!</div>')
|
||||
} else {
|
||||
$data.attr("data-follow", + result ? 'on' : 'off');
|
||||
$(self).text('Subscribe')
|
||||
}
|
||||
if (result) {
|
||||
$data.find(" > *").toggleClass("hidden");
|
||||
}
|
||||
$data.attr("data-follow", result ? 'on' : 'off');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -12,18 +12,17 @@
|
||||
t-att-value="email or ''"
|
||||
placeholder="your email..."/>
|
||||
<span class="input-group-btn">
|
||||
<button href="#"
|
||||
t-attf-class="btn btn-#{object.message_is_follower and 'default' or 'primary'} js_follow_btn">
|
||||
<t t-if="object.message_is_follower">Unsubscribe</t>
|
||||
<t t-if="not object.message_is_follower">Subscribe</t>
|
||||
</button>
|
||||
<button href="#" t-attf-class="btn btn-default js_unfollow_btn">Unsubscribe</button>
|
||||
<button href="#" t-attf-class="btn btn-primary js_follow_btn">Subscribe</button>
|
||||
</span>
|
||||
<div class="alert alert-success hidden">Thanks for your subscription!</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template id="head" inherit_id="website.layout" name="Mail customization">
|
||||
<xpath expr="//head" position="inside">
|
||||
<script type="text/javascript" src="/website_mail/static/src/js/website_mail.js"></script>
|
||||
<link rel='stylesheet' href='/website_mail/static/src/css/website_mail.css'/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ OpenERP E-Commerce
|
||||
|
||||
""",
|
||||
'author': 'OpenERP SA',
|
||||
'depends': ['website', 'sale', 'product', 'payment_acquirer'],
|
||||
'depends': ['website', 'sale', 'payment_acquirer'],
|
||||
'data': [
|
||||
'data/website_sale_data.xml',
|
||||
'views/website_sale.xml',
|
||||
|
||||
@@ -199,10 +199,10 @@ class Ecommerce(http.Controller):
|
||||
@website.route([
|
||||
'/shop/',
|
||||
'/shop/page/<int:page>/',
|
||||
'/shop/category/<int:category>/',
|
||||
'/shop/category/<int:category>/page/<int:page>/'
|
||||
'/shop/category/<model("product.public.category"):category>/',
|
||||
'/shop/category/<model("product.public.category"):category>/page/<int:page>/'
|
||||
], type='http', auth="public", multilang=True)
|
||||
def shop(self, category=0, page=0, filters='', search='', **post):
|
||||
def shop(self, category=None, page=0, filters='', search='', **post):
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
product_obj = request.registry.get('product.template')
|
||||
domain = request.registry.get('website').ecommerce_get_product_domain()
|
||||
@@ -211,7 +211,7 @@ class Ecommerce(http.Controller):
|
||||
('name', 'ilike', "%%%s%%" % search),
|
||||
('description', 'ilike', "%%%s%%" % search)]
|
||||
if category:
|
||||
domain.append(('product_variant_ids.public_categ_id', 'child_of', category))
|
||||
domain.append(('product_variant_ids.public_categ_id', 'child_of', category.id))
|
||||
if filters:
|
||||
filters = simplejson.loads(filters)
|
||||
if filters:
|
||||
@@ -286,7 +286,7 @@ class Ecommerce(http.Controller):
|
||||
}
|
||||
return request.website.render("website_sale.product", values)
|
||||
|
||||
@website.route(['/shop/product/<int:product_template_id>/comment'], type='http', auth="public")
|
||||
@website.route(['/shop/product/comment'], type='http', auth="public", methods=['POST'])
|
||||
def product_comment(self, product_template_id, **post):
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
if post.get('comment'):
|
||||
@@ -298,11 +298,11 @@ class Ecommerce(http.Controller):
|
||||
context=dict(context, mail_create_nosubcribe=True))
|
||||
return werkzeug.utils.redirect(request.httprequest.referrer + "#comments")
|
||||
|
||||
@website.route(['/shop/add_product/', '/shop/category/<int:cat_id>/add_product/'], type='http', auth="user", multilang=True, methods=['POST'])
|
||||
def add_product(self, name="New Product", cat_id=0, **post):
|
||||
@website.route(['/shop/add_product/'], type='http', auth="user", multilang=True, methods=['POST'])
|
||||
def add_product(self, name="New Product", category=0, **post):
|
||||
Product = request.registry.get('product.product')
|
||||
product_id = Product.create(request.cr, request.uid, {
|
||||
'name': name, 'public_categ_id': cat_id
|
||||
'name': name, 'public_categ_id': category
|
||||
}, context=request.context)
|
||||
product = Product.browse(request.cr, request.uid, product_id, context=request.context)
|
||||
|
||||
@@ -612,12 +612,12 @@ class Ecommerce(http.Controller):
|
||||
|
||||
# if no sale order at this stage: back to checkout beginning
|
||||
order = self.get_order()
|
||||
if not order or not order.state == 'draft' or not order.order_line:
|
||||
if not order or order.state != 'draft' or not order.order_line:
|
||||
request.registry['website'].ecommerce_reset(cr, uid, context=context)
|
||||
return request.redirect("/shop/")
|
||||
# alread a transaction: forward to confirmation
|
||||
tx = context.get('website_sale_transaction')
|
||||
if tx and not tx.state == 'draft':
|
||||
if tx and tx.state != 'draft':
|
||||
return request.redirect('/shop/confirmation/%s' % order.id)
|
||||
|
||||
shipping_partner_id = False
|
||||
@@ -780,12 +780,16 @@ class Ecommerce(http.Controller):
|
||||
return request.website.render("website_sale.confirmation", {'order': order})
|
||||
|
||||
@website.route(['/shop/change_sequence/'], type='json', auth="public")
|
||||
def change_sequence(self, id, top):
|
||||
def change_sequence(self, id, sequence):
|
||||
product_obj = request.registry.get('product.template')
|
||||
if top:
|
||||
if sequence == "top":
|
||||
product_obj.set_sequence_top(request.cr, request.uid, [id], context=request.context)
|
||||
else:
|
||||
elif sequence == "bottom":
|
||||
product_obj.set_sequence_bottom(request.cr, request.uid, [id], context=request.context)
|
||||
elif sequence == "up":
|
||||
product_obj.set_sequence_up(request.cr, request.uid, [id], context=request.context)
|
||||
elif sequence == "down":
|
||||
product_obj.set_sequence_down(request.cr, request.uid, [id], context=request.context)
|
||||
|
||||
@website.route(['/shop/change_styles/'], type='json', auth="public")
|
||||
def change_styles(self, id, style_id):
|
||||
|
||||
@@ -536,6 +536,7 @@ Weight: 1.1 ounces</field>
|
||||
</div>
|
||||
</section>
|
||||
</field>
|
||||
<field name="suggested_product_ids" eval="[(6, 0, [ref('product.product_template_7')])]"/>
|
||||
</record>
|
||||
|
||||
<record id="item1" model="product.pricelist.item">
|
||||
|
||||
@@ -61,10 +61,16 @@ class product_template(osv.Model):
|
||||
'website_sequence': fields.integer('Sequence', help="Determine the display order in the Website E-commerce"),
|
||||
'website_url': fields.function(_website_url, string="Website url", type="char"),
|
||||
}
|
||||
|
||||
def __defaults_website_sequence(self, cr, uid, *kwargs):
|
||||
cr.execute('SELECT MAX(website_sequence) FROM product_template')
|
||||
max_sequence = cr.fetchone()[0] or 0
|
||||
return max_sequence + 1
|
||||
|
||||
_defaults = {
|
||||
'website_size_x': 1,
|
||||
'website_size_y': 1,
|
||||
'website_sequence': 1,
|
||||
'website_sequence': __defaults_website_sequence,
|
||||
'website_published': False,
|
||||
}
|
||||
|
||||
@@ -74,7 +80,31 @@ class product_template(osv.Model):
|
||||
return self.write(cr, uid, ids, {'website_sequence': max_sequence + 1}, context=context)
|
||||
|
||||
def set_sequence_bottom(self, cr, uid, ids, context=None):
|
||||
return self.write(cr, uid, ids, {'website_sequence': 0}, context=context)
|
||||
cr.execute('SELECT MIN(website_sequence) FROM product_template')
|
||||
min_sequence = cr.fetchone()[0] or 0
|
||||
return self.write(cr, uid, ids, {'website_sequence': min_sequence -1}, context=context)
|
||||
|
||||
def set_sequence_up(self, cr, uid, ids, context=None):
|
||||
product = self.browse(cr, uid, ids[0], context=context)
|
||||
cr.execute(""" SELECT id, website_sequence FROM product_template
|
||||
WHERE website_sequence > %s AND website_published = %s ORDER BY website_sequence ASC LIMIT 1""" % (product.website_sequence, product.website_published))
|
||||
prev = cr.fetchone()
|
||||
if prev:
|
||||
self.write(cr, uid, [prev[0]], {'website_sequence': product.website_sequence}, context=context)
|
||||
return self.write(cr, uid, [ids[0]], {'website_sequence': prev[1]}, context=context)
|
||||
else:
|
||||
return self.set_sequence_top(cr, uid, ids, context=context)
|
||||
|
||||
def set_sequence_down(self, cr, uid, ids, context=None):
|
||||
product = self.browse(cr, uid, ids[0], context=context)
|
||||
cr.execute(""" SELECT id, website_sequence FROM product_template
|
||||
WHERE website_sequence < %s AND website_published = %s ORDER BY website_sequence DESC LIMIT 1""" % (product.website_sequence, product.website_published))
|
||||
next = cr.fetchone()
|
||||
if next:
|
||||
self.write(cr, uid, [next[0]], {'website_sequence': product.website_sequence}, context=context)
|
||||
return self.write(cr, uid, [ids[0]], {'website_sequence': next[1]}, context=context)
|
||||
else:
|
||||
return self.set_sequence_bottom(cr, uid, ids, context=context)
|
||||
|
||||
def recommended_products(self, cr, uid, ids, context=None):
|
||||
id = ids[0]
|
||||
|
||||
@@ -11,4 +11,4 @@ access_product_attribute,product.attribute.public,website_sale.model_product_att
|
||||
access_product_attribute_value,product.attribute.value.public,website_sale.model_product_attribute_value,,1,0,0,0
|
||||
access_product_attribute_product,product.attribute.product.public,website_sale.model_product_attribute_product,,1,0,0,0
|
||||
access_website_product_style,website.product.style.public,website_sale.model_website_product_style,,1,0,0,0
|
||||
access_product_supplierinfo,product.supplierinfo.public,product.model_product_supplierinfo,,1,0,0,0
|
||||
access_product_supplierinfo,product.supplierinfo.public,product.model_product_supplierinfo,base.group_public,1,0,0,0
|
||||
|
||||
|
@@ -25,10 +25,17 @@
|
||||
location.href = location.href.replace(/(\?|#|$).*/, search + location.hash);
|
||||
}
|
||||
|
||||
$(document).on('click', '.js_options .js_go_to_top,.js_options .js_go_to_bottom', function (event) {
|
||||
$(document).on('click', '.js_options .js_go_to_top,.js_options .js_go_to_bottom,.js_options .js_go_up,.js_options .js_go_down', function (event) {
|
||||
var $a = $(event.currentTarget);
|
||||
var $data = $a.parents(".js_options:first");
|
||||
openerp.jsonRpc('/shop/change_sequence/', 'call', {'id': $data.data('id'), 'top': $a.hasClass('js_go_to_top')})
|
||||
var sequence = "top";
|
||||
if ($a.hasClass('js_go_to_bottom'))
|
||||
sequence = "bottom";
|
||||
else if ($a.hasClass('js_go_up'))
|
||||
sequence = "up";
|
||||
else if ($a.hasClass('js_go_down'))
|
||||
sequence = "down";
|
||||
openerp.jsonRpc('/shop/change_sequence/', 'call', {'id': $data.data('id'), 'sequence': sequence})
|
||||
.then(reload_enable_editor);
|
||||
});
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
|
||||
<template id="products_cart" name="Shopping cart">
|
||||
<div class="ribbon-wrapper">
|
||||
<div class="ribbon btn btn-danger">Promo</div>
|
||||
<div class="ribbon btn btn-danger">Sale</div>
|
||||
</div>
|
||||
<div class="oe_product_image">
|
||||
<a t-href="/shop/product/#{ slug(product) }/" t-keep-query="category,search,filters">
|
||||
@@ -166,6 +166,9 @@
|
||||
<a tabindex="-1" href="#">Promote</a>
|
||||
<ul class="dropdown-menu" name="sequence">
|
||||
<li><a href="#" class="js_go_to_top">Push to top</a></li>
|
||||
<li><a href="#" class="js_go_up">Push up</a>
|
||||
</li>
|
||||
<li><a href="#" class="js_go_down">Push down</a></li>
|
||||
<li><a href="#" class="js_go_to_bottom">Push to bottom</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
@@ -185,7 +188,8 @@
|
||||
</table>
|
||||
<t t-if="not bins">
|
||||
<div class="text-center text-muted">
|
||||
<h3>No product found</h3>
|
||||
<h3 class="css_editable_display">No product found</h3>
|
||||
<h3 class="css_non_editable_mode_hidden">There isn't available products right know, click <a t-href="/page/website.contactus">here</a> to contact us</h3>
|
||||
<t groups="base.group_website_publisher">
|
||||
<p>Click on "Content" to define a new product or "Help" for more informations.</p>
|
||||
<img src="/website/static/src/img/content_here.png"/>
|
||||
@@ -675,7 +679,7 @@
|
||||
}'/>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<a t-href="./add_cart/#{ product.id }/"><strong>Add to Cart</strong></a>
|
||||
<a t-href="/shop/add_cart/#{ product.product_variant_ids[0].id }/"><strong>Add to Cart</strong></a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@@ -1027,17 +1031,19 @@
|
||||
<div class="oe_structure"/>
|
||||
</div>
|
||||
<div class="col-md-3 col-md-offset-1 text-muted" id="right_column">
|
||||
<h4>Bill To:</h4>
|
||||
<div t-field="order.partner_invoice_id"/>
|
||||
|
||||
<h4 class="mt32">Ship To:</h4>
|
||||
<div t-field="order.partner_shipping_id"/>
|
||||
|
||||
<h4 class="mt32">Amount:</h4>
|
||||
<!--<div t-field="order.amount_total" t-field-options='{
|
||||
"widget": "monetary",
|
||||
"display_currency": "website.pricelist_id.currency_id"
|
||||
}'/> -->
|
||||
<h4>Bill To:</h4>
|
||||
<div t-field="order.partner_invoice_id" t-field-options='{
|
||||
"widget": "contact",
|
||||
"fields": ["address", "name", "phone", "email"]
|
||||
}'/>
|
||||
<h4 class="mt32">Ship To:</h4>
|
||||
<t t-if="order.partner_shipping_id and order.partner_shipping_id.id != order.partner_invoice_id.id">
|
||||
<div t-field="order.partner_shipping_id" t-field-options='{
|
||||
"widget": "contact",
|
||||
"fields": ["address", "name", "phone"]
|
||||
}'/>
|
||||
</t>
|
||||
<address t-if="order.partner_shipping_id.id == order.partner_invoice_id.id">Ship to the same address</address>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
from openerp.addons.website_sale.controllers.main import Ecommerce
|
||||
from openerp.addons.web.http import request
|
||||
from openerp.addons.website.models import website
|
||||
from openerp import SUPERUSER_ID
|
||||
|
||||
|
||||
class Ecommerce(Ecommerce):
|
||||
@@ -15,8 +16,8 @@ class Ecommerce(Ecommerce):
|
||||
if order and carrier_id:
|
||||
# recompute delivery costs
|
||||
SaleOrder = request.registry['sale.order']
|
||||
SaleOrder.write(cr, uid, [order.id], {'carrier_id': carrier_id}, context=context)
|
||||
SaleOrder.delivery_set(cr, uid, [order.id], context=context)
|
||||
SaleOrder.write(cr, SUPERUSER_ID, [order.id], {'carrier_id': carrier_id}, context=context)
|
||||
SaleOrder.delivery_set(cr, SUPERUSER_ID, [order.id], context=context)
|
||||
|
||||
res = super(Ecommerce, self).payment(**post)
|
||||
return res
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<tr class="text-muted" id="order_delivery">
|
||||
<td><abbr title="Delivery will be updated after choosing a new delivery method">Delivery:</abbr></td>
|
||||
<td class="text-right">
|
||||
<span t-field="website_sale_order.amount_delivery" t-field-options='{
|
||||
<span t-field="order.amount_delivery" t-field-options='{
|
||||
"widget": "monetary",
|
||||
"display_currency": "website.pricelist_id.currency_id"
|
||||
}'/>
|
||||
@@ -41,7 +41,7 @@
|
||||
<li t-foreach="deliveries" t-as="delivery">
|
||||
<label>
|
||||
<input t-att-value="delivery.id" type="radio" name="delivery_type"
|
||||
t-att-checked="website_sale_order.carrier_id and website_sale_order.carrier_id.id == delivery.id and 'checked' or False"/>
|
||||
t-att-checked="order.carrier_id and order.carrier_id.id == delivery.id and 'checked' or False"/>
|
||||
<span t-field="delivery.name"/>
|
||||
<span class="badge" t-field="delivery.price"
|
||||
t-field-options='{
|
||||
|
||||
Reference in New Issue
Block a user