Skip to content

Commit e83d7c9

Browse files
authored
fix: Goto Value Skips Rows on String Column, Displays Incorrect Filter, and shift+enter Doesn't go to Previous (#1162)
- Fixes #1156, #1157 - Fixed a bug where goto value on string column skips rows - Fixed a bug where string column's filter displays `equals` and behaves as `contains` - Allows user to use shift + enter to seek backwards
1 parent 98cf0d9 commit e83d7c9

6 files changed

Lines changed: 65 additions & 12 deletions

File tree

packages/components/src/DateTimeInput.test.tsx

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,15 @@ const F = '\u2007';
1313
function makeDateTimeInput({
1414
value = DEFAULT_DATE_TIME,
1515
onChange = jest.fn(),
16+
onSubmit = jest.fn(),
1617
} = {}) {
17-
return render(<DateTimeInput defaultValue={value} onChange={onChange} />);
18+
return render(
19+
<DateTimeInput
20+
defaultValue={value}
21+
onChange={onChange}
22+
onSubmit={onSubmit}
23+
/>
24+
);
1825
}
1926

2027
it('mounts and unmounts properly', () => {
@@ -139,3 +146,16 @@ describe('addSeparators', () => {
139146
expect(addSeparators('2022-02-22')).toBe(`2022-02-22`);
140147
});
141148
});
149+
150+
it('onSubmit works correctly', async () => {
151+
const onSubmit = jest.fn();
152+
const { unmount } = makeDateTimeInput({
153+
value: '2022-02-22 00:00:00.000',
154+
onSubmit,
155+
});
156+
const input: HTMLInputElement = screen.getByRole('textbox');
157+
const user = userEvent.setup();
158+
await user.type(input, '{enter}');
159+
expect(onSubmit).toBeCalledTimes(1);
160+
unmount();
161+
});

packages/components/src/DateTimeInput.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useCallback, useState } from 'react';
1+
import React, { KeyboardEvent, useCallback, useState } from 'react';
22
import classNames from 'classnames';
33
import Log from '@deephaven/log';
44
import MaskedInput, { SelectionSegment } from './MaskedInput';
@@ -24,6 +24,7 @@ type DateTimeInputProps = {
2424
defaultValue?: string;
2525
onFocus?(): void;
2626
onBlur?(): void;
27+
onSubmit?(event?: KeyboardEvent<HTMLInputElement>): void;
2728
'data-testid'?: string;
2829
};
2930

@@ -50,6 +51,7 @@ const DateTimeInput = React.forwardRef<HTMLInputElement, DateTimeInputProps>(
5051
defaultValue = '',
5152
onFocus = () => undefined,
5253
onBlur = () => undefined,
54+
onSubmit,
5355
'data-testid': dataTestId,
5456
} = props;
5557
const [value, setValue] = useState(
@@ -86,6 +88,7 @@ const DateTimeInput = React.forwardRef<HTMLInputElement, DateTimeInputProps>(
8688
getNextSegmentValue={getNextSegmentValue}
8789
onChange={handleChange}
8890
onSelect={setSelection}
91+
onSubmit={onSubmit}
8992
pattern={FULL_DATE_PATTERN}
9093
placeholder={FULL_DATE_FORMAT}
9194
selection={selection}

packages/components/src/MaskedInput.test.tsx

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React from 'react';
2-
import { render } from '@testing-library/react';
2+
import { render, screen } from '@testing-library/react';
3+
import userEvent from '@testing-library/user-event';
34
import MaskedInput from './MaskedInput';
45
import { fillToLength, trimTrailingMask } from './MaskedInputUtils';
56

@@ -9,9 +10,15 @@ function makeMaskedInput({
910
value = '00:00:00',
1011
pattern = TIME_PATTERN,
1112
example = '12:34:56',
13+
onSubmit = jest.fn(),
1214
} = {}) {
1315
return render(
14-
<MaskedInput value={value} pattern={pattern} example={example} />
16+
<MaskedInput
17+
value={value}
18+
pattern={pattern}
19+
example={example}
20+
onSubmit={onSubmit}
21+
/>
1522
);
1623
}
1724

@@ -20,6 +27,16 @@ it('mounts and unmounts properly', () => {
2027
unmount();
2128
});
2229

30+
it('onSubmit works properly', async () => {
31+
const onSubmit = jest.fn();
32+
const { unmount } = makeMaskedInput({ onSubmit });
33+
const input: HTMLInputElement = screen.getByRole('textbox');
34+
const user = userEvent.setup();
35+
await user.type(input, '{enter}');
36+
expect(onSubmit).toBeCalledTimes(1);
37+
unmount();
38+
});
39+
2340
describe('fillToLength', () => {
2441
it('fills empty string with the example value', () => {
2542
expect(fillToLength('te', 'TEST', 0)).toBe('te');

packages/components/src/MaskedInput.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useMemo, useEffect, useCallback } from 'react';
1+
import React, { useMemo, useEffect, useCallback, KeyboardEvent } from 'react';
22
import classNames from 'classnames';
33
import Log from '@deephaven/log';
44
import { useForwardedRef } from '@deephaven/react-hooks';
@@ -46,6 +46,8 @@ type MaskedInputProps = {
4646
onChange?(value: string): void;
4747
/** Called when selection changes */
4848
onSelect?(segment: SelectionSegment): void;
49+
/** Called when enter is pressed */
50+
onSubmit?(event?: KeyboardEvent<HTMLInputElement>): void;
4951
/** Retrieve the next value for a provided segment */
5052
getNextSegmentValue?(
5153
segment: SelectionSegment,
@@ -82,6 +84,7 @@ const MaskedInput = React.forwardRef<HTMLInputElement, MaskedInputProps>(
8284
getPreferredReplacementString = DEFAULT_GET_PREFERRED_REPLACEMENT_STRING,
8385
onChange = () => false,
8486
onSelect = () => false,
87+
onSubmit,
8588
pattern,
8689
placeholder,
8790
selection,
@@ -386,7 +389,10 @@ const MaskedInput = React.forwardRef<HTMLInputElement, MaskedInputProps>(
386389
);
387390
return;
388391
}
389-
392+
if (key === 'Enter') {
393+
onSubmit?.(event);
394+
return;
395+
}
390396
if (key.startsWith('Arrow')) {
391397
handleArrowKey(event);
392398
return;

packages/iris-grid/src/GotoRow.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ interface GotoRowProps {
4646

4747
gotoValueSelectedColumnName: ColumnName;
4848
gotoValue: string;
49+
gotoValueFilter: FilterTypeValue;
4950
onGotoValueSelectedColumnNameChanged: (columnName: ColumnName) => void;
5051
onGotoValueSelectedFilterChanged: (filter: FilterTypeValue) => void;
5152
onGotoValueChanged: (input: string) => void;
@@ -67,6 +68,7 @@ function GotoRow({
6768
onClose,
6869
gotoValueSelectedColumnName,
6970
gotoValue,
71+
gotoValueFilter,
7072
onGotoValueSelectedColumnNameChanged,
7173
onGotoValueSelectedFilterChanged,
7274
onGotoValueChanged,
@@ -100,11 +102,11 @@ function GotoRow({
100102
}
101103
};
102104

103-
const handleGotoValueKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {
105+
const handleGotoValueKeySubmit = (e: KeyboardEvent<HTMLInputElement>) => {
104106
if (e.key === 'Enter') {
105107
e.stopPropagation();
106108
e.preventDefault();
107-
onGotoValueSubmit();
109+
onGotoValueSubmit(e.shiftKey);
108110
}
109111
};
110112

@@ -163,6 +165,7 @@ function GotoRow({
163165
return (
164166
<div className="goto-value-date-time-input">
165167
<DateTimeInput
168+
ref={gotoValueInputRef}
166169
className={classNames(
167170
'form-control',
168171
'goto-value-date-time-input',
@@ -172,6 +175,7 @@ function GotoRow({
172175
)}
173176
defaultValue={gotoValue}
174177
onChange={onGotoValueInputChanged}
178+
onSubmit={handleGotoValueKeySubmit}
175179
/>
176180
</div>
177181
);
@@ -186,6 +190,7 @@ function GotoRow({
186190
event.target.value as FilterTypeValue
187191
);
188192
}}
193+
value={gotoValueFilter}
189194
>
190195
<option key={FilterType.eq} value={FilterType.eq}>
191196
Equals
@@ -207,7 +212,7 @@ function GotoRow({
207212
className={classNames('form-control', {
208213
'is-invalid': gotoValueError !== '',
209214
})}
210-
onKeyDown={handleGotoValueKeyDown}
215+
onKeyDown={handleGotoValueKeySubmit}
211216
placeholder="value"
212217
onChange={e => onGotoValueInputChanged(e.target.value)}
213218
value={gotoValue}
@@ -241,7 +246,7 @@ function GotoRow({
241246
<input
242247
ref={gotoValueInputRef}
243248
className="form-control"
244-
onKeyDown={handleGotoValueKeyDown}
249+
onKeyDown={handleGotoValueKeySubmit}
245250
placeholder="value"
246251
onChange={e => onGotoValueInputChanged(e.target.value)}
247252
value={gotoValue}

packages/iris-grid/src/IrisGrid.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3336,7 +3336,7 @@ export class IrisGrid extends Component<IrisGridProps, IrisGridState> {
33363336
case TableUtils.dataType.CHAR:
33373337
case TableUtils.dataType.STRING: {
33383338
rowIndex = await model.seekRow(
3339-
isBackwards === true ? searchFromRow - 1 : searchFromRow + 1,
3339+
searchFromRow,
33403340
selectedColumn,
33413341
dh.ValueType.STRING,
33423342
inputString,
@@ -3352,7 +3352,7 @@ export class IrisGrid extends Component<IrisGridProps, IrisGridState> {
33523352
formatter.timeZone
33533353
);
33543354
rowIndex = await model.seekRow(
3355-
isBackwards === true ? searchFromRow - 1 : searchFromRow + 1,
3355+
searchFromRow,
33563356
selectedColumn,
33573357
dh.ValueType.DATETIME,
33583358
startDate,
@@ -3930,6 +3930,7 @@ export class IrisGrid extends Component<IrisGridProps, IrisGridState> {
39303930
gotoValueError,
39313931
gotoValueSelectedColumnName,
39323932
gotoValue,
3933+
gotoValueSelectedFilter,
39333934
} = this.state;
39343935
if (!isReady) {
39353936
return null;
@@ -4557,6 +4558,7 @@ export class IrisGrid extends Component<IrisGridProps, IrisGridState> {
45574558
onExited={this.handleAnimationEnd}
45584559
gotoValueSelectedColumnName={gotoValueSelectedColumnName}
45594560
gotoValue={gotoValue}
4561+
gotoValueFilter={gotoValueSelectedFilter}
45604562
onGotoValueSelectedColumnNameChanged={
45614563
this.handleGotoValueSelectedColumnNameChanged
45624564
}

0 commit comments

Comments
 (0)