diff --git a/client/coral-admin/src/actions/assets.js b/client/coral-admin/src/actions/assets.js index 1ce6ad6ac..d7c6d9448 100644 --- a/client/coral-admin/src/actions/assets.js +++ b/client/coral-admin/src/actions/assets.js @@ -1,3 +1,5 @@ +import queryString from 'query-string'; + import { FETCH_ASSETS_REQUEST, FETCH_ASSETS_SUCCESS, @@ -16,13 +18,16 @@ import t from 'coral-framework/services/i18n'; // Fetch a page of assets // Get comments to fill each of the three lists on the mod queue -export const fetchAssets = (skip = '', limit = '', search = '', sort = '', filter = '') => (dispatch, _, {rest}) => { +export const fetchAssets = (query = {}) => (dispatch, _, {rest}) => { dispatch({type: FETCH_ASSETS_REQUEST}); - return rest(`/assets?skip=${skip}&limit=${limit}&sort=${sort}&search=${search}&filter=${filter}`) - .then(({result, count}) => + return rest(`/assets?${queryString.stringify(query)}`) + .then(({result, page, count, limit, totalPages}) => dispatch({type: FETCH_ASSETS_SUCCESS, assets: result, - count + page, + count, + limit, + totalPages, })) .catch((error) => { console.error(error); diff --git a/client/coral-admin/src/reducers/assets.js b/client/coral-admin/src/reducers/assets.js index bb8751973..b4ea8d21f 100644 --- a/client/coral-admin/src/reducers/assets.js +++ b/client/coral-admin/src/reducers/assets.js @@ -16,6 +16,8 @@ export default function assets (state = initialState, action) { }, {}); return update(state, { + totalPages: {$set: action.totalPages}, + page: {$set: action.page}, byId: {$set: assets}, count: {$set: action.count}, ids: {$set: Object.keys(assets)}, diff --git a/client/coral-admin/src/routes/Stories/components/Stories.js b/client/coral-admin/src/routes/Stories/components/Stories.js index 966e8a9c3..c37a7f8f6 100644 --- a/client/coral-admin/src/routes/Stories/components/Stories.js +++ b/client/coral-admin/src/routes/Stories/components/Stories.js @@ -8,38 +8,54 @@ import t from 'coral-framework/services/i18n'; import styles from './Stories.css'; import EmptyCard from 'coral-admin/src/components/EmptyCard'; -const limit = 25; - class Stories extends Component { state = { - search: '', + searchValue: '', sort: 'desc', filter: 'all', statusMenus: {}, timer: null, - page: 0 } componentDidMount () { - this.props.fetchAssets(0, limit, '', this.state.sortBy); + const {sort} = this.state; + + this.props.fetchAssets({ + sort, + }); } onSettingChange = (setting) => (e) => { - let options = this.state; - this.setState({[setting]: e.target.value}); - options[setting] = e.target.value; - this.props.fetchAssets(0, limit, options.search, options.sort, options.filter); + const {searchValue, sort, filter} = this.state; + + this.setState({ + [setting]: e.target.value + }); + + this.props.fetchAssets({ + value: searchValue, + sort, + filter, + }); } onSearchChange = (e) => { - const search = e.target.value; + const {fetchAssets} = this.props; + const {value} = e.target; + const {sort, filter, limit} = this.state; + this.setState((prevState) => { - prevState.search = search; + prevState.searchValue = value; clearTimeout(prevState.timer); - const fetchAssets = this.props.fetchAssets; + prevState.timer = setTimeout(() => { - fetchAssets(0, limit, search, this.state.sort, this.state.filter); + fetchAssets({ + value, + sort, + filter, + limit, + }); }, 350); return prevState; }); @@ -51,10 +67,17 @@ class Stories extends Component { } onStatusChange = async (closeStream, id) => { + const {fetchAssets, updateAssetState} = this.props; + const {searchValue, sort, filter, limit} = this.state; + try { - this.props.updateAssetState(id, closeStream ? Date.now() : null); - const {search, sort, filter, page} = this.state; - this.props.fetchAssets(page, limit, search, sort, filter); + updateAssetState(id, closeStream ? Date.now() : null); + fetchAssets({ + value: searchValue, + sort, + filter, + limit, + }); } catch(err) { console.error(err); } @@ -74,10 +97,17 @@ class Stories extends Component { ); } - onPageClick = (page) => { - this.setState({page}); - const {search, sort, filter} = this.state; - this.props.fetchAssets((page - 1) * limit, limit, search, sort, filter); + onPageClick = ({selected}) => { + const page = selected + 1; + const {searchValue, sort, filter, limit} = this.state; + + this.props.fetchAssets({ + page, + value: searchValue, + sort, + filter, + limit, + }); } render () { @@ -140,7 +170,7 @@ class Stories extends Component { : {t('streams.empty_result')} diff --git a/client/coral-admin/src/routes/Stories/containers/Stories.js b/client/coral-admin/src/routes/Stories/containers/Stories.js index f645f310c..b940e46e6 100644 --- a/client/coral-admin/src/routes/Stories/containers/Stories.js +++ b/client/coral-admin/src/routes/Stories/containers/Stories.js @@ -1,19 +1,9 @@ -import React, {Component} from 'react'; import {connect} from 'react-redux'; import {bindActionCreators} from 'redux'; -import {compose} from 'react-apollo'; import {fetchAssets, updateAssetState} from 'coral-admin/src/actions/assets'; import Stories from '../components/Stories'; -class StoriesContainer extends Component { - render () { - return ; - } -} - -const mapStateToProps = (state) => ({ - assets: state.assets -}); +const mapStateToProps = ({assets}) => ({assets}); const mapDispatchToProps = (dispatch) => bindActionCreators({ @@ -21,7 +11,5 @@ const mapDispatchToProps = (dispatch) => updateAssetState, }, dispatch); -export default compose( - connect(mapStateToProps, mapDispatchToProps), -)(StoriesContainer); +export default connect(mapStateToProps, mapDispatchToProps)(Stories); diff --git a/routes/api/assets/index.js b/routes/api/assets/index.js index 1b2b0c7a9..4007517de 100644 --- a/routes/api/assets/index.js +++ b/routes/api/assets/index.js @@ -37,34 +37,44 @@ const FilterOpenAssets = (query, filter) => { router.get('/', authorization.needed('ADMIN', 'MODERATOR'), async (req, res, next) => { const { - limit = 20, - skip = 0, - sort = 'asc', + value = '', field = 'created_at', + page = 1, + asc = 'false', filter = 'all', - search = '' + limit = 20, } = req.query; try { + const queryOpts = { + sort: {[field]: (asc === 'true') ? 1 : -1}, + skip: (page - 1) * limit, + limit + }; + // Find all the assets. let [result, count] = await Promise.all([ // Find the actuall assets. - FilterOpenAssets(AssetsService.search({value: search}), filter) - .sort({[field]: (sort === 'asc') ? 1 : -1}) - .skip(parseInt(skip)) - .limit(parseInt(limit)), + FilterOpenAssets(AssetsService.search({value}), filter) + .sort(queryOpts.sort) + .skip(parseInt(queryOpts.skip)) + .limit(parseInt(queryOpts.limit)) + .lean(), // Get the count of actual assets. - FilterOpenAssets(AssetsService.search({value: search}), filter) + FilterOpenAssets(AssetsService.search({value}), filter) .count() ]); // Send back the asset data. res.json({ result, - count + limit: Number(limit), + count, + page: Number(page), + totalPages: Math.ceil(count / (limit === 0 ? 1 : limit)) }); } catch (e) { return next(e); diff --git a/routes/api/users/index.js b/routes/api/users/index.js index 0cf1c997b..98cdcdead 100644 --- a/routes/api/users/index.js +++ b/routes/api/users/index.js @@ -31,8 +31,8 @@ router.get('/', authorization.needed('ADMIN', 'MODERATOR'), async (req, res, nex UsersService .search(value) .sort(queryOpts.sort) - .skip(queryOpts.skip) - .limit(queryOpts.limit) + .skip(parseInt(queryOpts.skip)) + .limit(parseInt(queryOpts.limit)) .lean(), UsersService.search(value).count() ]);