Browse Source

feat(ui): Fix "Save as..." button on Discover (#22894)

Co-authored-by: Priscila Oliveira <priscila.oliveira@sentry.io>
Billy Vong 4 years ago
parent
commit
988009e624

+ 14 - 4
src/sentry/static/sentry/app/components/dropdownControl.tsx

@@ -6,6 +6,8 @@ import DropdownButton from 'app/components/dropdownButton';
 import DropdownMenu, {GetActorPropsFn} from 'app/components/dropdownMenu';
 import MenuItem from 'app/components/menuItem';
 
+type ButtonPriority = React.ComponentProps<typeof DropdownButton>['priority'];
+
 type DefaultProps = {
   /**
    * Should the menu contents always be rendered?  Defaults to true.
@@ -42,6 +44,8 @@ type Props = DefaultProps & {
    */
   blendWithActor?: boolean;
 
+  priority?: ButtonPriority;
+
   className?: string;
 };
 
@@ -57,13 +61,17 @@ class DropdownControl extends React.Component<Props> {
   };
 
   renderButton(isOpen: boolean, getActorProps: GetActorPropsFn) {
-    const {label, button, buttonProps} = this.props;
+    const {label, button, buttonProps, priority} = this.props;
     if (button) {
       return button({isOpen, getActorProps});
     }
 
     return (
-      <StyledDropdownButton {...getActorProps(buttonProps)} isOpen={isOpen}>
+      <StyledDropdownButton
+        priority={priority}
+        {...getActorProps(buttonProps)}
+        isOpen={isOpen}
+      >
         {label}
       </StyledDropdownButton>
     );
@@ -76,6 +84,7 @@ class DropdownControl extends React.Component<Props> {
       alignRight,
       menuWidth,
       blendWithActor,
+      priority,
       className,
     } = this.props;
     const alignMenu = alignRight ? 'right' : 'left';
@@ -88,6 +97,7 @@ class DropdownControl extends React.Component<Props> {
               {this.renderButton(isOpen, getActorProps)}
               <Content
                 {...getMenuProps()}
+                priority={priority}
                 alignMenu={alignMenu}
                 width={menuWidth}
                 isOpen={isOpen}
@@ -114,9 +124,9 @@ const StyledDropdownButton = styled(DropdownButton)`
   white-space: nowrap;
 `;
 
-const Content = styled(DropdownBubble)<{isOpen: boolean}>`
+const Content = styled(DropdownBubble)<{priority: ButtonPriority; isOpen: boolean}>`
   display: ${p => (p.isOpen ? 'block' : 'none')};
-  border-color: ${p => p.theme.button.form.border};
+  border-color: ${p => p.theme.button[p.priority || 'form'].border};
 `;
 
 const DropdownItem = styled(MenuItem)`

+ 7 - 1
src/sentry/static/sentry/app/components/events/interfaces/breadcrumbs/filter/dropdownButton.tsx

@@ -18,6 +18,7 @@ const DropDownButton = ({isOpen, getActorProps, checkedQuantity}: Props) => {
         {...getActorProps()}
         isOpen={isOpen}
         size="small"
+        hideBottomBorder={false}
         priority="primary"
       >
         {tn('%s Active Filter', '%s Active Filters', checkedQuantity)}
@@ -26,7 +27,12 @@ const DropDownButton = ({isOpen, getActorProps, checkedQuantity}: Props) => {
   }
 
   return (
-    <StyledDropdownButton {...getActorProps()} isOpen={isOpen} size="small">
+    <StyledDropdownButton
+      {...getActorProps()}
+      isOpen={isOpen}
+      size="small"
+      hideBottomBorder={false}
+    >
       {t('Filter By')}
     </StyledDropdownButton>
   );

+ 1 - 0
src/sentry/static/sentry/app/components/events/interfaces/breadcrumbs/filter/index.tsx

@@ -104,6 +104,7 @@ class Filter extends React.Component<Props, State> {
     return (
       <Wrapper>
         <DropdownControl
+          priority="form"
           menuWidth="240px"
           blendWithActor
           button={({isOpen, getActorProps}) => (

+ 18 - 32
src/sentry/static/sentry/app/views/eventsV2/savedQuery/index.tsx

@@ -7,10 +7,9 @@ import {Client} from 'app/api';
 import Feature from 'app/components/acl/feature';
 import FeatureDisabled from 'app/components/acl/featureDisabled';
 import Button from 'app/components/button';
+import ButtonBar from 'app/components/buttonBar';
 import {CreateAlertFromViewButton} from 'app/components/createAlertButton';
-import DropdownButton from 'app/components/dropdownButton';
 import DropdownControl from 'app/components/dropdownControl';
-import Input from 'app/components/forms/input';
 import Hovercard from 'app/components/hovercard';
 import {IconDelete} from 'app/icons';
 import {t} from 'app/locale';
@@ -22,6 +21,7 @@ import {getDiscoverLandingUrl} from 'app/utils/discover/urls';
 import withApi from 'app/utils/withApi';
 import withProjects from 'app/utils/withProjects';
 import {setBannerHidden} from 'app/views/eventsV2/utils';
+import InputControl from 'app/views/settings/components/forms/controls/input';
 
 import {handleCreateQuery, handleDeleteQuery, handleUpdateQuery} from './utils';
 
@@ -217,17 +217,13 @@ class SavedQueryButtonGroup extends React.PureComponent<Props, State> {
       <DropdownControl
         alignRight
         menuWidth="220px"
-        button={({isOpen, getActorProps}) => (
-          <ButtonSaveAs
-            data-test-id="button-save-as"
-            {...getActorProps()}
-            isOpen={isOpen}
-            showChevron={false}
-            disabled={disabled}
-          >
-            {t('Save as\u{2026}')}
-          </ButtonSaveAs>
-        )}
+        priority="default"
+        buttonProps={{
+          'aria-label': t('Save as'),
+          showChevron: false,
+          disabled,
+        }}
+        label={`${t('Save as')}\u{2026}`}
       >
         <ButtonSaveDropDown onClick={SavedQueryButtonGroup.stopEventPropagation}>
           <ButtonSaveInput
@@ -240,7 +236,6 @@ class SavedQueryButtonGroup extends React.PureComponent<Props, State> {
             disabled={disabled}
           />
           <Button
-            data-test-id="button-save-query"
             onClick={this.handleCreateQuery}
             priority="primary"
             disabled={disabled || !this.state.queryName}
@@ -350,41 +345,32 @@ class SavedQueryButtonGroup extends React.PureComponent<Props, State> {
     };
 
     return (
-      <ButtonGroup>
+      <ResponsiveButtonBar gap={1}>
         {renderQueryButton(disabled => this.renderButtonSave(disabled))}
         <Feature organization={organization} features={['incidents']}>
           {({hasFeature}) => hasFeature && this.renderButtonCreateAlert()}
         </Feature>
         {renderQueryButton(disabled => this.renderButtonDelete(disabled))}
-      </ButtonGroup>
+      </ResponsiveButtonBar>
     );
   }
 }
 
-const ButtonGroup = styled('div')`
-  display: flex;
-  align-items: center;
-  margin-top: ${space(1)};
-
-  > * + * {
-    margin-left: ${space(1)};
-  }
-
+const ResponsiveButtonBar = styled(ButtonBar)`
   @media (min-width: ${p => p.theme.breakpoints[1]}) {
     margin-top: 0;
   }
 `;
 
-const ButtonSaveAs = styled(DropdownButton)`
-  z-index: ${p => p.theme.zIndex.dropdownAutocomplete.actor};
-  white-space: nowrap;
-`;
 const ButtonSaveDropDown = styled('div')`
+  display: flex;
+  flex-direction: column;
   padding: ${space(1)};
+  gap: ${space(1)};
 `;
-const ButtonSaveInput = styled(Input)`
-  width: 100%;
-  margin-bottom: ${space(1)};
+
+const ButtonSaveInput = styled(InputControl)`
+  height: 40px;
 `;
 
 const IconUpdate = styled('div')`

+ 2 - 2
tests/acceptance/test_organization_events_v2.py

@@ -452,11 +452,11 @@ class OrganizationEventsV2Test(AcceptanceTestCase, SnubaTestCase):
             self.wait_until_loaded()
 
             # Open the save as drawer
-            self.browser.element('[data-test-id="button-save-as"]').click()
+            self.browser.element('[aria-label="Save as"]').click()
 
             # Fill out name and submit form.
             self.browser.element('input[name="query_name"]').send_keys(query_name)
-            self.browser.element('[data-test-id="button-save-query"]').click()
+            self.browser.element('[aria-label="Save"]').click()
 
             self.browser.wait_until(
                 'div[name="discover2-query-name"][value="{}"]'.format(query_name)

+ 2 - 2
tests/js/spec/views/eventsV2/savedQuery/index.spec.jsx

@@ -8,7 +8,7 @@ import SavedQueryButtonGroup from 'app/views/eventsV2/savedQuery';
 import * as utils from 'app/views/eventsV2/savedQuery/utils';
 import {isBannerHidden, setBannerHidden} from 'app/views/eventsV2/utils';
 
-const SELECTOR_BUTTON_SAVE_AS = 'ButtonSaveAs';
+const SELECTOR_BUTTON_SAVE_AS = 'button[aria-label="Save as"]';
 const SELECTOR_BUTTON_SAVED = '[data-test-id="discover2-savedquery-button-saved"]';
 const SELECTOR_BUTTON_UPDATE = '[data-test-id="discover2-savedquery-button-update"]';
 const SELECTOR_BUTTON_DELETE = '[data-test-id="discover2-savedquery-button-delete"]';
@@ -73,7 +73,7 @@ describe('EventsV2 > SaveQueryButtonGroup', function () {
       );
 
       const buttonSaveAs = wrapper.find(SELECTOR_BUTTON_SAVE_AS);
-      expect(buttonSaveAs.props().disabled).toBe(true);
+      expect(buttonSaveAs.props()['aria-disabled']).toBe(true);
     });
 
     it('renders the correct set of buttons', () => {