Unverified Commit cd0ab5db authored by Paul Kaplan's avatar Paul Kaplan Committed by GitHub

Merge pull request #5164 from paulkaplan/studio-roles

Fetch studio info and roles in redux
parents a087ac4f 57495259
const keyMirror = require('keymirror');
const api = require('../lib/api');
const log = require('../lib/log');
const Status = keyMirror({
FETCHED: null,
NOT_FETCHED: null,
FETCHING: null,
ERROR: null
});
const getInitialState = () => ({
infoStatus: Status.NOT_FETCHED,
title: '',
description: '',
openToAll: false,
commentingAllowed: false,
thumbnail: '',
followers: 0,
rolesStatus: Status.NOT_FETCHED,
manager: false,
curator: false,
follower: false,
invited: false
});
const studioReducer = (state, action) => {
if (typeof state === 'undefined') {
state = getInitialState();
}
switch (action.type) {
case 'SET_INFO':
return {
...state,
...action.info
};
case 'SET_ROLES':
return {
...state,
...action.roles
};
case 'SET_FETCH_STATUS':
if (action.error) {
log.error(action.error);
}
return {
...state,
[action.fetchType]: action.fetchStatus
};
default:
return state;
}
};
const setFetchStatus = (fetchType, fetchStatus, error) => ({
type: 'SET_FETCH_STATUS',
fetchType,
fetchStatus,
error
});
const setInfo = info => ({
type: 'SET_INFO',
info: info
});
const setRoles = roles => ({
type: 'SET_ROLES',
roles: roles
});
const getInfo = studioId => (dispatch => {
dispatch(setFetchStatus('infoStatus', Status.FETCHING));
api({uri: `/studios/${studioId}`}, (err, body, res) => {
if (err || typeof body === 'undefined' || res.statusCode !== 200) {
dispatch(setFetchStatus('infoStatus', Status.ERROR, err));
return;
}
dispatch(setFetchStatus('infoStatus', Status.FETCHED));
dispatch(setInfo({
title: body.title,
description: body.description,
openToAll: body.open_to_all,
commentingAllowed: body.commenting_allowed,
updated: new Date(body.history.modified),
followers: body.stats.followers
}));
});
});
const getRoles = (studioId, username, token) => (dispatch => {
dispatch(setFetchStatus('rolesStatus', Status.FETCHING));
api({
uri: `/studios/${studioId}/users/${username}`,
authentication: token
}, (err, body, res) => {
if (err || typeof body === 'undefined' || res.statusCode !== 200) {
dispatch(setFetchStatus('rolesStatus', Status.ERROR, err));
return;
}
dispatch(setFetchStatus('rolesStatus', Status.FETCHED));
dispatch(setRoles({
manager: body.manager,
curator: body.curator,
following: body.following,
invited: body.invited
}));
});
});
module.exports = {
getInitialState,
studioReducer,
Status,
getInfo,
getRoles
};
const ITEM_LIMIT = 4;
const infoFetcher = studioId => fetch(`${process.env.API_HOST}/studios/${studioId}`)
.then(response => response.json());
const projectFetcher = (studioId, offset) =>
fetch(`${process.env.API_HOST}/studios/${studioId}/projects?limit=${ITEM_LIMIT}&offset=${offset}`)
.then(response => response.json())
......@@ -25,7 +22,6 @@ const activityFetcher = studioId =>
export {
activityFetcher,
infoFetcher,
projectFetcher,
curatorFetcher,
managerFetcher
......
import React, {useState, useEffect} from 'react';
import React, {useEffect} from 'react';
import PropTypes from 'prop-types';
import {useParams} from 'react-router-dom';
import {infoFetcher} from './lib/fetchers';
import {connect} from 'react-redux';
import Debug from './debug.jsx';
import {getInfo, getRoles} from '../../redux/studio';
const StudioInfo = () => {
const StudioInfo = ({username, studio, token, onLoadInfo, onLoadRoles}) => {
const {studioId} = useParams();
const [state, setState] = useState({loading: false, error: null, data: null});
// Since this data is in a component that is always visible, it doesn't necessarily
// need to be kept in redux. One alternative is to use the infinite-list redux
// module and just treat the studio info as the first and only item in the list.
useEffect(() => {
if (!studioId) return;
infoFetcher(studioId)
.then(data => setState({loading: false, error: null, data}))
.catch(error => setState({loading: false, error, data: null}));
useEffect(() => { // Load studio info after first render
if (studioId) onLoadInfo(studioId);
}, [studioId]);
useEffect(() => { // Load roles info once the username is available
if (studioId && username && token) onLoadRoles(studioId, username, token);
}, [studioId, username, token]);
return (
<div>
<h2>Studio Info</h2>
{state.loading && <div>Loading..</div>}
{state.error && <Debug
label="Error"
data={state.error}
/>}
<Debug
label="Studio Info"
data={state.data}
data={studio}
/>
</div>
);
};
export default StudioInfo;
StudioInfo.propTypes = {
username: PropTypes.string,
token: PropTypes.string,
studio: PropTypes.shape({
// Fill this in as the data is used, just for demo now
}),
onLoadInfo: PropTypes.func,
onLoadRoles: PropTypes.func
};
export default connect(
state => {
const user = state.session.session.user;
return {
studio: state.studio,
username: user && user.username,
token: user && user.token
};
},
dispatch => ({
onLoadInfo: studioId => dispatch(getInfo(studioId)),
onLoadRoles: (studioId, username, token) => dispatch(
getRoles(studioId, username, token))
})
)(StudioInfo);
......@@ -24,6 +24,8 @@ import {
activity
} from './lib/redux-modules';
const {studioReducer} = require('../../redux/studio');
const StudioShell = () => {
const match = useRouteMatch();
......@@ -72,6 +74,7 @@ render(
[projects.key]: projects.reducer,
[curators.key]: curators.reducer,
[managers.key]: managers.reducer,
[activity.key]: activity.reducer
[activity.key]: activity.reducer,
studio: studioReducer
}
);
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