From e96cf05b2c80923fbf3f4e74fbc0f33ad40cbf39 Mon Sep 17 00:00:00 2001
From: Dalton <daltojohnso@users.noreply.github.com>
Date: Wed, 7 Jul 2021 18:13:02 -0700
Subject: [PATCH] don't show error card in prod & make it fullscreen when
 running cypress (#16908)

* don't show error card in prod & make it fullscreen when running cypress

* fix height styling
---
 frontend/src/metabase/App.jsx                 |  5 +-
 .../components/AppErrorCard/AppErrorCard.jsx  | 51 +++++++++++++++++++
 .../AppErrorCard/AppErrorCard.styled.jsx      | 26 ++++++++++
 .../src/metabase/components/ErrorCard.jsx     | 43 ----------------
 .../src/metabase/components/ExplicitSize.jsx  |  3 +-
 frontend/src/metabase/env.js                  |  4 ++
 frontend/src/metabase/lib/dom.js              |  4 +-
 7 files changed, 89 insertions(+), 47 deletions(-)
 create mode 100644 frontend/src/metabase/components/AppErrorCard/AppErrorCard.jsx
 create mode 100644 frontend/src/metabase/components/AppErrorCard/AppErrorCard.styled.jsx
 delete mode 100644 frontend/src/metabase/components/ErrorCard.jsx
 create mode 100644 frontend/src/metabase/env.js

diff --git a/frontend/src/metabase/App.jsx b/frontend/src/metabase/App.jsx
index c4818212642..6bacc9515ca 100644
--- a/frontend/src/metabase/App.jsx
+++ b/frontend/src/metabase/App.jsx
@@ -7,7 +7,7 @@ import Navbar from "metabase/nav/containers/Navbar";
 import { IFRAMED, initializeIframeResizer } from "metabase/lib/dom";
 
 import UndoListing from "metabase/containers/UndoListing";
-import ErrorCard from "metabase/components/ErrorCard";
+import AppErrorCard from "metabase/components/AppErrorCard/AppErrorCard";
 
 import {
   Archived,
@@ -55,6 +55,7 @@ export default class App extends Component {
   }
 
   componentDidCatch(error, errorInfo) {
+    console.log("COMPONENT DID CATCH LOLE");
     this.setState({ errorInfo });
   }
 
@@ -69,7 +70,7 @@ export default class App extends Component {
           {errorPage ? getErrorComponent(errorPage) : children}
           <UndoListing />
         </div>
-        <ErrorCard errorInfo={errorInfo} />
+        <AppErrorCard errorInfo={errorInfo} />
       </ScrollToTop>
     );
   }
diff --git a/frontend/src/metabase/components/AppErrorCard/AppErrorCard.jsx b/frontend/src/metabase/components/AppErrorCard/AppErrorCard.jsx
new file mode 100644
index 00000000000..3e9043d70b2
--- /dev/null
+++ b/frontend/src/metabase/components/AppErrorCard/AppErrorCard.jsx
@@ -0,0 +1,51 @@
+import React, { useState, useEffect } from "react";
+import PropTypes from "prop-types";
+import { t } from "ttag";
+
+import { isCypressActive, isProduction } from "metabase/env";
+
+import BodyComponent from "metabase/components/BodyComponent";
+import Icon from "metabase/components/Icon";
+import Button from "metabase/components/Button";
+import { FullscreenCard, FixedCard } from "./AppErrorCard.styled";
+
+const CardComponent = isCypressActive ? FullscreenCard : FixedCard;
+const isInEnvWhereErrorShouldBeShown = !isProduction || isCypressActive;
+
+export default BodyComponent(AppErrorCard);
+
+AppErrorCard.propTypes = {
+  errorInfo: PropTypes.shape({
+    componentStack: PropTypes.string,
+  }),
+};
+
+function AppErrorCard({ errorInfo }) {
+  const [hasNewError, setHasNewError] = useState(false);
+
+  useEffect(() => {
+    if (errorInfo) {
+      setHasNewError(true);
+    }
+  }, [errorInfo]);
+
+  const showError = hasNewError && isInEnvWhereErrorShouldBeShown;
+
+  return showError ? (
+    <CardComponent>
+      <div className="flex justify-between align-center mb1">
+        <div className="text-error flex align-center">
+          <Icon name="info_outline" mr={1} size="20" />
+          <h2>{t`Something went wrong`}</h2>
+        </div>
+        <Button
+          onlyIcon
+          icon="close"
+          className="pl1"
+          onClick={() => setHasNewError(false)}
+        />
+      </div>
+      <pre>{errorInfo.componentStack}</pre>
+    </CardComponent>
+  ) : null;
+}
diff --git a/frontend/src/metabase/components/AppErrorCard/AppErrorCard.styled.jsx b/frontend/src/metabase/components/AppErrorCard/AppErrorCard.styled.jsx
new file mode 100644
index 00000000000..f0e42458261
--- /dev/null
+++ b/frontend/src/metabase/components/AppErrorCard/AppErrorCard.styled.jsx
@@ -0,0 +1,26 @@
+import styled from "styled-components";
+import Card from "metabase/components/Card";
+
+export const FullscreenCard = styled(Card)`
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  height: 100vh;
+  padding: 1rem;
+  z-index: 5;
+  overflow: auto;
+`;
+
+export const FixedCard = styled(Card)`
+  position: fixed;
+  right: 0;
+  bottom: 0;
+  width: 350px;
+  height: 500px;
+  margin: 1rem;
+  padding: 1rem;
+  z-index: 5;
+  overflow: auto;
+`;
diff --git a/frontend/src/metabase/components/ErrorCard.jsx b/frontend/src/metabase/components/ErrorCard.jsx
deleted file mode 100644
index 585d32c783b..00000000000
--- a/frontend/src/metabase/components/ErrorCard.jsx
+++ /dev/null
@@ -1,43 +0,0 @@
-import React, { useState, useEffect } from "react";
-import PropTypes from "prop-types";
-import BodyComponent from "metabase/components/BodyComponent";
-import Card from "metabase/components/Card";
-import Icon from "metabase/components/Icon";
-import { t } from "ttag";
-
-function ErrorCard({ errorInfo }) {
-  const [showError, setShowError] = useState(false);
-
-  useEffect(() => {
-    if (errorInfo) {
-      setShowError(true);
-    }
-  }, [errorInfo]);
-
-  return showError ? (
-    <Card className="fixed right bottom zF" p={2} m={2} width={350}>
-      <div className="flex justify-between align-center mb1">
-        <div className="text-error flex align-center">
-          <Icon name="info_outline" mr={1} size="20" />
-          <h2>{t`Something went wrong`}</h2>
-        </div>
-        <Icon
-          name="close"
-          className="pl1 cursor-pointer text-dark"
-          onClick={() => setShowError(false)}
-        />
-      </div>
-      <pre style={{ height: "20vh" }} className="overflow-auto">
-        {errorInfo.componentStack}
-      </pre>
-    </Card>
-  ) : (
-    showError
-  );
-}
-
-ErrorCard.propTypes = {
-  errorInfo: PropTypes.object,
-};
-
-export default BodyComponent(ErrorCard);
diff --git a/frontend/src/metabase/components/ExplicitSize.jsx b/frontend/src/metabase/components/ExplicitSize.jsx
index e438ac16415..e45339c0030 100644
--- a/frontend/src/metabase/components/ExplicitSize.jsx
+++ b/frontend/src/metabase/components/ExplicitSize.jsx
@@ -6,10 +6,11 @@ import ResizeObserver from "resize-observer-polyfill";
 
 import cx from "classnames";
 import _ from "underscore";
+import { isCypressActive } from "metabase/env";
 
 // After adding throttling for resize re-renders, our Cypress tests became flaky
 // due to queried DOM elements are getting detached after re-renders
-const throttleDuration = window.Cypress ? 0 : 500;
+const throttleDuration = isCypressActive ? 0 : 500;
 
 export default ({ selector, wrapped } = {}) => ComposedComponent =>
   class extends Component {
diff --git a/frontend/src/metabase/env.js b/frontend/src/metabase/env.js
new file mode 100644
index 00000000000..098df2e77bb
--- /dev/null
+++ b/frontend/src/metabase/env.js
@@ -0,0 +1,4 @@
+export const isCypressActive = !!window.Cypress;
+
+// eslint-disable-next-line no-undef
+export const isProduction = process.env.NODE_ENV === "production";
diff --git a/frontend/src/metabase/lib/dom.js b/frontend/src/metabase/lib/dom.js
index 6c5dfc7f647..edc193c1b86 100644
--- a/frontend/src/metabase/lib/dom.js
+++ b/frontend/src/metabase/lib/dom.js
@@ -1,4 +1,6 @@
 import _ from "underscore";
+import { isCypressActive } from "metabase/env";
+
 // IE doesn't support scrollX/scrollY:
 export const getScrollX = () =>
   typeof window.scrollX === "undefined" ? window.pageXOffset : window.scrollX;
@@ -9,7 +11,7 @@ export const getScrollY = () =>
 // Cypress renders the whole app within an iframe, but we want to exlude it from this check to avoid certain components (like Nav bar) not rendering
 export const IFRAMED = (function() {
   try {
-    return !window.Cypress && window.self !== window.top;
+    return !isCypressActive && window.self !== window.top;
   } catch (e) {
     return true;
   }
-- 
GitLab