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,179 @@
import type { DataChange as EditingDataChange } from '@js/common/grids';
import { equalByValue } from '@js/core/utils/common';
import type { DeferredObj } from '@js/core/utils/deferred';
import type { DataController } from '@ts/grids/grid_core/data_controller/data_controller';
import type {
Cell,
DataChange,
GeneratedItem,
ItemProcessingOptions,
ProcessedItem,
UpdateChange,
} from '@ts/grids/grid_core/data_controller/types';
import type { RawItemData } from '@ts/grids/grid_core/data_source_adapter/types';
import type { ModuleType, OptionChanged } from '@ts/grids/grid_core/m_types';
import gridCoreUtils from '@ts/grids/grid_core/m_utils';

import { EDITING_EDITROWKEY_OPTION_NAME } from '../const';
import type { EditingController } from '../m_editing';

type EditingCell = Cell & { isEditing?: boolean };

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't it be shared type?


export const dataControllerEditingExtenderMixin = (

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
export const dataControllerEditingExtenderMixin = (
export const editingDataControllerExtender = (

Base: ModuleType<DataController>,
): ModuleType<DataController> => class DataControllerEditingExtender extends Base {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
): ModuleType<DataController> => class DataControllerEditingExtender extends Base {
): ModuleType<DataController> => class EditingDataControllerExtender extends Base {

protected _editingController!: EditingController;

public init(): void {
this._editingController = this.getController('editing');
super.init();
}

public reload(full?: boolean, repaintChangesOnly?: boolean): DeferredObj<unknown> {
if (!repaintChangesOnly) {
this._editingController.refresh();
}

return super.reload(full, repaintChangesOnly);
}

public repaintRows(
rowIndexes: number | (number | undefined)[] | undefined,
changesOnly?: boolean,
): void {
if (this._editingController.isSaving()) {
return;
}

super.repaintRows(rowIndexes, changesOnly);
}

private _updateEditRow(items: ProcessedItem[] | undefined): void {
if (!items) {
return;
}

const editRowKey = this.option(EDITING_EDITROWKEY_OPTION_NAME);
const editRowIndex = gridCoreUtils.getIndexByKey(editRowKey, items);
const editItem = items[editRowIndex];
if (editItem) {
editItem.isEditing = true;
// @ts-expect-error Badly typed based class
this._updateEditItem?.(editItem);
}
}

protected _updateItemsCore(change: DataChange): void {
super._updateItemsCore(change);
this._updateEditRow(this.items(true));
}

protected applyChangeUpdate(change: UpdateChange): void {
this._updateEditRow(change.items);
super.applyChangeUpdate(change);
}

protected applyChangesOnly(change: DataChange): void {
this._updateEditRow(change.items);
super.applyChangesOnly(change);
}

protected _processItems(items: RawItemData[], change: DataChange): ProcessedItem[] {
const editingItems = this._editingController.processItems(items, change);
return super._processItems(editingItems, change);
}

protected _processDataItem(
generatedItem: GeneratedItem,
options: ItemProcessingOptions,
): ProcessedItem {
this._editingController.processDataItem(generatedItem, options);
return super._processDataItem(generatedItem, options);
}

protected _processItem(dataItem: RawItemData, options: ItemProcessingOptions): ProcessedItem {
const processedItem = super._processItem(dataItem, options);

if (processedItem.isNewRow) {
options.dataIndex -= 1;
delete processedItem.dataIndex;
}

return processedItem;
}

protected _getChangedColumnIndices(
oldItem: ProcessedItem,
newItem: ProcessedItem,
visibleRowIndex: number,
isLiveUpdate?: boolean,
): number[] | undefined {
if (oldItem.isNewRow !== newItem.isNewRow || oldItem.removed !== newItem.removed) {
return undefined;
}

return super._getChangedColumnIndices(oldItem, newItem, visibleRowIndex, isLiveUpdate);
}

protected _isCellChanged(
oldRow: ProcessedItem,
newRow: ProcessedItem,
visibleRowIndex: number,
columnIndex: number,
isLiveUpdate?: boolean,
): boolean {
const cell = oldRow.cells?.[columnIndex] as EditingCell | undefined;
const isEditing = this._editingController
&& this._editingController.isEditCell(visibleRowIndex, columnIndex);

if (isLiveUpdate && isEditing) {
return false;
}

if (cell?.column && !cell.column.showEditorAlways && cell.isEditing !== isEditing) {
return true;
}

return super._isCellChanged(oldRow, newRow, visibleRowIndex, columnIndex, isLiveUpdate);
}

protected needToRefreshOnDataSourceChange(args?: OptionChanged): boolean {
const value = args?.value;
const isParasiteChange = Array.isArray(value)
&& value === args?.previousValue
&& this._editingController.isSaving();
return !isParasiteChange;
}

protected _handleDataSourceChange(args: OptionChanged): boolean {
const result = super._handleDataSourceChange(args);
const dataSource = args.value;
if (Array.isArray(dataSource)) {
this._dropEditingStateForRemovedItems(dataSource);
}
return result;
}

private _dropEditingStateForRemovedItems(dataSource: RawItemData[]): void {
const changes = this.option('editing.changes') as EditingDataChange[];
if (!changes.length) {
return;
}

const dataSourceKeys = dataSource.map((item) => this.keyOf(item));
const survivingChanges = changes.filter(
(change) => change.type === 'insert' || dataSourceKeys.some((key) => equalByValue(change.key, key)),
);
if (survivingChanges.length !== changes.length) {
this.option('editing.changes', survivingChanges);
}

const editRowKey = this.option('editing.editRowKey');
const isEditingNewRow = survivingChanges.some(
(change) => change.type === 'insert' && equalByValue(editRowKey, change.key),
);
if (!isEditingNewRow && dataSourceKeys.every((key) => !equalByValue(editRowKey, key))) {
this.option('editing.editRowKey', undefined);
}
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import type { DataController } from '@ts/grids/grid_core/data_controller/data_controller';
import type { ProcessedItem } from '@ts/grids/grid_core/data_controller/types';
import type { ModuleType } from '@ts/grids/grid_core/m_types';

import type { EditingController } from '../m_editing';

export const dataControllerEditingFormBasedExtender = (

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
export const dataControllerEditingFormBasedExtender = (
export const editingFormBasedDataControllerExtender = (

Base: ModuleType<DataController>,
): ModuleType<DataController> => class DataEditingFormBasedExtender extends Base {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
): ModuleType<DataController> => class DataEditingFormBasedExtender extends Base {
): ModuleType<DataController> => class EditingFormBasedDataControllerExtender extends Base {

protected _editingController!: EditingController;

public init(): void {
this._editingController = this.getController('editing');
super.init();
}

private _updateEditItem(item: ProcessedItem): void {
// @ts-expect-error isFormEditMode is private on the editing controller
if (this._editingController.isFormEditMode()) {
item.rowType = 'detail';
}
}

protected _getChangedColumnIndices(
oldItem: ProcessedItem,
newItem: ProcessedItem,
visibleRowIndex: number,
isLiveUpdate?: boolean,
): number[] | undefined {
// @ts-expect-error isFormEditMode is private on the editing controller
if (isLiveUpdate === false && newItem.isEditing && this._editingController.isFormEditMode()) {
return undefined;
}

return super._getChangedColumnIndices(oldItem, newItem, visibleRowIndex, isLiveUpdate);
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import type { DataController } from '@ts/grids/grid_core/data_controller/data_controller';
import type { ProcessedItem } from '@ts/grids/grid_core/data_controller/types';
import type { ModuleType } from '@ts/grids/grid_core/m_types';

import type { EditingController } from '../m_editing';

export const dataControllerEditingRowBasedExtender = (

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
export const dataControllerEditingRowBasedExtender = (
export const editingRowBasedDataControllerExtender = (

Base: ModuleType<DataController>,
): ModuleType<DataController> => class DataEditingRowBasedExtender extends Base {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
): ModuleType<DataController> => class DataEditingRowBasedExtender extends Base {
): ModuleType<DataController> => class EditingRowBasedDataControllerExtender extends Base {

protected _editingController!: EditingController;

public init(): void {
this._editingController = this.getController('editing');
super.init();
}

protected _getChangedColumnIndices(
oldItem: ProcessedItem,
newItem: ProcessedItem,
visibleRowIndex: number,
isLiveUpdate?: boolean,
): number[] | undefined {
if (this._editingController.isRowBasedEditMode() && oldItem.isEditing !== newItem.isEditing) {
return undefined;
}

return super._getChangedColumnIndices(oldItem, newItem, visibleRowIndex, isLiveUpdate);
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ import {
VIEWPORT_BOTTOM_NEW_ROW_POSITION,
VIEWPORT_TOP_NEW_ROW_POSITION,
} from './const';
import { dataControllerEditingExtenderMixin } from './extenders/editing_data_controller';
import type { ICellBasedEditingControllerExtender } from './m_editing_cell_based';
import type { IFormBasedEditingControllerExtender } from './m_editing_form_based';
import {
Expand Down Expand Up @@ -2544,117 +2545,7 @@ export type EditingController = EditingControllerImpl
& ICellBasedEditingControllerExtender
& IFormBasedEditingControllerExtender;

export const dataControllerEditingExtenderMixin = (Base: ModuleType<DataController>) => class DataControllerEditingExtender extends Base {
public reload(full, repaintChangesOnly) {
!repaintChangesOnly && this._editingController.refresh();

return super.reload.apply(this, arguments as any);
}

public repaintRows() {
if (this._editingController.isSaving()) return;
return super.repaintRows.apply(this, arguments as any);
}

private _updateEditRow(items) {
const editRowKey = this.option(EDITING_EDITROWKEY_OPTION_NAME);
const editRowIndex = gridCoreUtils.getIndexByKey(editRowKey, items);
const editItem = items[editRowIndex];
if (editItem) {
editItem.isEditing = true;
// @ts-expect-error Badly typed based class
this._updateEditItem?.(editItem);
}
}

protected _updateItemsCore(change: DataChange): void {
super._updateItemsCore(change);
this._updateEditRow(this.items(true));
}

protected applyChangeUpdate(change) {
this._updateEditRow(change.items);
super.applyChangeUpdate(change);
}

protected applyChangesOnly(change) {
this._updateEditRow(change.items);
super.applyChangesOnly(change);
}

protected _processItems(items: RawItemData[], change: DataChange): ProcessedItem[] {
items = this._editingController.processItems(items, change);
return super._processItems(items, change);
}

protected _processDataItem(
generatedItem: GeneratedItem,
options: ItemProcessingOptions,
): ProcessedItem {
this._editingController.processDataItem(generatedItem, options);
return super._processDataItem(generatedItem, options);
}

protected _processItem(dataItem: RawItemData, options: ItemProcessingOptions) {
const processedItem = super._processItem(dataItem, options);

if (processedItem.isNewRow) {
options.dataIndex--;
delete processedItem.dataIndex;
}

return processedItem;
}

protected _getChangedColumnIndices(oldItem, newItem, rowIndex, isLiveUpdate) {
if (oldItem.isNewRow !== newItem.isNewRow || oldItem.removed !== newItem.removed) {
return;
}

return super._getChangedColumnIndices.apply(this, arguments as any);
}

protected _isCellChanged(oldRow, newRow, visibleRowIndex, columnIndex, isLiveUpdate) {
const cell = oldRow.cells && oldRow.cells[columnIndex];
const isEditing = this._editingController && this._editingController.isEditCell(visibleRowIndex, columnIndex);

if (isLiveUpdate && isEditing) {
return false;
}

if (cell && cell.column && !cell.column.showEditorAlways && cell.isEditing !== isEditing) {
return true;
}

return super._isCellChanged.apply(this, arguments as any);
}

protected needToRefreshOnDataSourceChange(args) {
const isParasiteChange = Array.isArray(args.value) && args.value === args.previousValue && this._editingController.isSaving();
return !isParasiteChange;
}

protected _handleDataSourceChange(args) {
const result = super._handleDataSourceChange(args);
const changes: any = this.option('editing.changes');
const dataSource = args.value;
if (Array.isArray(dataSource) && changes.length) {
const dataSourceKeys = dataSource.map((item) => this.keyOf(item));
const newChanges = changes.filter((change) => change.type === 'insert' || dataSourceKeys.some((key) => equalByValue(change.key, key)));
if (newChanges.length !== changes.length) {
this.option('editing.changes', newChanges);
}
const editRowKey = this.option('editing.editRowKey');
const isEditNewItem = newChanges.some(
(change) => change.type === 'insert' && equalByValue(editRowKey, change.key),
);
if (!isEditNewItem && dataSourceKeys.every((key) => !equalByValue(editRowKey, key))) {
this.option('editing.editRowKey', undefined);
}
}
return result;
}
};
export { dataControllerEditingExtenderMixin };

const rowsView = (Base: ModuleType<RowsView>) => class RowsViewEditingExtender extends Base {
private _pointerDownTarget: any;
Expand Down
Loading
Loading