Commit 600e5846 authored by Paul Kaplan's avatar Paul Kaplan

Move activity loading to studio-activity-actions, include pagination

parent dbec1c7a
// TODO move this to studio-activity-actions, include pagination
const activityFetcher = studioId =>
fetch(`${process.env.API_HOST}/studios/${studioId}/activity`)
.then(response => response.json())
.then(data => ({items: data, moreToLoad: false})); // No pagination on the activity feed
export {
activityFetcher
};
import keyMirror from 'keymirror';
import api from '../../../lib/api';
import {activity} from './redux-modules';
import {selectStudioId} from '../../../redux/studio';
const Errors = keyMirror({
NETWORK: null,
SERVER: null,
PERMISSION: null
});
const normalizeError = (err, body, res) => {
if (err) return Errors.NETWORK;
if (res.statusCode === 401 || res.statusCode === 403) return Errors.PERMISSION;
if (res.statusCode !== 200) return Errors.SERVER;
return null;
};
const loadActivity = () => ((dispatch, getState) => {
const state = getState();
const studioId = selectStudioId(state);
const items = activity.selector(state).items;
const params = {limit: 20};
if (items.length > 0) {
// dateLimit is the newest notification you want to get back, which is
// the date of the oldest one we've already loaded
params.dateLimit = items[items.length - 1].datetime_created;
}
api({
uri: `/studios/${studioId}/activity/`,
params
}, (err, body, res) => {
const error = normalizeError(err, body, res);
if (error) return dispatch(activity.actions.error(error));
const ids = items.map(item => item.id);
// Deduplication is needed because pagination based on date can contain duplicates
const deduped = body.filter(item => ids.indexOf(item.id) === -1);
dispatch(activity.actions.append(deduped, body.length === params.limit));
});
});
export {loadActivity};
...@@ -2,20 +2,15 @@ import React, {useEffect} from 'react'; ...@@ -2,20 +2,15 @@ import React, {useEffect} from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import {connect} from 'react-redux'; import {connect} from 'react-redux';
import {useParams} from 'react-router';
import {activity} from './lib/redux-modules'; import {activity} from './lib/redux-modules';
import {activityFetcher} from './lib/fetchers'; import {loadActivity} from './lib/studio-activity-actions';
import Debug from './debug.jsx'; import Debug from './debug.jsx';
const StudioActivity = ({items, loading, error, onInitialLoad}) => { const StudioActivity = ({items, loading, error, moreToLoad, onLoadMore}) => {
const {studioId} = useParams();
// Fetch the data if none has been loaded yet. This would run only once,
// since studioId doesnt change, but the component is potentially mounted
// multiple times because of tab routing, so need to check for empty items.
useEffect(() => { useEffect(() => {
if (studioId && items.length === 0) onInitialLoad(studioId); if (items.length === 0) onLoadMore();
}, [studioId]); // items.length intentionally left out }, []);
return ( return (
<div> <div>
...@@ -33,6 +28,15 @@ const StudioActivity = ({items, loading, error, onInitialLoad}) => { ...@@ -33,6 +28,15 @@ const StudioActivity = ({items, loading, error, onInitialLoad}) => {
key={index} key={index}
/>) />)
)} )}
<div>
{loading ? <small>Loading...</small> : (
moreToLoad ?
<button onClick={onLoadMore}>
Load more
</button> :
<small>No more to load</small>
)}
</div>
</div> </div>
</div> </div>
); );
...@@ -42,13 +46,13 @@ StudioActivity.propTypes = { ...@@ -42,13 +46,13 @@ StudioActivity.propTypes = {
items: PropTypes.array, // eslint-disable-line react/forbid-prop-types items: PropTypes.array, // eslint-disable-line react/forbid-prop-types
loading: PropTypes.bool, loading: PropTypes.bool,
error: PropTypes.object, // eslint-disable-line react/forbid-prop-types error: PropTypes.object, // eslint-disable-line react/forbid-prop-types
onInitialLoad: PropTypes.func moreToLoad: PropTypes.bool,
onLoadMore: PropTypes.func
}; };
export default connect( export default connect(
state => activity.selector(state), state => activity.selector(state),
dispatch => ({ {
onInitialLoad: studioId => dispatch( onLoadMore: loadActivity
activity.actions.loadMore(activityFetcher.bind(null, studioId, 0))) }
})
)(StudioActivity); )(StudioActivity);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment