Skip to content
Merged
13 changes: 12 additions & 1 deletion packages/dashboard-core-plugins/src/panels/IrisGridPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ import {
ColumnHeaderGroup,
IrisGridContextMenuData,
PartitionConfig,
IrisGridRenderer,
MouseHandlersProp,
} from '@deephaven/iris-grid';
import {
type RowDataMap,
Expand Down Expand Up @@ -151,7 +153,10 @@ export interface OwnProps extends DashboardPanelProps {
/** Load a plugin defined by the table */
loadPlugin: (pluginName: string) => TablePluginComponent;

theme?: IrisGridThemeType;
theme?: Partial<IrisGridThemeType> & Record<string, unknown>;

mouseHandlers?: MouseHandlersProp;
renderer?: IrisGridRenderer;
}

interface StateProps {
Expand Down Expand Up @@ -993,6 +998,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 Expand Up @@ -1103,8 +1110,10 @@ export class IrisGridPanel extends PureComponent<
inputFilters,
links,
metadata,
mouseHandlers,
panelState,
user,
renderer,
settings,
theme,
} = this.props;
Expand Down Expand Up @@ -1206,11 +1215,13 @@ export class IrisGridPanel extends PureComponent<
isSelectingPartition={isSelectingPartition}
isStuckToBottom={isStuckToBottom}
isStuckToRight={isStuckToRight}
mouseHandlers={mouseHandlers}
movedColumns={movedColumns}
movedRows={movedRows}
partitions={partitions}
partitionConfig={partitionConfig}
quickFilters={quickFilters}
renderer={renderer}
reverse={reverse}
rollupConfig={rollupConfig}
settings={settings}
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 GridModel from './GridModel';
import { 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
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, Settings } from '@deephaven/jsapi-utils';
import { TestUtils } from '@deephaven/utils';
import { TypeValue } from '@deephaven/filters';
import {
ExpandableColumnGridModel,
isExpandableColumnGridModel,
} from '@deephaven/grid';
import IrisGrid from './IrisGrid';
import IrisGridTestUtils from './IrisGridTestUtils';
import 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 @@ -222,3 +236,96 @@ it('should set gotoValueSelectedColumnName to empty string if no columns are giv

expect(component.state.gotoValueSelectedColumnName).toEqual('');
});

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