Browse Source

chore(query-builder): Remove feature flag checks for issue search bars (#78395)

Malachi Willey 5 months ago
parent
commit
a41dc3108b

+ 3 - 4
static/app/components/modals/savedSearchModal/createSavedSearchModal.spec.tsx

@@ -83,9 +83,8 @@ describe('CreateSavedSearchModal', function () {
     await userEvent.click(screen.getByRole('textbox', {name: /name/i}));
     await userEvent.paste('new search name');
 
-    await userEvent.clear(screen.getByRole('textbox', {name: /filter issues/i}));
-    await userEvent.click(screen.getByRole('textbox', {name: /filter issues/i}));
-    await userEvent.paste('is:resolved');
+    await userEvent.click(screen.getAllByRole('combobox').at(-1)!);
+    await userEvent.paste('event.type:error');
 
     await selectEvent.select(screen.getByText('Last Seen'), 'Trends');
     await userEvent.click(screen.getByRole('button', {name: 'Save'}));
@@ -96,7 +95,7 @@ describe('CreateSavedSearchModal', function () {
         expect.objectContaining({
           data: {
             name: 'new search name',
-            query: 'is:resolved',
+            query: 'is:unresolved assigned:lyn@sentry.io event.type:error',
             sort: IssueSortOptions.TRENDS,
             type: 0,
             visibility: SavedSearchVisibility.OWNER,

+ 8 - 11
static/app/components/modals/savedSearchModal/editSavedSearchModal.spec.tsx

@@ -60,7 +60,7 @@ describe('EditSavedSearchModal', function () {
       body: {
         id: 'saved-search-id',
         name: 'test',
-        query: 'is:unresolved browser:firefox',
+        query: 'is:unresolved browser:firefox event.type:error',
         sort: IssueSortOptions.TRENDS,
         visibility: SavedSearchVisibility.OWNER,
       },
@@ -71,11 +71,13 @@ describe('EditSavedSearchModal', function () {
     await userEvent.clear(screen.getByRole('textbox', {name: /name/i}));
     await userEvent.paste('new search name');
 
-    await userEvent.clear(screen.getByRole('textbox', {name: /filter issues/i}));
-    await userEvent.paste('test');
-
     await selectEvent.select(screen.getByText('Last Seen'), 'Trends');
 
+    await userEvent.click(
+      screen.getAllByRole('combobox', {name: 'Add a search term'}).at(-1)!
+    );
+    await userEvent.paste('event.type:error');
+
     await selectEvent.select(screen.getByText('Only me'), 'Users in my organization');
 
     await userEvent.click(screen.getByRole('button', {name: 'Save'}));
@@ -86,7 +88,7 @@ describe('EditSavedSearchModal', function () {
         expect.objectContaining({
           data: expect.objectContaining({
             name: 'new search name',
-            query: 'test',
+            query: 'is:unresolved browser:firefox event.type:error',
             visibility: SavedSearchVisibility.ORGANIZATION,
           }),
         })
@@ -119,11 +121,6 @@ describe('EditSavedSearchModal', function () {
     await userEvent.clear(screen.getByRole('textbox', {name: /name/i}));
     await userEvent.paste('new search name');
 
-    await userEvent.clear(screen.getByTestId('smart-search-input'));
-    await userEvent.paste('test');
-
-    await selectEvent.select(screen.getByText('Last Seen'), 'Trends');
-
     // Hovering over the visibility dropdown shows disabled reason
     await userEvent.hover(screen.getByText(/only me/i));
     await screen.findByText(/only organization admins can create global saved searches/i);
@@ -136,7 +133,7 @@ describe('EditSavedSearchModal', function () {
         expect.objectContaining({
           data: expect.objectContaining({
             name: 'new search name',
-            query: 'test',
+            query: 'is:unresolved browser:firefox',
             visibility: SavedSearchVisibility.OWNER,
           }),
         })

+ 3 - 7
static/app/components/modals/savedSearchModal/savedSearchModalContent.tsx

@@ -55,19 +55,15 @@ export function SavedSearchModalContent({organization}: SavedSearchModalContentP
         flexibleControlStateSize
         required
       >
-        {({id, name, onChange, onBlur, disabled, value}) => (
+        {({onChange, onBlur, disabled, value}) => (
           <IssueListSearchBar
-            id={id}
-            name={name}
             organization={organization}
-            onClose={newValue => {
+            onChange={newValue => {
               onChange(newValue, {});
               onBlur(newValue, {});
             }}
-            includeLabel={false}
-            useFormWrapper={false}
             disabled={disabled}
-            query={value}
+            initialQuery={value}
             searchSource="saved_searches_modal"
           />
         )}

+ 3 - 0
static/app/components/searchQueryBuilder/tokens/combobox.tsx

@@ -64,6 +64,7 @@ type SearchQueryBuilderComboboxProps<T extends SelectOptionOrSectionWithKey<stri
    * Display an entirely custom menu.
    */
   customMenu?: CustomComboboxMenu<T>;
+  ['data-test-id']?: string;
   /**
    * If the combobox has additional information to display, passing JSX
    * to this prop will display it in an overlay at the top left position.
@@ -334,6 +335,7 @@ function SearchQueryBuilderComboboxInner<T extends SelectOptionOrSectionWithKey<
     onClick,
     customMenu,
     isOpen: incomingIsOpen,
+    ['data-test-id']: dataTestId,
   }: SearchQueryBuilderComboboxProps<T>,
   ref: ForwardedRef<HTMLInputElement>
 ) {
@@ -538,6 +540,7 @@ function SearchQueryBuilderComboboxInner<T extends SelectOptionOrSectionWithKey<
         onPaste={onPaste}
         disabled={disabled}
         onKeyDownCapture={e => onKeyDownCapture?.(e, {state})}
+        data-test-id={dataTestId}
       />
       {description ? (
         <StyledPositionWrapper

+ 3 - 0
static/app/components/searchQueryBuilder/tokens/freeText.tsx

@@ -500,6 +500,9 @@ function SearchQueryBuilderInputInternal({
           return true;
         }}
         onClick={onClick}
+        data-test-id={
+          state.collection.getLastKey() === item.key ? 'query-builder-input' : undefined
+        }
       >
         {keyItem =>
           itemIsSection(keyItem) ? (

+ 0 - 75
static/app/stores/tagStore.spec.tsx

@@ -1,5 +1,3 @@
-import {OrganizationFixture} from 'sentry-fixture/organization';
-
 import TagStore from 'sentry/stores/tagStore';
 
 describe('TagStore', function () {
@@ -37,79 +35,6 @@ describe('TagStore', function () {
     });
   });
 
-  describe('getIssueAttributes()', function () {
-    it('should populate the has tag with values', () => {
-      TagStore.loadTagsSuccess([
-        {
-          key: 'mytag',
-          name: 'My Custom Tag',
-        },
-        {
-          key: 'otherkey',
-          name: 'My other tag',
-        },
-      ]);
-
-      expect(TagStore.getIssueAttributes(OrganizationFixture()).has).toEqual({
-        key: 'has',
-        name: 'Has Tag',
-        values: ['mytag', 'otherkey'],
-        predefined: true,
-      });
-    });
-
-    it('should not overwrite predefined filters', () => {
-      TagStore.loadTagsSuccess([
-        {
-          key: 'is',
-          name: 'Custom Assigned To',
-        },
-      ]);
-
-      const tags = TagStore.getIssueAttributes(OrganizationFixture());
-      expect(tags.is).toBeTruthy();
-      expect(tags.is.key).toBe('is');
-      expect(tags.assigned).toBeTruthy();
-    });
-
-    it('should replace ignore with archive', () => {
-      TagStore.loadTagsSuccess([
-        {
-          key: 'is',
-          name: 'Custom Assigned To',
-        },
-      ]);
-
-      const tags = TagStore.getIssueAttributes(OrganizationFixture());
-      expect(tags.is.values).toContain('archived');
-    });
-  });
-
-  describe('getIssueTags()', function () {
-    it('should have built in, state, and issue attribute tags', () => {
-      TagStore.loadTagsSuccess([
-        {
-          key: 'mytag',
-          name: 'My Custom Tag',
-        },
-      ]);
-
-      const tags = TagStore.getIssueTags(OrganizationFixture());
-
-      // state
-      expect(tags.mytag).toBeTruthy();
-      expect(tags.mytag.key).toBe('mytag');
-
-      // attribute
-      expect(tags.has).toBeTruthy();
-      expect(tags.has.key).toBe('has');
-
-      // built in
-      expect(tags['device.family']).toBeTruthy();
-      expect(tags['device.family'].key).toBe('device.family');
-    });
-  });
-
   it('returns a stable reference from getState', () => {
     TagStore.loadTagsSuccess([
       {

+ 0 - 229
static/app/stores/tagStore.tsx

@@ -1,55 +1,10 @@
 import {createStore} from 'reflux';
 
-import {ItemType, type SearchGroup} from 'sentry/components/smartSearchBar/types';
 import type {Tag, TagCollection} from 'sentry/types/group';
-import {
-  getIssueTitleFromType,
-  IssueCategory,
-  IssueType,
-  PriorityLevel,
-} from 'sentry/types/group';
-import type {Organization} from 'sentry/types/organization';
-import {SEMVER_TAGS} from 'sentry/utils/discover/fields';
-import {
-  FieldKey,
-  FieldKind,
-  ISSUE_EVENT_PROPERTY_FIELDS,
-  ISSUE_FIELDS,
-  ISSUE_PROPERTY_FIELDS,
-} from 'sentry/utils/fields';
 
 import type {StrictStoreDefinition} from './types';
 
-// This list is only used on issues. Events/discover
-// have their own field list that exists elsewhere.
-const BUILTIN_TAGS = ISSUE_FIELDS.reduce<TagCollection>((acc, tag) => {
-  acc[tag] = {key: tag, name: tag};
-  return acc;
-}, {});
-
-// For the new query builder, we need to differentiate between issue and event fields
-const BUILTIN_TAGS_BY_CATEGORY = {
-  ...ISSUE_PROPERTY_FIELDS.reduce<TagCollection>((acc, tag) => {
-    acc[tag] = {key: tag, name: tag, predefined: true, kind: FieldKind.ISSUE_FIELD};
-    return acc;
-  }, {}),
-  ...ISSUE_EVENT_PROPERTY_FIELDS.reduce<TagCollection>((acc, tag) => {
-    acc[tag] = {key: tag, name: tag, predefined: false, kind: FieldKind.EVENT_FIELD};
-    return acc;
-  }, {}),
-};
-
-export function getBuiltInTags(organization: Organization) {
-  if (organization.features.includes('issue-stream-search-query-builder')) {
-    return BUILTIN_TAGS_BY_CATEGORY;
-  }
-
-  return BUILTIN_TAGS;
-}
-
 interface TagStoreDefinition extends StrictStoreDefinition<TagCollection> {
-  getIssueAttributes(organization: Organization): TagCollection;
-  getIssueTags(org: Organization): TagCollection;
   loadTagsSuccess(data: Tag[]): void;
   reset(): void;
 }
@@ -63,190 +18,6 @@ const storeConfig: TagStoreDefinition = {
     this.state = {};
   },
 
-  /**
-   * Gets only predefined issue attributes
-   */
-  getIssueAttributes(organization: Organization) {
-    // TODO(mitsuhiko): what do we do with translations here?
-    const isSuggestions = [
-      'resolved',
-      'unresolved',
-      ...['archived', 'escalating', 'new', 'ongoing', 'regressed'],
-      'assigned',
-      'unassigned',
-      'for_review',
-      'linked',
-      'unlinked',
-    ];
-
-    const sortedTagKeys = Object.keys(this.state).sort((a, b) => {
-      return a.toLowerCase().localeCompare(b.toLowerCase());
-    });
-
-    const builtinTags = getBuiltInTags(organization);
-
-    const tagCollection = {
-      [FieldKey.IS]: {
-        ...builtinTags[FieldKey.IS],
-        key: FieldKey.IS,
-        name: 'Status',
-        values: isSuggestions,
-        maxSuggestedValues: isSuggestions.length,
-        predefined: true,
-      },
-      [FieldKey.HAS]: {
-        ...builtinTags[FieldKey.HAS],
-        key: FieldKey.HAS,
-        name: 'Has Tag',
-        values: sortedTagKeys,
-        predefined: true,
-      },
-      [FieldKey.ASSIGNED]: {
-        ...builtinTags[FieldKey.ASSIGNED],
-        key: FieldKey.ASSIGNED,
-        name: 'Assigned To',
-        values: [],
-        predefined: true,
-      },
-      [FieldKey.BOOKMARKS]: {
-        ...builtinTags[FieldKey.BOOKMARKS],
-        name: 'Bookmarked By',
-        values: [],
-        predefined: true,
-      },
-      [FieldKey.ISSUE_CATEGORY]: {
-        ...builtinTags[FieldKey.ISSUE_CATEGORY],
-        name: 'Issue Category',
-        values: [
-          IssueCategory.ERROR,
-          IssueCategory.PERFORMANCE,
-          IssueCategory.REPLAY,
-          IssueCategory.CRON,
-          IssueCategory.UPTIME,
-        ],
-        predefined: true,
-      },
-      [FieldKey.ISSUE_TYPE]: {
-        ...builtinTags[FieldKey.ISSUE_TYPE],
-        name: 'Issue Type',
-        values: [
-          IssueType.PERFORMANCE_N_PLUS_ONE_DB_QUERIES,
-          IssueType.PERFORMANCE_N_PLUS_ONE_API_CALLS,
-          IssueType.PERFORMANCE_CONSECUTIVE_DB_QUERIES,
-          IssueType.PERFORMANCE_SLOW_DB_QUERY,
-          IssueType.PERFORMANCE_RENDER_BLOCKING_ASSET,
-          IssueType.PERFORMANCE_UNCOMPRESSED_ASSET,
-          IssueType.PERFORMANCE_ENDPOINT_REGRESSION,
-          IssueType.PROFILE_FILE_IO_MAIN_THREAD,
-          IssueType.PROFILE_IMAGE_DECODE_MAIN_THREAD,
-          IssueType.PROFILE_JSON_DECODE_MAIN_THREAD,
-          IssueType.PROFILE_REGEX_MAIN_THREAD,
-          IssueType.PROFILE_FUNCTION_REGRESSION,
-        ].map(value => ({
-          icon: null,
-          title: value,
-          name: value,
-          documentation: getIssueTitleFromType(value),
-          value,
-          type: ItemType.TAG_VALUE,
-          children: [],
-        })) as SearchGroup[],
-        predefined: true,
-      },
-      [FieldKey.LAST_SEEN]: {
-        ...builtinTags[FieldKey.LAST_SEEN],
-        name: 'Last Seen',
-        values: [],
-        predefined: false,
-      },
-      [FieldKey.FIRST_SEEN]: {
-        ...builtinTags[FieldKey.FIRST_SEEN],
-        name: 'First Seen',
-        values: [],
-        predefined: false,
-      },
-      [FieldKey.FIRST_RELEASE]: {
-        ...builtinTags[FieldKey.FIRST_RELEASE],
-        name: 'First Release',
-        values: ['latest'],
-        predefined: true,
-      },
-      [FieldKey.EVENT_TIMESTAMP]: {
-        ...builtinTags[FieldKey.EVENT_TIMESTAMP],
-        name: 'Event Timestamp',
-        values: [],
-        predefined: true,
-      },
-      [FieldKey.TIMES_SEEN]: {
-        ...builtinTags[FieldKey.TIMES_SEEN],
-        name: 'Times Seen',
-        isInput: true,
-        // Below values are required or else SearchBar will attempt to get values
-        // This is required or else SearchBar will attempt to get values
-        values: [],
-        predefined: true,
-      },
-      [FieldKey.ASSIGNED_OR_SUGGESTED]: {
-        ...builtinTags[FieldKey.ASSIGNED_OR_SUGGESTED],
-        name: 'Assigned or Suggested',
-        isInput: true,
-        values: [],
-        predefined: true,
-      },
-      [FieldKey.ISSUE_PRIORITY]: {
-        ...builtinTags[FieldKey.ISSUE_PRIORITY],
-        name: 'Issue Priority',
-        values: [PriorityLevel.HIGH, PriorityLevel.MEDIUM, PriorityLevel.LOW],
-        predefined: true,
-      },
-    };
-
-    // Ony include fields that that are part of the ISSUE_FIELDS. This is
-    // because we may sometimes have fields that are turned off by removing
-    // them from ISSUE_FIELDS
-    const filteredCollection = Object.entries(tagCollection).filter(([key]) =>
-      ISSUE_FIELDS.includes(key as FieldKey)
-    );
-
-    return Object.fromEntries(filteredCollection);
-  },
-
-  /**
-   * Get all tags including builtin issue tags and issue attributes
-   */
-  getIssueTags(org: Organization) {
-    const eventTags = Object.values(this.state).reduce<TagCollection>((acc, tag) => {
-      return {
-        ...acc,
-        [tag.key]: {
-          ...tag,
-          kind: FieldKind.TAG,
-        },
-      };
-    }, {});
-
-    const semverFields = Object.values(SEMVER_TAGS).reduce<TagCollection>((acc, tag) => {
-      return {
-        ...acc,
-        [tag.key]: {
-          predefined: false,
-          ...tag,
-          kind: org.features.includes('issue-stream-search-query-builder')
-            ? FieldKind.EVENT_FIELD
-            : FieldKind.FIELD,
-        },
-      };
-    }, {});
-
-    const issueTags = {
-      ...getBuiltInTags(org),
-      ...semverFields,
-      ...eventTags,
-      ...this.getIssueAttributes(org),
-    };
-    return issueTags;
-  },
-
   getState() {
     return this.state;
   },

+ 0 - 121
static/app/utils/withIssueTags.spec.tsx

@@ -1,121 +0,0 @@
-import {OrganizationFixture} from 'sentry-fixture/organization';
-import {TeamFixture} from 'sentry-fixture/team';
-import {UserFixture} from 'sentry-fixture/user';
-
-import {act, render, screen, waitFor} from 'sentry-test/reactTestingLibrary';
-
-import type {SearchGroup} from 'sentry/components/smartSearchBar/types';
-import MemberListStore from 'sentry/stores/memberListStore';
-import TagStore from 'sentry/stores/tagStore';
-import TeamStore from 'sentry/stores/teamStore';
-import type {WithIssueTagsProps} from 'sentry/utils/withIssueTags';
-import withIssueTags from 'sentry/utils/withIssueTags';
-
-interface MyComponentProps extends WithIssueTagsProps {
-  forwardedValue: string;
-}
-function MyComponent(props: MyComponentProps) {
-  return (
-    <div>
-      ForwardedValue: {props.forwardedValue}
-      {'is: ' + props.tags?.is?.values?.[0]}
-      {'mechanism: ' + props.tags?.mechanism?.values?.join(', ')}
-      {'bookmarks: ' + props.tags?.bookmarks?.values?.join(', ')}
-      {'assigned: ' +
-        (props.tags?.assigned?.values as SearchGroup[])
-          .flatMap(x => x.children)
-          .map(x => x.desc)
-          ?.join(', ')}
-      {'stack filename: ' + props.tags?.['stack.filename'].name}
-    </div>
-  );
-}
-
-describe('withIssueTags HoC', function () {
-  beforeEach(() => {
-    TeamStore.reset();
-    TagStore.reset();
-    MemberListStore.loadInitialData([]);
-  });
-
-  it('forwards loaded tags to the wrapped component', async function () {
-    const Container = withIssueTags(MyComponent);
-    render(<Container organization={OrganizationFixture()} forwardedValue="value" />);
-
-    // Should forward props.
-    expect(await screen.findByText(/ForwardedValue: value/)).toBeInTheDocument();
-
-    act(() => {
-      TagStore.loadTagsSuccess([
-        {name: 'MechanismTag', key: 'mechanism', values: ['MechanismTagValue']},
-      ]);
-    });
-
-    // includes custom tags
-    await waitFor(() => {
-      expect(screen.getByText(/MechanismTagValue/)).toBeInTheDocument();
-    });
-
-    // should include special issue and attributes.
-    expect(screen.getByText(/is: resolved/)).toBeInTheDocument();
-    expect(screen.getByText(/bookmarks: me/)).toBeInTheDocument();
-    expect(screen.getByText(/assigned: me/)).toBeInTheDocument();
-    expect(screen.getByText(/stack filename: stack.filename/)).toBeInTheDocument();
-  });
-
-  it('updates the assigned tags with users and teams, and bookmark tags with users', function () {
-    const Container = withIssueTags(MyComponent);
-    render(<Container organization={OrganizationFixture()} forwardedValue="value" />);
-
-    act(() => {
-      TagStore.loadTagsSuccess([
-        {name: 'MechanismTag', key: 'mechanism', values: ['MechanismTagValue']},
-      ]);
-    });
-
-    expect(
-      screen.getByText(/assigned: me, my_teams, none, \[me, my_teams, none\]/)
-    ).toBeInTheDocument();
-
-    act(() => {
-      TeamStore.loadInitialData([
-        TeamFixture({slug: 'best-team-na', name: 'Best Team NA', isMember: true}),
-      ]);
-      MemberListStore.loadInitialData([
-        UserFixture(),
-        UserFixture({username: 'joe@example.com'}),
-      ]);
-    });
-
-    expect(
-      screen.getByText(
-        /assigned: me, my_teams, none, \[me, my_teams, none\], #best-team-na, foo@example.com, joe@example.com/
-      )
-    ).toBeInTheDocument();
-
-    expect(
-      screen.getByText(/bookmarks: me, foo@example.com, joe@example.com/)
-    ).toBeInTheDocument();
-  });
-
-  it('groups assignees and puts suggestions first', function () {
-    const Container = withIssueTags(MyComponent);
-    TeamStore.loadInitialData([
-      TeamFixture({id: '1', slug: 'best-team', name: 'Best Team', isMember: true}),
-      TeamFixture({id: '2', slug: 'worst-team', name: 'Worst Team', isMember: false}),
-    ]);
-    MemberListStore.loadInitialData([
-      UserFixture(),
-      UserFixture({username: 'joe@example.com'}),
-    ]);
-    const {container} = render(
-      <Container organization={OrganizationFixture()} forwardedValue="value" />
-    );
-
-    expect(container).toHaveTextContent(
-      'assigned: me, my_teams, none, [me, my_teams, none], #best-team'
-    );
-    // Has the other teams/members
-    expect(container).toHaveTextContent('foo@example.com, joe@example.com, #worst-team');
-  });
-});

+ 0 - 126
static/app/utils/withIssueTags.tsx

@@ -1,126 +0,0 @@
-import {useEffect, useMemo, useState} from 'react';
-
-import type {SearchGroup} from 'sentry/components/smartSearchBar/types';
-import {ItemType} from 'sentry/components/smartSearchBar/types';
-import {escapeTagValue} from 'sentry/components/smartSearchBar/utils';
-import {IconStar, IconUser} from 'sentry/icons';
-import {t} from 'sentry/locale';
-import MemberListStore from 'sentry/stores/memberListStore';
-import TagStore from 'sentry/stores/tagStore';
-import TeamStore from 'sentry/stores/teamStore';
-import {useLegacyStore} from 'sentry/stores/useLegacyStore';
-import type {TagCollection} from 'sentry/types/group';
-import type {Organization} from 'sentry/types/organization';
-import type {User} from 'sentry/types/user';
-import getDisplayName from 'sentry/utils/getDisplayName';
-
-export interface WithIssueTagsProps {
-  organization: Organization;
-  tags: TagCollection;
-}
-
-type HocProps = {
-  organization: Organization;
-};
-
-const uuidPattern = /[0-9a-f]{32}$/;
-const getUsername = ({isManaged, username, email}: User) => {
-  // Users created via SAML receive unique UUID usernames. Use
-  // their email in these cases, instead.
-  if (username && uuidPattern.test(username)) {
-    return email;
-  }
-  return !isManaged && username ? username : email;
-};
-
-function convertToSearchItem(value: string) {
-  const escapedValue = escapeTagValue(value);
-  return {
-    value: escapedValue,
-    desc: value,
-    type: ItemType.TAG_VALUE,
-  };
-}
-
-/**
- * HOC for getting tags and many useful issue attributes as 'tags' for use
- * in autocomplete selectors or condition builders.
- */
-function withIssueTags<Props extends WithIssueTagsProps>(
-  WrappedComponent: React.ComponentType<Props>
-) {
-  function ComponentWithTags(props: Omit<Props, keyof WithIssueTagsProps> & HocProps) {
-    const {teams} = useLegacyStore(TeamStore);
-    const {members} = useLegacyStore(MemberListStore);
-    const [tags, setTags] = useState<TagCollection>(
-      TagStore.getIssueTags(props.organization)
-    );
-
-    const issueTags = useMemo((): TagCollection => {
-      const usernames: string[] = members.map(getUsername);
-      const userTeams = teams.filter(team => team.isMember).map(team => `#${team.slug}`);
-      const nonMemberTeams = teams
-        .filter(team => !team.isMember)
-        .map(team => `#${team.slug}`);
-
-      const suggestedAssignees: string[] = [
-        'me',
-        'my_teams',
-        'none',
-        // New search builder only works with single value suggestions
-        ...(props.organization.features.includes('issue-stream-search-query-builder')
-          ? []
-          : ['[me, my_teams, none]']),
-        ...userTeams,
-      ];
-      const assignedValues: SearchGroup[] | string[] = [
-        {
-          title: t('Suggested Values'),
-          type: 'header',
-          icon: <IconStar size="xs" />,
-          children: suggestedAssignees.map(convertToSearchItem),
-        },
-        {
-          title: t('All Values'),
-          type: 'header',
-          icon: <IconUser size="xs" />,
-          children: [
-            ...usernames.map(convertToSearchItem),
-            ...nonMemberTeams.map(convertToSearchItem),
-          ],
-        },
-      ];
-
-      return {
-        ...tags,
-        assigned: {
-          ...tags.assigned,
-          values: assignedValues,
-        },
-        bookmarks: {
-          ...tags.bookmarks,
-          values: ['me', ...usernames],
-        },
-        assigned_or_suggested: {
-          ...tags.assigned_or_suggested,
-          values: assignedValues,
-        },
-      };
-    }, [members, teams, props.organization.features, tags]);
-
-    // Listen to tag store updates and cleanup listener on unmount
-    useEffect(() => {
-      const unsubscribeTags = TagStore.listen(() => {
-        setTags(TagStore.getIssueTags(props.organization));
-      }, undefined);
-
-      return () => unsubscribeTags();
-    }, [props.organization, setTags]);
-
-    return <WrappedComponent {...(props as Props)} tags={issueTags} />;
-  }
-  ComponentWithTags.displayName = `withIssueTags(${getDisplayName(WrappedComponent)})`;
-  return ComponentWithTags;
-}
-
-export default withIssueTags;

+ 15 - 39
static/app/views/dashboards/widgetBuilder/buildSteps/filterResultsStep/issuesSearchBar.tsx

@@ -1,14 +1,11 @@
-import {ClassNames} from '@emotion/react';
+import {useCallback} from 'react';
 import styled from '@emotion/styled';
 
 import type {SearchBarProps} from 'sentry/components/events/searchBar';
+import type {SearchQueryBuilderProps} from 'sentry/components/searchQueryBuilder';
 import {t} from 'sentry/locale';
 import type {Organization} from 'sentry/types/organization';
 import type {WidgetQuery} from 'sentry/views/dashboards/types';
-import {
-  MAX_MENU_HEIGHT,
-  MAX_SEARCH_ITEMS,
-} from 'sentry/views/dashboards/widgetBuilder/utils';
 import IssueListSearchBar from 'sentry/views/issueList/searchBar';
 
 interface Props {
@@ -18,35 +15,21 @@ interface Props {
 }
 
 function IssuesSearchBar({onClose, widgetQuery, organization}: Props) {
-  if (organization.features.includes('issue-stream-search-query-builder')) {
-    return (
-      <StyledIssueListSearchQueryBuilder
-        searchSource="widget_builder"
-        organization={organization}
-        query={widgetQuery.conditions || ''}
-        onClose={onClose}
-        placeholder={t('Search for issues, status, assigned, and more')}
-      />
-    );
-  }
+  const onChange = useCallback<NonNullable<SearchQueryBuilderProps['onChange']>>(
+    (query, state) => {
+      onClose?.(query, {validSearch: state.queryIsValid});
+    },
+    [onClose]
+  );
 
   return (
-    <ClassNames>
-      {({css}) => (
-        <StyledIssueListSearchBar
-          searchSource="widget_builder"
-          organization={organization}
-          query={widgetQuery.conditions || ''}
-          onClose={onClose}
-          placeholder={t('Search for issues, status, assigned, and more')}
-          maxSearchItems={MAX_SEARCH_ITEMS}
-          dropdownClassName={css`
-            max-height: ${MAX_MENU_HEIGHT}px;
-            overflow-y: auto;
-          `}
-        />
-      )}
-    </ClassNames>
+    <StyledIssueListSearchQueryBuilder
+      searchSource="widget_builder"
+      organization={organization}
+      initialQuery={widgetQuery.conditions || ''}
+      onChange={onChange}
+      placeholder={t('Search for issues, status, assigned, and more')}
+    />
   );
 }
 
@@ -55,10 +38,3 @@ export {IssuesSearchBar};
 const StyledIssueListSearchQueryBuilder = styled(IssueListSearchBar)`
   flex-grow: 1;
 `;
-
-const StyledIssueListSearchBar = styled(IssueListSearchBar)`
-  flex-grow: 1;
-  button:not([aria-label='Clear search']) {
-    display: none;
-  }
-`;

Some files were not shown because too many files changed in this diff