sforkowany z mirror/soapbox
Refactor AwaitingApproval
rodzic
732fba73f5
commit
a89ea524a9
|
@ -5,24 +5,18 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
|
|||
import PropTypes from 'prop-types';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import Column from '../ui/components/column';
|
||||
import IconButton from 'soapbox/components/icon_button';
|
||||
import ScrollableList from 'soapbox/components/scrollable_list';
|
||||
import { fetchUsers, deleteUsers, approveUsers } from 'soapbox/actions/admin';
|
||||
import snackbar from 'soapbox/actions/snackbar';
|
||||
import UnapprovedAccount from './components/unapproved_account';
|
||||
import { fetchUsers } from 'soapbox/actions/admin';
|
||||
|
||||
const messages = defineMessages({
|
||||
heading: { id: 'column.admin.awaiting_approval', defaultMessage: 'Awaiting Approval' },
|
||||
emptyMessage: { id: 'admin.awaiting_approval.empty_message', defaultMessage: 'There is nobody waiting for approval. When a new user signs up, you can review them here.' },
|
||||
approved: { id: 'admin.awaiting_approval.approved_message', defaultMessage: '{acct} was approved!' },
|
||||
rejected: { id: 'admin.awaiting_approval.rejected_message', defaultMessage: '{acct} was rejected.' },
|
||||
});
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const nicknames = state.getIn(['admin', 'awaitingApproval']);
|
||||
return {
|
||||
users: nicknames.toList().map(nickname => state.getIn(['admin', 'users', nickname])),
|
||||
};
|
||||
};
|
||||
const mapStateToProps = state => ({
|
||||
accountIds: state.getIn(['admin', 'awaitingApproval']),
|
||||
});
|
||||
|
||||
export default @connect(mapStateToProps)
|
||||
@injectIntl
|
||||
|
@ -30,7 +24,7 @@ class AwaitingApproval extends ImmutablePureComponent {
|
|||
|
||||
static propTypes = {
|
||||
intl: PropTypes.object.isRequired,
|
||||
users: ImmutablePropTypes.list.isRequired,
|
||||
accountIds: ImmutablePropTypes.orderedSet.isRequired,
|
||||
};
|
||||
|
||||
state = {
|
||||
|
@ -44,45 +38,21 @@ class AwaitingApproval extends ImmutablePureComponent {
|
|||
.catch(() => {});
|
||||
}
|
||||
|
||||
handleApprove = nickname => {
|
||||
const { dispatch, intl } = this.props;
|
||||
return e => {
|
||||
dispatch(approveUsers([nickname])).then(() => {
|
||||
const message = intl.formatMessage(messages.approved, { acct: `@${nickname}` });
|
||||
dispatch(snackbar.success(message));
|
||||
}).catch(() => {});
|
||||
};
|
||||
}
|
||||
|
||||
handleReject = nickname => {
|
||||
const { dispatch, intl } = this.props;
|
||||
return e => {
|
||||
dispatch(deleteUsers([nickname])).then(() => {
|
||||
const message = intl.formatMessage(messages.rejected, { acct: `@${nickname}` });
|
||||
dispatch(snackbar.info(message));
|
||||
}).catch(() => {});
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
const { intl, users } = this.props;
|
||||
const { intl, accountIds } = this.props;
|
||||
const { isLoading } = this.state;
|
||||
const showLoading = isLoading && users.count() === 0;
|
||||
const showLoading = isLoading && accountIds.count() === 0;
|
||||
|
||||
return (
|
||||
<Column icon='user' heading={intl.formatMessage(messages.heading)} backBtnSlim>
|
||||
<ScrollableList isLoading={isLoading} showLoading={showLoading} scrollKey='awaiting-approval' emptyMessage={intl.formatMessage(messages.emptyMessage)}>
|
||||
{users.map((user, i) => (
|
||||
<div className='unapproved-account' key={user.get('id')}>
|
||||
<div className='unapproved-account__bio'>
|
||||
<div className='unapproved-account__nickname'>@{user.get('nickname')}</div>
|
||||
<blockquote className='md'>{user.get('registration_reason')}</blockquote>
|
||||
</div>
|
||||
<div className='unapproved-account__actions'>
|
||||
<IconButton icon='check' size={22} onClick={this.handleApprove(user.get('nickname'))} />
|
||||
<IconButton icon='close' size={22} onClick={this.handleReject(user.get('nickname'))} />
|
||||
</div>
|
||||
</div>
|
||||
<ScrollableList
|
||||
isLoading={isLoading}
|
||||
showLoading={showLoading}
|
||||
scrollKey='awaiting-approval'
|
||||
emptyMessage={intl.formatMessage(messages.emptyMessage)}
|
||||
>
|
||||
{accountIds.map(id => (
|
||||
<UnapprovedAccount accountId={id} key={id} />
|
||||
))}
|
||||
</ScrollableList>
|
||||
</Column>
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
import React from 'react';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import { connect } from 'react-redux';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import PropTypes from 'prop-types';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import IconButton from 'soapbox/components/icon_button';
|
||||
import { deleteUsers, approveUsers } from 'soapbox/actions/admin';
|
||||
import { makeGetAccount } from 'soapbox/selectors';
|
||||
import snackbar from 'soapbox/actions/snackbar';
|
||||
|
||||
const messages = defineMessages({
|
||||
approved: { id: 'admin.awaiting_approval.approved_message', defaultMessage: '{acct} was approved!' },
|
||||
rejected: { id: 'admin.awaiting_approval.rejected_message', defaultMessage: '{acct} was rejected.' },
|
||||
});
|
||||
|
||||
const makeMapStateToProps = () => {
|
||||
const getAccount = makeGetAccount();
|
||||
|
||||
const mapStateToProps = (state, { accountId }) => {
|
||||
return {
|
||||
account: getAccount(state, accountId),
|
||||
};
|
||||
};
|
||||
|
||||
return mapStateToProps;
|
||||
};
|
||||
|
||||
export default @connect(makeMapStateToProps)
|
||||
@injectIntl
|
||||
class UnapprovedAccount extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
intl: PropTypes.object.isRequired,
|
||||
account: ImmutablePropTypes.map.isRequired,
|
||||
};
|
||||
|
||||
handleApprove = () => {
|
||||
const { dispatch, intl, account } = this.props;
|
||||
|
||||
dispatch(approveUsers([account.get('id')]))
|
||||
.then(() => {
|
||||
const message = intl.formatMessage(messages.approved, { acct: `@${account.get('acct')}` });
|
||||
dispatch(snackbar.success(message));
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
|
||||
handleReject = () => {
|
||||
const { dispatch, intl, account } = this.props;
|
||||
|
||||
dispatch(deleteUsers([account.get('id')]))
|
||||
.then(() => {
|
||||
const message = intl.formatMessage(messages.rejected, { acct: `@${account.get('acct')}` });
|
||||
dispatch(snackbar.info(message));
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { account } = this.props;
|
||||
|
||||
return (
|
||||
<div className='unapproved-account'>
|
||||
<div className='unapproved-account__bio'>
|
||||
<div className='unapproved-account__nickname'>@{account.get('acct')}</div>
|
||||
<blockquote className='md'>{account.getIn(['pleroma', 'admin', 'registration_reason'])}</blockquote>
|
||||
</div>
|
||||
<div className='unapproved-account__actions'>
|
||||
<IconButton icon='check' size={22} onClick={this.handleApprove} />
|
||||
<IconButton icon='close' size={22} onClick={this.handleReject} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -33,8 +33,8 @@ class UserIndex extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
fetchNextPage = () => {
|
||||
const nextPage = this.state.page + 1;
|
||||
const filters = this.state.filters.toJS();
|
||||
const { filters, page } = this.state;
|
||||
const nextPage = page + 1;
|
||||
|
||||
this.props.dispatch(fetchUsers(filters, nextPage))
|
||||
.then(({ users, count }) => {
|
||||
|
|
|
@ -31,9 +31,12 @@ function importUsers(state, users) {
|
|||
users.forEach(user => {
|
||||
user = normalizePleromaUserFields(user);
|
||||
if (!user.is_approved) {
|
||||
state.update('awaitingApproval', orderedSet => orderedSet.add(user.nickname));
|
||||
state.update('awaitingApproval', orderedSet => orderedSet.add(user.id));
|
||||
}
|
||||
state.setIn(['users', user.nickname], fromJS(user));
|
||||
state.setIn(['users', user.id], ImmutableMap({
|
||||
email: user.email,
|
||||
registration_reason: user.registration_reason,
|
||||
}));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ const getAccountBase = (state, id) => state.getIn(['accounts', id], null
|
|||
const getAccountCounters = (state, id) => state.getIn(['accounts_counters', id], null);
|
||||
const getAccountRelationship = (state, id) => state.getIn(['relationships', id], null);
|
||||
const getAccountMoved = (state, id) => state.getIn(['accounts', state.getIn(['accounts', id, 'moved'])]);
|
||||
const getAccountAdminData = (state, id) => state.getIn(['admin', 'users', id]);
|
||||
const getAccountPatron = (state, id) => {
|
||||
const url = state.getIn(['accounts', id, 'url']);
|
||||
return state.getIn(['patron', 'accounts', url]);
|
||||
|
@ -16,8 +17,9 @@ export const makeGetAccount = () => {
|
|||
getAccountCounters,
|
||||
getAccountRelationship,
|
||||
getAccountMoved,
|
||||
getAccountAdminData,
|
||||
getAccountPatron,
|
||||
], (base, counters, relationship, moved, patron) => {
|
||||
], (base, counters, relationship, moved, admin, patron) => {
|
||||
if (base === null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -26,6 +28,7 @@ export const makeGetAccount = () => {
|
|||
map.set('relationship', relationship);
|
||||
map.set('moved', moved);
|
||||
map.set('patron', patron);
|
||||
map.setIn(['pleroma', 'admin'], admin);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
Ładowanie…
Reference in New Issue