[MERGE] sync from website-al

bzr revid: chm@openerp.com-20131018121050-vpk0lltaia4lka4l
This commit is contained in:
Christophe Matthieu
2013-10-18 14:10:50 +02:00
20 changed files with 327 additions and 227 deletions
+1
View File
@@ -20,3 +20,4 @@
##############################################################################
import payment_acquirer
import controllers
+2 -2
View File
@@ -11,8 +11,8 @@ class view(osv.osv):
'inherited_option_ids': fields.one2many('ir.ui.view','inherit_option_id','Optional Inheritancies'),
'page': fields.boolean("Whether this view is a web page template (complete)"),
'website_meta_title': fields.char("Website meta title", size=70, translate=True),
'website_meta_description': fields.text("Website meta description", translate=True),
'website_meta_keywords': fields.char("Website meta keywords", size=70, translate=True),
'website_meta_description': fields.text("Website meta description", size=160, translate=True),
'website_meta_keywords': fields.char("Website meta keywords", translate=True),
}
_defaults = {
'page': False,
+27 -5
View File
@@ -14,6 +14,7 @@ import traceback
from openerp.tools.safe_eval import safe_eval
from openerp.exceptions import AccessError, AccessDenied
import werkzeug
from openerp.addons.base.ir.ir_qweb import QWebException
import logging
logger = logging.getLogger(__name__)
@@ -181,11 +182,12 @@ class website(osv.osv):
logger.error("Website Rendering Error.\n\n%s" % traceback.format_exc())
return self.render(cr, uid, ids, 'website.404', qweb_context)
try:
main_object = request.registry[view_ref[0]].browse(cr, uid, view_ref[1])
qweb_context['main_object'] = main_object
except Exception:
pass
if 'main_object' not in qweb_context:
try:
main_object = request.registry[view_ref[0]].browse(cr, uid, view_ref[1])
qweb_context['main_object'] = main_object
except Exception:
pass
try:
return view.render(
@@ -196,6 +198,16 @@ class website(osv.osv):
qweb_context['error'] = err[1]
logger.warn("Website Rendering Error.\n\n%s" % traceback.format_exc())
return self.render(cr, uid, ids, 'website.401', qweb_context)
except (QWebException,), err:
qweb_context['traceback'] = traceback.format_exc()
qweb_context['template'] = err.template
qweb_context['message'] = err.message
qweb_context['node'] = err.node and err.node.toxml()
logger.error("Website Rendering Error.\n%(message)s\n%(node)s\n\n%(traceback)s" % qweb_context)
return view.render(
cr, uid,
'website.500' if qweb_context['editable'] else 'website.404',
qweb_context, context=context)
except Exception:
logger.exception("Website Rendering Error.")
qweb_context['traceback'] = traceback.format_exc()
@@ -392,3 +404,13 @@ class base_language_install(osv.osv):
'target': 'self'
}
return action
class SeoMetadata(osv.Model):
_name = 'website.seo.metadata'
_description = 'SEO metadata'
_columns = {
'website_meta_title': fields.char("Website meta title", size=70, translate=True),
'website_meta_description': fields.text("Website meta description", size=160, translate=True),
'website_meta_keywords': fields.char("Website meta keywords", translate=True),
}
+24 -58
View File
@@ -305,87 +305,53 @@ table.editorbar-panel td.selected {
}
/* ---- SNIPPETS DROP ZONES ---- */
#dark_for_dropzone {
width: 100%;
position: absolute;
top: 0;
left: 0;
opacity: 0.4;
z-index: 1000;
pointer-events: none;
}
#dark_for_dropzone td {
background: black;
}
#dark_for_dropzone td.center.active {
background: transparent;
}
.oe_drop_zone, .oe_drop_zone_style {
border: none;
background: rgba(100, 255, 255, 0.9);
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
-ms-border-radius: 4px;
-o-border-radius: 4px;
border-radius: 4px;
}
.oe_drop_zone div, .oe_drop_zone_style div {
margin: 0;
line-height: 48px;
text-align: center;
color: magenta;
font-weight: bold;
font-size: 24px;
}
.oe_drop_zone .oe_active, .oe_drop_zone_style .oe_active {
display: none;
}
.oe_drop_zone_style div {
line-height: 24px;
}
.oe_drop_zone {
.oe_drop_zone.oe_insert {
display: block;
height: 48px;
margin: 0px;
margin-top: -4px;
margin-bottom: -44px;
z-index: 1002;
-webkit-transition: margin 250ms linear;
-moz-transition: margin 250ms linear;
-o-transition: margin 250ms linear;
transition: margin 250ms linear;
width: 100%;
position: absolute;
z-index: 1000;
}
.oe_drop_zone:not(.oe_vertical):before {
.oe_drop_zone.oe_insert:not(.oe_vertical):before {
content: "";
display: block;
border-top: dashed 2px rgba(209, 178, 255, 0.72);
position: relative;
top: 0px;
}
.oe_drop_zone.oe_hover:before {
.oe_drop_zone.oe_insert.oe_hover:before {
border-top: dashed 2px rgba(116, 255, 161, 0.72);
}
.oe_drop_zone.oe_vertical {
.oe_drop_zone.oe_insert.oe_vertical {
width: 48px;
float: left;
position: relative;
margin: 4px -24px !important;
margin: 0px -24px !important;
}
.oe_drop_zone.oe_vertical div {
display: none;
}
.oe_drop_zone.oe_overlay {
.oe_drop_zone.oe_insert.oe_overlay {
border-radius: 3px;
background: rgba(153, 0, 255, 0.5);
}
.oe_drop_zone.oe_drop_active {
background: rgba(100, 255, 255, 0.3);
.oe_drop_zone, .oe_drop_zone_style {
border: none;
background: rgba(153, 0, 255, 0.3);
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
-ms-border-radius: 4px;
-o-border-radius: 4px;
border-radius: 4px;
}
.oe_drop_zone.oe_drop_active div {
display: none;
}
.oe_drop_zone.oe_drop_active .oe_active {
display: block;
.oe_drop_zone.oe_hover, .oe_drop_zone_style.oe_hover {
background: rgba(0, 255, 133, 0.3);
z-index: 1001;
}
.oe_drop_zone_style {
+17 -41
View File
@@ -242,45 +242,16 @@ table.editorbar-panel
/* ---- SNIPPETS DROP ZONES ---- */
#dark_for_dropzone
width: 100%
position: absolute
top: 0
left: 0
opacity: 0.4
z-index: 1000
pointer-events: none
td
background: #000
&.center.active
background: transparent
.oe_drop_zone, .oe_drop_zone_style
border: none
background: rgba(100, 255, 255, .9)
+border-radius(4px)
div
margin: 0
line-height: 48px
text-align: center
color: #FF00FF
font-weight: bold
font-size: 24px
.oe_active
display: none
.oe_drop_zone_style div
line-height: 24px
.oe_drop_zone
.oe_drop_zone.oe_insert
display: block
height: 48px
margin: 0px
margin-top: -4px
margin-bottom: -44px
z-index: 1002
@include transition(margin 250ms linear)
width: 100%
position: absolute
z-index: 1000
&:not(.oe_vertical):before
content: ""
display: block
@@ -293,17 +264,22 @@ table.editorbar-panel
width: 48px
float: left
position: relative
margin: 4px -24px !important
div
display: none
margin: 0px -24px !important
&.oe_overlay
border-radius: 3px
&.oe_drop_active
background: rgba(100, 255, 255, .3)
div
display: none
.oe_active
display: block
//@include background-image( repeating-linear-gradient(45deg, rgba(255,255,255,.1) ,rgba(255,255,255,.1) 35px, rgba(0,0,0,.1) 35px, rgba(0,0,0,.1) 75px))
//background-size: 100px 100px
background: rgba(153, 0, 255,.5)
.oe_drop_zone, .oe_drop_zone_style
border: none
//@include background-image( repeating-linear-gradient(45deg, rgba(255,255,255,.1) ,rgba(255,255,255,.1) 35px, rgba(0,0,0,.1) 35px, rgba(0,0,0,.1) 75px))
//background-size: 100px 100px
background: rgba(153, 0, 255, .3)
+border-radius(4px)
&.oe_hover
background: rgba(0, 255, 133, .3)
z-index: 1001
.oe_drop_zone_style
color: white
+2 -1
View File
@@ -216,4 +216,5 @@
[data-snippet-id] {
min-height: 10px;
min-width: 10px;
}
}
+1 -4
View File
@@ -235,10 +235,7 @@ footer {
}
.oe_structure.oe_empty > .oe_drop_zone.oe_insert:only-child, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child {
position: relative;
}
.oe_structure.oe_empty > .oe_drop_zone.oe_insert:only-child div, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child div {
display: none;
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 {
+1 -3
View File
@@ -161,9 +161,7 @@ footer
height: 220px !important
.oe_structure.oe_empty > .oe_drop_zone.oe_insert:only-child, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child
position: relative
div
display: none
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: 'Click Edit To Create Content'
+108 -4
View File
@@ -311,6 +311,7 @@
},
});
var blocks_selector = _.keys(CKEDITOR.dtd.$block).join(',');
/* ----- RICH TEXT EDITOR ---- */
website.RTE = openerp.Widget.extend({
tagName: 'li',
@@ -324,6 +325,103 @@
this._super.apply(this, arguments);
},
/**
* In Webkit-based browsers, triple-click will select a paragraph up to
* the start of the next "paragraph" including any empty space
* inbetween. When said paragraph is removed or altered, it nukes
* the empty space and brings part of the content of the next
* "paragraph" (which may well be e.g. an image) into the current one,
* completely fucking up layouts and breaking snippets.
*
* Try to fuck around with selections on triple-click to attempt to
* fix this garbage behavior.
*
* Note: for consistent behavior we may actually want to take over
* triple-clicks, in all browsers in order to ensure consistent cross-
* platform behavior instead of being at the mercy of rendering engines
* & platform selection quirks?
*/
webkitSelectionFixer: function (root) {
root.addEventListener('click', function (e) {
// only webkit seems to have a fucked up behavior, ignore others
// FIXME: $.browser goes away in jquery 1.9...
if (!$.browser.webkit) { return; }
// http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-eventgroupings-mouseevents
// The detail attribute indicates the number of times a mouse button has been pressed
// we just want the triple click
if (e.detail !== 3) { return; }
// Get closest block-level element to the triple-clicked
// element (using ckeditor's block list because why not)
var $closest_block = $(e.target).closest(blocks_selector);
// manually set selection range to the content of the
// triple-clicked block-level element, to avoid crossing over
// between block-level elements
document.getSelection().selectAllChildren($closest_block[0]);
});
},
tableNavigation: function (root) {
var self = this;
$(root).on('keydown', function (e) {
// ignore non-TAB
if (e.which !== 9) { return; }
if (self.handleTab(e)) {
e.preventDefault();
}
});
},
/**
* Performs whatever operation is necessary on a [TAB] hit, returns
* ``true`` if the event's default should be cancelled (if the TAB was
* handled by the function)
*/
handleTab: function (event) {
var forward = !event.shiftKey;
var root = window.getSelection().getRangeAt(0).commonAncestorContainer;
var $cell = $(root).closest('td,th');
if (!$cell.length) { return false; }
var cell = $cell[0];
// find cell in same row
var row = cell.parentNode;
var sibling = row.cells[cell.cellIndex + (forward ? 1 : -1)];
if (sibling) {
document.getSelection().selectAllChildren(sibling);
return true;
}
// find cell in previous/next row
var table = row.parentNode;
var sibling_row = table.rows[row.rowIndex + (forward ? 1 : -1)];
if (sibling_row) {
var new_cell = sibling_row.cells[forward ? 0 : sibling_row.cells.length - 1];
document.getSelection().selectAllChildren(new_cell);
return true;
}
// at edge cells, copy word/openoffice behavior: if going backwards
// from first cell do nothing, if going forwards from last cell add
// a row
if (forward) {
var row_size = row.cells.length;
var new_row = document.createElement('tr');
while(row_size--) {
var newcell = document.createElement('td');
// zero-width space
newcell.textContent = '\u200B';
new_row.appendChild(newcell);
}
table.appendChild(new_row);
document.getSelection().selectAllChildren(new_row.cells[0]);
}
return true;
},
start_edition: function ($elements) {
var self = this;
// create a single editor for the whole page
@@ -331,6 +429,8 @@
$(root).on('dragstart', 'img', function (e) {
e.preventDefault();
});
this.webkitSelectionFixer(root);
this.tableNavigation(root);
var editor = this.editor = CKEDITOR.inline(root, self._config());
editor.on('instanceReady', function () {
editor.setReadOnly(false);
@@ -341,6 +441,10 @@
self.setup_editables(root);
// disable firefox's broken table resizing thing
document.execCommand("enableObjectResizing", false, "false");
document.execCommand("enableInlineTableEditing", false, "false");
self.trigger('rte:ready');
});
},
@@ -394,14 +498,14 @@
// - contextmenu & tabletools (disable contextual menu)
// - bunch of unused plugins
var plugins = [
'a11yhelp', 'basicstyles', 'bidi', 'blockquote',
'a11yhelp', 'basicstyles', 'blockquote',
'clipboard', 'colorbutton', 'colordialog', 'dialogadvtab',
'elementspath', 'enterkey', 'entities', 'filebrowser',
'find', 'floatingspace','format', 'htmlwriter', 'iframe',
'indentblock', 'indentlist', 'justify',
'list', 'pastefromword', 'pastetext', 'preview',
'removeformat', 'resize', 'save', 'selectall', 'stylescombo',
'tab', 'table', 'templates', 'toolbar', 'undo', 'wysiwygarea'
'table', 'templates', 'toolbar', 'undo', 'wysiwygarea'
];
return {
// FIXME
@@ -927,7 +1031,7 @@
}
var Observer = window.MutationObserver || window.WebkitMutationObserver || window.JsMutationObserver;
website.Observer = window.MutationObserver || window.WebkitMutationObserver || window.JsMutationObserver;
var OBSERVER_CONFIG = {
childList: true,
attributes: true,
@@ -935,7 +1039,7 @@
subtree: true,
attributeOldValue: true,
};
var observer = new Observer(function (mutations) {
var observer = new website.Observer(function (mutations) {
// NOTE: Webkit does not fire DOMAttrModified => webkit browsers
// relying on JsMutationObserver shim (Chrome < 18, Safari < 6)
// will not mark dirty on attribute changes (@class, img/@src,
+42 -14
View File
@@ -241,7 +241,8 @@
return hashIndex >= 0 ? url.substring(0, hashIndex) : url;
},
title: function () {
return ($('title').length > 0) && $('title').text() && $('title').text().trim();
var $title = $('title');
return ($title.length > 0) && $title.text() && $title.text().trim();
},
changeTitle: function (title) {
// TODO create tag if missing
@@ -250,7 +251,7 @@
},
description: function () {
var $description = $('meta[name=description]');
return ($description.length > 0) && $description.attr('value') && $description.attr('value').trim();
return ($description.length > 0) && ($description.attr('value') && $description.attr('value').trim());
},
changeDescription: function (description) {
// TODO create tag if missing
@@ -322,6 +323,9 @@
'click button[data-action=update]': 'update',
'hidden.bs.modal': 'destroy',
},
canEditTitle: false,
canEditDescription: false,
canEditKeywords: false,
maxTitleSize: 65,
maxDescriptionSize: 155,
start: function () {
@@ -331,13 +335,13 @@
$modal.find('.js_seo_page_url').text(htmlPage.url());
$modal.find('input[name=seo_page_title]').val(htmlPage.title());
$modal.find('textarea[name=seo_page_description]').val(htmlPage.description());
self.suggestImprovements();
self.imageList = new website.seo.ImageList(self, { page: htmlPage });
if (htmlPage.images().length === 0) {
$modal.find('.js_image_section').remove();
} else {
self.imageList.appendTo($modal.find('.js_seo_image_list'));
}
// self.suggestImprovements();
// self.imageList = new website.seo.ImageList(self, { page: htmlPage });
// if (htmlPage.images().length === 0) {
// $modal.find('.js_image_section').remove();
// } else {
// self.imageList.appendTo($modal.find('.js_seo_image_list'));
// }
self.keywordList = new website.seo.KeywordList(self, { page: htmlPage });
self.keywordList.on('list-full', self, function () {
$modal.find('input[name=seo_page_keywords]')
@@ -356,8 +360,27 @@
self.keywordList.add(word);
});
self.keywordList.appendTo($modal.find('.js_seo_keywords_list'));
self.disableUnsavableFields();
$modal.modal();
},
disableUnsavableFields: function () {
var self = this;
var $modal = self.$el;
self.loadMetaData().then(function (data) {
self.canEditTitle = data && ('website_meta_title' in data);
self.canEditDescription = data && ('website_meta_description' in data);
self.canEditKeywords = data && ('website_meta_keywords' in data);
if (!self.canEditTitle) {
$modal.find('input[name=seo_page_title]').attr('disabled', true);
}
if (!self.canEditDescription) {
$modal.find('textarea[name=seo_page_description]').attr('disabled', true);
}
if (!self.canEditTitle && !canEditDescription && !canEditKeywords) {
$modal.find('button[data-action=update]').attr('disabled', true);
}
});
},
suggestImprovements: function () {
var tips = [];
var self = this;
@@ -397,11 +420,16 @@
},
update: function () {
var self = this;
var data = {
website_meta_title: self.htmlPage.title(),
website_meta_description: self.htmlPage.description(),
website_meta_keywords: self.keywordList.keywords().join(", "),
};
var data = {};
if (self.canEditTitle) {
data.website_meta_title = self.htmlPage.title();
}
if (self.canEditDescription) {
data.website_meta_description = self.htmlPage.description();
}
if (self.canEditKeywords) {
data.website_meta_keywords = self.keywordList.keywords().join(", ");
}
self.saveMetaData(data).then(function () {
self.$el.modal('hide');
});
@@ -45,7 +45,14 @@
/* ----- SNIPPET SELECTOR ---- */
website.snippet = {};
var observer = new website.Observer(function (mutations) {
if (!_(mutations).find(function (m) {
return m.type === 'childList' && m.addedNodes.length > 0;
})) {
return;
}
hack_to_add_snippet_id()
});
// puts $el at the same absolute position as $target
function hack_to_add_snippet_id () {
@@ -80,7 +87,11 @@
this.$active_snipped_id = false;
hack_to_add_snippet_id();
this.snippets = [];
$("body").on('DOMNodeInserted', hack_to_add_snippet_id);
observer.observe(document.body, {
childList: true,
subtree: true,
});
},
dom_filter: function (dom, sibling) {
if (typeof dom === "string") {
@@ -308,32 +319,17 @@
}
var $dark = $(openerp.qweb.render('website.snippet_dark_for_dropzone'))
.css('height', $("body")[0].scrollHeight + 'px');
$("body").append($dark);
$('.oe_drop_zone').droppable({
over: function(){
if( action === 'insert'){
dropped = true;
$(this).first().addClass("oe_drop_active").after($toInsert);
$dark.find("td:first")
.css('height', $toInsert.offset().top+'px');
$dark.find("tr:eq(1) td:first")
.css('width', $toInsert.offset().left+'px');
$dark.find("td.center")
.addClass("active")
.css('height', $toInsert.outerHeight()+'px')
.css('width', $toInsert.outerWidth()+'px');
$(this).first().after($toInsert);
}
},
out: function(){
if( action === 'insert'){
$(this).removeClass("oe_drop_active");
dropped = false;
$toInsert.detach();
$dark.find("td.center").removeClass("active");
$("body").scroll(); // trigger a scroll to reset position for jquery api
}
},
drop: function(){
@@ -342,8 +338,15 @@
});
},
stop: function(ev, ui){
if (action === 'insert' && ! dropped) {
var el = $('.oe_drop_zone').nearest({x: ui.position.left, y: ui.position.top}).first()
if (el) {
el.after($toInsert)
dropped = true;
}
}
$('.oe_drop_zone').droppable('destroy').remove();
$("#dark_for_dropzone").remove();
if (dropped) {
var $target = false;
if(action === 'insert'){
@@ -394,7 +397,7 @@
var sibling_selector = selector.siblings;
var vertical_child_selector = selector.vertical_children;
var zone_template = openerp.qweb.render('website.snippet_drop_zone');
var zone_template = "<div class='oe_drop_zone oe_insert'></div>";
if(child_selector){
self.dom_filter(child_selector).each(function (){
@@ -414,7 +417,7 @@
var temp_left = 0;
$zone.find('> *:not(.oe_drop_zone):visible').each(function () {
var $col = $(this);
$template.css('height', ($col.outerHeight() + parseInt($col.css("margin-top")) + parseInt($col.css("margin-bottom")) - 8)+'px');
$template.css('height', ($col.outerHeight() + parseInt($col.css("margin-top")) + parseInt($col.css("margin-bottom")))+'px');
$lastinsert = $template.clone();
$(this).after($lastinsert);
@@ -583,8 +586,7 @@
* Displayed into the overlay options on focus
*/
_readXMLData: function() {
var self = this;
this.$el = this.parent.$snippets.filter(function () { return $(this).data("snippet-id") == self.snippet_id; }).clone();
this.$el = this.parent.$snippets.siblings("[data-snippet-id='"+this.snippet_id+"']").clone();
this.$editor = this.$el.find(".oe_snippet_options");
var $options = this.$overlay.find(".oe_overlay_options");
this.$editor.prependTo($options.find(".oe_options ul"));
@@ -619,28 +621,18 @@
});
},
_drag_and_drop_after_insert_dropzone: function (){},
_drag_and_drop_active_drop_zone: function (){
_drag_and_drop_active_drop_zone: function ($zones){
var self = this;
var $dark = $("#dark_for_dropzone");
$('.oe_drop_zone').droppable({
$zones.droppable({
over: function(){
$(this).first().addClass("oe_drop_active").after(self.$target);
$dark.find("td:first")
.css('height', self.$target.offset().top+'px');
$dark.find("tr:eq(1) td:first")
.css('width', self.$target.offset().left+'px');
$dark.find("td.center")
.addClass("active")
.css('height', self.$target.outerHeight()+'px')
.css('width', self.$target.outerWidth()+'px');
$(".oe_drop_zone.hide").removeClass("hide");
$(this).addClass("hide").first().after(self.$target);
self.dropped = true;
},
out: function(){
$(this).removeClass("oe_drop_active");
$dark.find("td.center").removeClass("active");
$(this).removeClass("hide");
self.$target.detach();
self.dropped = false;
$("body").scroll(); // trigger a scroll to reset position for jquery api
},
});
},
@@ -664,12 +656,8 @@
$("body").addClass('move-important');
var $dark = $(openerp.qweb.render('website.snippet_dark_for_dropzone'))
.css('height', $("body")[0].scrollHeight + 'px');
$("body").append($dark);
self._drag_and_drop_after_insert_dropzone();
self._drag_and_drop_active_drop_zone();
self._drag_and_drop_active_drop_zone($('.oe_drop_zone'));
},
_drag_and_drop_stop: function (){
var self = this;
@@ -679,7 +667,6 @@
self.$overlay.removeClass("hidden");
$("body").removeClass('move-important');
$('.oe_drop_zone').droppable('destroy').remove();
$('#dark_for_dropzone').remove();
$(".oe_drop_clone, .oe_drop_to_remove").remove();
self.parent.editor_busy = false;
self.get_parent_block();
@@ -977,25 +964,23 @@
_drag_and_drop_after_insert_dropzone: function(){
var self = this;
// commented for perf
// var $zones = $(".row:has(> .oe_drop_zone)").each(function () {
// var $row = $(this);
// var width = $row.innerWidth();
// var pos = 0;
// while (width > pos + self.size.width) {
// var $last = $row.find("> .oe_drop_zone:last");
// $last.each(function () {
// pos = $(this).position().left;
// });
// if (width > pos + self.size.width) {
// $row.append("<div class='col-md-1 oe_drop_to_remove'/>");
// var $add_drop = $last.clone();
// $row.append($add_drop);
// self._drag_and_drop_active_drop_zone($add_drop);
// }
// }
// });
var $zones = $(".row:has(> .oe_drop_zone)").each(function () {
var $row = $(this);
var width = $row.innerWidth();
var pos = 0;
while (width > pos + self.size.width) {
var $last = $row.find("> .oe_drop_zone:last");
$last.each(function () {
pos = $(this).position().left;
});
if (width > pos + self.size.width) {
$row.append("<div class='col-md-1 oe_drop_to_remove'/>");
var $add_drop = $last.clone();
$row.append($add_drop);
self._drag_and_drop_active_drop_zone($add_drop);
}
}
});
},
_drag_and_drop_start: function () {
this._super();
@@ -1089,6 +1074,14 @@
self.$target.carousel();
});
this.$target.on('dblclick', '.item.active .carousel-image img', function (event) {
var $img = $(event.currentTarget);
var editor = new website.editor.ImageDialog();
editor.on('start', self, function (o) {o.url = $img.attr("src");});
editor.on('save', self, function (o) {$img.attr("src", o.url);});
editor.appendTo($('body'));
});
this.rebind_event();
},
// rebind event to active carousel on edit mode
@@ -48,12 +48,13 @@
</div>
</div>
</section>
<!--
<section class="js_image_section">
<h3 class="page-header">3. Describe your images</h3>
<div class="row js_seo_image_list">
<!-- filled in JS -->
</div>
</section>
-->
</div><div class="modal-footer">
<button data-action="discard" data-dismiss="modal" href="#" class="btn btn-default">Discard</button>
<button type="button" data-action="update" class="btn btn-primary">Apply Changes</button>
@@ -31,8 +31,8 @@
this one:
</p>
<div class="row">
<div class="col-sm-6 col-sm-offset-3 oe_drop_zone_style text-center">
<div>drop in this zone</div>
<div class="col-sm-4 col-sm-offset-4 oe_drop_zone_style text-center">
<span class="mt16">drop in this zone</span>
</div>
</div>
<div class="text-muted">
@@ -57,25 +57,6 @@
<div id='oe_snippets'></div>
</t>
<t t-name="website.snippet_drop_zone">
<div class='oe_drop_zone oe_insert'>
<div>Drag your block here (move your mouse in this zone)</div>
<div class="oe_active">Drop your block</div>
</div>
</t>
<t t-name="website.snippet_dark_for_dropzone">
<div id="dark_for_dropzone">
<table width="100%" height="100%">
<tbody>
<tr><td colspan="3"></td></tr>
<tr><td></td><td class="center"></td><td></td></tr>
<tr><td colspan="3"></td></tr>
</tbody>
</table>
</div>
</t>
<t t-name="website.snippet_overlay">
<div class="oe_overlay">
<div class="oe_overlay_options">
+10 -3
View File
@@ -29,8 +29,10 @@
</t>
<title><t t-esc="title"/></title>
<meta name="openerp.company" t-att-value="res_company.name"/>
<meta name="description" t-att-value="main_object and main_object.website_meta_description or website_meta_description"/>
<meta name="keywords" t-att-value="main_object and main_object.website_meta_keywords or website_meta_keywords"/>
<meta name="description" t-att-value="main_object and 'website_meta_description' in main_object
and main_object.website_meta_description or website_meta_description"/>
<meta name="keywords" t-att-value="main_object and 'website_meta_keywords' in main_object
and main_object.website_meta_keywords or website_meta_keywords"/>
<!-- Load stylesheets before scripts to avoid blocking -->
<link rel='stylesheet' href='/web/static/lib/fontawesome/css/font-awesome.css'/>
@@ -356,7 +358,12 @@
<div class="oe_structure">
<h1 class="container mt32">500: Internal Server Error!</h1>
</div>
<pre t-if="editable" t-esc="traceback"/>
<t t-if="editable">
<h3>An exception appear in the template: <span id="exception_template" t-esc="template"/></h3>
<b id="exception_message" t-esc="message"/>
<pre id="exception_node" t-esc="node"/>
<pre id="exception_traceback" t-esc="traceback"/>
</t>
</div>
</t>
</template>
+7
View File
@@ -150,6 +150,13 @@ class WebsiteBlog(http.Controller):
'unable_editor': post.get('unable_editor')
}
if blog_post:
values['main_object'] = blog_post
elif tag:
values['main_object'] = tag
elif category:
values['main_object'] = category
return request.website.render("website_blog.index", values)
@website.route(['/blog/nav'], type='http', auth="public")
+3 -2
View File
@@ -31,7 +31,7 @@ import difflib
class BlogCategory(osv.Model):
_name = 'blog.category'
_description = 'Blog Category'
_inherit = ['mail.thread']
_inherit = ['mail.thread', 'website.seo.metadata']
_order = 'name'
_columns = {
@@ -47,6 +47,7 @@ class BlogCategory(osv.Model):
class BlogTag(osv.Model):
_name = 'blog.tag'
_description = 'Blog Tag'
_inherit = ['website.seo.metadata']
_order = 'name'
_columns = {
@@ -60,7 +61,7 @@ class BlogTag(osv.Model):
class BlogPost(osv.Model):
_name = "blog.post"
_description = "Blog Post"
_inherit = ['mail.thread']
_inherit = ['mail.thread', 'website.seo.metadata']
_order = 'write_date DESC'
# maximum number of characters to display in summary
_shorten_max_char = 250
+3 -2
View File
@@ -154,9 +154,10 @@ class website_event(http.Controller):
@website.route(['/event/<int:event_id>'], type='http', auth="public", multilang=True)
def event(self, event_id=None, **post):
event_obj = request.registry['event.event']
event = event_obj.browse(request.cr, request.uid, event_id, dict(request.context, show_address_only=1))
values = {
'event_id': event_obj.browse(request.cr, request.uid, event_id,
dict(request.context, show_address_only=1)),
'event_id': event,
'main_object': event,
'range': range,
'float': float,
}
+3
View File
@@ -45,6 +45,9 @@ class event(osv.osv):
string='Website Messages',
help="Website communication history",
),
'website_meta_title': fields.char("Website meta title", size=70, translate=True),
'website_meta_description': fields.text("Website meta description", size=160, translate=True),
'website_meta_keywords': fields.char("Website meta keywords", translate=True),
}
_defaults = {
'website_published': False,
+3
View File
@@ -50,6 +50,9 @@ class product_template(osv.Model):
'website_style_ids' : fields.many2many('website.product.style','product_website_style_rel', 'product_id', 'style_id', 'Styles'),
'website_sequence': fields.integer('Sequence', help="Determine the display order in the Website E-commerce"),
'website_url': fields.function(_website_url, string="Website url"),
'website_meta_title': fields.char("Website meta title", size=70, translate=True),
'website_meta_description': fields.text("Website meta description", size=160, translate=True),
'website_meta_keywords': fields.char("Website meta keywords", translate=True),
}
_defaults = {
'website_size_x': 1,
@@ -29,14 +29,24 @@ class attributes(osv.Model):
result.update(dict(cr.fetchall()))
return result
def _get_min_max(self, cr, uid, ids, context=None):
result = {}
for value in self.pool.get('product.attribute.product').browse(cr, uid, ids, context=context):
if value.type == 'float':
result[value.attribute_id.id] = True
return result.keys()
_columns = {
'name': fields.char('Name', size=64, translate=True, required=True),
'type': fields.selection([('distinct', 'Distinct'), ('float', 'Float')], "Type", required=True),
'value_ids': fields.one2many('product.attribute.value', 'attribute_id', 'Values'),
'product_ids': fields.one2many('product.attribute.product', 'attribute_id', 'Products'),
'float_max': fields.function(_get_float_max, type='float', string="Max", relation='product.attribute.product'),
'float_min': fields.function(_get_float_min, type='float', string="Min", relation='product.attribute.product'),
'float_max': fields.function(_get_float_max, type='float', string="Max", store={
'product.attribute.product': (_get_min_max, ['value','attribute_id'], 20),
}),
'float_min': fields.function(_get_float_min, type='float', string="Min", store={
'product.attribute.product': (_get_min_max, ['value','attribute_id'], 20),
}),
}
_defaults = {
'type': 'distinct'