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';
customComponentName: NEW_WORKFLOW_MODAL,
title: 'New Workflow'
})
- )
+ ),
+ searchInputChanged: searchValue =>
+ dispatch(searchChangedAction(searchValue))
});
const Catalog = connect(mapStateToProps, mapDispatchToProps)(CatalogView);
* 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';
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;
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 {
return (
<div className="wf-catalog">
- <Header />
+ <Header
+ searchChange={this.searchChange}
+ searchValue={this.state.searchValue}
+ />
<InfiniteScroll
useWindow={false}
loadMore={this.handleScroll}
handleResetWorkflow: PropTypes.func,
handleFetchWorkflow: PropTypes.func,
showNewWorkflowModal: PropTypes.func,
- clearWorkflow: PropTypes.func
+ clearWorkflow: PropTypes.func,
+ searchInputChanged: PropTypes.func
};
CatalogView.defaultProps = {
'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';
takeLatest(fetchWorkflow, fetchWorkflowSaga)
);
+ expect(gen.next().value).toEqual(
+ throttle(SEARCH_BUFFER, SEARCH_CHANGED, fetchWorkflowSaga)
+ );
expect(gen.next().done).toBe(true);
});
[NAME]: DESC
};
const offset = 0;
+ const searchNameFilter = undefined;
const data = {
paging: {
offset,
hasMore: false,
total: 2
},
+ searchNameFilter: 'w',
items: [
{
id: 'c5b7ca1a0f7944bfa948b85b32c5f314',
expect(catalogApi.getWorkflows).toBeCalledWith(
sort,
LIMIT,
- offset + LIMIT
+ offset + LIMIT,
+ searchNameFilter
);
});
});
* 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 }
RESET_WORKFLOW: undefined
}
});
+
+export const searchChangedAction = createAction(
+ SEARCH_CHANGED,
+ payload => payload
+);
}
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}`);
}
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`;
* 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();
function* catalogSaga() {
yield takeLatest(fetchWorkflow, fetchWorkflowSaga);
+ yield throttle(SEARCH_BUFFER, SEARCH_CHANGED, fetchWorkflowSaga);
}
export default catalogSaga;