Improved how user lists look, added follow button to them
This commit is contained in:
		
							parent
							
								
									1c84d505c8
								
							
						
					
					
						commit
						ac4f53a3a2
					
				| @ -40,6 +40,10 @@ export const FOLLOWING_FETCH_REQUEST = 'FOLLOWING_FETCH_REQUEST'; | ||||
| export const FOLLOWING_FETCH_SUCCESS = 'FOLLOWING_FETCH_SUCCESS'; | ||||
| export const FOLLOWING_FETCH_FAIL    = 'FOLLOWING_FETCH_FAIL'; | ||||
| 
 | ||||
| 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 function setAccountSelf(account) { | ||||
|   return { | ||||
|     type: ACCOUNT_SET_SELF, | ||||
| @ -304,6 +308,7 @@ export function fetchFollowers(id) { | ||||
| 
 | ||||
|     api(getState).get(`/api/v1/accounts/${id}/followers`).then(response => { | ||||
|       dispatch(fetchFollowersSuccess(id, response.data)); | ||||
|       dispatch(fetchRelationships(response.data.map(item => item.id))); | ||||
|     }).catch(error => { | ||||
|       dispatch(fetchFollowersFail(id, error)); | ||||
|     }); | ||||
| @ -339,6 +344,7 @@ export function fetchFollowing(id) { | ||||
| 
 | ||||
|     api(getState).get(`/api/v1/accounts/${id}/following`).then(response => { | ||||
|       dispatch(fetchFollowingSuccess(id, response.data)); | ||||
|       dispatch(fetchRelationships(response.data.map(item => item.id))); | ||||
|     }).catch(error => { | ||||
|       dispatch(fetchFollowingFail(id, error)); | ||||
|     }); | ||||
| @ -367,3 +373,36 @@ export function fetchFollowingFail(id, error) { | ||||
|     error: error | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| export function fetchRelationships(account_ids) { | ||||
|   return (dispatch, getState) => { | ||||
|     dispatch(fetchRelationshipsRequest(account_ids)); | ||||
| 
 | ||||
|     api(getState).get(`/api/v1/accounts/relationships?${account_ids.map(id => `id[]=${id}`).join('&')}`).then(response => { | ||||
|       dispatch(fetchRelationshipsSuccess(response.data)); | ||||
|     }).catch(error => { | ||||
|       dispatch(fetchRelationshipsFail(error)); | ||||
|     }); | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| export function fetchRelationshipsRequest(ids) { | ||||
|   return { | ||||
|     type: RELATIONSHIPS_FETCH_REQUEST, | ||||
|     ids: ids | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| export function fetchRelationshipsSuccess(relationships) { | ||||
|   return { | ||||
|     type: RELATIONSHIPS_FETCH_SUCCESS, | ||||
|     relationships: relationships | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| export function fetchRelationshipsFail(error) { | ||||
|   return { | ||||
|     type: RELATIONSHIPS_FETCH_FAIL, | ||||
|     error: error | ||||
|   }; | ||||
| }; | ||||
|  | ||||
| @ -109,7 +109,7 @@ const SuggestionsBox = React.createClass({ | ||||
|             <Link key={account.get('id')} style={itemStyle} to={`/accounts/${account.get('id')}`}> | ||||
|               <div style={{ float: 'left', marginRight: '10px' }}><Avatar src={account.get('avatar')} size={36} /></div> | ||||
|               <strong style={displayNameStyle}>{displayName}</strong> | ||||
|               <span style={acctStyle}>{account.get('acct')}</span> | ||||
|               <span style={acctStyle}>@{account.get('acct')}</span> | ||||
|             </Link> | ||||
|           ) | ||||
|         })} | ||||
|  | ||||
| @ -1,62 +1,82 @@ | ||||
| import PureRenderMixin    from 'react-addons-pure-render-mixin'; | ||||
| import ImmutablePropTypes from 'react-immutable-proptypes'; | ||||
| import Avatar             from '../../../components/avatar'; | ||||
| import DisplayName        from '../../../components/display_name'; | ||||
| import { Link }           from 'react-router'; | ||||
| import IconButton         from '../../../components/icon_button'; | ||||
| 
 | ||||
| const outerStyle = { | ||||
|   padding: '10px' | ||||
| }; | ||||
| 
 | ||||
| const displayNameStyle = { | ||||
|   display: 'block', | ||||
|   fontWeight: '500', | ||||
|   overflow: 'hidden', | ||||
|   textOverflow: 'ellipsis', | ||||
|   color: '#fff' | ||||
| }; | ||||
| 
 | ||||
| const acctStyle = { | ||||
|   display: 'block', | ||||
|   overflow: 'hidden', | ||||
|   textOverflow: 'ellipsis' | ||||
|   padding: '10px', | ||||
|   borderBottom: '1px solid #363c4b' | ||||
| }; | ||||
| 
 | ||||
| const itemStyle = { | ||||
|   flex: '1 1 auto', | ||||
|   display: 'block', | ||||
|   color: '#9baec8', | ||||
|   overflow: 'hidden', | ||||
|   textDecoration: 'none' | ||||
|   textDecoration: 'none', | ||||
|   fontSize: '14px' | ||||
| }; | ||||
| 
 | ||||
| const noteStyle = { | ||||
|   paddingTop: '5px', | ||||
|   fontSize: '12px', | ||||
|   color: '#616b86' | ||||
| }; | ||||
| 
 | ||||
| const buttonsStyle = { | ||||
|   padding: '10px' | ||||
| }; | ||||
| 
 | ||||
| const Account = React.createClass({ | ||||
| 
 | ||||
|   propTypes: { | ||||
|     account: ImmutablePropTypes.map.isRequired, | ||||
|     me: React.PropTypes.number.isRequired | ||||
|     me: React.PropTypes.number.isRequired, | ||||
|     onFollow: React.PropTypes.func.isRequired, | ||||
|     withNote: React.PropTypes.bool | ||||
|   }, | ||||
| 
 | ||||
|   mixins: [PureRenderMixin], | ||||
| 
 | ||||
|   handleFollow () { | ||||
|     this.props.onFollow(this.props.account); | ||||
|   }, | ||||
| 
 | ||||
|   render () { | ||||
|     const { account } = this.props; | ||||
|     const { account, me } = this.props; | ||||
| 
 | ||||
|     if (!account) { | ||||
|       return <div />; | ||||
|     } | ||||
| 
 | ||||
|     let displayName = account.get('display_name'); | ||||
|     let note, buttons; | ||||
| 
 | ||||
|     if (displayName.length === 0) { | ||||
|       displayName = account.get('username'); | ||||
|     if (account.get('note').length > 0) { | ||||
|       note = <div style={noteStyle}>{account.get('note')}</div>; | ||||
|     } | ||||
| 
 | ||||
|     if (account.get('id') !== me) { | ||||
|       buttons = ( | ||||
|         <div style={buttonsStyle}> | ||||
|           <IconButton icon='user-plus' title='Follow' onClick={this.handleFollow} active={account.getIn(['relationship', 'following'])} /> | ||||
|         </div> | ||||
|       ); | ||||
|     } | ||||
| 
 | ||||
|     return ( | ||||
|       <div style={outerStyle}> | ||||
|         <Link key={account.get('id')} style={itemStyle} to={`/accounts/${account.get('id')}`}> | ||||
|           <div style={{ float: 'left', marginRight: '10px' }}><Avatar src={account.get('avatar')} size={36} /></div> | ||||
|           <strong style={displayNameStyle}>{displayName}</strong> | ||||
|           <span style={acctStyle}>{account.get('acct')}</span> | ||||
|         </Link> | ||||
|         <div style={{ display: 'flex' }}> | ||||
|           <Link key={account.get('id')} style={itemStyle} className='account__display-name' to={`/accounts/${account.get('id')}`}> | ||||
|             <div style={{ float: 'left', marginRight: '10px' }}><Avatar src={account.get('avatar')} size={36} /></div> | ||||
|             <DisplayName account={account} /> | ||||
|           </Link> | ||||
| 
 | ||||
|           {buttons} | ||||
|         </div> | ||||
| 
 | ||||
|         {note} | ||||
|       </div> | ||||
|     ); | ||||
|   } | ||||
|  | ||||
| @ -1,6 +1,10 @@ | ||||
| import { connect }            from 'react-redux'; | ||||
| import { makeGetAccount }     from '../../../selectors'; | ||||
| import Account                from '../components/account'; | ||||
| import { | ||||
|   followAccount, | ||||
|   unfollowAccount | ||||
| }                             from '../../../actions/accounts'; | ||||
| 
 | ||||
| const makeMapStateToProps = () => { | ||||
|   const getAccount = makeGetAccount(); | ||||
| @ -14,7 +18,13 @@ const makeMapStateToProps = () => { | ||||
| }; | ||||
| 
 | ||||
| const mapDispatchToProps = (dispatch) => ({ | ||||
|   // | ||||
|   onFollow (account) { | ||||
|     if (account.getIn(['relationship', 'following'])) { | ||||
|       dispatch(unfollowAccount(account.get('id'))); | ||||
|     } else { | ||||
|       dispatch(followAccount(account.get('id'))); | ||||
|     } | ||||
|   } | ||||
| }); | ||||
| 
 | ||||
| export default connect(makeMapStateToProps, mapDispatchToProps)(Account); | ||||
|  | ||||
| @ -20,7 +20,8 @@ import { | ||||
|   ACCOUNT_TIMELINE_FETCH_SUCCESS, | ||||
|   ACCOUNT_TIMELINE_EXPAND_SUCCESS, | ||||
|   FOLLOWERS_FETCH_SUCCESS, | ||||
|   FOLLOWING_FETCH_SUCCESS | ||||
|   FOLLOWING_FETCH_SUCCESS, | ||||
|   RELATIONSHIPS_FETCH_SUCCESS | ||||
| }                                from '../actions/accounts'; | ||||
| import { | ||||
|   STATUS_FETCH_SUCCESS, | ||||
| @ -184,6 +185,14 @@ function normalizeRelationship(state, relationship) { | ||||
|   return state.setIn(['relationships', relationship.get('id')], relationship); | ||||
| }; | ||||
| 
 | ||||
| function normalizeRelationships(state, relationships) { | ||||
|   relationships.forEach(relationship => { | ||||
|     state = normalizeRelationship(state, relationship); | ||||
|   }); | ||||
| 
 | ||||
|   return state; | ||||
| }; | ||||
| 
 | ||||
| function setSelf(state, account) { | ||||
|   state = normalizeAccount(state, account); | ||||
|   return state.set('me', account.get('id')); | ||||
| @ -252,6 +261,8 @@ export default function timelines(state = initialState, action) { | ||||
|     case FOLLOWERS_FETCH_SUCCESS: | ||||
|     case FOLLOWING_FETCH_SUCCESS: | ||||
|       return normalizeAccounts(state, Immutable.fromJS(action.accounts)); | ||||
|     case RELATIONSHIPS_FETCH_SUCCESS: | ||||
|       return normalizeRelationships(state, Immutable.fromJS(action.relationships)); | ||||
|     default: | ||||
|       return state; | ||||
|   } | ||||
|  | ||||
| @ -117,17 +117,17 @@ | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| .status__display-name, .status__relative-time, .detailed-status__display-name, .detailed-status__datetime { | ||||
| .status__display-name, .status__relative-time, .detailed-status__display-name, .detailed-status__datetime, .account__display-name { | ||||
|   text-decoration: none; | ||||
| } | ||||
| 
 | ||||
| .status__display-name { | ||||
| .status__display-name, .account__display-name { | ||||
|   strong { | ||||
|     color: #fff; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| .status__display-name, .reply-indicator__display-name, .detailed-status__display-name { | ||||
| .status__display-name, .reply-indicator__display-name, .detailed-status__display-name, .account__display-name { | ||||
|   &:hover { | ||||
|     strong { | ||||
|       text-decoration: underline; | ||||
| @ -135,6 +135,12 @@ | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| .account__display-name { | ||||
|   strong { | ||||
|     display: block; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| .detailed-status__display-name { | ||||
|   color: #d9e1e8; | ||||
|   line-height: 24px; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user