Skip to content

Commit

Permalink
fix: Render tables partitioned by non-string columns (#1533)
Browse files Browse the repository at this point in the history
* Partitioned tables were unable to be rendered if the partitioned
column type is not `java.lang.String`
* Grid can now render string, numerical, and character columns
* Fixes partitioning columns filter dropdown to correctly display `char`
types instead of their ASCII values
* The partition search bar function is now able to search for numbers
* Removes the handleFocus function for `PartitionSelectorSearch` since
it made it impossible for the user to edit the search bar after
deselecting it
* Fixes #1441

---------

Co-authored-by: georgecwan <georgecwan@users.noreply.github.com>
  • Loading branch information
georgecwan and georgecwan authored Sep 27, 2023
1 parent 5592627 commit 585b2ff
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 28 deletions.
25 changes: 21 additions & 4 deletions packages/iris-grid/src/IrisGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1924,10 +1924,27 @@ export class IrisGrid extends Component<IrisGridProps, IrisGridState> {
}

updatePartition(partition: string, partitionColumn: Column): void {
if (TableUtils.isCharType(partitionColumn.type) && partition === '') {
return;
}

const { model } = this.props;
const partitionFilter = partitionColumn
.filter()
.eq(model.dh.FilterValue.ofString(partition));

const partitionText = TableUtils.isCharType(partitionColumn.type)
? model.displayString(
partition,
partitionColumn.type,
partitionColumn.name
)
: partition;
const partitionFilter = this.tableUtils.makeQuickFilterFromComponent(
partitionColumn,
partitionText
);
if (partitionFilter === null) {
return;
}

const partitionFilters = [partitionFilter];
this.setState({
partition,
Expand Down Expand Up @@ -4427,7 +4444,7 @@ export class IrisGrid extends Component<IrisGridProps, IrisGridState> {
type: string,
stringName: string
) => model.displayString(value, type, stringName)}
columnName={partitionColumn.name}
column={partitionColumn}
partition={partition}
onChange={this.handlePartitionChange}
onFetchAll={this.handlePartitionFetchAll}
Expand Down
2 changes: 1 addition & 1 deletion packages/iris-grid/src/IrisGridPartitionSelector.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ function makeIrisGridPartitionSelector(
<IrisGridPartitionSelector
dh={dh}
table={table}
columnName="0"
column={new IrisGridTestUtils(dh).makeColumn()}
getFormattedString={getFormattedString}
onChange={onChange}
onDone={onDone}
Expand Down
26 changes: 19 additions & 7 deletions packages/iris-grid/src/IrisGridPartitionSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import { DropdownMenu, Tooltip } from '@deephaven/components';
import { vsTriangleDown, vsClose } from '@deephaven/icons';
import Log from '@deephaven/log';
import debounce from 'lodash.debounce';
import type { dh as DhType, Table } from '@deephaven/jsapi-types';
import type { Column, dh as DhType, Table } from '@deephaven/jsapi-types';
import { TableUtils } from '@deephaven/jsapi-utils';
import PartitionSelectorSearch from './PartitionSelectorSearch';
import './IrisGridPartitionSelector.scss';
import { ColumnName } from './CommonTypes';
import IrisGridUtils from './IrisGridUtils';

const log = Log.module('IrisGridPartitionSelector');

Expand All @@ -16,7 +17,7 @@ interface IrisGridPartitionSelectorProps<T> {
dh: DhType;
getFormattedString: (value: T, type: string, name: string) => string;
table: Table;
columnName: ColumnName;
column: Column;
partition: string;
onAppend?: (partition: string) => void;
onFetchAll: () => void;
Expand Down Expand Up @@ -90,9 +91,15 @@ class IrisGridPartitionSelector<T> extends Component<
handlePartitionChange(event: React.ChangeEvent<HTMLInputElement>): void {
log.debug2('handlePartitionChange');

const { column } = this.props;
const { value: partition } = event.target;

this.setState({ partition });
this.setState({
partition:
TableUtils.isCharType(column.type) && partition.length > 0
? partition.charCodeAt(0).toString()
: partition,
});

this.debounceUpdate();
}
Expand Down Expand Up @@ -154,7 +161,7 @@ class IrisGridPartitionSelector<T> extends Component<
}

render(): JSX.Element {
const { columnName, dh, getFormattedString, onAppend, onDone, table } =
const { column, dh, getFormattedString, onAppend, onDone, table } =
this.props;
const { partition } = this.state;
const partitionSelectorSearch = (
Expand All @@ -173,12 +180,17 @@ class IrisGridPartitionSelector<T> extends Component<
return (
<div className="iris-grid-partition-selector">
<div className="status-message">
<span>Filtering &quot;{columnName}&quot; partition to</span>
<span>Filtering &quot;{column.name}&quot; partition to</span>
</div>
<div className="input-group">
<input
type="text"
value={partition}
value={
TableUtils.isCharType(column.type) &&
partition.toString().length > 0
? String.fromCharCode(parseInt(partition, 10))
: IrisGridUtils.convertValueToText(partition, column.type)
}
onChange={this.handlePartitionChange}
className="form-control input-partition"
/>
Expand Down
43 changes: 27 additions & 16 deletions packages/iris-grid/src/PartitionSelectorSearch.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import debounce from 'lodash.debounce';
import { TableUtils } from '@deephaven/jsapi-utils';
import type { dh as DhType, Table } from '@deephaven/jsapi-types';
import { ItemList, LoadingSpinner } from '@deephaven/components';
import Log from '@deephaven/log';
Expand Down Expand Up @@ -74,7 +75,6 @@ class PartitionSelectorSearch<T> extends Component<
super(props);

this.handleFilterChange = this.handleFilterChange.bind(this);
this.handleInputFocus = this.handleInputFocus.bind(this);
this.handleKeyDown = this.handleKeyDown.bind(this);
this.handleListKeydown = this.handleListKeydown.bind(this);
this.handleSelect = this.handleSelect.bind(this);
Expand All @@ -86,6 +86,9 @@ class PartitionSelectorSearch<T> extends Component<
this.searchInput = null;
this.timer = null;

const { dh } = props;
this.tableUtils = new TableUtils(dh);

this.state = {
offset: 0,
itemCount: 0,
Expand Down Expand Up @@ -125,6 +128,8 @@ class PartitionSelectorSearch<T> extends Component<

timer: null;

tableUtils: TableUtils;

handleKeyDown(event: React.KeyboardEvent<HTMLInputElement>): boolean {
if (this.itemList == null) {
return false;
Expand Down Expand Up @@ -181,12 +186,6 @@ class PartitionSelectorSearch<T> extends Component<
this.setState({ itemCount, isLoading: true });
}

handleInputFocus(): void {
if (this.itemList) {
this.itemList.focusItem(0);
}
}

handleSelect(itemIndex: ModelIndex): void {
log.debug2('handleSelect', itemIndex);

Expand Down Expand Up @@ -227,9 +226,14 @@ class PartitionSelectorSearch<T> extends Component<
handleTextChange(event: React.ChangeEvent<HTMLInputElement>): void {
log.debug2('handleTextChange');

const { table } = this.props;
const { value: text } = event.target;

this.setState({ text });
if (text !== '' && TableUtils.isIntegerType(table.columns[0].type)) {
this.setState({ text: parseInt(text, 10).toString() });
} else {
this.setState({ text });
}

this.debounceUpdateFilter();
}
Expand Down Expand Up @@ -275,18 +279,21 @@ class PartitionSelectorSearch<T> extends Component<
}

updateFilter(): void {
const { dh, initialPageSize, table } = this.props;
const { initialPageSize, table } = this.props;
const { text } = this.state;
const filterText = text.trim();
const filters = [];
if (filterText.length > 0) {
const column = table.columns[0];
const filter = column
.filter()
.invoke(
'matches',
dh.FilterValue.ofString(`(?s)(?i).*\\Q${filterText}\\E.*`)
const filter = this.tableUtils.makeQuickFilterFromComponent(
column,
TableUtils.isStringType(column.type) ? `~${filterText}` : filterText
);
if (!filter) {
throw new Error(
'Unable to create column filter for partition selector'
);
}
filters.push(filter);
}

Expand All @@ -297,24 +304,28 @@ class PartitionSelectorSearch<T> extends Component<
}

render(): JSX.Element {
const { table } = this.props;
const { isLoading, itemCount, items, offset, text } = this.state;

const listHeight =
Math.min(itemCount, PartitionSelectorSearch.MAX_VISIBLE_ITEMS) *
ItemList.DEFAULT_ROW_HEIGHT +
// Adjust for ListItem vertical padding - .375rem ~ 5.25px
11;
const inputType = TableUtils.isNumberType(table.columns[0].type)
? 'number'
: 'text';
return (
<div className="iris-grid-partition-selector-search">
<div className="search-container">
<input
type="text"
type={inputType}
ref={searchInput => {
this.searchInput = searchInput;
}}
value={text}
placeholder="Available Partitions"
onChange={this.handleTextChange}
onFocus={this.handleInputFocus}
onKeyDown={this.handleKeyDown}
className="form-control input-partition"
/>
Expand Down

0 comments on commit 585b2ff

Please sign in to comment.