diff --git a/app/assets/javascripts/components/actions/accounts.jsx b/app/assets/javascripts/components/actions/accounts.jsx new file mode 100644 index 000000000..a334e3c20 --- /dev/null +++ b/app/assets/javascripts/components/actions/accounts.jsx @@ -0,0 +1,48 @@ +import api from '../api' + +export const ACCOUNT_SET_SELF = 'ACCOUNT_SET_SELF'; +export const ACCOUNT_FETCH = 'ACCOUNT_FETCH'; +export const ACCOUNT_FETCH_REQUEST = 'ACCOUNT_FETCH_REQUEST'; +export const ACCOUNT_FETCH_SUCCESS = 'ACCOUNT_FETCH_SUCCESS'; +export const ACCOUNT_FETCH_FAIL = 'ACCOUNT_FETCH_FAIL'; + +export function setAccountSelf(account) { + return { + type: ACCOUNT_SET_SELF, + account: account + }; +}; + +export function fetchAccount(id) { + return (dispatch, getState) => { + dispatch(fetchAccountRequest(id)); + + api(getState).get(`/api/accounts/${id}`).then(response => { + dispatch(fetchAccountSuccess(response.data)); + }).catch(error => { + dispatch(fetchAccountFail(id, error)); + }); + }; +}; + +export function fetchAccountRequest(id) { + return { + type: ACCOUNT_FETCH_REQUEST, + id: id + }; +}; + +export function fetchAccountSuccess(account) { + return { + type: ACCOUNT_FETCH_SUCCESS, + account: account + }; +}; + +export function fetchAccountFail(id, error) { + return { + type: ACCOUNT_FETCH_FAIL, + id: id, + error: error + }; +}; diff --git a/app/assets/javascripts/components/actions/statuses.jsx b/app/assets/javascripts/components/actions/statuses.jsx new file mode 100644 index 000000000..faf33ea1d --- /dev/null +++ b/app/assets/javascripts/components/actions/statuses.jsx @@ -0,0 +1,6 @@ +import api from '../api'; + +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'; diff --git a/app/assets/javascripts/components/components/column.jsx b/app/assets/javascripts/components/components/column.jsx index 7f9a4665a..b3b13ba9e 100644 --- a/app/assets/javascripts/components/components/column.jsx +++ b/app/assets/javascripts/components/components/column.jsx @@ -5,7 +5,8 @@ const Column = React.createClass({ propTypes: { heading: React.PropTypes.string, - icon: React.PropTypes.string + icon: React.PropTypes.string, + fluid: React.PropTypes.bool }, mixins: [PureRenderMixin], @@ -22,8 +23,16 @@ const Column = React.createClass({ header = ; } + const style = { width: '350px', flex: '0 0 auto', background: '#282c37', margin: '10px', marginRight: '0', display: 'flex', flexDirection: 'column' }; + + if (this.props.fluid) { + style.width = 'auto'; + style.flex = '1 1 auto'; + style.background = '#21242d'; + } + return ( -
+
{header} {this.props.children}
diff --git a/app/assets/javascripts/components/components/columns_area.jsx b/app/assets/javascripts/components/components/columns_area.jsx index 7708b3273..e45a6466d 100644 --- a/app/assets/javascripts/components/components/columns_area.jsx +++ b/app/assets/javascripts/components/components/columns_area.jsx @@ -6,7 +6,7 @@ const ColumnsArea = React.createClass({ render () { return ( -
+
{this.props.children}
); diff --git a/app/assets/javascripts/components/components/display_name.jsx b/app/assets/javascripts/components/components/display_name.jsx index f8d821bce..8bffca551 100644 --- a/app/assets/javascripts/components/components/display_name.jsx +++ b/app/assets/javascripts/components/components/display_name.jsx @@ -1,4 +1,5 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; +import PureRenderMixin from 'react-addons-pure-render-mixin'; const DisplayName = React.createClass({ @@ -6,6 +7,8 @@ const DisplayName = React.createClass({ account: ImmutablePropTypes.map.isRequired }, + mixins: [PureRenderMixin], + render () { let displayName = this.props.account.get('display_name'); diff --git a/app/assets/javascripts/components/components/frontend.jsx b/app/assets/javascripts/components/components/frontend.jsx index 9d5166a08..aab3f55dc 100644 --- a/app/assets/javascripts/components/components/frontend.jsx +++ b/app/assets/javascripts/components/components/frontend.jsx @@ -1,12 +1,13 @@ -import ColumnsArea from './columns_area'; -import Column from './column'; -import Drawer from './drawer'; +import ColumnsArea from './columns_area'; +import Column from './column'; +import Drawer from './drawer'; import ComposeFormContainer from '../containers/compose_form_container'; import FollowFormContainer from '../containers/follow_form_container'; import UploadFormContainer from '../containers/upload_form_container'; import StatusListContainer from '../containers/status_list_container'; import NotificationsContainer from '../containers/notifications_container'; -import PureRenderMixin from 'react-addons-pure-render-mixin'; +import NavigationContainer from '../containers/navigation_container'; +import PureRenderMixin from 'react-addons-pure-render-mixin'; const Frontend = React.createClass({ @@ -17,6 +18,7 @@ const Frontend = React.createClass({
+
@@ -32,6 +34,10 @@ const Frontend = React.createClass({ + + + {this.props.children} + diff --git a/app/assets/javascripts/components/components/navigation_bar.jsx b/app/assets/javascripts/components/components/navigation_bar.jsx new file mode 100644 index 000000000..3470cd52f --- /dev/null +++ b/app/assets/javascripts/components/components/navigation_bar.jsx @@ -0,0 +1,30 @@ +import PureRenderMixin from 'react-addons-pure-render-mixin'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import Avatar from './avatar'; +import IconButton from './icon_button'; +import DisplayName from './display_name'; +import { Link } from 'react-router'; + +const NavigationBar = React.createClass({ + propTypes: { + account: ImmutablePropTypes.map.isRequired + }, + + mixins: [PureRenderMixin], + + render () { + return ( +
+ + +
+ {this.props.account.get('acct')} + Settings +
+
+ ); + } + +}); + +export default NavigationBar; diff --git a/app/assets/javascripts/components/components/status.jsx b/app/assets/javascripts/components/components/status.jsx index b72198b09..d8a2a77e0 100644 --- a/app/assets/javascripts/components/components/status.jsx +++ b/app/assets/javascripts/components/components/status.jsx @@ -5,11 +5,13 @@ import PureRenderMixin from 'react-addons-pure-render-mixin'; import IconButton from './icon_button'; import DisplayName from './display_name'; import MediaGallery from './media_gallery'; +import { hashHistory } from 'react-router'; const Status = React.createClass({ propTypes: { status: ImmutablePropTypes.map.isRequired, + wrapped: React.PropTypes.bool, onReply: React.PropTypes.func, onFavourite: React.PropTypes.func, onReblog: React.PropTypes.func @@ -29,6 +31,10 @@ const Status = React.createClass({ this.props.onReblog(this.props.status); }, + handleClick () { + hashHistory.push(`/statuses/${this.props.status.get('id')}`); + }, + render () { var content = { __html: this.props.status.get('content') }; var media = ''; @@ -37,13 +43,13 @@ const Status = React.createClass({ if (status.get('reblog') !== null) { return ( -
+ ); } @@ -53,7 +59,7 @@ const Status = React.createClass({ } return ( -
+
diff --git a/app/assets/javascripts/components/components/upload_button.jsx b/app/assets/javascripts/components/components/upload_button.jsx index 295c3b855..a77aacc10 100644 --- a/app/assets/javascripts/components/components/upload_button.jsx +++ b/app/assets/javascripts/components/components/upload_button.jsx @@ -27,7 +27,7 @@ const UploadButton = React.createClass({ Add images - +
); } diff --git a/app/assets/javascripts/components/containers/navigation_container.jsx b/app/assets/javascripts/components/containers/navigation_container.jsx new file mode 100644 index 000000000..4aeea4c37 --- /dev/null +++ b/app/assets/javascripts/components/containers/navigation_container.jsx @@ -0,0 +1,8 @@ +import { connect } from 'react-redux'; +import NavigationBar from '../components/navigation_bar'; + +const mapStateToProps = (state, props) => ({ + account: state.getIn(['timelines', 'accounts', state.getIn(['timelines', 'me'])]) +}); + +export default connect(mapStateToProps)(NavigationBar); diff --git a/app/assets/javascripts/components/containers/root.jsx b/app/assets/javascripts/components/containers/root.jsx index e2baefa24..1ded95d3c 100644 --- a/app/assets/javascripts/components/containers/root.jsx +++ b/app/assets/javascripts/components/containers/root.jsx @@ -3,25 +3,25 @@ import configureStore fro import Frontend from '../components/frontend'; import { setTimeline, updateTimeline, deleteFromTimelines, refreshTimeline } from '../actions/timelines'; import { setAccessToken } from '../actions/meta'; +import { setAccountSelf } from '../actions/accounts'; import PureRenderMixin from 'react-addons-pure-render-mixin'; -import { Router, Route, createMemoryHistory } from 'react-router'; -import AccountRoute from '../routes/account_route'; -import StatusRoute from '../routes/status_route'; +import { Router, Route, hashHistory } from 'react-router'; -const store = configureStore(); -const history = createMemoryHistory(); +const store = configureStore(); const Root = React.createClass({ propTypes: { token: React.PropTypes.string.isRequired, - timelines: React.PropTypes.object + timelines: React.PropTypes.object, + account: React.PropTypes.string }, mixins: [PureRenderMixin], componentWillMount() { store.dispatch(setAccessToken(this.props.token)); + store.dispatch(setAccountSelf(JSON.parse(this.props.account))); for (var timelineType in this.props.timelines) { if (this.props.timelines.hasOwnProperty(timelineType)) { @@ -53,10 +53,12 @@ const Root = React.createClass({ render () { return ( - - - - + + + + + + diff --git a/app/assets/javascripts/components/reducers/timelines.jsx b/app/assets/javascripts/components/reducers/timelines.jsx index b6ecdfb1f..24adeccf8 100644 --- a/app/assets/javascripts/components/reducers/timelines.jsx +++ b/app/assets/javascripts/components/reducers/timelines.jsx @@ -1,12 +1,14 @@ import { TIMELINE_SET, TIMELINE_UPDATE, TIMELINE_DELETE } from '../actions/timelines'; import { REBLOG_SUCCESS, FAVOURITE_SUCCESS } from '../actions/interactions'; +import { ACCOUNT_SET_SELF } from '../actions/accounts'; import Immutable from 'immutable'; const initialState = Immutable.Map({ home: Immutable.List([]), mentions: Immutable.List([]), statuses: Immutable.Map(), - accounts: Immutable.Map() + accounts: Immutable.Map(), + me: null }); function statusToMaps(state, status) { @@ -63,6 +65,11 @@ export default function timelines(state = initialState, action) { case REBLOG_SUCCESS: case FAVOURITE_SUCCESS: return statusToMaps(state, Immutable.fromJS(action.response)); + case ACCOUNT_SET_SELF: + return state.withMutations(map => { + map.setIn(['accounts', action.account.id], Immutable.fromJS(action.account)); + map.set('me', action.account.id); + }); default: return state; } diff --git a/app/assets/javascripts/components/routes/account_route.jsx b/app/assets/javascripts/components/routes/account_route.jsx deleted file mode 100644 index 830621ed8..000000000 --- a/app/assets/javascripts/components/routes/account_route.jsx +++ /dev/null @@ -1,13 +0,0 @@ -const AccountRoute = React.createClass({ - - render() { - return ( -
- {this.props.params.account_id} -
- ) - } - -}); - -export default AccountRoute; diff --git a/app/assets/javascripts/components/routes/status_route.jsx b/app/assets/javascripts/components/routes/status_route.jsx deleted file mode 100644 index 358157f1e..000000000 --- a/app/assets/javascripts/components/routes/status_route.jsx +++ /dev/null @@ -1,13 +0,0 @@ -const StatusRoute = React.createClass({ - - render() { - return ( -
- {this.props.params.status_id} -
- ) - } - -}); - -export default StatusRoute; diff --git a/app/helpers/home_helper.rb b/app/helpers/home_helper.rb index 23de56ac6..d08264e1e 100644 --- a/app/helpers/home_helper.rb +++ b/app/helpers/home_helper.rb @@ -1,2 +1,14 @@ module HomeHelper + def default_props + { + token: @token, + + account: render(file: 'api/accounts/show', locals: { account: current_user.account }, formats: :json), + + timelines: { + home: render(file: 'api/statuses/home', locals: { statuses: @home }, formats: :json), + mentions: render(file: 'api/statuses/mentions', locals: { statuses: @mentions }, formats: :json) + } + } + end end diff --git a/app/views/home/index.html.haml b/app/views/home/index.html.haml index 9279ae9ae..34028462c 100644 --- a/app/views/home/index.html.haml +++ b/app/views/home/index.html.haml @@ -1 +1 @@ -= react_component 'Root', { token: @token, timelines: { home: render(file: 'api/statuses/home', locals: { statuses: @home }, formats: :json), mentions: render(file: 'api/statuses/mentions', locals: { statuses: @mentions }, formats: :json) }}, class: 'app-holder', prerender: false += react_component 'Root', default_props, class: 'app-holder', prerender: false