This commit is contained in:
Belen Curcio
2017-10-23 23:47:43 -03:00
parent f004573ed2
commit d363c977dc
11 changed files with 202 additions and 236 deletions
+10 -10
View File
@@ -1,9 +1,9 @@
import queryString from 'query-string';
import {
FETCH_COMMENTERS_REQUEST,
FETCH_COMMENTERS_SUCCESS,
FETCH_COMMENTERS_FAILURE,
FETCH_USERS_REQUEST,
FETCH_USERS_SUCCESS,
FETCH_USERS_FAILURE,
SORT_UPDATE,
COMMENTERS_NEW_PAGE,
SET_ROLE,
@@ -16,13 +16,13 @@ import {
import t from 'coral-framework/services/i18n';
export const fetchAccounts = (query = {}) => (dispatch, _, {rest}) => {
dispatch(requestFetchAccounts());
export const fetchUsers = (query = {}) => (dispatch, _, {rest}) => {
dispatch(requestFetchUsers());
rest(`/users?${queryString.stringify(query)}`)
.then(({result, page, count, limit, totalPages}) =>{
dispatch({
type: FETCH_COMMENTERS_SUCCESS,
accounts: result,
type: FETCH_USERS_SUCCESS,
users: result,
page,
count,
limit,
@@ -32,12 +32,12 @@ export const fetchAccounts = (query = {}) => (dispatch, _, {rest}) => {
.catch((error) => {
console.error(error);
const errorMessage = error.translation_key ? t(`error.${error.translation_key}`) : error.toString();
dispatch({type: FETCH_COMMENTERS_FAILURE, error: errorMessage});
dispatch({type: FETCH_USERS_FAILURE, error: errorMessage});
});
};
const requestFetchAccounts = () => ({
type: FETCH_COMMENTERS_REQUEST
const requestFetchUsers = () => ({
type: FETCH_USERS_REQUEST
});
export const updateSorting = (sort) => ({
@@ -1,6 +1,7 @@
export const FETCH_COMMENTERS_REQUEST = 'FETCH_COMMENTERS_REQUEST';
export const FETCH_COMMENTERS_SUCCESS = 'FETCH_COMMENTERS_SUCCESS';
export const FETCH_COMMENTERS_FAILURE = 'FETCH_COMMENTERS_FAILURE';
export const FETCH_USERS_REQUEST = 'FETCH_USERS_REQUEST';
export const FETCH_USERS_SUCCESS = 'FETCH_USERS_SUCCESS';
export const FETCH_USERS_FAILURE = 'FETCH_USERS_FAILURE';
export const SORT_UPDATE = 'SORT_UPDATE';
export const COMMENTERS_NEW_PAGE = 'COMMENTERS_NEW_PAGE';
export const SET_ROLE = 'SET_ROLE';
+13 -13
View File
@@ -1,7 +1,7 @@
import {
FETCH_COMMENTERS_REQUEST,
FETCH_COMMENTERS_FAILURE,
FETCH_COMMENTERS_SUCCESS,
FETCH_USERS_REQUEST,
FETCH_USERS_SUCCESS,
FETCH_USERS_FAILURE,
SORT_UPDATE,
SET_ROLE,
SET_COMMENTER_STATUS,
@@ -15,7 +15,7 @@ const initialState = {
community: {},
isFetchingPeople: false,
errorPeople: '',
accounts: [],
users: [],
fieldPeople: 'created_at',
ascPeople: false,
totalPagesPeople: 0,
@@ -27,19 +27,19 @@ const initialState = {
export default function community (state = initialState, action) {
switch (action.type) {
case FETCH_COMMENTERS_REQUEST :
case FETCH_USERS_REQUEST :
return {
...state,
isFetchingPeople: true,
};
case FETCH_COMMENTERS_FAILURE :
case FETCH_USERS_FAILURE :
return {
...state,
isFetchingPeople: false,
errorPeople: action.error,
};
case FETCH_COMMENTERS_SUCCESS : {
const {accounts, type, page, count, limit, totalPages, ...rest} = action; // eslint-disable-line
case FETCH_USERS_SUCCESS : {
const {users, type, page, count, limit, totalPages, ...rest} = action; // eslint-disable-line
return {
...state,
isFetchingPeople: false,
@@ -49,27 +49,27 @@ export default function community (state = initialState, action) {
limitPeople: limit,
totalPagesPeople: totalPages,
...rest,
accounts, // Sets to normal array
users, // Sets to normal array
};
}
case SET_ROLE : {
const commenters = state.accounts;
const commenters = state.users;
const idx = commenters.findIndex((el) => el.id === action.id);
commenters[idx].roles[0] = action.role;
return {
...state,
accounts: commenters.map((id) => id),
users: commenters.map((id) => id),
};
}
case SET_COMMENTER_STATUS: {
const commenters = state.accounts;
const commenters = state.users;
const idx = commenters.findIndex((el) => el.id === action.id);
commenters[idx].status = action.status;
return {
...state,
accounts: commenters.map((id) => id),
users: commenters.map((id) => id),
};
}
@@ -0,0 +1,4 @@
.container {
max-width: 1280px;
margin: 0 auto;
}
@@ -1,78 +1,18 @@
import React, {Component} from 'react';
import CommunityMenu from './CommunityMenu';
import People from './People';
import FlaggedAccounts from '../containers/FlaggedAccounts';
import RejectUsernameDialog from './RejectUsernameDialog';
import PropTypes from 'prop-types';
import styles from './Community.css';
import People from '../containers/People';
import CommunityMenu from './CommunityMenu';
import RejectUsernameDialog from './RejectUsernameDialog';
import FlaggedAccounts from '../containers/FlaggedAccounts';
export default class Community extends Component {
state = {
searchValue: '',
timer: null
};
onKeyDownHandler = (e) => {
if (e.key === 'Enter') {
e.preventDefault();
this.search();
}
}
onSearchChange = (e) => {
const value = e.target.value;
this.setState((prevState) => {
prevState.searchValue = value;
clearTimeout(prevState.timer);
const fetchAccounts = this.props.fetchAccounts;
prevState.timer = setTimeout(() => {
fetchAccounts({value});
}, 350);
return prevState;
});
}
onHeaderClickHandler = (sort) => {
this.props.updateSorting(sort);
this.search();
}
onNewPageHandler = (page) => {
this.props.newPage(page);
this.search({page});
}
search(query = {}) {
const {community} = this.props;
this.props.fetchAccounts({
value: this.state.searchValue,
field: community.fieldPeople,
asc: community.ascPeople,
...query
});
}
getTabContent(searchValue, props) {
const {community} = props;
const activeTab = props.route.path === ':id' ? 'flagged' : props.route.path;
class Community extends Component {
renderTab() {
const {route, community, ...props} = this.props;
const activeTab = route.path === ':id' ? 'flagged' : route.path;
if (activeTab === 'people') {
return (
<People
isFetching={community.isFetchingPeople}
commenters={community.accounts}
searchValue={searchValue}
onSearchChange={this.onSearchChange}
error={community.errorPeople}
totalPages={community.totalPagesPeople}
page={community.pagePeople}
onKeyDown={this.onKeyDownHandler}
onHeaderClickHandler={this.onHeaderClickHandler}
onNewPageHandler={this.onNewPageHandler}
/>
);
return <People community={community} />;
}
return (
@@ -82,37 +22,34 @@ export default class Community extends Component {
root={this.props.root}
/>
<RejectUsernameDialog
open={community.rejectUsernameDialog}
handleClose={props.hideRejectUsernameDialog}
user={community.user}
open={community.rejectUsernameDialog}
rejectUsername={props.rejectUsername}
handleClose={props.hideRejectUsernameDialog}
/>
</div>
);
}
render() {
const {searchValue} = this.state;
const tab = this.getTabContent(searchValue, this.props);
const {root: {flaggedUsernamesCount}} = this.props;
return (
<div>
<CommunityMenu flaggedUsernamesCount={flaggedUsernamesCount} />
<div>{tab}</div>
<div className={styles.container}>
{this.renderTab()}
</div>
</div>
);
}
}
Community.propTypes = {
community: PropTypes.object,
fetchAccounts: PropTypes.func,
hideRejectUsernameDialog: PropTypes.func,
updateSorting: PropTypes.func,
newPage: PropTypes.func,
route: PropTypes.object,
rejectUsername: PropTypes.func,
community: PropTypes.object,
data: PropTypes.object,
root: PropTypes.object
root: PropTypes.object,
};
export default Community;
@@ -1,33 +1,24 @@
import React from 'react';
import styles from './styles.css';
import Table from '../containers/Table';
import {Pager, Icon} from 'coral-ui';
import Table from './Table';
import {Paginate, Icon} from 'coral-ui';
import EmptyCard from '../../../components/EmptyCard';
import t from 'coral-framework/services/i18n';
import PropTypes from 'prop-types';
const tableHeaders = [
{
title: t('community.username_and_email'),
field: 'username'
},
{
title: t('community.account_creation_date'),
field: 'created_at'
},
{
title: t('community.status'),
field: 'status'
},
{
title: t('community.newsroom_role'),
field: 'role'
}
];
const People = (props) => {
const {
users = [],
searchValue,
onSearchChange,
onHeaderClickHandler,
onNewPageHandler,
totalPages,
} = props;
const hasResults = !!users.length;
const People = ({commenters, searchValue, onSearchChange, ...props}) => {
const hasResults = !!commenters.length;
return (
<div className={styles.container}>
<div className={styles.leftColumn}>
@@ -47,16 +38,15 @@ const People = ({commenters, searchValue, onSearchChange, ...props}) => {
{
hasResults
? <Table
headers={tableHeaders}
commenters={commenters}
onHeaderClickHandler={props.onHeaderClickHandler}
users={users}
onHeaderClickHandler={onHeaderClickHandler}
/>
: <EmptyCard>{t('community.no_results')}</EmptyCard>
}
<Pager
totalPages={props.totalPages}
page={props.page}
onNewPageHandler={props.onNewPageHandler}
<Paginate
pageCount={totalPages}
onPageChange={onNewPageHandler}
/>
</div>
</div>
@@ -64,7 +54,8 @@ const People = ({commenters, searchValue, onSearchChange, ...props}) => {
};
People.propTypes = {
commenters: PropTypes.array,
onHeaderClickHandler: PropTypes.func,
users: PropTypes.array,
searchValue: PropTypes.string,
onSearchChange: PropTypes.func,
totalPages: PropTypes.number,
@@ -5,7 +5,26 @@ import PropTypes from 'prop-types';
import {Dropdown, Option} from 'coral-ui';
import cn from 'classnames';
const Table = ({headers, commenters, onHeaderClickHandler, onRoleChange, onCommenterStatusChange, viewUserDetail}) => (
const headers = [
{
title: t('community.username_and_email'),
field: 'username'
},
{
title: t('community.account_creation_date'),
field: 'created_at'
},
{
title: t('community.status'),
field: 'status'
},
{
title: t('community.newsroom_role'),
field: 'role'
}
];
const Table = ({users, onHeaderClickHandler, onRoleChange, onCommenterStatusChange, viewUserDetail}) => (
<table className={`mdl-data-table ${styles.dataTable}`}>
<thead>
<tr>
@@ -21,7 +40,7 @@ const Table = ({headers, commenters, onHeaderClickHandler, onRoleChange, onComme
</tr>
</thead>
<tbody>
{commenters.map((row, i)=> (
{users.map((row, i)=> (
<tr key={i}>
<td className="mdl-data-table__cell--non-numeric">
<button onClick={() => {viewUserDetail(row.id);}} className={cn(styles.username, styles.button)}>{row.username}</button>
@@ -57,9 +76,8 @@ const Table = ({headers, commenters, onHeaderClickHandler, onRoleChange, onComme
);
Table.propTypes = {
headers: PropTypes.array,
commenters: PropTypes.array,
onHeaderClickHandler: PropTypes.func,
users: PropTypes.array,
onHeaderClickHandler: PropTypes.func.isRequired,
onRoleChange: PropTypes.func,
onCommenterStatusChange: PropTypes.func,
viewUserDetail: PropTypes.func,
@@ -1,65 +1,21 @@
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import PropTypes from 'prop-types';
import {compose, gql} from 'react-apollo';
import withQuery from 'coral-framework/hocs/withQuery';
import {getDefinitionName} from 'coral-framework/utils';
import {withSetUserStatus, withRejectUsername} from 'coral-framework/graphql/mutations';
import FlaggedAccounts from '../containers/FlaggedAccounts';
import FlaggedUser from '../containers/FlaggedUser';
import {
fetchAccounts,
updateSorting,
newPage,
hideRejectUsernameDialog
} from '../../../actions/community';
import {hideRejectUsernameDialog} from '../../../actions/community';
import Community from '../components/Community';
class CommunityContainer extends Component {
componentWillMount() {
this.props.fetchAccounts({});
}
render() {
return <Community
fetchAccounts={this.props.fetchAccounts}
community={this.props.community}
hideRejectUsernameDialog={this.props.hideRejectUsernameDialog}
updateSorting={this.props.updateSorting}
newPage={this.props.newPage}
route={this.props.route}
rejectUsername={this.props.rejectUsername}
data={this.props.data}
root={this.props.root}
/>;
}
}
const mapStateToProps = (state) => ({
community: state.community,
});
CommunityContainer.propTypes = {
community: PropTypes.object,
fetchAccounts: PropTypes.func,
hideRejectUsernameDialog: PropTypes.func,
updateSorting: PropTypes.func,
newPage: PropTypes.func,
route: PropTypes.object,
rejectUsername: PropTypes.func,
data: PropTypes.object,
root: PropTypes.object
};
const mapDispatchToProps = (dispatch) =>
bindActionCreators({
fetchAccounts,
hideRejectUsernameDialog,
updateSorting,
newPage,
}, dispatch);
const withData = withQuery(gql`
@@ -89,4 +45,4 @@ export default compose(
withSetUserStatus,
withRejectUsername,
withData
)(CommunityContainer);
)(Community);
@@ -0,0 +1,102 @@
import React from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import People from '../components/People';
import PropTypes from 'prop-types';
import {viewUserDetail} from '../../../actions/userDetail';
import {
fetchUsers,
updateSorting,
newPage,
hideRejectUsernameDialog,
setCommenterStatus,
setRole,
} from '../../../actions/community';
class PeopleContainer extends React.Component {
state = {
searchValue: '',
timer: null
};
componentWillMount() {
this.props.fetchUsers();
}
onKeyDownHandler = (e) => {
if (e.key === 'Enter') {
e.preventDefault();
this.search();
}
}
onSearchChange = (e) => {
const value = e.target.value;
this.setState((prevState) => {
prevState.searchValue = value;
clearTimeout(prevState.timer);
const fetchAccounts = this.props.fetchUsers;
prevState.timer = setTimeout(() => {
fetchAccounts({value});
}, 350);
return prevState;
});
}
onHeaderClickHandler = (sort) => {
this.props.updateSorting(sort);
this.search();
}
onNewPageHandler = ({selected}) => {
const page = selected + 1;
this.props.newPage(page);
this.search({page});
}
search(query = {}) {
const {community} = this.props;
this.props.fetchUsers({
value: this.state.searchValue,
field: community.fieldPeople,
asc: community.ascPeople,
...query
});
}
render() {
return <People
users={this.props.community.users}
searchValue={this.state.searchValue}
onSearchChange={this.onSearchChange}
onHeaderClickHandler={this.onHeaderClickHandler}
onNewPageHandler={this.onNewPageHandler}
totalPages={this.props.community.totalPagesPeople}
/>;
}
}
PeopleContainer.propTypes = {
newPage: PropTypes.func,
fetchUsers: PropTypes.func,
updateSorting: PropTypes.func,
setRole: PropTypes.func,
setCommenterStatus: PropTypes.func,
community: PropTypes.object,
};
const mapDispatchToProps = (dispatch) =>
bindActionCreators({
newPage,
fetchUsers,
updateSorting,
hideRejectUsernameDialog,
setCommenterStatus,
setRole,
viewUserDetail,
}, dispatch);
export default connect(null, mapDispatchToProps)(PeopleContainer);
@@ -1,43 +0,0 @@
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import {setRole, setCommenterStatus} from '../../../actions/community';
import Table from '../components/Table';
import {viewUserDetail} from '../../../actions/userDetail';
import PropTypes from 'prop-types';
class TableContainer extends Component {
constructor (props) {
super(props);
}
render () {
return <Table
{...this.props}
onRoleChange={this.props.setRole}
onCommenterStatusChange={this.props.setCommenterStatus}
commenters={this.props.commenters}
/>;
}
}
TableContainer.propTypes = {
setRole: PropTypes.func,
setCommenterStatus: PropTypes.func,
commenters: PropTypes.array,
};
const mapStateToProps = (state) => ({
commenters: state.community.accounts,
});
const mapDispatchToProps = (dispatch) =>
bindActionCreators({
setCommenterStatus,
setRole,
viewUserDetail,
}, dispatch);
export default connect(mapStateToProps, mapDispatchToProps)(TableContainer);
@@ -2,7 +2,7 @@ import React, {Component} from 'react';
import {Link} from 'react-router';
import PropTypes from 'prop-types';
import sortBy from 'lodash/sortBy';
import {Dropdown, Option, Pager, Icon} from 'coral-ui';
import {Dropdown, Option, Paginate, Icon} from 'coral-ui';
import {DataTable, TableHeader, RadioGroup, Radio} from 'react-mdl';
import t from 'coral-framework/services/i18n';
import styles from './Stories.css';
@@ -139,10 +139,10 @@ class Stories extends Component {
{t('streams.status')}
</TableHeader>
</DataTable>
<Pager
{/* <Paginate
totalPages={Math.ceil((assets.count || 0) / limit)}
page={this.state.page}
onNewPageHandler={this.onPageClick} />
onNewPageHandler={this.onPageClick} /> */}
</div>
: <EmptyCard>{t('streams.empty_result')}</EmptyCard>
}