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
24 changes: 24 additions & 0 deletions static/app/components/searchQueryBuilder/index.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
QueryInterfaceType,
} from 'sentry/components/searchQueryBuilder/types';
import {INTERFACE_TYPE_LOCALSTORAGE_KEY} from 'sentry/components/searchQueryBuilder/utils';
import {InvalidReason} from 'sentry/components/searchSyntax/parser';
import type {TagCollection} from 'sentry/types/group';
import {FieldKey, FieldKind, FieldValueType} from 'sentry/utils/fields';
import localStorageWrapper from 'sentry/utils/localStorage';
Expand Down Expand Up @@ -2051,4 +2052,27 @@ describe('SearchQueryBuilder', function () {
).toBeInTheDocument();
});
});

describe('invalidMessages', function () {
it('should customize invalid messages', async function () {
render(
<SearchQueryBuilder
{...defaultProps}
initialQuery="foo:"
invalidMessages={{
[InvalidReason.FILTER_MUST_HAVE_VALUE]: 'foo bar baz',
}}
/>
);

expect(screen.getByRole('row', {name: 'foo:'})).toHaveAttribute(
'aria-invalid',
'true'
);

await userEvent.click(getLastInput());
await userEvent.keyboard('{ArrowLeft}');
expect(await screen.findByText('foo bar baz')).toBeInTheDocument();
});
});
});
25 changes: 24 additions & 1 deletion static/app/components/searchQueryBuilder/index.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import Alert from 'sentry/components/alert';
import MultipleCheckbox from 'sentry/components/forms/controls/multipleCheckbox';
import {SearchQueryBuilder} from 'sentry/components/searchQueryBuilder';
import type {FilterKeySection} from 'sentry/components/searchQueryBuilder/types';
import {InvalidReason} from 'sentry/components/searchSyntax/parser';
import JSXProperty from 'sentry/components/stories/jsxProperty';
import SizingWindow from 'sentry/components/stories/sizingWindow';
import storyBook from 'sentry/stories/storyBook';
import type {TagCollection} from 'sentry/types/group';
Expand Down Expand Up @@ -132,7 +134,8 @@ export default storyBook(SearchQueryBuilder, story => {
<p>
There are some config options which allow you to customize which types of syntax
are considered valid. This should be used when the search backend does not
support certain operators like boolean logic or wildcards.
support certain operators like boolean logic or wildcards. Use the checkboxes
below to enable/disable the following options:
</p>
<MultipleCheckbox
onChange={setEnabledConfigs}
Expand All @@ -153,6 +156,26 @@ export default storyBook(SearchQueryBuilder, story => {
searchSource="storybook"
{...queryBuilderOptions}
/>
<p>
The query above has a few invalid tokens. The invalid tokens are highlighted in
red and display a tooltip with a message when focused. The invalid token
messages can be customized using the <code>invalidMessages</code> prop. In this
case, the unsupported tag message is modified with{' '}
<JSXProperty
name="invalidMessages"
value={{[InvalidReason.LOGICAL_AND_NOT_ALLOWED]: 'foo bar baz'}}
/>
.
</p>
<SearchQueryBuilder
initialQuery="AND"
filterKeySections={FITLER_KEY_SECTIONS}
filterKeys={FILTER_KEYS}
getTagValues={getTagValues}
searchSource="storybook"
disallowLogicalOperators
invalidMessages={{[InvalidReason.LOGICAL_AND_NOT_ALLOWED]: 'foo bar baz'}}
/>
</Fragment>
);
});
Expand Down
14 changes: 11 additions & 3 deletions static/app/components/searchQueryBuilder/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
QueryInterfaceType,
} from 'sentry/components/searchQueryBuilder/types';
import {parseQueryBuilderValue} from 'sentry/components/searchQueryBuilder/utils';
import type {SearchConfig} from 'sentry/components/searchSyntax/parser';
import {IconClose, IconSearch} from 'sentry/icons';
import {t} from 'sentry/locale';
import {space} from 'sentry/styles/space';
Expand Down Expand Up @@ -67,6 +68,10 @@ export interface SearchQueryBuilderProps {
* Sections and filter keys are displayed in the order they are provided.
*/
filterKeySections?: FilterKeySection[];
/**
* Allows for customization of the invalid token messages.
*/
invalidMessages?: SearchConfig['invalidMessages'];
label?: string;
onBlur?: (query: string) => void;
/**
Expand Down Expand Up @@ -107,6 +112,7 @@ export function SearchQueryBuilder({
disallowFreeText,
disallowUnsupportedFilters,
disallowWildcard,
invalidMessages,
label,
initialQuery,
fieldDefinitionGetter = getFieldDefinition,
Expand All @@ -132,15 +138,17 @@ export function SearchQueryBuilder({
disallowUnsupportedFilters,
disallowWildcard,
filterKeys,
invalidMessages,
}),
[
state.query,
fieldDefinitionGetter,
disallowFreeText,
disallowLogicalOperators,
disallowUnsupportedFilters,
disallowWildcard,
fieldDefinitionGetter,
filterKeys,
disallowUnsupportedFilters,
state.query,
invalidMessages,
]
);

Expand Down
2 changes: 2 additions & 0 deletions static/app/components/searchQueryBuilder/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export function parseQueryBuilderValue(
disallowLogicalOperators?: boolean;
disallowUnsupportedFilters?: boolean;
disallowWildcard?: boolean;
invalidMessages?: SearchConfig['invalidMessages'];
}
): ParseResult | null {
return collapseTextTokens(
Expand All @@ -82,6 +83,7 @@ export function parseQueryBuilderValue(
: undefined,
disallowParens: options?.disallowLogicalOperators,
...getSearchConfigFromKeys(options?.filterKeys ?? {}, getFieldDefinition),
invalidMessages: options?.invalidMessages,
supportedTags: options?.filterKeys,
})
);
Expand Down