From a88af560b27fe45f29af39d34d0157aa72128a59 Mon Sep 17 00:00:00 2001
From: Aleksandr Lesnenko <alxnddr@users.noreply.github.com>
Date: Fri, 8 Jul 2022 19:21:33 +0400
Subject: [PATCH] load data reference metadata when it is not cached already
 (#23775)

---
 .../components/dataref/DataReference.jsx      |  2 +-
 .../components/dataref/DatabaseTablesPane.jsx | 85 ++++++++-----------
 .../components/dataref/MainPane.jsx           |  6 +-
 ...10-load-data-reference-metadata.cy.spec.js | 49 +++++++++++
 4 files changed, 88 insertions(+), 54 deletions(-)
 create mode 100644 frontend/test/metabase/scenarios/native/reproductions/23510-load-data-reference-metadata.cy.spec.js

diff --git a/frontend/src/metabase/query_builder/components/dataref/DataReference.jsx b/frontend/src/metabase/query_builder/components/dataref/DataReference.jsx
index 26cfe8e9f78..83d6be16c13 100644
--- a/frontend/src/metabase/query_builder/components/dataref/DataReference.jsx
+++ b/frontend/src/metabase/query_builder/components/dataref/DataReference.jsx
@@ -106,7 +106,7 @@ export default class DataReference extends Component {
         onBack={stack.length > 0 ? this.back : null}
         onClose={this.close}
       >
-        <div className="px4">{content}</div>
+        <div className="px3">{content}</div>
       </SidebarContent>
     );
   }
diff --git a/frontend/src/metabase/query_builder/components/dataref/DatabaseTablesPane.jsx b/frontend/src/metabase/query_builder/components/dataref/DatabaseTablesPane.jsx
index 9f4be4f58f3..95c04f142ff 100644
--- a/frontend/src/metabase/query_builder/components/dataref/DatabaseTablesPane.jsx
+++ b/frontend/src/metabase/query_builder/components/dataref/DatabaseTablesPane.jsx
@@ -1,61 +1,46 @@
-/* eslint "react/prop-types": "warn" */
-import React, { Component } from "react";
+import React from "react";
 import PropTypes from "prop-types";
 import Icon from "metabase/components/Icon";
+import Table from "metabase/entities/tables";
 
-class DatabaseTablesPane extends Component {
-  componentDidMount() {
-    const { database } = this.props;
-    if (database.tables.length === 0) {
-      // FIXME: this also fetches fields
-      database.fetchDatabaseMetadata();
-    }
-  }
-
-  componentDidUpdate(prevProps) {
-    const { database } = this.props;
-    if (database.id !== prevProps.database.id) {
-      // FIXME: this also fetches fields
-      database.fetchDatabaseMetadata();
-    }
-  }
-
-  render() {
-    const { database, show } = this.props;
-    const tables = database.tables.sort((a, b) => a.name.localeCompare(b.name));
-    return (
-      <div>
-        <div className="ml1 my2 flex align-center justify-between border-bottom pb1">
-          <div className="flex align-center">
-            <Icon name="database" className="text-medium pr1" size={14} />
-            <h3 className="text-wrap">{database.name}</h3>
-          </div>
-          <div className="flex align-center">
-            <Icon name="table2" className="text-light pr1" size={12} />
-            <span className="text-medium">{tables.length}</span>
-          </div>
+const DatabaseTablesPane = ({ database, show }) => {
+  const tables = database.tables.sort((a, b) => a.name.localeCompare(b.name));
+  return (
+    <div>
+      <div className="ml1 my2 flex align-center justify-between border-bottom pb1">
+        <div className="flex align-center">
+          <Icon name="database" className="text-medium pr1" size={14} />
+          <h3 className="text-wrap">{database.name}</h3>
+        </div>
+        <div className="flex align-center">
+          <Icon name="table2" className="text-light pr1" size={12} />
+          <span className="text-medium">{tables.length}</span>
         </div>
-
-        <ul>
-          {tables.map(table => (
-            <li key={table.id}>
-              <a
-                className="flex-full flex p1 text-bold text-brand text-wrap no-decoration bg-medium-hover"
-                onClick={() => show("table", table)}
-              >
-                {table.name}
-              </a>
-            </li>
-          ))}
-        </ul>
       </div>
-    );
-  }
-}
+
+      <ul>
+        {tables.map(table => (
+          <li key={table.id}>
+            <a
+              className="flex-full flex p1 text-bold text-brand text-wrap no-decoration bg-medium-hover"
+              onClick={() => show("table", table)}
+            >
+              {table.name}
+            </a>
+          </li>
+        ))}
+      </ul>
+    </div>
+  );
+};
 
 DatabaseTablesPane.propTypes = {
   show: PropTypes.func.isRequired,
   database: PropTypes.object.isRequired,
 };
 
-export default DatabaseTablesPane;
+export default Table.loadList({
+  query: (_state, props) => ({
+    dbId: props.database?.id,
+  }),
+})(DatabaseTablesPane);
diff --git a/frontend/src/metabase/query_builder/components/dataref/MainPane.jsx b/frontend/src/metabase/query_builder/components/dataref/MainPane.jsx
index 28c4e666313..9772fc3458e 100644
--- a/frontend/src/metabase/query_builder/components/dataref/MainPane.jsx
+++ b/frontend/src/metabase/query_builder/components/dataref/MainPane.jsx
@@ -3,6 +3,7 @@ import React from "react";
 import PropTypes from "prop-types";
 import { t } from "ttag";
 import Icon from "metabase/components/Icon";
+import Databases from "metabase/entities/databases";
 
 const MainPane = ({ databases, show }) => (
   <div>
@@ -13,9 +14,8 @@ const MainPane = ({ databases, show }) => (
       {databases &&
         databases
           .filter(db => !db.is_saved_questions)
-          .filter(db => db.tables && db.tables.length > 0)
           .map(database => (
-            <li className="mb2" key={database.id}>
+            <li className="mb1" key={database.id}>
               <a
                 onClick={() => show("database", database)}
                 className="p1 flex align-center no-decoration bg-medium-hover"
@@ -34,4 +34,4 @@ MainPane.propTypes = {
   databases: PropTypes.array,
 };
 
-export default MainPane;
+export default Databases.loadList()(MainPane);
diff --git a/frontend/test/metabase/scenarios/native/reproductions/23510-load-data-reference-metadata.cy.spec.js b/frontend/test/metabase/scenarios/native/reproductions/23510-load-data-reference-metadata.cy.spec.js
new file mode 100644
index 00000000000..03284d3e16f
--- /dev/null
+++ b/frontend/test/metabase/scenarios/native/reproductions/23510-load-data-reference-metadata.cy.spec.js
@@ -0,0 +1,49 @@
+import { restore } from "__support__/e2e/helpers";
+import { SAMPLE_DATABASE } from "__support__/e2e/cypress_sample_database";
+const { PRODUCTS } = SAMPLE_DATABASE;
+
+describe("issue 23510", () => {
+  beforeEach(() => {
+    restore();
+    cy.signInAsAdmin();
+  });
+
+  it("loads metadata when it is not cached (metabase#23510)", () => {
+    cy.createNativeQuestion(
+      {
+        name: `Q23510`,
+        native: {
+          query:
+            "select count(*) from orders left join products on products.id=orders.product_id where {{category}}",
+          "template-tags": {
+            ID: {
+              id: "6b8b10ef-0104-1047-1e1b-2492d5954322",
+              name: "Category",
+              display_name: "Category",
+              type: "dimension",
+              dimension: ["field", PRODUCTS.CATEGORY, null],
+              "widget-type": "category",
+              default: null,
+            },
+          },
+        },
+        display: "scalar",
+      },
+      { visitQuestion: true },
+    );
+
+    cy.findByText("Open Editor").click();
+    cy.icon("reference").click();
+
+    cy.findByTestId("sidebar-content").within(() => {
+      cy.findByText("ORDERS");
+      cy.findByText("PRODUCTS");
+      cy.findByText("REVIEWS");
+      cy.findByText("PEOPLE");
+
+      cy.findByText("Back").click();
+
+      cy.findByText("Sample Database");
+    });
+  });
+});
-- 
GitLab