[MERGE] Merge parents
bzr revid: rim@openerp.com-20131105103727-8uy08rsv0be3x1mv
This commit is contained in:
@@ -155,7 +155,6 @@
|
||||
<field name="type" ref="event_type_4"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="address_id" ref="base.res_partner_2"/>
|
||||
<field name="organizer_id" ref="base.res_partner_address_4"/>
|
||||
<field name="description"><![CDATA[
|
||||
<div class="oe_structure">
|
||||
<center><strong>5-days Technical Training</strong></center>
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,5 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import base64
|
||||
import cStringIO
|
||||
import contextlib
|
||||
import hashlib
|
||||
@@ -49,7 +48,19 @@ MAX_IMAGE_WIDTH, MAX_IMAGE_HEIGHT = IMAGE_LIMITS = (1024, 768)
|
||||
class Website(openerp.addons.web.controllers.main.Home):
|
||||
@website.route('/', type='http', auth="public", multilang=True)
|
||||
def index(self, **kw):
|
||||
return self.page("website.homepage")
|
||||
# TODO: check if plain SQL is needed
|
||||
menu = request.registry['website.menu']
|
||||
root_domain = [('parent_id', '=', False)] # TODO: multiwebsite ('website_id', '=', request.website.id),
|
||||
root_id = menu.search(request.cr, request.uid, root_domain, limit=1, context=request.context)[0]
|
||||
first_menu = menu.search_read(
|
||||
request.cr, request.uid, [('parent_id', '=', root_id)], ['url'],
|
||||
limit=1, order='sequence', context=request.context)
|
||||
if first_menu:
|
||||
first_menu = first_menu[0]['url']
|
||||
if first_menu and first_menu != '/':
|
||||
return request.redirect(first_menu)
|
||||
else:
|
||||
return self.page("website.homepage")
|
||||
|
||||
@website.route('/pagenew/<path:path>', type='http', auth="user")
|
||||
def pagenew(self, path, noredirect=NOPE):
|
||||
@@ -124,11 +135,8 @@ class Website(openerp.addons.web.controllers.main.Home):
|
||||
values = {
|
||||
'path': path,
|
||||
}
|
||||
try:
|
||||
html = request.website.render(path, values)
|
||||
except ValueError:
|
||||
html = request.website.render('website.404', values)
|
||||
return html
|
||||
|
||||
return request.website.render(path, values)
|
||||
|
||||
@website.route('/website/customize_template_toggle', type='json', auth='user')
|
||||
def customize_template_set(self, view_id):
|
||||
|
||||
@@ -8,6 +8,22 @@
|
||||
<field name="default_lang_id" ref="base.lang_en"/>
|
||||
</record>
|
||||
|
||||
<record id="main_menu" model="website.menu">
|
||||
<field name="name">Main Menu</field>
|
||||
</record>
|
||||
|
||||
<record id="menu_homepage" model="website.menu">
|
||||
<field name="name">Homepage</field>
|
||||
<field name="url">/</field>
|
||||
<field name="parent_id" ref="website.main_menu"/>
|
||||
</record>
|
||||
|
||||
<record id="menu_contactus" model="website.menu">
|
||||
<field name="name">Contact us</field>
|
||||
<field name="url">/page/website.contactus</field>
|
||||
<field name="parent_id" ref="website.main_menu"/>
|
||||
</record>
|
||||
|
||||
<record id="public_user" model="res.users">
|
||||
<field name="name">public</field>
|
||||
<field name="login">public</field>
|
||||
|
||||
@@ -1,22 +1,25 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import fnmatch
|
||||
import functools
|
||||
import operator
|
||||
import logging
|
||||
import math
|
||||
import simplejson
|
||||
|
||||
import openerp
|
||||
from openerp.osv import osv, fields
|
||||
from openerp.addons.web import http
|
||||
from openerp.addons.web.http import request
|
||||
import traceback
|
||||
import urllib
|
||||
from urlparse import urljoin
|
||||
import math
|
||||
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
|
||||
import werkzeug
|
||||
import werkzeug.exceptions
|
||||
import werkzeug.wrappers
|
||||
|
||||
import openerp
|
||||
from openerp.exceptions import AccessError, AccessDenied
|
||||
from openerp.osv import osv, fields
|
||||
from openerp.tools.safe_eval import safe_eval
|
||||
from openerp.addons.web import http
|
||||
from openerp.addons.web.http import request
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def route(routes, *route_args, **route_kwargs):
|
||||
@@ -179,8 +182,7 @@ class website(osv.osv):
|
||||
try:
|
||||
view_ref = IMD.get_object_reference(cr, uid, module, xmlid)
|
||||
except ValueError:
|
||||
logger.error("Website Rendering Error.\n\n%s" % traceback.format_exc())
|
||||
return self.render(cr, uid, ids, 'website.404', qweb_context)
|
||||
return self.error(cr, uid, 404, qweb_context, context=context)
|
||||
|
||||
if 'main_object' not in qweb_context:
|
||||
try:
|
||||
@@ -197,15 +199,23 @@ class website(osv.osv):
|
||||
logger.error(err)
|
||||
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)
|
||||
return self.error(cr, uid, 401, qweb_context, context=context)
|
||||
except Exception, e:
|
||||
qweb_context['template'] = getattr(e, 'qweb_template', '')
|
||||
node = getattr(e, 'qweb_node', None)
|
||||
qweb_context['node'] = node and node.toxml()
|
||||
qweb_context['expr'] = getattr(e, 'qweb_eval', '')
|
||||
qweb_context['traceback'] = traceback.format_exc()
|
||||
logger.error("Website Rendering Error.\n%(template)s\n%(expr)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)
|
||||
logger.exception("Website Rendering Error.\n%(template)s\n%(expr)s\n%(node)s" % qweb_context)
|
||||
return self.error(cr, uid, 500 if qweb_context['editable'] else 404,
|
||||
qweb_context, context=context)
|
||||
|
||||
def error(self, cr, uid, code, qweb_context, context=None):
|
||||
View = request.registry['ir.ui.view']
|
||||
return werkzeug.wrappers.Response(
|
||||
View.render(cr, uid, 'website.%d' % code, qweb_context),
|
||||
status=code,
|
||||
content_type='text/html;charset=utf-8')
|
||||
|
||||
def pager(self, cr, uid, ids, url, total, page=1, step=30, scope=5, url_args=None):
|
||||
# Compute Pager
|
||||
@@ -352,6 +362,75 @@ class website(osv.osv):
|
||||
html += request.website.render(template, {'object_id': object_id})
|
||||
return html
|
||||
|
||||
def get_menu_tree(self, cr, uid, ids, context=None):
|
||||
return self.pool['website.menu'].get_tree(cr, uid, ids[0], context=context)
|
||||
|
||||
class website_menu(osv.osv):
|
||||
_name = "website.menu"
|
||||
_description = "Website Menu"
|
||||
_columns = {
|
||||
'name': fields.char('Menu', size=64, required=True, translate=True),
|
||||
'url': fields.char('Url', required=True, translate=True),
|
||||
'new_window': fields.boolean('New Window'),
|
||||
'sequence': fields.integer('Sequence'),
|
||||
# TODO: support multiwebsite once done for ir.ui.views
|
||||
'website_id': fields.many2one('website', 'Website'),
|
||||
'parent_id': fields.many2one('website.menu', 'Parent Menu', select=True, ondelete="cascade"),
|
||||
'parent_left': fields.integer('Parent Left', select=True),
|
||||
'parent_right': fields.integer('Parent Right', select=True),
|
||||
}
|
||||
_defaults = {
|
||||
'url': '',
|
||||
'sequence': 0,
|
||||
}
|
||||
_order = "parent_left"
|
||||
|
||||
# TODO: ormcache
|
||||
def get_tree(self, cr, uid, website_id, fields=None, context=None):
|
||||
if not fields:
|
||||
fields = ['id', 'name', 'url', 'new_window', 'sequence', 'parent_id']
|
||||
root_domain = [('parent_id', '=', False)] # ('website_id', '=', website_id),
|
||||
root_menu_id = self.search(cr, uid, root_domain, limit=1, context=context)[0]
|
||||
menu_ids = self.search(cr, uid, [('id', 'child_of', root_menu_id)], 0, False, False, context)
|
||||
menu_items = self.read(cr, uid, menu_ids, fields, context=context)
|
||||
menu_items_map = dict((menu_item["id"], menu_item) for menu_item in menu_items)
|
||||
for menu_item in menu_items:
|
||||
if menu_item['parent_id']:
|
||||
parent = menu_item['parent_id'][0]
|
||||
else:
|
||||
parent = False
|
||||
if parent in menu_items_map:
|
||||
parent_obj = menu_items_map[parent]
|
||||
parent_obj.setdefault('level', 0)
|
||||
parent_obj.setdefault('children', []).append(menu_item)
|
||||
menu_item['level'] = parent_obj['level'] + 1
|
||||
|
||||
# sort by sequence a tree using parent_id
|
||||
for menu_item in menu_items:
|
||||
menu_item.setdefault('children', []).sort(
|
||||
key=operator.itemgetter('sequence'))
|
||||
|
||||
return menu_items[0]
|
||||
|
||||
def save(self, cr, uid, website_id, data, context=None):
|
||||
def replace_id(old_id, new_id):
|
||||
for menu in data['data']:
|
||||
if menu['id'] == old_id:
|
||||
menu['id'] = new_id
|
||||
if menu['parent_id'] == old_id:
|
||||
menu['parent_id'] = new_id
|
||||
to_delete = data['to_delete']
|
||||
if to_delete:
|
||||
self.unlink(cr, uid, to_delete, context=context)
|
||||
for menu in data['data']:
|
||||
mid = menu['id']
|
||||
if isinstance(mid, str):
|
||||
new_id = self.create(cr, uid, {'name': menu['name']}, context=context)
|
||||
replace_id(mid, new_id)
|
||||
for menu in data['data']:
|
||||
self.write(cr, uid, [menu['id']], menu, context=context)
|
||||
return True
|
||||
|
||||
class ir_attachment(osv.osv):
|
||||
_inherit = "ir.attachment"
|
||||
def _website_url_get(self, cr, uid, ids, name, arg, context=None):
|
||||
@@ -392,6 +471,15 @@ class res_partner(osv.osv):
|
||||
}
|
||||
return urlplus('https://maps.google.be/maps' , params)
|
||||
|
||||
class res_company(osv.osv):
|
||||
_inherit = "res.company"
|
||||
def google_map_img(self, cr, uid, ids, zoom=8, width=298, height=298, context=None):
|
||||
partner = self.browse(cr, openerp.SUPERUSER_ID, ids[0], context=context).parent_id
|
||||
return partner and partner.google_map_img(zoom, width, height, context=context) or None
|
||||
def google_map_link(self, cr, uid, ids, zoom=8, context=None):
|
||||
partner = self.browse(cr, openerp.SUPERUSER_ID, ids[0], context=context).parent_id
|
||||
return partner and partner.google_map_link(zoom, context=context) or None
|
||||
|
||||
class base_language_install(osv.osv):
|
||||
_inherit = "base.language.install"
|
||||
_columns = {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_website_public,website,website.model_website,base.group_public,1,0,0,0
|
||||
access_website,website,website.model_website,base.group_user,1,0,0,0
|
||||
access_website_menu,access_website_menu,model_website_menu,,1,0,0,0
|
||||
access_website_converter_test,access_website_converter_test,model_website_converter_test,,1,1,1,1
|
||||
access_website_converter_test_sub,access_website_converter_test_sub,model_website_converter_test_sub,,1,1,1,1
|
||||
access_website_qweb,access_website_qweb,model_website_qweb,,0,0,0,0
|
||||
|
||||
|
@@ -0,0 +1,429 @@
|
||||
/*
|
||||
* jQuery UI Nested Sortable
|
||||
* v 1.3.5 / 21 jun 2012
|
||||
* http://mjsarfatti.com/code/nestedSortable
|
||||
*
|
||||
* Depends on:
|
||||
* jquery.ui.sortable.js 1.8+
|
||||
*
|
||||
* Copyright (c) 2010-2012 Manuele J Sarfatti
|
||||
* Licensed under the MIT License
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
|
||||
$.widget("mjs.nestedSortable", $.extend({}, $.ui.sortable.prototype, {
|
||||
|
||||
options: {
|
||||
tabSize: 20,
|
||||
disableNesting: 'mjs-nestedSortable-no-nesting',
|
||||
errorClass: 'mjs-nestedSortable-error',
|
||||
doNotClear: false,
|
||||
listType: 'ol',
|
||||
maxLevels: 0,
|
||||
protectRoot: false,
|
||||
rootID: null,
|
||||
rtl: false,
|
||||
isAllowed: function(item, parent) { return true; }
|
||||
},
|
||||
|
||||
_create: function() {
|
||||
this.element.data('sortable', this.element.data('nestedSortable'));
|
||||
|
||||
if (!this.element.is(this.options.listType))
|
||||
throw new Error('nestedSortable: Please check the listType option is set to your actual list type');
|
||||
|
||||
return $.ui.sortable.prototype._create.apply(this, arguments);
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this.element
|
||||
.removeData("nestedSortable")
|
||||
.unbind(".nestedSortable");
|
||||
return $.ui.sortable.prototype.destroy.apply(this, arguments);
|
||||
},
|
||||
|
||||
_mouseDrag: function(event) {
|
||||
|
||||
//Compute the helpers position
|
||||
this.position = this._generatePosition(event);
|
||||
this.positionAbs = this._convertPositionTo("absolute");
|
||||
|
||||
if (!this.lastPositionAbs) {
|
||||
this.lastPositionAbs = this.positionAbs;
|
||||
}
|
||||
|
||||
var o = this.options;
|
||||
|
||||
//Do scrolling
|
||||
if(this.options.scroll) {
|
||||
var scrolled = false;
|
||||
if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
|
||||
|
||||
if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
|
||||
this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
|
||||
else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
|
||||
this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
|
||||
|
||||
if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
|
||||
this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
|
||||
else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
|
||||
this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
|
||||
|
||||
} else {
|
||||
|
||||
if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
|
||||
scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
|
||||
else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
|
||||
scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
|
||||
|
||||
if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
|
||||
scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
|
||||
else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
|
||||
scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
|
||||
|
||||
}
|
||||
|
||||
if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
|
||||
$.ui.ddmanager.prepareOffsets(this, event);
|
||||
}
|
||||
|
||||
//Regenerate the absolute position used for position checks
|
||||
this.positionAbs = this._convertPositionTo("absolute");
|
||||
|
||||
// Find the top offset before rearrangement,
|
||||
var previousTopOffset = this.placeholder.offset().top;
|
||||
|
||||
//Set the helper position
|
||||
if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
|
||||
if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
|
||||
|
||||
//Rearrange
|
||||
for (var i = this.items.length - 1; i >= 0; i--) {
|
||||
|
||||
//Cache variables and intersection, continue if no intersection
|
||||
var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
|
||||
if (!intersection) continue;
|
||||
|
||||
if(itemElement != this.currentItem[0] //cannot intersect with itself
|
||||
&& this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
|
||||
&& !$.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
|
||||
&& (this.options.type == 'semi-dynamic' ? !$.contains(this.element[0], itemElement) : true)
|
||||
//&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
|
||||
) {
|
||||
|
||||
$(itemElement).mouseenter();
|
||||
|
||||
this.direction = intersection == 1 ? "down" : "up";
|
||||
|
||||
if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
|
||||
$(itemElement).mouseleave();
|
||||
this._rearrange(event, item);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
// Clear emtpy ul's/ol's
|
||||
this._clearEmpty(itemElement);
|
||||
|
||||
this._trigger("change", event, this._uiHash());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var parentItem = (this.placeholder[0].parentNode.parentNode &&
|
||||
$(this.placeholder[0].parentNode.parentNode).closest('.ui-sortable').length)
|
||||
? $(this.placeholder[0].parentNode.parentNode)
|
||||
: null,
|
||||
level = this._getLevel(this.placeholder),
|
||||
childLevels = this._getChildLevels(this.helper);
|
||||
|
||||
// To find the previous sibling in the list, keep backtracking until we hit a valid list item.
|
||||
var previousItem = this.placeholder[0].previousSibling ? $(this.placeholder[0].previousSibling) : null;
|
||||
if (previousItem != null) {
|
||||
while (previousItem[0].nodeName.toLowerCase() != 'li' || previousItem[0] == this.currentItem[0] || previousItem[0] == this.helper[0]) {
|
||||
if (previousItem[0].previousSibling) {
|
||||
previousItem = $(previousItem[0].previousSibling);
|
||||
} else {
|
||||
previousItem = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// To find the next sibling in the list, keep stepping forward until we hit a valid list item.
|
||||
var nextItem = this.placeholder[0].nextSibling ? $(this.placeholder[0].nextSibling) : null;
|
||||
if (nextItem != null) {
|
||||
while (nextItem[0].nodeName.toLowerCase() != 'li' || nextItem[0] == this.currentItem[0] || nextItem[0] == this.helper[0]) {
|
||||
if (nextItem[0].nextSibling) {
|
||||
nextItem = $(nextItem[0].nextSibling);
|
||||
} else {
|
||||
nextItem = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var newList = document.createElement(o.listType);
|
||||
|
||||
this.beyondMaxLevels = 0;
|
||||
|
||||
// If the item is moved to the left, send it to its parent's level unless there are siblings below it.
|
||||
if (parentItem != null && nextItem == null &&
|
||||
(o.rtl && (this.positionAbs.left + this.helper.outerWidth() > parentItem.offset().left + parentItem.outerWidth()) ||
|
||||
!o.rtl && (this.positionAbs.left < parentItem.offset().left))) {
|
||||
parentItem.after(this.placeholder[0]);
|
||||
this._clearEmpty(parentItem[0]);
|
||||
this._trigger("change", event, this._uiHash());
|
||||
}
|
||||
// If the item is below a sibling and is moved to the right, make it a child of that sibling.
|
||||
else if (previousItem != null &&
|
||||
(o.rtl && (this.positionAbs.left + this.helper.outerWidth() < previousItem.offset().left + previousItem.outerWidth() - o.tabSize) ||
|
||||
!o.rtl && (this.positionAbs.left > previousItem.offset().left + o.tabSize))) {
|
||||
this._isAllowed(previousItem, level, level+childLevels+1);
|
||||
if (!previousItem.children(o.listType).length) {
|
||||
previousItem[0].appendChild(newList);
|
||||
}
|
||||
// If this item is being moved from the top, add it to the top of the list.
|
||||
if (previousTopOffset && (previousTopOffset <= previousItem.offset().top)) {
|
||||
previousItem.children(o.listType).prepend(this.placeholder);
|
||||
}
|
||||
// Otherwise, add it to the bottom of the list.
|
||||
else {
|
||||
previousItem.children(o.listType)[0].appendChild(this.placeholder[0]);
|
||||
}
|
||||
this._trigger("change", event, this._uiHash());
|
||||
}
|
||||
else {
|
||||
this._isAllowed(parentItem, level, level+childLevels);
|
||||
}
|
||||
|
||||
//Post events to containers
|
||||
this._contactContainers(event);
|
||||
|
||||
//Interconnect with droppables
|
||||
if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
|
||||
|
||||
//Call callbacks
|
||||
this._trigger('sort', event, this._uiHash());
|
||||
|
||||
this.lastPositionAbs = this.positionAbs;
|
||||
return false;
|
||||
|
||||
},
|
||||
|
||||
_mouseStop: function(event, noPropagation) {
|
||||
|
||||
// If the item is in a position not allowed, send it back
|
||||
if (this.beyondMaxLevels) {
|
||||
|
||||
this.placeholder.removeClass(this.options.errorClass);
|
||||
|
||||
if (this.domPosition.prev) {
|
||||
$(this.domPosition.prev).after(this.placeholder);
|
||||
} else {
|
||||
$(this.domPosition.parent).prepend(this.placeholder);
|
||||
}
|
||||
|
||||
this._trigger("revert", event, this._uiHash());
|
||||
|
||||
}
|
||||
|
||||
// Clean last empty ul/ol
|
||||
for (var i = this.items.length - 1; i >= 0; i--) {
|
||||
var item = this.items[i].item[0];
|
||||
this._clearEmpty(item);
|
||||
}
|
||||
|
||||
$.ui.sortable.prototype._mouseStop.apply(this, arguments);
|
||||
|
||||
},
|
||||
|
||||
serialize: function(options) {
|
||||
|
||||
var o = $.extend({}, this.options, options),
|
||||
items = this._getItemsAsjQuery(o && o.connected),
|
||||
str = [];
|
||||
|
||||
$(items).each(function() {
|
||||
var res = ($(o.item || this).attr(o.attribute || 'id') || '')
|
||||
.match(o.expression || (/(.+)[-=_](.+)/)),
|
||||
pid = ($(o.item || this).parent(o.listType)
|
||||
.parent(o.items)
|
||||
.attr(o.attribute || 'id') || '')
|
||||
.match(o.expression || (/(.+)[-=_](.+)/));
|
||||
|
||||
if (res) {
|
||||
str.push(((o.key || res[1]) + '[' + (o.key && o.expression ? res[1] : res[2]) + ']')
|
||||
+ '='
|
||||
+ (pid ? (o.key && o.expression ? pid[1] : pid[2]) : o.rootID));
|
||||
}
|
||||
});
|
||||
|
||||
if(!str.length && o.key) {
|
||||
str.push(o.key + '=');
|
||||
}
|
||||
|
||||
return str.join('&');
|
||||
|
||||
},
|
||||
|
||||
toHierarchy: function(options) {
|
||||
|
||||
var o = $.extend({}, this.options, options),
|
||||
sDepth = o.startDepthCount || 0,
|
||||
ret = [];
|
||||
|
||||
$(this.element).children(o.items).each(function () {
|
||||
var level = _recursiveItems(this);
|
||||
ret.push(level);
|
||||
});
|
||||
|
||||
return ret;
|
||||
|
||||
function _recursiveItems(item) {
|
||||
var id = ($(item).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
|
||||
if (id) {
|
||||
var currentItem = {"id" : id[2]};
|
||||
if ($(item).children(o.listType).children(o.items).length > 0) {
|
||||
currentItem.children = [];
|
||||
$(item).children(o.listType).children(o.items).each(function() {
|
||||
var level = _recursiveItems(this);
|
||||
currentItem.children.push(level);
|
||||
});
|
||||
}
|
||||
return currentItem;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
toArray: function(options) {
|
||||
|
||||
var o = $.extend({}, this.options, options),
|
||||
sDepth = o.startDepthCount || 0,
|
||||
ret = [],
|
||||
left = 2;
|
||||
|
||||
ret.push({
|
||||
"item_id": o.rootID,
|
||||
"parent_id": 'none',
|
||||
"depth": sDepth,
|
||||
"left": '1',
|
||||
"right": ($(o.items, this.element).length + 1) * 2
|
||||
});
|
||||
|
||||
$(this.element).children(o.items).each(function () {
|
||||
left = _recursiveArray(this, sDepth + 1, left);
|
||||
});
|
||||
|
||||
ret = ret.sort(function(a,b){ return (a.left - b.left); });
|
||||
|
||||
return ret;
|
||||
|
||||
function _recursiveArray(item, depth, left) {
|
||||
|
||||
var right = left + 1,
|
||||
id,
|
||||
pid;
|
||||
|
||||
if ($(item).children(o.listType).children(o.items).length > 0) {
|
||||
depth ++;
|
||||
$(item).children(o.listType).children(o.items).each(function () {
|
||||
right = _recursiveArray($(this), depth, right);
|
||||
});
|
||||
depth --;
|
||||
}
|
||||
|
||||
id = ($(item).attr(o.attribute || 'id')).match(o.expression || (/(.+)[-=_](.+)/));
|
||||
|
||||
if (depth === sDepth + 1) {
|
||||
pid = o.rootID;
|
||||
} else {
|
||||
var parentItem = ($(item).parent(o.listType)
|
||||
.parent(o.items)
|
||||
.attr(o.attribute || 'id'))
|
||||
.match(o.expression || (/(.+)[-=_](.+)/));
|
||||
pid = parentItem[2];
|
||||
}
|
||||
|
||||
if (id) {
|
||||
ret.push({"item_id": id[2], "parent_id": pid, "depth": depth, "left": left, "right": right});
|
||||
}
|
||||
|
||||
left = right + 1;
|
||||
return left;
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
_clearEmpty: function(item) {
|
||||
|
||||
var emptyList = $(item).children(this.options.listType);
|
||||
if (emptyList.length && !emptyList.children().length && !this.options.doNotClear) {
|
||||
emptyList.remove();
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
_getLevel: function(item) {
|
||||
|
||||
var level = 1;
|
||||
|
||||
if (this.options.listType) {
|
||||
var list = item.closest(this.options.listType);
|
||||
while (list && list.length > 0 &&
|
||||
!list.is('.ui-sortable')) {
|
||||
level++;
|
||||
list = list.parent().closest(this.options.listType);
|
||||
}
|
||||
}
|
||||
|
||||
return level;
|
||||
},
|
||||
|
||||
_getChildLevels: function(parent, depth) {
|
||||
var self = this,
|
||||
o = this.options,
|
||||
result = 0;
|
||||
depth = depth || 0;
|
||||
|
||||
$(parent).children(o.listType).children(o.items).each(function (index, child) {
|
||||
result = Math.max(self._getChildLevels(child, depth + 1), result);
|
||||
});
|
||||
|
||||
return depth ? result + 1 : result;
|
||||
},
|
||||
|
||||
_isAllowed: function(parentItem, level, levels) {
|
||||
var o = this.options,
|
||||
isRoot = $(this.domPosition.parent).hasClass('ui-sortable') ? true : false,
|
||||
maxLevels = this.placeholder.closest('.ui-sortable').nestedSortable('option', 'maxLevels'); // this takes into account the maxLevels set to the recipient list
|
||||
|
||||
// Is the root protected?
|
||||
// Are we trying to nest under a no-nest?
|
||||
// Are we nesting too deep?
|
||||
if (!o.isAllowed(this.currentItem, parentItem) ||
|
||||
parentItem && parentItem.hasClass(o.disableNesting) ||
|
||||
o.protectRoot && (parentItem == null && !isRoot || isRoot && level > 1)) {
|
||||
this.placeholder.addClass(o.errorClass);
|
||||
if (maxLevels < levels && maxLevels != 0) {
|
||||
this.beyondMaxLevels = levels - maxLevels;
|
||||
} else {
|
||||
this.beyondMaxLevels = 1;
|
||||
}
|
||||
} else {
|
||||
if (maxLevels < levels && maxLevels != 0) {
|
||||
this.placeholder.addClass(o.errorClass);
|
||||
this.beyondMaxLevels = levels - maxLevels;
|
||||
} else {
|
||||
this.placeholder.removeClass(o.errorClass);
|
||||
this.beyondMaxLevels = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}));
|
||||
|
||||
$.mjs.nestedSortable.prototype.options = $.extend({}, $.ui.sortable.prototype.options, $.mjs.nestedSortable.prototype.options);
|
||||
})(jQuery);
|
||||
@@ -114,7 +114,7 @@ table.editorbar-panel td.selected {
|
||||
|
||||
.oe_translate_or {
|
||||
color: white;
|
||||
padding: 0 0.2em;
|
||||
padding: 0 0 0 1em;
|
||||
}
|
||||
|
||||
.oe_translate_examples li {
|
||||
@@ -142,6 +142,84 @@ table.editorbar-panel td.selected {
|
||||
background: #ffffb6;
|
||||
}
|
||||
|
||||
div.oe_menu_buttons {
|
||||
top: -8px;
|
||||
right: -8px;
|
||||
}
|
||||
|
||||
ul.oe_menu_editor > li:first-child > div > i:before {
|
||||
content: "\f015";
|
||||
}
|
||||
ul.oe_menu_editor, ul.oe_menu_editor ul {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
ul.oe_menu_editor ul {
|
||||
padding-left: 30px;
|
||||
}
|
||||
ul.oe_menu_editor button {
|
||||
margin-left: 4px;
|
||||
}
|
||||
ul.oe_menu_editor li {
|
||||
margin: 5px 0 0 0;
|
||||
padding: 0;
|
||||
}
|
||||
ul.oe_menu_editor .oe_menu_placeholder {
|
||||
outline: 1px dashed #4183c4;
|
||||
}
|
||||
ul.oe_menu_editor .mjs-nestedSortable-error {
|
||||
background: #fbe3e4;
|
||||
border-color: transparent;
|
||||
}
|
||||
ul.oe_menu_editor li div {
|
||||
border: 1px solid #d4d4d4;
|
||||
-webkit-border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
border-color: #d4d4d4 #d4d4d4 #bcbcbc;
|
||||
padding: 6px;
|
||||
margin: 0;
|
||||
cursor: move;
|
||||
background: #f6f6f6;
|
||||
background: -moz-linear-gradient(top, white 0%, #f6f6f6 47%, #ededed 100%);
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, white), color-stop(47%, #f6f6f6), color-stop(100%, #ededed));
|
||||
background: -webkit-linear-gradient(top, white 0%, #f6f6f6 47%, #ededed 100%);
|
||||
background: -o-linear-gradient(top, white 0%, #f6f6f6 47%, #ededed 100%);
|
||||
background: -ms-linear-gradient(top, white 0%, #f6f6f6 47%, #ededed 100%);
|
||||
background: linear-gradient(to bottom, #ffffff 0%, #f6f6f6 47%, #ededed 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#ededed',GradientType=0 );
|
||||
}
|
||||
ul.oe_menu_editor li.mjs-nestedSortable-branch div {
|
||||
background: -moz-linear-gradient(top, white 0%, #f6f6f6 47%, #f0ece9 100%);
|
||||
background: -webkit-linear-gradient(top, white 0%, #f6f6f6 47%, #f0ece9 100%);
|
||||
}
|
||||
ul.oe_menu_editor li.mjs-nestedSortable-leaf div {
|
||||
background: -moz-linear-gradient(top, white 0%, #f6f6f6 47%, #bcccbc 100%);
|
||||
background: -webkit-linear-gradient(top, white 0%, #f6f6f6 47%, #bcccbc 100%);
|
||||
}
|
||||
ul.oe_menu_editor li.mjs-nestedSortable-collapsed.mjs-nestedSortable-hovering div {
|
||||
border-color: #999999;
|
||||
background: #fafafa;
|
||||
}
|
||||
ul.oe_menu_editor .disclose {
|
||||
cursor: pointer;
|
||||
width: 10px;
|
||||
display: none;
|
||||
}
|
||||
ul.oe_menu_editor li.mjs-nestedSortable-collapsed > ul {
|
||||
display: none;
|
||||
}
|
||||
ul.oe_menu_editor li.mjs-nestedSortable-branch > div > .disclose {
|
||||
display: inline-block;
|
||||
}
|
||||
ul.oe_menu_editor li.mjs-nestedSortable-collapsed > div > .disclose > span:before {
|
||||
content: "+ ";
|
||||
}
|
||||
ul.oe_menu_editor li.mjs-nestedSortable-expanded > div > .disclose > span:before {
|
||||
content: "- ";
|
||||
}
|
||||
|
||||
/* ---- RTE ---- */
|
||||
.oe_editable .btn {
|
||||
-webkit-user-select: auto;
|
||||
|
||||
@@ -108,7 +108,7 @@ table.editorbar-panel
|
||||
// ---- TRANSLATIONS ---- {{{
|
||||
.oe_translate_or
|
||||
color: white
|
||||
padding: 0 0.2em
|
||||
padding: 0 0 0 1em
|
||||
.oe_translate_examples li
|
||||
margin: 10px
|
||||
padding: 4px
|
||||
@@ -124,6 +124,84 @@ table.editorbar-panel
|
||||
background: rgb(255, 255, 182)
|
||||
// }}}
|
||||
|
||||
// -------- MENU -------- {{{
|
||||
div.oe_menu_buttons
|
||||
top: -8px
|
||||
right: -8px
|
||||
ul.oe_menu_editor
|
||||
> li:first-child > div > i:before
|
||||
content: "\f015"
|
||||
&, & ul
|
||||
list-style-type: none
|
||||
margin: 0
|
||||
padding: 0
|
||||
& ul
|
||||
padding-left: 30px
|
||||
|
||||
button
|
||||
margin-left: 4px
|
||||
|
||||
li
|
||||
margin: 5px 0 0 0
|
||||
padding: 0
|
||||
|
||||
.oe_menu_placeholder
|
||||
outline: 1px dashed #4183C4
|
||||
|
||||
.mjs-nestedSortable-error
|
||||
background: #fbe3e4
|
||||
border-color: transparent
|
||||
|
||||
|
||||
// TODO: use compass mixins
|
||||
li div
|
||||
border: 1px solid #d4d4d4
|
||||
-webkit-border-radius: 3px
|
||||
-moz-border-radius: 3px
|
||||
border-radius: 3px
|
||||
border-color: #D4D4D4 #D4D4D4 #BCBCBC
|
||||
padding: 6px
|
||||
margin: 0
|
||||
cursor: move
|
||||
background: #f6f6f6
|
||||
background: -moz-linear-gradient(top, #ffffff 0%, #f6f6f6 47%, #ededed 100%)
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ffffff), color-stop(47%,#f6f6f6), color-stop(100%,#ededed))
|
||||
background: -webkit-linear-gradient(top, #ffffff 0%,#f6f6f6 47%,#ededed 100%)
|
||||
background: -o-linear-gradient(top, #ffffff 0%,#f6f6f6 47%,#ededed 100%)
|
||||
background: -ms-linear-gradient(top, #ffffff 0%,#f6f6f6 47%,#ededed 100%)
|
||||
background: linear-gradient(to bottom, #ffffff 0%,#f6f6f6 47%,#ededed 100%)
|
||||
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#ededed',GradientType=0 )
|
||||
|
||||
li.mjs-nestedSortable-branch div
|
||||
background: -moz-linear-gradient(top, #ffffff 0%, #f6f6f6 47%, #f0ece9 100%)
|
||||
background: -webkit-linear-gradient(top, #ffffff 0%,#f6f6f6 47%,#f0ece9 100%)
|
||||
|
||||
li.mjs-nestedSortable-leaf div
|
||||
background: -moz-linear-gradient(top, #ffffff 0%, #f6f6f6 47%, #bcccbc 100%)
|
||||
background: -webkit-linear-gradient(top, #ffffff 0%,#f6f6f6 47%,#bcccbc 100%)
|
||||
|
||||
li.mjs-nestedSortable-collapsed.mjs-nestedSortable-hovering div
|
||||
border-color: #999
|
||||
background: #fafafa
|
||||
|
||||
.disclose
|
||||
cursor: pointer
|
||||
width: 10px
|
||||
display: none
|
||||
|
||||
li.mjs-nestedSortable-collapsed > ul
|
||||
display: none
|
||||
|
||||
li.mjs-nestedSortable-branch > div > .disclose
|
||||
display: inline-block
|
||||
|
||||
li.mjs-nestedSortable-collapsed > div > .disclose > span:before
|
||||
content: '+ '
|
||||
|
||||
li.mjs-nestedSortable-expanded > div > .disclose > span:before
|
||||
content: '- '
|
||||
// }}}
|
||||
|
||||
/* ---- RTE ---- */
|
||||
|
||||
// bootstrap makes .btn elements unselectable -> RTE double-click can't know
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
@@ -6,7 +6,7 @@
|
||||
var hash = "#advanced-view-editor";
|
||||
|
||||
var website = openerp.website;
|
||||
website.templates.push('/website/static/src/xml/website.ace.xml');
|
||||
website.add_template_file('/website/static/src/xml/website.ace.xml');
|
||||
|
||||
website.ready().then(function () {
|
||||
if (window.location.hash.indexOf(hash) >= 0) {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
var website = openerp.website;
|
||||
// $.fn.data automatically parses value, '0'|'1' -> 0|1
|
||||
|
||||
website.templates.push('/website/static/src/xml/website.editor.xml');
|
||||
website.add_template_file('/website/static/src/xml/website.editor.xml');
|
||||
website.dom_ready.done(function () {
|
||||
var is_smartphone = $(document.body)[0].clientWidth < 767;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
});
|
||||
|
||||
function link_dialog(editor) {
|
||||
return new website.editor.LinkDialog(editor).appendTo(document.body);
|
||||
return new website.editor.RTELinkDialog(editor).appendTo(document.body);
|
||||
}
|
||||
function image_dialog(editor) {
|
||||
return new website.editor.RTEImageDialog(editor).appendTo(document.body);
|
||||
@@ -805,6 +805,106 @@
|
||||
this.pages = Object.create(null);
|
||||
this.text = null;
|
||||
},
|
||||
start: function () {
|
||||
var self = this;
|
||||
return $.when(
|
||||
this.fetch_pages().done(this.proxy('fill_pages')),
|
||||
this._super()
|
||||
).done(function () {
|
||||
self.bind_data();
|
||||
});
|
||||
},
|
||||
save: function () {
|
||||
var self = this, _super = this._super.bind(this);
|
||||
var $e = this.$('.list-group-item.active .url-source');
|
||||
var val = $e.val();
|
||||
if (!val || !$e[0].checkValidity()) {
|
||||
// FIXME: error message
|
||||
$e.closest('.form-group').addClass('has-error');
|
||||
$e.focus();
|
||||
return;
|
||||
}
|
||||
|
||||
var done = $.when();
|
||||
if ($e.hasClass('email-address')) {
|
||||
this.make_link('mailto:' + val, false, val);
|
||||
} else if ($e.hasClass('existing')) {
|
||||
self.make_link(val, false, this.pages[val]);
|
||||
} else if ($e.hasClass('pages')) {
|
||||
// Create the page, get the URL back
|
||||
done = $.get(_.str.sprintf(
|
||||
'/pagenew/%s?noredirect', encodeURI(val)))
|
||||
.then(function (response) {
|
||||
self.make_link(response, false, val);
|
||||
});
|
||||
} else {
|
||||
this.make_link(val, this.$('input.window-new').prop('checked'));
|
||||
}
|
||||
done.then(_super);
|
||||
},
|
||||
make_link: function (url, new_window, label) {
|
||||
},
|
||||
bind_data: function (text, href, new_window) {
|
||||
href = href || this.element && (this.element.data( 'cke-saved-href')
|
||||
|| this.element.getAttribute('href'));
|
||||
if (!href) { return; }
|
||||
|
||||
if (new_window === undefined) {
|
||||
new_window = this.element.getAttribute('target') === '_blank';
|
||||
}
|
||||
if (text === undefined) {
|
||||
text = this.element.getText();
|
||||
}
|
||||
|
||||
var match, $control;
|
||||
if ((match = /mailto:(.+)/.exec(href))) {
|
||||
$control = this.$('input.email-address').val(match[1]);
|
||||
} else if (href in this.pages) {
|
||||
$control = this.$('select.existing').val(href);
|
||||
} else if ((match = /\/page\/(.+)/.exec(href))) {
|
||||
var actual_href = '/page/website.' + match[1];
|
||||
if (actual_href in this.pages) {
|
||||
$control = this.$('select.existing').val(actual_href);
|
||||
}
|
||||
}
|
||||
if (!$control) {
|
||||
$control = this.$('input.url').val(href);
|
||||
}
|
||||
|
||||
this.changed($control);
|
||||
|
||||
this.$('input#link-text').val(text);
|
||||
this.$('input.window-new').prop('checked', new_window);
|
||||
},
|
||||
changed: function ($e) {
|
||||
this.$('.url-source').not($e).val('');
|
||||
$e.closest('.list-group-item')
|
||||
.addClass('active')
|
||||
.siblings().removeClass('active')
|
||||
.addBack().removeClass('has-error');
|
||||
},
|
||||
fetch_pages: function () {
|
||||
return openerp.jsonRpc('/web/dataset/call_kw', 'call', {
|
||||
model: 'website',
|
||||
method: 'list_pages',
|
||||
args: [null],
|
||||
kwargs: {
|
||||
context: website.get_context()
|
||||
},
|
||||
});
|
||||
},
|
||||
fill_pages: function (results) {
|
||||
var self = this;
|
||||
var pages = this.$('select.existing')[0];
|
||||
_(results).each(function (result) {
|
||||
self.pages[result.url] = result.name;
|
||||
|
||||
pages.options[pages.options.length] =
|
||||
new Option(result.name, result.url);
|
||||
});
|
||||
},
|
||||
});
|
||||
website.editor.RTELinkDialog = website.editor.LinkDialog.extend({
|
||||
start: function () {
|
||||
var element;
|
||||
if ((element = this.get_selected_link()) && element.hasAttribute('href')) {
|
||||
@@ -815,10 +915,7 @@
|
||||
this.add_removal_button();
|
||||
}
|
||||
|
||||
return $.when(
|
||||
this.fetch_pages().done(this.proxy('fill_pages')),
|
||||
this._super()
|
||||
).done(this.proxy('bind_data'));
|
||||
return this._super();
|
||||
},
|
||||
add_removal_button: function () {
|
||||
this.$('.modal-footer').prepend(
|
||||
@@ -884,66 +981,6 @@
|
||||
}, 0);
|
||||
}
|
||||
},
|
||||
save: function () {
|
||||
var self = this, _super = this._super.bind(this);
|
||||
var $e = this.$('.list-group-item.active .url-source');
|
||||
var val = $e.val();
|
||||
if (!val || !$e[0].checkValidity()) {
|
||||
// FIXME: error message
|
||||
$e.closest('.form-group').addClass('has-error');
|
||||
return;
|
||||
}
|
||||
|
||||
var done = $.when();
|
||||
if ($e.hasClass('email-address')) {
|
||||
this.make_link('mailto:' + val, false, val);
|
||||
} else if ($e.hasClass('existing')) {
|
||||
self.make_link(val, false, this.pages[val]);
|
||||
} else if ($e.hasClass('pages')) {
|
||||
// Create the page, get the URL back
|
||||
done = $.get(_.str.sprintf(
|
||||
'/pagenew/%s?noredirect', encodeURI(val)))
|
||||
.then(function (response) {
|
||||
self.make_link(response, false, val);
|
||||
});
|
||||
} else {
|
||||
this.make_link(val, this.$('input.window-new').prop('checked'));
|
||||
}
|
||||
done.then(_super);
|
||||
},
|
||||
bind_data: function () {
|
||||
var href = this.element && (this.element.data( 'cke-saved-href')
|
||||
|| this.element.getAttribute('href'));
|
||||
if (!href) { return; }
|
||||
|
||||
var match, $control;
|
||||
if (match = /mailto:(.+)/.exec(href)) {
|
||||
$control = this.$('input.email-address').val(match[1]);
|
||||
} else if (href in this.pages) {
|
||||
$control = this.$('select.existing').val(href);
|
||||
} else if (match = /\/page\/(.+)/.exec(href)) {
|
||||
var actual_href = '/page/website.' + match[1];
|
||||
if (actual_href in this.pages) {
|
||||
$control = this.$('select.existing').val(actual_href);
|
||||
}
|
||||
}
|
||||
if (!$control) {
|
||||
$control = this.$('input.url').val(href);
|
||||
}
|
||||
|
||||
this.changed($control);
|
||||
|
||||
this.$('input#link-text').val(this.element.getText());
|
||||
this.$('input.window-new').prop(
|
||||
'checked', this.element.getAttribute('target') === '_blank');
|
||||
},
|
||||
changed: function ($e) {
|
||||
this.$('.url-source').not($e).val('');
|
||||
$e.closest('.list-group-item')
|
||||
.addClass('active')
|
||||
.siblings().removeClass('active')
|
||||
.addBack().removeClass('has-error');
|
||||
},
|
||||
/**
|
||||
* CKEDITOR.plugins.link.getSelectedLink ignores the editor's root,
|
||||
* if the editor is set directly on a link it will thus not work.
|
||||
@@ -951,27 +988,8 @@
|
||||
get_selected_link: function () {
|
||||
return get_selected_link(this.editor);
|
||||
},
|
||||
fetch_pages: function () {
|
||||
return openerp.jsonRpc('/web/dataset/call_kw', 'call', {
|
||||
model: 'website',
|
||||
method: 'list_pages',
|
||||
args: [null],
|
||||
kwargs: {
|
||||
context: website.get_context()
|
||||
},
|
||||
});
|
||||
},
|
||||
fill_pages: function (results) {
|
||||
var self = this;
|
||||
var pages = this.$('select.existing')[0];
|
||||
_(results).each(function (result) {
|
||||
self.pages[result.url] = result.name;
|
||||
|
||||
pages.options[pages.options.length] =
|
||||
new Option(result.name, result.url);
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* ImageDialog widget. Lets users change an image, including uploading a
|
||||
* new image in OpenERP or selecting the image style (if supported by
|
||||
|
||||
@@ -5,35 +5,30 @@
|
||||
// The following line can be removed in 2017
|
||||
openerp.website = website;
|
||||
|
||||
var templates = website.templates = [
|
||||
'/website/static/src/xml/website.xml'
|
||||
];
|
||||
|
||||
website.get_context = function (dict) {
|
||||
var html = document.documentElement;
|
||||
return _.extend({
|
||||
lang: html.getAttribute('lang').replace('-', '_')
|
||||
lang: html.getAttribute('lang').replace('-', '_'),
|
||||
website_id: html.getAttribute('data-website-id')|0
|
||||
}, dict);
|
||||
};
|
||||
|
||||
/* ----- TEMPLATE LOADING ---- */
|
||||
website.add_template = function(template) {
|
||||
templates.push(template);
|
||||
};
|
||||
website.load_templates = function(templates) {
|
||||
var dones = _(templates).map(function (t) {
|
||||
return new $.Deferred(function (d) {
|
||||
openerp.qweb.add_template(t, function(err) {
|
||||
if (err) {
|
||||
d.reject(err);
|
||||
} else {
|
||||
d.resolve();
|
||||
}
|
||||
});
|
||||
var templates_def = $.Deferred().resolve();
|
||||
website.add_template_file = function(template) {
|
||||
templates_def = templates_def.then(function() {
|
||||
var def = $.Deferred();
|
||||
openerp.qweb.add_template(template, function(err) {
|
||||
if (err) {
|
||||
def.reject(err);
|
||||
} else {
|
||||
def.resolve();
|
||||
}
|
||||
});
|
||||
return def;
|
||||
});
|
||||
return $.when.apply(null, dones);
|
||||
};
|
||||
website.add_template_file('/website/static/src/xml/website.xml');
|
||||
website.reload = function () {
|
||||
location.hash = "scrollTop=" + window.document.body.scrollTop;
|
||||
if (location.search.indexOf("enable_editor") > -1) {
|
||||
@@ -110,20 +105,33 @@
|
||||
*/
|
||||
website.ready = function() {
|
||||
if (!all_ready) {
|
||||
var tpl = website.load_templates(templates);
|
||||
all_ready = dom_ready.then(function () {
|
||||
all_ready = $.when(dom_ready, templates_def).then(function () {
|
||||
if ($('html').data('editable')) {
|
||||
website.id = $('html').data('website-id');
|
||||
website.session = new openerp.Session();
|
||||
var modules = ['website'];
|
||||
return openerp._t.database.load_translations(website.session, modules, website.get_context().lang);
|
||||
}
|
||||
}).then(tpl).promise();
|
||||
}).promise();
|
||||
}
|
||||
return all_ready;
|
||||
};
|
||||
|
||||
website.error = function(data, url) {
|
||||
var $error = $(openerp.qweb.render('website.error_dialog', {
|
||||
'title': data.data ? data.data.arguments[0] : data.statusText,
|
||||
'message': data.data ? data.data.arguments[1] : "",
|
||||
'backend_url': url
|
||||
}));
|
||||
$error.appendTo("body");
|
||||
$error.modal('show');
|
||||
};
|
||||
|
||||
dom_ready.then(function () {
|
||||
|
||||
/* ----- BOOTSTRAP STUFF ---- */
|
||||
$('.js_tooltip').bstooltip();
|
||||
|
||||
/* ----- PUBLISHING STUFF ---- */
|
||||
$('[data-publish]:has(.js_publish)').each(function () {
|
||||
var $pub = $("[data-publish]", this);
|
||||
@@ -140,11 +148,13 @@
|
||||
|
||||
$(document).on('click', '.js_publish', function (e) {
|
||||
e.preventDefault();
|
||||
var $data = $(":first", this).parents("[data-publish]");
|
||||
$data.attr("data-publish", $data.first().attr("data-publish") == 'off' ? 'on' : 'off');
|
||||
openerp.jsonRpc('/website/publish', 'call', {'id': $(this).data('id'), 'object': $(this).data('object')})
|
||||
var $a = $(this);
|
||||
var $data = $a.find(":first").parents("[data-publish]");
|
||||
openerp.jsonRpc($a.data('controller') || '/website/publish', 'call', {'id': +$a.data('id'), 'object': $a.data('object')})
|
||||
.then(function (result) {
|
||||
$data.attr("data-publish", +result ? 'on' : 'off');
|
||||
}).fail(function (err, data) {
|
||||
website.error(data, '/web#model='+$a.data('object')+'&id='+$a.data('id'));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -156,11 +166,13 @@
|
||||
$data.toggleClass("css_unpublish css_publish");
|
||||
$btn.removeClass("btn-default btn-success");
|
||||
|
||||
openerp.jsonRpc('/website/publish', 'call', {'id': +$data.data('id'), 'object': $data.data('object')})
|
||||
openerp.jsonRpc($data.data('controller') || '/website/publish', 'call', {'id': +$data.data('id'), 'object': $data.data('object')})
|
||||
.then(function (result) {
|
||||
$btn.toggleClass("btn-default", !result).toggleClass("btn-success", result);
|
||||
$data.toggleClass("css_unpublish", !result).toggleClass("css_publish", result);
|
||||
$data.parents("[data-publish]").attr("data-publish", +result ? 'on' : 'off');
|
||||
}).fail(function (err, data) {
|
||||
website.error(data, '/web#model='+$data.data('object')+'&id='+$data.data('id'));
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var website = openerp.website;
|
||||
website.menu = {};
|
||||
website.add_template_file('/website/static/src/xml/website.menu.xml');
|
||||
|
||||
website.EditorBar.include({
|
||||
events: _.extend({}, website.EditorBar.prototype.events, {
|
||||
'click a[data-action="edit-structure"]': 'editStructure',
|
||||
}),
|
||||
editStructure: function () {
|
||||
var context = website.get_context();
|
||||
openerp.jsonRpc('/web/dataset/call_kw', 'call', {
|
||||
model: 'website.menu',
|
||||
method: 'get_tree',
|
||||
args: [[context.website_id]],
|
||||
kwargs: {
|
||||
context: context
|
||||
},
|
||||
}).then(function (menu) {
|
||||
return new website.menu.EditMenuDialog(menu).appendTo(document.body);
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
website.menu.EditMenuDialog = website.editor.Dialog.extend({
|
||||
template: 'website.menu.dialog.edit',
|
||||
events: _.extend({}, website.editor.Dialog.prototype.events, {
|
||||
'click button.js_add_menu': 'add_menu',
|
||||
'click button.js_edit_menu': 'edit_menu',
|
||||
'click button.js_delete_menu': 'delete_menu',
|
||||
}),
|
||||
init: function (menu) {
|
||||
this.menu = menu;
|
||||
this.root_menu_id = menu.id;
|
||||
this.flat = this.flatenize(menu);
|
||||
this.to_delete = [];
|
||||
this._super();
|
||||
},
|
||||
start: function () {
|
||||
var r = this._super.apply(this, arguments);
|
||||
var button = openerp.qweb.render('website.menu.dialog.footer-button');
|
||||
this.$('.modal-footer').prepend(button);
|
||||
this.$('.oe_menu_editor').nestedSortable({
|
||||
listType: 'ul',
|
||||
handle: 'div',
|
||||
items: 'li',
|
||||
maxLevels: 2,
|
||||
toleranceElement: '> div',
|
||||
forcePlaceholderSize: true,
|
||||
opacity: 0.6,
|
||||
placeholder: 'oe_menu_placeholder',
|
||||
tolerance: 'pointer',
|
||||
attribute: 'data-menu-id',
|
||||
expression: '()(.+)', // nestedSortable takes the second match of an expression (*sigh*)
|
||||
});
|
||||
return r;
|
||||
},
|
||||
flatenize: function (node, dict) {
|
||||
dict = dict || {};
|
||||
var self = this;
|
||||
dict[node.id] = node;
|
||||
node.children.forEach(function (child) {
|
||||
self.flatenize(child, dict);
|
||||
});
|
||||
return dict;
|
||||
},
|
||||
add_menu: function () {
|
||||
var self = this;
|
||||
var dialog = new website.menu.MenuEntryDialog();
|
||||
dialog.on('add-menu', this, function (link) {
|
||||
var new_menu = {
|
||||
id: _.uniqueId('new-'),
|
||||
name: link[2] || link[0],
|
||||
url: link[0],
|
||||
new_window: link[1],
|
||||
parent_id: false,
|
||||
sequence: 0,
|
||||
children: [],
|
||||
};
|
||||
self.flat[new_menu.id] = new_menu;
|
||||
self.$('.oe_menu_editor').append(
|
||||
openerp.qweb.render(
|
||||
'website.menu.dialog.submenu', { submenu: new_menu }));
|
||||
});
|
||||
dialog.appendTo(document.body);
|
||||
},
|
||||
edit_menu: function (ev) {
|
||||
var self = this;
|
||||
var menu_id = $(ev.currentTarget).closest('[data-menu-id]').data('menu-id');
|
||||
var menu = self.flat[menu_id];
|
||||
if (menu) {
|
||||
var dialog = new website.menu.MenuEntryDialog(undefined, menu);
|
||||
dialog.on('update-menu', this, function (link) {
|
||||
var id = link.shift();
|
||||
var menu_obj = self.flat[id];
|
||||
_.extend(menu_obj, {
|
||||
name: link[2],
|
||||
url: link[0],
|
||||
new_window: link[1],
|
||||
});
|
||||
var $menu = self.$('[data-menu-id="' + id + '"]');
|
||||
$menu.find('> div > span').text(menu_obj.name);
|
||||
});
|
||||
dialog.appendTo(document.body);
|
||||
} else {
|
||||
alert("Could not find menu entry");
|
||||
}
|
||||
},
|
||||
delete_menu: function (ev) {
|
||||
var self = this;
|
||||
var $menu = $(ev.currentTarget).closest('[data-menu-id]');
|
||||
var mid = $menu.data('menu-id')|0;
|
||||
if (mid) {
|
||||
this.to_delete.push(mid);
|
||||
}
|
||||
$menu.remove();
|
||||
},
|
||||
save: function () {
|
||||
var self = this;
|
||||
var new_menu = this.$('.oe_menu_editor').nestedSortable('toArray', {startDepthCount: 0});
|
||||
var levels = [];
|
||||
var data = [];
|
||||
var context = website.get_context();
|
||||
// Resquence, re-tree and remove useless data
|
||||
new_menu.forEach(function (menu) {
|
||||
if (menu.item_id) {
|
||||
levels[menu.depth] = (levels[menu.depth] || 0) + 1;
|
||||
var mobj = self.flat[menu.item_id];
|
||||
mobj.sequence = levels[menu.depth];
|
||||
mobj.parent_id = (menu.parent_id|0) || menu.parent_id || self.root_menu_id;
|
||||
delete(mobj.children);
|
||||
delete(mobj.level);
|
||||
data.push(mobj);
|
||||
}
|
||||
});
|
||||
openerp.jsonRpc('/web/dataset/call_kw', 'call', {
|
||||
model: 'website.menu',
|
||||
method: 'save',
|
||||
args: [[context.website_id], { data: data, to_delete: self.to_delete }],
|
||||
kwargs: {
|
||||
context: context
|
||||
},
|
||||
}).then(function (menu) {
|
||||
self.close();
|
||||
website.reload();
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
website.menu.MenuEntryDialog = website.editor.LinkDialog.extend({
|
||||
template: 'website.menu.dialog.add',
|
||||
init: function (editor, data) {
|
||||
this.data = data;
|
||||
this.update_mode = !!this.data;
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
start: function () {
|
||||
var self = this;
|
||||
return $.when(this._super.apply(this, arguments)).then(function () {
|
||||
if (self.data) {
|
||||
self.bind_data(self.data.name, self.data.url, self.data.new_window);
|
||||
}
|
||||
var $link_text = self.$('#link-text').focus();
|
||||
self.$('#link-existing').change(function () {
|
||||
if (!$link_text.val()) {
|
||||
$link_text.val($(this).find('option:selected').text());
|
||||
$link_text.focus();
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
save: function () {
|
||||
var $e = this.$('#link-text');
|
||||
if (!$e.val() || !$e[0].checkValidity()) {
|
||||
$e.closest('.form-group').addClass('has-error');
|
||||
$e.focus();
|
||||
return;
|
||||
}
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
make_link: function (url, new_window, label) {
|
||||
var menu_label = this.$('input#link-text').val() || label;
|
||||
if (this.data) {
|
||||
this.trigger('update-menu', [this.data.id, url, new_window, menu_label]);
|
||||
} else {
|
||||
this.trigger('add-menu', [url, new_window, menu_label]);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
})();
|
||||
@@ -2,7 +2,7 @@
|
||||
'use strict';
|
||||
|
||||
var website = openerp.website;
|
||||
website.templates.push('/website/static/src/xml/website.seo.xml');
|
||||
website.add_template_file('/website/static/src/xml/website.seo.xml');
|
||||
|
||||
website.EditorBar.include({
|
||||
events: _.extend({}, website.EditorBar.prototype.events, {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
'use strict';
|
||||
|
||||
var website = openerp.website;
|
||||
website.templates.push('/website/static/src/xml/website.snippets.xml');
|
||||
website.add_template_file('/website/static/src/xml/website.snippets.xml');
|
||||
|
||||
website.EditorBar.include({
|
||||
start: function () {
|
||||
@@ -589,7 +589,8 @@
|
||||
* Displayed into the overlay options on focus
|
||||
*/
|
||||
_readXMLData: function() {
|
||||
this.$el = this.parent.$snippets.siblings("[data-snippet-id='"+this.snippet_id+"']").clone();
|
||||
var self = this;
|
||||
this.$el = this.parent.$snippets.filter(function () { return $(this).data("snippet-id") == self.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"));
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
'use strict';
|
||||
|
||||
var website = openerp.website;
|
||||
website.templates.push('/website/static/src/xml/website.tour.xml');
|
||||
website.add_template_file('/website/static/src/xml/website.tour.xml');
|
||||
|
||||
website.tour = {
|
||||
render: function render (template, dict) {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
'use strict';
|
||||
|
||||
var website = openerp.website;
|
||||
website.templates.push('/website/static/src/xml/website.translator.xml');
|
||||
website.add_template_file('/website/static/src/xml/website.translator.xml');
|
||||
var nodialog = 'website_translator_nodialog';
|
||||
|
||||
website.EditorBar.include({
|
||||
@@ -17,6 +17,7 @@
|
||||
.text("Translate")
|
||||
.after(openerp.qweb.render('website.TranslatorAdditionalButtons'));
|
||||
self.$('[data-action=snippet]').hide();
|
||||
self.$('[data-action=edit-structure]').hide();
|
||||
self.$('#customize-menu-button').hide();
|
||||
});
|
||||
},
|
||||
|
||||
@@ -39,22 +39,22 @@
|
||||
<form>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item form-group active">
|
||||
<h3 class="list-group-item-heading">
|
||||
<h4 class="list-group-item-heading">
|
||||
<label for="link-existing" class="control-label">
|
||||
Existing page
|
||||
</label>
|
||||
</h3>
|
||||
</h4>
|
||||
<select class="existing form-control url-source"
|
||||
id="link-existing">
|
||||
<option/>
|
||||
</select>
|
||||
</li>
|
||||
<li class="list-group-item form-group">
|
||||
<h3 class="list-group-item-heading">
|
||||
<h4 class="list-group-item-heading">
|
||||
<label for="link-new" class="control-label">
|
||||
New page
|
||||
</label>
|
||||
</h3>
|
||||
</h4>
|
||||
<input type="text" class="form-control pages url-source"
|
||||
id="link-new" placeholder="Page Name"/>
|
||||
</li>
|
||||
@@ -65,20 +65,20 @@
|
||||
Open in new window
|
||||
</label>
|
||||
</div>
|
||||
<h3 class="list-group-item-heading">
|
||||
<h4 class="list-group-item-heading">
|
||||
<label for="link-external" class="control-label">
|
||||
External Website
|
||||
URL
|
||||
</label>
|
||||
</h3>
|
||||
</h4>
|
||||
<input type="text" class="form-control url url-source"
|
||||
id="link-external" placeholder="http://openerp.com"/>
|
||||
</li>
|
||||
<li class="list-group-item form-group">
|
||||
<h3 class="list-group-item-heading">
|
||||
<h4 class="list-group-item-heading">
|
||||
<label for="link-email" class="control-label">
|
||||
Email Address
|
||||
</label>
|
||||
</h3>
|
||||
</h4>
|
||||
<input type="email" class="form-control email-address url-source"
|
||||
id="link-email" placeholder="you@yourwebsite.com"/>
|
||||
</li>
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
<t t-name="website.menu.dialog.submenu">
|
||||
<li t-att-data-menu-id="submenu.id">
|
||||
<div>
|
||||
<i class="icon-reorder"/>
|
||||
<span><t t-esc="submenu.name"/></span>
|
||||
<div class="btn-group btn-group-xs pull-right oe_menu_buttons">
|
||||
<button type="button" class="btn js_edit_menu">
|
||||
<i class="icon-edit"/>
|
||||
</button>
|
||||
<button type="button" class="btn js_delete_menu">
|
||||
<i class="icon-trash"/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<t t-set="children" t-value="submenu.children"/>
|
||||
<ul t-if="children">
|
||||
<t t-foreach="children" t-as="submenu">
|
||||
<t t-call="website.menu.dialog.submenu"/>
|
||||
</t>
|
||||
</ul>
|
||||
</li>
|
||||
</t>
|
||||
<t t-name="website.menu.dialog.footer-button">
|
||||
<button type="button" class="btn pull-left js_add_menu btn-success">
|
||||
<i class="icon-plus-sign"/> Add Menu Entry
|
||||
</button>
|
||||
</t>
|
||||
<t t-name="website.menu.dialog.edit">
|
||||
<t t-call="website.editor.dialog">
|
||||
<t t-set="title">Edit Structure</t>
|
||||
<ul class="oe_menu_editor">
|
||||
<t t-foreach="widget.menu.children" t-as="submenu">
|
||||
<t t-call="website.menu.dialog.submenu"/>
|
||||
</t>
|
||||
</ul>
|
||||
</t>
|
||||
</t>
|
||||
<t t-name="website.menu.dialog.add" t-extend="website.editor.dialog.link">
|
||||
<t t-jquery="t[t-set='title']" t-operation="inner">
|
||||
<t t-if="!widget.update_mode">Add Menu Entry</t>
|
||||
<t t-if="widget.update_mode">Edit Menu Entry</t>
|
||||
</t>
|
||||
<t t-jquery="form > div.form-horizontal" t-operation="replace"/>
|
||||
<t t-jquery="ul.list-group" t-operation="before">
|
||||
<div class="list-group">
|
||||
<div class="form-group list-group-item active">
|
||||
<h3 class="list-group-item-heading">
|
||||
<label for="link-new" class="control-label">
|
||||
Menu Label
|
||||
</label>
|
||||
</h3>
|
||||
<input type="text" class="form-control"
|
||||
id="link-text" required="required"/>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</templates>
|
||||
@@ -32,7 +32,7 @@
|
||||
<!-- filled in JS -->
|
||||
</section>
|
||||
<section>
|
||||
<h3 class="page-header">2. Reference Your Page <small>using above suggestions</small></h3>
|
||||
<h3 class="page-header">2. Reference Your Page <small>using above suggested keywords</small></h3>
|
||||
<div class="form-horizontal mt16" role="form">
|
||||
<div class="form-group">
|
||||
<label for="seo_page_title" class="col-lg-2 control-label">Title</label>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<templates id="template" xml:space="preserve">
|
||||
<t t-name="website.TranslatorAdditionalButtons">
|
||||
<strong class="oe_translate_or">or</strong>
|
||||
<a class="btn btn-default" data-action="edit_master" href="#">Edit Master</a>
|
||||
<span class="oe_translate_or">or</span>
|
||||
<a class="btn btn-link" data-action="edit_master" href="#">Edit Master</a>
|
||||
</t>
|
||||
<t t-name="website.TranslatorDialog">
|
||||
<div class="modal fade oe_website_translator" tabindex="-1" role="dialog">
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li><a data-action="show-mobile-preview" href="#"><span title="Mobile preview" class="icon-mobile-phone"/></a></li>
|
||||
<li class="divider-vertical"></li>
|
||||
<li><a data-action="edit-structure" href="#"><span title="Edit website structure">Structure</span></a></li>
|
||||
<li><a data-action="promote-current-page" href="#"><span title="Promote page on the web">Promote</span></a></li>
|
||||
<li class="dropdown">
|
||||
<a id="customize-menu-button" class="dropdown-toggle" data-toggle="dropdown" href="#">Customize <span class="caret"></span></a>
|
||||
@@ -61,4 +62,27 @@
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="website.error_dialog">
|
||||
<div class="modal fade" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button title="Close" type="button" class="close" data-dismiss="modal">×</button>
|
||||
<div class="h2"><t t-esc="title"/></div>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<section>
|
||||
<t t-esc="message"/>
|
||||
</section>
|
||||
<section class="mt32">
|
||||
You have encountered an error. You can edit in the <a t-att-href="backend_url">backend</a> this data.
|
||||
</section>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" data-dismiss="modal" href="#" class="close btn btn-default">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
|
||||
@@ -323,6 +323,7 @@
|
||||
|
||||
<div data-snippet-id="well" data-selector-siblings="p, h1, h2, h3, blockquote">
|
||||
<div class="oe_snippet_thumbnail">
|
||||
<img class="oe_snippet_thumbnail_img" src="/website/static/src/img/blocks/block_well.png"/>
|
||||
<span class="oe_snippet_thumbnail_title">Well</span>
|
||||
</div>
|
||||
<div class="oe_snippet_body well">
|
||||
@@ -716,7 +717,7 @@
|
||||
|
||||
<div data-snippet-id="parallax_quote" 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_parallax.png"/>
|
||||
<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>
|
||||
<section class="oe_snippet_body parallax_quote oe_structure">
|
||||
|
||||
@@ -10,9 +10,28 @@
|
||||
<link id="website_css" rel='stylesheet' href='/website/static/src/css/website.css' t-ignore="true"/>
|
||||
</template>
|
||||
|
||||
<template id="layout" name="Main layout">
|
||||
<!DOCTYPE html>
|
||||
<template id="website.submenu" name="Submenu">
|
||||
<t t-set="children" t-value="submenu['children']"/>
|
||||
<li t-if="not children">
|
||||
<a t-att-href="url_for(submenu['url'])">
|
||||
<t t-esc="submenu['name']"/>
|
||||
</a>
|
||||
</li>
|
||||
<li t-if="children" class="dropdown">
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<t t-esc="submenu['name']"/> <span class="caret"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<t t-foreach="children" t-as="submenu">
|
||||
<t t-call="website.submenu"/>
|
||||
</t>
|
||||
</ul>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<template id="layout" name="Main layout"><!DOCTYPE html>
|
||||
<html t-att-lang="lang.replace('_', '-')"
|
||||
t-att-data-website-id="website.id if editable else None"
|
||||
t-att-data-editable="'1' if editable else None"
|
||||
t-att-data-translatable="'1' if translatable else None"
|
||||
t-att-data-view-xmlid="xmlid if editable else None"
|
||||
@@ -49,6 +68,11 @@
|
||||
<script type="text/javascript" src="/web/static/lib/underscore.string/lib/underscore.string.js"></script>
|
||||
<script type="text/javascript" src="/web/static/lib/jquery/jquery.js"></script>
|
||||
<script type="text/javascript" src="/website/static/lib/bootstrap/js/bootstrap.js"></script>
|
||||
<script type="text/javascript">
|
||||
// Bootstrap and jQuery UI conflicts
|
||||
$.fn.bstooltip = $.fn.tooltip;
|
||||
$.fn.bsbutton = $.fn.button;
|
||||
</script>
|
||||
|
||||
<script type="text/javascript" src="/web/static/lib/qweb/qweb2.js"></script>
|
||||
<script type="text/javascript" src="/web/static/src/js/openerpframework.js"></script>
|
||||
@@ -65,11 +89,13 @@
|
||||
<script type="text/javascript" src="/web/static/lib/jquery.ui/js/jquery-ui-1.9.1.custom.js"></script>
|
||||
<link rel='stylesheet' href="/web/static/lib/jquery.ui/css/smoothness/jquery-ui-1.9.1.custom.css"/>
|
||||
<!-- mutation observers shim backed by mutation events (8 < IE < 11, Safari < 6, FF < 14, Chrome < 17) -->
|
||||
<script type="text/javascript" src="/website/static/lib//jquery.mjs.nestedSortable/jquery.mjs.nestedSortable.js"></script>
|
||||
<script type="text/javascript" src="/website/static/lib/MutationObservers/test/sidetable.js"></script>
|
||||
<script type="text/javascript" src='/website/static/lib/nearest/jquery.nearest.js'></script>
|
||||
<script type="text/javascript" src="/website/static/lib/MutationObservers/MutationObserver.js"></script>
|
||||
|
||||
<script type="text/javascript" src="/website/static/src/js/website.editor.js"></script>
|
||||
<script type="text/javascript" src="/website/static/src/js/website.menu.js"></script>
|
||||
<script type="text/javascript" src="/website/static/src/js/website.mobile.js"></script>
|
||||
<script type="text/javascript" src="/website/static/src/js/website.seo.js"></script>
|
||||
<script type="text/javascript" src="/website/static/src/js/website.tour.js"></script>
|
||||
@@ -93,38 +119,28 @@
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" t-href="/page/website.homepage"><em>Your</em><b>Company</b></a>
|
||||
<a class="navbar-brand" t-href="/"><em>Your</em><b>Company</b></a>
|
||||
</div>
|
||||
<div class="collapse navbar-collapse navbar-top-collapse">
|
||||
<ul class="nav navbar-nav navbar-right" id="top_menu">
|
||||
<li name="contactus"><a t-href="/page/website.contactus">Contact us</a></li>
|
||||
<li t-if="user_id.id == website.public_user.id"><a href="/web">Sign in</a></li>
|
||||
<li t-if="user_id.id != website.public_user.id"><a href="/web"><span t-field="user_id.name"/></a></li>
|
||||
<li t-if="request.multilang and
|
||||
(len(website.language_ids) > 1 or editable)" class="dropdown">
|
||||
<!-- TODO: use flags for language selection -->
|
||||
<a class="dropdown-toggle js_language_selected" data-toggle="dropdown" href="#">
|
||||
<t t-esc="lang_selected[0]['name'].split('/').pop()"/> <span class="caret"></span>
|
||||
<t t-foreach="website.get_menu_tree()['children']" t-as="submenu">
|
||||
<t t-call="website.submenu"/>
|
||||
</t>
|
||||
|
||||
<li class="active" t-if="user_id.id == website.public_user.id">
|
||||
<a t-attf-href="/web#redirect=#{ url_for('') }">
|
||||
Sign in
|
||||
</a>
|
||||
<ul class="dropdown-menu js_language_selector" role="menu">
|
||||
<li t-foreach="website.language_ids" t-as="lg">
|
||||
<a t-att-href="url_for('', lang=lg.code)" role="menuitem"
|
||||
t-att-data-default-lang="editable and 'true' if lg.code == website.default_lang_id.code else None">
|
||||
<strong t-att-class="'icon-circle' if lg.code == lang
|
||||
else 'icon-circle-blank'"></strong>
|
||||
<t t-esc="lg.name.split('/').pop()"/>
|
||||
</a>
|
||||
</li>
|
||||
<li t-if="editable" class="divider"/>
|
||||
<li t-if="editable">
|
||||
<t t-set="url_return" t-value="request.multilang and url_for(request.httprequest.path, '[lang]') or request.httprequest.path"/>
|
||||
<t t-if="request.httprequest.query_string">
|
||||
<t t-set="url_return" t-value="url_return + '?' + request.httprequest.query_string"/>
|
||||
</t>
|
||||
<a t-attf-href="/web#action=base.action_view_base_language_install&website_id=#{website.id}&url_return=#{url_return}">
|
||||
Add a language...
|
||||
</a>
|
||||
</li>
|
||||
</li>
|
||||
<li class="active dropdown" t-ignore="true" t-if="user_id.id != website.public_user.id">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
||||
<span t-esc="user_id.name"/>
|
||||
<span class="caret"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu js_usermenu" role="menu">
|
||||
<li><a href="/web" role="menuitem">Administration</a></li>
|
||||
<li class="divider"/>
|
||||
<li><a t-attf-href="/web/session/logout?redirect=#{ url_for('') }" role="menuitem">Logout</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -174,6 +190,22 @@
|
||||
Our products are designed for small to medium companies willing to optimize
|
||||
their performance.
|
||||
</p>
|
||||
<ul class="nav nav-pills js_language_selector" t-if="request.multilang and
|
||||
(len(website.language_ids) > 1 or editable)">
|
||||
<li t-foreach="website.language_ids" t-as="lg">
|
||||
<a t-att-href="url_for('', lang=lg.code)"
|
||||
t-att-data-default-lang="editable and 'true' if lg.code == website.default_lang_id.code else None">
|
||||
<t t-esc="lg.name.split('/').pop()"/>
|
||||
</a>
|
||||
</li>
|
||||
<li t-if="editable">
|
||||
<t t-set="url_return" t-value="request.multilang and url_for(request.httprequest.path, '[lang]') or request.httprequest.path"/>
|
||||
<a t-attf-href="/web#action=base.action_view_base_language_install&website_id=#{website.id}&url_return=#{url_return}">
|
||||
<i class="icon-plus-sign"/>
|
||||
Add a language...
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -227,7 +259,7 @@
|
||||
<template id="publish_management">
|
||||
<t t-if="editable" t-ignore="true">
|
||||
<div class="pull-right">
|
||||
<div t-attf-class="btn-group dropdown js_publish_management #{object.id and object.website_published and 'css_publish' or 'css_unpublish'}" t-att-data-id="object.id" t-att-data-object="object._name">
|
||||
<div t-attf-class="btn-group dropdown js_publish_management #{object.id and object.website_published and 'css_publish' or 'css_unpublish'}" t-att-data-id="object.id" t-att-data-object="object._name" t-att-data-controller="publish_controller">
|
||||
<a t-attf-class="btn btn-sm btn-#{object.id and object.website_published and 'success' or 'default'}" t-att-id="'dopprod-%s' % object.id" role="button" data-toggle="dropdown">Options <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu" t-att-aria-labelledby="'dopprod-%s' % object.id">
|
||||
<t t-raw="0"/>
|
||||
@@ -439,8 +471,8 @@ Sitemap: <t t-esc="url_root"/>sitemap.xml
|
||||
<span>&#x2706; <span t-field="res_company.phone"></span></span><br />
|
||||
<i class="icon-envelope"></i> <span t-field="res_company.email"></span>
|
||||
</address>
|
||||
<a t-att-href="res_company.partner_id.google_map_link()" target="_BLANK">
|
||||
<img class="thumbnail img-responsive" t-att-src="res_company.partner_id.google_map_img()" />
|
||||
<a t-att-href="res_company.google_map_link()" target="_BLANK">
|
||||
<img class="thumbnail img-responsive" t-att-src="res_company.google_map_img()" />
|
||||
</a>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -181,24 +181,16 @@ class WebsiteBlog(http.Controller):
|
||||
]
|
||||
return simplejson.dumps(blog_post_data)
|
||||
|
||||
@website.route(['/blog/<int:blog_post_id>/post'], type='http', auth="public")
|
||||
@website.route(['/blog/<int:blog_post_id>/comment'], type='http', auth="public")
|
||||
def blog_post_comment(self, blog_post_id=None, **post):
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
url = request.httprequest.host_url
|
||||
request.session.body = post.get('body')
|
||||
if request.context['is_public_user']: # purpose of this ?
|
||||
return '%s/web#action=redirect&url=%s/blog/%s/post' % (url, url, blog_post_id)
|
||||
|
||||
if request.session.get('body') and blog_post_id:
|
||||
request.registry['blog.post'].message_post(
|
||||
cr, uid, blog_post_id,
|
||||
body=request.session.body,
|
||||
type='comment',
|
||||
subtype='mt_comment',
|
||||
context=dict(context, mail_create_nosubcribe=True))
|
||||
request.session.body = False
|
||||
|
||||
return werkzeug.utils.redirect("/blog/%s/?enable_editor=1" % (blog_post_id))
|
||||
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))
|
||||
return werkzeug.utils.redirect(request.httprequest.referrer + "#comments")
|
||||
|
||||
@website.route(['/blog/<int:category_id>/new'], type='http', auth="public")
|
||||
def blog_post_create(self, category_id=None, **post):
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<openerp>
|
||||
<!-- <data noupdate="1"> -->
|
||||
<data noupdate="1">
|
||||
<record id="menu_blog" model="website.menu">
|
||||
<field name="name">News</field>
|
||||
<field name="url">/blog</field>
|
||||
<field name="parent_id" ref="website.main_menu"/>
|
||||
</record>
|
||||
</data>
|
||||
|
||||
<data>
|
||||
|
||||
<!-- jump to blog at install -->
|
||||
|
||||
@@ -25,16 +25,4 @@ $(document).ready(function () {
|
||||
}
|
||||
});
|
||||
|
||||
var $form = $('.js_website_blog form#comment');
|
||||
$form.submit(function (e) {
|
||||
e.preventDefault();
|
||||
var error = $form.find("textarea").val().length < 3;
|
||||
$form.find("textarea").toggleClass("has-error", error);
|
||||
if (!error) {
|
||||
$form.css("visibility", "hidden");
|
||||
$.post(window.location.pathname + '/post', {'body': $form.find("textarea").val()}, function (url) {
|
||||
window.location.href = url
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -3,9 +3,6 @@
|
||||
<data>
|
||||
<!-- Layout add nav and footer -->
|
||||
<template id="header_footer_custom" inherit_id="website.layout">
|
||||
<xpath expr="//header//ul[@id='top_menu']/li[@name='contactus']" position="before">
|
||||
<li><a t-href="/blog/cat/%(website_blog.blog_category_1)d/">News</a></li>
|
||||
</xpath>
|
||||
<xpath expr="//footer//div[@name='info']/ul" position="inside">
|
||||
<li><a t-href="/blog/cat/%(website_blog.blog_category_1)d/">News</a></li>
|
||||
</xpath>
|
||||
@@ -132,17 +129,19 @@
|
||||
<template id="opt_blog_post_complete_comment" name="Comment Form"
|
||||
inherit_option_id="website_blog.blog_post_complete" inherit_id="website_blog.blog_post_complete">
|
||||
<xpath expr="//ul[last()]" position="after">
|
||||
<section groups="group_website_blog_reply" class="mb32">
|
||||
<h4>Leave a Comment</h4>
|
||||
<form id="comment" t-attf-action="/blog/#{blog_post.id}/post#post"
|
||||
method="POST">
|
||||
<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" class="form-control" placeholder="Write a comment..."></textarea>
|
||||
<button type="submit" class="btn btn-danger mt8">Post</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
<t t-if="not is_public_user">
|
||||
<section groups="group_website_blog_reply" class="mb32">
|
||||
<h4>Leave a Comment</h4>
|
||||
<form id="comment" t-attf-action="/blog/#{blog_post.id}/comment"
|
||||
method="POST">
|
||||
<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>
|
||||
<button type="submit" class="btn btn-danger mt8">Post</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
</t>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ class WebsiteCustomer(http.Controller):
|
||||
@website.route([
|
||||
'/customers/', '/customers/page/<int:page>/',
|
||||
'/customers/country/<int:country_id>', '/customers/country/<int:country_id>/page/<int:page>/'
|
||||
], type='http', auth="public")
|
||||
], type='http', auth="public", multilang=True)
|
||||
def customers(self, country_id=None, page=0, **post):
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
partner_obj = request.registry['res.partner']
|
||||
@@ -70,7 +70,7 @@ class WebsiteCustomer(http.Controller):
|
||||
}
|
||||
return request.website.render("website_customer.index", values)
|
||||
|
||||
@website.route(['/customers/<int:partner_id>/'], type='http', auth="public")
|
||||
@website.route(['/customers/<int:partner_id>/'], type='http', auth="public", multilang=True)
|
||||
def customer(self, partner_id=None, **post):
|
||||
""" Route for displaying a single partner / customer.
|
||||
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
<!-- Layout add nav and footer -->
|
||||
<template id="footer_custom" inherit_id="website.layout" name="Custom Footer">
|
||||
<xpath expr="//footer//div[@name='info']/ul" position="inside">
|
||||
<li><a href="/customers/">Customer References</a></li>
|
||||
<li><a t-href="/customers/">Customer References</a></li>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- Page -->
|
||||
<!-- Page -->
|
||||
<template id="layout" name="Customer References Layout">
|
||||
<t t-call="website.layout">
|
||||
<t t-set="additional_title">Customer References</t>
|
||||
@@ -53,7 +53,7 @@
|
||||
<t t-set="classname" t-value="'pull-left'"/>
|
||||
</t>
|
||||
<form action="/customers/" method="get" class="navbar-search pull-right pagination form-inline">
|
||||
<div class="form-group">
|
||||
<div class="form-group">
|
||||
<input type="text" name="search" class="search-query form-control"
|
||||
placeholder="Search" t-att-value="post.get('search', '')"/>
|
||||
</div>
|
||||
@@ -63,11 +63,11 @@
|
||||
<div>
|
||||
<div t-foreach="partner_ids" t-as="partner" class="media thumbnail" data-publish="">
|
||||
<t t-call="website.publish_management"><t t-set="object" t-value="partner"/></t>
|
||||
<a class="pull-left" t-attf-href="/customers/#{ partner.id }/">
|
||||
<a class="pull-left" t-href="/customers/#{ partner.id }/">
|
||||
<img class="media-object" t-att-src="partner.img('image_small')"/>
|
||||
</a>
|
||||
<div class="media-body" style="min-height: 64px;">
|
||||
<a class="media-heading" t-attf-href="/customers/#{ partner.id }/"><span t-field="partner.parent_id"/> <span t-field="partner.name"/></a>
|
||||
<a class="media-heading" t-href="/customers/#{ partner.id }/"><span t-field="partner.parent_id"/> <span t-field="partner.name"/></a>
|
||||
<div t-field="partner.website_short_description"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -15,6 +15,7 @@ Online Events
|
||||
'data': [
|
||||
'data/event_data.xml',
|
||||
'views/website_event.xml',
|
||||
'views/website_event_sale_backend.xml',
|
||||
'security/ir.model.access.csv',
|
||||
'security/website_event.xml',
|
||||
],
|
||||
|
||||
@@ -25,6 +25,9 @@ from openerp.addons.web.http import request
|
||||
from openerp.tools.translate import _
|
||||
from openerp.addons import website_sale
|
||||
from openerp.addons.website.models import website
|
||||
from openerp.addons.website.controllers.main import Website as controllers
|
||||
controllers = controllers()
|
||||
|
||||
|
||||
from datetime import datetime
|
||||
from dateutil.relativedelta import relativedelta
|
||||
@@ -216,3 +219,15 @@ class website_event(http.Controller):
|
||||
if not _values:
|
||||
return request.redirect("/event/%s/" % event_id)
|
||||
return request.redirect("/shop/checkout")
|
||||
|
||||
@website.route(['/event/publish'], type='json', auth="public")
|
||||
def publish(self, id, object):
|
||||
# if a user publish an event, he publish all linked res.partner
|
||||
event = request.registry[object].browse(request.cr, request.uid, int(id))
|
||||
if not event.website_published:
|
||||
if event.organizer_id and not event.organizer_id.website_published:
|
||||
event.organizer_id.write({'website_published': True})
|
||||
if event.address_id and not event.address_id.website_published:
|
||||
event.address_id.write({'website_published': True})
|
||||
|
||||
return controllers.publish(id, object)
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
|
||||
<record id="menu_events" model="website.menu">
|
||||
<field name="name">Events</field>
|
||||
<field name="url">/event</field>
|
||||
<field name="parent_id" ref="website.main_menu"/>
|
||||
</record>
|
||||
<record id="action_open_website" model="ir.actions.act_url">
|
||||
<field name="name">Website Home</field>
|
||||
<field name="target">self</field>
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="base.res_partner_6" model="res.partner">
|
||||
<field name="website_published">True</field>
|
||||
</record>
|
||||
<record id="event.event_0" model="event.event">
|
||||
<field name="website_published">True</field>
|
||||
<field name="twitter_hashtag">openerp</field>
|
||||
@@ -162,6 +165,9 @@
|
||||
</div>
|
||||
]]></field> </record>
|
||||
|
||||
<record id="base.res_partner_5" model="res.partner">
|
||||
<field name="website_published">True</field>
|
||||
</record>
|
||||
<record id="event.event_1" model="event.event">
|
||||
<field name="website_published">True</field>
|
||||
<field name="twitter_hashtag">openerp</field>
|
||||
@@ -323,11 +329,20 @@
|
||||
]]></field>
|
||||
</record>
|
||||
|
||||
<record id="base.res_partner_14" model="res.partner">
|
||||
<field name="website_published">True</field>
|
||||
</record>
|
||||
<record id="event.event_2" model="event.event">
|
||||
<field name="website_published">True</field>
|
||||
<field name="twitter_hashtag">openerp</field>
|
||||
</record>
|
||||
|
||||
<record id="base.res_partner_2" model="res.partner">
|
||||
<field name="website_published">True</field>
|
||||
</record>
|
||||
<record id="base.res_partner_address_4" model="res.partner">
|
||||
<field name="website_published">True</field>
|
||||
</record>
|
||||
<record id="event.event_3" model="event.event">
|
||||
<field name="website_published">True</field>
|
||||
<field name="twitter_hashtag">openerp</field>
|
||||
|
||||
@@ -51,6 +51,21 @@ class event(osv.osv):
|
||||
'website_published': False,
|
||||
}
|
||||
|
||||
def _check_organizer_id_published(self, cr, uid, ids, context=None):
|
||||
for obj in self.browse(cr, uid, ids, context=context):
|
||||
if obj.website_published and obj.organizer_id and not obj.organizer_id.website_published:
|
||||
return False
|
||||
return True
|
||||
def _check_address_id_published(self, cr, uid, ids, context=None):
|
||||
for obj in self.browse(cr, uid, ids, context=context):
|
||||
if obj.website_published and obj.address_id and not obj.address_id.website_published:
|
||||
return False
|
||||
return True
|
||||
_constraints = [
|
||||
(_check_organizer_id_published, "This event can't be published if the field Orginizer is not website published.", ['organizer_id','website_published']),
|
||||
(_check_address_id_published, "This event can't be published if the field Location is not website published.", ['address_id','website_published']),
|
||||
]
|
||||
|
||||
def google_map_img(self, cr, uid, ids, zoom=8, width=298, height=298, context=None):
|
||||
partner = self.browse(cr, uid, ids[0], context=context)
|
||||
if partner.address_id:
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
|
||||
<!-- Layout add nav and footer -->
|
||||
<template id="header_footer_custom" inherit_id="website.layout">
|
||||
<xpath expr="//header//ul[@id='top_menu']/li[@name='contactus']" position="before">
|
||||
<li><a t-href="/event">Events</a></li>
|
||||
</xpath>
|
||||
<xpath expr="//footer//div[@name='info']/ul" position="inside">
|
||||
<li><a t-href="/event">Events</a></li>
|
||||
</xpath>
|
||||
@@ -48,7 +45,10 @@
|
||||
</div>
|
||||
<ul class="media-list">
|
||||
<li t-foreach="event_ids" t-as="event" class="media" data-publish="">
|
||||
<t t-call="website.publish_management"><t t-set="object" t-value="event"/></t>
|
||||
<t t-call="website.publish_management">
|
||||
<t t-set="object" t-value="event"/>
|
||||
<t t-set="publish_controller">/event/publish</t>
|
||||
</t>
|
||||
<div class="media-body">
|
||||
<span t-if="not event.event_ticket_ids" class="label label-danger pull-right">Registration Closed</span>
|
||||
<t t-if="event.event_ticket_ids">
|
||||
@@ -177,7 +177,11 @@
|
||||
<ul class="media-list" id="comment">
|
||||
<li t-foreach="event_id.website_message_ids" t-as="comment" class="media">
|
||||
<div class="media-body">
|
||||
<t t-call="website.publish_management"><t t-set="object" t-value="comment"/></t>
|
||||
<t t-call="website.publish_management">
|
||||
<t t-set="object" t-value="comment"/>
|
||||
<t t-set="publish_edit" t-value="True"/>
|
||||
<t t-set="publish_controller">/event/publish</t>
|
||||
</t>
|
||||
<t t-raw="comment.body"/>
|
||||
<small class="pull-right muted text-right">
|
||||
<div t-field="comment.author_id"/>
|
||||
@@ -192,7 +196,11 @@
|
||||
|
||||
<div class="panel panel-default" t-if="event_id.address_id">
|
||||
<div class="panel-heading">
|
||||
<t t-call="website.publish_management"><t t-set="object" t-value="event_id"/></t>
|
||||
<t t-call="website.publish_management">
|
||||
<t t-set="object" t-value="event_id"/>
|
||||
<t t-set="publish_edit" t-value="True"/>
|
||||
<t t-set="publish_controller">/event/publish</t>
|
||||
</t>
|
||||
<h4>Where</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record model="ir.ui.view" id="view_event_form">
|
||||
<field name="name">event.event.website.form</field>
|
||||
<field name="model">event.event</field>
|
||||
<field name="inherit_id" ref="event_sale.view_event_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="organizer_id" position="after">
|
||||
<field name="website_published"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -2,6 +2,9 @@
|
||||
from openerp.addons.web import http
|
||||
from openerp.addons.web.http import request
|
||||
from openerp.addons.website.models import website
|
||||
from openerp.addons.website.controllers.main import Website as controllers
|
||||
controllers = controllers()
|
||||
|
||||
import base64
|
||||
|
||||
|
||||
@@ -48,7 +51,7 @@ class website_hr_recruitment(http.Controller):
|
||||
return request.website.render("website_hr_recruitment.index", values)
|
||||
|
||||
@website.route(['/job/detail/<model("hr.job"):job>'], type='http', auth="public", multilang=True)
|
||||
def detail(self, job=None):
|
||||
def detail(self, job=None, **kwargs):
|
||||
values = {
|
||||
'job': job,
|
||||
'vals_date': job.write_date.split(' ')[0],
|
||||
@@ -68,28 +71,23 @@ class website_hr_recruitment(http.Controller):
|
||||
'res_id': id
|
||||
}
|
||||
request.registry['ir.attachment'].create(request.cr, request.uid, attachment_values)
|
||||
website = request.registry['website']
|
||||
values = {
|
||||
'jobid': post['job_id']
|
||||
}
|
||||
return request.website.render("website_hr_recruitment.thankyou", values)
|
||||
|
||||
@website.route(['/apply/<int:id>'], type='http', auth="public", multilang=True)
|
||||
def applyjobpost(self, id=0, **kwargs):
|
||||
id = id and int(id) or 0
|
||||
job = request.registry['hr.job'].browse(request.cr, request.uid, id)
|
||||
values = {
|
||||
'job': job
|
||||
}
|
||||
return request.website.render("website_hr_recruitment.applyjobpost", values)
|
||||
@website.route(['/apply/<model("hr.job"):job>'], type='http', auth="public", multilang=True)
|
||||
def applyjobpost(self, job=None, **kwargs):
|
||||
return request.website.render("website_hr_recruitment.applyjobpost", { 'job': job })
|
||||
|
||||
@website.route('/recruitment/published', type='json', auth="admin", multilang=True)
|
||||
def published (self, id, **post):
|
||||
hr_job = request.registry['hr.job']
|
||||
@website.route('/job/publish', type='json', auth="admin", multilang=True)
|
||||
def publish (self, id, object):
|
||||
res = controllers.publish(id, object)
|
||||
|
||||
hr_job = request.registry[object]
|
||||
id = int(id)
|
||||
rec = hr_job.browse(request.cr, request.uid, id)
|
||||
vals = {}
|
||||
|
||||
if rec.website_published:
|
||||
vals['state'] = 'recruit'
|
||||
if not rec.no_of_recruitment:
|
||||
@@ -98,6 +96,5 @@ class website_hr_recruitment(http.Controller):
|
||||
vals['state'] = 'open'
|
||||
hr_job.write(request.cr, request.uid, [rec.id], vals, context=request.context)
|
||||
|
||||
obj = hr_job.browse(request.cr, request.uid, id, context=request.context)
|
||||
return { 'count': obj.no_of_recruitment, 'state': obj.state, 'published': obj.website_published }
|
||||
return res
|
||||
# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
|
||||
<record id="menu_jobs" model="website.menu">
|
||||
<field name="name">Jobs</field>
|
||||
<field name="url">/jobs</field>
|
||||
<field name="parent_id" ref="website.main_menu"/>
|
||||
</record>
|
||||
<record id="action_open_website" model="ir.actions.act_url">
|
||||
<field name="name">Website Recruitment Form</field>
|
||||
<field name="target">self</field>
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
$(function () {
|
||||
$(this).ajaxComplete(function(event, xhr, settings) {
|
||||
var data = JSON.parse(settings.data).params;
|
||||
if (settings.url == "/website/publish") {
|
||||
var $data = $(".oe_website_hr_recruitment .js_publish_management[data-id='" + data.id + "'][data-object='" + data.object + "']");
|
||||
if ($data.length) {
|
||||
settings.jsonpCallback = openerp.jsonRpc('/recruitment/published', 'call', data);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -8,9 +8,6 @@
|
||||
</record>
|
||||
|
||||
<template id="job_footer_custom" inherit_id="website.layout" name="Custom Footer Job">
|
||||
<xpath expr="//header//ul[@id='top_menu']/li[@name='contactus']" position="before">
|
||||
<li><a t-href="/jobs">Jobs</a></li>
|
||||
</xpath>
|
||||
<xpath expr="//footer//div[@name='info']/ul" position="inside">
|
||||
<li><a t-href="/jobs">Jobs</a></li>
|
||||
</xpath>
|
||||
@@ -56,10 +53,6 @@
|
||||
|
||||
<template id="detail">
|
||||
<t t-call="website.layout">
|
||||
<t t-set="head">
|
||||
<script type="text/javascript" src="/website_hr_recruitment/static/src/js/recruitment.js"></script>
|
||||
<t t-raw="head or ''"/>
|
||||
</t>
|
||||
<t t-set="additional_title">Job Detail</t>
|
||||
<div id="wrap">
|
||||
<div class="container oe_website_hr_recruitment">
|
||||
@@ -73,6 +66,7 @@
|
||||
<t t-call="website.publish_management">
|
||||
<t t-set="object" t-value="job"/>
|
||||
<t t-set="publish_edit" t-value="True"/>
|
||||
<t t-set="publish_controller">/job/publish</t>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -214,7 +214,6 @@ class Ecommerce(http.Controller):
|
||||
col += 1
|
||||
line += 1
|
||||
|
||||
print bin_packing_list
|
||||
return bin_packing_list
|
||||
|
||||
def get_products(self, product_ids):
|
||||
|
||||
@@ -4,6 +4,7 @@ access_product_template_public,product.template.public,product.model_product_tem
|
||||
access_product_category_,product.category.public,product.model_product_category,base.group_public,1,0,0,0
|
||||
access_product_category_public,product.category.public,product.model_product_public_category,base.group_public,1,0,0,0
|
||||
access_product_pricelist_version_public,product.pricelist.version.public,product.model_product_pricelist_version,base.group_public,1,0,0,0
|
||||
access_product_pricelist_public,product.pricelist.public,product.model_product_pricelist,base.group_public,1,0,0,0
|
||||
access_product_product_price_type_public,product.price.type.public,product.model_product_price_type,base.group_public,1,0,0,0
|
||||
access_sale_order_public,sale.order.public,model_sale_order,base.group_public,1,0,0,0
|
||||
access_sale_order_line_public,sale.order.line.public,model_sale_order_line,base.group_public,1,0,0,0
|
||||
|
@@ -42,5 +42,16 @@
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_unlink" eval="False"/>
|
||||
</record>
|
||||
|
||||
<record id="product_pricelist_public" model="ir.rule">
|
||||
<field name="name">Public product pricelist</field>
|
||||
<field name="model_id" ref="product.model_product_pricelist"/>
|
||||
<field name="domain_force">[('id','=',session.get('ecommerce_pricelist'))]</field>
|
||||
<field name="groups" eval="[(4, ref('base.group_public'))]"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_unlink" eval="False"/>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
</openerp>
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
<template id="header" inherit_id="website.layout" name="Custom Header">
|
||||
<xpath expr="//header//ul[@id='top_menu']/li" position="before">
|
||||
<li><a t-href="/shop/">Shop</a></li>
|
||||
<li t-att-class="(not website_sale_order or not website_sale_order.get_total_quantity()) and 'hidden' or ''">
|
||||
<a t-href="/shop/mycart/">
|
||||
<i class="icon-shopping-cart"></i>
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
|
||||
<record id="menu_shop" model="website.menu">
|
||||
<field name="name">Shop</field>
|
||||
<field name="url">/shop</field>
|
||||
<field name="parent_id" ref="website.main_menu"/>
|
||||
</record>
|
||||
<record id="action_open_website" model="ir.actions.act_url">
|
||||
<field name="name">Website Shop</field>
|
||||
<field name="target">self</field>
|
||||
|
||||
Reference in New Issue
Block a user