From 2dd143376d763a6c45c537c711f1a5e29cb36333 Mon Sep 17 00:00:00 2001
From: Alexandru Munteanu <alexandru.munteanu@thinslices.com>
Date: Thu, 1 Feb 2018 21:21:01 +0200
Subject: [PATCH] Create withFilter decorator

---
 .../src/components/Dashboard/Dashboard.js     | 45 +++++++++----------
 .../components/Dashboard/DashboardFilters.js  | 12 ++++-
 .../src/components/Dashboard/DashboardPage.js | 43 ++++++++++++++++--
 .../src/components/Dashboard/withFilters.js   | 30 +++++++++++++
 4 files changed, 100 insertions(+), 30 deletions(-)
 create mode 100644 packages/components-faraday/src/components/Dashboard/withFilters.js

diff --git a/packages/components-faraday/src/components/Dashboard/Dashboard.js b/packages/components-faraday/src/components/Dashboard/Dashboard.js
index 03de9a484..36429611c 100644
--- a/packages/components-faraday/src/components/Dashboard/Dashboard.js
+++ b/packages/components-faraday/src/components/Dashboard/Dashboard.js
@@ -17,6 +17,11 @@ const Dashboard = ({
   listView,
   filters,
   getItems,
+  getFilterOptions,
+  changeFilterValue,
+  filterValues,
+  filterItems,
+  ...rest
 }) => (
   <div className={classes.root}>
     <div className={classes.header}>
@@ -25,7 +30,12 @@ const Dashboard = ({
         New
       </Button>
     </div>
-    <DashboardFilters changeView={changeViewMode} listView={listView} />
+    <DashboardFilters
+      changeFilterValue={changeFilterValue}
+      changeView={changeViewMode}
+      getFilterOptions={getFilterOptions}
+      listView={listView}
+    />
     <DashboardItems
       deleteProject={deleteProject}
       list={getItems()}
@@ -40,33 +50,18 @@ export default compose(
     sortOrder: state.filters.sortValue,
   })),
   withHandlers({
-    getItems: ({ filters, sortOrder, currentUser, dashboard }) => () => {
+    getItems: ({
+      filters,
+      sortOrder,
+      currentUser,
+      dashboard,
+      filterItems,
+    }) => () => {
       const userItems = get(currentUser, 'admin')
         ? dashboard.all
         : dashboard.owner
-      const statusItems =
-        filters.status === 'all'
-          ? userItems
-          : userItems.filter(item => {
-              const itemStatus = get(item, 'status')
-              if (!itemStatus && filters.status === 'draft') {
-                return true
-              }
-              return itemStatus === filters.status
-            })
-      const ownerItems =
-        filters.owner === 'all'
-          ? statusItems
-          : statusItems.filter(item => {
-              const itemOwnerIds = item.owners.map(o => o.id)
-              if (filters.owner === 'me') {
-                return itemOwnerIds.includes(currentUser.id)
-              } else if (filters.owner === 'other') {
-                return !itemOwnerIds.includes(currentUser.id)
-              }
-              return false
-            })
-      return ownerItems.sort((a, b) => {
+
+      return filterItems(userItems).sort((a, b) => {
         if (sortOrder === 'newest') return a.created - b.created < 0
         return a.created - b.created > 0
       })
diff --git a/packages/components-faraday/src/components/Dashboard/DashboardFilters.js b/packages/components-faraday/src/components/Dashboard/DashboardFilters.js
index 45ceb6508..898778b14 100644
--- a/packages/components-faraday/src/components/Dashboard/DashboardFilters.js
+++ b/packages/components-faraday/src/components/Dashboard/DashboardFilters.js
@@ -31,17 +31,25 @@ const DashboardFilters = ({
   listView,
   changeFilter,
   changeSort,
+  getFilterOptions,
+  changeFilterValue,
 }) => (
   <div className={classes.filtersContainer}>
     <div className={classes.filters}>
       Filter view:
       <div className={classes['filter-group']}>
         <span>Owner</span>
-        <Menu onChange={changeFilter('owner')} options={ownerFilterOptions} />
+        <Menu
+          onChange={changeFilterValue('owner')}
+          options={getFilterOptions('owner')}
+        />
       </div>
       <div className={classes['filter-group']}>
         <span>Status</span>
-        <Menu onChange={changeFilter('status')} options={statusFilterOptions} />
+        <Menu
+          onChange={changeFilterValue('status')}
+          options={getFilterOptions('status')}
+        />
       </div>
       <div className={classes['filter-group']}>
         <span>Sort</span>
diff --git a/packages/components-faraday/src/components/Dashboard/DashboardPage.js b/packages/components-faraday/src/components/Dashboard/DashboardPage.js
index 8b9978eba..3006b1890 100644
--- a/packages/components-faraday/src/components/Dashboard/DashboardPage.js
+++ b/packages/components-faraday/src/components/Dashboard/DashboardPage.js
@@ -1,13 +1,16 @@
-import { compose, withState, withHandlers } from 'recompose'
+import { get } from 'lodash'
 import { connect } from 'react-redux'
-import { withRouter } from 'react-router-dom'
 import { actions } from 'pubsweet-client'
-import { newestFirst, selectCurrentUser } from 'xpub-selectors'
 import { ConnectPage } from 'xpub-connect'
+import { withRouter } from 'react-router-dom'
+import { compose, withState, withHandlers } from 'recompose'
+import { newestFirst, selectCurrentUser } from 'xpub-selectors'
 import { createDraftSubmission } from 'pubsweet-component-wizard/src/redux/conversion'
 
 import Dashboard from './Dashboard'
 
+import withFilters from './withFilters'
+
 export default compose(
   ConnectPage(() => [
     actions.getCollections(),
@@ -51,4 +54,38 @@ export default compose(
     }),
   ),
   withRouter,
+  withFilters({
+    status: {
+      options: [
+        { label: 'All', value: 'all' },
+        { label: 'Submitted', value: 'submitted' },
+        { label: 'Draft', value: 'draft' },
+      ],
+      filterFn: filterValue => item => {
+        if (filterValue === 'all' || filterValue === '') return true
+        const itemStatus = get(item, 'status')
+        if (!itemStatus && filterValue === 'draft') {
+          return true
+        }
+        return itemStatus === filterValue
+      },
+    },
+    owner: {
+      options: [
+        { label: 'Everyone', value: 'all' },
+        { label: 'My work', value: 'me' },
+        { label: `Other's work`, value: 'other' },
+      ],
+      filterFn: (filterValue, { currentUser }) => item => {
+        if (filterValue === 'all' || filterValue === '') return true
+        const itemOwnerIds = item.owners.map(o => o.id)
+        if (filterValue === 'me') {
+          return itemOwnerIds.includes(currentUser.id)
+        } else if (filterValue === 'other') {
+          return !itemOwnerIds.includes(currentUser.id)
+        }
+        return false
+      },
+    },
+  }),
 )(Dashboard)
diff --git a/packages/components-faraday/src/components/Dashboard/withFilters.js b/packages/components-faraday/src/components/Dashboard/withFilters.js
new file mode 100644
index 000000000..b51b7b6eb
--- /dev/null
+++ b/packages/components-faraday/src/components/Dashboard/withFilters.js
@@ -0,0 +1,30 @@
+import { get } from 'lodash'
+import { compose, withState, withHandlers } from 'recompose'
+
+export default config => Component => {
+  const filterFns = Object.entries(config).map(([filterKey, { filterFn }]) => ({
+    key: filterKey,
+    fn: filterFn,
+  }))
+  const filterValues = Object.keys(config).reduce(
+    (acc, el) => ({ ...acc, [el]: '' }),
+    {},
+  )
+  return compose(
+    withState('filterValues', 'setFilterValues', filterValues),
+    withHandlers({
+      getFilterOptions: () => key => get(config, `${key}.options`) || [],
+      changeFilterValue: ({ setFilterValues }) => filterKey => value => {
+        setFilterValues(v => ({
+          ...v,
+          [filterKey]: value,
+        }))
+      },
+      filterItems: ({ filterValues, ...props }) => items =>
+        filterFns.reduce(
+          (acc, { key, fn }) => acc.filter(fn(filterValues[key], props)),
+          items,
+        ),
+    }),
+  )(Component)
+}
-- 
GitLab