Admin: make awaiting approval actions work
This commit is contained in:
parent
1ad3ea4437
commit
a3f208c1be
4 changed files with 130 additions and 9 deletions
|
@ -12,6 +12,14 @@ export const ADMIN_USERS_FETCH_REQUEST = 'ADMIN_USERS_FETCH_REQUEST';
|
|||
export const ADMIN_USERS_FETCH_SUCCESS = 'ADMIN_USERS_FETCH_SUCCESS';
|
||||
export const ADMIN_USERS_FETCH_FAIL = 'ADMIN_USERS_FETCH_FAIL';
|
||||
|
||||
export const ADMIN_USERS_DELETE_REQUEST = 'ADMIN_USERS_DELETE_REQUEST';
|
||||
export const ADMIN_USERS_DELETE_SUCCESS = 'ADMIN_USERS_DELETE_SUCCESS';
|
||||
export const ADMIN_USERS_DELETE_FAIL = 'ADMIN_USERS_DELETE_FAIL';
|
||||
|
||||
export const ADMIN_USERS_APPROVE_REQUEST = 'ADMIN_USERS_APPROVE_REQUEST';
|
||||
export const ADMIN_USERS_APPROVE_SUCCESS = 'ADMIN_USERS_APPROVE_SUCCESS';
|
||||
export const ADMIN_USERS_APPROVE_FAIL = 'ADMIN_USERS_APPROVE_FAIL';
|
||||
|
||||
export function updateAdminConfig(params) {
|
||||
return (dispatch, getState) => {
|
||||
dispatch({ type: ADMIN_CONFIG_UPDATE_REQUEST });
|
||||
|
@ -50,3 +58,29 @@ export function fetchUsers(params) {
|
|||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function deleteUsers(nicknames) {
|
||||
return (dispatch, getState) => {
|
||||
dispatch({ type: ADMIN_USERS_DELETE_REQUEST, nicknames });
|
||||
return api(getState)
|
||||
.delete('/api/pleroma/admin/users', { data: { nicknames } })
|
||||
.then(({ data: nicknames }) => {
|
||||
dispatch({ type: ADMIN_USERS_DELETE_SUCCESS, nicknames });
|
||||
}).catch(error => {
|
||||
dispatch({ type: ADMIN_USERS_DELETE_FAIL, error, nicknames });
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function approveUsers(nicknames) {
|
||||
return (dispatch, getState) => {
|
||||
dispatch({ type: ADMIN_USERS_APPROVE_REQUEST, nicknames });
|
||||
return api(getState)
|
||||
.patch('/api/pleroma/admin/users/approve', { nicknames })
|
||||
.then(({ data: { users } }) => {
|
||||
dispatch({ type: ADMIN_USERS_APPROVE_SUCCESS, users, nicknames });
|
||||
}).catch(error => {
|
||||
dispatch({ type: ADMIN_USERS_APPROVE_FAIL, error, nicknames });
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -5,16 +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 { fetchUsers } from 'soapbox/actions/admin';
|
||||
import IconButton from 'soapbox/components/icon_button';
|
||||
import ScrollableList from 'soapbox/components/scrollable_list';
|
||||
import { fetchUsers, deleteUsers, approveUsers } from 'soapbox/actions/admin';
|
||||
|
||||
const messages = defineMessages({
|
||||
heading: { id: 'column.admin.awaiting_approval', defaultMessage: 'Awaiting Approval' },
|
||||
});
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const userIds = state.getIn(['admin', 'awaitingApproval']);
|
||||
const nicknames = state.getIn(['admin', 'awaitingApproval']);
|
||||
return {
|
||||
users: userIds.map(id => state.getIn(['admin', 'users', id])),
|
||||
users: nicknames.toList().map(nickname => state.getIn(['admin', 'users', nickname])),
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -27,18 +29,52 @@ class AwaitingApproval extends ImmutablePureComponent {
|
|||
users: ImmutablePropTypes.list.isRequired,
|
||||
};
|
||||
|
||||
state = {
|
||||
isLoading: true,
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.props.dispatch(fetchUsers({ page: 1, filters: 'local,need_approval' }));
|
||||
const { dispatch } = this.props;
|
||||
const params = { page: 1, filters: 'local,need_approval' };
|
||||
dispatch(fetchUsers(params))
|
||||
.then(() => this.setState({ isLoading: false }))
|
||||
.catch(() => {});
|
||||
}
|
||||
|
||||
handleApprove = nickname => {
|
||||
const { dispatch } = this.props;
|
||||
return e => {
|
||||
dispatch(approveUsers([nickname]));
|
||||
};
|
||||
}
|
||||
|
||||
handleReject = nickname => {
|
||||
const { dispatch } = this.props;
|
||||
return e => {
|
||||
dispatch(deleteUsers([nickname]));
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
const { intl, users } = this.props;
|
||||
const { isLoading } = this.state;
|
||||
|
||||
return (
|
||||
<Column icon='user' heading={intl.formatMessage(messages.heading)} backBtnSlim>
|
||||
{users.map((user, i) => (
|
||||
<div key={i}>{user.get('nickname')}</div>
|
||||
))}
|
||||
<ScrollableList isLoading={isLoading} showLoading={isLoading} scrollKey='awaiting-approval'>
|
||||
{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='unapproved-account__reason'>{user.get('registration_reason')}</blockquote>
|
||||
</div>
|
||||
<div className='unapproved-account__actions'>
|
||||
<IconButton icon='check' onClick={this.handleApprove(user.get('nickname'))} />
|
||||
<IconButton icon='close' onClick={this.handleReject(user.get('nickname'))} />
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</ScrollableList>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import {
|
||||
ADMIN_REPORTS_FETCH_SUCCESS,
|
||||
ADMIN_USERS_FETCH_SUCCESS,
|
||||
ADMIN_USERS_DELETE_SUCCESS,
|
||||
ADMIN_USERS_APPROVE_SUCCESS,
|
||||
} from '../actions/admin';
|
||||
import {
|
||||
Map as ImmutableMap,
|
||||
|
@ -20,9 +22,27 @@ function importUsers(state, users) {
|
|||
return state.withMutations(state => {
|
||||
users.forEach(user => {
|
||||
if (user.approval_pending) {
|
||||
state.update('awaitingApproval', orderedSet => orderedSet.add(user.id));
|
||||
state.update('awaitingApproval', orderedSet => orderedSet.add(user.nickname));
|
||||
}
|
||||
state.setIn(['users', user.id], fromJS(user));
|
||||
state.setIn(['users', user.nickname], fromJS(user));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function deleteUsers(state, nicknames) {
|
||||
return state.withMutations(state => {
|
||||
nicknames.forEach(nickname => {
|
||||
state.update('awaitingApproval', orderedSet => orderedSet.delete(nickname));
|
||||
state.deleteIn(['users', nickname]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function approveUsers(state, users) {
|
||||
return state.withMutations(state => {
|
||||
users.forEach(user => {
|
||||
state.update('awaitingApproval', orderedSet => orderedSet.delete(user.nickname));
|
||||
state.setIn(['users', user.nickname], fromJS(user));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -39,6 +59,10 @@ export default function admin(state = initialState, action) {
|
|||
}
|
||||
case ADMIN_USERS_FETCH_SUCCESS:
|
||||
return importUsers(state, action.data.users);
|
||||
case ADMIN_USERS_DELETE_SUCCESS:
|
||||
return deleteUsers(state, action.nicknames);
|
||||
case ADMIN_USERS_APPROVE_SUCCESS:
|
||||
return approveUsers(state, action.users);
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
|
|
@ -67,3 +67,30 @@
|
|||
border-bottom: 1px solid var(--accent-color--med);
|
||||
}
|
||||
}
|
||||
|
||||
.unapproved-account {
|
||||
padding: 15px 20px;
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
|
||||
&__nickname {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
&__reason {
|
||||
padding: 5px 0 5px 15px;
|
||||
border-left: 3px solid hsla(var(--primary-text-color_hsl), 0.4);
|
||||
color: var(--primary-text-color--faint);
|
||||
}
|
||||
|
||||
&__actions {
|
||||
margin-left: auto;
|
||||
padding-left: 20px;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.slist .item-list article:nth-child(2n-1) .unapproved-account {
|
||||
background-color: hsla(var(--accent-color_hsl), 0.07);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue