Skip to content

Commit 1c14588

Browse files
mofojedAkshatJawne
andauthored
fix: Input Tables cannot paste more rows than number of visible rows (DH-18723) (#2371)
- cherry-picked from #2053 and #2152 - Resolves #2089 - I published an alpha package and tested it against dev-jackson2 with the test steps from DH-18184 --------- Co-authored-by: Akshat Jawne <[email protected]>
1 parent 301af0d commit 1c14588

File tree

4 files changed

+72
-35
lines changed

4 files changed

+72
-35
lines changed

packages/grid/src/Grid.tsx

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1326,6 +1326,7 @@ class Grid extends PureComponent<GridProps, GridState> {
13261326
const { columnCount, rowCount } = model;
13271327
let ranges = selectedRanges;
13281328
// If each cell is a single selection, we need to update the selection to map to the newly pasted data
1329+
// Check for
13291330
if (
13301331
ranges.every(
13311332
range =>
@@ -1347,16 +1348,6 @@ class Grid extends PureComponent<GridProps, GridState> {
13471348
this.setSelectedRanges(ranges);
13481349
}
13491350

1350-
if (
1351-
!ranges.every(
1352-
range =>
1353-
GridRange.rowCount([range]) === tableHeight &&
1354-
GridRange.columnCount([range]) === tableWidth
1355-
)
1356-
) {
1357-
throw new PasteError('Copy and paste area are not same size.');
1358-
}
1359-
13601351
const edits: EditOperation[] = [];
13611352
ranges.forEach(range => {
13621353
for (let x = 0; x < tableWidth; x += 1) {

packages/grid/src/GridMetricCalculator.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -762,9 +762,13 @@ export class GridMetricCalculator {
762762
visibleWidth: number = this.getVisibleWidth(state)
763763
): VisibleIndex {
764764
const { model } = state;
765-
const { columnCount } = model;
765+
const { columnCount, floatingRightColumnCount } = model;
766+
767+
if (columnCount === 0) {
768+
return 0;
769+
}
766770

767-
let lastLeft = columnCount - 1;
771+
let lastLeft = Math.max(0, columnCount - floatingRightColumnCount - 1);
768772
if (right != null) {
769773
lastLeft = right;
770774
}

packages/iris-grid/src/IrisGridModel.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,17 @@ import type {
2323
import { Formatter } from '@deephaven/jsapi-utils';
2424

2525
type RowIndex = ModelIndex;
26+
type ColumnName = string;
2627

2728
type IrisGridModelEventNames = typeof IrisGridModel.EVENT[keyof typeof IrisGridModel.EVENT];
2829

2930
type IrisGridModelEventMap = {
3031
[E in IrisGridModelEventNames]: Event<E>;
3132
};
3233

34+
const EMPTY_ARRAY: never[] = [];
35+
const EMPTY_SET: Set<never> = new Set();
36+
3337
/**
3438
* Abstract class that extends the GridModel to have more functionality, like filtering and sorting.
3539
* For use from IrisGrid.
@@ -134,12 +138,12 @@ abstract class IrisGridModel<
134138

135139
/** List of column movements defined by the model. Used as initial movements for IrisGrid */
136140
get movedColumns(): MoveOperation[] {
137-
return [];
141+
return EMPTY_ARRAY;
138142
}
139143

140144
/** List of row movements defined by the model. Used as initial movements for IrisGrid */
141145
get movedRows(): MoveOperation[] {
142-
return [];
146+
return EMPTY_ARRAY;
143147
}
144148

145149
/**
@@ -262,21 +266,28 @@ abstract class IrisGridModel<
262266
* @returns Names of columns which should be locked to the front, but not floating
263267
*/
264268
get frontColumns(): string[] {
265-
return [];
269+
return EMPTY_ARRAY;
266270
}
267271

268272
/**
269273
* @returns Names of columns which should be locked to the back, but not floating
270274
*/
271275
get backColumns(): string[] {
272-
return [];
276+
return EMPTY_ARRAY;
277+
}
278+
279+
/**
280+
* @returns Names of key columns
281+
*/
282+
get keyColumnSet(): Set<ColumnName> {
283+
return EMPTY_SET;
273284
}
274285

275286
/**
276287
* @returns Names of columns which should be frozen to the front and floating
277288
*/
278289
get frozenColumns(): string[] {
279-
return [];
290+
return EMPTY_ARRAY;
280291
}
281292

282293
/**

packages/iris-grid/src/IrisGridTableModel.js

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const log = Log.module('IrisGridTableModel');
1515

1616
const SET_VIEWPORT_THROTTLE = 150;
1717
const APPLY_VIEWPORT_THROTTLE = 0;
18+
const EMPTY_ARRAY = Object.freeze([]);
1819

1920
/**
2021
* Model for a grid showing an iris data table
@@ -544,16 +545,24 @@ class IrisGridTableModel extends IrisGridModel {
544545
return this.getMemoizedColumnMap(this.table.columns);
545546
}
546547

548+
getMemoizedKeyColumnSet = memoize(
549+
inputTableKeys => new Set(inputTableKeys ?? EMPTY_ARRAY)
550+
);
551+
552+
get keyColumnSet() {
553+
return this.getMemoizedKeyColumnSet(this.inputTable?.keys);
554+
}
555+
547556
getMemoizedFrontColumns = memoize(
548-
layoutHintsFrontColumns => layoutHintsFrontColumns ?? []
557+
layoutHintsFrontColumns => layoutHintsFrontColumns ?? EMPTY_ARRAY
549558
);
550559

551560
get frontColumns() {
552561
return this.getMemoizedFrontColumns(this.layoutHints?.frontColumns);
553562
}
554563

555564
getMemoizedBackColumns = memoize(
556-
layoutHintsBackColumns => layoutHintsBackColumns ?? []
565+
layoutHintsBackColumns => layoutHintsBackColumns ?? EMPTY_ARRAY
557566
);
558567

559568
get backColumns() {
@@ -562,7 +571,7 @@ class IrisGridTableModel extends IrisGridModel {
562571

563572
getMemoizedFrozenColumns = memoize(
564573
(layoutHintsFrozenColumns, userFrozenColumns) =>
565-
userFrozenColumns ?? layoutHintsFrozenColumns ?? []
574+
userFrozenColumns ?? layoutHintsFrozenColumns ?? EMPTY_ARRAY
566575
);
567576

568577
get frozenColumns() {
@@ -581,7 +590,7 @@ class IrisGridTableModel extends IrisGridModel {
581590
}
582591

583592
get groupedColumns() {
584-
return [];
593+
return EMPTY_ARRAY;
585594
}
586595

587596
get description() {
@@ -654,7 +663,7 @@ class IrisGridTableModel extends IrisGridModel {
654663
*/
655664
pendingRow(y) {
656665
const pendingRow = y - this.floatingTopRowCount - this.table.size;
657-
if (pendingRow >= 0 && pendingRow < this.pendingNewRowCount) {
666+
if (pendingRow >= 0) {
658667
return pendingRow;
659668
}
660669

@@ -1252,26 +1261,48 @@ class IrisGridTableModel extends IrisGridModel {
12521261
}
12531262

12541263
isKeyColumn(x) {
1255-
return x < (this.inputTable?.keyColumns.length ?? 0);
1264+
return this.keyColumnSet.has(this.columns[x].name);
12561265
}
12571266

12581267
isRowMovable() {
12591268
return false;
12601269
}
12611270

12621271
isEditableRange(range) {
1263-
return (
1264-
this.inputTable != null &&
1265-
GridRange.isBounded(range) &&
1266-
((this.isPendingRow(range.startRow) && this.isPendingRow(range.endRow)) ||
1267-
(range.startColumn >= this.inputTable.keyColumns.length &&
1268-
range.endColumn >= this.inputTable.keyColumns.length)) &&
1269-
range.startRow >= this.floatingTopRowCount &&
1270-
range.startRow <
1271-
this.floatingTopRowCount + this.table.size + this.pendingRowCount &&
1272-
range.endRow <
1273-
this.floatingTopRowCount + this.table.size + this.pendingRowCount
1274-
);
1272+
// Make sure we have an input table and a valid range
1273+
if (
1274+
this.inputTable == null ||
1275+
range.startRow == null ||
1276+
range.endRow == null
1277+
) {
1278+
return false;
1279+
}
1280+
1281+
// Check that the edit is in the editable range
1282+
// If an input table has keyed columns, the non-key columns are always editable
1283+
// If an input table does not have key columns, it is append only and existing rows cannot be editable
1284+
// Pending rows are always editable
1285+
const isPendingRange =
1286+
this.isPendingRow(range.startRow) && this.isPendingRow(range.endRow);
1287+
1288+
let isKeyColumnInRange = false;
1289+
1290+
// Check if any of the columns in grid range are key columns
1291+
const bound = range.endColumn ?? this.table.size;
1292+
for (let column = range.startColumn; column <= bound; column += 1) {
1293+
if (this.isKeyColumn(column)) {
1294+
isKeyColumnInRange = true;
1295+
break;
1296+
}
1297+
}
1298+
1299+
if (
1300+
!(isPendingRange || (this.keyColumnSet.size !== 0 && !isKeyColumnInRange))
1301+
) {
1302+
return false;
1303+
}
1304+
1305+
return true;
12751306
}
12761307

12771308
isDeletableRange(range) {

0 commit comments

Comments
 (0)