From 4584c9b3974561439584fa74f9d03ed9afc5f651 Mon Sep 17 00:00:00 2001
From: Paul Rosenzweig <paulrosenzweig@users.noreply.github.com>
Date: Fri, 26 Jul 2019 21:10:23 -0400
Subject: [PATCH] In settings, show selected option even when the default is
 selected (#10411)

---
 .../components/widgets/SettingSelect.jsx      | 35 +++++++++------
 .../src/metabase/admin/settings/selectors.js  |  7 +--
 frontend/src/metabase/components/Select.jsx   |  6 ++-
 .../metabase/components/Select.unit.spec.js   | 45 +++++++++++++++++++
 4 files changed, 72 insertions(+), 21 deletions(-)
 create mode 100644 frontend/test/metabase/components/Select.unit.spec.js

diff --git a/frontend/src/metabase/admin/settings/components/widgets/SettingSelect.jsx b/frontend/src/metabase/admin/settings/components/widgets/SettingSelect.jsx
index ec49282e6a9..72c493af863 100644
--- a/frontend/src/metabase/admin/settings/components/widgets/SettingSelect.jsx
+++ b/frontend/src/metabase/admin/settings/components/widgets/SettingSelect.jsx
@@ -1,22 +1,29 @@
 import React from "react";
 
-import Select from "metabase/components/Select.jsx";
-import _ from "underscore";
+import Select, { Option } from "metabase/components/Select.jsx";
 
-const SettingSelect = ({ setting, onChange, disabled }) => (
+const SettingSelect = ({
+  setting: { placeholder, value, options, defaultValue },
+  onChange,
+  disabled,
+}) => (
   <Select
     className="full-width"
-    placeholder={setting.placeholder}
-    value={
-      _.findWhere(setting.options, { value: setting.value }) || setting.value
-    }
-    options={setting.options}
-    onChange={onChange}
-    optionNameFn={option => (typeof option === "object" ? option.name : option)}
-    optionValueFn={option =>
-      typeof option === "object" ? option.value : option
-    }
-  />
+    placeholder={placeholder}
+    value={value}
+    defaultValue={defaultValue}
+    onChange={e => onChange(e.target.value)}
+  >
+    {options.map(option => {
+      const name = typeof option === "object" ? option.name : option;
+      const value = typeof option === "object" ? option.value : option;
+      return (
+        <Option key={value} name={name} value={value}>
+          {name}
+        </Option>
+      );
+    })}
+  </Select>
 );
 
 export default SettingSelect;
diff --git a/frontend/src/metabase/admin/settings/selectors.js b/frontend/src/metabase/admin/settings/selectors.js
index c324ec85ef0..18f5be6d471 100644
--- a/frontend/src/metabase/admin/settings/selectors.js
+++ b/frontend/src/metabase/admin/settings/selectors.js
@@ -51,7 +51,6 @@ const SECTIONS = [
           { name: t`Database Default`, value: "" },
           ...MetabaseSettings.get("timezones"),
         ],
-        placeholder: t`Select a timezone`,
         note: t`Not all databases support timezones, in which case this setting won't take effect.`,
         allowValueCollection: true,
       },
@@ -62,7 +61,7 @@ const SECTIONS = [
         options: (MetabaseSettings.get("available_locales") || []).map(
           ([value, name]) => ({ name, value }),
         ),
-        placeholder: t`Select a language`,
+        defaultValue: "en",
         getHidden: () => MetabaseSettings.get("available_locales").length < 2,
       },
       {
@@ -82,9 +81,7 @@ const SECTIONS = [
           },
           { value: "none", name: t`Disabled` },
         ],
-        // this needs to be here because 'advanced' is the default value, so if you select 'advanced' the
-        // widget will always show the placeholder instead of the 'name' defined above :(
-        placeholder: t`Enabled`,
+        defaultValue: "advanced",
       },
       {
         key: "enable-nested-queries",
diff --git a/frontend/src/metabase/components/Select.jsx b/frontend/src/metabase/components/Select.jsx
index 3c14be8354d..8c25a4cea80 100644
--- a/frontend/src/metabase/components/Select.jsx
+++ b/frontend/src/metabase/components/Select.jsx
@@ -36,6 +36,7 @@ class BrowserSelect extends Component {
     children: PropTypes.array.isRequired,
     onChange: PropTypes.func.isRequired,
     value: PropTypes.any,
+    defaultValue: PropTypes.any,
 
     searchProp: PropTypes.string,
     searchCaseInsensitive: PropTypes.bool,
@@ -66,14 +67,15 @@ class BrowserSelect extends Component {
   };
 
   isSelected(otherValue) {
-    const { value, multiple } = this.props;
+    const { value, multiple, defaultValue } = this.props;
     if (multiple) {
       return _.any(value, v => v === otherValue);
     } else {
       return (
         value === otherValue ||
         ((value == null || value === "") &&
-          (otherValue == null || otherValue === ""))
+          (otherValue == null || otherValue === "")) ||
+        (value == null && otherValue === defaultValue)
       );
     }
   }
diff --git a/frontend/test/metabase/components/Select.unit.spec.js b/frontend/test/metabase/components/Select.unit.spec.js
new file mode 100644
index 00000000000..517e4aeb705
--- /dev/null
+++ b/frontend/test/metabase/components/Select.unit.spec.js
@@ -0,0 +1,45 @@
+import React from "react";
+import { render, cleanup } from "@testing-library/react";
+
+import Select, { Option } from "metabase/components/Select";
+
+describe("Select", () => {
+  afterEach(cleanup);
+
+  it("should render selected option", () => {
+    const { getByText, queryByText } = render(
+      <Select value="b">
+        <Option value="a">option a</Option>
+        <Option value="b">option b</Option>
+      </Select>,
+    );
+
+    expect(queryByText("option a")).toBe(null);
+    getByText("option b");
+  });
+
+  it("should render the defaultValue if none is selected", () => {
+    const { getByText, queryByText } = render(
+      <Select defaultValue="b">
+        <Option value="a">option a</Option>
+        <Option value="b">option b</Option>
+      </Select>,
+    );
+
+    expect(queryByText("option a")).toBe(null);
+    getByText("option b");
+  });
+
+  it("should render a placeholder if none is selected", () => {
+    const { getByText, queryByText } = render(
+      <Select placeholder="choose an option">
+        <Option value="a">option a</Option>
+        <Option value="b">option b</Option>
+      </Select>,
+    );
+
+    expect(queryByText("option a")).toBe(null);
+    expect(queryByText("option b")).toBe(null);
+    getByText("choose an option");
+  });
+});
-- 
GitLab