connected seatch to wf catalog

Issue-ID: SDC-1671
Change-Id: I61972b9715141cbf7a8a00d4d0d5e1a4b5c40555
Signed-off-by: Yarin Dekel <yarind@amdocs.com>
diff --git a/workflow-designer-ui/src/main/frontend/src/features/catalog/Catalog.js b/workflow-designer-ui/src/main/frontend/src/features/catalog/Catalog.js
index 8ff33bd..dbbdbb1 100644
--- a/workflow-designer-ui/src/main/frontend/src/features/catalog/Catalog.js
+++ b/workflow-designer-ui/src/main/frontend/src/features/catalog/Catalog.js
@@ -17,7 +17,11 @@
 import { connect } from 'react-redux';
 
 import CatalogView from 'features/catalog/CatalogView';
-import { fetchWorkflow, resetWorkflow } from 'features/catalog/catalogActions';
+import {
+    fetchWorkflow,
+    resetWorkflow,
+    searchChangedAction
+} from 'features/catalog/catalogActions';
 
 import { showCustomModalAction } from 'shared/modal/modalWrapperActions';
 import { NEW_WORKFLOW_MODAL } from 'shared/modal/modalWrapperComponents';
@@ -38,7 +42,9 @@
                 customComponentName: NEW_WORKFLOW_MODAL,
                 title: 'New Workflow'
             })
-        )
+        ),
+    searchInputChanged: searchValue =>
+        dispatch(searchChangedAction(searchValue))
 });
 
 const Catalog = connect(mapStateToProps, mapDispatchToProps)(CatalogView);
diff --git a/workflow-designer-ui/src/main/frontend/src/features/catalog/CatalogView.jsx b/workflow-designer-ui/src/main/frontend/src/features/catalog/CatalogView.jsx
index 2d8c8d7..05a79e9 100644
--- a/workflow-designer-ui/src/main/frontend/src/features/catalog/CatalogView.jsx
+++ b/workflow-designer-ui/src/main/frontend/src/features/catalog/CatalogView.jsx
@@ -14,7 +14,7 @@
 * limitations under the License.
 */
 
-import React from 'react';
+import React, { Component } from 'react';
 import PropTypes from 'prop-types';
 import InfiniteScroll from 'shared/scroll/InfiniteScroll';
 import Workflows from 'features/catalog/views/Workflows';
@@ -22,10 +22,16 @@
 
 import Header from 'features/catalog/views/Header';
 import Main from 'features/catalog/views/Main';
-
 import { NAME, ASC, DESC } from 'features/catalog/catalogConstants';
 
-class CatalogView extends React.Component {
+class CatalogView extends Component {
+    constructor(props) {
+        super(props);
+        this.state = {
+            searchValue: ''
+        };
+    }
+
     componentDidMount() {
         const { clearWorkflow } = this.props;
 
@@ -68,6 +74,15 @@
         history.push('/workflow/' + id + '/overview');
     };
 
+    searchChange = searchValue => {
+        const { searchInputChanged, catalog } = this.props;
+        this.setState({ searchValue: searchValue });
+        searchInputChanged({
+            ...catalog,
+            searchNameFilter: searchValue
+        });
+    };
+
     render() {
         const { catalog, showNewWorkflowModal } = this.props;
         const {
@@ -79,7 +94,10 @@
 
         return (
             <div className="wf-catalog">
-                <Header />
+                <Header
+                    searchChange={this.searchChange}
+                    searchValue={this.state.searchValue}
+                />
                 <InfiniteScroll
                     useWindow={false}
                     loadMore={this.handleScroll}
@@ -110,7 +128,8 @@
     handleResetWorkflow: PropTypes.func,
     handleFetchWorkflow: PropTypes.func,
     showNewWorkflowModal: PropTypes.func,
-    clearWorkflow: PropTypes.func
+    clearWorkflow: PropTypes.func,
+    searchInputChanged: PropTypes.func
 };
 
 CatalogView.defaultProps = {
diff --git a/workflow-designer-ui/src/main/frontend/src/features/catalog/__tests__/catalogSagas-test.js b/workflow-designer-ui/src/main/frontend/src/features/catalog/__tests__/catalogSagas-test.js
index dd89c18..b747e97 100644
--- a/workflow-designer-ui/src/main/frontend/src/features/catalog/__tests__/catalogSagas-test.js
+++ b/workflow-designer-ui/src/main/frontend/src/features/catalog/__tests__/catalogSagas-test.js
@@ -17,9 +17,15 @@
 'use strict';
 
 import { runSaga } from 'redux-saga';
-import { takeLatest } from 'redux-saga/effects';
+import { takeLatest, throttle } from 'redux-saga/effects';
 
-import { NAME, DESC, LIMIT } from 'features/catalog/catalogConstants';
+import {
+    NAME,
+    DESC,
+    LIMIT,
+    SEARCH_CHANGED,
+    SEARCH_BUFFER
+} from 'features/catalog/catalogConstants';
 import catalogApi from '../catalogApi';
 import { fetchWorkflow, updateWorkflow } from 'features/catalog/catalogActions';
 import catalogSaga, { fetchWorkflowSaga } from 'features/catalog/catalogSagas';
@@ -34,6 +40,9 @@
             takeLatest(fetchWorkflow, fetchWorkflowSaga)
         );
 
+        expect(gen.next().value).toEqual(
+            throttle(SEARCH_BUFFER, SEARCH_CHANGED, fetchWorkflowSaga)
+        );
         expect(gen.next().done).toBe(true);
     });
 
@@ -42,6 +51,7 @@
             [NAME]: DESC
         };
         const offset = 0;
+        const searchNameFilter = undefined;
         const data = {
             paging: {
                 offset,
@@ -50,6 +60,7 @@
                 hasMore: false,
                 total: 2
             },
+            searchNameFilter: 'w',
             items: [
                 {
                     id: 'c5b7ca1a0f7944bfa948b85b32c5f314',
@@ -86,7 +97,8 @@
         expect(catalogApi.getWorkflows).toBeCalledWith(
             sort,
             LIMIT,
-            offset + LIMIT
+            offset + LIMIT,
+            searchNameFilter
         );
     });
 });
diff --git a/workflow-designer-ui/src/main/frontend/src/features/catalog/catalogActions.js b/workflow-designer-ui/src/main/frontend/src/features/catalog/catalogActions.js
index 13e43a0..eed8b9c 100644
--- a/workflow-designer-ui/src/main/frontend/src/features/catalog/catalogActions.js
+++ b/workflow-designer-ui/src/main/frontend/src/features/catalog/catalogActions.js
@@ -14,9 +14,13 @@
 * limitations under the License.
 */
 
-import { createActions } from 'redux-actions';
+import { createActions, createAction } from 'redux-actions';
 
-import { NAMESPACE, LIMIT } from 'features/catalog/catalogConstants';
+import {
+    NAMESPACE,
+    LIMIT,
+    SEARCH_CHANGED
+} from 'features/catalog/catalogConstants';
 
 export const {
     [NAMESPACE]: { fetchWorkflow, updateWorkflow, resetWorkflow }
@@ -31,3 +35,8 @@
         RESET_WORKFLOW: undefined
     }
 });
+
+export const searchChangedAction = createAction(
+    SEARCH_CHANGED,
+    payload => payload
+);
diff --git a/workflow-designer-ui/src/main/frontend/src/features/catalog/catalogApi.js b/workflow-designer-ui/src/main/frontend/src/features/catalog/catalogApi.js
index 622c523..f5c9e21 100644
--- a/workflow-designer-ui/src/main/frontend/src/features/catalog/catalogApi.js
+++ b/workflow-designer-ui/src/main/frontend/src/features/catalog/catalogApi.js
@@ -25,18 +25,17 @@
 }
 
 const Api = {
-    getWorkflows: (sort, limit, offset) => {
-        const queryString = qs.stringify(
-            {
-                sort: Object.keys(sort).map(key => `${key}:${sort[key]}`),
-                limit,
-                offset
-            },
-            {
-                indices: false,
-                addQueryPrefix: true
-            }
-        );
+    getWorkflows: (sort, limit, offset, searchNameFilter) => {
+        const queryParams = {
+            sort: Object.keys(sort).map(key => `${key}:${sort[key]}`),
+            limit,
+            offset
+        };
+        if (searchNameFilter) queryParams.searchNameFilter = searchNameFilter;
+        const queryString = qs.stringify(queryParams, {
+            indices: false,
+            addQueryPrefix: true
+        });
 
         return RestfulAPIUtil.fetch(`${baseUrl()}${queryString}`);
     }
diff --git a/workflow-designer-ui/src/main/frontend/src/features/catalog/catalogConstants.js b/workflow-designer-ui/src/main/frontend/src/features/catalog/catalogConstants.js
index a945b83..1306937 100644
--- a/workflow-designer-ui/src/main/frontend/src/features/catalog/catalogConstants.js
+++ b/workflow-designer-ui/src/main/frontend/src/features/catalog/catalogConstants.js
@@ -21,6 +21,8 @@
 export const DESC = 'desc';
 
 export const LIMIT = 20;
+export const SEARCH_BUFFER = 1000;
+export const SEARCH_CHANGED = `catalog/SEARCH_CHANGED`;
 
 export const FETCH_WORKFLOW = `${NAMESPACE}/FETCH_WORKFLOW`;
 export const UPDATE_WORKFLOW = `${NAMESPACE}/UPDATE_WORKFLOW`;
diff --git a/workflow-designer-ui/src/main/frontend/src/features/catalog/catalogSagas.js b/workflow-designer-ui/src/main/frontend/src/features/catalog/catalogSagas.js
index bf56c61..fc8d349 100644
--- a/workflow-designer-ui/src/main/frontend/src/features/catalog/catalogSagas.js
+++ b/workflow-designer-ui/src/main/frontend/src/features/catalog/catalogSagas.js
@@ -14,24 +14,27 @@
 * limitations under the License.
 */
 
-import { call, put, takeLatest } from 'redux-saga/effects';
+import { call, put, takeLatest, throttle } from 'redux-saga/effects';
 
 import catalogApi from 'features/catalog/catalogApi';
 import { fetchWorkflow, updateWorkflow } from 'features/catalog/catalogActions';
+import {
+    SEARCH_CHANGED,
+    SEARCH_BUFFER
+} from 'features/catalog/catalogConstants';
 
 const noOp = () => {};
 
 export function* fetchWorkflowSaga({ payload }) {
-    const { sort, limit, offset } = payload;
-
+    const { sort, limit, offset, searchNameFilter } = payload;
     try {
         const data = yield call(
             catalogApi.getWorkflows,
             sort,
             limit,
-            offset === undefined ? 0 : offset + limit
+            offset === undefined ? 0 : offset + limit,
+            searchNameFilter
         );
-
         yield put(updateWorkflow({ sort, ...data }));
     } catch (e) {
         noOp();
@@ -40,6 +43,7 @@
 
 function* catalogSaga() {
     yield takeLatest(fetchWorkflow, fetchWorkflowSaga);
+    yield throttle(SEARCH_BUFFER, SEARCH_CHANGED, fetchWorkflowSaga);
 }
 
 export default catalogSaga;