Skip to content

Commit 7c54025

Browse files
Grids: type public getters block in DataController (#34736)
1 parent 29667e3 commit 7c54025

17 files changed

Lines changed: 139 additions & 100 deletions

File tree

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import type { ArrayStore as BaseArrayStore } from '@js/common/data';
2+
import type { StoreChange } from '@js/data/store';
3+
4+
export interface ArrayStore extends BaseArrayStore {
5+
_array: unknown[];
6+
}
7+
8+
type BeforePushHandler = (e: { changes: StoreChange[] }) => void;
9+
10+
declare module '@js/data/store' {
11+
interface Store {
12+
/* eslint-disable @typescript-eslint/method-signature-style */
13+
// AbstractStore fires `beforePush`, which the public StoreEventName union omits.
14+
on(eventName: 'beforePush', eventHandler: BeforePushHandler): this;
15+
off(eventName: 'beforePush', eventHandler: BeforePushHandler): this;
16+
/* eslint-enable @typescript-eslint/method-signature-style */
17+
}
18+
}

packages/devextreme/js/__internal/grids/grid_core/adaptivity/m_adaptivity.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ import { AI_COLUMN_NAME } from '../ai_column/const';
2424
import type { ColumnsController } from '../columns_controller/m_columns_controller';
2525
import type { ColumnsResizerViewController, DraggingHeaderViewController } from '../columns_resizing_reordering/m_columns_resizing_reordering';
2626
import type { DataController } from '../data_controller/data_controller';
27-
import type { DataChange, ProcessedItem, RawItemData } from '../data_controller/types';
27+
import type { DataChange, ProcessedItem } from '../data_controller/types';
28+
import type { RawItemData } from '../data_source_adapter/types';
2829
import type { EditingController } from '../editing/m_editing';
2930
import type { EditorFactory } from '../editor_factory/m_editor_factory';
3031
import type { Direction } from '../keyboard_navigation/const';

packages/devextreme/js/__internal/grids/grid_core/ai_column/controllers/m_ai_column_controller.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
import type { DataChange } from '@js/common/grids';
21
import type { Callback } from '@js/core/utils/callbacks';
2+
import type { StoreChange } from '@js/data/store';
33
import { isDefined } from '@ts/core/utils/m_type';
44
import type { Column } from '@ts/grids/grid_core/columns_controller/types';
55

66
import type { ColumnsController } from '../../columns_controller/m_columns_controller';
77
import type { DataController } from '../../data_controller/data_controller';
8-
import type { RawItemData } from '../../data_controller/types';
9-
import type { ChangedEvent } from '../../data_source_adapter/types';
8+
import type { ChangedEvent, RawItemData } from '../../data_source_adapter/types';
109
import { Controller } from '../../m_modules';
1110
import type { RowKey } from '../../m_types';
1211
import gridCoreUtils from '../../m_utils';
@@ -27,7 +26,7 @@ export class AIColumnController extends Controller {
2726

2827
private storeRemovedHandler!: (key: RowKey) => void;
2928

30-
private storeBeforePushHandler!: ({ changes }: { changes: DataChange[] }) => void;
29+
private storeBeforePushHandler!: ({ changes }: { changes: StoreChange[] }) => void;
3130

3231
private dataControllerChangedHandler!: () => void;
3332

@@ -141,7 +140,7 @@ export class AIColumnController extends Controller {
141140
this.clearAIColumnsByKey(key);
142141
}
143142

144-
private handleStoreBeforePush({ changes }: { changes: DataChange[] }): void {
143+
private handleStoreBeforePush({ changes }: { changes: StoreChange[] }): void {
145144
changes.forEach(({ key }) => {
146145
if (isDefined(key)) {
147146
this.clearAIColumnsByKey(key);

packages/devextreme/js/__internal/grids/grid_core/ai_column/controllers/m_ai_column_integration_controller.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import errors from '@js/ui/widget/ui.errors';
88

99
import type { ColumnsController } from '../../columns_controller/m_columns_controller';
1010
import type { DataController } from '../../data_controller/data_controller';
11-
import type { RawItemData } from '../../data_controller/types';
11+
import type { RawItemData } from '../../data_source_adapter/types';
1212
import type { ErrorHandlingController } from '../../error_handling/m_error_handling';
1313
import { Controller } from '../../m_modules';
1414
import type { RowKey } from '../../m_types';
@@ -137,7 +137,7 @@ export class AIColumnIntegrationController extends Controller {
137137
}
138138

139139
const keyField = this.dataController.key();
140-
if (isKeyMissingInData(args.data, keyField)) {
140+
if (keyField === undefined || isKeyMissingInData(args.data, keyField)) {
141141
this.dataController.fireError('E1046', keyField);
142142
return;
143143
}

packages/devextreme/js/__internal/grids/grid_core/ai_column/utils.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import {
33
} from '@jest/globals';
44
import type { Column } from '@ts/grids/grid_core/columns_controller/types';
55

6-
import type { ProcessedItem, RawItemData } from '../data_controller/types';
6+
import type { ProcessedItem } from '../data_controller/types';
7+
import type { RawItemData } from '../data_source_adapter/types';
78
import {
89
getDataFromRowItems,
910
isAIColumnAutoMode,

packages/devextreme/js/__internal/grids/grid_core/ai_column/utils.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { isDefined } from '@ts/core/utils/m_type';
22
import type { Column } from '@ts/grids/grid_core/columns_controller/types';
33

4-
import type { ProcessedItem, RawItemData } from '../data_controller/types';
4+
import type { ProcessedItem } from '../data_controller/types';
5+
import type { RawItemData } from '../data_source_adapter/types';
56
import { AI_COLUMN_NAME, CLASSES } from './const';
67

78
export const getAICommandColumnDefaultOptions = (): object => ({

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

Lines changed: 79 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,23 @@
1313
/* eslint-disable max-depth */
1414
/* eslint-disable no-param-reassign */
1515
/* eslint-disable no-plusplus */
16-
import type { DataSource } from '@js/common/data';
16+
import type { DataSource, Store } from '@js/common/data';
1717
import $ from '@js/core/renderer';
1818
import type { Callback } from '@js/core/utils/callbacks';
1919
import { deferRender, equalByValue } from '@js/core/utils/common';
2020
import type { DeferredObj } from '@js/core/utils/deferred';
2121
import { Deferred, when } from '@js/core/utils/deferred';
22-
import { extend } from '@js/core/utils/extend';
2322
import { each } from '@js/core/utils/iterator';
2423
import { isDefined } from '@js/core/utils/type';
2524
import errors from '@js/ui/widget/ui.errors';
2625
import { findChanges } from '@ts/core/utils/m_array_compare';
26+
import { fromPromise } from '@ts/core/utils/m_deferred';
27+
import type { StoreLoadOptions } from '@ts/data/data_source/types';
28+
import type { ColumnsChanges } from '@ts/grids/grid_core/columns_controller/types';
29+
import type {
30+
ChangedEvent, LoadOperation, OperationTypes, RawItemData,
31+
} from '@ts/grids/grid_core/data_source_adapter/types';
32+
import { isLocalStore } from '@ts/grids/grid_core/data_source_adapter/utils/store';
2733
import type { EditingController } from '@ts/grids/grid_core/editing/m_editing';
2834
import type { EditorFactory } from '@ts/grids/grid_core/editor_factory/m_editor_factory';
2935
import type { ErrorHandlingController } from '@ts/grids/grid_core/error_handling/m_error_handling';
@@ -32,18 +38,16 @@ import type { FilterSyncController } from '@ts/grids/grid_core/filter/m_filter_s
3238
import type { FocusController } from '@ts/grids/grid_core/focus/m_focus';
3339
import type { HeaderFilterController } from '@ts/grids/grid_core/header_filter/m_header_filter';
3440
import type { KeyboardNavigationController } from '@ts/grids/grid_core/keyboard_navigation/m_keyboard_navigation';
41+
import modules from '@ts/grids/grid_core/m_modules';
42+
import type {
43+
Controllers, Module, OptionChanged, RowKey,
44+
} from '@ts/grids/grid_core/m_types';
45+
import gridCoreUtils from '@ts/grids/grid_core/m_utils';
3546
import type { SelectionController } from '@ts/grids/grid_core/selection/m_selection';
3647
import type { StateStoringController } from '@ts/grids/grid_core/state_storing/m_state_storing_core';
3748
import type { ValidatingController } from '@ts/grids/grid_core/validating/m_validating';
49+
import type { VirtualScrollController } from '@ts/grids/grid_core/virtual_scrolling/m_virtual_scrolling_core';
3850

39-
import type { ColumnsChanges } from '../columns_controller/types';
40-
import type { ChangedEvent, LoadOperation, OperationTypes } from '../data_source_adapter/types';
41-
import modules from '../m_modules';
42-
import type {
43-
Controllers, Module, OptionChanged, RowKey,
44-
} from '../m_types';
45-
import gridCoreUtils from '../m_utils';
46-
import type { VirtualScrollController } from '../virtual_scrolling/m_virtual_scrolling_core';
4751
import { DataHelperMixin } from './data_helper_mixin';
4852
import type {
4953
BinaryDataFilterExpression,
@@ -58,7 +62,6 @@ import type {
5862
PagingOptionName,
5963
PagingResult,
6064
ProcessedItem,
61-
RawItemData,
6265
} from './types';
6366
import { resolvePaginate, syncPaging } from './utils/paging';
6467
import { generateRowValues } from './utils/row_values';
@@ -262,7 +265,7 @@ export class DataController extends DataHelperMixin(modules.Controller) {
262265
const isValueChanged = args.value !== args.previousValue;
263266
if (isValueChanged) {
264267
const store = this.store();
265-
if (store) {
268+
if (isLocalStore(store)) {
266269
store._array = args.value;
267270
}
268271
}
@@ -1454,31 +1457,29 @@ export class DataController extends DataHelperMixin(modules.Controller) {
14541457
/**
14551458
* @extended: virtual_scrolling
14561459
*/
1457-
public isEmpty() {
1460+
public isEmpty(): boolean {
14581461
return !this.items().length;
14591462
}
14601463

1461-
public pageCount() {
1464+
public pageCount(): number {
14621465
return this._dataSource ? this._dataSource.pageCount() : 1;
14631466
}
14641467

14651468
public dataSource() {
14661469
return this._dataSource;
14671470
}
14681471

1469-
public store() {
1470-
const dataSource = this._dataSource;
1471-
return dataSource?.store();
1472+
public store(): Store | undefined {
1473+
return this._dataSource?.store();
14721474
}
14731475

1474-
public loadAll(data, skipFilter = false) {
1475-
// @ts-expect-error
1476-
const d = new Deferred();
1476+
public loadAll(data?: RawItemData[], skipFilter = false): DeferredObj<ProcessedItem[]> {
1477+
const d = Deferred<ProcessedItem[]>();
14771478
const dataSource = this._dataSource;
14781479

14791480
if (dataSource) {
14801481
if (data) {
1481-
const options: Record<string, any> = {
1482+
const loadOperation: Omit<LoadOperation, 'data'> & Required<Pick<LoadOperation, 'data'>> = {
14821483
data,
14831484
isCustomLoading: true,
14841485
storeLoadOptions: { isLoadingAll: true },
@@ -1488,94 +1489,104 @@ export class DataController extends DataHelperMixin(modules.Controller) {
14881489
sort: dataSource.sort(),
14891490
},
14901491
};
1491-
dataSource._handleDataLoaded(options);
1492-
when(options.data).done((data) => {
1493-
data = this._beforeProcessItems(data);
1494-
d.resolve(this._processItems(data, { changeType: 'loadingAll' }), options.extra?.summary);
1495-
}).fail(d.reject);
1492+
dataSource._handleDataLoaded(loadOperation);
1493+
1494+
when<RawItemData[]>(loadOperation.data)
1495+
.done((loadedData: RawItemData[]): void => {
1496+
const items = this._processItems(
1497+
this._beforeProcessItems(loadedData),
1498+
{ changeType: 'loadingAll' },
1499+
);
1500+
// @ts-expect-error DataGrid-only summary leaks into grid_core
1501+
d.resolve(items, loadOperation.extra?.summary);
1502+
})
1503+
.fail(d.reject as (...args: unknown[]) => void);
14961504
} else if (!dataSource.isLoading()) {
1497-
const loadOptions = extend({}, dataSource.loadOptions(), { isLoadingAll: true, requireTotalCount: false });
1498-
dataSource.load(loadOptions).done((items, extra) => {
1499-
items = this._beforeProcessItems(items);
1500-
items = this._processItems(items, { changeType: 'loadingAll' });
1501-
d.resolve(items, extra?.summary);
1502-
}).fail(d.reject);
1505+
const loadOptions: StoreLoadOptions & { isLoadingAll: boolean } = {
1506+
...dataSource.loadOptions(),
1507+
isLoadingAll: true,
1508+
requireTotalCount: false,
1509+
};
1510+
dataSource.load(loadOptions)
1511+
.done((loadedItems: RawItemData[], extra: LoadOperation['extra']): void => {
1512+
const items = this._processItems(
1513+
this._beforeProcessItems(loadedItems),
1514+
{ changeType: 'loadingAll' },
1515+
);
1516+
// @ts-expect-error DataGrid-only summary leaks into grid_core
1517+
d.resolve(items, extra?.summary);
1518+
})
1519+
.fail(d.reject);
15031520
} else {
15041521
d.reject();
15051522
}
15061523
} else {
15071524
d.resolve([]);
15081525
}
1526+
15091527
return d;
15101528
}
15111529

1512-
public getAllDataRowKeys(): Promise<RowKey[]> {
1513-
return Promise.resolve(this.loadAll(undefined) as unknown as Promise<ProcessedItem[]>)
1514-
.then((items) => items
1515-
.filter((item) => item.rowType === 'data')
1516-
.map((item) => item.key));
1530+
public async getAllDataRowKeys(): Promise<RowKey[]> {
1531+
const items = await Promise.resolve(this.loadAll(undefined));
1532+
1533+
return items
1534+
.filter((item) => item.rowType === 'data')
1535+
.map((item): RowKey => item.key);
15171536
}
15181537

1519-
public getKeyByRowIndex(rowIndex, byLoaded?) {
1538+
public getKeyByRowIndex(rowIndex: number, byLoaded?: boolean): RowKey | undefined {
15201539
const item = this.items(byLoaded)[rowIndex];
1521-
if (item) {
1522-
return item.key;
1523-
}
1540+
1541+
return item?.key;
15241542
}
15251543

1526-
public getRowIndexByKey(key, byLoaded?) {
1544+
public getRowIndexByKey(key: RowKey, byLoaded?: boolean): number {
15271545
return gridCoreUtils.getIndexByKey(key, this.items(byLoaded));
15281546
}
15291547

1530-
public getRowByKey(key: unknown): ProcessedItem | undefined {
1548+
public getRowByKey(key: RowKey): ProcessedItem | undefined {
15311549
return this.items()?.[this.getRowIndexByKey(key)];
15321550
}
15331551

1534-
public keyOf(data) {
1535-
const store = this.store();
1536-
if (store) {
1537-
return store.keyOf(data);
1538-
}
1552+
public keyOf(data: RawItemData): RowKey | undefined {
1553+
return this.store()?.keyOf(data);
15391554
}
15401555

1541-
private byKey(key) {
1556+
private byKey(key: RowKey): DeferredObj<RawItemData> {
15421557
const store = this.store();
1543-
const rowIndex = this.getRowIndexByKey(key);
1544-
let result;
15451558

1546-
if (!store) return;
1559+
if (!store) {
1560+
return Deferred<RawItemData>().reject();
1561+
}
1562+
1563+
const rowIndex = this.getRowIndexByKey(key);
15471564

15481565
if (rowIndex >= 0) {
1549-
// @ts-expect-error
1550-
result = new Deferred().resolve(this.items()[rowIndex].data);
1566+
return Deferred<RawItemData>().resolve(this.items()[rowIndex].data);
15511567
}
15521568

1553-
return result || store.byKey(key);
1569+
return fromPromise(store.byKey(key));
15541570
}
15551571

1556-
public key() {
1557-
const store = this.store();
1558-
1559-
if (store) {
1560-
return store.key();
1561-
}
1572+
public key(): string | string[] | undefined {
1573+
return this.store()?.key();
15621574
}
15631575

15641576
/**
15651577
* @extended: virtual_scrolling
15661578
*/
15671579
// eslint-disable-next-line @typescript-eslint/no-unused-vars
1568-
public getRowIndexOffset(byLoadedRows?: boolean) {
1580+
public getRowIndexOffset(byLoadedRows?: boolean): number {
15691581
return 0;
15701582
}
15711583

1572-
private getDataByKeys(rowKeys) {
1573-
// @ts-expect-error
1574-
const result = new Deferred();
1575-
const deferreds: any[] = [];
1576-
const data: any[] = [];
1584+
private getDataByKeys(rowKeys: RowKey[]): DeferredObj<RawItemData[]> {
1585+
const result = Deferred<RawItemData[]>();
1586+
const deferreds: DeferredObj<RawItemData>[] = [];
1587+
const data: RawItemData[] = [];
15771588

1578-
each(rowKeys, (index, key) => {
1589+
each(rowKeys, (index: number, key: RowKey) => {
15791590
deferreds.push(this.byKey(key).done((keyData) => {
15801591
data[index] = keyData;
15811592
}));

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,13 @@ import type { ScalarFilterValue } from '@js/common/grids';
44
import type { DeferredObj } from '@js/core/utils/deferred';
55

66
import type { Column } from '../columns_controller/types';
7-
import type { ChangedEvent, OperationTypes } from '../data_source_adapter/types';
7+
import type { ChangedEvent, OperationTypes, RawItemData } from '../data_source_adapter/types';
88
/** data */
99

1010
export interface DataSourceAdapterLike {
1111
_dataSource: DataSource;
1212
}
1313

14-
export type RawItemData = Record<string, unknown>;
15-
1614
export interface ItemProcessingOptions {
1715
visibleColumns: Column[];
1816
dataIndex: number;

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { AI_COLUMN_NAME } from '@ts/grids/grid_core/ai_column/const';
22
import type { Column } from '@ts/grids/grid_core/columns_controller/types';
33

4-
import type { RawItemData } from '../types';
4+
import type { RawItemData } from '../../data_source_adapter/types';
55

66
export function generateRowValues(
77
data: RawItemData,

packages/devextreme/js/__internal/grids/grid_core/data_source_adapter/m_data_source_adapter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ export default class DataSourceAdapter extends modules.Controller {
410410

411411
protected _customizeStoreLoadOptionsHandler(options: LoadOperation): void {
412412
this._handleDataLoading(options);
413-
if (!(options.data?.length === 0)) {
413+
if (!(Array.isArray(options.data) && options.data.length === 0)) {
414414
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
415415
options.data = getPageDataFromCache(options, true) || options.cachedStoreData;
416416
}

0 commit comments

Comments
 (0)