[FIX] web: drag and drop kanban flicker

Before this commit, in a kanban view, if you resequence records or
groups by dragging and dropping, there is a flicker.

How to reproduce:
- Go to a kanban view
- Drag and drop a kanban card

Before this commit:
    The moved kanban card returns to its previous position during a render.

After this commit:
    The kanban card keeps its new position.

closes odoo/odoo#130561

Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
This commit is contained in:
FrancoisGe
2023-08-04 09:42:58 +02:00
parent 825df5c5f5
commit 41750141c2
4 changed files with 19 additions and 31 deletions
@@ -86,7 +86,7 @@ export class DynamicGroupList extends DynamicList {
const targetGroup = this.groups.find((g) => g.id === targetGroupId);
if (dataGroupId === targetGroupId) {
// move a record inside the same group
targetGroup.list.records = await targetGroup.list._resequence(
await targetGroup.list._resequence(
targetGroup.list.records,
this.resModel,
dataRecordId,
@@ -125,7 +125,7 @@ export class DynamicGroupList extends DynamicList {
throw e;
}
if (!targetGroup.isFolded) {
targetGroup.list.records = await targetGroup.list._resequence(
await targetGroup.list._resequence(
targetGroup.list.records,
this.resModel,
dataRecordId,
@@ -140,7 +140,7 @@ export class DynamicGroupList extends DynamicList {
}
return this.model.mutex.exec(async () => {
this.groups = await this._resequence(
await this._resequence(
this.groups,
this.groupByField.relation,
movedGroupId,
@@ -220,12 +220,8 @@ export class DynamicGroupList extends DynamicList {
const group = this._createGroupDatapoint(data);
if (lastGroup) {
const groups = [...this.groups, group];
this.groups = await this._resequence(
groups,
this.groupByField.relation,
group.id,
lastGroup.id
);
await this._resequence(groups, this.groupByField.relation, group.id, lastGroup.id);
this.groups = groups;
} else {
this.groups.push(group);
}
@@ -268,18 +268,17 @@ export class DynamicList extends DataPoint {
async _resequence(originalList, resModel, movedId, targetId) {
if (this.resModel === resModel && !this.canResequence()) {
return originalList;
return;
}
const handleField = this.resModel === resModel ? this.handleField : DEFAULT_HANDLE_FIELD;
const dataPoints = [...originalList];
const order = this.orderBy.find((o) => o.name === handleField);
const asc = !order || order.asc;
// Find indices
const fromIndex = dataPoints.findIndex((d) => d.id === movedId);
const fromIndex = originalList.findIndex((d) => d.id === movedId);
let toIndex = 0;
if (targetId !== null) {
const targetIndex = dataPoints.findIndex((d) => d.id === targetId);
const targetIndex = originalList.findIndex((d) => d.id === targetId);
toIndex = fromIndex > targetIndex ? targetIndex + 1 : targetIndex;
}
@@ -288,13 +287,13 @@ export class DynamicList extends DataPoint {
// Determine which records/groups need to be modified
const firstIndex = Math.min(fromIndex, toIndex);
const lastIndex = Math.max(fromIndex, toIndex) + 1;
let reorderAll = dataPoints.some(
let reorderAll = originalList.some(
(dp) => this._getDPFieldValue(dp, handleField) === undefined
);
if (!reorderAll) {
let lastSequence = (asc ? -1 : 1) * Infinity;
for (let index = 0; index < dataPoints.length; index++) {
const sequence = getSequence(dataPoints[index]);
for (let index = 0; index < originalList.length; index++) {
const sequence = getSequence(originalList[index]);
if (
((index < firstIndex || index >= lastIndex) &&
((asc && lastSequence >= sequence) ||
@@ -308,11 +307,11 @@ export class DynamicList extends DataPoint {
}
// Perform the resequence in the list of records/groups
const [dp] = dataPoints.splice(fromIndex, 1);
dataPoints.splice(toIndex, 0, dp);
const [dp] = originalList.splice(fromIndex, 1);
originalList.splice(toIndex, 0, dp);
// Creates the list of records/groups to modify
let toReorder = dataPoints;
let toReorder = originalList;
if (!reorderAll) {
toReorder = toReorder.slice(firstIndex, lastIndex).filter((r) => r.id !== movedId);
if (fromIndex < toIndex) {
@@ -341,22 +340,20 @@ export class DynamicList extends DataPoint {
}
const wasResequenced = await this.model.rpc("/web/dataset/resequence", params);
if (!wasResequenced) {
return originalList;
return;
}
// Read the actual values set by the server and update the records/groups
const kwargs = { context: this.context };
const result = await this.model.orm.read(resModel, resIds, [handleField], kwargs);
for (const dpData of result) {
const dp = dataPoints.find((d) => this._getDPresId(d) === dpData.id);
const dp = originalList.find((d) => this._getDPresId(d) === dpData.id);
if (dp instanceof Record) {
dp._applyValues(dpData);
} else {
dp[handleField] = dpData[handleField];
}
}
return dataPoints;
}
async _toggleArchive(isSelected, state) {
@@ -88,12 +88,7 @@ export class DynamicRecordList extends DynamicList {
async resequence(movedRecordId, targetRecordId) {
return this.model.mutex.exec(
async () =>
(this.records = await this._resequence(
this.records,
this.resModel,
movedRecordId,
targetRecordId
))
await this._resequence(this.records, this.resModel, movedRecordId, targetRecordId)
);
}
@@ -12577,13 +12577,13 @@ QUnit.module("Views", (hooks) => {
[...target.querySelectorAll(".o_kanban_record:not(.o_kanban_ghost)")].map(
(el) => el.innerText
),
["blip", "blip", "yop", "gnap"]
["blip", "yop", "blip", "gnap"]
);
assert.verifySteps(["resequence"]);
// try again
await dragAndDrop(".o_kanban_record:nth-child(2)", ".o_kanban_record:nth-child(3)");
-assert.verifySteps([]);
assert.verifySteps([]);
def.resolve();
await nextTick();