[FIX] stock: fix lazy list views
- Avoid traceback when click on priority widget - Also, fetch directly the lazy column if the web client read one record (happen when we modify a single record). closes odoo/odoo#77402 X-original-commit: eb26406cff7a0c61768c287a0525c2b6bc123f9e Signed-off-by: William Henrotin <Whenrow@users.noreply.github.com> Signed-off-by: Rémy Voet <ryv-odoo@users.noreply.github.com>
This commit is contained in:
@@ -16,9 +16,14 @@ function _findRecordsInState(entrypoint, result = []) {
|
||||
return result;
|
||||
}
|
||||
|
||||
function _bindLazyColumnToState(entrypoint, lazyColumns, values) {
|
||||
function _bindLazyColumnToState(entrypoint, lazyColumns, values, startRequestTime) {
|
||||
let records = _findRecordsInState(entrypoint);
|
||||
for (const recordData of records.values()) {
|
||||
// keep track of request start time (in _fetchRecord) when we fetch a particular record (can happens we
|
||||
// modify the priority field) to avoids to erase the old data if the lazy loaded finished after.
|
||||
if (startRequestTime && recordData.specialData && recordData.specialData.lastUpdateLazy && startRequestTime <= recordData.specialData.lastUpdateLazy){
|
||||
continue
|
||||
}
|
||||
for (const lazyCol of lazyColumns) {
|
||||
recordData.data[lazyCol] =
|
||||
(values && values[recordData.data.id] && values[recordData.data.id][lazyCol]) ||
|
||||
@@ -29,6 +34,9 @@ function _bindLazyColumnToState(entrypoint, lazyColumns, values) {
|
||||
|
||||
function _getLazyColumns(fieldsInfo) {
|
||||
const lazyColumns = [];
|
||||
if (!fieldsInfo) {
|
||||
return lazyColumns;
|
||||
}
|
||||
for (const [key, value] of Object.entries(fieldsInfo)) {
|
||||
if (value.options && value.options.lazy) {
|
||||
lazyColumns.push(key);
|
||||
@@ -50,6 +58,10 @@ const LazyColumnListModel = ListModel.extend({
|
||||
*/
|
||||
_getFieldNames: function (element, options) {
|
||||
const res = this._super.apply(this, arguments);
|
||||
if (element.type !== "list") {
|
||||
// lazy is only for list type element
|
||||
return res;
|
||||
}
|
||||
const fieldsInfo = element.fieldsInfo;
|
||||
const viewType = (options && options.viewType) || element.viewType;
|
||||
const lazyColumns = _getLazyColumns(fieldsInfo[viewType]);
|
||||
@@ -66,6 +78,11 @@ const LazyColumnListModel = ListModel.extend({
|
||||
}
|
||||
return dataPoint;
|
||||
},
|
||||
|
||||
_fetchRecord: function(record, options) {
|
||||
record.specialData.lastUpdateLazy = Date.now();
|
||||
return this._super.apply(this, arguments);
|
||||
}
|
||||
});
|
||||
|
||||
const LazyColumnListRenderer = ListRenderer.extend({
|
||||
@@ -75,6 +92,7 @@ const LazyColumnListRenderer = ListRenderer.extend({
|
||||
},
|
||||
|
||||
_lazyLoad: async function (state, lazyColumns) {
|
||||
const startRequestTime = Date.now()
|
||||
const res = await this._rpc(
|
||||
{
|
||||
model: state.model,
|
||||
@@ -90,9 +108,9 @@ const LazyColumnListRenderer = ListRenderer.extend({
|
||||
resById[element.id][lazyCol] = element[lazyCol];
|
||||
}
|
||||
}
|
||||
_bindLazyColumnToState(this.state, lazyColumns, resById);
|
||||
_bindLazyColumnToState(this.state, lazyColumns, resById, startRequestTime);
|
||||
this.currentNbLazyRpc -= 1;
|
||||
// Render only thr
|
||||
// Render only the lazy columns
|
||||
for (const lazyCol of lazyColumns) {
|
||||
const node = this.columns.find((colAttribute) => colAttribute.attrs.name === lazyCol);
|
||||
if (!node) {
|
||||
|
||||
@@ -14,11 +14,12 @@ QUnit.module(
|
||||
person: {
|
||||
fields: {
|
||||
name: { string: "Name", type: "char" },
|
||||
priority: { string: "Priority", type: "selection", selection: [['0', 'normal'],['1', 'important']]},
|
||||
slowField: { string: "Hard to Compute", type: "char" },
|
||||
},
|
||||
records: [
|
||||
{ id: 1, name: "Daniel Fortesque" },
|
||||
{ id: 2, name: "Samuel Oak" },
|
||||
{ id: 1, priority: '0', name: "Daniel Fortesque" },
|
||||
{ id: 2, priority: '0', name: "Samuel Oak" },
|
||||
],
|
||||
},
|
||||
};
|
||||
@@ -40,23 +41,21 @@ QUnit.module(
|
||||
'<field name="slowField" options=\'{"lazy": true}\'/>' +
|
||||
"</tree>",
|
||||
mockRPC: async function (route, args) {
|
||||
console.log(route);
|
||||
if (route === "/web/dataset/call_kw/person/read") {
|
||||
const record_ids = args.args[0];
|
||||
const fields = args.args[1];
|
||||
const records = [];
|
||||
const recs = [];
|
||||
for (const d of this.data.person.records) {
|
||||
let reco = { id: d.id };
|
||||
for (const f of fields) {
|
||||
if (f === "slowField") {
|
||||
reco[f] = `${d.name} ${d.id}`;
|
||||
} else {
|
||||
reco[f] = d[f];
|
||||
}
|
||||
if (record_ids.includes(d.id)) {
|
||||
d["slowField"] = `${d.name} ${d.id}`;
|
||||
recs.push(d);
|
||||
}
|
||||
records.push(reco);
|
||||
}
|
||||
await promiseRead;
|
||||
return Promise.resolve(records);
|
||||
// Don't wait if it read only one record
|
||||
if (fields.includes("slowField") && record_ids.length > 1) {
|
||||
await promiseRead;
|
||||
}
|
||||
return Promise.resolve(recs);
|
||||
}
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
@@ -87,5 +86,81 @@ QUnit.module(
|
||||
|
||||
list.destroy();
|
||||
});
|
||||
|
||||
QUnit.test("With the priority widget", async function (assert) {
|
||||
assert.expect(19);
|
||||
const promiseRead = makeDeferred();
|
||||
const list = await createView({
|
||||
View: LazyColumnList,
|
||||
model: "person",
|
||||
data: this.data,
|
||||
arch:
|
||||
'<tree editable="top" js_class="lazy_column_list">' +
|
||||
'<field name="name"/>' +
|
||||
'<field name="priority" widget="priority"/>' +
|
||||
'<field name="slowField" options=\'{"lazy": true}\'/>' +
|
||||
"</tree>",
|
||||
mockRPC: async function (route, args) {
|
||||
if (route === "/web/dataset/call_kw/person/read") {
|
||||
const record_ids = args.args[0];
|
||||
const fields = args.args[1];
|
||||
const recs = [];
|
||||
for (const d of this.data.person.records) {
|
||||
if (record_ids.includes(d.id)) {
|
||||
d["slowField"] = `${d.name} ${d.id} ${d.priority}`;
|
||||
recs.push(d);
|
||||
}
|
||||
}
|
||||
// Don't wait if it read only one record
|
||||
if (fields.includes("slowField") && record_ids.length > 1) {
|
||||
await promiseRead;
|
||||
}
|
||||
return Promise.resolve(recs);
|
||||
}
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
});
|
||||
// Checks we have initially 2 records
|
||||
assert.containsN(list, ".o_data_row", 2, "should have 2 records");
|
||||
|
||||
let $spin = list.$el.find("th[data-name='slowField'] .fa.fa-spin");
|
||||
let $results = list.$el.find("td[name='slowField']");
|
||||
assert.equal($spin.length, 1);
|
||||
assert.equal($spin.hasClass("invisible"), false);
|
||||
assert.equal($results.length, 2);
|
||||
assert.equal($results.first().text(), "");
|
||||
assert.equal($results.last().text(), "");
|
||||
|
||||
assert.strictEqual(list.$('.o_data_row').first().find('.o_priority a.fa-star').length, 0,
|
||||
"widget shouldn't be considered set");
|
||||
await testUtils.dom.click(list.$('.o_data_row').first().find('.o_priority a.fa-star-o').first());
|
||||
|
||||
assert.strictEqual(list.$('.o_data_row').first().find('.o_priority a.fa-star').length, 1,
|
||||
"widget should be considered set");
|
||||
$spin = list.$el.find("th[data-name='slowField'] .fa.fa-spin");
|
||||
$results = list.$el.find("td[name='slowField']");
|
||||
assert.equal($spin.length, 1);
|
||||
assert.equal($spin.hasClass("invisible"), false);
|
||||
assert.equal($results.length, 2);
|
||||
assert.equal($results.first().text(), "Daniel Fortesque 1 1",
|
||||
"It should be read by the click on priority");
|
||||
assert.equal($results.last().text(), "");
|
||||
|
||||
promiseRead.resolve();
|
||||
await nextTick();
|
||||
|
||||
$spin = list.$el.find("th[data-name='slowField'] .fa.fa-spin");
|
||||
$results = list.$el.find("td[name='slowField']");
|
||||
assert.equal($spin.length, 1);
|
||||
assert.equal($spin.hasClass("invisible"), true);
|
||||
assert.equal($results.length, 2);
|
||||
assert.equal($results.first().text(), "Daniel Fortesque 1 1",
|
||||
"It shouldn't be erase the data from priority click because this data is newer");
|
||||
assert.equal($results.last().text(), "Samuel Oak 2 0");
|
||||
|
||||
assert.containsN(list, ".o_data_row", 2, "should have 2 records");
|
||||
|
||||
list.destroy();
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user