From 92afd296509de82e7550f67064b032db916b1f63 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 26 Aug 2016 19:12:19 +0200 Subject: The frontend will now be an OAuth app, auto-authorized. The frontend will use an access token for API requests Adding better errors for the API controllers, posting a simple status works from the frontend now --- app/assets/javascripts/components/actions/meta.jsx | 8 ++++ .../javascripts/components/actions/statuses.jsx | 56 ++++++++++++++++++++-- .../components/components/composer_drawer.jsx | 1 + .../javascripts/components/containers/root.jsx | 11 +++++ .../javascripts/components/reducers/index.jsx | 4 +- .../javascripts/components/reducers/meta.jsx | 13 +++++ 6 files changed, 88 insertions(+), 5 deletions(-) create mode 100644 app/assets/javascripts/components/actions/meta.jsx create mode 100644 app/assets/javascripts/components/reducers/meta.jsx (limited to 'app/assets/javascripts') diff --git a/app/assets/javascripts/components/actions/meta.jsx b/app/assets/javascripts/components/actions/meta.jsx new file mode 100644 index 000000000..1b64db1c2 --- /dev/null +++ b/app/assets/javascripts/components/actions/meta.jsx @@ -0,0 +1,8 @@ +export const SET_ACCESS_TOKEN = 'SET_ACCESS_TOKEN'; + +export function setAccessToken(token) { + return { + type: SET_ACCESS_TOKEN, + token: token + }; +} diff --git a/app/assets/javascripts/components/actions/statuses.jsx b/app/assets/javascripts/components/actions/statuses.jsx index fece257d5..45d62fab2 100644 --- a/app/assets/javascripts/components/actions/statuses.jsx +++ b/app/assets/javascripts/components/actions/statuses.jsx @@ -2,7 +2,11 @@ import fetch from 'isomorphic-fetch' export const SET_TIMELINE = 'SET_TIMELINE'; export const ADD_STATUS = 'ADD_STATUS'; -export const PUBLISH = 'PUBLISH'; + +export const PUBLISH = 'PUBLISH'; +export const PUBLISH_START = 'PUBLISH_START'; +export const PUBLISH_SUCC = 'PUBLISH_SUCC'; +export const PUBLISH_ERROR = 'PUBLISH_ERROR'; export function setTimeline(timeline, statuses) { return { @@ -20,14 +24,58 @@ export function addStatus(timeline, status) { }; } +export function publishStart() { + return { + type: PUBLISH_START + }; +} + +export function publishError(error) { + return { + type: PUBLISH_ERROR, + error: error + }; +} + +export function publishSucc(status) { + return { + type: PUBLISH_SUCC, + status: status + }; +} + export function publish(text, in_reply_to_id) { - return function (dispatch) { + return function (dispatch, getState) { + const access_token = getState().getIn(['meta', 'access_token']); + + var data = new FormData(); + + data.append('status', text); + + if (in_reply_to_id !== null) { + data.append('in_reply_to_id', in_reply_to_id); + } + + dispatch(publishStart()); + return fetch('/api/statuses', { - method: 'POST' + method: 'POST', + + headers: { + 'Authorization': `Bearer ${access_token}` + }, + + body: data }).then(function (response) { return response.json(); }).then(function (json) { - console.log(json); + if (json.error) { + dispatch(publishError(json.error)); + } else { + dispatch(publishSucc(json)); + } + }).catch(function (error) { + dispatch(publishError(error)); }); }; } diff --git a/app/assets/javascripts/components/components/composer_drawer.jsx b/app/assets/javascripts/components/components/composer_drawer.jsx index d33e28219..7b742f64e 100644 --- a/app/assets/javascripts/components/components/composer_drawer.jsx +++ b/app/assets/javascripts/components/components/composer_drawer.jsx @@ -26,6 +26,7 @@ const ComposerDrawer = React.createClass({ handleSubmit () { this.props.onSubmit(this.state.text, null); + this.setState({ text: '' }); }, render () { diff --git a/app/assets/javascripts/components/containers/root.jsx b/app/assets/javascripts/components/containers/root.jsx index 7da984d89..661ffb22c 100644 --- a/app/assets/javascripts/components/containers/root.jsx +++ b/app/assets/javascripts/components/containers/root.jsx @@ -2,12 +2,23 @@ import { Provider } from 'react-redux'; import configureStore from '../store/configureStore'; import Frontend from '../components/frontend'; import { setTimeline, addStatus } from '../actions/statuses'; +import { setAccessToken } from '../actions/meta'; +import PureRenderMixin from 'react-addons-pure-render-mixin'; const store = configureStore(); const Root = React.createClass({ + propTypes: { + token: React.PropTypes.string.isRequired, + timelines: React.PropTypes.array + }, + + mixins: [PureRenderMixin], + componentWillMount() { + store.dispatch(setAccessToken(this.props.token)); + for (var timelineType in this.props.timelines) { if (this.props.timelines.hasOwnProperty(timelineType)) { store.dispatch(setTimeline(timelineType, JSON.parse(this.props.timelines[timelineType]))); diff --git a/app/assets/javascripts/components/reducers/index.jsx b/app/assets/javascripts/components/reducers/index.jsx index c7e858f38..96c026c8c 100644 --- a/app/assets/javascripts/components/reducers/index.jsx +++ b/app/assets/javascripts/components/reducers/index.jsx @@ -1,6 +1,8 @@ import { combineReducers } from 'redux-immutable'; import statuses from './statuses'; +import meta from './meta'; export default combineReducers({ - statuses + statuses, + meta }); diff --git a/app/assets/javascripts/components/reducers/meta.jsx b/app/assets/javascripts/components/reducers/meta.jsx new file mode 100644 index 000000000..401be435d --- /dev/null +++ b/app/assets/javascripts/components/reducers/meta.jsx @@ -0,0 +1,13 @@ +import { SET_ACCESS_TOKEN } from '../actions/meta'; +import Immutable from 'immutable'; + +const initialState = Immutable.Map(); + +export default function meta(state = initialState, action) { + switch(action.type) { + case SET_ACCESS_TOKEN: + return state.set('access_token', action.token); + default: + return state; + } +} -- cgit