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