Skip to content
Merged
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
11 changes: 1 addition & 10 deletions packages/grid/src/Grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1326,6 +1326,7 @@ class Grid extends PureComponent<GridProps, GridState> {
const { columnCount, rowCount } = model;
let ranges = selectedRanges;
// If each cell is a single selection, we need to update the selection to map to the newly pasted data
// Check for
if (
ranges.every(
range =>
Expand All @@ -1347,16 +1348,6 @@ class Grid extends PureComponent<GridProps, GridState> {
this.setSelectedRanges(ranges);
}

if (
!ranges.every(
range =>
GridRange.rowCount([range]) === tableHeight &&
GridRange.columnCount([range]) === tableWidth
)
) {
throw new PasteError('Copy and paste area are not same size.');
}

const edits: EditOperation[] = [];
ranges.forEach(range => {
for (let x = 0; x < tableWidth; x += 1) {
Expand Down
8 changes: 6 additions & 2 deletions packages/grid/src/GridMetricCalculator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -762,9 +762,13 @@ export class GridMetricCalculator {
visibleWidth: number = this.getVisibleWidth(state)
): VisibleIndex {
const { model } = state;
const { columnCount } = model;
const { columnCount, floatingRightColumnCount } = model;

if (columnCount === 0) {
return 0;
}

let lastLeft = columnCount - 1;
let lastLeft = Math.max(0, columnCount - floatingRightColumnCount - 1);
if (right != null) {
lastLeft = right;
}
Expand Down
21 changes: 16 additions & 5 deletions packages/iris-grid/src/IrisGridModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,17 @@ import type {
import { Formatter } from '@deephaven/jsapi-utils';

type RowIndex = ModelIndex;
type ColumnName = string;

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

type IrisGridModelEventMap = {
[E in IrisGridModelEventNames]: Event<E>;
};

const EMPTY_ARRAY: never[] = [];
const EMPTY_SET: Set<never> = new Set();

/**
* Abstract class that extends the GridModel to have more functionality, like filtering and sorting.
* For use from IrisGrid.
Expand Down Expand Up @@ -134,12 +138,12 @@ abstract class IrisGridModel<

/** List of column movements defined by the model. Used as initial movements for IrisGrid */
get movedColumns(): MoveOperation[] {
return [];
return EMPTY_ARRAY;
}

/** List of row movements defined by the model. Used as initial movements for IrisGrid */
get movedRows(): MoveOperation[] {
return [];
return EMPTY_ARRAY;
}

/**
Expand Down Expand Up @@ -262,21 +266,28 @@ abstract class IrisGridModel<
* @returns Names of columns which should be locked to the front, but not floating
*/
get frontColumns(): string[] {
return [];
return EMPTY_ARRAY;
}

/**
* @returns Names of columns which should be locked to the back, but not floating
*/
get backColumns(): string[] {
return [];
return EMPTY_ARRAY;
}

/**
* @returns Names of key columns
*/
get keyColumnSet(): Set<ColumnName> {
return EMPTY_SET;
}

/**
* @returns Names of columns which should be frozen to the front and floating
*/
get frozenColumns(): string[] {
return [];
return EMPTY_ARRAY;
}

/**
Expand Down
67 changes: 49 additions & 18 deletions packages/iris-grid/src/IrisGridTableModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const log = Log.module('IrisGridTableModel');

const SET_VIEWPORT_THROTTLE = 150;
const APPLY_VIEWPORT_THROTTLE = 0;
const EMPTY_ARRAY = Object.freeze([]);

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

getMemoizedKeyColumnSet = memoize(
inputTableKeys => new Set(inputTableKeys ?? EMPTY_ARRAY)
);

get keyColumnSet() {
return this.getMemoizedKeyColumnSet(this.inputTable?.keys);
}

getMemoizedFrontColumns = memoize(
layoutHintsFrontColumns => layoutHintsFrontColumns ?? []
layoutHintsFrontColumns => layoutHintsFrontColumns ?? EMPTY_ARRAY
);

get frontColumns() {
return this.getMemoizedFrontColumns(this.layoutHints?.frontColumns);
}

getMemoizedBackColumns = memoize(
layoutHintsBackColumns => layoutHintsBackColumns ?? []
layoutHintsBackColumns => layoutHintsBackColumns ?? EMPTY_ARRAY
);

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

getMemoizedFrozenColumns = memoize(
(layoutHintsFrozenColumns, userFrozenColumns) =>
userFrozenColumns ?? layoutHintsFrozenColumns ?? []
userFrozenColumns ?? layoutHintsFrozenColumns ?? EMPTY_ARRAY
);

get frozenColumns() {
Expand All @@ -581,7 +590,7 @@ class IrisGridTableModel extends IrisGridModel {
}

get groupedColumns() {
return [];
return EMPTY_ARRAY;
}

get description() {
Expand Down Expand Up @@ -654,7 +663,7 @@ class IrisGridTableModel extends IrisGridModel {
*/
pendingRow(y) {
const pendingRow = y - this.floatingTopRowCount - this.table.size;
if (pendingRow >= 0 && pendingRow < this.pendingNewRowCount) {
if (pendingRow >= 0) {
return pendingRow;
}

Expand Down Expand Up @@ -1252,26 +1261,48 @@ class IrisGridTableModel extends IrisGridModel {
}

isKeyColumn(x) {
return x < (this.inputTable?.keyColumns.length ?? 0);
return this.keyColumnSet.has(this.columns[x].name);
}

isRowMovable() {
return false;
}

isEditableRange(range) {
return (
this.inputTable != null &&
GridRange.isBounded(range) &&
((this.isPendingRow(range.startRow) && this.isPendingRow(range.endRow)) ||
(range.startColumn >= this.inputTable.keyColumns.length &&
range.endColumn >= this.inputTable.keyColumns.length)) &&
range.startRow >= this.floatingTopRowCount &&
range.startRow <
this.floatingTopRowCount + this.table.size + this.pendingRowCount &&
range.endRow <
this.floatingTopRowCount + this.table.size + this.pendingRowCount
);
// Make sure we have an input table and a valid range
if (
this.inputTable == null ||
range.startRow == null ||
range.endRow == null
) {
return false;
}

// Check that the edit is in the editable range
// If an input table has keyed columns, the non-key columns are always editable
// If an input table does not have key columns, it is append only and existing rows cannot be editable
// Pending rows are always editable
const isPendingRange =
this.isPendingRow(range.startRow) && this.isPendingRow(range.endRow);

let isKeyColumnInRange = false;

// Check if any of the columns in grid range are key columns
const bound = range.endColumn ?? this.table.size;
for (let column = range.startColumn; column <= bound; column += 1) {
if (this.isKeyColumn(column)) {
isKeyColumnInRange = true;
break;
}
}

if (
!(isPendingRange || (this.keyColumnSet.size !== 0 && !isKeyColumnInRange))
) {
return false;
}

return true;
}

isDeletableRange(range) {
Expand Down
Loading