Refactor AwaitingApproval

remove-account-counters-reducer
Alex Gleason 2021-07-13 17:59:55 -05:00
rodzic 732fba73f5
commit a89ea524a9
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 7211D1F99744FBB7
5 zmienionych plików z 104 dodań i 51 usunięć

Wyświetl plik

@ -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>

Wyświetl plik

@ -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>
);
}
}

Wyświetl plik

@ -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 }) => {

Wyświetl plik

@ -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,
}));
});
});
}

Wyświetl plik

@ -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);
});
});
};