Browse Source

ref(ui): Remove less for detailedError (#38605)

Evan Purkhiser 2 years ago
parent
commit
7218397d70

+ 65 - 69
static/app/components/errors/detailedError.tsx

@@ -1,24 +1,22 @@
-import {Component} from 'react';
+import styled from '@emotion/styled';
 import * as Sentry from '@sentry/react';
-import classNames from 'classnames';
 
 import Button from 'sentry/components/button';
+import ButtonBar from 'sentry/components/buttonBar';
 import {IconFlag} from 'sentry/icons';
 import {t} from 'sentry/locale';
+import space from 'sentry/styles/space';
 
-type DefaultProps = {
-  /**
-   * Hide support links in footer of error message
-   */
-  hideSupportLinks: boolean;
-};
-
-type Props = DefaultProps & {
+type Props = {
   /**
    * Error heading
    */
   heading: React.ReactNode;
   className?: string;
+  /**
+   * Hide support links in footer of error message
+   */
+  hideSupportLinks?: boolean;
   /**
    * Detailed error explanation
    */
@@ -26,7 +24,7 @@ type Props = DefaultProps & {
   /**
    * Retry callback
    */
-  onRetry?: (e: React.MouseEvent<HTMLAnchorElement>) => void;
+  onRetry?: (e: React.MouseEvent) => void;
 };
 
 function openFeedback(e: React.MouseEvent) {
@@ -34,66 +32,64 @@ function openFeedback(e: React.MouseEvent) {
   Sentry.showReportDialog();
 }
 
-class DetailedError extends Component<Props> {
-  static defaultProps: DefaultProps = {
-    hideSupportLinks: false,
-  };
-
-  componentDidMount() {
-    // XXX(epurkhiser): Why is this here?
-    this.forceUpdateTimeout = window.setTimeout(() => this.forceUpdate(), 100);
-  }
-
-  componentWillUnmount() {
-    window.clearTimeout(this.forceUpdateTimeout);
-  }
-
-  forceUpdateTimeout: number | undefined = undefined;
-
-  render() {
-    const {className, heading, message, onRetry, hideSupportLinks} = this.props;
-    const cx = classNames('detailed-error', className);
-
-    const showFooter = !!onRetry || !hideSupportLinks;
-
-    return (
-      <div className={cx}>
-        <div className="detailed-error-icon">
-          <IconFlag size="lg" />
-        </div>
-        <div className="detailed-error-content">
-          <h4>{heading}</h4>
-
-          <div className="detailed-error-content-body">{message}</div>
-
-          {showFooter && (
-            <div className="detailed-error-content-footer">
-              <div>
-                {onRetry && (
-                  <a onClick={onRetry} className="btn btn-default">
-                    {t('Retry')}
-                  </a>
-                )}
-              </div>
-
-              {!hideSupportLinks && (
-                <div className="detailed-error-support-links">
-                  {Sentry.lastEventId() && (
-                    <Button priority="link" onClick={openFeedback}>
-                      {t('Fill out a report')}
-                    </Button>
-                  )}
-                  <a href="https://status.sentry.io/">{t('Service status')}</a>
-
-                  <a href="https://sentry.io/support/">{t('Contact support')}</a>
-                </div>
+function DetailedError({className, heading, message, onRetry, hideSupportLinks}: Props) {
+  const showFooter = !!onRetry || !hideSupportLinks;
+  const hasLastEvent = !!Sentry.lastEventId();
+
+  return (
+    <Wrapper className={className}>
+      <ErrorHeading>
+        <IconFlag size="md" color="red300" />
+        {heading}
+      </ErrorHeading>
+
+      {message}
+
+      {showFooter && (
+        <ErrorFooter>
+          <div>{onRetry && <Button onClick={onRetry}>{t('Retry')}</Button>}</div>
+
+          {!hideSupportLinks && (
+            <ButtonBar gap={1.5}>
+              {hasLastEvent && (
+                <Button priority="link" onClick={openFeedback}>
+                  {t('Fill out a report')}
+                </Button>
               )}
-            </div>
+              <Button priority="link" external href="https://status.sentry.io/">
+                {t('Service status')}
+              </Button>
+              <Button priority="link" external href="https://sentry.io/support/">
+                {t('Contact support')}
+              </Button>
+            </ButtonBar>
           )}
-        </div>
-      </div>
-    );
-  }
+        </ErrorFooter>
+      )}
+    </Wrapper>
+  );
 }
 
+const Wrapper = styled('div')`
+  margin: ${space(2)} auto 0 auto;
+  padding: ${space(2)};
+  width: max-content;
+`;
+
+const ErrorHeading = styled('h4')`
+  display: flex;
+  gap: ${space(1.5)};
+  align-items: center;
+  margin-left: calc(-1 * (${p => p.theme.iconSizes.md} + ${space(1.5)}));
+`;
+
+const ErrorFooter = styled('div')`
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-top: ${space(2)};
+  border-top: 1px solid ${p => p.theme.innerBorder};
+  padding-top: ${space(2)};
+`;
+
 export default DetailedError;

+ 4 - 4
static/app/components/errors/groupEventDetailsLoadingError.tsx

@@ -1,10 +1,11 @@
 import DetailedError from 'sentry/components/errors/detailedError';
+import List from 'sentry/components/list';
 import {t} from 'sentry/locale';
 import {Environment} from 'sentry/types';
 
 type Props = {
   environments: Environment[];
-  onRetry?: (e: React.MouseEvent<HTMLAnchorElement>) => void;
+  onRetry?: (e: React.MouseEvent) => void;
 };
 
 const GroupEventDetailsLoadingError = ({onRetry, environments}: Props) => {
@@ -21,11 +22,11 @@ const GroupEventDetailsLoadingError = ({onRetry, environments}: Props) => {
     message = (
       <div>
         <p>{t('This could be due to a handful of reasons:')}</p>
-        <ol className="detailed-error-list">
+        <List symbol="bullet">
           {reasons.map((reason, i) => (
             <li key={i}>{reason}</li>
           ))}
-        </ol>
+        </List>
       </div>
     );
   } else {
@@ -36,7 +37,6 @@ const GroupEventDetailsLoadingError = ({onRetry, environments}: Props) => {
 
   return (
     <DetailedError
-      className="group-event-details-error"
       onRetry={environments.length === 0 ? onRetry : undefined}
       heading={t('Sorry, the events for this issue could not be found.')}
       message={message}

+ 3 - 2
static/app/views/replays/details.tsx

@@ -3,6 +3,7 @@ import type {RouteComponentProps} from 'react-router';
 
 import DetailedError from 'sentry/components/errors/detailedError';
 import NotFound from 'sentry/components/errors/notFound';
+import List from 'sentry/components/list';
 import {
   Provider as ReplayContextProvider,
   useReplayContext,
@@ -61,11 +62,11 @@ function ReplayDetails({
             message={
               <Fragment>
                 <p>{t('This could be due to a couple of reasons:')}</p>
-                <ol className="detailed-error-list">
+                <List symbol="bullet">
                   {reasons.map((reason, i) => (
                     <li key={i}>{reason}</li>
                   ))}
-                </ol>
+                </List>
               </Fragment>
             }
           />

+ 3 - 2
static/app/views/replays/replays.tsx

@@ -4,6 +4,7 @@ import {useTheme} from '@emotion/react';
 import styled from '@emotion/styled';
 
 import DetailedError from 'sentry/components/errors/detailedError';
+import List from 'sentry/components/list';
 import PageFiltersContainer from 'sentry/components/organizations/pageFilters/container';
 import PageHeading from 'sentry/components/pageHeading';
 import Pagination from 'sentry/components/pagination';
@@ -66,11 +67,11 @@ function Replays({location}: Props) {
         message={
           <div>
             <p>{t('This could be due to a handful of reasons:')}</p>
-            <ol className="detailed-error-list">
+            <List symbol="bullet">
               {reasons.map((reason, i) => (
                 <li key={i}>{reason}</li>
               ))}
-            </ol>
+            </List>
           </div>
         }
       />

+ 0 - 45
static/less/errors.less

@@ -1,45 +0,0 @@
-.detailed-error {
-  display: flex;
-  justify-content: center;
-  padding: 18px;
-  &.group-event-details-error {
-    padding-top: 48px;
-  }
-}
-
-.detailed-error-icon {
-  color: @red;
-  font-size: 2.4em;
-  padding: 6px 18px 0 18px;
-  opacity: 0.3;
-}
-
-.detailed-error-content {
-  margin-top: 8px;
-}
-
-.detailed-error-content-footer {
-  margin-top: 18px;
-  border-top: 1px solid @trim;
-  padding-top: 18px;
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-}
-
-.detailed-error-support-links {
-  font-size: 0.9em;
-  a {
-    margin: 12px;
-  }
-}
-
-.detailed-error-list {
-  li {
-    margin-bottom: 6px;
-
-    &:last-child {
-      margin-bottom: 0;
-    }
-  }
-}

+ 0 - 1
static/less/sentry.less

@@ -23,7 +23,6 @@
 @import url('./result-grid.less');
 @import url('./browser-icons.less');
 @import url('./dropdowns.less');
-@import url('./errors.less');
 
 // Page specific
 @import url('./auth.less');