Replacing follow requests in the settings area with in-UI column
This commit is contained in:
		@@ -51,6 +51,22 @@ export const RELATIONSHIPS_FETCH_REQUEST = 'RELATIONSHIPS_FETCH_REQUEST';
 | 
			
		||||
export const RELATIONSHIPS_FETCH_SUCCESS = 'RELATIONSHIPS_FETCH_SUCCESS';
 | 
			
		||||
export const RELATIONSHIPS_FETCH_FAIL    = 'RELATIONSHIPS_FETCH_FAIL';
 | 
			
		||||
 | 
			
		||||
export const FOLLOW_REQUESTS_FETCH_REQUEST = 'FOLLOW_REQUESTS_FETCH_REQUEST';
 | 
			
		||||
export const FOLLOW_REQUESTS_FETCH_SUCCESS = 'FOLLOW_REQUESTS_FETCH_SUCCESS';
 | 
			
		||||
export const FOLLOW_REQUESTS_FETCH_FAIL    = 'FOLLOW_REQUESTS_FETCH_FAIL';
 | 
			
		||||
 | 
			
		||||
export const FOLLOW_REQUESTS_EXPAND_REQUEST = 'FOLLOW_REQUESTS_EXPAND_REQUEST';
 | 
			
		||||
export const FOLLOW_REQUESTS_EXPAND_SUCCESS = 'FOLLOW_REQUESTS_EXPAND_SUCCESS';
 | 
			
		||||
export const FOLLOW_REQUESTS_EXPAND_FAIL    = 'FOLLOW_REQUESTS_EXPAND_FAIL';
 | 
			
		||||
 | 
			
		||||
export const FOLLOW_REQUEST_AUTHORIZE_REQUEST = 'FOLLOW_REQUEST_AUTHORIZE_REQUEST';
 | 
			
		||||
export const FOLLOW_REQUEST_AUTHORIZE_SUCCESS = 'FOLLOW_REQUEST_AUTHORIZE_SUCCESS';
 | 
			
		||||
export const FOLLOW_REQUEST_AUTHORIZE_FAIL    = 'FOLLOW_REQUEST_AUTHORIZE_FAIL';
 | 
			
		||||
 | 
			
		||||
export const FOLLOW_REQUEST_REJECT_REQUEST = 'FOLLOW_REQUEST_REJECT_REQUEST';
 | 
			
		||||
export const FOLLOW_REQUEST_REJECT_SUCCESS = 'FOLLOW_REQUEST_REJECT_SUCCESS';
 | 
			
		||||
export const FOLLOW_REQUEST_REJECT_FAIL    = 'FOLLOW_REQUEST_REJECT_FAIL';
 | 
			
		||||
 | 
			
		||||
export function setAccountSelf(account) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: ACCOUNT_SET_SELF,
 | 
			
		||||
@@ -509,3 +525,140 @@ export function fetchRelationshipsFail(error) {
 | 
			
		||||
    error
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function fetchFollowRequests() {
 | 
			
		||||
  return (dispatch, getState) => {
 | 
			
		||||
    dispatch(fetchFollowRequestsRequest());
 | 
			
		||||
 | 
			
		||||
    api(getState).get('/api/v1/follow_requests').then(response => {
 | 
			
		||||
      const next = getLinks(response).refs.find(link => link.rel === 'next');
 | 
			
		||||
      dispatch(fetchFollowRequestsSuccess(response.data, next ? next.uri : null))
 | 
			
		||||
    }).catch(error => dispatch(fetchFollowRequestsFail(error)));
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function fetchFollowRequestsRequest() {
 | 
			
		||||
  return {
 | 
			
		||||
    type: FOLLOW_REQUESTS_FETCH_REQUEST
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function fetchFollowRequestsSuccess(accounts, next) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: FOLLOW_REQUESTS_FETCH_SUCCESS,
 | 
			
		||||
    accounts,
 | 
			
		||||
    next
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function fetchFollowRequestsFail(error) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: FOLLOW_REQUESTS_FETCH_FAIL,
 | 
			
		||||
    error
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function expandFollowRequests() {
 | 
			
		||||
  return (dispatch, getState) => {
 | 
			
		||||
    const url = getState().getIn(['user_lists', 'follow_requests', 'next']);
 | 
			
		||||
 | 
			
		||||
    if (url === null) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    dispatch(expandFollowRequestsRequest());
 | 
			
		||||
 | 
			
		||||
    api(getState).get(url).then(response => {
 | 
			
		||||
      const next = getLinks(response).refs.find(link => link.rel === 'next');
 | 
			
		||||
      dispatch(expandFollowRequestsSuccess(response.data, next ? next.uri : null))
 | 
			
		||||
    }).catch(error => dispatch(expandFollowRequestsFail(error)));
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function expandFollowRequestsRequest() {
 | 
			
		||||
  return {
 | 
			
		||||
    type: FOLLOW_REQUESTS_EXPAND_REQUEST
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function expandFollowRequestsSuccess(accounts, next) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: FOLLOW_REQUESTS_EXPAND_SUCCESS,
 | 
			
		||||
    accounts,
 | 
			
		||||
    next
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function expandFollowRequestsFail(error) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: FOLLOW_REQUESTS_EXPAND_FAIL,
 | 
			
		||||
    error
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function authorizeFollowRequest(id) {
 | 
			
		||||
  return (dispatch, getState) => {
 | 
			
		||||
    dispatch(authorizeFollowRequestRequest(id));
 | 
			
		||||
 | 
			
		||||
    api(getState)
 | 
			
		||||
      .post(`/api/v1/follow_requests/${id}/authorize`)
 | 
			
		||||
      .then(response => dispatch(authorizeFollowRequestSuccess(id)))
 | 
			
		||||
      .catch(error => dispatch(authorizeFollowRequestFail(id, error)));
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function authorizeFollowRequestRequest(id) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: FOLLOW_REQUEST_AUTHORIZE_REQUEST,
 | 
			
		||||
    id
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function authorizeFollowRequestSuccess(id) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: FOLLOW_REQUEST_AUTHORIZE_SUCCESS,
 | 
			
		||||
    id
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function authorizeFollowRequestFail(id, error) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: FOLLOW_REQUEST_AUTHORIZE_FAIL,
 | 
			
		||||
    id,
 | 
			
		||||
    error
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
export function rejectFollowRequest(id) {
 | 
			
		||||
  return (dispatch, getState) => {
 | 
			
		||||
    dispatch(rejectFollowRequestRequest(id));
 | 
			
		||||
 | 
			
		||||
    api(getState)
 | 
			
		||||
      .post(`/api/v1/follow_requests/${id}/reject`)
 | 
			
		||||
      .then(response => dispatch(rejectFollowRequestSuccess(id)))
 | 
			
		||||
      .catch(error => dispatch(rejectFollowRequestFail(id, error)));
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function rejectFollowRequestRequest(id) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: FOLLOW_REQUEST_REJECT_REQUEST,
 | 
			
		||||
    id
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function rejectFollowRequestSuccess(id) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: FOLLOW_REQUEST_REJECT_SUCCESS,
 | 
			
		||||
    id
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function rejectFollowRequestFail(id, error) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: FOLLOW_REQUEST_REJECT_FAIL,
 | 
			
		||||
    id,
 | 
			
		||||
    error
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -27,11 +27,11 @@ const StatusList = React.createClass({
 | 
			
		||||
 | 
			
		||||
    this._oldScrollPosition = scrollHeight - scrollTop;
 | 
			
		||||
 | 
			
		||||
    if (scrollTop === scrollHeight - clientHeight) {
 | 
			
		||||
    if (scrollTop === scrollHeight - clientHeight && this.props.onScrollToBottom) {
 | 
			
		||||
      this.props.onScrollToBottom();
 | 
			
		||||
    } else if (scrollTop < 100) {
 | 
			
		||||
    } else if (scrollTop < 100 && this.props.onScrollToTop) {
 | 
			
		||||
      this.props.onScrollToTop();
 | 
			
		||||
    } else {
 | 
			
		||||
    } else if (this.props.onScroll) {
 | 
			
		||||
      this.props.onScroll();
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 
 | 
			
		||||
@@ -34,6 +34,7 @@ import Reblogs from '../features/reblogs';
 | 
			
		||||
import Favourites from '../features/favourites';
 | 
			
		||||
import HashtagTimeline from '../features/hashtag_timeline';
 | 
			
		||||
import Notifications from '../features/notifications';
 | 
			
		||||
import FollowRequests from '../features/follow_requests';
 | 
			
		||||
import { IntlProvider, addLocaleData } from 'react-intl';
 | 
			
		||||
import en from 'react-intl/locale-data/en';
 | 
			
		||||
import de from 'react-intl/locale-data/de';
 | 
			
		||||
@@ -125,6 +126,8 @@ const Mastodon = React.createClass({
 | 
			
		||||
                <Route path='followers' component={Followers} />
 | 
			
		||||
                <Route path='following' component={Following} />
 | 
			
		||||
              </Route>
 | 
			
		||||
 | 
			
		||||
              <Route path='follow_requests' component={FollowRequests} />
 | 
			
		||||
            </Route>
 | 
			
		||||
          </Router>
 | 
			
		||||
        </Provider>
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,61 @@
 | 
			
		||||
import ImmutablePropTypes from 'react-immutable-proptypes';
 | 
			
		||||
import Permalink from '../../../components/permalink';
 | 
			
		||||
import Avatar from '../../../components/avatar';
 | 
			
		||||
import DisplayName from '../../../components/display_name';
 | 
			
		||||
import emojify from '../../../emoji';
 | 
			
		||||
import IconButton from '../../../components/icon_button';
 | 
			
		||||
import { defineMessages, injectIntl } from 'react-intl';
 | 
			
		||||
 | 
			
		||||
const messages = defineMessages({
 | 
			
		||||
  authorize: { id: 'follow_request.authorize', defaultMessage: 'Authorize' },
 | 
			
		||||
  reject: { id: 'follow_request.reject', defaultMessage: 'Reject' }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const outerStyle = {
 | 
			
		||||
  padding: '14px 10px'
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const panelStyle = {
 | 
			
		||||
  background: '#2f3441',
 | 
			
		||||
  display: 'flex',
 | 
			
		||||
  flexDirection: 'row',
 | 
			
		||||
  borderTop: '1px solid #363c4b',
 | 
			
		||||
  borderBottom: '1px solid #363c4b',
 | 
			
		||||
  padding: '10px 0'
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const btnStyle = {
 | 
			
		||||
  flex: '1 1 auto',
 | 
			
		||||
  textAlign: 'center'
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const AccountAuthorize = ({ intl, account, onAuthorize, onReject }) => {
 | 
			
		||||
  const content = { __html: emojify(account.get('note')) };
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div>
 | 
			
		||||
      <div style={outerStyle}>
 | 
			
		||||
        <Permalink href={account.get('url')} className='detailed-status__display-name' style={{ display: 'block', overflow: 'hidden', marginBottom: '15px' }}>
 | 
			
		||||
          <div style={{ float: 'left', marginRight: '10px' }}><Avatar src={account.get('avatar')} size={48} /></div>
 | 
			
		||||
          <DisplayName account={account} />
 | 
			
		||||
        </Permalink>
 | 
			
		||||
 | 
			
		||||
        <div style={{ color: '#616b86', fontSize: '14px' }} className='account__header__content' dangerouslySetInnerHTML={content} />
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <div style={panelStyle}>
 | 
			
		||||
        <div style={btnStyle}><IconButton title={intl.formatMessage(messages.authorize)} icon='check' onClick={onAuthorize} /></div>
 | 
			
		||||
        <div style={btnStyle}><IconButton title={intl.formatMessage(messages.reject)} icon='times' onClick={onReject} /></div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
  )
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
AccountAuthorize.propTypes = {
 | 
			
		||||
  account: ImmutablePropTypes.map.isRequired,
 | 
			
		||||
  onAuthorize: React.PropTypes.func.isRequired,
 | 
			
		||||
  onReject: React.PropTypes.func.isRequired,
 | 
			
		||||
  intl: React.PropTypes.object.isRequired
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default injectIntl(AccountAuthorize);
 | 
			
		||||
@@ -0,0 +1,26 @@
 | 
			
		||||
import { connect } from 'react-redux';
 | 
			
		||||
import { makeGetAccount } from '../../../selectors';
 | 
			
		||||
import AccountAuthorize from '../components/account_authorize';
 | 
			
		||||
import { authorizeFollowRequest, rejectFollowRequest } from '../../../actions/accounts';
 | 
			
		||||
 | 
			
		||||
const makeMapStateToProps = () => {
 | 
			
		||||
  const getAccount = makeGetAccount();
 | 
			
		||||
 | 
			
		||||
  const mapStateToProps = (state, props) => ({
 | 
			
		||||
    account: getAccount(state, props.id)
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  return mapStateToProps;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const mapDispatchToProps = (dispatch, { id }) => ({
 | 
			
		||||
  onAuthorize (account) {
 | 
			
		||||
    dispatch(authorizeFollowRequest(id));
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  onReject (account) {
 | 
			
		||||
    dispatch(rejectFollowRequest(id));
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
export default connect(makeMapStateToProps, mapDispatchToProps)(AccountAuthorize);
 | 
			
		||||
@@ -0,0 +1,66 @@
 | 
			
		||||
import { connect } from 'react-redux';
 | 
			
		||||
import PureRenderMixin from 'react-addons-pure-render-mixin';
 | 
			
		||||
import ImmutablePropTypes from 'react-immutable-proptypes';
 | 
			
		||||
import LoadingIndicator from '../../components/loading_indicator';
 | 
			
		||||
import { ScrollContainer } from 'react-router-scroll';
 | 
			
		||||
import Column from '../ui/components/column';
 | 
			
		||||
import AccountAuthorizeContainer from './containers/account_authorize_container';
 | 
			
		||||
import { fetchFollowRequests, expandFollowRequests } from '../../actions/accounts';
 | 
			
		||||
import { defineMessages, injectIntl } from 'react-intl';
 | 
			
		||||
 | 
			
		||||
const messages = defineMessages({
 | 
			
		||||
  heading: { id: 'column.follow_requests', defaultMessage: 'Follow requests' }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const mapStateToProps = state => ({
 | 
			
		||||
  accountIds: state.getIn(['user_lists', 'follow_requests', 'items'])
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const FollowRequests = React.createClass({
 | 
			
		||||
  propTypes: {
 | 
			
		||||
    params: React.PropTypes.object.isRequired,
 | 
			
		||||
    dispatch: React.PropTypes.func.isRequired,
 | 
			
		||||
    accountIds: ImmutablePropTypes.list,
 | 
			
		||||
    intl: React.PropTypes.object.isRequired
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  mixins: [PureRenderMixin],
 | 
			
		||||
 | 
			
		||||
  componentWillMount () {
 | 
			
		||||
    this.props.dispatch(fetchFollowRequests());
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  handleScroll (e) {
 | 
			
		||||
    const { scrollTop, scrollHeight, clientHeight } = e.target;
 | 
			
		||||
 | 
			
		||||
    if (scrollTop === scrollHeight - clientHeight) {
 | 
			
		||||
      this.props.dispatch(expandFollowRequests());
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  render () {
 | 
			
		||||
    const { intl, accountIds } = this.props;
 | 
			
		||||
 | 
			
		||||
    if (!accountIds) {
 | 
			
		||||
      return (
 | 
			
		||||
        <Column>
 | 
			
		||||
          <LoadingIndicator />
 | 
			
		||||
        </Column>
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
      <Column icon='users' heading={intl.formatMessage(messages.heading)}>
 | 
			
		||||
        <ScrollContainer scrollKey='follow_requests'>
 | 
			
		||||
          <div className='scrollable' onScroll={this.handleScroll}>
 | 
			
		||||
            {accountIds.map(id =>
 | 
			
		||||
              <AccountAuthorizeContainer key={id} id={id} />
 | 
			
		||||
            )}
 | 
			
		||||
          </div>
 | 
			
		||||
        </ScrollContainer>
 | 
			
		||||
      </Column>
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
export default connect(mapStateToProps)(injectIntl(FollowRequests));
 | 
			
		||||
@@ -7,7 +7,8 @@ import { connect } from 'react-redux';
 | 
			
		||||
const messages = defineMessages({
 | 
			
		||||
  heading: { id: 'getting_started.heading', defaultMessage: 'Getting started' },
 | 
			
		||||
  public_timeline: { id: 'navigation_bar.public_timeline', defaultMessage: 'Public timeline' },
 | 
			
		||||
  settings: { id: 'navigation_bar.settings', defaultMessage: 'Settings' }
 | 
			
		||||
  settings: { id: 'navigation_bar.settings', defaultMessage: 'Settings' },
 | 
			
		||||
  follow_requests: { id: 'navigation_bar.follow_requests', defaultMessage: 'Follow requests' }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const mapStateToProps = state => ({
 | 
			
		||||
@@ -32,6 +33,7 @@ const GettingStarted = ({ intl, me }) => {
 | 
			
		||||
        <div style={hamburgerStyle}><i className='fa fa-bars' /></div>
 | 
			
		||||
        <ColumnLink icon='globe' text={intl.formatMessage(messages.public_timeline)} to='/timelines/public' />
 | 
			
		||||
        <ColumnLink icon='cog' text={intl.formatMessage(messages.settings)} href='/settings/profile' />
 | 
			
		||||
        <ColumnLink icon='users' text={intl.formatMessage(messages.follow_requests)} to='/follow_requests' />
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <div className='static-content'>
 | 
			
		||||
@@ -43,4 +45,9 @@ const GettingStarted = ({ intl, me }) => {
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
GettingStarted.propTypes = {
 | 
			
		||||
  intl: React.PropTypes.object.isRequired,
 | 
			
		||||
  me: React.PropTypes.number
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default connect(mapStateToProps)(injectIntl(GettingStarted));
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,8 @@ import {
 | 
			
		||||
  FOLLOWING_FETCH_SUCCESS,
 | 
			
		||||
  FOLLOWING_EXPAND_SUCCESS,
 | 
			
		||||
  ACCOUNT_TIMELINE_FETCH_SUCCESS,
 | 
			
		||||
  ACCOUNT_TIMELINE_EXPAND_SUCCESS
 | 
			
		||||
  ACCOUNT_TIMELINE_EXPAND_SUCCESS,
 | 
			
		||||
  FOLLOW_REQUESTS_FETCH_SUCCESS
 | 
			
		||||
} from '../actions/accounts';
 | 
			
		||||
import { COMPOSE_SUGGESTIONS_READY } from '../actions/compose';
 | 
			
		||||
import {
 | 
			
		||||
@@ -78,6 +79,7 @@ export default function accounts(state = initialState, action) {
 | 
			
		||||
    case FAVOURITES_FETCH_SUCCESS:
 | 
			
		||||
    case COMPOSE_SUGGESTIONS_READY:
 | 
			
		||||
    case SEARCH_SUGGESTIONS_READY:
 | 
			
		||||
    case FOLLOW_REQUESTS_FETCH_SUCCESS:
 | 
			
		||||
      return normalizeAccounts(state, action.accounts);
 | 
			
		||||
    case NOTIFICATIONS_REFRESH_SUCCESS:
 | 
			
		||||
    case NOTIFICATIONS_EXPAND_SUCCESS:
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,10 @@ import {
 | 
			
		||||
  FOLLOWERS_FETCH_SUCCESS,
 | 
			
		||||
  FOLLOWERS_EXPAND_SUCCESS,
 | 
			
		||||
  FOLLOWING_FETCH_SUCCESS,
 | 
			
		||||
  FOLLOWING_EXPAND_SUCCESS
 | 
			
		||||
  FOLLOWING_EXPAND_SUCCESS,
 | 
			
		||||
  FOLLOW_REQUESTS_FETCH_SUCCESS,
 | 
			
		||||
  FOLLOW_REQUEST_AUTHORIZE_SUCCESS,
 | 
			
		||||
  FOLLOW_REQUEST_REJECT_SUCCESS
 | 
			
		||||
} from '../actions/accounts';
 | 
			
		||||
import {
 | 
			
		||||
  REBLOGS_FETCH_SUCCESS,
 | 
			
		||||
@@ -14,7 +17,8 @@ const initialState = Immutable.Map({
 | 
			
		||||
  followers: Immutable.Map(),
 | 
			
		||||
  following: Immutable.Map(),
 | 
			
		||||
  reblogged_by: Immutable.Map(),
 | 
			
		||||
  favourited_by: Immutable.Map()
 | 
			
		||||
  favourited_by: Immutable.Map(),
 | 
			
		||||
  follow_requests: Immutable.Map()
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const normalizeList = (state, type, id, accounts, next) => {
 | 
			
		||||
@@ -44,6 +48,11 @@ export default function userLists(state = initialState, action) {
 | 
			
		||||
      return state.setIn(['reblogged_by', action.id], Immutable.List(action.accounts.map(item => item.id)));
 | 
			
		||||
    case FAVOURITES_FETCH_SUCCESS:
 | 
			
		||||
      return state.setIn(['favourited_by', action.id], Immutable.List(action.accounts.map(item => item.id)));
 | 
			
		||||
    case FOLLOW_REQUESTS_FETCH_SUCCESS:
 | 
			
		||||
      return state.setIn(['follow_requests', 'items'], Immutable.List(action.accounts.map(item => item.id))).setIn(['follow_requests', 'next'], action.next);
 | 
			
		||||
    case FOLLOW_REQUEST_AUTHORIZE_SUCCESS:
 | 
			
		||||
    case FOLLOW_REQUEST_REJECT_SUCCESS:
 | 
			
		||||
      return state.updateIn(['follow_requests', 'items'], list => list.filterNot(item => item === action.id));
 | 
			
		||||
    default:
 | 
			
		||||
      return state;
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,28 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class FollowRequestsController < ApplicationController
 | 
			
		||||
  layout 'auth'
 | 
			
		||||
 | 
			
		||||
  before_action :authenticate_user!
 | 
			
		||||
  before_action :set_follow_request, except: :index
 | 
			
		||||
 | 
			
		||||
  def index
 | 
			
		||||
    @follow_requests = FollowRequest.where(target_account: current_account)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def authorize
 | 
			
		||||
    @follow_request.authorize!
 | 
			
		||||
    redirect_to follow_requests_path
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def reject
 | 
			
		||||
    @follow_request.reject!
 | 
			
		||||
    redirect_to follow_requests_path
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  private
 | 
			
		||||
 | 
			
		||||
  def set_follow_request
 | 
			
		||||
    @follow_request = FollowRequest.find(params[:id])
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@@ -1,2 +0,0 @@
 | 
			
		||||
module FollowRequestsHelper
 | 
			
		||||
end
 | 
			
		||||
@@ -1,16 +0,0 @@
 | 
			
		||||
- content_for :page_title do
 | 
			
		||||
  = t('follow_requests.title')
 | 
			
		||||
 | 
			
		||||
- if @follow_requests.empty?
 | 
			
		||||
  %p.nothing-here= t('accounts.nothing_here')
 | 
			
		||||
- else
 | 
			
		||||
  %table.table
 | 
			
		||||
    %tbody
 | 
			
		||||
      - @follow_requests.each do |follow_request|
 | 
			
		||||
        %tr
 | 
			
		||||
          %td= link_to follow_request.account.acct, web_path("accounts/#{follow_request.account.id}")
 | 
			
		||||
          %td{ style: 'text-align: right' }
 | 
			
		||||
            = table_link_to 'check-circle', t('follow_requests.authorize'), authorize_follow_request_path(follow_request), method: :post
 | 
			
		||||
            = table_link_to 'times-circle', t('follow_requests.reject'), reject_follow_request_path(follow_request), method: :post
 | 
			
		||||
 | 
			
		||||
.form-footer= render "settings/shared/links"
 | 
			
		||||
@@ -1,8 +1,6 @@
 | 
			
		||||
%ul.no-list
 | 
			
		||||
  - if controller_name != 'profiles'
 | 
			
		||||
    %li= link_to t('settings.edit_profile'), settings_profile_path
 | 
			
		||||
  - if controller_name != 'follow_requests'
 | 
			
		||||
    %li= link_to t('follow_requests.title'), follow_requests_path
 | 
			
		||||
  - if controller_name != 'preferences'
 | 
			
		||||
    %li= link_to t('settings.preferences'), settings_preferences_path
 | 
			
		||||
  - if controller_name != 'registrations'
 | 
			
		||||
 
 | 
			
		||||
@@ -40,10 +40,6 @@ en:
 | 
			
		||||
      x_minutes: "%{count}m"
 | 
			
		||||
      x_months: "%{count}mo"
 | 
			
		||||
      x_seconds: "%{count}s"
 | 
			
		||||
  follow_requests:
 | 
			
		||||
    authorize: Authorize
 | 
			
		||||
    reject: Reject
 | 
			
		||||
    title: Follow requests
 | 
			
		||||
  generic:
 | 
			
		||||
    changes_saved_msg: Changes successfully saved!
 | 
			
		||||
    powered_by: powered by %{link}
 | 
			
		||||
 
 | 
			
		||||
@@ -48,13 +48,6 @@ Rails.application.routes.draw do
 | 
			
		||||
  resources :media, only: [:show]
 | 
			
		||||
  resources :tags,  only: [:show]
 | 
			
		||||
 | 
			
		||||
  resources :follow_requests do
 | 
			
		||||
    member do
 | 
			
		||||
      post :authorize
 | 
			
		||||
      post :reject
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  namespace :admin do
 | 
			
		||||
    resources :pubsubhubbub, only: [:index]
 | 
			
		||||
    resources :domain_blocks, only: [:index, :create]
 | 
			
		||||
 
 | 
			
		||||
@@ -1,16 +0,0 @@
 | 
			
		||||
require 'rails_helper'
 | 
			
		||||
 | 
			
		||||
RSpec.describe FollowRequestsController, type: :controller do
 | 
			
		||||
  render_views
 | 
			
		||||
 | 
			
		||||
  before do
 | 
			
		||||
    sign_in Fabricate(:user), scope: :user
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe 'GET #index' do
 | 
			
		||||
    it 'returns http success' do
 | 
			
		||||
      get :index
 | 
			
		||||
      expect(response).to have_http_status(:success)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@@ -1,5 +0,0 @@
 | 
			
		||||
require 'rails_helper'
 | 
			
		||||
 | 
			
		||||
RSpec.describe FollowRequestsHelper, type: :helper do
 | 
			
		||||
 | 
			
		||||
end
 | 
			
		||||
		Reference in New Issue
	
	Block a user