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
2 changes: 2 additions & 0 deletions packages/dashboard-core-plugins/src/panels/IrisGridPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1022,6 +1022,8 @@ export class IrisGridPanel extends PureComponent<
rollupConfig,
aggregationSettings,
sorts,
// TODO:
// DH-20403: IrisGrid should persist user column widths when the model initializes with a partial column list
userColumnWidths,
userRowHeights,
showSearchBar,
Expand Down
29 changes: 29 additions & 0 deletions packages/grid/src/ExpandableColumnGridModel.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { isExpandableColumnGridModel } from './ExpandableColumnGridModel';
import type GridModel from './GridModel';
import type ExpandableColumnGridModel from './ExpandableColumnGridModel';

describe('ExpandableColumnGridModel', () => {
describe('isExpandableColumnGridModel', () => {
it('should return true for model with hasExpandableColumns property', () => {
const model = {
hasExpandableColumns: true,
} as ExpandableColumnGridModel;

expect(isExpandableColumnGridModel(model)).toBe(true);
});

it('should return true when hasExpandableColumns is false', () => {
const model = {
hasExpandableColumns: false,
} as ExpandableColumnGridModel;

expect(isExpandableColumnGridModel(model)).toBe(true);
});

it('should return false for model without hasExpandableColumns property', () => {
const model = {} as GridModel;

expect(isExpandableColumnGridModel(model)).toBe(false);
});
});
});
64 changes: 64 additions & 0 deletions packages/grid/src/ExpandableColumnGridModel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import type GridModel from './GridModel';
import { type ModelIndex } from './GridMetrics';

export function isExpandableColumnGridModel(
model: GridModel
): model is ExpandableColumnGridModel {
return (
(model as ExpandableColumnGridModel)?.hasExpandableColumns !== undefined
);
}

/**
* Expandable grid model. Allows for a grid with columns that can expand (e.g. Pivot Table)
*/
export interface ExpandableColumnGridModel extends GridModel {
/** Whether the grid has columns that can be expanded */
hasExpandableColumns: boolean;

/** Whether the grid can expand all columns */
isExpandAllColumnsAvailable: boolean;

/**
* @param column Column to check
* @returns True if the column is expandable
*/
isColumnExpandable: (column: ModelIndex) => boolean;

/**
* @param column Column to check
* @returns True if the column is currently expanded
*/
isColumnExpanded: (column: ModelIndex) => boolean;

/**
* Change the expanded status of an expandable column
* @param column Column to expand
* @param isExpanded True to expand the column, false to collapse
* @param expandDescendants True to expand nested columns, false otherwise
*/
setColumnExpanded: (
column: ModelIndex,
isExpanded: boolean,
expandDescendants?: boolean
) => void;

/**
* Expand all columns
*/
expandAllColumns: () => void;

/**
* Collapse all columns
*/
collapseAllColumns: () => void;

/**
* Get the depth of a column (ie. How indented the column should be)
* @param column Column to check
* @returns Depth of the column
*/
depthForColumn: (column: ModelIndex) => number;
}

export default ExpandableColumnGridModel;
1 change: 1 addition & 0 deletions packages/grid/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export * from './ColumnHeaderGroup';
export * from './EditableGridModel';
export * from './DeletableGridModel';
export * from './ExpandableGridModel';
export * from './ExpandableColumnGridModel';
export { default as Grid } from './Grid';
export * from './Grid';
export * from './GridMetricCalculator';
Expand Down
18 changes: 10 additions & 8 deletions packages/iris-grid/src/ColumnHeaderGroup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ export function isColumnHeaderGroup(x: unknown): x is ColumnHeaderGroup {
return x instanceof ColumnHeaderGroup;
}

export type ColumnHeaderGroupConfig = {
name: string;
children: string[];
color?: string | null;
depth: number;
childIndexes: ModelIndex[];
parent?: string;
};

export default class ColumnHeaderGroup implements IColumnHeaderGroup {
static NEW_GROUP_PREFIX = ':newGroup';

Expand All @@ -36,14 +45,7 @@ export default class ColumnHeaderGroup implements IColumnHeaderGroup {
depth,
childIndexes,
parent,
}: {
name: string;
children: string[];
color?: string | null;
depth: number;
childIndexes: ModelIndex[];
parent?: string;
}) {
}: ColumnHeaderGroupConfig) {
this.name = name;
this.children = children;
this.color = color ?? undefined;
Expand Down
21 changes: 19 additions & 2 deletions packages/iris-grid/src/CommonTypes.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { type AdvancedFilterOptions } from '@deephaven/jsapi-utils';
import { type ModelIndex } from '@deephaven/grid';
import { type GridRangeIndex, type ModelIndex } from '@deephaven/grid';
import type { dh } from '@deephaven/jsapi-types';
import { type Shortcut } from '@deephaven/components';
import { type IconDefinition } from '@deephaven/icons';
import type AggregationOperation from './sidebar/aggregations/AggregationOperation';
import { type OptionType } from './sidebar';
import { type UIRollupConfig, type OptionType } from './sidebar';
import type IrisGridModel from './IrisGridModel';
import { type IrisGridThemeType } from './IrisGridTheme';

export type RowIndex = ModelIndex;

Expand Down Expand Up @@ -84,3 +86,18 @@ export type PendingDataErrorMap<T extends Error = Error> = ReadonlyMap<
RowIndex,
readonly T[]
>;

export interface IrisGridStateOverride extends Record<string, unknown> {
model: IrisGridModel;
theme: IrisGridThemeType;
hoverSelectColumn: GridRangeIndex;
isFilterBarShown: boolean;
isMenuShown: boolean;
isSelectingColumn: boolean;
loadingScrimProgress: number | null;
advancedFilters: ReadonlyAdvancedFilterMap;
quickFilters: ReadonlyQuickFilterMap;
sorts: readonly dh.Sort[];
reverse: boolean;
rollupConfig: UIRollupConfig | undefined;
}
111 changes: 109 additions & 2 deletions packages/iris-grid/src/IrisGrid.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@ import dh from '@deephaven/jsapi-shim';
import { DateUtils, type Settings } from '@deephaven/jsapi-utils';
import { TestUtils } from '@deephaven/test-utils';
import { type TypeValue } from '@deephaven/filters';
import {
type ExpandableColumnGridModel,
isExpandableColumnGridModel,
} from '@deephaven/grid';
import IrisGrid from './IrisGrid';
import IrisGridTestUtils from './IrisGridTestUtils';
import type IrisGridProxyModel from './IrisGridProxyModel';

class MockPath2D {
// eslint-disable-next-line class-methods-use-this
Expand All @@ -14,6 +19,13 @@ class MockPath2D {

window.Path2D = MockPath2D as unknown as new () => Path2D;

jest.mock('@deephaven/grid', () => ({
...jest.requireActual('@deephaven/grid'),
isExpandableColumnGridModel: jest.fn(),
}));

const { asMock } = TestUtils;

const VIEW_SIZE = 5000;

const DEFAULT_SETTINGS: Settings = {
Expand Down Expand Up @@ -66,10 +78,12 @@ function createNodeMock(element: ReactElement) {

function makeComponent(
model = irisGridTestUtils.makeModel(),
settings = DEFAULT_SETTINGS
settings = DEFAULT_SETTINGS,
props = {}
) {
const testRenderer = TestRenderer.create(
<IrisGrid model={model} settings={settings} />,
// eslint-disable-next-line react/jsx-props-no-spreading
<IrisGrid model={model} settings={settings} {...props} />,
{
createNodeMock,
}
Expand Down Expand Up @@ -358,4 +372,97 @@ describe('handleResizeAllColumns', () => {
);
});
});

describe('rebuildFilters', () => {
it('updates state if filters not empty', () => {
const component = makeComponent(undefined, undefined, {
quickFilters: [
[
'2',
{
columnType: IrisGridTestUtils.DEFAULT_TYPE,
filterList: [
{
operator: 'eq',
text: 'null',
value: null,
startColumnIndex: 0,
},
],
},
],
],
});
jest.spyOn(component, 'setState');
expect(component.setState).not.toBeCalled();
component.rebuildFilters();
expect(component.setState).toBeCalled();
});

it('does not update state for empty filters', () => {
const component = makeComponent();
jest.spyOn(component, 'setState');
component.rebuildFilters();
expect(component.setState).not.toBeCalled();
});
});

describe('column expand/collapse', () => {
let model: IrisGridProxyModel & ExpandableColumnGridModel;
let component: IrisGrid;

beforeEach(() => {
model = irisGridTestUtils.makeModel() as IrisGridProxyModel &
ExpandableColumnGridModel;
component = makeComponent(model);
model.setColumnExpanded = jest.fn();
model.isColumnExpanded = jest.fn(() => false);
model.expandAllColumns = jest.fn();
model.collapseAllColumns = jest.fn();
});

afterEach(() => {
jest.clearAllMocks();
});

it('calls setColumnExpanded if model supports expandable columns', () => {
asMock(isExpandableColumnGridModel).mockReturnValue(true);
model.hasExpandableColumns = true;
component.toggleExpandColumn(0);
expect(model.setColumnExpanded).toHaveBeenCalled();
});

it('ignores setColumnExpanded and expand/collapse all if model does not support expandable columns', () => {
asMock(isExpandableColumnGridModel).mockReturnValue(false);
component.toggleExpandColumn(0);
expect(model.setColumnExpanded).not.toHaveBeenCalled();

component.expandAllColumns();
expect(model.expandAllColumns).not.toHaveBeenCalled();

component.collapseAllColumns();
expect(model.collapseAllColumns).not.toHaveBeenCalled();
});

it('calls expandAllColumns if model supports expandable columns and expand all', () => {
asMock(isExpandableColumnGridModel).mockReturnValue(true);
model.isExpandAllColumnsAvailable = true;
component.expandAllColumns();
expect(model.expandAllColumns).toHaveBeenCalled();

component.collapseAllColumns();
expect(model.collapseAllColumns).toHaveBeenCalled();
});

it('ignores expandAllColumns if model does not support expand all', () => {
asMock(isExpandableColumnGridModel).mockReturnValue(true);
model.isExpandAllColumnsAvailable = false;

component.expandAllColumns();
expect(model.expandAllColumns).not.toHaveBeenCalled();

component.collapseAllColumns();
expect(model.collapseAllColumns).not.toHaveBeenCalled();
});
});
});
Loading
Loading