Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { adaptivityModule } from '@ts/grids/grid_core/adaptivity/adaptivity_module';

import gridCore from '../m_core';
import { adaptivityExportViewControllerExtender } from './extenders/adaptivity_export_view_controller';

gridCore.registerModule('adaptivity', {
...adaptivityModule,
extenders: {
...adaptivityModule.extenders,
controllers: {
...adaptivityModule.extenders?.controllers,
export: adaptivityExportViewControllerExtender,
},
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import type { ExportController } from '@ts/grids/data_grid/export/m_export';
import type { ModuleType } from '@ts/grids/grid_core/m_types';

import { HIDDEN_COLUMNS_WIDTH } from '../../../grid_core/adaptivity/const';

export const adaptivityExportViewControllerExtender = (
Base: ModuleType<ExportController>,
): ModuleType<ExportController> => class AdaptivityExportViewControllerExtender extends Base {
protected _updateColumnWidth(column, width): void {
super._updateColumnWidth(
column,
column.visibleWidth === HIDDEN_COLUMNS_WIDTH ? column.bestFitWidth : width,
);
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import './keyboard_navigation/m_group_panel_keyboard_navigation';
import './summary/summary_module';
import './module_not_extended/sticky_columns';
import './module_not_extended/column_fixing';
import './module_not_extended/adaptivity';
import './adaptivity/adaptivity_module';
import './module_not_extended/virtual_columns';
import './export/m_export';
import './focus/m_focus';
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { describe, expect, it } from '@jest/globals';

import { getAdaptiveDetailRowIndex, resolveAdaptiveDetailRowTarget } from '../utils';

describe('resolveAdaptiveDetailRowTarget', () => {
it('expands the row when no adaptive detail row is expanded', () => {
expect(resolveAdaptiveDetailRowTarget('key_1', 2, -1, false)).toEqual({
key: 'key_1',
rowIndex: 2,
});
});

it('expands the row when another adaptive detail row is expanded', () => {
expect(resolveAdaptiveDetailRowTarget('key_1', 2, 5, false)).toEqual({
key: 'key_1',
rowIndex: 2,
});
});

it('collapses the row when its adaptive detail row is expanded', () => {
expect(resolveAdaptiveDetailRowTarget('key_1', 2, 2, false)).toEqual({
key: undefined,
rowIndex: -1,
});
});

it('keeps the row expanded when the adaptive detail row should always be expanded', () => {
expect(resolveAdaptiveDetailRowTarget('key_1', 2, 2, true)).toEqual({
key: 'key_1',
rowIndex: 2,
});
});

it('keeps the key when neither the key nor the expanded key is loaded', () => {
expect(resolveAdaptiveDetailRowTarget('key_1', -1, -1, false)).toEqual({
key: 'key_1',
rowIndex: -1,
});
});
});

describe('getAdaptiveDetailRowIndex', () => {
it('returns the index of the row that follows the data row', () => {
expect(getAdaptiveDetailRowIndex(2)).toBe(3);
});

it('subtracts the row index delta', () => {
expect(getAdaptiveDetailRowIndex(20, 15)).toBe(6);
});

it('keeps a negative index of a row that is not loaded', () => {
expect(getAdaptiveDetailRowIndex(-1)).toBe(-1);
expect(getAdaptiveDetailRowIndex(-1, 15)).toBe(-16);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import type { Module } from '../m_types';
import { adaptivityColumnsControllerExtender } from './extenders/adaptivity_columns_controller';
import { adaptivityColumnsResizerViewControllerExtender } from './extenders/adaptivity_columns_resizer_view_controller';
import { adaptivityDataControllerExtender } from './extenders/adaptivity_data_controller';
import { adaptivityDraggingHeaderViewControllerExtender } from './extenders/adaptivity_dragging_header_view_controller';
import { adaptivityEditingViewControllerExtender } from './extenders/adaptivity_editing_view_controller';
import { adaptivityEditorFactoryViewControllerExtender } from './extenders/adaptivity_editor_factory_view_controller';
import { adaptivityHeadersKeyboardNavigationViewControllerExtender } from './extenders/adaptivity_headers_keyboard_navigation_view_controller';
import { adaptivityKeyboardNavigationViewControllerExtender } from './extenders/adaptivity_keyboard_navigation_view_controller';
import { adaptivityResizingViewControllerExtender } from './extenders/adaptivity_resizing_view_controller';
import { adaptivityRowsViewExtender } from './extenders/adaptivity_rows_view';
import { AdaptiveColumnsController } from './m_adaptivity';

export const adaptivityModule: Module = {
defaultOptions() {
return {
columnHidingEnabled: false,
};
},
controllers: {
adaptiveColumns: AdaptiveColumnsController,
},
extenders: {
views: {
rowsView: adaptivityRowsViewExtender,
},
controllers: {
columnsResizer: adaptivityColumnsResizerViewControllerExtender,
draggingHeader: adaptivityDraggingHeaderViewControllerExtender,
editing: adaptivityEditingViewControllerExtender,
resizing: adaptivityResizingViewControllerExtender,
data: adaptivityDataControllerExtender,
editorFactory: adaptivityEditorFactoryViewControllerExtender,
columns: adaptivityColumnsControllerExtender,
keyboardNavigation: adaptivityKeyboardNavigationViewControllerExtender,
headersKeyboardNavigation: adaptivityHeadersKeyboardNavigationViewControllerExtender,
},
},
};
Original file line number Diff line number Diff line change
@@ -1 +1,32 @@
export const COLUMN_HEADERS_VIEW = 'columnHeadersView' as const;
export const ROWS_VIEW = 'rowsView' as const;
export const FOOTER_VIEW = 'footerView' as const;
export const COLUMN_VIEWS = [COLUMN_HEADERS_VIEW, ROWS_VIEW, FOOTER_VIEW] as const;

export const ADAPTIVE_NAMESPACE = 'dxDataGridAdaptivity';
export const HIDDEN_COLUMNS_WIDTH = 'adaptiveHidden';
export const ADAPTIVE_ROW_TYPE = 'detailAdaptive';

export const FORM_ITEM_CONTENT_CLASS = 'dx-field-item-content';
export const FORM_ITEM_MODIFIED = 'dx-item-modified';

export const HIDDEN_COLUMN_CLASS = 'hidden-column';
export const ADAPTIVE_COLUMN_BUTTON_CLASS = 'adaptive-more';
export const ADAPTIVE_COLUMN_NAME_CLASS = 'dx-command-adaptive';
export const COMMAND_ADAPTIVE_HIDDEN_CLASS = 'dx-command-adaptive-hidden';
export const ADAPTIVE_DETAIL_ROW_CLASS = 'dx-adaptive-detail-row';
export const ADAPTIVE_ITEM_TEXT_CLASS = 'dx-adaptive-item-text';
export const MASTER_DETAIL_CELL_CLASS = 'dx-master-detail-cell';
export const LAST_DATA_CELL_CLASS = 'dx-last-data-cell';
export const ADAPTIVE_COLUMN_NAME = 'adaptive';
export const EDIT_MODE_BATCH = 'batch';
export const EDIT_MODE_ROW = 'row';
export const EDIT_MODE_FORM = 'form';
export const EDIT_MODE_POPUP = 'popup';
export const REVERT_TOOLTIP_CLASS = 'revert-tooltip';
export const GROUP_CELL_CLASS = 'dx-group-cell';
export const GROUP_ROW_CLASS = 'dx-group-row';

export const EXPAND_ARIA_NAME = 'dxDataGrid-ariaAdaptiveExpand';
export const COLLAPSE_ARIA_NAME = 'dxDataGrid-ariaAdaptiveCollapse';
export const LEGACY_SCROLLING_MODE = 'scrolling.legacyMode';
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/* eslint-disable @typescript-eslint/explicit-function-return-type */
/* eslint-disable @typescript-eslint/no-unsafe-return */
import type { ColumnsController } from '@ts/grids/grid_core/columns_controller/m_columns_controller';
import type { Column } from '@ts/grids/grid_core/columns_controller/types';
import type { ModuleType } from '@ts/grids/grid_core/m_types';

import { HIDDEN_COLUMNS_WIDTH } from '../const';
import type { AdaptiveColumnsController } from '../m_adaptivity';

export const adaptivityColumnsControllerExtender = (
Base: ModuleType<ColumnsController>,
): ModuleType<ColumnsController> => class AdaptivityColumnsControllerExtender extends Base {
private adaptiveColumnsController!: AdaptiveColumnsController;

public init(isApplyingUserState?: boolean): void {
super.init(isApplyingUserState);
this.adaptiveColumnsController = this.getController('adaptiveColumns');
}

protected _isColumnVisible(column) {
return super._isColumnVisible(column) && !column.adaptiveHidden;
}

public getVisibleDataColumnsByBandColumn(bandColumnIndex: number) {
return super.getVisibleDataColumnsByBandColumn(bandColumnIndex)
.filter((column) => column.visibleWidth !== HIDDEN_COLUMNS_WIDTH);
}

public isAdaptiveHiddenColumn(column: Column): boolean {
return super.isAdaptiveHiddenColumn(column)
|| this.adaptiveColumnsController.isColumnHidden(column);
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/* eslint-disable @stylistic/max-len */
/* eslint-disable @typescript-eslint/explicit-function-return-type */
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable no-plusplus */
import type { dxElementWrapper } from '@js/core/renderer';
import type { ColumnsResizerViewController } from '@ts/grids/grid_core/columns_resizing_reordering/m_columns_resizing_reordering';
import type { ModuleType } from '@ts/grids/grid_core/m_types';

import { HIDDEN_COLUMNS_WIDTH } from '../const';

export const adaptivityColumnsResizerViewControllerExtender = (
Base: ModuleType<ColumnsResizerViewController>,
): ModuleType<ColumnsResizerViewController> => class AdaptivityColumnsResizerViewControllerExtender extends Base {
protected _pointCreated(point, columns, cells?: dxElementWrapper) {
const result = super._pointCreated(point, columns, cells);
const currentColumn = columns[point.columnIndex] || {};
const nextColumnIndex = this._getNextColumnIndex(point.columnIndex);
const nextColumn = columns[nextColumnIndex] || {};
const hasHiddenColumnsOnly = nextColumnIndex !== point.columnIndex + 1 && nextColumn.command;
const hasAdaptiveHiddenWidth = currentColumn.visibleWidth === HIDDEN_COLUMNS_WIDTH || hasHiddenColumnsOnly;

return result || hasAdaptiveHiddenWidth;
}

protected _getNextColumnIndex(currentColumnIndex) {
const visibleColumns = this._columnsController.getVisibleColumns();
let index = super._getNextColumnIndex(currentColumnIndex);

while (visibleColumns[index]?.visibleWidth === HIDDEN_COLUMNS_WIDTH) {
index++;
}

return index;
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import { isDefined } from '@js/core/utils/type';
import type { DataController } from '@ts/grids/grid_core/data_controller/data_controller';
import type { DataChange, ProcessedItem } from '@ts/grids/grid_core/data_controller/types';
import type { RawItemData } from '@ts/grids/grid_core/data_source_adapter/types';
import type { ModuleType, RowKey } from '@ts/grids/grid_core/m_types';
import gridCoreUtils from '@ts/grids/grid_core/m_utils';

import {
ADAPTIVE_ROW_TYPE,
COLLAPSE_ARIA_NAME,
EXPAND_ARIA_NAME,
LEGACY_SCROLLING_MODE,
} from '../const';
import type { AdaptiveColumnsController } from '../m_adaptivity';
import { getAdaptiveDetailRowIndex, resolveAdaptiveDetailRowTarget } from '../utils';

export const adaptivityDataControllerExtender = (
Base: ModuleType<DataController>,
): ModuleType<DataController> => class AdaptivityDataControllerExtender extends Base {
private adaptiveExpandedKey: RowKey | undefined;

protected adaptiveColumnsController!: AdaptiveColumnsController;

public init(): void {
super.init();
this.adaptiveExpandedKey = undefined;
this.adaptiveColumnsController = this.getController('adaptiveColumns');
}

protected _processItems(items: RawItemData[], change: DataChange): ProcessedItem[] {
const processedItems = super._processItems(items, change);
const { changeType } = change;

if ((changeType === 'loadingAll') || !isDefined(this.adaptiveExpandedKey)) {
return processedItems;
}

const expandRowIndex = gridCoreUtils.getIndexByKey(this.adaptiveExpandedKey, processedItems);
const newMode = this.option(LEGACY_SCROLLING_MODE) === false;

if (expandRowIndex >= 0) {
const item = processedItems[expandRowIndex];
processedItems.splice(expandRowIndex + 1, 0, {
visible: true,
rowType: ADAPTIVE_ROW_TYPE,
key: item.key,
data: item.data,
// @ts-expect-error treelist specific field
node: item.node,
modifiedValues: item.modifiedValues,
isNewRow: item.isNewRow,
values: item.values,
});
} else if (changeType === 'refresh' && !(newMode && change.repaintChangesOnly)) {
this.adaptiveExpandedKey = undefined;
}

return processedItems;
}

protected getRowIndicesForExpand(key: RowKey): number[] {
const rowIndices = super.getRowIndicesForExpand(key);

if (this.adaptiveColumnsController.isAdaptiveDetailRowExpanded(key)) {
const lastRowIndex = rowIndices[rowIndices.length - 1];

rowIndices.push(lastRowIndex + 1);
}

return rowIndices;
}

public toggleExpandAdaptiveDetailRow(key?: RowKey, alwaysExpanded = false): void {
const oldKey = this.adaptiveExpandedKey;
const oldRowIndex = gridCoreUtils.getIndexByKey(oldKey, this._items);

const target = resolveAdaptiveDetailRowTarget(
key,
gridCoreUtils.getIndexByKey(key, this._items),
oldRowIndex,
alwaysExpanded,
);

this.adaptiveExpandedKey = target.key;

this.updateAdaptiveDetailRows(oldRowIndex, target.rowIndex);
this.updateAdaptiveAriaLabels(target.key, oldKey);
}

private updateAdaptiveDetailRows(oldRowIndex: number, newRowIndex: number): void {
const rowIndexDelta = this.getRowIndexDelta();

this.updateItems({
allowInvisibleRowIndices: true,
changeType: 'update',
rowIndices: [oldRowIndex, newRowIndex]
.map((rowIndex) => getAdaptiveDetailRowIndex(rowIndex, rowIndexDelta)),
});
}

private updateAdaptiveAriaLabels(
expandedKey: RowKey | undefined,
collapsedKey: RowKey | undefined,
): void {
this.adaptiveColumnsController.updateCommandAdaptiveAriaLabel(expandedKey, COLLAPSE_ARIA_NAME);
this.adaptiveColumnsController.updateCommandAdaptiveAriaLabel(collapsedKey, EXPAND_ARIA_NAME);
}

public getAdaptiveExpandedKey(): RowKey | undefined {
return this.adaptiveExpandedKey;
}

public setAdaptiveExpandedKey(key: RowKey): void {
this.adaptiveExpandedKey = key;
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/* eslint-disable @typescript-eslint/explicit-function-return-type */
import type { DraggingHeaderViewController } from '@ts/grids/grid_core/columns_resizing_reordering/m_columns_resizing_reordering';
import type { ModuleType } from '@ts/grids/grid_core/m_types';

import { HIDDEN_COLUMNS_WIDTH } from '../const';

export const adaptivityDraggingHeaderViewControllerExtender = (
Base: ModuleType<DraggingHeaderViewController>,
): ModuleType<DraggingHeaderViewController> => class AdaptivityDraggingHeaderViewControllerExtender
extends Base {
protected _pointCreated({
point, columns, location, sourceColumn, cells,
}) {
const result = super._pointCreated({
point, columns, location, sourceColumn, cells,
});
const column = columns[point.columnIndex - 1] || {};
const hasAdaptiveHiddenWidth = column.visibleWidth === HIDDEN_COLUMNS_WIDTH;

return result || hasAdaptiveHiddenWidth;
}
};
Loading
Loading