From 651da83c239434867df24cf2af35e0632cbd0e13 Mon Sep 17 00:00:00 2001
From: "Mahatthana (Kelvin) Nomsawadi" <me@bboykelvin.dev>
Date: Mon, 7 Mar 2022 09:54:20 +0700
Subject: [PATCH] Fix "Show error details" keeps showing after clicked (#20824)

---
 .../src/metabase/components/ErrorDetails.jsx  | 43 -----------------
 .../components/ErrorDetails/ErrorDetails.tsx  | 48 +++++++++++++++++++
 .../metabase/components/ErrorDetails/index.ts |  1 +
 .../metabase/components/ErrorDetails/types.ts |  5 ++
 .../src/metabase/containers/ErrorPages.jsx    |  2 +-
 .../components/VisualizationError.jsx         |  2 +-
 6 files changed, 56 insertions(+), 45 deletions(-)
 delete mode 100644 frontend/src/metabase/components/ErrorDetails.jsx
 create mode 100644 frontend/src/metabase/components/ErrorDetails/ErrorDetails.tsx
 create mode 100644 frontend/src/metabase/components/ErrorDetails/index.ts
 create mode 100644 frontend/src/metabase/components/ErrorDetails/types.ts

diff --git a/frontend/src/metabase/components/ErrorDetails.jsx b/frontend/src/metabase/components/ErrorDetails.jsx
deleted file mode 100644
index 88aaa18342e..00000000000
--- a/frontend/src/metabase/components/ErrorDetails.jsx
+++ /dev/null
@@ -1,43 +0,0 @@
-/* eslint-disable react/prop-types */
-import React from "react";
-import { t } from "ttag";
-import cx from "classnames";
-
-export default class ErrorDetails extends React.Component {
-  state = {
-    showError: false,
-  };
-  render() {
-    const { details, centered, className } = this.props;
-    if (!details) {
-      return null;
-    }
-    return (
-      <div className={className}>
-        <div className={centered ? "text-centered" : "text-left"}>
-          <a
-            onClick={() => this.setState({ showError: true })}
-            className="link cursor-pointer"
-          >{t`Show error details`}</a>
-        </div>
-        <div
-          style={{ display: this.state.showError ? "inherit" : "none" }}
-          className={cx("pt3", centered ? "text-centered" : "text-left")}
-        >
-          <h2>{t`Here's the full error message`}</h2>
-          <div
-            style={{ fontFamily: "monospace" }}
-            className="QueryError2-detailBody bordered rounded bg-light text-bold p2 mt1"
-          >
-            {/* ensure we don't try to render anything except a string */}
-            {typeof details === "string"
-              ? details
-              : typeof details.message === "string"
-              ? details.message
-              : String(details)}
-          </div>
-        </div>
-      </div>
-    );
-  }
-}
diff --git a/frontend/src/metabase/components/ErrorDetails/ErrorDetails.tsx b/frontend/src/metabase/components/ErrorDetails/ErrorDetails.tsx
new file mode 100644
index 00000000000..2dcbdef97b9
--- /dev/null
+++ b/frontend/src/metabase/components/ErrorDetails/ErrorDetails.tsx
@@ -0,0 +1,48 @@
+import React, { useState } from "react";
+import { t } from "ttag";
+import cx from "classnames";
+
+import { ErrorDetailsProps } from "./types";
+
+export default function ErrorDetails({
+  details,
+  centered,
+  className,
+}: ErrorDetailsProps) {
+  const [showError, setShowError] = useState(false);
+
+  if (!details) {
+    return null;
+  }
+
+  function toggleShowError() {
+    setShowError(showError => !showError);
+  }
+
+  return (
+    <div className={className}>
+      <div className={centered ? "text-centered" : "text-left"}>
+        <a onClick={toggleShowError} className="link cursor-pointer">
+          {showError ? t`Hide error details` : t`Show error details`}
+        </a>
+      </div>
+      <div
+        style={{ display: showError ? "inherit" : "none" }}
+        className={cx("pt3", centered ? "text-centered" : "text-left")}
+      >
+        <h2>{t`Here's the full error message`}</h2>
+        <div
+          style={{ fontFamily: "monospace" }}
+          className="QueryError2-detailBody bordered rounded bg-light text-bold p2 mt1"
+        >
+          {/* ensure we don't try to render anything except a string */}
+          {typeof details === "string"
+            ? details
+            : typeof details.message === "string"
+            ? details.message
+            : String(details)}
+        </div>
+      </div>
+    </div>
+  );
+}
diff --git a/frontend/src/metabase/components/ErrorDetails/index.ts b/frontend/src/metabase/components/ErrorDetails/index.ts
new file mode 100644
index 00000000000..d0b6d4f260e
--- /dev/null
+++ b/frontend/src/metabase/components/ErrorDetails/index.ts
@@ -0,0 +1 @@
+export { default } from "./ErrorDetails";
diff --git a/frontend/src/metabase/components/ErrorDetails/types.ts b/frontend/src/metabase/components/ErrorDetails/types.ts
new file mode 100644
index 00000000000..3f0133559f6
--- /dev/null
+++ b/frontend/src/metabase/components/ErrorDetails/types.ts
@@ -0,0 +1,5 @@
+export interface ErrorDetailsProps {
+  details: string | Record<string, any>;
+  centered?: boolean;
+  className?: string;
+}
diff --git a/frontend/src/metabase/containers/ErrorPages.jsx b/frontend/src/metabase/containers/ErrorPages.jsx
index 8acb299b761..903cdb50c72 100644
--- a/frontend/src/metabase/containers/ErrorPages.jsx
+++ b/frontend/src/metabase/containers/ErrorPages.jsx
@@ -6,7 +6,7 @@ import fitViewport from "metabase/hoc/FitViewPort";
 
 import Icon from "metabase/components/Icon";
 import EmptyState from "metabase/components/EmptyState";
-import ErrorDetails from "metabase/components/ErrorDetails";
+import ErrorDetails from "metabase/components/ErrorDetails/ErrorDetails";
 
 import NoResults from "assets/img/no_results.svg";
 import { ErrorPageRoot } from "./ErrorPages.styled";
diff --git a/frontend/src/metabase/query_builder/components/VisualizationError.jsx b/frontend/src/metabase/query_builder/components/VisualizationError.jsx
index 1e66758515c..760c1173172 100644
--- a/frontend/src/metabase/query_builder/components/VisualizationError.jsx
+++ b/frontend/src/metabase/query_builder/components/VisualizationError.jsx
@@ -8,7 +8,7 @@ import cx from "classnames";
 
 import MetabaseSettings from "metabase/lib/settings";
 import ErrorMessage from "metabase/components/ErrorMessage";
-import ErrorDetails from "metabase/components/ErrorDetails";
+import ErrorDetails from "metabase/components/ErrorDetails/ErrorDetails";
 import {
   QueryError,
   QueryErrorIcon,
-- 
GitLab