@ -1,6 +1,44 @@ | |||
import api from '../api'; | |||
import api from '../api'; | |||
import axios from 'axios'; | |||
export const STATUS_FETCH = 'STATUS_FETCH'; | |||
export const STATUS_FETCH_REQUEST = 'STATUS_FETCH_REQUEST'; | |||
export const STATUS_FETCH_SUCCESS = 'STATUS_FETCH_SUCCESS'; | |||
export const STATUS_FETCH_FAIL = 'STATUS_FETCH_FAIL'; | |||
export function fetchStatusRequest(id) { | |||
return { | |||
type: STATUS_FETCH_REQUEST, | |||
id: id | |||
}; | |||
}; | |||
export function fetchStatus(id) { | |||
return (dispatch, getState) => { | |||
const boundApi = api(getState); | |||
dispatch(fetchStatusRequest(id)); | |||
axios.all([boundApi.get(`/api/statuses/${id}`), boundApi.get(`/api/statuses/${id}/context`)]).then(values => { | |||
dispatch(fetchStatusSuccess(values[0].data, values[1].data)); | |||
}).catch(error => { | |||
dispatch(fetchStatusFail(id, error)); | |||
}); | |||
}; | |||
}; | |||
export function fetchStatusSuccess(status, context) { | |||
return { | |||
type: STATUS_FETCH_SUCCESS, | |||
status: status, | |||
context: context | |||
}; | |||
}; | |||
export function fetchStatusFail(id, error) { | |||
return { | |||
type: STATUS_FETCH_FAIL, | |||
id: id, | |||
error: error | |||
}; | |||
}; |
@ -0,0 +1,79 @@ | |||
import { connect } from 'react-redux'; | |||
import PureRenderMixin from 'react-addons-pure-render-mixin'; | |||
import ImmutablePropTypes from 'react-immutable-proptypes'; | |||
import { fetchAccount, followAccount, unfollowAccount } from '../../actions/accounts'; | |||
import Button from '../../components/button'; | |||
function selectAccount(state, id) { | |||
return state.getIn(['timelines', 'accounts', id], null); | |||
} | |||
const mapStateToProps = (state, props) => ({ | |||
account: selectAccount(state, Number(props.params.accountId)) | |||
}); | |||
const Account = React.createClass({ | |||
propTypes: { | |||
params: React.PropTypes.object.isRequired, | |||
dispatch: React.PropTypes.func.isRequired, | |||
account: ImmutablePropTypes.map | |||
}, | |||
mixins: [PureRenderMixin], | |||
componentWillMount () { | |||
this.props.dispatch(fetchAccount(this.props.params.accountId)); | |||
}, | |||
componentWillReceiveProps(nextProps) { | |||
if (nextProps.params.accountId !== this.props.params.accountId && nextProps.params.accountId) { | |||
this.props.dispatch(fetchAccount(nextProps.params.accountId)); | |||
} | |||
}, | |||
handleFollowClick () { | |||
this.props.dispatch(followAccount(this.props.account.get('id'))); | |||
}, | |||
handleUnfollowClick () { | |||
this.props.dispatch(unfollowAccount(this.props.account.get('id'))); | |||
}, | |||
render () { | |||
const { account } = this.props; | |||
let action; | |||
if (account === null) { | |||
return <div>Loading {this.props.params.accountId}...</div>; | |||
} | |||
if (account.get('following')) { | |||
action = <Button text='Unfollow' onClick={this.handleUnfollowClick} />; | |||
} else { | |||
action = <Button text='Follow' onClick={this.handleFollowClick} /> | |||
} | |||
return ( | |||
<div> | |||
<p> | |||
{account.get('display_name')} | |||
{account.get('acct')} | |||
</p> | |||
{account.get('url')} | |||
<p>{account.get('note')}</p> | |||
{account.get('followers_count')} followers<br /> | |||
{account.get('following_count')} following<br /> | |||
{account.get('statuses_count')} posts | |||
<p>{action}</p> | |||
</div> | |||
); | |||
} | |||
}); | |||
export default connect(mapStateToProps)(Account); |
@ -0,0 +1,28 @@ | |||
import { connect } from 'react-redux'; | |||
import PureRenderMixin from 'react-addons-pure-render-mixin'; | |||
import ImmutablePropTypes from 'react-immutable-proptypes'; | |||
const mapStateToProps = (state, props) => ({ | |||
}); | |||
const Settings = React.createClass({ | |||
propTypes: { | |||
params: React.PropTypes.object.isRequired, | |||
dispatch: React.PropTypes.func.isRequired | |||
}, | |||
mixins: [PureRenderMixin], | |||
componentWillMount () { | |||
// | |||
}, | |||
render () { | |||
return <div>Settings</div>; | |||
} | |||
}); | |||
export default connect(mapStateToProps)(Settings); |
@ -0,0 +1,74 @@ | |||
import { connect } from 'react-redux'; | |||
import PureRenderMixin from 'react-addons-pure-render-mixin'; | |||
import ImmutablePropTypes from 'react-immutable-proptypes'; | |||
import { fetchStatus } from '../../actions/statuses'; | |||
import Immutable from 'immutable'; | |||
import EmbeddedStatus from '../../components/status'; | |||
function selectStatus(state, id) { | |||
let status = state.getIn(['timelines', 'statuses', id]); | |||
status = status.set('account', state.getIn(['timelines', 'accounts', status.get('account')])); | |||
if (status.get('reblog') !== null) { | |||
status = status.set('reblog', selectStatus(state, status.get('reblog'))); | |||
} | |||
return status; | |||
}; | |||
function selectStatuses(state, ids) { | |||
return ids.map(id => selectStatus(state, id)); | |||
}; | |||
const mapStateToProps = (state, props) => ({ | |||
status: selectStatus(state, Number(props.params.statusId)), | |||
ancestors: selectStatuses(state, state.getIn(['timelines', 'ancestors', Number(props.params.statusId)], Immutable.List())), | |||
descendants: selectStatuses(state, state.getIn(['timelines', 'descendants', Number(props.params.statusId)], Immutable.List())) | |||
}); | |||
const Status = React.createClass({ | |||
propTypes: { | |||
params: React.PropTypes.object.isRequired, | |||
dispatch: React.PropTypes.func.isRequired, | |||
status: ImmutablePropTypes.map, | |||
ancestors: ImmutablePropTypes.list.isRequired, | |||
descendants: ImmutablePropTypes.list.isRequired | |||
}, | |||
mixins: [PureRenderMixin], | |||
componentWillMount () { | |||
this.props.dispatch(fetchStatus(this.props.params.statusId)); | |||
}, | |||
componentWillReceiveProps (nextProps) { | |||
if (nextProps.params.statusId !== this.props.params.statusId && nextProps.params.statusId) { | |||
this.props.dispatch(fetchStatus(nextProps.params.statusId)); | |||
} | |||
}, | |||
renderChildren (list) { | |||
return list.map(s => <EmbeddedStatus status={s} key={s.get('id')} />); | |||
}, | |||
render () { | |||
const { status, ancestors, descendants } = this.props; | |||
if (status === null) { | |||
return <div>Loading {this.props.params.statusId}...</div>; | |||
} | |||
return ( | |||
<div> | |||
{this.renderChildren(ancestors)} | |||
<EmbeddedStatus status={status} /> | |||
{this.renderChildren(descendants)} | |||
</div> | |||
); | |||
} | |||
}); | |||
export default connect(mapStateToProps)(Status); |
@ -0,0 +1,28 @@ | |||
import { connect } from 'react-redux'; | |||
import PureRenderMixin from 'react-addons-pure-render-mixin'; | |||
import ImmutablePropTypes from 'react-immutable-proptypes'; | |||
const mapStateToProps = (state, props) => ({ | |||
}); | |||
const Subscriptions = React.createClass({ | |||
propTypes: { | |||
params: React.PropTypes.object.isRequired, | |||
dispatch: React.PropTypes.func.isRequired | |||
}, | |||
mixins: [PureRenderMixin], | |||
componentWillMount () { | |||
// | |||
}, | |||
render () { | |||
return <div>Subscriptions</div>; | |||
} | |||
}); | |||
export default connect(mapStateToProps)(Subscriptions); |
@ -0,0 +1,13 @@ | |||
object false | |||
node :ancestors do | |||
@ancestors.map do |status| | |||
partial('api/statuses/show', object: status) | |||
end | |||
end | |||
node :descendants do | |||
@descendants.map do |status| | |||
partial('api/statuses/show', object: status) | |||
end | |||
end |