[MERGE] from upstream
bzr revid: fva@openerp.com-20130821163002-y45g9l65xwrcxmsn
This commit is contained in:
commit
6ccd087ee0
|
@ -27,6 +27,10 @@ def auth_method_public():
|
|||
http.auth_methods['public'] = auth_method_public
|
||||
|
||||
|
||||
# PIL images have a type flag, but no MIME. Reverse type flag to MIME.
|
||||
PIL_MIME_MAPPING = {'PNG': 'image/png', 'JPEG': 'image/jpeg', 'GIF': 'image/gif', }
|
||||
# Completely arbitrary limits
|
||||
MAX_IMAGE_WIDTH, MAX_IMAGE_HEIGHT = IMAGE_LIMITS = (1024, 768)
|
||||
class Website(openerp.addons.web.controllers.main.Home):
|
||||
@http.route('/', type='http', auth="admin")
|
||||
def index(self, **kw):
|
||||
|
@ -45,7 +49,8 @@ class Website(openerp.addons.web.controllers.main.Home):
|
|||
newview = view.browse(request.cr, request.uid, newview_id, context={})
|
||||
newview.write({
|
||||
'arch': newview.arch.replace("website.default_page", path),
|
||||
'name': "page/%s" % path
|
||||
'name': "page/%s" % path,
|
||||
'page': True,
|
||||
})
|
||||
if '.' in path:
|
||||
module, idname = path.split('.')
|
||||
|
@ -145,15 +150,20 @@ class Website(openerp.addons.web.controllers.main.Home):
|
|||
buf = cStringIO.StringIO(base64.decodestring(attachment.datas))
|
||||
|
||||
image = Image.open(buf)
|
||||
image.thumbnail((1024, 768), Image.ANTIALIAS)
|
||||
mime = PIL_MIME_MAPPING[image.format]
|
||||
|
||||
response = werkzeug.wrappers.Response(status=200, mimetype={
|
||||
'PNG': 'image/png',
|
||||
'JPEG': 'image/jpeg',
|
||||
'GIF': 'image/gif',
|
||||
}[image.format])
|
||||
w, h = image.size
|
||||
resized = w > MAX_IMAGE_WIDTH or h > MAX_IMAGE_HEIGHT
|
||||
|
||||
# If saving unnecessary, just send the image buffer, don't go through
|
||||
# Image.save() (especially as it breaks animated gifs)
|
||||
if not resized:
|
||||
buf.seek(0)
|
||||
return werkzeug.wrappers.Response(buf, status=200, mimetype=mime)
|
||||
|
||||
image.thumbnail(IMAGE_LIMITS, Image.ANTIALIAS)
|
||||
response = werkzeug.wrappers.Response(status=200, mimetype=mime)
|
||||
image.save(response.stream, image.format)
|
||||
|
||||
return response
|
||||
|
||||
@http.route('/website/image', type='http', auth="public")
|
||||
|
@ -208,4 +218,8 @@ class Website(openerp.addons.web.controllers.main.Home):
|
|||
|
||||
return obj.website_published and "1" or "0"
|
||||
|
||||
@http.route(['/website/kanban/'], type='http', auth="public")
|
||||
def kanban(self, **post):
|
||||
return request.registry['website'].kanban_col(**post)
|
||||
|
||||
# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -250,7 +250,7 @@
|
|||
]},{
|
||||
name: 'span', items: [
|
||||
"Link", "Unlink", "Blockquote", "BulletedList",
|
||||
"NumberedList", "Indent", "Outdent",
|
||||
"NumberedList", "Indent", "Outdent"
|
||||
]},{
|
||||
name: 'justify', items: [
|
||||
"JustifyLeft", "JustifyCenter", "JustifyRight", "JustifyBlock"
|
||||
|
@ -450,6 +450,146 @@
|
|||
},
|
||||
});
|
||||
|
||||
function noop() {}
|
||||
var alter_dialog = {
|
||||
image: function (definition) {
|
||||
definition.removeContents('Link');
|
||||
definition.removeContents('advanced');
|
||||
|
||||
var upload = definition.getContents('Upload');
|
||||
upload.add({
|
||||
type: 'select',
|
||||
label: 'Existing attachments',
|
||||
id: 'ir_attachment',
|
||||
items: [['']],
|
||||
/**
|
||||
* On dialog load, fetch all attachments (on ir.ui.view =>
|
||||
* previously uploaded images) and add them to the select's
|
||||
* options (items array & add method)
|
||||
*/
|
||||
onLoad: function () {
|
||||
var field = this;
|
||||
|
||||
// FIXME: fuck this garbage, also fuck openerp.Model
|
||||
return openerp.jsonRpc('/web/dataset/call_kw', 'call', {
|
||||
model: 'ir.attachment',
|
||||
method: 'search_read',
|
||||
args: [],
|
||||
kwargs: {
|
||||
fields: ['name'],
|
||||
domain: [['res_model', '=', 'ir.ui.view']],
|
||||
order: 'name',
|
||||
}
|
||||
}).then(function (results) {
|
||||
_(results).each(function (result) {
|
||||
field.add(result.name, result.id);
|
||||
});
|
||||
});
|
||||
},
|
||||
/**
|
||||
* The image widgets uses "txtUrl" to do most of its stuff.
|
||||
* Synchronize select & txtUrl by generating the correct URL
|
||||
* and setting it there
|
||||
*/
|
||||
onChange: function () {
|
||||
var id = this.getValue();
|
||||
var url = this.getDialog().getContentElement('info', 'txtUrl');
|
||||
if (!id) {
|
||||
url.setValue('');
|
||||
return;
|
||||
}
|
||||
|
||||
url.setValue('/website/attachment/' + id);
|
||||
},
|
||||
});
|
||||
// Override uploadButton to send its information to the select
|
||||
// created above instead of directly to txtUrl. The select will
|
||||
// propagate to txtUrl
|
||||
upload.get('uploadButton').filebrowser = {
|
||||
onSelect: function (url) {
|
||||
var id = url.split('/').pop();
|
||||
var attachments = this.getDialog().getContentElement('Upload', 'ir_attachment');
|
||||
// TODO: return supplementary info to get image/attachment name?
|
||||
attachments.add(id, id);
|
||||
attachments.setValue(id);
|
||||
}
|
||||
};
|
||||
|
||||
var old_show = definition.onShow;
|
||||
definition.onShow = function () {
|
||||
// CKEDITOR does not *override* onShow, is smashes the existing
|
||||
// one instead, so override "by hand"
|
||||
if (old_show) {
|
||||
old_show.call(this);
|
||||
}
|
||||
// Assloads of code in the image plugin just go and tear into
|
||||
// the info tab without a care, so can't just remove the tab or
|
||||
// its content. Hide the tab instead, the effect is roughly the
|
||||
// same.
|
||||
this.hidePage('info');
|
||||
// Force the dialog to always and only display the Upload tab
|
||||
this.selectPage('Upload');
|
||||
this.on('selectPage', function (e) {
|
||||
setTimeout(function () {
|
||||
if (e.data.page !== 'Upload') {
|
||||
this.selectPage('Upload');
|
||||
}
|
||||
}.bind(this), 0);
|
||||
});
|
||||
}
|
||||
},
|
||||
link: function (definition) {
|
||||
definition.removeContents('target');
|
||||
definition.removeContents('advanced');
|
||||
|
||||
var info = definition.getContents('info');
|
||||
info.remove('linkType');
|
||||
info.remove('anchorOptions');
|
||||
info.remove('emailOptions');
|
||||
|
||||
info.get('urlOptions').children[0].widths = [ '0%', '100%' ];
|
||||
info.get('protocol').style = 'display: none';
|
||||
// TODO: sync edition of url to website_pages?
|
||||
info.add({
|
||||
type: 'select',
|
||||
label: "Existing page",
|
||||
id: 'website_pages',
|
||||
items: [['']],
|
||||
/**
|
||||
* onload fetch all the pages existing in the website, then
|
||||
* display that.
|
||||
*/
|
||||
onLoad: function () {
|
||||
var field = this;
|
||||
|
||||
return openerp.jsonRpc('/web/dataset/call_kw', 'call', {
|
||||
model: 'website',
|
||||
method: 'list_pages',
|
||||
args: [],
|
||||
kwargs: {}
|
||||
}).then(function (results) {
|
||||
_(results).each(function (result) {
|
||||
field.add(result.name, result.url);
|
||||
});
|
||||
});
|
||||
},
|
||||
onChange: function () {
|
||||
var url = this.getValue();
|
||||
var url_field = this.getDialog().getContentElement('info', 'url');
|
||||
if (!url) {
|
||||
url_field.setValue('');
|
||||
return;
|
||||
}
|
||||
|
||||
url_field.setValue(url);
|
||||
}
|
||||
})
|
||||
}
|
||||
};
|
||||
CKEDITOR.on('dialogDefinition', function (ev) {
|
||||
(alter_dialog[ev.data.name] || noop)(ev.data.definition);
|
||||
});
|
||||
|
||||
var all_ready = null;
|
||||
var dom_ready = $.Deferred();
|
||||
$(dom_ready.resolve);
|
||||
|
|
|
@ -132,7 +132,7 @@
|
|||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="homepage">
|
||||
<template id="homepage" page="True">
|
||||
<t t-call="website.layout">
|
||||
|
||||
<section>
|
||||
|
@ -318,7 +318,7 @@
|
|||
</template>
|
||||
|
||||
|
||||
<template id="contactus" name="Contact us">
|
||||
<template id="contactus" name="Contact us" page="True">
|
||||
<t t-call="website.layout">
|
||||
<t t-set="title">Contact us - <t t-raw="res_company.name"/></t>
|
||||
<div class="container">
|
||||
|
@ -353,7 +353,7 @@
|
|||
</t>
|
||||
</template>
|
||||
|
||||
<template id="aboutus">
|
||||
<template id="aboutus" page="True">
|
||||
<t t-call="website.layout">
|
||||
<t t-set="title">About us - <t t-raw="res_company.name"/></t>
|
||||
<div class="container">
|
||||
|
@ -380,9 +380,9 @@
|
|||
<li t-att-class=" 'disabled' if pager['page']['num'] == 1 else '' " >
|
||||
<a t-att-href=" pager['page_start']['url'] if pager['page']['num'] != 1 else '' ">Prev</a>
|
||||
</li>
|
||||
<t t-foreach="pager['pages']">
|
||||
<li t-att-class=" 'active' if num == pager['page']['num'] else '' ">
|
||||
<a t-att-href="url" t-raw="num"></a>
|
||||
<t t-foreach="pager['pages']" t-as="page">
|
||||
<li t-att-class=" 'active' if page['num'] == pager['page']['num'] else '' ">
|
||||
<a t-att-href="page['url']" t-raw="page['num']"></a>
|
||||
</li>
|
||||
</t>
|
||||
<li t-att-class=" 'disabled' if pager['page']['num'] == pager['page_count'] else '' " >
|
||||
|
@ -394,8 +394,8 @@
|
|||
|
||||
<template id="publish">
|
||||
<a href="#" t-att-data-id="object.id" t-att-data-object="object._name" class="pull-right" t-if="editable" t-ignore="true">
|
||||
<span t-att-class="'label label-success js_unpublish %%s' %% (not object.website_published and 'hidden' or '')">Unpublish</span>
|
||||
<span t-att-class="'label label-important js_publish %%s' %% (object.website_published and 'hidden' or '')">Publish</span>
|
||||
<span t-attf-class="label label-success js_unpublish #{ '' if object.website_published else 'hidden' }">Unpublish</span>
|
||||
<span t-attf-class="label label-important js_publish #{ 'hidden' if object.website_published else '' }">Publish</span>
|
||||
</a>
|
||||
</template>
|
||||
|
||||
|
@ -491,5 +491,125 @@
|
|||
|
||||
</template>
|
||||
|
||||
|
||||
<template id="kanban">
|
||||
<t t-set="step"><t t-esc="step or 0"/></t>
|
||||
<t t-set="scope"><t t-esc="scope or 0"/></t>
|
||||
<t t-set="orderby"><t t-esc="orderby or 'name'"/></t>
|
||||
<t t-raw="snipped['kanban'](model, domain, column, content, step=step, scope=scope, orderby=orderby)"/>
|
||||
</template>
|
||||
|
||||
<template id="kanban_contain">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<t t-set="width" t-value="'%%s%%%%' % (100/len(objects))"/>
|
||||
<t t-foreach="objects">
|
||||
<th t-att-width="width">
|
||||
<div t-field="column_id.name" class="text-center"/>
|
||||
</th>
|
||||
</t>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<t t-foreach="objects">
|
||||
|
||||
<t t-set="pager">
|
||||
<div t-if="1 != page_end" class="pagination pagination-centered">
|
||||
<ul>
|
||||
<li t-attf-class="prev #{'active' if page == 1 else '' }" >
|
||||
<a t-att-href=" '%s,%s-%s' % (kanban_url, column_id.id, (page > 1 and page-1 or 1)) ">Prev</a>
|
||||
</li>
|
||||
<t t-foreach="range(page_start, page_end+1)" t-as="p">
|
||||
<li t-att-class=" 'active' if page == p else '' ">
|
||||
<a t-att-href=" '%s,%s-%s' % (kanban_url, column_id.id, p)" t-esc="p"/>
|
||||
</li>
|
||||
</t>
|
||||
<li t-attf-class="next #{'active' if page == page_end else '' }" >
|
||||
<a t-att-href=" '%s,%s-%s' % (kanban_url, column_id.id, (page < page_end and page+1 or page_end) )">Next</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<td class="js_kanban_col"
|
||||
t-att-data-content="content"
|
||||
t-att-data-domain="domain"
|
||||
t-att-data-page_count="page_count"
|
||||
t-att-data-model="model"
|
||||
t-att-data-step="step"
|
||||
t-att-data-orderby="orderby">
|
||||
<t t-raw="pager"/>
|
||||
<div t-foreach="object_ids" t-as="object_id" class="thumbnail">
|
||||
<t t-call="website_project.kanban_card"/>
|
||||
</div>
|
||||
<t t-raw="pager"/>
|
||||
</td>
|
||||
|
||||
</t>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<script>
|
||||
|
||||
$('.js_kanban_col').each(function () {
|
||||
var $col = $(this);
|
||||
var $pagination = $('.pagination', $col);
|
||||
if(!$pagination.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var page_count = $col.data('page_count');
|
||||
var scope = $pagination.first().find("li").size()-2;
|
||||
var kanban_url_col = $pagination.find("li a:first").attr("href").replace(/[0-9]+$/, '');
|
||||
|
||||
var data = {
|
||||
'domain': $col.data('domain'),
|
||||
'model': $col.data('model'),
|
||||
'content': $col.data('content'),
|
||||
'step': $col.data('step'),
|
||||
'orderby': $col.data('orderby')
|
||||
};
|
||||
|
||||
$pagination.on('click', 'a', function (ev) {
|
||||
ev.preventDefault();
|
||||
var $a = $(ev.target);
|
||||
if($a.hasClass('active')) {
|
||||
return;
|
||||
}
|
||||
|
||||
var page = +$a.attr("href").split(",").pop().split('-')[1];
|
||||
data['page'] = page;
|
||||
|
||||
$.post('/website/kanban/', data, function (col) {
|
||||
$col.find("> .thumbnail").remove();
|
||||
$pagination.first().after('<div class="thumbnail">'+col+'</div>');
|
||||
});
|
||||
|
||||
var page_start = page - parseInt(Math.floor((scope-1)/2));
|
||||
if (page_start < 1 ) page_start = 1;
|
||||
var page_end = page_start + (scope-1);
|
||||
if (page_end > page_count ) page_end = page_count;
|
||||
|
||||
if (page_end - page_start < scope) {
|
||||
page_start = page_end - scope > 0 ? page_end - scope : 1;
|
||||
}
|
||||
|
||||
$pagination.find('li.prev a').attr("href", kanban_url_col+(page-1 > 0 ? page-1 : 1));
|
||||
$pagination.find('li.next a').attr("href", kanban_url_col+(page+1));
|
||||
for(var i=0; i < scope; i++) {
|
||||
$pagination.find('li:not(.prev):not(.next):eq('+i+') a').attr("href", kanban_url_col+(page_start+i)).html(page_start+i);
|
||||
}
|
||||
$pagination.find('li.active').removeClass('active');
|
||||
$pagination.find('li:has(a[href="'+kanban_url_col+page+'"])').addClass('active');
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
</template>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -9,6 +9,7 @@ from openerp.addons.web.http import request
|
|||
import urllib
|
||||
import math
|
||||
import traceback
|
||||
from openerp.tools.safe_eval import safe_eval
|
||||
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -63,6 +64,9 @@ class website(osv.osv):
|
|||
'host_url': request.httprequest.host_url,
|
||||
'res_company': request.registry['res.company'].browse(request.cr, openerp.SUPERUSER_ID, 1),
|
||||
'json': simplejson,
|
||||
'snipped': {
|
||||
'kanban': self.kanban
|
||||
}
|
||||
}
|
||||
if additional_values:
|
||||
values.update(additional_values)
|
||||
|
@ -75,10 +79,10 @@ class website(osv.osv):
|
|||
}
|
||||
try:
|
||||
return view.render(request.cr, request.uid, template, values, context=context)
|
||||
except (osv.except_osv, orm.except_orm), err:
|
||||
logger.error(err)
|
||||
values['error'] = err[1]
|
||||
return self.render('website.401', values)
|
||||
# except (osv.except_osv, orm.except_orm), err:
|
||||
# logger.error(err)
|
||||
# values['error'] = err[1]
|
||||
# return self.render('website.401', values)
|
||||
# except ValueError:
|
||||
# logger.error("Website Rendering Error.\n\n%s" % (traceback.format_exc()))
|
||||
# return self.render('website.404', values)
|
||||
|
@ -93,19 +97,16 @@ class website(osv.osv):
|
|||
|
||||
def pager(self, url, total, page=1, step=30, scope=5, url_args=None):
|
||||
# Compute Pager
|
||||
d = {}
|
||||
d["page_count"] = int(math.ceil(float(total) / step))
|
||||
page_count = int(math.ceil(float(total) / step))
|
||||
|
||||
page = max(1, min(int(page), d["page_count"]))
|
||||
|
||||
d["offset"] = (page-1) * step
|
||||
page = max(1, min(int(page), page_count))
|
||||
scope -= 1
|
||||
|
||||
pmin = max(page - int(math.floor(scope/2)), 1)
|
||||
pmax = min(pmin + scope, d["page_count"])
|
||||
pmax = min(pmin + scope, page_count)
|
||||
|
||||
if pmax - pmin < scope:
|
||||
pmin = pmax - scope > 0 and pmax - scope or 1
|
||||
pmin = pmax - scope if pmax - scope > 0 else 1
|
||||
|
||||
def get_url(page):
|
||||
_url = "%spage/%s/" % (url, page)
|
||||
|
@ -113,15 +114,113 @@ class website(osv.osv):
|
|||
_url = "%s?%s" % (_url, urllib.urlencode(url_args))
|
||||
return _url
|
||||
|
||||
d["page"] = {'url': get_url(page), 'num': page}
|
||||
d["page_start"] = {'url': get_url(pmin), 'num': pmin}
|
||||
d["page_end"] = {'url': get_url(min(pmax, page+1)), 'num': min(pmax, page+1)}
|
||||
d["pages"] = []
|
||||
for page in range(pmin, pmax+1):
|
||||
d["pages"].append({'url': get_url(page), 'num': page})
|
||||
return {
|
||||
"page_count": page_count,
|
||||
"offset": (page - 1) * step,
|
||||
"page": {'url': get_url(page), 'num': page},
|
||||
"page_start": {'url': get_url(pmin), 'num': pmin},
|
||||
"page_end": {'url': get_url(min(pmax, page + 1)),
|
||||
'num': min(pmax, page + 1)},
|
||||
"pages": [
|
||||
{'url': get_url(page), 'num': page}
|
||||
for page in xrange(pmin, pmax+1)
|
||||
]
|
||||
}
|
||||
|
||||
return d
|
||||
def list_pages(self, cr, uid, context=None):
|
||||
""" Available pages in the website/CMS. This is mostly used for links
|
||||
generation and can be overridden by modules setting up new HTML
|
||||
controllers for dynamic pages (e.g. blog).
|
||||
|
||||
By default, returns template views marked as pages.
|
||||
|
||||
:returns: a list of mappings with two keys: ``name`` is the displayable
|
||||
name of the resource (page), ``url`` is the absolute URL
|
||||
of the same.
|
||||
:rtype: list({name: str, url: str})
|
||||
"""
|
||||
View = self.pool['ir.ui.view']
|
||||
views = View.search_read(cr, uid, [['page', '=', True]],
|
||||
fields=['name'], order='name', context=context)
|
||||
xids = View.get_external_id(cr, uid, [view['id'] for view in views], context=context)
|
||||
|
||||
return [
|
||||
{'name': view['name'], 'url': '/page/' + xids[view['id']]}
|
||||
for view in views
|
||||
if xids[view['id']]
|
||||
]
|
||||
|
||||
def kanban(self, model, domain, column, content, step=None, scope=None, orderby=None):
|
||||
step = step and int(step) or 10
|
||||
scope = scope and int(scope) or 5
|
||||
orderby = orderby or "name"
|
||||
|
||||
get_args = dict(request.httprequest.args or {})
|
||||
model_obj = request.registry[model]
|
||||
relation = model_obj._columns.get(column)._obj
|
||||
relation_obj = request.registry[relation]
|
||||
|
||||
get_args.setdefault('kanban', "")
|
||||
kanban = get_args.pop('kanban')
|
||||
kanban_url = "?%s&kanban=" % urllib.urlencode(get_args)
|
||||
|
||||
pages = {}
|
||||
for col in kanban.split(","):
|
||||
if col:
|
||||
col = col.split("-")
|
||||
pages[int(col[0])] = int(col[1])
|
||||
|
||||
objects = []
|
||||
for group in model_obj.read_group(request.cr, request.uid, domain, ["id", column], groupby=column):
|
||||
obj = {}
|
||||
|
||||
# browse column
|
||||
relation_id = group[column][0]
|
||||
obj['column_id'] = relation_obj.browse(request.cr, request.uid, relation_id)
|
||||
|
||||
obj['kanban_url'] = kanban_url
|
||||
for k, v in pages.items():
|
||||
if k != relation_id:
|
||||
obj['kanban_url'] += "%s-%s" % (k, v)
|
||||
|
||||
# pager
|
||||
number = model_obj.search(request.cr, request.uid, group['__domain'], count=True)
|
||||
obj['page'] = pages.get(relation_id) or 1
|
||||
obj['page_count'] = int(math.ceil(float(number) / step))
|
||||
offset = (obj['page']-1) * step
|
||||
obj['page_start'] = max(obj['page'] - int(math.floor((scope-1)/2)), 1)
|
||||
obj['page_end'] = min(obj['page_start'] + (scope-1), obj['page_count'])
|
||||
|
||||
# view data
|
||||
obj['domain'] = group['__domain']
|
||||
obj['model'] = model
|
||||
obj['step'] = step
|
||||
obj['orderby'] = orderby
|
||||
|
||||
# browse objects
|
||||
object_ids = model_obj.search(request.cr, request.uid, group['__domain'], limit=step, offset=offset, order=orderby)
|
||||
obj['object_ids'] = model_obj.browse(request.cr, request.uid, object_ids)
|
||||
|
||||
objects.append(obj)
|
||||
|
||||
values = self.get_rendering_context({
|
||||
'objects': objects,
|
||||
'range': range,
|
||||
'content': content,
|
||||
})
|
||||
return self.render("website.kanban_contain", values)
|
||||
|
||||
def kanban_col(self, model, domain, page, content, step, orderby):
|
||||
html = ""
|
||||
model_obj = request.registry[model]
|
||||
domain = safe_eval(domain)
|
||||
step = int(step)
|
||||
offset = (int(page)-1) * step
|
||||
object_ids = model_obj.search(request.cr, request.uid, domain, limit=step, offset=offset, order=orderby)
|
||||
object_ids = model_obj.browse(request.cr, request.uid, object_ids)
|
||||
for object_id in object_ids:
|
||||
html += self.render(content, self.get_rendering_context({'object_id': object_id}))
|
||||
return html
|
||||
|
||||
class res_partner(osv.osv):
|
||||
_inherit = "res.partner"
|
||||
|
|
|
@ -18,15 +18,15 @@
|
|||
<t t-set="title">References</t>
|
||||
<div class="container">
|
||||
<div class="thumbnails grid grid-align-top">
|
||||
<div t-foreach="partner_ids" t-as="partner_id" class="span6">
|
||||
<div t-foreach="partner_ids" t-as="partner" class="span6">
|
||||
<div class="media thumbnail">
|
||||
<a class="pull-left" href="#">
|
||||
<img class="media-object" t-att-src="partner_id.img('image_small')"/>
|
||||
<img class="media-object" t-att-src="partner.img('image_small')"/>
|
||||
</a>
|
||||
<div class="media-body">
|
||||
<t t-call="website.publish"><t t-set="object" t-value="partner_id"/></t>
|
||||
<h5 class="media-heading" t-field="partner_id.name"/>
|
||||
<pre t-field="partner_id.website_testimonial"/>
|
||||
<t t-call="website.publish"><t t-set="object" t-value="partner"/></t>
|
||||
<h5 class="media-heading" t-field="partner.name"/>
|
||||
<pre t-field="partner.website_testimonial"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
<!-- Page -->
|
||||
|
||||
<template id="index" name="Events">
|
||||
<template id="index" name="Events" page="True">
|
||||
<t t-call="website.layout">
|
||||
<t t-set="head">
|
||||
<script type="text/javascript" src="/website_hr/static/src/js/website_hr.js"></script>
|
||||
|
@ -29,7 +29,7 @@
|
|||
<li class="nav-header">Date</li>
|
||||
<t t-foreach="dates" t-as="date">
|
||||
<li t-att-class="searches.get('date') == date[0] and 'active' or ''">
|
||||
<a t-att-href="'/event/%%s&date=%%s' %% (search_path, date[0])"><t t-esc="date[1]"/> <small t-if="date[3]">(<t t-esc="date[3]"/>)</small></a>
|
||||
<a t-attf-href="/event/#{ search_path }&date=#{ date[0] }"><t t-esc="date[1]"/> <small t-if="date[3]">(<t t-esc="date[3]"/>)</small></a>
|
||||
</li>
|
||||
</t>
|
||||
</ul>
|
||||
|
@ -43,33 +43,33 @@
|
|||
</div>
|
||||
<div class="span8">
|
||||
<ul class="media-list">
|
||||
<li t-foreach="event_ids" t-as="event_id" class="media thumbnail">
|
||||
<li t-foreach="event_ids" t-as="event" class="media thumbnail">
|
||||
<div class="media-body">
|
||||
<span t-if="not event_id.event_ticket_ids" class="label pull-right">No tickets needed.</span>
|
||||
<t t-if="event_id.event_ticket_ids">
|
||||
<span t-if="event_id.register_avail == 9999" class="label pull-right label-info">Tickets availables.</span>
|
||||
<span t-if="not event_id.register_avail" class="label pull-right">No ticket available.</span>
|
||||
<span t-if="event_id.register_avail and event_id.register_avail != 9999" t-att-class="'label pull-right label-%%s' %% (event_id.register_avail <= 10 and 'warning' or 'info')">
|
||||
<t t-if="event_id.register_avail <= 10">Only</t>
|
||||
<t t-esc="event_id.register_avail"/>
|
||||
<t t-if="event_id.register_avail > 1">tickets </t>
|
||||
<t t-if="event_id.register_avail == 1">ticket </t>
|
||||
<span t-if="not event.event_ticket_ids" class="label pull-right">No tickets needed.</span>
|
||||
<t t-if="event.event_ticket_ids">
|
||||
<span t-if="event.register_avail == 9999" class="label pull-right label-info">Tickets availables.</span>
|
||||
<span t-if="not event.register_avail" class="label pull-right">No ticket available.</span>
|
||||
<span t-if="event.register_avail and event.register_avail != 9999" t-attf-class="label pull-right label-#{ event.register_avail <= 10 and 'warning' or 'info' }">
|
||||
<t t-if="event.register_avail <= 10">Only</t>
|
||||
<t t-esc="event.register_avail"/>
|
||||
<t t-if="event.register_avail > 1">tickets</t>
|
||||
<t t-if="event.register_avail == 1">ticket</t>
|
||||
available.
|
||||
</span>
|
||||
</t>
|
||||
<h4 class="media-heading"><a t-att-href="'/event/%%s/' %% event_id.id"><span t-field="event_id.name"> </span></a></h4>
|
||||
<t t-call="website.publish"><t t-set="object" t-value="event_id"/></t>
|
||||
<h4 class="media-heading"><a t-attf-href="/event/#{ event.id }/"><span t-field="event.name"> </span></a></h4>
|
||||
<t t-call="website.publish"><t t-set="object" t-value="event"/></t>
|
||||
<div>
|
||||
<span t-field="event_id.type">: </span>
|
||||
<t t-if="event_id.user_id">
|
||||
Organized by: <span t-field="event_id.user_id"> </span>
|
||||
<span t-field="event.type">: </span>
|
||||
<t t-if="event.user_id">
|
||||
Organized by: <span t-field="event.user_id"> </span>
|
||||
</t>
|
||||
</div>
|
||||
<div>
|
||||
<i class="icon-time"></i> <span t-field="event_id.date_begin"> </span> <i>to</i> <span t-field="event_id.date_end"> </span>
|
||||
<i class="icon-time"></i> <span t-field="event.date_begin"> </span> <i>to</i> <span t-field="event.date_end"> </span>
|
||||
</div>
|
||||
<div t-if="event_id.country_id">
|
||||
<i class="icon-map-marker"></i> <span t-field="event_id.city"> </span> <span t-field="event_id.zip"> </span>, <span t-field="event_id.country_id"> </span>
|
||||
<div t-if="event.country_id">
|
||||
<i class="icon-map-marker"></i> <span t-field="event.city"> </span> <span t-field="event.zip"> </span>, <span t-field="event.country_id"> </span>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
@ -89,7 +89,7 @@
|
|||
<li class="nav-header">Category</li>
|
||||
<t t-foreach="types">
|
||||
<li t-if="type" t-att-class="searches.get('type') == str(type and type[0]) and 'active' or ''">
|
||||
<a t-att-href="'/event/%%s&type=%%s' %% (search_path, type[0])"><t t-esc="type[1]"/> <small>(<t t-esc="type_count"/>)</small></a>
|
||||
<a t-attf-href="/event/#{ search_path }&type=#{ type[0] }"><t t-esc="type[1]"/> <small>(<t t-esc="type_count"/>)</small></a>
|
||||
</li>
|
||||
</t>
|
||||
</ul>
|
||||
|
@ -101,7 +101,7 @@
|
|||
<li class="nav-header">Location</li>
|
||||
<t t-foreach="countries">
|
||||
<li t-if="country_id" t-att-class="searches.get('country') == str(country_id and country_id[0]) and 'active' or ''">
|
||||
<a t-att-href="'/event/%%s&country=%%s' %% (search_path, country_id[0])"><t t-esc="country_id[1]"/><small>(<t t-esc="country_id_count"/>)</small></a>
|
||||
<a t-attf-href="/event/#{ search_path }&country=#{ country_id[0] }"><t t-esc="country_id[1]"/><small>(<t t-esc="country_id_count"/>)</small></a>
|
||||
</li>
|
||||
</t>
|
||||
</ul>
|
||||
|
@ -138,7 +138,7 @@
|
|||
<t t-if="event_id.event_ticket_ids">
|
||||
<span t-if="event_id.register_avail == 9999" class="label pull-right">Tickets availables.</span>
|
||||
<span t-if="not event_id.register_avail" class="label pull-right">No ticket available.</span>
|
||||
<span t-if="event_id.register_avail and event_id.register_avail != 9999" t-att-class="'label pull-right label-%%s' %% (event_id.register_avail <= 10 and 'warning' or 'info')">
|
||||
<span t-if="event_id.register_avail and event_id.register_avail != 9999" t-attf-class="label pull-right label-#{ event_id.register_avail <= 10 and 'warning' or 'info' }">
|
||||
<t t-if="event_id.register_avail <= 10">Only</t>
|
||||
<t t-esc="event_id.register_avail"/>
|
||||
<t t-if="event_id.register_avail > 1">tickets </t>
|
||||
|
@ -146,7 +146,7 @@
|
|||
available.
|
||||
</span>
|
||||
</t>
|
||||
<h4 class="media-heading"><a t-att-href="'/event/%%s/' %% event_id.id"><span t-field="event_id.name"> </span></a></h4>
|
||||
<h4 class="media-heading"><a t-attf-href="/event/#{ event_id.id }/"><span t-field="event_id.name"> </span></a></h4>
|
||||
<t t-call="website.publish"><t t-set="object" t-value="event_id"/></t>
|
||||
<h5 class="media-heading">
|
||||
<span t-field="event_id.address_id"/><br/>
|
||||
|
@ -154,7 +154,7 @@
|
|||
<i class="icon-time"></i> <span t-field="event_id.date_end"/>
|
||||
</h5>
|
||||
<h4 t-if="event_id.event_ticket_ids">Ticket Information</h4>
|
||||
<form t-att-action="'/event/%%s/add_cart' %% event_id.id" method="post" t-if="event_id.event_ticket_ids">
|
||||
<form t-attf-action="/event/#{ event_id.id }/add_cart" method="post" t-if="event_id.event_ticket_ids">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
|
@ -172,7 +172,7 @@
|
|||
<td t-field="ticket.price"/>
|
||||
<td><span t-if="ticket.register_max"><t t-esc="ticket.register_current"/>/<t t-field="ticket.register_max"/></span></td>
|
||||
<td>
|
||||
<select t-if="ticket.register_avail" t-att-name="'ticket-%%s' %% ticket.id">
|
||||
<select t-if="ticket.register_avail" t-attf-name="ticket- #{ ticket.id }">
|
||||
<t t-foreach="range(0, ticket.register_avail > 9 and 10 or ticket.register_avail+1 )" t-as="nb"><option t-esc="nb"/></t>
|
||||
</select>
|
||||
<span t-if="not ticket.register_avail">Not ticket available</span>
|
||||
|
|
|
@ -29,20 +29,20 @@
|
|||
</t>
|
||||
<h3>Our team</h3>
|
||||
<div class="thumbnails">
|
||||
<div t-foreach="employee_ids" t-as="employee_id" class="span4 mt16">
|
||||
<div t-foreach="employee_ids" t-as="employee" class="span4 mt16">
|
||||
<div class="media thumbnail">
|
||||
<a class="pull-left" href="#">
|
||||
<img class="media-object" t-att-src="employee_id.img('image_small')"/>
|
||||
<img class="media-object" t-att-src="employee.img('image_small')"/>
|
||||
</a>
|
||||
<div class="media-body">
|
||||
<t t-call="website.publish"><t t-set="object" t-value="employee_id"/></t>
|
||||
<h5 class="media-heading" t-field="employee_id.name"/>
|
||||
<div t-field="employee_id.department_id"/>
|
||||
<div t-field="employee_id.job_id"/>
|
||||
<div t-field="employee_id.work_location"/>
|
||||
<div t-field="employee_id.work_phone"/>
|
||||
<div t-field="employee_id.work_email"/>
|
||||
<div t-field="employee_id.public_info"/>
|
||||
<t t-call="website.publish"><t t-set="object" t-value="employee"/></t>
|
||||
<h5 class="media-heading" t-field="employee.name"/>
|
||||
<div t-field="employee.department_id"/>
|
||||
<div t-field="employee.job_id"/>
|
||||
<div t-field="employee.work_location"/>
|
||||
<div t-field="employee.work_phone"/>
|
||||
<div t-field="employee.work_email"/>
|
||||
<div t-field="employee.public_info"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
<!-- Page -->
|
||||
|
||||
<template id="index" name="Blogs">
|
||||
<template id="index" name="Blogs" page="True">
|
||||
<t t-call="website.layout">
|
||||
<t t-set="head">
|
||||
<script type="text/javascript" src="/website_mail/static/src/js/blog.js"></script>
|
||||
|
@ -34,7 +34,7 @@
|
|||
<div class="container mt48 js_website_mail">
|
||||
<div class="row">
|
||||
<div class="span4" id="left_column">
|
||||
<a t-if="mail_group_id and editable" t-att-href="'/blog/%%s/new' %% mail_group_id" class="btn">Add a new Blog</a>
|
||||
<a t-if="mail_group_id and editable" t-attf-href="/blog/#{ mail_group_id }/new" class="btn">Add a new Blog</a>
|
||||
|
||||
<div id="blog_subscribe">
|
||||
<form action="./subscribe" method="POST" class="form-inline" t-if="not subscribe">
|
||||
|
@ -69,7 +69,7 @@
|
|||
</small>
|
||||
</div>
|
||||
</li>
|
||||
<form id="post" t-att-action="'/blog/%%s/%%s/post#post' %% (blog_id.res_id, blog_id.id)" method="POST" class="form-horizontal text-center" groups="group_website_mail_reply">
|
||||
<form id="post" t-attf-action="/blog/#{ blog_id.res_id }/#{ blog_id.id }/post#post" method="POST" class="form-horizontal text-center" groups="group_website_mail_reply">
|
||||
<textarea rows="4" placeholder="Your comment" class="span7"> </textarea>
|
||||
<button type="submit" class="btn">Post your comment</button>
|
||||
</form>
|
||||
|
@ -80,14 +80,14 @@
|
|||
<div class="span8" t-if="not blog_id and blog_ids">
|
||||
<ul class="media-list">
|
||||
<li t-foreach="blog_ids" t-as="blog" class="media well">
|
||||
<div t-att-class="'media-body %%s' %% (blog.website_published and 'css_published' or '')">
|
||||
<div t-attf-class="media-body #{ 'css_published' if blog.website_published else '' }">
|
||||
<t t-call="website.publish"><t t-set="object" t-value="blog"/></t>
|
||||
<h4 class="media-heading" ><a t-att-href="'/blog/%%s/%%s#comment' %% (blog.res_id, blog.id)" t-field="blog.subject"></a></h4>
|
||||
<h4 class="media-heading" ><a t-attf-href="/blog/#{ blog.res_id }/#{ blog.id }#comment" t-field="blog.subject"></a></h4>
|
||||
<div class="media">
|
||||
<div t-field="blog.body"/>
|
||||
<small class="pull-left muted text-right" t-if="len(blog.child_ids)">
|
||||
<a t-if="len(blog.child_ids) <= 1" t-att-href="'/blog/%%s/%%s#comment' %% (blog.res_id, blog.id)"><t t-esc="len(blog.child_ids)"/> Comment</a>
|
||||
<a t-if="len(blog.child_ids) > 1" t-att-href="'/blog/%%s/%%s#comment' %% (blog.res_id, blog.id)"><t t-esc="len(blog.child_ids)"/> Comments</a>
|
||||
<a t-if="len(blog.child_ids) <= 1" t-attf-href="/blog/#{ blog.res_id }/#{ blog.id }#comment"><t t-esc="len(blog.child_ids)"/> Comment</a>
|
||||
<a t-if="len(blog.child_ids) > 1" t-attf-href="/blog/#{ blog.res_id }/#{ blog.id }#comment"><t t-esc="len(blog.child_ids)"/> Comments</a>
|
||||
</small>
|
||||
<small class="pull-right muted text-right">
|
||||
<div t-field="blog.author_id"/>
|
||||
|
@ -109,7 +109,7 @@
|
|||
<template id="blog_history" inherit_id="website_mail.index" inherit_option_id="website_mail.index" name="History">
|
||||
<xpath expr="//div[@id='left_column']" position="inside">
|
||||
<ul class="nav nav-list">
|
||||
<li class="nav-header"><a t-att-href="'/blog/%%s/' %% mail_group_id">BLOG ARCHIVE</a></li>
|
||||
<li class="nav-header"><a t-attf-href="/blog/#{ mail_group_id }/">BLOG ARCHIVE</a></li>
|
||||
<!-- TODO: check qweb iteration -->
|
||||
<li t-foreach="nav_list" t-as="year" class="js_nav_year">
|
||||
<t t-set="year" t-value="nav_list[year]"/>
|
||||
|
|
|
@ -24,20 +24,10 @@ class website_project(http.Controller):
|
|||
def blog(self, project_id=None, **post):
|
||||
website = request.registry['website']
|
||||
project_obj = request.registry['project.project']
|
||||
task_obj = request.registry['project.task']
|
||||
stage_obj = request.registry['project.task.type']
|
||||
|
||||
project = project_obj.browse(request.cr, request.uid, project_id)
|
||||
|
||||
domain = [('id', 'in', [task.id for task in project.tasks])]
|
||||
stages = task_obj.read_group(request.cr, request.uid, domain, ["id", "stage_id"], groupby="stage_id")
|
||||
for stage in stages:
|
||||
stage['stage_id'] = stage_obj.browse(request.cr, request.uid, stage['stage_id'][0])
|
||||
task_ids = task_obj.search(request.cr, request.uid, stage['__domain'])
|
||||
stage['task_ids'] = task_obj.browse(request.cr, request.uid, task_ids)
|
||||
|
||||
values = website.get_rendering_context({
|
||||
'project_id': project,
|
||||
'stages': stages,
|
||||
})
|
||||
return website.render("website_project.index", values)
|
||||
|
|
|
@ -7,47 +7,40 @@
|
|||
|
||||
<template id="footer_custom" inherit_id="website.layout" name="Custom Footer">
|
||||
<xpath expr="//body/footer//div[@name='info']/ul" position="inside">
|
||||
<li t-foreach="project_ids" t-as="project_id"><a t-attf-href="/project/#{ project_id.id }/"><t t-esc="project_id.name"/></a></li>
|
||||
<li t-foreach="project_ids" t-as="project"><a t-attf-href="/project/#{ project.id }/"><t t-esc="project.name"/></a></li>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- Page -->
|
||||
|
||||
|
||||
<template id="kanban_card" name="Project">
|
||||
<a t-attf-href="/task/#{ object_id.id }/"><span t-field="object_id.name"/></a>
|
||||
<div>
|
||||
Assigned to <span t-field="object_id.user_id"/>
|
||||
</div>
|
||||
<div>
|
||||
<span t-foreach="object_id.categ_ids" t-as="categ_id" class="label">
|
||||
<t t-esc="categ_id.name"/>
|
||||
</span>
|
||||
</div>
|
||||
<small>
|
||||
<i class="icon-time"></i> <span t-field="object_id.date_start"/><br/>
|
||||
<t t-if="object_id.date_end">Ending Date: <span t-field="object_id.date_end"/></t>
|
||||
</small>
|
||||
</template>
|
||||
|
||||
<template id="index" name="Project">
|
||||
<t t-call="website.layout">
|
||||
<t t-set="title">Project</t>
|
||||
<div class="container">
|
||||
<h4 t-field="project_id.name"/>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th t-foreach="stages" t-as="stage">
|
||||
<span t-field="stage_id.name"/>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td t-foreach="stages" t-as="stage">
|
||||
<div t-foreach="task_ids" t-as="task_id" class="thumbnail">
|
||||
<a t-attf-href="/task/#{ task_id.id }/"><span t-field="task_id.name"/></a>
|
||||
<div>
|
||||
Assigned to <span t-field="task_id.user_id"/>
|
||||
</div>
|
||||
<div>
|
||||
<span t-foreach="task_id.categ_ids" t-as="categ_id" class="label">
|
||||
<t t-esc="categ_id.name"/>
|
||||
</span>
|
||||
</div>
|
||||
<small>
|
||||
<i class="icon-time"></i> <span t-field="task_id.date_start"/><br/>
|
||||
<t t-if="task_id.date_end">Ending Date: <span t-field="task_id.date_end"/></t>
|
||||
</small>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<t t-call="website.kanban">
|
||||
<t t-set="model">project.task</t>
|
||||
<t t-set="domain" t-value="[('project_id', '=', project_id.id)]"/>
|
||||
<t t-set="column">stage_id</t>
|
||||
<t t-set="content">website_project.kanban_card</t>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
|
|
@ -93,7 +93,7 @@
|
|||
|
||||
<!-- Product list -->
|
||||
|
||||
<template id="products">
|
||||
<template id="products" page="True">
|
||||
<t t-call="website_sale.layout">
|
||||
<t t-set="title">Product</t>
|
||||
<t t-set="shop_content">
|
||||
|
@ -184,7 +184,7 @@
|
|||
|
||||
<!-- Page Shop my cart -->
|
||||
|
||||
<template id="mycart" name="My cart">
|
||||
<template id="mycart" name="My cart" page="True">
|
||||
<t t-call="website_sale.layout">
|
||||
<t t-set="title">My cart</t>
|
||||
<t t-set="shop_content">
|
||||
|
@ -269,18 +269,18 @@
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<t t-foreach="suggested_products" t-as="product_id">
|
||||
<t t-foreach="suggested_products" t-as="product">
|
||||
<tr>
|
||||
<td>
|
||||
<a t-attf-href="/shop/product/#{ product_id.id }/"><span t-field="product_id.name"/></a><br/>
|
||||
<small t-field="product_id.description_sale"/>
|
||||
<a t-attf-href="/shop/product/#{ product.id }/"><span t-field="product.name"/></a><br/>
|
||||
<small t-field="product.description_sale"/>
|
||||
</td>
|
||||
<td>
|
||||
<span t-field="product_id.list_price"></span>€
|
||||
<span t-field="product.list_price"></span>€
|
||||
</td>
|
||||
<td>
|
||||
<div class="pull-right">
|
||||
<a t-attf-href="./add_cart/#{ product_id.id }/" class="btn btn-small btn-success">+</a>
|
||||
<a t-attf-href="./add_cart/#{ product.id }/" class="btn btn-small btn-success">+</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -356,7 +356,7 @@
|
|||
</div>
|
||||
<form class="span8 form-horizontal" action="/shop/confirm_order/" method="post">
|
||||
<div class=" row">
|
||||
<a t-if="not partner" t-att-href="'/admin#action=redirect&url=%%s/shop/checkout/' %% host_url" class="btn btn-primary">Log me, I have an account</a>
|
||||
<a t-if="not partner" t-attf-href="/admin#action=redirect&url=#{ host_url }/shop/checkout/" class="btn btn-primary">Log me, I have an account</a>
|
||||
<h3 class="span8">Billing Information</h3>
|
||||
<div t-attf-class="control-group #{error.get('name', '')}">
|
||||
<label class="control-label" for="contact_name">Name and firstname</label>
|
||||
|
|
Loading…
Reference in New Issue