[MERGE] forward port branch saas-16 up to 09d698d05f
This commit is contained in:
@@ -30,5 +30,6 @@ class ResPartner(models.Model):
|
||||
if partner_id: # Modifying existing partner
|
||||
self.browse(partner_id).write(partner)
|
||||
else:
|
||||
partner['lang'] = self.env.user.lang
|
||||
partner_id = self.create(partner).id
|
||||
return partner_id
|
||||
|
||||
@@ -645,7 +645,7 @@ class StockMove(models.Model):
|
||||
(move.picking_id.picking_type_id.use_existing_lots or move.picking_id.picking_type_id.use_create_lots) and \
|
||||
move.product_id.tracking != 'none' and \
|
||||
not (move_line and (move_line.product_id and move_line.pack_lot_ids)) or (move_line and not move_line.product_id):
|
||||
raise UserError(_('You need to provide a Lot/Serial Number for product %s') % move.product_id.name)
|
||||
raise UserError(_('You need to provide a Lot/Serial Number for product %s') % ("%s (%s)" % (move.product_id.name, move.picking_id.name)))
|
||||
|
||||
def _prepare_move_line_vals(self, quantity=None, reserved_quant=None):
|
||||
self.ensure_one()
|
||||
|
||||
@@ -1016,8 +1016,8 @@ class Binary(http.Controller):
|
||||
elif status != 200 and download:
|
||||
return request.not_found()
|
||||
|
||||
height = int(height)
|
||||
width = int(width)
|
||||
height = int(height or 0)
|
||||
width = int(width or 0)
|
||||
if content and (width or height):
|
||||
# resize maximum 500*500
|
||||
if width > 500:
|
||||
|
||||
@@ -330,11 +330,12 @@ return AbstractRenderer.extend({
|
||||
}
|
||||
element.find('.fc-content .fc-time').text(display_hour);
|
||||
},
|
||||
height: 'auto',
|
||||
height: 'parent',
|
||||
unselectAuto: false,
|
||||
});
|
||||
|
||||
this.$calendar.fullCalendar(fc_options);
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
},
|
||||
/**
|
||||
* Initialize the mini calendar in the sidebar
|
||||
|
||||
@@ -114,18 +114,20 @@ var FormRenderer = BasicRenderer.extend({
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Disable stat buttons so that they can't be clicked anymore
|
||||
* Disable statusbar buttons and stat buttons so that they can't be clicked anymore
|
||||
*
|
||||
*/
|
||||
disableButtons: function() {
|
||||
this.$('.oe_button_box button').attr('disabled', true);
|
||||
this.$('.o_statusbar_buttons button, .oe_button_box button')
|
||||
.attr('disabled', true);
|
||||
},
|
||||
/**
|
||||
* Enable stat buttons so they can be clicked again
|
||||
* Enable statusbar buttons and stat buttons so they can be clicked again
|
||||
*
|
||||
*/
|
||||
enableButtons: function() {
|
||||
this.$('.oe_button_box button').removeAttr('disabled');
|
||||
this.$('.o_statusbar_buttons button, .oe_button_box button')
|
||||
.removeAttr('disabled');
|
||||
},
|
||||
/**
|
||||
* returns the active tab pages for each notebook
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
*/
|
||||
|
||||
// No content helper
|
||||
.o_view_manager_content > div {
|
||||
height: 100%;
|
||||
}
|
||||
.oe_view_nocontent {
|
||||
a {
|
||||
cursor: pointer;
|
||||
|
||||
@@ -981,6 +981,37 @@ QUnit.module('Views', {
|
||||
calendar.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('ensure calendar adapts to screen size', function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
// We want to be able to restore changes on 'body'
|
||||
var bodyStyle = $('body').attr('style');
|
||||
|
||||
// Force the view height to be smaller than the natural calendar height
|
||||
// (FullCalendar requires that the height be modified on body not $target)
|
||||
var height = 500;
|
||||
$('body').height(height);
|
||||
|
||||
var calendar = createView({
|
||||
View: CalendarView,
|
||||
model: 'event',
|
||||
data: this.data,
|
||||
arch: '<calendar mode="week" date_start="start" />',
|
||||
});
|
||||
|
||||
var $scroller = calendar.$('.fc-scroller')
|
||||
assert.strictEqual($scroller.height() < height, true,
|
||||
"the scroller should be smaller than the view height");
|
||||
assert.strictEqual($scroller.prop('scrollHeight') > height, true,
|
||||
"the scroller should have a scrollbar");
|
||||
calendar.destroy();
|
||||
|
||||
$('body').removeAttr('style');
|
||||
if (bodyStyle) {
|
||||
$('body').attr('style', bodyStyle);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -4946,8 +4946,8 @@ QUnit.module('Views', {
|
||||
_t.database.multi_lang = multi_lang;
|
||||
});
|
||||
|
||||
QUnit.test('buttons are disabled until action is resolved', function (assert) {
|
||||
assert.expect(3);
|
||||
QUnit.test('buttons are disabled until status bar action is resolved', function (assert) {
|
||||
assert.expect(9);
|
||||
|
||||
var def = $.Deferred();
|
||||
|
||||
@@ -4956,6 +4956,10 @@ QUnit.module('Views', {
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch: '<form string="Partners">' +
|
||||
'<header>' +
|
||||
'<button name="post" class="p" string="Confirm" type="object"/>' +
|
||||
'<button name="some_method" class="s" string="Do it" type="object"/>' +
|
||||
'</header>' +
|
||||
'<sheet>' +
|
||||
'<div name="button_box" class="oe_button_box">' +
|
||||
'<button class="oe_stat_button">' +
|
||||
@@ -4977,18 +4981,94 @@ QUnit.module('Views', {
|
||||
},
|
||||
});
|
||||
|
||||
assert.notOk(form.$('.oe_button_box button').attr('disabled'),
|
||||
assert.strictEqual(form.$buttons.find('button:not(:disabled)').length, 4,
|
||||
"control panel buttons should be enabled");
|
||||
assert.strictEqual(form.$('.o_form_statusbar button:not(:disabled)').length, 2,
|
||||
"status bar buttons should be enabled");
|
||||
assert.strictEqual(form.$('.oe_button_box button:not(:disabled)').length, 1,
|
||||
"stat buttons should be enabled");
|
||||
|
||||
form.$('.o_form_statusbar button').click();
|
||||
|
||||
// The unresolved deferred lets us check the state of the buttons
|
||||
assert.strictEqual(form.$buttons.find('button:disabled').length, 4,
|
||||
"control panel buttons should be disabled");
|
||||
assert.strictEqual(form.$('.o_form_statusbar button:disabled').length, 2,
|
||||
"status bar buttons should be disabled");
|
||||
assert.strictEqual(form.$('.oe_button_box button:disabled').length, 1,
|
||||
"stat buttons should be disabled");
|
||||
|
||||
def.resolve();
|
||||
|
||||
assert.strictEqual(form.$buttons.find('button:not(:disabled)').length, 4,
|
||||
"control panel buttons should be enabled");
|
||||
assert.strictEqual(form.$('.o_form_statusbar button:not(:disabled)').length, 2,
|
||||
"status bar buttons should be enabled");
|
||||
assert.strictEqual(form.$('.oe_button_box button:not(:disabled)').length, 1,
|
||||
"stat buttons should be enabled");
|
||||
|
||||
form.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('buttons are disabled until button box action is resolved', function (assert) {
|
||||
assert.expect(9);
|
||||
|
||||
var def = $.Deferred();
|
||||
|
||||
var form = createView({
|
||||
View: FormView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch: '<form string="Partners">' +
|
||||
'<header>' +
|
||||
'<button name="post" class="p" string="Confirm" type="object"/>' +
|
||||
'<button name="some_method" class="s" string="Do it" type="object"/>' +
|
||||
'</header>' +
|
||||
'<sheet>' +
|
||||
'<div name="button_box" class="oe_button_box">' +
|
||||
'<button class="oe_stat_button">' +
|
||||
'<field name="bar"/>' +
|
||||
'</button>' +
|
||||
'</div>' +
|
||||
'<group>' +
|
||||
'<field name="foo"/>' +
|
||||
'</group>' +
|
||||
'</sheet>' +
|
||||
'</form>',
|
||||
res_id: 1,
|
||||
intercepts: {
|
||||
execute_action: function (event) {
|
||||
return def.then(function() {
|
||||
event.data.on_success();
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
assert.strictEqual(form.$buttons.find('button:not(:disabled)').length, 4,
|
||||
"control panel buttons should be enabled");
|
||||
assert.strictEqual(form.$('.o_form_statusbar button:not(:disabled)').length, 2,
|
||||
"status bar buttons should be enabled");
|
||||
assert.strictEqual(form.$('.oe_button_box button:not(:disabled)').length, 1,
|
||||
"stat buttons should be enabled");
|
||||
|
||||
form.$('.oe_button_box button').click();
|
||||
|
||||
// The unresolved deferred lets us check the state of the buttons
|
||||
assert.ok(form.$('.oe_button_box button').attr('disabled'),
|
||||
assert.strictEqual(form.$buttons.find('button:disabled').length, 4,
|
||||
"control panel buttons should be disabled");
|
||||
assert.strictEqual(form.$('.o_form_statusbar button:disabled').length, 2,
|
||||
"status bar buttons should be disabled");
|
||||
assert.strictEqual(form.$('.oe_button_box button:disabled').length, 1,
|
||||
"stat buttons should be disabled");
|
||||
|
||||
def.resolve();
|
||||
|
||||
assert.notOk(form.$('.oe_button_box button').attr('disabled'),
|
||||
assert.strictEqual(form.$buttons.find('button:not(:disabled)').length, 4,
|
||||
"control panel buttons should be enabled");
|
||||
assert.strictEqual(form.$('.o_form_statusbar button:not(:disabled)').length, 2,
|
||||
"status bar buttons should be enabled");
|
||||
assert.strictEqual(form.$('.oe_button_box button:not(:disabled)').length, 1,
|
||||
"stat buttons should be enabled");
|
||||
|
||||
form.destroy();
|
||||
|
||||
@@ -366,7 +366,10 @@ class Slide(models.Model):
|
||||
if slide.id: # avoid to perform a slug on a not yet saved record in case of an onchange.
|
||||
# link_tracker is not in dependencies, so use it to shorten url only if installed.
|
||||
if self.env.registry.get('link.tracker'):
|
||||
url = self.env['link.tracker'].sudo().create({'url': '%s/slides/slide/%s' % (base_url, slug(slide))}).short_url
|
||||
url = self.env['link.tracker'].sudo().create({
|
||||
'url': '%s/slides/slide/%s' % (base_url, slug(slide)),
|
||||
'title': slide.name,
|
||||
}).short_url
|
||||
else:
|
||||
url = '%s/slides/slide/%s' % (base_url, slug(slide))
|
||||
slide.website_url = url
|
||||
|
||||
@@ -21,6 +21,8 @@ import threading
|
||||
import traceback
|
||||
import time
|
||||
|
||||
from psycopg2 import ProgrammingError, errorcodes
|
||||
|
||||
import odoo
|
||||
|
||||
from . import Command
|
||||
@@ -136,6 +138,15 @@ def main(args):
|
||||
for db_name in preload:
|
||||
try:
|
||||
odoo.service.db._create_empty_database(db_name)
|
||||
except ProgrammingError as err:
|
||||
if err.pgcode == errorcodes.INSUFFICIENT_PRIVILEGE:
|
||||
# We use an INFO loglevel on purpose in order to avoid
|
||||
# reporting unnecessary warnings on build environment
|
||||
# using restricted database access.
|
||||
_logger.info("Could not determine if database %s exists, "
|
||||
"skipping auto-creation: %s", db_name, err)
|
||||
else:
|
||||
raise err
|
||||
except odoo.service.db.DatabaseExists:
|
||||
pass
|
||||
|
||||
|
||||
Reference in New Issue
Block a user