From 3689c119f0ad8d523ab8deb3c2c8ed0a9c84db6e Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 26 Dec 2016 21:33:51 +0100 Subject: Replacing follow requests in the settings area with in-UI column --- .../components/account_authorize.jsx | 61 ++++++++++++++++++++ .../containers/account_authorize_container.jsx | 26 +++++++++ .../components/features/follow_requests/index.jsx | 66 ++++++++++++++++++++++ .../components/features/getting_started/index.jsx | 9 ++- 4 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 app/assets/javascripts/components/features/follow_requests/components/account_authorize.jsx create mode 100644 app/assets/javascripts/components/features/follow_requests/containers/account_authorize_container.jsx create mode 100644 app/assets/javascripts/components/features/follow_requests/index.jsx (limited to 'app/assets/javascripts/components/features') diff --git a/app/assets/javascripts/components/features/follow_requests/components/account_authorize.jsx b/app/assets/javascripts/components/features/follow_requests/components/account_authorize.jsx new file mode 100644 index 000000000..c16488aea --- /dev/null +++ b/app/assets/javascripts/components/features/follow_requests/components/account_authorize.jsx @@ -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 ( +
+
+ +
+ +
+ +
+
+ +
+
+
+
+
+ ) +}; + +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); diff --git a/app/assets/javascripts/components/features/follow_requests/containers/account_authorize_container.jsx b/app/assets/javascripts/components/features/follow_requests/containers/account_authorize_container.jsx new file mode 100644 index 000000000..da1e5eaa1 --- /dev/null +++ b/app/assets/javascripts/components/features/follow_requests/containers/account_authorize_container.jsx @@ -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); diff --git a/app/assets/javascripts/components/features/follow_requests/index.jsx b/app/assets/javascripts/components/features/follow_requests/index.jsx new file mode 100644 index 000000000..461370999 --- /dev/null +++ b/app/assets/javascripts/components/features/follow_requests/index.jsx @@ -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 ( + + + + ); + } + + return ( + + +
+ {accountIds.map(id => + + )} +
+
+
+ ); + } +}); + +export default connect(mapStateToProps)(injectIntl(FollowRequests)); diff --git a/app/assets/javascripts/components/features/getting_started/index.jsx b/app/assets/javascripts/components/features/getting_started/index.jsx index bff75f86f..7c2491954 100644 --- a/app/assets/javascripts/components/features/getting_started/index.jsx +++ b/app/assets/javascripts/components/features/getting_started/index.jsx @@ -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 }) => {
+
@@ -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)); -- cgit