From 499beb4484031703f029511787163e3a5bb6e47a Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Wed, 7 Sep 2016 18:17:15 +0200 Subject: UI for uploading media attachments (and cancelling them) Mostly resolves #8, though attachments are still not displayed in public view --- app/assets/images/void.png | Bin 0 -> 180 bytes .../javascripts/components/actions/compose.jsx | 76 ++++++++++++++++++--- .../javascripts/components/components/button.jsx | 10 +-- .../components/components/compose_form.jsx | 3 +- .../javascripts/components/components/frontend.jsx | 2 + .../components/components/upload_button.jsx | 37 ++++++++++ .../components/components/upload_form.jsx | 41 +++++++++++ .../containers/upload_form_container.jsx | 25 +++++++ .../javascripts/components/reducers/compose.jsx | 26 ++++++- app/assets/stylesheets/components.scss | 17 ++++- app/services/post_status_service.rb | 2 +- app/views/api/media/create.rabl | 1 + 12 files changed, 222 insertions(+), 18 deletions(-) create mode 100644 app/assets/images/void.png create mode 100644 app/assets/javascripts/components/components/upload_button.jsx create mode 100644 app/assets/javascripts/components/components/upload_form.jsx create mode 100644 app/assets/javascripts/components/containers/upload_form_container.jsx (limited to 'app') diff --git a/app/assets/images/void.png b/app/assets/images/void.png new file mode 100644 index 000000000..7eeee75af Binary files /dev/null and b/app/assets/images/void.png differ diff --git a/app/assets/javascripts/components/actions/compose.jsx b/app/assets/javascripts/components/actions/compose.jsx index 4954f0f5c..a107b3352 100644 --- a/app/assets/javascripts/components/actions/compose.jsx +++ b/app/assets/javascripts/components/actions/compose.jsx @@ -1,12 +1,18 @@ import api from '../api' -export const COMPOSE_CHANGE = 'COMPOSE_CHANGE'; -export const COMPOSE_SUBMIT = 'COMPOSE_SUBMIT'; -export const COMPOSE_SUBMIT_REQUEST = 'COMPOSE_SUBMIT_REQUEST'; -export const COMPOSE_SUBMIT_SUCCESS = 'COMPOSE_SUBMIT_SUCCESS'; -export const COMPOSE_SUBMIT_FAIL = 'COMPOSE_SUBMIT_FAIL'; -export const COMPOSE_REPLY = 'COMPOSE_REPLY'; -export const COMPOSE_REPLY_CANCEL = 'COMPOSE_REPLY_CANCEL'; +export const COMPOSE_CHANGE = 'COMPOSE_CHANGE'; +export const COMPOSE_SUBMIT = 'COMPOSE_SUBMIT'; +export const COMPOSE_SUBMIT_REQUEST = 'COMPOSE_SUBMIT_REQUEST'; +export const COMPOSE_SUBMIT_SUCCESS = 'COMPOSE_SUBMIT_SUCCESS'; +export const COMPOSE_SUBMIT_FAIL = 'COMPOSE_SUBMIT_FAIL'; +export const COMPOSE_REPLY = 'COMPOSE_REPLY'; +export const COMPOSE_REPLY_CANCEL = 'COMPOSE_REPLY_CANCEL'; +export const COMPOSE_UPLOAD = 'COMPOSE_UPLOAD'; +export const COMPOSE_UPLOAD_REQUEST = 'COMPOSE_UPLOAD_REQUEST'; +export const COMPOSE_UPLOAD_SUCCESS = 'COMPOSE_UPLOAD_SUCCESS'; +export const COMPOSE_UPLOAD_FAIL = 'COMPOSE_UPLOAD_FAIL'; +export const COMPOSE_UPLOAD_PROGRESS = 'COMPOSE_UPLOAD_PROGRESS'; +export const COMPOSE_UPLOAD_UNDO = 'COMPOSE_UPLOAD_UNDO'; export function changeCompose(text) { return { @@ -34,7 +40,8 @@ export function submitCompose() { api(getState).post('/api/statuses', { status: getState().getIn(['compose', 'text'], ''), - in_reply_to_id: getState().getIn(['compose', 'in_reply_to'], null) + in_reply_to_id: getState().getIn(['compose', 'in_reply_to'], null), + media_ids: getState().getIn(['compose', 'media_attachments']).map(item => item.get('id')) }).then(function (response) { dispatch(submitComposeSuccess(response.data)); }).catch(function (error) { @@ -63,3 +70,56 @@ export function submitComposeFail(error) { }; } +export function uploadCompose(files) { + return function (dispatch, getState) { + dispatch(uploadComposeRequest()); + + let data = new FormData(); + data.append('file', files[0]); + + api(getState).post('/api/media', data, { + onUploadProgress: function (e) { + dispatch(uploadComposeProgress(e.loaded, e.total)); + } + }).then(function (response) { + dispatch(uploadComposeSuccess(response.data)); + }).catch(function (error) { + dispatch(uploadComposeFail(error)); + }); + }; +} + +export function uploadComposeRequest() { + return { + type: COMPOSE_UPLOAD_REQUEST + }; +} + +export function uploadComposeProgress(loaded, total) { + return { + type: COMPOSE_UPLOAD_PROGRESS, + loaded: loaded, + total: total + }; +} + +export function uploadComposeSuccess(media) { + return { + type: COMPOSE_UPLOAD_SUCCESS, + media: media + }; +} + +export function uploadComposeFail(error) { + return { + type: COMPOSE_UPLOAD_FAIL, + error: error + }; +} + +export function undoUploadCompose(media_id) { + return { + type: COMPOSE_UPLOAD_UNDO, + media_id: media_id + }; +} diff --git a/app/assets/javascripts/components/components/button.jsx b/app/assets/javascripts/components/components/button.jsx index 1a55dd879..6f7ace323 100644 --- a/app/assets/javascripts/components/components/button.jsx +++ b/app/assets/javascripts/components/components/button.jsx @@ -3,9 +3,11 @@ import PureRenderMixin from 'react-addons-pure-render-mixin'; const Button = React.createClass({ propTypes: { - text: React.PropTypes.string.isRequired, + text: React.PropTypes.string, onClick: React.PropTypes.func, - disabled: React.PropTypes.bool + disabled: React.PropTypes.bool, + block: React.PropTypes.bool, + secondary: React.PropTypes.bool }, mixins: [PureRenderMixin], @@ -18,8 +20,8 @@ const Button = React.createClass({ render () { return ( - ); } diff --git a/app/assets/javascripts/components/components/compose_form.jsx b/app/assets/javascripts/components/components/compose_form.jsx index 641412012..40d9b7773 100644 --- a/app/assets/javascripts/components/components/compose_form.jsx +++ b/app/assets/javascripts/components/components/compose_form.jsx @@ -3,6 +3,7 @@ import Button from './button'; import PureRenderMixin from 'react-addons-pure-render-mixin'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ReplyIndicator from './reply_indicator'; +import UploadButton from './upload_button'; const ComposeForm = React.createClass({ @@ -39,7 +40,7 @@ const ComposeForm = React.createClass({ } return ( -
+
{replyArea}