diff options
Diffstat (limited to 'app/assets/javascripts/components/features/compose')
14 files changed, 229 insertions, 206 deletions
diff --git a/app/assets/javascripts/components/features/compose/components/character_counter.jsx b/app/assets/javascripts/components/features/compose/components/character_counter.jsx index fc64f94a5..b1e74b4de 100644 --- a/app/assets/javascripts/components/features/compose/components/character_counter.jsx +++ b/app/assets/javascripts/components/features/compose/components/character_counter.jsx @@ -1,20 +1,13 @@ -import PureRenderMixin from 'react-addons-pure-render-mixin'; +import PropTypes from 'prop-types'; -const CharacterCounter = React.createClass({ - - propTypes: { - text: React.PropTypes.string.isRequired, - max: React.PropTypes.number.isRequired - }, - - mixins: [PureRenderMixin], +class CharacterCounter extends React.PureComponent { checkRemainingText (diff) { if (diff <= 0) { return <span style={{ fontSize: '16px', cursor: 'default', color: '#ff5050' }}>{diff}</span>; } return <span style={{ fontSize: '16px', cursor: 'default' }}>{diff}</span>; - }, + } render () { const diff = this.props.max - this.props.text.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, "_").length; @@ -22,6 +15,11 @@ const CharacterCounter = React.createClass({ return this.checkRemainingText(diff); } -}); +} + +CharacterCounter.propTypes = { + text: PropTypes.string.isRequired, + max: PropTypes.number.isRequired +} export default CharacterCounter; diff --git a/app/assets/javascripts/components/features/compose/components/compose_form.jsx b/app/assets/javascripts/components/features/compose/components/compose_form.jsx index e6e68351e..b8e8ed5ef 100644 --- a/app/assets/javascripts/components/features/compose/components/compose_form.jsx +++ b/app/assets/javascripts/components/features/compose/components/compose_form.jsx @@ -1,7 +1,7 @@ import CharacterCounter from './character_counter'; import Button from '../../../components/button'; -import PureRenderMixin from 'react-addons-pure-render-mixin'; import ImmutablePropTypes from 'react-immutable-proptypes'; +import PropTypes from 'prop-types'; import ReplyIndicatorContainer from '../containers/reply_indicator_container'; import AutosuggestTextarea from '../../../components/autosuggest_textarea'; import { debounce } from 'react-decoration'; @@ -22,67 +22,53 @@ const messages = defineMessages({ publish: { id: 'compose_form.publish', defaultMessage: 'Toot' } }); -const ComposeForm = React.createClass({ - - propTypes: { - intl: React.PropTypes.object.isRequired, - text: React.PropTypes.string.isRequired, - suggestion_token: React.PropTypes.string, - suggestions: ImmutablePropTypes.list, - spoiler: React.PropTypes.bool, - privacy: React.PropTypes.string, - spoiler_text: React.PropTypes.string, - focusDate: React.PropTypes.instanceOf(Date), - preselectDate: React.PropTypes.instanceOf(Date), - is_submitting: React.PropTypes.bool, - is_uploading: React.PropTypes.bool, - me: React.PropTypes.number, - needsPrivacyWarning: React.PropTypes.bool, - mentionedDomains: React.PropTypes.array.isRequired, - onChange: React.PropTypes.func.isRequired, - onSubmit: React.PropTypes.func.isRequired, - onClearSuggestions: React.PropTypes.func.isRequired, - onFetchSuggestions: React.PropTypes.func.isRequired, - onSuggestionSelected: React.PropTypes.func.isRequired, - onChangeSpoilerText: React.PropTypes.func.isRequired, - onPaste: React.PropTypes.func.isRequired, - onPickEmoji: React.PropTypes.func.isRequired - }, - - mixins: [PureRenderMixin], +class ComposeForm extends React.PureComponent { + + constructor (props, context) { + super(props, context); + this.handleChange = this.handleChange.bind(this); + this.handleKeyDown = this.handleKeyDown.bind(this); + this.handleSubmit = this.handleSubmit.bind(this); + this.onSuggestionsClearRequested = this.onSuggestionsClearRequested.bind(this); + this.onSuggestionsFetchRequested = this.onSuggestionsFetchRequested.bind(this); + this.onSuggestionSelected = this.onSuggestionSelected.bind(this); + this.handleChangeSpoilerText = this.handleChangeSpoilerText.bind(this); + this.setAutosuggestTextarea = this.setAutosuggestTextarea.bind(this); + this.handleEmojiPick = this.handleEmojiPick.bind(this); + } handleChange (e) { this.props.onChange(e.target.value); - }, + } handleKeyDown (e) { if (e.keyCode === 13 && (e.ctrlKey || e.metaKey)) { this.props.onSubmit(); } - }, + } handleSubmit () { this.autosuggestTextarea.textarea.style.height = "auto"; this.props.onSubmit(); - }, + } onSuggestionsClearRequested () { this.props.onClearSuggestions(); - }, + } @debounce(500) onSuggestionsFetchRequested (token) { this.props.onFetchSuggestions(token); - }, + } onSuggestionSelected (tokenStart, token, value) { this._restoreCaret = null; this.props.onSuggestionSelected(tokenStart, token, value); - }, + } handleChangeSpoilerText (e) { this.props.onChangeSpoilerText(e.target.value); - }, + } componentWillReceiveProps (nextProps) { // If this is the update where we've finished uploading, @@ -90,7 +76,7 @@ const ComposeForm = React.createClass({ if (!nextProps.is_uploading && this.props.is_uploading) { this._restoreCaret = this.autosuggestTextarea.textarea.selectionStart; } - }, + } componentDidUpdate (prevProps) { // This statement does several things: @@ -117,17 +103,17 @@ const ComposeForm = React.createClass({ this.autosuggestTextarea.textarea.setSelectionRange(selectionStart, selectionEnd); this.autosuggestTextarea.textarea.focus(); } - }, + } setAutosuggestTextarea (c) { this.autosuggestTextarea = c; - }, + } handleEmojiPick (data) { const position = this.autosuggestTextarea.textarea.selectionStart; this._restoreCaret = position + data.shortname.length + 1; this.props.onPickEmoji(position, data); - }, + } render () { const { intl, needsPrivacyWarning, mentionedDomains, onPaste } = this.props; @@ -207,6 +193,31 @@ const ComposeForm = React.createClass({ ); } -}); +} + +ComposeForm.propTypes = { + intl: PropTypes.object.isRequired, + text: PropTypes.string.isRequired, + suggestion_token: PropTypes.string, + suggestions: ImmutablePropTypes.list, + spoiler: PropTypes.bool, + privacy: PropTypes.string, + spoiler_text: PropTypes.string, + focusDate: PropTypes.instanceOf(Date), + preselectDate: PropTypes.instanceOf(Date), + is_submitting: PropTypes.bool, + is_uploading: PropTypes.bool, + me: PropTypes.number, + needsPrivacyWarning: PropTypes.bool, + mentionedDomains: PropTypes.array.isRequired, + onChange: PropTypes.func.isRequired, + onSubmit: PropTypes.func.isRequired, + onClearSuggestions: PropTypes.func.isRequired, + onFetchSuggestions: PropTypes.func.isRequired, + onSuggestionSelected: PropTypes.func.isRequired, + onChangeSpoilerText: PropTypes.func.isRequired, + onPaste: PropTypes.func.isRequired, + onPickEmoji: PropTypes.func.isRequired +}; export default injectIntl(ComposeForm); diff --git a/app/assets/javascripts/components/features/compose/components/emoji_picker_dropdown.jsx b/app/assets/javascripts/components/features/compose/components/emoji_picker_dropdown.jsx index 36e97df41..77117b7e4 100644 --- a/app/assets/javascripts/components/features/compose/components/emoji_picker_dropdown.jsx +++ b/app/assets/javascripts/components/features/compose/components/emoji_picker_dropdown.jsx @@ -1,6 +1,6 @@ import Dropdown, { DropdownTrigger, DropdownContent } from 'react-simple-dropdown'; import EmojiPicker from 'emojione-picker'; -import PureRenderMixin from 'react-addons-pure-render-mixin'; +import PropTypes from 'prop-types'; import { defineMessages, injectIntl } from 'react-intl'; const messages = defineMessages({ @@ -19,23 +19,22 @@ const style = { top: '5px' }; -const EmojiPickerDropdown = React.createClass({ +class EmojiPickerDropdown extends React.PureComponent { - propTypes: { - intl: React.PropTypes.object.isRequired, - onPickEmoji: React.PropTypes.func.isRequired - }, - - mixins: [PureRenderMixin], + constructor (props, context) { + super(props, context); + this.setRef = this.setRef.bind(this); + this.handleChange = this.handleChange.bind(this); + } setRef (c) { this.dropdown = c; - }, + } handleChange (data) { this.dropdown.hide(); this.props.onPickEmoji(data); - }, + } render () { const { intl } = this.props; @@ -53,6 +52,11 @@ const EmojiPickerDropdown = React.createClass({ ); } -}); +} + +EmojiPickerDropdown.propTypes = { + intl: PropTypes.object.isRequired, + onPickEmoji: PropTypes.func.isRequired +}; export default injectIntl(EmojiPickerDropdown); diff --git a/app/assets/javascripts/components/features/compose/components/navigation_bar.jsx b/app/assets/javascripts/components/features/compose/components/navigation_bar.jsx index 1a748a23c..f4c45278c 100644 --- a/app/assets/javascripts/components/features/compose/components/navigation_bar.jsx +++ b/app/assets/javascripts/components/features/compose/components/navigation_bar.jsx @@ -1,4 +1,3 @@ -import PureRenderMixin from 'react-addons-pure-render-mixin'; import ImmutablePropTypes from 'react-immutable-proptypes'; import Avatar from '../../../components/avatar'; import IconButton from '../../../components/icon_button'; @@ -7,12 +6,7 @@ import Permalink from '../../../components/permalink'; import { FormattedMessage } from 'react-intl'; import { Link } from 'react-router'; -const NavigationBar = React.createClass({ - propTypes: { - account: ImmutablePropTypes.map.isRequired - }, - - mixins: [PureRenderMixin], +class NavigationBar extends React.PureComponent { render () { return ( @@ -27,6 +21,10 @@ const NavigationBar = React.createClass({ ); } -}); +} + +NavigationBar.propTypes = { + account: ImmutablePropTypes.map.isRequired +}; export default NavigationBar; diff --git a/app/assets/javascripts/components/features/compose/components/privacy_dropdown.jsx b/app/assets/javascripts/components/features/compose/components/privacy_dropdown.jsx index de8942d4d..6a80cf7a2 100644 --- a/app/assets/javascripts/components/features/compose/components/privacy_dropdown.jsx +++ b/app/assets/javascripts/components/features/compose/components/privacy_dropdown.jsx @@ -1,4 +1,4 @@ -import PureRenderMixin from 'react-addons-pure-render-mixin'; +import PropTypes from 'prop-types'; import { injectIntl, defineMessages } from 'react-intl'; import IconButton from '../../../components/icon_button'; @@ -19,51 +19,48 @@ const iconStyle = { height: null }; -const PrivacyDropdown = React.createClass({ +class PrivacyDropdown extends React.PureComponent { - propTypes: { - value: React.PropTypes.string.isRequired, - onChange: React.PropTypes.func.isRequired, - intl: React.PropTypes.object.isRequired - }, - - getInitialState () { - return { + constructor (props, context) { + super(props, context); + this.state = { open: false }; - }, - - mixins: [PureRenderMixin], + this.handleToggle = this.handleToggle.bind(this); + this.handleClick = this.handleClick.bind(this); + this.onGlobalClick = this.onGlobalClick.bind(this); + this.setRef = this.setRef.bind(this); + } handleToggle () { this.setState({ open: !this.state.open }); - }, + } handleClick (value, e) { e.preventDefault(); this.setState({ open: false }); this.props.onChange(value); - }, + } onGlobalClick (e) { if (e.target !== this.node && !this.node.contains(e.target) && this.state.open) { this.setState({ open: false }); } - }, + } componentDidMount () { window.addEventListener('click', this.onGlobalClick); window.addEventListener('touchstart', this.onGlobalClick); - }, + } componentWillUnmount () { window.removeEventListener('click', this.onGlobalClick); window.removeEventListener('touchstart', this.onGlobalClick); - }, + } setRef (c) { this.node = c; - }, + } render () { const { value, onChange, intl } = this.props; @@ -96,6 +93,12 @@ const PrivacyDropdown = React.createClass({ ); } -}); +} + +PrivacyDropdown.propTypes = { + value: PropTypes.string.isRequired, + onChange: PropTypes.func.isRequired, + intl: PropTypes.object.isRequired +}; export default injectIntl(PrivacyDropdown); diff --git a/app/assets/javascripts/components/features/compose/components/reply_indicator.jsx b/app/assets/javascripts/components/features/compose/components/reply_indicator.jsx index 11a89449e..784f08284 100644 --- a/app/assets/javascripts/components/features/compose/components/reply_indicator.jsx +++ b/app/assets/javascripts/components/features/compose/components/reply_indicator.jsx @@ -1,5 +1,5 @@ -import PureRenderMixin from 'react-addons-pure-render-mixin'; import ImmutablePropTypes from 'react-immutable-proptypes'; +import PropTypes from 'prop-types'; import Avatar from '../../../components/avatar'; import IconButton from '../../../components/icon_button'; import DisplayName from '../../../components/display_name'; @@ -10,30 +10,24 @@ const messages = defineMessages({ cancel: { id: 'reply_indicator.cancel', defaultMessage: 'Cancel' } }); -const ReplyIndicator = React.createClass({ +class ReplyIndicator extends React.PureComponent { - contextTypes: { - router: React.PropTypes.object - }, - - propTypes: { - status: ImmutablePropTypes.map, - onCancel: React.PropTypes.func.isRequired, - intl: React.PropTypes.object.isRequired - }, - - mixins: [PureRenderMixin], + constructor (props, context) { + super(props, context); + this.handleClick = this.handleClick.bind(this); + this.handleAccountClick = this.handleAccountClick.bind(this); + } handleClick () { this.props.onCancel(); - }, + } handleAccountClick (e) { if (e.button === 0) { e.preventDefault(); this.context.router.push(`/accounts/${this.props.status.getIn(['account', 'id'])}`); } - }, + } render () { const { status, intl } = this.props; @@ -60,6 +54,16 @@ const ReplyIndicator = React.createClass({ ); } -}); +} + +ReplyIndicator.contextTypes = { + router: PropTypes.object +}; + +ReplyIndicator.propTypes = { + status: ImmutablePropTypes.map, + onCancel: PropTypes.func.isRequired, + intl: PropTypes.object.isRequired +}; export default injectIntl(ReplyIndicator); diff --git a/app/assets/javascripts/components/features/compose/components/search.jsx b/app/assets/javascripts/components/features/compose/components/search.jsx index 9ca1f5dc5..7b025341b 100644 --- a/app/assets/javascripts/components/features/compose/components/search.jsx +++ b/app/assets/javascripts/components/features/compose/components/search.jsx @@ -1,48 +1,43 @@ -import PureRenderMixin from 'react-addons-pure-render-mixin'; import ImmutablePropTypes from 'react-immutable-proptypes'; +import PropTypes from 'prop-types'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; const messages = defineMessages({ placeholder: { id: 'search.placeholder', defaultMessage: 'Search' } }); -const Search = React.createClass({ +class Search extends React.PureComponent { - propTypes: { - value: React.PropTypes.string.isRequired, - submitted: React.PropTypes.bool, - onChange: React.PropTypes.func.isRequired, - onSubmit: React.PropTypes.func.isRequired, - onClear: React.PropTypes.func.isRequired, - onShow: React.PropTypes.func.isRequired, - intl: React.PropTypes.object.isRequired - }, - - mixins: [PureRenderMixin], + constructor (props, context) { + super(props, context); + this.handleChange = this.handleChange.bind(this); + this.handleKeyDown = this.handleKeyDown.bind(this); + this.handleFocus = this.handleFocus.bind(this); + } handleChange (e) { this.props.onChange(e.target.value); - }, + } handleClear (e) { e.preventDefault(); this.props.onClear(); - }, + } handleKeyDown (e) { if (e.key === 'Enter') { e.preventDefault(); this.props.onSubmit(); } - }, + } noop () { - }, + } handleFocus () { this.props.onShow(); - }, + } render () { const { intl, value, submitted } = this.props; @@ -68,6 +63,16 @@ const Search = React.createClass({ ); } -}); +} + +Search.propTypes = { + value: PropTypes.string.isRequired, + submitted: PropTypes.bool, + onChange: PropTypes.func.isRequired, + onSubmit: PropTypes.func.isRequired, + onClear: PropTypes.func.isRequired, + onShow: PropTypes.func.isRequired, + intl: PropTypes.object.isRequired +}; export default injectIntl(Search); diff --git a/app/assets/javascripts/components/features/compose/components/search_results.jsx b/app/assets/javascripts/components/features/compose/components/search_results.jsx index d0064f1b9..00bfd1786 100644 --- a/app/assets/javascripts/components/features/compose/components/search_results.jsx +++ b/app/assets/javascripts/components/features/compose/components/search_results.jsx @@ -1,17 +1,10 @@ -import PureRenderMixin from 'react-addons-pure-render-mixin'; import ImmutablePropTypes from 'react-immutable-proptypes'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import AccountContainer from '../../../containers/account_container'; import StatusContainer from '../../../containers/status_container'; import { Link } from 'react-router'; -const SearchResults = React.createClass({ - - propTypes: { - results: ImmutablePropTypes.map.isRequired - }, - - mixins: [PureRenderMixin], +class SearchResults extends React.PureComponent { render () { const { results } = this.props; @@ -63,6 +56,10 @@ const SearchResults = React.createClass({ ); } -}); +} + +SearchResults.propTypes = { + results: ImmutablePropTypes.map.isRequired +}; export default SearchResults; diff --git a/app/assets/javascripts/components/features/compose/components/text_icon_button.jsx b/app/assets/javascripts/components/features/compose/components/text_icon_button.jsx index e3ac63d87..edf413e87 100644 --- a/app/assets/javascripts/components/features/compose/components/text_icon_button.jsx +++ b/app/assets/javascripts/components/features/compose/components/text_icon_button.jsx @@ -1,20 +1,16 @@ -import PureRenderMixin from 'react-addons-pure-render-mixin'; +import PropTypes from 'prop-types'; -const TextIconButton = React.createClass({ +class TextIconButton extends React.PureComponent { - propTypes: { - label: React.PropTypes.string.isRequired, - title: React.PropTypes.string, - active: React.PropTypes.bool, - onClick: React.PropTypes.func.isRequired - }, - - mixins: [PureRenderMixin], + constructor (props, context) { + super(props, context); + this.handleClick = this.handleClick.bind(this); + } handleClick (e) { e.preventDefault(); this.props.onClick(); - }, + } render () { const { label, title, active } = this.props; @@ -26,6 +22,13 @@ const TextIconButton = React.createClass({ ); } -}); +} + +TextIconButton.propTypes = { + label: PropTypes.string.isRequired, + title: PropTypes.string, + active: PropTypes.bool, + onClick: PropTypes.func.isRequired +}; export default TextIconButton; diff --git a/app/assets/javascripts/components/features/compose/components/upload_button.jsx b/app/assets/javascripts/components/features/compose/components/upload_button.jsx index 2ba0e8fd2..64b36a4df 100644 --- a/app/assets/javascripts/components/features/compose/components/upload_button.jsx +++ b/app/assets/javascripts/components/features/compose/components/upload_button.jsx @@ -1,5 +1,5 @@ -import PureRenderMixin from 'react-addons-pure-render-mixin'; import IconButton from '../../../components/icon_button'; +import PropTypes from 'prop-types'; import { defineMessages, injectIntl } from 'react-intl'; const messages = defineMessages({ @@ -11,31 +11,28 @@ const iconStyle = { height: null }; -const UploadButton = React.createClass({ +class UploadButton extends React.PureComponent { - propTypes: { - disabled: React.PropTypes.bool, - onSelectFile: React.PropTypes.func.isRequired, - style: React.PropTypes.object, - resetFileKey: React.PropTypes.number, - intl: React.PropTypes.object.isRequired - }, - - mixins: [PureRenderMixin], + constructor (props, context) { + super(props, context); + this.handleChange = this.handleChange.bind(this); + this.handleClick = this.handleClick.bind(this); + this.setRef = this.setRef.bind(this); + } handleChange (e) { if (e.target.files.length > 0) { this.props.onSelectFile(e.target.files); } - }, + } handleClick () { this.fileElement.click(); - }, + } setRef (c) { this.fileElement = c; - }, + } render () { const { intl, resetFileKey, disabled } = this.props; @@ -48,6 +45,14 @@ const UploadButton = React.createClass({ ); } -}); +} + +UploadButton.propTypes = { + disabled: PropTypes.bool, + onSelectFile: PropTypes.func.isRequired, + style: PropTypes.object, + resetFileKey: PropTypes.number, + intl: PropTypes.object.isRequired +}; export default injectIntl(UploadButton); diff --git a/app/assets/javascripts/components/features/compose/components/upload_form.jsx b/app/assets/javascripts/components/features/compose/components/upload_form.jsx index 77590d90d..f28944ad5 100644 --- a/app/assets/javascripts/components/features/compose/components/upload_form.jsx +++ b/app/assets/javascripts/components/features/compose/components/upload_form.jsx @@ -1,5 +1,5 @@ -import PureRenderMixin from 'react-addons-pure-render-mixin'; import ImmutablePropTypes from 'react-immutable-proptypes'; +import PropTypes from 'prop-types'; import IconButton from '../../../components/icon_button'; import { defineMessages, injectIntl } from 'react-intl'; import UploadProgressContainer from '../containers/upload_progress_container'; @@ -9,15 +9,7 @@ const messages = defineMessages({ undo: { id: 'upload_form.undo', defaultMessage: 'Undo' } }); -const UploadForm = React.createClass({ - - propTypes: { - media: ImmutablePropTypes.list.isRequired, - onRemoveFile: React.PropTypes.func.isRequired, - intl: React.PropTypes.object.isRequired - }, - - mixins: [PureRenderMixin], +class UploadForm extends React.PureComponent { render () { const { intl, media } = this.props; @@ -42,6 +34,12 @@ const UploadForm = React.createClass({ ); } -}); +} + +UploadForm.propTypes = { + media: ImmutablePropTypes.list.isRequired, + onRemoveFile: PropTypes.func.isRequired, + intl: PropTypes.object.isRequired +}; export default injectIntl(UploadForm); diff --git a/app/assets/javascripts/components/features/compose/components/upload_progress.jsx b/app/assets/javascripts/components/features/compose/components/upload_progress.jsx index 86ffbf936..a04edb97d 100644 --- a/app/assets/javascripts/components/features/compose/components/upload_progress.jsx +++ b/app/assets/javascripts/components/features/compose/components/upload_progress.jsx @@ -1,15 +1,8 @@ -import PureRenderMixin from 'react-addons-pure-render-mixin'; +import PropTypes from 'prop-types'; import { Motion, spring } from 'react-motion'; import { FormattedMessage } from 'react-intl'; -const UploadProgress = React.createClass({ - - propTypes: { - active: React.PropTypes.bool, - progress: React.PropTypes.number - }, - - mixins: [PureRenderMixin], +class UploadProgress extends React.PureComponent { render () { const { active, progress } = this.props; @@ -39,6 +32,11 @@ const UploadProgress = React.createClass({ ); } -}); +} + +UploadProgress.propTypes = { + active: PropTypes.bool, + progress: PropTypes.number +}; export default UploadProgress; diff --git a/app/assets/javascripts/components/features/compose/containers/sensitive_button_container.jsx b/app/assets/javascripts/components/features/compose/containers/sensitive_button_container.jsx index 074b568f4..c83598a7d 100644 --- a/app/assets/javascripts/components/features/compose/containers/sensitive_button_container.jsx +++ b/app/assets/javascripts/components/features/compose/containers/sensitive_button_container.jsx @@ -1,4 +1,5 @@ import { connect } from 'react-redux'; +import PropTypes from 'prop-types'; import TextIconButton from '../components/text_icon_button'; import { changeComposeSensitivity } from '../../../actions/compose'; import { Motion, spring } from 'react-motion'; @@ -21,14 +22,7 @@ const mapDispatchToProps = dispatch => ({ }); -const SensitiveButton = React.createClass({ - - propTypes: { - visible: React.PropTypes.bool, - active: React.PropTypes.bool, - onClick: React.PropTypes.func.isRequired, - intl: React.PropTypes.object.isRequired - }, +class SensitiveButton extends React.PureComponent { render () { const { visible, active, onClick, intl } = this.props; @@ -44,6 +38,13 @@ const SensitiveButton = React.createClass({ ); } -}); +} + +SensitiveButton.propTypes = { + visible: PropTypes.bool, + active: PropTypes.bool, + onClick: PropTypes.func.isRequired, + intl: PropTypes.object.isRequired +}; export default connect(mapStateToProps, mapDispatchToProps)(injectIntl(SensitiveButton)); diff --git a/app/assets/javascripts/components/features/compose/index.jsx b/app/assets/javascripts/components/features/compose/index.jsx index 33e16472c..eee5c440a 100644 --- a/app/assets/javascripts/components/features/compose/index.jsx +++ b/app/assets/javascripts/components/features/compose/index.jsx @@ -1,7 +1,7 @@ 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 PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { mountCompose, unmountCompose } from '../../actions/compose'; import { Link } from 'react-router'; @@ -22,24 +22,15 @@ const mapStateToProps = state => ({ showSearch: state.getIn(['search', 'submitted']) && !state.getIn(['search', 'hidden']) }); -const Compose = React.createClass({ - - propTypes: { - dispatch: React.PropTypes.func.isRequired, - withHeader: React.PropTypes.bool, - showSearch: React.PropTypes.bool, - intl: React.PropTypes.object.isRequired - }, - - mixins: [PureRenderMixin], +class Compose extends React.PureComponent { componentDidMount () { this.props.dispatch(mountCompose()); - }, + } componentWillUnmount () { this.props.dispatch(unmountCompose()); - }, + } render () { const { withHeader, showSearch, intl } = this.props; @@ -82,6 +73,13 @@ const Compose = React.createClass({ ); } -}); +} + +Compose.propTypes = { + dispatch: PropTypes.func.isRequired, + withHeader: PropTypes.bool, + showSearch: PropTypes.bool, + intl: PropTypes.object.isRequired +}; export default connect(mapStateToProps)(injectIntl(Compose)); |