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_SUCCESS = 'ADMIN_USERS_FETCH_SUCCESS';
|
||||||
export const ADMIN_USERS_FETCH_FAIL = 'ADMIN_USERS_FETCH_FAIL';
|
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) {
|
export function updateAdminConfig(params) {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
dispatch({ type: ADMIN_CONFIG_UPDATE_REQUEST });
|
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 PropTypes from 'prop-types';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import Column from '../ui/components/column';
|
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({
|
const messages = defineMessages({
|
||||||
heading: { id: 'column.admin.awaiting_approval', defaultMessage: 'Awaiting Approval' },
|
heading: { id: 'column.admin.awaiting_approval', defaultMessage: 'Awaiting Approval' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
const mapStateToProps = state => {
|
||||||
const userIds = state.getIn(['admin', 'awaitingApproval']);
|
const nicknames = state.getIn(['admin', 'awaitingApproval']);
|
||||||
return {
|
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,
|
users: ImmutablePropTypes.list.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
state = {
|
||||||
|
isLoading: true,
|
||||||
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
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() {
|
render() {
|
||||||
const { intl, users } = this.props;
|
const { intl, users } = this.props;
|
||||||
|
const { isLoading } = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column icon='user' heading={intl.formatMessage(messages.heading)} backBtnSlim>
|
<Column icon='user' heading={intl.formatMessage(messages.heading)} backBtnSlim>
|
||||||
{users.map((user, i) => (
|
<ScrollableList isLoading={isLoading} showLoading={isLoading} scrollKey='awaiting-approval'>
|
||||||
<div key={i}>{user.get('nickname')}</div>
|
{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>
|
</Column>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import {
|
import {
|
||||||
ADMIN_REPORTS_FETCH_SUCCESS,
|
ADMIN_REPORTS_FETCH_SUCCESS,
|
||||||
ADMIN_USERS_FETCH_SUCCESS,
|
ADMIN_USERS_FETCH_SUCCESS,
|
||||||
|
ADMIN_USERS_DELETE_SUCCESS,
|
||||||
|
ADMIN_USERS_APPROVE_SUCCESS,
|
||||||
} from '../actions/admin';
|
} from '../actions/admin';
|
||||||
import {
|
import {
|
||||||
Map as ImmutableMap,
|
Map as ImmutableMap,
|
||||||
|
@ -20,9 +22,27 @@ function importUsers(state, users) {
|
||||||
return state.withMutations(state => {
|
return state.withMutations(state => {
|
||||||
users.forEach(user => {
|
users.forEach(user => {
|
||||||
if (user.approval_pending) {
|
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:
|
case ADMIN_USERS_FETCH_SUCCESS:
|
||||||
return importUsers(state, action.data.users);
|
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:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,3 +67,30 @@
|
||||||
border-bottom: 1px solid var(--accent-color--med);
|
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