From bcfcf896408bdf6d98588bd3572248fc57cc57d6 Mon Sep 17 00:00:00 2001
From: pkupczyk <piotr.kupczyk@id.ethz.ch>
Date: Mon, 9 Sep 2019 20:55:09 +0200
Subject: [PATCH] SSDM-7594 : Grid - separate filtering for each column

---
 .../src/components/common/grid/Grid.jsx       | 62 ++++++++++++-------
 .../src/components/types/search/Search.jsx    | 18 ++++--
 .../src/components/users/search/Search.jsx    | 39 +++++++-----
 3 files changed, 77 insertions(+), 42 deletions(-)

diff --git a/openbis_ng_ui/src/components/common/grid/Grid.jsx b/openbis_ng_ui/src/components/common/grid/Grid.jsx
index 4d1708b0133..aaef1a30bed 100644
--- a/openbis_ng_ui/src/components/common/grid/Grid.jsx
+++ b/openbis_ng_ui/src/components/common/grid/Grid.jsx
@@ -22,11 +22,6 @@ const styles = theme => ({
     flexDirection: 'column',
     height: '100%'
   },
-  headerContainer: {
-    flexGrow: 0,
-    padding: theme.spacing(2),
-    paddingBottom: 0
-  },
   footerContainer: {
     display: 'flex',
     alignItems: 'center',
@@ -82,7 +77,7 @@ class Grid extends React.Component {
 
     this.state = {
       loaded: false,
-      filter: this.props.filter || '',
+      filters: this.props.filters || {},
       page: 0,
       pageSize: 10,
       visibleColumns: Object.keys(this.columnsMap),
@@ -112,7 +107,7 @@ class Grid extends React.Component {
   loadData() {
     if (_.isFunction(this.props.data)) {
       let loadConfig = {
-        filter: this.state.filter,
+        filters: this.state.filters,
         page: this.state.page,
         pageSize: this.state.pageSize,
         sort: this.state.sort,
@@ -173,11 +168,16 @@ class Grid extends React.Component {
     facade.updatePersons([update])
   }
 
-  handleFilterChange(filter) {
+  handleFilterChange(column, filter) {
+    let filters = {
+      ...this.state.filters,
+      [column]: filter
+    }
+
     this.setState(
       () => ({
         page: 0,
-        filter
+        filters
       }),
       () => {
         this.loadData()
@@ -239,17 +239,13 @@ class Grid extends React.Component {
   }
 
   filter(objects) {
-    const filter = this.state.filter
-      ? this.state.filter.trim().toUpperCase()
-      : null
-
-    function matches(value) {
+    function matches(value, filter) {
       if (filter) {
         return value
           ? value
               .trim()
               .toUpperCase()
-              .includes(filter)
+              .includes(filter.trim().toUpperCase())
           : false
       } else {
         return true
@@ -257,11 +253,13 @@ class Grid extends React.Component {
     }
 
     return _.filter(objects, row => {
-      return this.state.visibleColumns.some(visibleColumn => {
-        let column = this.columnsMap[visibleColumn]
-        let value = _.get(row, column.field)
-        return matches(value)
+      let matchesAll = true
+      this.state.visibleColumns.forEach(visibleColumn => {
+        let value = _.get(row, visibleColumn)
+        let filter = this.state.filters[visibleColumn]
+        matchesAll = matchesAll && matches(value, filter)
       })
+      return matchesAll
     })
   }
 
@@ -297,7 +295,7 @@ class Grid extends React.Component {
     }
 
     const { classes } = this.props
-    const { page, pageSize, filter, visibleColumns } = this.state
+    const { page, pageSize, visibleColumns } = this.state
 
     let pagedObjects = null
     let totalCount = null
@@ -314,12 +312,12 @@ class Grid extends React.Component {
 
     return (
       <div className={classes.container}>
-        <div className={classes.headerContainer}>
-          <FilterField filter={filter} filterChange={this.handleFilterChange} />
-        </div>
         <div className={classes.tableContainer}>
           <Table classes={{ root: classes.table }}>
             <TableHead classes={{ root: classes.tableHeader }}>
+              <TableRow>
+                {this.columnsArray.map(column => this.renderFilterCell(column))}
+              </TableRow>
               <TableRow>
                 {this.columnsArray.map(column => this.renderHeaderCell(column))}
               </TableRow>
@@ -382,6 +380,24 @@ class Grid extends React.Component {
     }
   }
 
+  renderFilterCell(column) {
+    const { visibleColumns, filters } = this.state
+
+    if (visibleColumns.includes(column.field)) {
+      let filter = filters[column.field] || ''
+      let filterChange = filter => {
+        this.handleFilterChange(column.field, filter)
+      }
+      return (
+        <TableCell key={column.field}>
+          <FilterField filter={filter} filterChange={filterChange} />
+        </TableCell>
+      )
+    } else {
+      return null
+    }
+  }
+
   renderRowCell(column, row) {
     const { visibleColumns } = this.state
 
diff --git a/openbis_ng_ui/src/components/types/search/Search.jsx b/openbis_ng_ui/src/components/types/search/Search.jsx
index c3b35814edb..c524ad3954f 100644
--- a/openbis_ng_ui/src/components/types/search/Search.jsx
+++ b/openbis_ng_ui/src/components/types/search/Search.jsx
@@ -58,10 +58,19 @@ class Search extends React.Component {
         dataSetTypes,
         materialTypes
       )
-      return allTypes.map(type => ({
-        ...type,
-        id: type.permId.entityKind + '-' + type.permId.permId
-      }))
+
+      let query = this.props.objectId.toUpperCase()
+
+      return allTypes
+        .filter(
+          type =>
+            (type.code && type.code.toUpperCase().includes(query)) ||
+            (type.description && type.description.toUpperCase().includes(query))
+        )
+        .map(type => ({
+          ...type,
+          id: type.permId.entityKind + '-' + type.permId.permId
+        }))
     })
   }
 
@@ -125,7 +134,6 @@ class Search extends React.Component {
     return (
       <Grid
         id={ids.TYPES_GRID_ID}
-        filter={this.props.objectId}
         columns={[
           {
             field: 'permId.entityKind',
diff --git a/openbis_ng_ui/src/components/users/search/Search.jsx b/openbis_ng_ui/src/components/users/search/Search.jsx
index cf9aef58c1d..337e8bbd177 100644
--- a/openbis_ng_ui/src/components/users/search/Search.jsx
+++ b/openbis_ng_ui/src/components/users/search/Search.jsx
@@ -8,40 +8,51 @@ class Search extends React.Component {
   constructor(props) {
     super(props)
 
+    this.state = {
+      loaded: false
+    }
+
     this.load = this.load.bind(this)
   }
 
-  load({ filter, page, pageSize }) {
+  componentDidMount() {
+    this.load().then(users => {
+      this.setState(() => ({
+        users,
+        loaded: true
+      }))
+    })
+  }
+
+  load() {
+    let query = this.props.objectId
+
     let criteria = new dto.PersonSearchCriteria()
     let fo = new dto.PersonFetchOptions()
 
     criteria.withOrOperator()
-    criteria.withUserId().thatContains(filter)
-    criteria.withFirstName().thatContains(filter)
-    criteria.withLastName().thatContains(filter)
-
-    fo.count(pageSize)
-    fo.from(page * pageSize)
+    criteria.withUserId().thatContains(query)
+    criteria.withFirstName().thatContains(query)
+    criteria.withLastName().thatContains(query)
 
     return facade.searchPersons(criteria, fo).then(result => {
-      let objects = result.objects.map(user => ({
+      return result.objects.map(user => ({
         ...user,
         id: user.userId
       }))
-      return {
-        objects,
-        totalCount: result.totalCount
-      }
     })
   }
 
   render() {
     logger.log(logger.DEBUG, 'Search.render')
 
+    if (!this.state.loaded) {
+      return null
+    }
+
     return (
       <Grid
         id={ids.USERS_GRID_ID}
-        filter={this.props.objectId}
         columns={[
           {
             field: 'userId'
@@ -53,7 +64,7 @@ class Search extends React.Component {
             field: 'lastName'
           }
         ]}
-        data={this.load}
+        data={this.state.users}
       />
     )
   }
-- 
GitLab