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
5 changes: 5 additions & 0 deletions .changeset/twenty-squids-argue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@hyperdx/app": patch
---

fix: Multiline support for WHERE Input boxes
51 changes: 32 additions & 19 deletions packages/app/src/AutocompleteInput.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useEffect, useMemo, useRef, useState } from 'react';
import Fuse from 'fuse.js';
import { OverlayTrigger } from 'react-bootstrap';
import { TextInput, UnstyledButton } from '@mantine/core';
import { Textarea, UnstyledButton } from '@mantine/core';

import { useQueryHistory } from '@/utils';

Expand All @@ -27,7 +27,7 @@ export default function AutocompleteInput({
queryHistoryType,
'data-testid': dataTestId,
}: {
inputRef: React.RefObject<HTMLInputElement>;
inputRef: React.RefObject<HTMLTextAreaElement>;
value?: string;
onChange: (value: string) => void;
onSubmit?: () => void;
Expand Down Expand Up @@ -236,14 +236,19 @@ export default function AutocompleteInput({
}}
trigger={[]}
>
<TextInput
<Textarea
ref={inputRef}
type="text"
style={{ flexGrow: 1 }}
placeholder={placeholder}
className="border-0 fs-8"
className="fs-8"
value={value}
size={size}
autosize
minRows={1}
maxRows={4}
style={{
flexGrow: 1,
resize: 'none',
}}
data-testid={dataTestId}
onChange={e => onChange(e.target.value)}
onFocus={() => {
Expand All @@ -257,12 +262,12 @@ export default function AutocompleteInput({
setIsSearchInputFocused(false);
}}
onKeyDown={e => {
if (e.key === 'Escape' && e.target instanceof HTMLInputElement) {
if (e.key === 'Escape' && e.target instanceof HTMLTextAreaElement) {
e.target.blur();
}

// Autocomplete Navigation/Acceptance Keys
if (e.key === 'Tab' && e.target instanceof HTMLInputElement) {
if (e.key === 'Tab' && e.target instanceof HTMLTextAreaElement) {
if (
suggestedProperties.length > 0 &&
selectedAutocompleteIndex < suggestedProperties.length &&
Expand All @@ -274,23 +279,31 @@ export default function AutocompleteInput({
);
}
}
if (e.key === 'Enter' && e.target instanceof HTMLInputElement) {
if (e.key === 'Enter' && e.target instanceof HTMLTextAreaElement) {
if (
suggestedProperties.length > 0 &&
selectedAutocompleteIndex < suggestedProperties.length &&
selectedAutocompleteIndex >= 0
) {
e.preventDefault();
onAcceptSuggestion(
suggestedProperties[selectedAutocompleteIndex].value,
);
} else {
if (queryHistoryType && value) {
setQueryHistory(value);
// Allow shift+enter to still create new lines
if (!e.shiftKey) {
e.preventDefault();
if (queryHistoryType && value) {
setQueryHistory(value);
}
onSubmit?.();
}
onSubmit?.();
}
}
if (e.key === 'ArrowDown' && e.target instanceof HTMLInputElement) {
if (
e.key === 'ArrowDown' &&
e.target instanceof HTMLTextAreaElement
) {
if (suggestedProperties.length > 0) {
setSelectedAutocompleteIndex(
Math.min(
Expand All @@ -301,7 +314,7 @@ export default function AutocompleteInput({
);
}
}
if (e.key === 'ArrowUp' && e.target instanceof HTMLInputElement) {
if (e.key === 'ArrowUp' && e.target instanceof HTMLTextAreaElement) {
if (suggestedProperties.length > 0) {
setSelectedAutocompleteIndex(
Math.max(selectedAutocompleteIndex - 1, 0),
Expand All @@ -311,15 +324,15 @@ export default function AutocompleteInput({
}}
rightSectionWidth={ref.current?.clientWidth ?? 'auto'}
rightSection={
<div ref={ref}>
{language != null && onLanguageChange != null && (
language != null && onLanguageChange != null ? (
<div ref={ref}>
<InputLanguageSwitch
showHotkey={showHotkey && isSearchInputFocused}
language={language}
onLanguageChange={onLanguageChange}
/>
)}
</div>
</div>
) : undefined
}
/>
</OverlayTrigger>
Expand Down
1 change: 1 addition & 0 deletions packages/app/src/DBDashboardPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1018,6 +1018,7 @@ function DBDashboardPage({ presetConfig }: { presetConfig?: Dashboard }) {
onSubmit={onSubmit}
label="GLOBAL WHERE"
enableHotkey
allowMultiline={true}
/>
) : (
<SearchInputV2
Expand Down
1 change: 1 addition & 0 deletions packages/app/src/DBSearchPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1418,6 +1418,7 @@ function DBSearchPage() {
label="WHERE"
queryHistoryType={QUERY_LOCAL_STORAGE.SEARCH_SQL}
enableHotkey
allowMultiline={true}
/>
</Box>
}
Expand Down
2 changes: 1 addition & 1 deletion packages/app/src/SearchInputV2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export default function SearchInputV2({
field: { onChange, value },
} = useController(props);

const ref = useRef<HTMLInputElement>(null);
const ref = useRef<HTMLTextAreaElement>(null);
const [parsedEnglishQuery, setParsedEnglishQuery] = useState<string>('');

const autoCompleteOptions = useAutoCompleteOptions(
Expand Down
1 change: 1 addition & 0 deletions packages/app/src/ServicesDashboardPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -968,6 +968,7 @@ function ServicesDashboardPage() {
language="sql"
label="WHERE"
enableHotkey
allowMultiline={true}
/>
}
luceneInput={
Expand Down
2 changes: 1 addition & 1 deletion packages/app/src/SessionSubpanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ export default function SessionSubpanel({
);

// Event Filter Input =========================
const inputRef = useRef<HTMLInputElement>(null);
const inputRef = useRef<HTMLTextAreaElement>(null);
const [_inputQuery, setInputQuery] = useState<string | undefined>(undefined);
const inputQuery = _inputQuery ?? '';
const [_searchedQuery, setSearchedQuery] = useQueryState('session_q', {
Expand Down
1 change: 1 addition & 0 deletions packages/app/src/SessionsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,7 @@ export default function SessionsPage() {
language="sql"
label="WHERE"
enableHotkey
allowMultiline={true}
/>
</Box>
}
Expand Down
68 changes: 41 additions & 27 deletions packages/app/src/components/SQLInlineEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,4 @@
import {
memo,
RefObject,
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from 'react';
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useController, UseControllerProps } from 'react-hook-form';
import { useHotkeys } from 'react-hotkeys-hook';
import {
Expand Down Expand Up @@ -122,24 +114,33 @@ type SQLInlineEditorProps = {
additionalSuggestions?: string[];
queryHistoryType?: string;
parentRef?: HTMLElement | null;
allowMultiline?: boolean;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't want multiline to apply to all SQLInlineEditor instances for the sake of layout continuity.

Image

};

const styleTheme = EditorView.baseTheme({
'&.cm-editor.cm-focused': {
outline: '0px solid transparent',
},
'&.cm-editor': {
background: 'transparent !important',
},
'& .cm-tooltip-autocomplete': {
whiteSpace: 'nowrap',
wordWrap: 'break-word',
maxWidth: '100%',
},
'& .cm-scroller': {
overflowX: 'hidden',
},
});
const MAX_EDITOR_HEIGHT = '150px';

const createStyleTheme = (allowMultiline: boolean = false) =>
EditorView.baseTheme({
'&.cm-editor.cm-focused': {
outline: '0px solid transparent',
},
'&.cm-editor': {
background: 'transparent !important',
...(allowMultiline && { maxHeight: MAX_EDITOR_HEIGHT }),
},
'& .cm-tooltip-autocomplete': {
whiteSpace: 'nowrap',
wordWrap: 'break-word',
maxWidth: '100%',
},
'& .cm-scroller': {
overflowX: 'hidden',
...(allowMultiline && {
maxHeight: MAX_EDITOR_HEIGHT,
overflowY: 'auto',
}),
},
});

export default function SQLInlineEditor({
tableConnections,
Expand All @@ -158,6 +159,7 @@ export default function SQLInlineEditor({
additionalSuggestions = [],
queryHistoryType,
parentRef,
allowMultiline = false,
}: SQLInlineEditorProps) {
const { data: fields } = useAllFields(tableConnections ?? []);
const filteredFields = useMemo(() => {
Expand Down Expand Up @@ -332,7 +334,8 @@ export default function SQLInlineEditor({
}}
extensions={[
...tooltipExt,
styleTheme,
createStyleTheme(allowMultiline),
...(allowMultiline ? [EditorView.lineWrapping] : []),
compartmentRef.current.of(
sql({
upperCaseKeywords: true,
Expand All @@ -342,7 +345,7 @@ export default function SQLInlineEditor({
keymap.of([
{
key: 'Enter',
run: () => {
run: view => {
if (onSubmit == null) {
return false;
}
Expand All @@ -353,6 +356,17 @@ export default function SQLInlineEditor({
return true;
},
},
...(allowMultiline
? [
{
key: 'Shift-Enter',
run: () => {
// Allow default behavior (insert new line)
return false;
},
},
]
: []),
]),
),
keymap.of([
Expand Down
2 changes: 0 additions & 2 deletions packages/app/tests/e2e/features/search/search.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,6 @@ test.describe('Search', { tag: '@search' }, () => {
});
});

//TODO: Add query test using sql

test('Comprehensive Search Workflow - Search, View Results, Navigate Side Panel', async ({
page,
}) => {
Expand Down
Loading
Loading