From 4b7ace0104aebe63222de63c7821213a523433d0 Mon Sep 17 00:00:00 2001
From: Tom Robinson <tlrobinson@gmail.com>
Date: Wed, 6 Jun 2018 14:58:53 -0700
Subject: [PATCH] Cleanup entities/search and ListSelect

---
 frontend/src/metabase/entities/search.js |  6 ----
 frontend/src/metabase/hoc/ListSelect.jsx | 38 +++++++++++++++++-------
 2 files changed, 27 insertions(+), 17 deletions(-)

diff --git a/frontend/src/metabase/entities/search.js b/frontend/src/metabase/entities/search.js
index be8143ccd31..6b3ccf8f349 100644
--- a/frontend/src/metabase/entities/search.js
+++ b/frontend/src/metabase/entities/search.js
@@ -10,12 +10,6 @@ import {
   SegmentSchema,
   MetricSchema,
 } from "metabase/schema";
-import {
-  CardApi,
-  DashboardApi,
-  PulseApi,
-  CollectionsApi,
-} from "metabase/services";
 
 // backend returns type = "card" instead of "question"
 const backendTypeToEntitiesName = object =>
diff --git a/frontend/src/metabase/hoc/ListSelect.jsx b/frontend/src/metabase/hoc/ListSelect.jsx
index a4019abbd4a..207d73f162a 100644
--- a/frontend/src/metabase/hoc/ListSelect.jsx
+++ b/frontend/src/metabase/hoc/ListSelect.jsx
@@ -1,24 +1,37 @@
 import React from "react";
+import PropTypes from "prop-types";
 
 import _ from "underscore";
 
-const keyForItem = item => `${item.type}:${item.id}`;
+const DEFAULT_KEY_FOR_ITEM = item => `${item.type}:${item.id}`;
 
 // Higher order component for managing selection of a list.
 //
+// Expects component to be provided a `list` prop (or prop named by `listProp`)
 // Injects `selected` and `deselected` arrays, a `selection` set, and various
 // methods to select or deselect individual or all items
 //
 // Composes with EntityListLoader, ListSearch, etc
-const listSelect = ({ listProp = "list" } = {}) => ComposedComponent =>
+const listSelect = ({
+  listProp = "list",
+  keyForItem = DEFAULT_KEY_FOR_ITEM,
+} = {}) => ComposedComponent =>
   class extends React.Component {
     state = {
-      selection: new Set(),
+      selectionKeys: new Set(),
+    };
+
+    static displayName = "ListSelect[" +
+      (ComposedComponent.displayName || ComposedComponent.name) +
+      "]";
+
+    static propTypes = {
+      [listProp]: PropTypes.array.isRequired,
     };
 
     render() {
       const [selected, deselected] = _.partition(this.props[listProp], item =>
-        this.state.selection.has(keyForItem(item)),
+        this.state.selectionKeys.has(keyForItem(item)),
       );
       return (
         <ComposedComponent
@@ -36,13 +49,14 @@ const listSelect = ({ listProp = "list" } = {}) => ComposedComponent =>
     }
 
     _setSelected(item, selected) {
-      const selection = new Set(this.state.selection);
+      // copy so we can mutate selectionKeys
+      const selectionKeys = new Set(this.state.selectionKeys);
       if (selected) {
-        selection.add(keyForItem(item));
+        selectionKeys.add(keyForItem(item));
       } else {
-        selection.delete(keyForItem(item));
+        selectionKeys.delete(keyForItem(item));
       }
-      this.setState({ selection });
+      this.setState({ selectionKeys });
     }
 
     handleSelect = item => {
@@ -52,15 +66,17 @@ const listSelect = ({ listProp = "list" } = {}) => ComposedComponent =>
       this._setSelected(item, false);
     };
     handleToggleSelected = item => {
-      this._setSelected(item, !this.state.selection.has(keyForItem(item)));
+      this._setSelected(item, !this.state.selectionKeys.has(keyForItem(item)));
     };
     handleSelectAll = () => {
+      // set selectionKeys to key for every item in list
       this.setState({
-        selection: new Set((this.props[listProp] || []).map(keyForItem)),
+        selectionKeys: new Set((this.props[listProp] || []).map(keyForItem)),
       });
     };
     handleSelectNone = () => {
-      this.setState({ selection: new Set() });
+      // reset selectionKeys
+      this.setState({ selectionKeys: new Set() });
     };
   };
 
-- 
GitLab