From b8bc2e80fcbce1833ffd9f7013845515f39a6ac8 Mon Sep 17 00:00:00 2001
From: Tom Robinson <tlrobinson@gmail.com>
Date: Tue, 27 Dec 2016 16:22:44 -0800
Subject: [PATCH] Lint fixes

---
 .../people/containers/PeopleListingApp.jsx    |  1 -
 .../containers/CollectionsPermissionsApp.jsx  |  2 +-
 .../components/CreateDashboardModal.jsx       | 12 +--
 frontend/src/metabase/components/Modal.jsx    |  2 +-
 .../src/metabase/containers/UndoListing.jsx   |  1 -
 .../metabase/pulse/components/CardPicker.jsx  |  9 ++
 .../questions/components/ArchivedItem.jsx     |  3 +-
 .../components/CollectionButtons.jsx          | 30 +++---
 .../metabase/questions/components/Item.jsx    |  5 +
 .../questions/components/MoveToCollection.jsx |  0
 .../components/NewCollectionButton.jsx        |  0
 .../metabase/questions/components/Sidebar.css | 92 -------------------
 .../metabase/questions/components/Sidebar.jsx | 76 ---------------
 .../metabase/questions/containers/Archive.jsx |  4 +-
 .../questions/containers/EntityItem.jsx       |  4 +
 .../questions/containers/EntityList.jsx       | 13 ++-
 .../questions/containers/QuestionIndex.jsx    |  7 +-
 frontend/src/metabase/questions/questions.js  |  2 +-
 18 files changed, 56 insertions(+), 207 deletions(-)
 delete mode 100644 frontend/src/metabase/questions/components/MoveToCollection.jsx
 delete mode 100644 frontend/src/metabase/questions/components/NewCollectionButton.jsx
 delete mode 100644 frontend/src/metabase/questions/components/Sidebar.css
 delete mode 100644 frontend/src/metabase/questions/components/Sidebar.jsx

diff --git a/frontend/src/metabase/admin/people/containers/PeopleListingApp.jsx b/frontend/src/metabase/admin/people/containers/PeopleListingApp.jsx
index c3859552a2f..c306b66c19f 100644
--- a/frontend/src/metabase/admin/people/containers/PeopleListingApp.jsx
+++ b/frontend/src/metabase/admin/people/containers/PeopleListingApp.jsx
@@ -9,7 +9,6 @@ import AdminPaneLayout from "metabase/components/AdminPaneLayout.jsx";
 import MetabaseSettings from "metabase/lib/settings";
 import MetabaseUtils from "metabase/lib/utils";
 import Modal from "metabase/components/Modal.jsx";
-import ModalContent, { ModalFooter } from "metabase/components/ModalContent.jsx";
 import PasswordReveal from "metabase/components/PasswordReveal.jsx";
 import UserAvatar from "metabase/components/UserAvatar.jsx";
 import Icon from "metabase/components/Icon.jsx";
diff --git a/frontend/src/metabase/admin/permissions/containers/CollectionsPermissionsApp.jsx b/frontend/src/metabase/admin/permissions/containers/CollectionsPermissionsApp.jsx
index 8d780bac830..7e182b4de13 100644
--- a/frontend/src/metabase/admin/permissions/containers/CollectionsPermissionsApp.jsx
+++ b/frontend/src/metabase/admin/permissions/containers/CollectionsPermissionsApp.jsx
@@ -7,7 +7,7 @@ import PermissionsApp from "./PermissionsApp.jsx";
 import { CollectionsApi } from "metabase/services";
 
 import { getCollectionsPermissionsGrid, getIsDirty, getSaveError, getDiff } from "../selectors";
-import { updatePermission, savePermissions, loadPermissions, loadCollections } from "../permissions";
+import { updatePermission, savePermissions, loadCollections } from "../permissions";
 import { goBack, push } from "react-router-redux";
 
 const mapStateToProps = (state, props) => {
diff --git a/frontend/src/metabase/components/CreateDashboardModal.jsx b/frontend/src/metabase/components/CreateDashboardModal.jsx
index 745b0e35fe8..e39425df144 100644
--- a/frontend/src/metabase/components/CreateDashboardModal.jsx
+++ b/frontend/src/metabase/components/CreateDashboardModal.jsx
@@ -4,8 +4,6 @@ import FormField from "metabase/components/FormField.jsx";
 import ModalContent from "metabase/components/ModalContent.jsx";
 import Button from "metabase/components/Button.jsx";
 
-import cx from "classnames";
-
 export default class CreateDashboardModal extends Component {
     constructor(props, context) {
         super(props, context);
@@ -78,6 +76,7 @@ export default class CreateDashboardModal extends Component {
                 id="CreateDashboardModal"
                 title="Create dashboard"
                 footer={[
+                    formError,
                     <Button onClick={this.props.onClose}>Cancel</Button>,
                     <Button primary={formReady} disabled={!formReady} onClick={this.createNewDash}>Create</Button>
                 ]}
@@ -88,15 +87,16 @@ export default class CreateDashboardModal extends Component {
                         <FormField
                             displayName="Name"
                             fieldName="name"
-                            errors={this.state.errors}>
-                            <input className="Form-input
-                            full" name="name" placeholder="What is the name of your dashboard?" value={this.state.name} onChange={this.setName} autoFocus />
+                            errors={this.state.errors}
+                        >
+                            <input className="Form-input full" name="name" placeholder="What is the name of your dashboard?" value={this.state.name} onChange={this.setName} autoFocus />
                         </FormField>
 
                         <FormField
                             displayName="Description"
                             fieldName="description"
-                            errors={this.state.errors}>
+                            errors={this.state.errors}
+                        >
                             <input className="Form-input full" name="description" placeholder="It's optional but oh, so helpful"  value={this.state.description} onChange={this.setDescription} />
                         </FormField>
                     </div>
diff --git a/frontend/src/metabase/components/Modal.jsx b/frontend/src/metabase/components/Modal.jsx
index 0a713c031d0..b9f06220e31 100644
--- a/frontend/src/metabase/components/Modal.jsx
+++ b/frontend/src/metabase/components/Modal.jsx
@@ -3,7 +3,7 @@ import ReactDOM from "react-dom";
 import cx from "classnames";
 
 import ReactCSSTransitionGroup from "react-addons-css-transition-group";
-import { Motion, spring, presets } from "react-motion";
+import { Motion, spring } from "react-motion";
 
 import OnClickOutsideWrapper from "./OnClickOutsideWrapper.jsx";
 import ModalContent from "./ModalContent";
diff --git a/frontend/src/metabase/containers/UndoListing.jsx b/frontend/src/metabase/containers/UndoListing.jsx
index 65e1723b40e..8d1e7785a39 100644
--- a/frontend/src/metabase/containers/UndoListing.jsx
+++ b/frontend/src/metabase/containers/UndoListing.jsx
@@ -1,6 +1,5 @@
 /* eslint "react/prop-types": "warn" */
 import React, { Component, PropTypes } from "react";
-import { Link } from "react-router";
 import { connect } from "react-redux";
 
 import S from "./UndoListing.css";
diff --git a/frontend/src/metabase/pulse/components/CardPicker.jsx b/frontend/src/metabase/pulse/components/CardPicker.jsx
index c793c7dc328..9a006998085 100644
--- a/frontend/src/metabase/pulse/components/CardPicker.jsx
+++ b/frontend/src/metabase/pulse/components/CardPicker.jsx
@@ -182,7 +182,16 @@ const CollectionListItem = ({ collection, onClick }) =>
         <Icon name="chevronright" className="flex-align-right text-grey-2" />
     </li>
 
+CollectionListItem.propTypes = {
+    collection: PropTypes.object.isRequired,
+    onClick: PropTypes.func.isRequired
+};
+
 const CollectionList = ({ children }) =>
     <ul className="List text-brand">
         {children}
     </ul>
+
+CollectionList.propTypes = {
+    children: PropTypes.array.isRequired
+};
diff --git a/frontend/src/metabase/questions/components/ArchivedItem.jsx b/frontend/src/metabase/questions/components/ArchivedItem.jsx
index 7de7901ef3f..cc8954514eb 100644
--- a/frontend/src/metabase/questions/components/ArchivedItem.jsx
+++ b/frontend/src/metabase/questions/components/ArchivedItem.jsx
@@ -5,7 +5,7 @@ import React, { PropTypes } from "react";
 import Icon from "metabase/components/Icon";
 import Tooltip from "metabase/components/Tooltip";
 
-const ArchivedItem = ({ name, type, icon, color = '#DEEAF1', isAdmin, onUnarchive }) =>
+const ArchivedItem = ({ name, type, icon, color = '#DEEAF1', isAdmin = false, onUnarchive }) =>
     <div className="flex align-center p2 hover-parent hover--visibility border-bottom bg-grey-0-hover">
         <Icon
             name={icon}
@@ -30,6 +30,7 @@ ArchivedItem.propTypes = {
     type:        PropTypes.string.isRequired,
     icon:        PropTypes.string.isRequired,
     color:       PropTypes.string,
+    isAdmin:     PropTypes.bool,
     onUnarchive: PropTypes.func.isRequired
 }
 
diff --git a/frontend/src/metabase/questions/components/CollectionButtons.jsx b/frontend/src/metabase/questions/components/CollectionButtons.jsx
index e53a1efda91..83226805115 100644
--- a/frontend/src/metabase/questions/components/CollectionButtons.jsx
+++ b/frontend/src/metabase/questions/components/CollectionButtons.jsx
@@ -7,11 +7,11 @@ import ArchiveCollectionWidget from "../containers/ArchiveCollectionWidget";
 
 const COLLECTION_ICON_SIZE = 64;
 
-const CollectionButtons = ({ collections, isAdmin }) =>
+const CollectionButtons = ({ collections, isAdmin, push }) =>
     <ol className="">
         { collections
-            .map(collection => <CollectionButton {...collection} isAdmin={isAdmin} />)
-            .concat(isAdmin ? [<NewCollectionButton />] : [])
+            .map(collection => <CollectionButton {...collection} push={push} isAdmin={isAdmin} />)
+            .concat(isAdmin ? [<NewCollectionButton push={push} />] : [])
             .map((element, index) =>
                 <li key={index} className="inline-block pr2 pb2" style={{ width: "25%" }}>
                     {element}
@@ -20,13 +20,11 @@ const CollectionButtons = ({ collections, isAdmin }) =>
         }
     </ol>
 
-const NewCollectionButton = () =>
-    <Link
+const NewCollectionButton = ({ push }) =>
+    <div
         className="relative block p4 hover-parent text-centered text-brand-hover bg-grey-0 bg-light-blue-hover no-decoration"
-        style={{
-            borderRadius: 10
-        }}
-        to="/collections/create"
+        style={{ borderRadius: 10 }}
+        onClick={() => push(`/collections/create`)}
     >
         <div>
             <div
@@ -46,15 +44,13 @@ const NewCollectionButton = () =>
             </div>
         </div>
         <h3 className="text-brand">New collection</h3>
-    </Link>
+    </div>
 
-const CollectionButton = ({ id, name, color, slug, isAdmin }) =>
-    <Link
+const CollectionButton = ({ id, name, color, slug, isAdmin, push }) =>
+    <div
         className="relative block p4 hover-parent hover--visibility text-centered text-brand-hover bg-grey-0 bg-light-blue-hover no-decoration"
-        style={{
-            borderRadius: 10
-        }}
-        to={`/questions/collections/${slug}`}
+        style={{ borderRadius: 10 }}
+        onClick={() => push(`/questions/collections/${slug}`)}
     >
         { isAdmin &&
             <div className="absolute top right mt2 mr2 hover-child">
@@ -73,6 +69,6 @@ const CollectionButton = ({ id, name, color, slug, isAdmin }) =>
             style={{ color }}
         />
         <h3>{ name }</h3>
-    </Link>
+    </div>
 
 export default CollectionButtons;
diff --git a/frontend/src/metabase/questions/components/Item.jsx b/frontend/src/metabase/questions/components/Item.jsx
index cf48494f6b4..b8f5003d4fd 100644
--- a/frontend/src/metabase/questions/components/Item.jsx
+++ b/frontend/src/metabase/questions/components/Item.jsx
@@ -100,11 +100,14 @@ const Item = ({
     </div>
 
 Item.propTypes = {
+    entity:             PropTypes.object.isRequired,
     id:                 PropTypes.number.isRequired,
     name:               PropTypes.string.isRequired,
     created:            PropTypes.string.isRequired,
     description:        PropTypes.string,
     by:                 PropTypes.string.isRequired,
+    labels:             PropTypes.array.isRequired,
+    collection:         PropTypes.object,
     selected:           PropTypes.bool.isRequired,
     favorite:           PropTypes.bool.isRequired,
     archived:           PropTypes.bool.isRequired,
@@ -112,6 +115,8 @@ Item.propTypes = {
     setItemSelected:    PropTypes.func.isRequired,
     setFavorited:       PropTypes.func.isRequired,
     setArchived:        PropTypes.func.isRequired,
+    onEntityClick:      PropTypes.func,
+    showCollectionName: PropTypes.bool,
 };
 
 const ItemBody = pure(({ entity, id, name, description, labels, favorite, collection, setFavorited, onEntityClick }) =>
diff --git a/frontend/src/metabase/questions/components/MoveToCollection.jsx b/frontend/src/metabase/questions/components/MoveToCollection.jsx
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/frontend/src/metabase/questions/components/NewCollectionButton.jsx b/frontend/src/metabase/questions/components/NewCollectionButton.jsx
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/frontend/src/metabase/questions/components/Sidebar.css b/frontend/src/metabase/questions/components/Sidebar.css
deleted file mode 100644
index 91fa7d24da2..00000000000
--- a/frontend/src/metabase/questions/components/Sidebar.css
+++ /dev/null
@@ -1,92 +0,0 @@
-:root {
-    --item-padding: 45px;
-}
-
-:local(.sidebar-padding) {
-  padding-left: var(--item-padding);
-  padding-right: var(--item-padding);
-}
-
-:local(.sidebar-margin) {
-  margin-left: var(--item-padding);
-  margin-right: var(--item-padding);
-}
-
-:local(.sidebar) {
-    composes: py2 from "style";
-    width: 345px;
-    background-color: rgb(248, 252, 253);
-    border-right: 1px solid rgb(223, 238, 245);
-    color: #606E7B;
-}
-
-:local(.sidebar) a {
-    text-decoration: none;
-}
-
-:local(.item),
-:local(.sectionTitle) {
-    composes: flex align-center from "style";
-    composes: py2 from "style";
-    composes: sidebar-padding;
-}
-
-:local(.item) {
-    composes: transition-color from "style";
-    composes: transition-background from "style";
-    font-size: 1em;
-    color: #CFE4F5;
-}
-
-:local(.item) :local(.icon) {
-  line-height: 1em;
-}
-
-:local(.sectionTitle) {
-    composes: my1 from "style";
-    composes: text-bold from "style";
-    font-size: 16px;
-}
-
-
-:local(.item.selected),
-:local(.item.selected) :local(.icon),
-:local(.sectionTitle.selected),
-:local(.item):hover,
-:local(.item):hover :local(.icon),
-:local(.sectionTitle):hover {
-    background-color: #E3F0F9;
-    color: #2D86D4;
-}
-
-:local(.divider) {
-    composes: my2 from "style";
-    composes: border-bottom from "style";
-    composes: sidebar-margin;
-}
-
-:local(.name) {
-    composes: ml2 text-bold from "style";
-    color: #9CAEBE;
-    text-overflow: ellipsis;
-    white-space: nowrap;
-    overflow-x: hidden;
-}
-
-:local(.item):hover :local(.name),
-:local(.item.selected) :local(.name) {
-    color: #2D86D4;
-}
-
-:local(.icon) {
-    composes: flex-no-shrink from "style";
-}
-
-
-:local(.noLabelsMessage) {
-  composes: relative from "style";
-  composes: text-centered from "style";
-  composes: p2 my3 from "style";
-  composes: text-brand-light from "style";
-  composes: sidebar-margin;
-}
diff --git a/frontend/src/metabase/questions/components/Sidebar.jsx b/frontend/src/metabase/questions/components/Sidebar.jsx
deleted file mode 100644
index d70b60b752d..00000000000
--- a/frontend/src/metabase/questions/components/Sidebar.jsx
+++ /dev/null
@@ -1,76 +0,0 @@
-/* eslint "react/prop-types": "warn" */
-import React, { PropTypes } from "react";
-import { Link } from "react-router";
-import S from "./Sidebar.css";
-
-import Icon from "metabase/components/Icon.jsx";
-import LabelIcon from "metabase/components/LabelIcon.jsx";
-import LoadingAndErrorWrapper from "metabase/components/LoadingAndErrorWrapper.jsx";
-
-import cx from 'classnames';
-import pure from "recompose/pure";
-
-const Sidebar = ({ sections, labels, labelsLoading, labelsError, style, className }) =>
-    <div className={cx(S.sidebar, className)} style={style}>
-        <ul>
-            {sections.map(section =>
-                <QuestionSidebarItem key={section.id} href={"/questions/" + section.id} {...section} />
-            )}
-            <QuestionSidebarSectionTitle name="Labels" href="/questions/edit/labels" />
-        </ul>
-        <LoadingAndErrorWrapper loading={labelsLoading} error={labelsError} noBackground noWrapper>
-        { () => labels.length > 0 ? // eslint-disable-line
-            <ul>
-            { labels.map(label =>
-                <QuestionSidebarItem key={label.id} href={"/questions/label/"+label.slug} {...label} />
-            )}
-            </ul>
-        :
-            <div className={S.noLabelsMessage}>
-                <div>
-                  <Icon name="label" />
-                </div>
-                Create labels to group and manage questions.
-            </div>
-        }
-        </LoadingAndErrorWrapper>
-        <ul>
-            <li className={S.divider} />
-            <QuestionSidebarItem name="Archive" href="/questions/archived" icon="archive" />
-        </ul>
-    </div>
-
-Sidebar.propTypes = {
-    className:      PropTypes.string,
-    style:          PropTypes.object,
-    sections:       PropTypes.array.isRequired,
-    labels:         PropTypes.array.isRequired,
-    labelsLoading:  PropTypes.bool.isRequired,
-    labelsError:    PropTypes.any,
-};
-
-const QuestionSidebarSectionTitle = ({ name, href }) =>
-    <li>
-        <Link to={href} className={S.sectionTitle} activeClassName={S.selected}>{name}</Link>
-    </li>
-
-QuestionSidebarSectionTitle.propTypes = {
-    name:  PropTypes.string.isRequired,
-    href:  PropTypes.string.isRequired,
-};
-
-const QuestionSidebarItem = ({ name, icon, href }) =>
-    <li>
-        <Link to={href} className={S.item} activeClassName={S.selected}>
-            <LabelIcon className={S.icon} icon={icon}/>
-            <span className={S.name}>{name}</span>
-        </Link>
-    </li>
-
-QuestionSidebarItem.propTypes = {
-    name:  PropTypes.string.isRequired,
-    icon:  PropTypes.string.isRequired,
-    href:  PropTypes.string.isRequired,
-};
-
-export default pure(Sidebar);
diff --git a/frontend/src/metabase/questions/containers/Archive.jsx b/frontend/src/metabase/questions/containers/Archive.jsx
index d820b9b6aed..595b0d1a2b7 100644
--- a/frontend/src/metabase/questions/containers/Archive.jsx
+++ b/frontend/src/metabase/questions/containers/Archive.jsx
@@ -52,12 +52,12 @@ export default class Archive extends Component {
                 <div>
                     { items.map(item =>
                         item.type === "collection" ?
-                            <ArchivedItem name={item.name} type="collection" icon="collection" color={item.color} isAdmin={isAdmin} onUnarchive={async () => {
+                            <ArchivedItem key={item.type + item.id} name={item.name} type="collection" icon="collection" color={item.color} isAdmin={isAdmin} onUnarchive={async () => {
                                 await this.props.setCollectionArchived(item.id, false);
                                 this.loadEntities()
                             }} />
                         : item.type === "card" ?
-                            <ArchivedItem name={item.name} type="card" icon={visualizations.get(item.display).iconName} isAdmin={isAdmin} onUnarchive={async () => {
+                            <ArchivedItem key={item.type + item.id} name={item.name} type="card" icon={visualizations.get(item.display).iconName} isAdmin={isAdmin} onUnarchive={async () => {
                                 await this.props.setArchived(item.id, false, true);
                                 this.loadEntities();
                             }} />
diff --git a/frontend/src/metabase/questions/containers/EntityItem.jsx b/frontend/src/metabase/questions/containers/EntityItem.jsx
index bf216bbac6c..42882525c8b 100644
--- a/frontend/src/metabase/questions/containers/EntityItem.jsx
+++ b/frontend/src/metabase/questions/containers/EntityItem.jsx
@@ -30,6 +30,10 @@ export default class EntityItem extends Component {
         setItemSelected:    PropTypes.func.isRequired,
         setFavorited:       PropTypes.func.isRequired,
         setArchived:        PropTypes.func.isRequired,
+        editable:           PropTypes.bool,
+        showCollectionName: PropTypes.bool,
+        onEntityClick:      PropTypes.func,
+        onMove:             PropTypes.func,
     };
 
     render() {
diff --git a/frontend/src/metabase/questions/containers/EntityList.jsx b/frontend/src/metabase/questions/containers/EntityList.jsx
index ea4986b7726..2866d636930 100644
--- a/frontend/src/metabase/questions/containers/EntityList.jsx
+++ b/frontend/src/metabase/questions/containers/EntityList.jsx
@@ -120,14 +120,17 @@ export default class EntityList extends Component {
         setItemSelected:    PropTypes.func.isRequired,
         setAllSelected:     PropTypes.func.isRequired,
         setArchived:        PropTypes.func.isRequired,
-        loadEntities:      PropTypes.func.isRequired,
 
-        onChangeSection:    PropTypes.func,
-        showSearchWidget:   PropTypes.bool,
-        showCollectionName: PropTypes.bool,
-        editable:           PropTypes.bool,
+        loadEntities:       PropTypes.func.isRequired,
+        loadLabels:         PropTypes.func.isRequired,
 
         onEntityClick:      PropTypes.func,
+        onChangeSection:    PropTypes.func,
+        showSearchWidget:   PropTypes.bool.isRequired,
+        showCollectionName: PropTypes.bool.isRequired,
+        editable:           PropTypes.bool.isRequired,
+
+        defaultEmptyState:  PropTypes.string
     };
 
     static defaultProps = {
diff --git a/frontend/src/metabase/questions/containers/QuestionIndex.jsx b/frontend/src/metabase/questions/containers/QuestionIndex.jsx
index e6396897306..eb63c604f46 100644
--- a/frontend/src/metabase/questions/containers/QuestionIndex.jsx
+++ b/frontend/src/metabase/questions/containers/QuestionIndex.jsx
@@ -18,7 +18,7 @@ import { search } from "../questions";
 import { loadCollections } from "../collections";
 import { getUserIsAdmin } from "metabase/selectors/user";
 
-import { replace } from "react-router-redux";
+import { replace, push } from "react-router-redux";
 
 const mapStateToProps = (state, props) => ({
     items: state.questions.entities.cards,
@@ -32,6 +32,7 @@ const mapDispatchToProps = ({
     search,
     loadCollections,
     replace,
+    push,
 })
 
 @connect(mapStateToProps, mapDispatchToProps)
@@ -47,7 +48,7 @@ export default class QuestionIndex extends Component {
     }
 
     render () {
-        const { collections, replace, location, isAdmin } = this.props;
+        const { collections, replace, push, location, isAdmin } = this.props;
         const { questionsExpanded } = this.state;
         const hasCollections = collections.length > 0;
         const showCollections = isAdmin || hasCollections;
@@ -73,7 +74,7 @@ export default class QuestionIndex extends Component {
                 { showCollections &&
                     <div className="mb2">
                         { collections.length > 0 ?
-                            <CollectionButtons collections={collections} isAdmin={isAdmin} />
+                            <CollectionButtons collections={collections} isAdmin={isAdmin} push={push} />
                         :
                             <CollectionEmptyState />
                         }
diff --git a/frontend/src/metabase/questions/questions.js b/frontend/src/metabase/questions/questions.js
index 23f86b1b7db..8e786c57069 100644
--- a/frontend/src/metabase/questions/questions.js
+++ b/frontend/src/metabase/questions/questions.js
@@ -78,7 +78,7 @@ function createUndo(type, actions, collection) {
     return {
         type: type,
         count: actions.length,
-        message: (undo) =>
+        message: (undo) => // eslint-disable-line react/display-name
             <div className="flex flex-column">
                 <div>
                     { undo.count + " " + inflect(null, undo.count, "question was", "questions were") + " " + type }
-- 
GitLab