Added Upstream Patch for web, website
This commit is contained in:
parent
750aef6e5f
commit
da5b6d7dbf
@ -1542,6 +1542,8 @@ class ExcelExport(ExportFormat, http.Controller):
|
|||||||
|
|
||||||
if isinstance(cell_value, pycompat.string_types):
|
if isinstance(cell_value, pycompat.string_types):
|
||||||
cell_value = re.sub("\r", " ", pycompat.to_text(cell_value))
|
cell_value = re.sub("\r", " ", pycompat.to_text(cell_value))
|
||||||
|
# Excel supports a maximum of 32767 characters in each cell:
|
||||||
|
cell_value = cell_value[:32767]
|
||||||
elif isinstance(cell_value, datetime.datetime):
|
elif isinstance(cell_value, datetime.datetime):
|
||||||
cell_style = datetime_style
|
cell_style = datetime_style
|
||||||
elif isinstance(cell_value, datetime.date):
|
elif isinstance(cell_value, datetime.date):
|
||||||
|
@ -26,7 +26,7 @@ class Http(models.AbstractModel):
|
|||||||
"session_id": request.session.sid,
|
"session_id": request.session.sid,
|
||||||
"uid": request.session.uid,
|
"uid": request.session.uid,
|
||||||
"is_system": request.env.user._is_system(),
|
"is_system": request.env.user._is_system(),
|
||||||
"is_superuser": request.env.user._is_superuser(),
|
"is_superuser": request.env.user._is_superuser() if request.session.uid else False,
|
||||||
"user_context": request.session.get_context() if request.session.uid else {},
|
"user_context": request.session.get_context() if request.session.uid else {},
|
||||||
"db": request.session.db,
|
"db": request.session.db,
|
||||||
"server_version": version_info.get('server_version'),
|
"server_version": version_info.get('server_version'),
|
||||||
@ -36,7 +36,7 @@ class Http(models.AbstractModel):
|
|||||||
"company_id": request.env.user.company_id.id if request.session.uid else None,
|
"company_id": request.env.user.company_id.id if request.session.uid else None,
|
||||||
"partner_id": request.env.user.partner_id.id if request.session.uid and request.env.user.partner_id else None,
|
"partner_id": request.env.user.partner_id.id if request.session.uid and request.env.user.partner_id else None,
|
||||||
"user_companies": {'current_company': (user.company_id.id, user.company_id.name), 'allowed_companies': [(comp.id, comp.name) for comp in user.company_ids]} if display_switch_company_menu else False,
|
"user_companies": {'current_company': (user.company_id.id, user.company_id.name), 'allowed_companies': [(comp.id, comp.name) for comp in user.company_ids]} if display_switch_company_menu else False,
|
||||||
"currencies": self.get_currencies(),
|
"currencies": self.get_currencies() if request.session.uid else {},
|
||||||
"web.base.url": self.env['ir.config_parameter'].sudo().get_param('web.base.url', default=''),
|
"web.base.url": self.env['ir.config_parameter'].sudo().get_param('web.base.url', default=''),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,14 +260,15 @@ var QueryGroup = Class.extend({
|
|||||||
|
|
||||||
var count_key = (grouping_fields[0] && grouping_fields[0].split(':')[0]) + '_count';
|
var count_key = (grouping_fields[0] && grouping_fields[0].split(':')[0]) + '_count';
|
||||||
var aggregates = {};
|
var aggregates = {};
|
||||||
_(fixed_group).each(function (value, key) {
|
for (var key in fixed_group) {
|
||||||
if (key.indexOf('__') === 0
|
if (fixed_group.hasOwnProperty(key)) {
|
||||||
|
if (!(key.indexOf('__') === 0
|
||||||
|| _.contains(grouping_fields, key)
|
|| _.contains(grouping_fields, key)
|
||||||
|| (key === count_key)) {
|
|| (key === count_key))) {
|
||||||
return;
|
aggregates[key] = fixed_group[key] || 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
aggregates[key] = value || 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
this.model = new Model(
|
this.model = new Model(
|
||||||
model, fixed_group.__context, fixed_group.__domain);
|
model, fixed_group.__context, fixed_group.__domain);
|
||||||
|
@ -814,7 +814,8 @@ var BasicModel = AbstractModel.extend({
|
|||||||
return this.mutex.exec(this._applyChange.bind(this, record_id, changes, options));
|
return this.mutex.exec(this._applyChange.bind(this, record_id, changes, options));
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* Reload all data for a given resource
|
* Reload all data for a given resource. At any time there is at most one
|
||||||
|
* reload operation active.
|
||||||
*
|
*
|
||||||
* @param {string} id local id for a resource
|
* @param {string} id local id for a resource
|
||||||
* @param {Object} [options]
|
* @param {Object} [options]
|
||||||
@ -823,64 +824,7 @@ var BasicModel = AbstractModel.extend({
|
|||||||
* @returns {Deferred<string>} resolves to the id of the resource
|
* @returns {Deferred<string>} resolves to the id of the resource
|
||||||
*/
|
*/
|
||||||
reload: function (id, options) {
|
reload: function (id, options) {
|
||||||
options = options || {};
|
return this.mutex.exec(this._reload.bind(this, id, options));
|
||||||
var element = this.localData[id];
|
|
||||||
|
|
||||||
if (element.type === 'record') {
|
|
||||||
if (!options.currentId && (('currentId' in options) || this.isNew(id))) {
|
|
||||||
var params = {
|
|
||||||
context: element.context,
|
|
||||||
fieldsInfo: element.fieldsInfo,
|
|
||||||
fields: element.fields,
|
|
||||||
viewType: element.viewType,
|
|
||||||
};
|
|
||||||
return this._makeDefaultRecord(element.model, params);
|
|
||||||
}
|
|
||||||
if (!options.keepChanges) {
|
|
||||||
this.discardChanges(id, {rollback: false});
|
|
||||||
}
|
|
||||||
} else if (element._changes) {
|
|
||||||
delete element.tempLimitIncrement;
|
|
||||||
_.each(element._changes, function (change) {
|
|
||||||
delete change.isNew;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.context !== undefined) {
|
|
||||||
element.context = options.context;
|
|
||||||
}
|
|
||||||
if (options.domain !== undefined) {
|
|
||||||
element.domain = options.domain;
|
|
||||||
}
|
|
||||||
if (options.groupBy !== undefined) {
|
|
||||||
element.groupedBy = options.groupBy;
|
|
||||||
}
|
|
||||||
if (options.limit !== undefined) {
|
|
||||||
element.limit = options.limit;
|
|
||||||
}
|
|
||||||
if (options.offset !== undefined) {
|
|
||||||
this._setOffset(element.id, options.offset);
|
|
||||||
}
|
|
||||||
if (options.loadMoreOffset !== undefined) {
|
|
||||||
element.loadMoreOffset = options.loadMoreOffset;
|
|
||||||
} else {
|
|
||||||
// reset if not specified
|
|
||||||
element.loadMoreOffset = 0;
|
|
||||||
}
|
|
||||||
if (options.currentId !== undefined) {
|
|
||||||
element.res_id = options.currentId;
|
|
||||||
}
|
|
||||||
if (options.ids !== undefined) {
|
|
||||||
element.res_ids = options.ids;
|
|
||||||
element.count = element.res_ids.length;
|
|
||||||
}
|
|
||||||
if (element.type === 'record') {
|
|
||||||
element.offset = _.indexOf(element.res_ids, element.res_id);
|
|
||||||
}
|
|
||||||
var loadOptions = _.pick(options, 'fieldNames', 'viewType');
|
|
||||||
return this._load(element, loadOptions).then(function (result) {
|
|
||||||
return result.id;
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* In some case, we may need to remove an element from a list, without going
|
* In some case, we may need to remove an element from a list, without going
|
||||||
@ -2916,13 +2860,10 @@ var BasicModel = AbstractModel.extend({
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
changes = this._generateChanges(relRecord, options);
|
changes = this._generateChanges(relRecord, options);
|
||||||
if (changes.id) {
|
if (!this.isNew(relRecord.id)) {
|
||||||
// the subrecord already exists in db
|
// the subrecord already exists in db
|
||||||
delete changes.id;
|
|
||||||
if (this.isNew(record.id)) {
|
|
||||||
// if the main record is new, link the subrecord to it
|
|
||||||
commands[fieldName].push(x2ManyCommands.link_to(relRecord.res_id));
|
commands[fieldName].push(x2ManyCommands.link_to(relRecord.res_id));
|
||||||
}
|
delete changes.id;
|
||||||
if (!_.isEmpty(changes)) {
|
if (!_.isEmpty(changes)) {
|
||||||
commands[fieldName].push(x2ManyCommands.update(relRecord.res_id, changes));
|
commands[fieldName].push(x2ManyCommands.update(relRecord.res_id, changes));
|
||||||
}
|
}
|
||||||
@ -4008,6 +3949,76 @@ var BasicModel = AbstractModel.extend({
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* Reload all data for a given resource
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {string} id local id for a resource
|
||||||
|
* @param {Object} [options]
|
||||||
|
* @param {boolean} [options.keepChanges=false] if true, doesn't discard the
|
||||||
|
* changes on the record before reloading it
|
||||||
|
* @returns {Deferred<string>} resolves to the id of the resource
|
||||||
|
*/
|
||||||
|
_reload: function (id, options) {
|
||||||
|
options = options || {};
|
||||||
|
var element = this.localData[id];
|
||||||
|
|
||||||
|
if (element.type === 'record') {
|
||||||
|
if (!options.currentId && (('currentId' in options) || this.isNew(id))) {
|
||||||
|
var params = {
|
||||||
|
context: element.context,
|
||||||
|
fieldsInfo: element.fieldsInfo,
|
||||||
|
fields: element.fields,
|
||||||
|
viewType: element.viewType,
|
||||||
|
};
|
||||||
|
return this._makeDefaultRecord(element.model, params);
|
||||||
|
}
|
||||||
|
if (!options.keepChanges) {
|
||||||
|
this.discardChanges(id, {rollback: false});
|
||||||
|
}
|
||||||
|
} else if (element._changes) {
|
||||||
|
delete element.tempLimitIncrement;
|
||||||
|
_.each(element._changes, function (change) {
|
||||||
|
delete change.isNew;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.context !== undefined) {
|
||||||
|
element.context = options.context;
|
||||||
|
}
|
||||||
|
if (options.domain !== undefined) {
|
||||||
|
element.domain = options.domain;
|
||||||
|
}
|
||||||
|
if (options.groupBy !== undefined) {
|
||||||
|
element.groupedBy = options.groupBy;
|
||||||
|
}
|
||||||
|
if (options.limit !== undefined) {
|
||||||
|
element.limit = options.limit;
|
||||||
|
}
|
||||||
|
if (options.offset !== undefined) {
|
||||||
|
this._setOffset(element.id, options.offset);
|
||||||
|
}
|
||||||
|
if (options.loadMoreOffset !== undefined) {
|
||||||
|
element.loadMoreOffset = options.loadMoreOffset;
|
||||||
|
} else {
|
||||||
|
// reset if not specified
|
||||||
|
element.loadMoreOffset = 0;
|
||||||
|
}
|
||||||
|
if (options.currentId !== undefined) {
|
||||||
|
element.res_id = options.currentId;
|
||||||
|
}
|
||||||
|
if (options.ids !== undefined) {
|
||||||
|
element.res_ids = options.ids;
|
||||||
|
element.count = element.res_ids.length;
|
||||||
|
}
|
||||||
|
if (element.type === 'record') {
|
||||||
|
element.offset = _.indexOf(element.res_ids, element.res_id);
|
||||||
|
}
|
||||||
|
var loadOptions = _.pick(options, 'fieldNames', 'viewType');
|
||||||
|
return this._load(element, loadOptions).then(function (result) {
|
||||||
|
return result.id;
|
||||||
|
});
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* Allows to save a value in the specialData cache associated to a given
|
* Allows to save a value in the specialData cache associated to a given
|
||||||
* record and fieldName. If the value in the cache was already the given
|
* record and fieldName. If the value in the cache was already the given
|
||||||
|
@ -841,8 +841,16 @@ ListRenderer.include({
|
|||||||
*/
|
*/
|
||||||
_onTrashIconClick: function (event) {
|
_onTrashIconClick: function (event) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
var id = $(event.target).closest('tr').data('id');
|
var $row = $(event.target).closest('tr')
|
||||||
|
var id = $row.data('id');
|
||||||
|
if ($row.hasClass('o_selected_row')) {
|
||||||
this.trigger_up('list_record_delete', {id: id});
|
this.trigger_up('list_record_delete', {id: id});
|
||||||
|
} else {
|
||||||
|
var self = this;
|
||||||
|
this.unselectRow().then(function () {
|
||||||
|
self.trigger_up('list_record_delete', {id: id});
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* When a click happens outside the list view, or outside a currently
|
* When a click happens outside the list view, or outside a currently
|
||||||
|
@ -3206,6 +3206,136 @@ QUnit.module('relational_fields', {
|
|||||||
form.destroy();
|
form.destroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
QUnit.test('onchange for embedded one2many in a one2many with a second page', function (assert) {
|
||||||
|
assert.expect(1);
|
||||||
|
|
||||||
|
this.data.turtle.fields.partner_ids.type = 'one2many';
|
||||||
|
this.data.turtle.records[0].partner_ids = [1];
|
||||||
|
// we need a second page, so we set two records and only display one per page
|
||||||
|
this.data.partner.records[0].turtles = [1, 2];
|
||||||
|
|
||||||
|
this.data.partner.onchanges = {
|
||||||
|
turtles: function (obj) {
|
||||||
|
obj.turtles = [
|
||||||
|
[5],
|
||||||
|
[1, 1, {
|
||||||
|
turtle_foo: "hop",
|
||||||
|
partner_ids: [[5], [4, 1]],
|
||||||
|
}],
|
||||||
|
[1, 2, {
|
||||||
|
turtle_foo: "blip",
|
||||||
|
partner_ids: [[5], [4, 2], [4, 4]],
|
||||||
|
}],
|
||||||
|
];
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
var form = createView({
|
||||||
|
View: FormView,
|
||||||
|
model: 'partner',
|
||||||
|
data: this.data,
|
||||||
|
arch:'<form string="Partners">' +
|
||||||
|
'<field name="turtles">' +
|
||||||
|
'<tree editable="bottom" limit="1">' +
|
||||||
|
'<field name="turtle_foo"/>' +
|
||||||
|
'<field name="partner_ids" widget="many2many_tags"/>' +
|
||||||
|
'</tree>' +
|
||||||
|
'</field>' +
|
||||||
|
'</form>',
|
||||||
|
res_id: 1,
|
||||||
|
mockRPC: function (route, args) {
|
||||||
|
if (args.method === 'write') {
|
||||||
|
var expectedResultTurtles = [
|
||||||
|
[1, 1, {
|
||||||
|
turtle_foo: "hop",
|
||||||
|
}],
|
||||||
|
[1, 2, {
|
||||||
|
partner_ids: [[4, 2, false], [4, 4, false]],
|
||||||
|
turtle_foo: "blip",
|
||||||
|
}],
|
||||||
|
];
|
||||||
|
assert.deepEqual(args.args[1].turtles, expectedResultTurtles,
|
||||||
|
"the right values should be written");
|
||||||
|
}
|
||||||
|
return this._super.apply(this, arguments);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
form.$buttons.find('.o_form_button_edit').click();
|
||||||
|
form.$('.o_data_cell').eq(1).click();
|
||||||
|
var $cell = form.$('.o_selected_row .o_input[name=turtle_foo]');
|
||||||
|
$cell.val("hop").trigger('change');
|
||||||
|
form.$buttons.find('.o_form_button_save').click();
|
||||||
|
|
||||||
|
form.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('onchange for embedded one2many in a one2many updated by server', function (assert) {
|
||||||
|
// here we test that after an onchange, the embedded one2many field has
|
||||||
|
// been updated by a new list of ids by the server response, to this new
|
||||||
|
// list should be correctly sent back at save time
|
||||||
|
assert.expect(3);
|
||||||
|
|
||||||
|
this.data.turtle.fields.partner_ids.type = 'one2many';
|
||||||
|
this.data.partner.records[0].turtles = [2];
|
||||||
|
this.data.turtle.records[1].partner_ids = [2];
|
||||||
|
|
||||||
|
this.data.partner.onchanges = {
|
||||||
|
turtles: function (obj) {
|
||||||
|
obj.turtles = [
|
||||||
|
[5],
|
||||||
|
[1, 2, {
|
||||||
|
turtle_foo: "hop",
|
||||||
|
partner_ids: [[5], [4, 2], [4, 4]],
|
||||||
|
}],
|
||||||
|
];
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
var form = createView({
|
||||||
|
View: FormView,
|
||||||
|
model: 'partner',
|
||||||
|
data: this.data,
|
||||||
|
arch:'<form string="Partners">' +
|
||||||
|
'<field name="turtles">' +
|
||||||
|
'<tree editable="bottom">' +
|
||||||
|
'<field name="turtle_foo"/>' +
|
||||||
|
'<field name="partner_ids" widget="many2many_tags"/>' +
|
||||||
|
'</tree>' +
|
||||||
|
'</field>' +
|
||||||
|
'</form>',
|
||||||
|
res_id: 1,
|
||||||
|
mockRPC: function (route, args) {
|
||||||
|
if (route === '/web/dataset/call_kw/partner/write') {
|
||||||
|
var expectedResultTurtles = [
|
||||||
|
[1, 2, {
|
||||||
|
partner_ids: [[4, 2, false], [4, 4, false]],
|
||||||
|
turtle_foo: "hop",
|
||||||
|
}],
|
||||||
|
];
|
||||||
|
assert.deepEqual(args.args[1].turtles, expectedResultTurtles,
|
||||||
|
'The right values should be written');
|
||||||
|
}
|
||||||
|
return this._super.apply(this, arguments);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.deepEqual(form.$('.o_many2many_tags_cell').text().trim(), "second record",
|
||||||
|
"the partner_ids should be as specified at initialization");
|
||||||
|
|
||||||
|
form.$buttons.find('.o_form_button_edit').click();
|
||||||
|
form.$('.o_data_cell').eq(1).click();
|
||||||
|
var $cell = form.$('.o_selected_row .o_input[name=turtle_foo]');
|
||||||
|
$cell.val("hop").trigger("change");
|
||||||
|
form.$buttons.find('.o_form_button_save').click();
|
||||||
|
|
||||||
|
assert.deepEqual(form.$('.o_many2many_tags_cell').text().trim().split(/\s+/),
|
||||||
|
[ "second", "record", "aaa" ],
|
||||||
|
'The partner_ids should have been updated');
|
||||||
|
|
||||||
|
form.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
QUnit.test('onchange for embedded one2many with handle widget', function (assert) {
|
QUnit.test('onchange for embedded one2many with handle widget', function (assert) {
|
||||||
assert.expect(2);
|
assert.expect(2);
|
||||||
|
|
||||||
|
@ -3067,6 +3067,42 @@ QUnit.module('Views', {
|
|||||||
form.destroy();
|
form.destroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
QUnit.test('delete a line in a one2many while editing another line triggers a warning', function (assert) {
|
||||||
|
assert.expect(3);
|
||||||
|
|
||||||
|
this.data.partner.records[0].p = [1, 2];
|
||||||
|
|
||||||
|
var form = createView({
|
||||||
|
View: FormView,
|
||||||
|
model: 'partner',
|
||||||
|
data: this.data,
|
||||||
|
arch: '<form>' +
|
||||||
|
'<field name="p">' +
|
||||||
|
'<tree editable="bottom">' +
|
||||||
|
'<field name="display_name" required="True"/>' +
|
||||||
|
'</tree>' +
|
||||||
|
'</field>' +
|
||||||
|
'</form>',
|
||||||
|
res_id: 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
form.$buttons.find('.o_form_button_edit').click();
|
||||||
|
form.$('.o_data_cell').first().click(); // edit first row
|
||||||
|
form.$('input').val('').trigger('input');
|
||||||
|
form.$('.fa-trash-o').eq(1).click(); // delete second row
|
||||||
|
|
||||||
|
assert.strictEqual($('.modal').find('.modal-title').first().text(), "Warning",
|
||||||
|
"Clicking out of a dirty line while editing should trigger a warning modal.");
|
||||||
|
|
||||||
|
$('.modal').find('.btn-primary').click(); // discard changes
|
||||||
|
|
||||||
|
assert.strictEqual(form.$('.o_data_cell').first().text(), "first record",
|
||||||
|
"Value should have been reset to what it was before editing began.");
|
||||||
|
assert.strictEqual(form.$('.o_data_row').length, 1,
|
||||||
|
"The other line should have been deleted.");
|
||||||
|
form.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
QUnit.test('properly apply onchange on many2many fields', function (assert) {
|
QUnit.test('properly apply onchange on many2many fields', function (assert) {
|
||||||
assert.expect(14);
|
assert.expect(14);
|
||||||
|
|
||||||
|
@ -2840,6 +2840,56 @@ QUnit.module('Views', {
|
|||||||
testUtils.unpatch(mixins.ParentedMixin);
|
testUtils.unpatch(mixins.ParentedMixin);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
QUnit.test('grouped kanban becomes ungrouped when clearing domain then clearing groupby', function (assert) {
|
||||||
|
// in this test, we simulate that clearing the domain is slow, so that
|
||||||
|
// clearing the groupby does not corrupt the data handled while
|
||||||
|
// reloading the kanban view.
|
||||||
|
assert.expect(4);
|
||||||
|
|
||||||
|
var def = $.Deferred();
|
||||||
|
|
||||||
|
var kanban = createView({
|
||||||
|
View: KanbanView,
|
||||||
|
model: 'partner',
|
||||||
|
data: this.data,
|
||||||
|
arch: '<kanban class="o_kanban_test">' +
|
||||||
|
'<field name="bar"/>' +
|
||||||
|
'<templates><t t-name="kanban-box">' +
|
||||||
|
'<div><field name="foo"/></div>' +
|
||||||
|
'</t></templates></kanban>',
|
||||||
|
domain: [['foo', '=', 'norecord']],
|
||||||
|
groupBy: ['bar'],
|
||||||
|
mockRPC: function (route, args) {
|
||||||
|
var result = this._super(route, args);
|
||||||
|
if (args.method === 'read_group') {
|
||||||
|
var isFirstUpdate = _.isEmpty(args.kwargs.domain) &&
|
||||||
|
args.kwargs.groupby &&
|
||||||
|
args.kwargs.groupby[0] === 'bar';
|
||||||
|
if (isFirstUpdate) {
|
||||||
|
return def.then(_.constant(result));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.ok(kanban.$('.o_kanban_view').hasClass('o_kanban_grouped'),
|
||||||
|
"the kanban view should be grouped");
|
||||||
|
assert.notOk(kanban.$('.o_kanban_view').hasClass('o_kanban_ungrouped'),
|
||||||
|
"the kanban view should not be ungrouped");
|
||||||
|
|
||||||
|
kanban.update({domain: []}); // 1st update on kanban view
|
||||||
|
kanban.update({groupBy: false}); // 2n update on kanban view
|
||||||
|
def.resolve(); // simulate slow 1st update of kanban view
|
||||||
|
|
||||||
|
assert.notOk(kanban.$('.o_kanban_view').hasClass('o_kanban_grouped'),
|
||||||
|
"the kanban view should not longer be grouped");
|
||||||
|
assert.ok(kanban.$('.o_kanban_view').hasClass('o_kanban_ungrouped'),
|
||||||
|
"the kanban view should have become ungrouped");
|
||||||
|
|
||||||
|
kanban.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -145,6 +145,7 @@ var PagePropertiesDialog = widget.Dialog.extend({
|
|||||||
horizontal: 'auto',
|
horizontal: 'auto',
|
||||||
vertical: 'top',
|
vertical: 'top',
|
||||||
},
|
},
|
||||||
|
widgetParent: 'body',
|
||||||
};
|
};
|
||||||
if (self.page.date_publish) {
|
if (self.page.date_publish) {
|
||||||
datepickersOptions.defaultDate = time.str_to_datetime(self.page.date_publish);
|
datepickersOptions.defaultDate = time.str_to_datetime(self.page.date_publish);
|
||||||
|
Loading…
Reference in New Issue
Block a user