diff options
19 files changed, 85 insertions, 229 deletions
diff --git a/app/assets/javascripts/components/actions/follow.jsx b/app/assets/javascripts/components/actions/follow.jsx deleted file mode 100644 index 8eb440789..000000000 --- a/app/assets/javascripts/components/actions/follow.jsx +++ /dev/null @@ -1,48 +0,0 @@ -import api from '../api' - -export const FOLLOW_CHANGE = 'FOLLOW_CHANGE'; -export const FOLLOW_SUBMIT_REQUEST = 'FOLLOW_SUBMIT_REQUEST'; -export const FOLLOW_SUBMIT_SUCCESS = 'FOLLOW_SUBMIT_SUCCESS'; -export const FOLLOW_SUBMIT_FAIL = 'FOLLOW_SUBMIT_FAIL'; - -export function changeFollow(text) { - return { - type: FOLLOW_CHANGE, - text: text - }; -}; - -export function submitFollow(router) { - return function (dispatch, getState) { - dispatch(submitFollowRequest()); - - api(getState).post('/api/v1/follows', { - uri: getState().getIn(['follow', 'text']) - }).then(function (response) { - dispatch(submitFollowSuccess(response.data)); - router.push(`/accounts/${response.data.id}`); - }).catch(function (error) { - dispatch(submitFollowFail(error)); - }); - }; -}; - -export function submitFollowRequest() { - return { - type: FOLLOW_SUBMIT_REQUEST - }; -}; - -export function submitFollowSuccess(account) { - return { - type: FOLLOW_SUBMIT_SUCCESS, - account: account - }; -}; - -export function submitFollowFail(error) { - return { - type: FOLLOW_SUBMIT_FAIL, - error: error - }; -}; diff --git a/app/assets/javascripts/components/features/ui/components/character_counter.jsx b/app/assets/javascripts/components/features/compose/components/character_counter.jsx index f0c1b7c8d..f0c1b7c8d 100644 --- a/app/assets/javascripts/components/features/ui/components/character_counter.jsx +++ b/app/assets/javascripts/components/features/compose/components/character_counter.jsx diff --git a/app/assets/javascripts/components/features/ui/components/compose_form.jsx b/app/assets/javascripts/components/features/compose/components/compose_form.jsx index aef228d58..ead8e0008 100644 --- a/app/assets/javascripts/components/features/ui/components/compose_form.jsx +++ b/app/assets/javascripts/components/features/compose/components/compose_form.jsx @@ -7,6 +7,7 @@ import UploadButton from './upload_button'; import Autosuggest from 'react-autosuggest'; import AutosuggestAccountContainer from '../../compose/containers/autosuggest_account_container'; import { debounce } from 'react-decoration'; +import UploadButtonContainer from '../containers/upload_button_container'; const getTokenForSuggestions = (str, caretPosition) => { let word; @@ -168,6 +169,7 @@ const ComposeForm = React.createClass({ <div style={{ marginTop: '10px', overflow: 'hidden' }}> <div style={{ float: 'right' }}><Button text='Publish' onClick={this.handleSubmit} disabled={disabled} /></div> <div style={{ float: 'right', marginRight: '16px', lineHeight: '36px' }}><CharacterCounter max={500} text={this.props.text} /></div> + <UploadButtonContainer style={{ paddingTop: '4px' }} /> </div> </div> ); diff --git a/app/assets/javascripts/components/features/ui/components/drawer.jsx b/app/assets/javascripts/components/features/compose/components/drawer.jsx index d31d0e453..d31d0e453 100644 --- a/app/assets/javascripts/components/features/ui/components/drawer.jsx +++ b/app/assets/javascripts/components/features/compose/components/drawer.jsx diff --git a/app/assets/javascripts/components/features/ui/components/navigation_bar.jsx b/app/assets/javascripts/components/features/compose/components/navigation_bar.jsx index d2dae141f..d2dae141f 100644 --- a/app/assets/javascripts/components/features/ui/components/navigation_bar.jsx +++ b/app/assets/javascripts/components/features/compose/components/navigation_bar.jsx diff --git a/app/assets/javascripts/components/features/ui/components/reply_indicator.jsx b/app/assets/javascripts/components/features/compose/components/reply_indicator.jsx index 6298d3de9..6298d3de9 100644 --- a/app/assets/javascripts/components/features/ui/components/reply_indicator.jsx +++ b/app/assets/javascripts/components/features/compose/components/reply_indicator.jsx diff --git a/app/assets/javascripts/components/features/ui/components/upload_button.jsx b/app/assets/javascripts/components/features/compose/components/upload_button.jsx index 9e9fc7298..8289e0a09 100644 --- a/app/assets/javascripts/components/features/ui/components/upload_button.jsx +++ b/app/assets/javascripts/components/features/compose/components/upload_button.jsx @@ -1,11 +1,12 @@ import PureRenderMixin from 'react-addons-pure-render-mixin'; -import Button from '../../../components/button'; +import IconButton from '../../../components/icon_button'; const UploadButton = React.createClass({ propTypes: { disabled: React.PropTypes.bool, - onSelectFile: React.PropTypes.func.isRequired + onSelectFile: React.PropTypes.func.isRequired, + style: React.PropTypes.object }, mixins: [PureRenderMixin], @@ -17,17 +18,18 @@ const UploadButton = React.createClass({ }, handleClick () { - this.refs.fileElement.click(); + this.fileElement.click(); + }, + + setRef (c) { + this.fileElement = c; }, render () { return ( - <div> - <Button disabled={this.props.disabled} onClick={this.handleClick} block={true}> - <i className='fa fa-fw fa-photo' /> Add media - </Button> - - <input ref='fileElement' type='file' multiple={false} onChange={this.handleChange} disabled={this.props.disabled} style={{ display: 'none' }} /> + <div style={this.props.style}> + <IconButton icon='photo' title='Add media' disabled={this.props.disabled} onClick={this.handleClick} size={24} /> + <input ref={this.setRef} type='file' multiple={false} onChange={this.handleChange} disabled={this.props.disabled} style={{ display: 'none' }} /> </div> ); } diff --git a/app/assets/javascripts/components/features/compose/components/upload_form.jsx b/app/assets/javascripts/components/features/compose/components/upload_form.jsx new file mode 100644 index 000000000..751f76ab7 --- /dev/null +++ b/app/assets/javascripts/components/features/compose/components/upload_form.jsx @@ -0,0 +1,34 @@ +import PureRenderMixin from 'react-addons-pure-render-mixin'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import IconButton from '../../../components/icon_button'; + +const UploadForm = React.createClass({ + + propTypes: { + media: ImmutablePropTypes.list.isRequired, + is_uploading: React.PropTypes.bool, + onSelectFile: React.PropTypes.func.isRequired, + onRemoveFile: React.PropTypes.func.isRequired + }, + + mixins: [PureRenderMixin], + + render () { + const uploads = this.props.media.map(attachment => ( + <div key={attachment.get('id')} style={{ borderRadius: '4px', marginBottom: '10px' }} className='transparent-background'> + <div style={{ width: '100%', height: '100px', borderRadius: '4px', background: `url(${attachment.get('preview_url')}) no-repeat center`, backgroundSize: 'cover' }}> + <IconButton icon='times' title='Undo' size={36} onClick={this.props.onRemoveFile.bind(this, attachment.get('id'))} /> + </div> + </div> + )); + + return ( + <div style={{ marginBottom: '20px', padding: '10px', overflow: 'hidden' }}> + {uploads} + </div> + ); + } + +}); + +export default UploadForm; diff --git a/app/assets/javascripts/components/features/ui/containers/compose_form_container.jsx b/app/assets/javascripts/components/features/compose/containers/compose_form_container.jsx index 87bcd6b99..87bcd6b99 100644 --- a/app/assets/javascripts/components/features/ui/containers/compose_form_container.jsx +++ b/app/assets/javascripts/components/features/compose/containers/compose_form_container.jsx diff --git a/app/assets/javascripts/components/features/ui/containers/navigation_container.jsx b/app/assets/javascripts/components/features/compose/containers/navigation_container.jsx index 51e2513d8..51e2513d8 100644 --- a/app/assets/javascripts/components/features/ui/containers/navigation_container.jsx +++ b/app/assets/javascripts/components/features/compose/containers/navigation_container.jsx diff --git a/app/assets/javascripts/components/features/compose/containers/upload_button_container.jsx b/app/assets/javascripts/components/features/compose/containers/upload_button_container.jsx new file mode 100644 index 000000000..4154b0737 --- /dev/null +++ b/app/assets/javascripts/components/features/compose/containers/upload_button_container.jsx @@ -0,0 +1,17 @@ +import { connect } from 'react-redux'; +import UploadButton from '../components/upload_button'; +import { uploadCompose } from '../../../actions/compose'; + +const mapStateToProps = state => ({ + disabled: state.getIn(['compose', 'is_uploading']) || (state.getIn(['compose', 'media_attachments']).size > 3 || state.getIn(['compose', 'media_attachments']).some(m => m.get('type') === 'video')), +}); + +const mapDispatchToProps = dispatch => ({ + + onSelectFile (files) { + dispatch(uploadCompose(files)); + } + +}); + +export default connect(mapStateToProps, mapDispatchToProps)(UploadButton); diff --git a/app/assets/javascripts/components/features/compose/containers/upload_form_container.jsx b/app/assets/javascripts/components/features/compose/containers/upload_form_container.jsx new file mode 100644 index 000000000..a6a202e17 --- /dev/null +++ b/app/assets/javascripts/components/features/compose/containers/upload_form_container.jsx @@ -0,0 +1,17 @@ +import { connect } from 'react-redux'; +import UploadForm from '../components/upload_form'; +import { undoUploadCompose } from '../../../actions/compose'; + +const mapStateToProps = (state, props) => ({ + media: state.getIn(['compose', 'media_attachments']), +}); + +const mapDispatchToProps = dispatch => ({ + + onRemoveFile (media_id) { + dispatch(undoUploadCompose(media_id)); + } + +}); + +export default connect(mapStateToProps, mapDispatchToProps)(UploadForm); diff --git a/app/assets/javascripts/components/features/compose/index.jsx b/app/assets/javascripts/components/features/compose/index.jsx index 260f67034..a50118bef 100644 --- a/app/assets/javascripts/components/features/compose/index.jsx +++ b/app/assets/javascripts/components/features/compose/index.jsx @@ -1,8 +1,7 @@ -import Drawer from '../ui/components/drawer'; -import ComposeFormContainer from '../ui/containers/compose_form_container'; -import FollowFormContainer from '../ui/containers/follow_form_container'; -import UploadFormContainer from '../ui/containers/upload_form_container'; -import NavigationContainer from '../ui/containers/navigation_container'; +import Drawer from './components/drawer'; +import ComposeFormContainer from './containers/compose_form_container'; +import UploadFormContainer from './containers/upload_form_container'; +import NavigationContainer from './containers/navigation_container'; import PureRenderMixin from 'react-addons-pure-render-mixin'; import SuggestionsContainer from './containers/suggestions_container'; import SearchContainer from './containers/search_container'; diff --git a/app/assets/javascripts/components/features/ui/components/follow_form.jsx b/app/assets/javascripts/components/features/ui/components/follow_form.jsx deleted file mode 100644 index 4ba5dfc25..000000000 --- a/app/assets/javascripts/components/features/ui/components/follow_form.jsx +++ /dev/null @@ -1,44 +0,0 @@ -import IconButton from '../../../components/icon_button'; -import PureRenderMixin from 'react-addons-pure-render-mixin'; - -const FollowForm = React.createClass({ - - contextTypes: { - router: React.PropTypes.object - }, - - propTypes: { - text: React.PropTypes.string.isRequired, - is_submitting: React.PropTypes.bool, - onChange: React.PropTypes.func.isRequired, - onSubmit: React.PropTypes.func.isRequired - }, - - mixins: [PureRenderMixin], - - handleChange (e) { - this.props.onChange(e.target.value); - }, - - handleKeyUp (e) { - if (e.keyCode === 13) { - this.handleSubmit(); - } - }, - - handleSubmit () { - this.props.onSubmit(this.context.router); - }, - - render () { - return ( - <div style={{ display: 'flex', lineHeight: '20px', padding: '10px', background: '#373b4a' }}> - <input autoComplete='off' type='text' disabled={this.props.is_submitting} placeholder='username@domain' value={this.props.text} onKeyUp={this.handleKeyUp} onChange={this.handleChange} className='follow-form__input' style={{ flex: '1 1 auto', boxSizing: 'border-box', display: 'block', border: 'none', padding: '10px', fontFamily: 'Roboto', color: '#282c37', fontSize: '14px', margin: '0' }} /> - <div style={{ padding: '10px', paddingRight: '0' }}><IconButton title='Follow' size={20} icon='user-plus' onClick={this.handleSubmit} disabled={this.props.is_submitting} /></div> - </div> - ); - } - -}); - -export default FollowForm; diff --git a/app/assets/javascripts/components/features/ui/components/upload_form.jsx b/app/assets/javascripts/components/features/ui/components/upload_form.jsx deleted file mode 100644 index d584e9ab7..000000000 --- a/app/assets/javascripts/components/features/ui/components/upload_form.jsx +++ /dev/null @@ -1,43 +0,0 @@ -import PureRenderMixin from 'react-addons-pure-render-mixin'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import UploadButton from './upload_button'; -import IconButton from '../../../components/icon_button'; - -const UploadForm = React.createClass({ - - propTypes: { - media: ImmutablePropTypes.list.isRequired, - is_uploading: React.PropTypes.bool, - onSelectFile: React.PropTypes.func.isRequired, - onRemoveFile: React.PropTypes.func.isRequired - }, - - mixins: [PureRenderMixin], - - render () { - let uploads = this.props.media.map(function (attachment) { - return ( - <div key={attachment.get('id')} style={{ borderRadius: '4px', marginBottom: '10px' }} className='transparent-background'> - <div style={{ width: '100%', height: '100px', borderRadius: '4px', background: `url(${attachment.get('preview_url')}) no-repeat center`, backgroundSize: 'cover' }}> - <IconButton icon='times' title='Undo' size={36} onClick={() => this.props.onRemoveFile(attachment.get('id'))} /> - </div> - </div> - ); - }.bind(this)); - - const noMoreAllowed = (this.props.media.some(m => m.get('type') === 'video')) || (this.props.media.size > 3); - - return ( - <div style={{ marginBottom: '20px', padding: '10px', paddingTop: '0' }}> - <UploadButton onSelectFile={this.props.onSelectFile} disabled={this.props.is_uploading || noMoreAllowed } /> - - <div style={{ marginTop: '10px', overflow: 'hidden' }}> - {uploads} - </div> - </div> - ); - } - -}); - -export default UploadForm; diff --git a/app/assets/javascripts/components/features/ui/containers/follow_form_container.jsx b/app/assets/javascripts/components/features/ui/containers/follow_form_container.jsx deleted file mode 100644 index 05cfb7c1d..000000000 --- a/app/assets/javascripts/components/features/ui/containers/follow_form_container.jsx +++ /dev/null @@ -1,24 +0,0 @@ -import { connect } from 'react-redux'; -import FollowForm from '../components/follow_form'; -import { changeFollow, submitFollow } from '../../../actions/follow'; - -const mapStateToProps = function (state, props) { - return { - text: state.getIn(['follow', 'text']), - is_submitting: state.getIn(['follow', 'is_submitting']) - }; -}; - -const mapDispatchToProps = function (dispatch) { - return { - onChange: function (text) { - dispatch(changeFollow(text)); - }, - - onSubmit: function (router) { - dispatch(submitFollow(router)); - } - } -}; - -export default connect(mapStateToProps, mapDispatchToProps)(FollowForm); diff --git a/app/assets/javascripts/components/features/ui/containers/upload_form_container.jsx b/app/assets/javascripts/components/features/ui/containers/upload_form_container.jsx deleted file mode 100644 index 6554f944f..000000000 --- a/app/assets/javascripts/components/features/ui/containers/upload_form_container.jsx +++ /dev/null @@ -1,25 +0,0 @@ -import { connect } from 'react-redux'; -import UploadForm from '../components/upload_form'; -import { uploadCompose, undoUploadCompose } from '../../../actions/compose'; - -const mapStateToProps = function (state, props) { - return { - media: state.getIn(['compose', 'media_attachments']), - progress: state.getIn(['compose', 'progress']), - is_uploading: state.getIn(['compose', 'is_uploading']) - }; -}; - -const mapDispatchToProps = function (dispatch) { - return { - onSelectFile: function (files) { - dispatch(uploadCompose(files)); - }, - - onRemoveFile: function (media_id) { - dispatch(undoUploadCompose(media_id)); - } - } -}; - -export default connect(mapStateToProps, mapDispatchToProps)(UploadForm); diff --git a/app/assets/javascripts/components/reducers/follow.jsx b/app/assets/javascripts/components/reducers/follow.jsx deleted file mode 100644 index ed6e8e0ef..000000000 --- a/app/assets/javascripts/components/reducers/follow.jsx +++ /dev/null @@ -1,29 +0,0 @@ -import { - FOLLOW_CHANGE, - FOLLOW_SUBMIT_REQUEST, - FOLLOW_SUBMIT_SUCCESS, - FOLLOW_SUBMIT_FAIL -} from '../actions/follow'; -import Immutable from 'immutable'; - -const initialState = Immutable.Map({ - text: '', - is_submitting: false -}); - -export default function follow(state = initialState, action) { - switch(action.type) { - case FOLLOW_CHANGE: - return state.set('text', action.text); - case FOLLOW_SUBMIT_REQUEST: - return state.set('is_submitting', true); - case FOLLOW_SUBMIT_SUCCESS: - return state.withMutations(map => { - map.set('text', '').set('is_submitting', false); - }); - case FOLLOW_SUBMIT_FAIL: - return state.set('is_submitting', false); - default: - return state; - } -}; diff --git a/app/assets/javascripts/components/reducers/index.jsx b/app/assets/javascripts/components/reducers/index.jsx index e2203cc1a..1e015cf74 100644 --- a/app/assets/javascripts/components/reducers/index.jsx +++ b/app/assets/javascripts/components/reducers/index.jsx @@ -2,7 +2,6 @@ import { combineReducers } from 'redux-immutable'; import timelines from './timelines'; import meta from './meta'; import compose from './compose'; -import follow from './follow'; import notifications from './notifications'; import { loadingBarReducer } from 'react-redux-loading-bar'; import modal from './modal'; @@ -16,7 +15,6 @@ export default combineReducers({ timelines, meta, compose, - follow, notifications, loadingBar: loadingBarReducer, modal, |