Skip to content

Commit 09c1055

Browse files
authored
Grids: fix eslint errors in data_controller module (part 4) (#34718)
Co-authored-by: Alyar <>
1 parent 92dd0d0 commit 09c1055

5 files changed

Lines changed: 552 additions & 140 deletions

File tree

packages/devextreme/js/__internal/grids/grid_core/data_controller/data_controller.ts

Lines changed: 155 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// TODO: fix the rules disabled below
22
/* eslint-disable @stylistic/max-len */
3-
/* eslint-disable @stylistic/no-mixed-operators */
43
/* eslint-disable @typescript-eslint/explicit-function-return-type */
54
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
65
/* eslint-disable @typescript-eslint/init-declarations */
@@ -10,13 +9,12 @@
109
/* eslint-disable @typescript-eslint/no-shadow */
1110
/* eslint-disable @typescript-eslint/no-unsafe-return */
1211
/* eslint-disable consistent-return */
13-
/* eslint-disable max-depth */
1412
/* eslint-disable no-param-reassign */
1513
/* eslint-disable no-plusplus */
1614
import type { DataSource, Store } from '@js/common/data';
1715
import $ from '@js/core/renderer';
1816
import type { Callback } from '@js/core/utils/callbacks';
19-
import { deferRender, equalByValue } from '@js/core/utils/common';
17+
import { deferRender } from '@js/core/utils/common';
2018
import type { DeferredObj } from '@js/core/utils/deferred';
2119
import { Deferred, when } from '@js/core/utils/deferred';
2220
import { each } from '@js/core/utils/iterator';
@@ -62,8 +60,13 @@ import type {
6260
PagingOptionName,
6361
PagingResult,
6462
ProcessedItem,
63+
UpdateChange,
64+
UpdateRowChange,
6565
} from './types';
6666
import { resolvePaginate, syncPaging } from './utils/paging';
67+
import {
68+
getChangedRowIndices, getRowOperation, isSameGroupRowState, pushChangedRow, resetChangedRows,
69+
} from './utils/row_changes';
6770
import { generateRowValues } from './utils/row_values';
6871

6972
export class DataController extends DataHelperMixin(modules.Controller) {
@@ -808,7 +811,7 @@ export class DataController extends DataHelperMixin(modules.Controller) {
808811
}
809812

810813
if (change.changeType === 'update') {
811-
this._applyChangeUpdate(change);
814+
this.applyChangeUpdate(change);
812815
} else if (change.changeType === 'refresh') {
813816
if (this.items().length && change.repaintChangesOnly) {
814817
this._applyChangesOnly(change);
@@ -818,168 +821,195 @@ export class DataController extends DataHelperMixin(modules.Controller) {
818821
}
819822
}
820823

821-
private _applyChangeFull(change) {
822-
this._items = change.items.slice(0);
824+
private _applyChangeFull(change: DataChange): void {
825+
this._items = (change.items ?? []).slice(0);
823826
}
824827

825-
private _getRowIndices(change) {
826-
const rowIndices = change.rowIndices.slice(0);
827-
const rowIndexDelta = this.getRowIndexDelta();
828+
private updateRow(
829+
newItem: ProcessedItem,
830+
rowIndex: number,
831+
visibleRowIndex: number,
832+
isPartialUpdate: boolean,
833+
): UpdateRowChange {
834+
const oldItem = this._items[rowIndex];
828835

829-
rowIndices.sort((a, b) => a - b);
836+
this._items[rowIndex] = newItem;
830837

831-
for (let i = 0; i < rowIndices.length; i++) {
832-
let correctedRowIndex = rowIndices[i];
838+
if (oldItem.visible !== newItem.visible) {
839+
return {
840+
changeType: 'update',
841+
rowIndex: visibleRowIndex,
842+
item: { visible: newItem.visible } as ProcessedItem,
843+
};
844+
}
833845

834-
if (change.allowInvisibleRowIndices) {
835-
correctedRowIndex += rowIndexDelta;
836-
}
846+
return {
847+
changeType: 'update',
848+
rowIndex: visibleRowIndex,
849+
item: newItem,
850+
columnIndices: isPartialUpdate
851+
? this._partialUpdateRow(oldItem, newItem, visibleRowIndex)
852+
: undefined,
853+
};
854+
}
837855

838-
if (correctedRowIndex < 0) {
839-
rowIndices.splice(i, 1);
840-
i--;
841-
}
856+
private applyRowOperation(
857+
newItems: ProcessedItem[],
858+
rowIndex: number,
859+
rowIndexDelta: number,
860+
isPartialUpdate: boolean,
861+
): UpdateRowChange | undefined {
862+
const visibleRowIndex = rowIndex - rowIndexDelta;
863+
const item = newItems[rowIndex];
864+
865+
if (item) {
866+
item.rowIndex = rowIndex;
842867
}
843868

844-
return rowIndices;
869+
switch (getRowOperation(this._items, newItems, rowIndex)) {
870+
case 'update':
871+
return this.updateRow(item, rowIndex, visibleRowIndex, isPartialUpdate);
872+
case 'insert':
873+
this._items.splice(rowIndex, 0, item);
874+
return { changeType: 'insert', rowIndex: visibleRowIndex, item };
875+
case 'remove':
876+
this._items.splice(rowIndex, 1);
877+
return { changeType: 'remove', rowIndex: visibleRowIndex, item };
878+
case 'replace':
879+
this._items[rowIndex] = item;
880+
return { changeType: 'update', rowIndex: visibleRowIndex, item };
881+
default:
882+
return undefined;
883+
}
845884
}
846885

847886
/**
848887
* @extended: editing
849888
*/
850-
protected _applyChangeUpdate(change): void {
851-
const { items } = change;
852-
const rowIndices = this._getRowIndices(change);
889+
protected applyChangeUpdate(change: UpdateChange): void {
890+
const newItems = change.items ?? [];
853891
const rowIndexDelta = this.getRowIndexDelta();
854-
const repaintChangesOnly = this.option('repaintChangesOnly');
855-
let prevIndex = -1;
892+
const isPartialUpdate = Boolean(this.option('repaintChangesOnly')) && !change.isFullUpdate;
893+
const rowIndices = getChangedRowIndices(
894+
change.rowIndices,
895+
rowIndexDelta,
896+
change.allowInvisibleRowIndices,
897+
);
898+
const changedRows = resetChangedRows(change);
899+
let prevRowIndex = -1;
856900
let rowIndexCorrection = 0;
857-
let changeType;
858901

859-
change.items = [];
860-
change.rowIndices = [];
861-
change.columnIndices = [];
862-
change.changeTypes = [];
902+
rowIndices.forEach((changedRowIndex: number) => {
903+
const rowIndex = changedRowIndex + rowIndexCorrection + rowIndexDelta;
863904

864-
const equalItems = function (item1, item2, strict?) {
865-
let result = item1 && item2 && equalByValue(item1.key, item2.key);
866-
if (result && strict) {
867-
result = item1.rowType === item2.rowType && (item2.rowType !== 'detail' || item1.isEditing === item2.isEditing);
905+
if (prevRowIndex === rowIndex) {
906+
return;
868907
}
869-
return result;
870-
};
871-
872-
each(rowIndices, (index, rowIndex) => {
873-
let columnIndices;
874908

875-
rowIndex += rowIndexCorrection + rowIndexDelta;
909+
prevRowIndex = rowIndex;
876910

877-
if (prevIndex === rowIndex) return;
911+
const changedRow = this.applyRowOperation(newItems, rowIndex, rowIndexDelta, isPartialUpdate);
878912

879-
prevIndex = rowIndex;
880-
const oldItem = this._items[rowIndex];
881-
const oldNextItem = this._items[rowIndex + 1];
882-
const newItem = items[rowIndex];
883-
const newNextItem = items[rowIndex + 1];
884-
885-
const strict = equalItems(oldItem, oldNextItem) || equalItems(newItem, newNextItem);
886-
887-
if (newItem) {
888-
newItem.rowIndex = rowIndex;
889-
change.items.push(newItem);
890-
}
891-
892-
if (oldItem && newItem && equalItems(oldItem, newItem, strict)) {
893-
changeType = 'update';
894-
this._items[rowIndex] = newItem;
895-
if (oldItem.visible !== newItem.visible) {
896-
change.items.splice(-1, 1, { visible: newItem.visible });
897-
} else if (repaintChangesOnly && !change.isFullUpdate) {
898-
columnIndices = this._partialUpdateRow(oldItem, newItem, rowIndex - rowIndexDelta);
899-
}
900-
} else if (newItem && !oldItem || (newNextItem && equalItems(oldItem, newNextItem, strict))) {
901-
changeType = 'insert';
902-
this._items.splice(rowIndex, 0, newItem);
903-
rowIndexCorrection++;
904-
} else if (oldItem && !newItem || (oldNextItem && equalItems(newItem, oldNextItem, strict))) {
905-
changeType = 'remove';
906-
this._items.splice(rowIndex, 1);
907-
rowIndexCorrection--;
908-
prevIndex = -1;
909-
} else if (newItem) {
910-
changeType = 'update';
911-
this._items[rowIndex] = newItem;
912-
} else {
913+
if (!changedRow) {
913914
return;
914915
}
915916

916-
change.rowIndices.push(rowIndex - rowIndexDelta);
917-
change.changeTypes.push(changeType);
918-
change.columnIndices.push(columnIndices);
917+
pushChangedRow(changedRows, changedRow);
918+
919+
if (changedRow.changeType === 'insert') {
920+
rowIndexCorrection += 1;
921+
} else if (changedRow.changeType === 'remove') {
922+
rowIndexCorrection -= 1;
923+
prevRowIndex = -1;
924+
}
919925
});
920926
}
921927

922928
/**
923929
* @extended: editing, validating
924930
*/
925-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
926-
protected _isCellChanged(oldRow, newRow, visibleRowIndex, columnIndex, isLiveUpdate) {
927-
if (JSON.stringify(oldRow.values[columnIndex]) !== JSON.stringify(newRow.values[columnIndex])) {
931+
protected _isCellChanged(
932+
oldRow: ProcessedItem,
933+
newRow: ProcessedItem,
934+
visibleRowIndex: number,
935+
columnIndex: number,
936+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
937+
isLiveUpdate?: boolean,
938+
): boolean {
939+
const oldValue = oldRow.values[columnIndex];
940+
const newValue = newRow.values[columnIndex];
941+
942+
if (JSON.stringify(oldValue) !== JSON.stringify(newValue)) {
928943
return true;
929944
}
930945

931-
function isCellModified(row, columnIndex) {
932-
return row.modifiedValues ? row.modifiedValues[columnIndex] !== undefined : false;
933-
}
946+
const isCellModified = (row: ProcessedItem): boolean => row.modifiedValues?.[columnIndex] !== undefined;
934947

935-
if (isCellModified(oldRow, columnIndex) !== isCellModified(newRow, columnIndex)) {
936-
return true;
937-
}
938-
939-
return false;
948+
return isCellModified(oldRow) !== isCellModified(newRow);
940949
}
941950

942951
/**
943952
* @extended: editing_row_based, editing, editing_form_based
944953
*/
945-
protected _getChangedColumnIndices(oldItem, newItem, visibleRowIndex, isLiveUpdate) {
946-
let columnIndices;
947-
if (oldItem.rowType === newItem.rowType) {
948-
if (newItem.rowType !== 'group' && newItem.rowType !== 'groupFooter') {
949-
columnIndices = [];
950-
951-
if (newItem.rowType !== 'detail') {
952-
for (let columnIndex = 0; columnIndex < oldItem.values.length; columnIndex++) {
953-
if (this._isCellChanged(oldItem, newItem, visibleRowIndex, columnIndex, isLiveUpdate)) {
954-
columnIndices.push(columnIndex);
955-
}
956-
}
957-
}
954+
protected _getChangedColumnIndices(
955+
oldItem: ProcessedItem,
956+
newItem: ProcessedItem,
957+
visibleRowIndex: number,
958+
isLiveUpdate?: boolean,
959+
): number[] | undefined {
960+
if (oldItem.rowType !== newItem.rowType) {
961+
return undefined;
962+
}
963+
964+
if (newItem.rowType === 'group') {
965+
if (!oldItem.cells || !isSameGroupRowState(oldItem, newItem)) {
966+
return undefined;
958967
}
959968

960-
if (newItem.rowType === 'group' && oldItem.cells) {
961-
const isRowStateEquals = newItem.isExpanded === oldItem.isExpanded
962-
&& newItem.data.isContinuation === oldItem.data.isContinuation
963-
&& newItem.data.isContinuationOnNextPage === oldItem.data.isContinuationOnNextPage;
969+
return oldItem.cells
970+
.map((cell, index) => (cell.column?.type !== 'groupExpand' ? index : -1))
971+
.filter((index) => index >= 0);
972+
}
973+
974+
if (newItem.rowType === 'groupFooter') {
975+
return undefined;
976+
}
964977

965-
if (isRowStateEquals) {
966-
columnIndices = oldItem.cells.map((cell, index) => (cell.column?.type !== 'groupExpand' ? index : -1)).filter((index) => index >= 0);
967-
}
978+
const columnIndices: number[] = [];
979+
980+
if (newItem.rowType === 'detail') {
981+
return columnIndices;
982+
}
983+
984+
for (let columnIndex = 0; columnIndex < oldItem.values.length; columnIndex += 1) {
985+
if (this._isCellChanged(oldItem, newItem, visibleRowIndex, columnIndex, isLiveUpdate)) {
986+
columnIndices.push(columnIndex);
968987
}
969988
}
989+
970990
return columnIndices;
971991
}
972992

973-
private _partialUpdateRow(oldItem, newItem, visibleRowIndex, isLiveUpdate?) {
974-
let changedColumnIndices = this._getChangedColumnIndices(oldItem, newItem, visibleRowIndex, isLiveUpdate);
975-
976-
if (changedColumnIndices?.length && this.option('dataRowTemplate')) {
977-
changedColumnIndices = undefined;
978-
}
979-
980-
if (changedColumnIndices) {
993+
private _partialUpdateRow(
994+
oldItem: ProcessedItem,
995+
newItem: ProcessedItem,
996+
visibleRowIndex: number,
997+
isLiveUpdate?: boolean,
998+
): number[] | undefined {
999+
const changedColumnIndices = this
1000+
._getChangedColumnIndices(
1001+
oldItem,
1002+
newItem,
1003+
visibleRowIndex,
1004+
isLiveUpdate,
1005+
);
1006+
const columnIndices = changedColumnIndices?.length && this.option('dataRowTemplate')
1007+
? undefined
1008+
: changedColumnIndices;
1009+
1010+
if (columnIndices) {
9811011
oldItem.cells?.forEach((cell, columnIndex) => {
982-
const isCellChanged = changedColumnIndices.indexOf(columnIndex) >= 0;
1012+
const isCellChanged = columnIndices.includes(columnIndex);
9831013
if (!isCellChanged && cell?.update) {
9841014
cell.update(newItem);
9851015
}
@@ -996,24 +1026,24 @@ export class DataController extends DataHelperMixin(modules.Controller) {
9961026
oldItem.update?.(newItem);
9971027
}
9981028

999-
return changedColumnIndices;
1029+
return columnIndices;
10001030
}
10011031

1002-
protected _isItemEquals(item1, item2) {
1032+
protected _isItemEquals(item1: ProcessedItem, item2: ProcessedItem): boolean {
10031033
if (JSON.stringify(item1.values) !== JSON.stringify(item2.values)) {
10041034
return false;
10051035
}
10061036

1007-
const compareFields = ['modified', 'isNewRow', 'removed', 'isEditing'];
1037+
const compareFields = ['modified', 'isNewRow', 'removed', 'isEditing'] as const;
10081038
if (compareFields.some((field) => item1[field] !== item2[field])) {
10091039
return false;
10101040
}
10111041

10121042
if (item1.rowType === 'group' || item1.rowType === 'groupFooter') {
1013-
const expandedMatch = item1.isExpanded === item2.isExpanded;
1014-
const summaryCellsMatch = JSON.stringify(item1.summaryCells) === JSON.stringify(item2.summaryCells);
1015-
const continuationMatch = item1.data?.isContinuation === item2.data?.isContinuation && item1.data?.isContinuationOnNextPage === item2.data?.isContinuationOnNextPage;
1016-
if (!expandedMatch || !summaryCellsMatch || !continuationMatch) {
1043+
const summaryCellsMatch = JSON.stringify(item1.summaryCells)
1044+
=== JSON.stringify(item2.summaryCells);
1045+
1046+
if (!summaryCellsMatch || !isSameGroupRowState(item1, item2)) {
10171047
return false;
10181048
}
10191049
}

0 commit comments

Comments
 (0)