From 337462aa5e68014aa15788e4513e190b2e434d7e Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 19 Sep 2016 23:25:59 +0200 Subject: Re-organizing components to be more modular, adding loading bars --- .../components/features/status/index.jsx | 4 +- .../features/ui/components/character_counter.jsx | 21 ++++++ .../components/features/ui/components/column.jsx | 76 ++++++++++++++++++++++ .../features/ui/components/column_header.jsx | 34 ++++++++++ .../features/ui/components/columns_area.jsx | 17 +++++ .../features/ui/components/compose_form.jsx | 58 +++++++++++++++++ .../components/features/ui/components/drawer.jsx | 17 +++++ .../features/ui/components/follow_form.jsx | 40 ++++++++++++ .../features/ui/components/media_gallery.jsx | 75 +++++++++++++++++++++ .../features/ui/components/navigation_bar.jsx | 30 +++++++++ .../features/ui/components/reply_indicator.jsx | 41 ++++++++++++ .../features/ui/components/upload_button.jsx | 37 +++++++++++ .../features/ui/components/upload_form.jsx | 43 ++++++++++++ .../ui/containers/compose_form_container.jsx | 42 ++++++++++++ .../ui/containers/follow_form_container.jsx | 24 +++++++ .../ui/containers/navigation_container.jsx | 8 +++ .../ui/containers/notifications_container.jsx | 25 +++++++ .../ui/containers/status_list_container.jsx | 29 +++++++++ .../ui/containers/upload_form_container.jsx | 25 +++++++ .../javascripts/components/features/ui/index.jsx | 56 ++++++++++++++++ 20 files changed, 700 insertions(+), 2 deletions(-) create mode 100644 app/assets/javascripts/components/features/ui/components/character_counter.jsx create mode 100644 app/assets/javascripts/components/features/ui/components/column.jsx create mode 100644 app/assets/javascripts/components/features/ui/components/column_header.jsx create mode 100644 app/assets/javascripts/components/features/ui/components/columns_area.jsx create mode 100644 app/assets/javascripts/components/features/ui/components/compose_form.jsx create mode 100644 app/assets/javascripts/components/features/ui/components/drawer.jsx create mode 100644 app/assets/javascripts/components/features/ui/components/follow_form.jsx create mode 100644 app/assets/javascripts/components/features/ui/components/media_gallery.jsx create mode 100644 app/assets/javascripts/components/features/ui/components/navigation_bar.jsx create mode 100644 app/assets/javascripts/components/features/ui/components/reply_indicator.jsx create mode 100644 app/assets/javascripts/components/features/ui/components/upload_button.jsx create mode 100644 app/assets/javascripts/components/features/ui/components/upload_form.jsx create mode 100644 app/assets/javascripts/components/features/ui/containers/compose_form_container.jsx create mode 100644 app/assets/javascripts/components/features/ui/containers/follow_form_container.jsx create mode 100644 app/assets/javascripts/components/features/ui/containers/navigation_container.jsx create mode 100644 app/assets/javascripts/components/features/ui/containers/notifications_container.jsx create mode 100644 app/assets/javascripts/components/features/ui/containers/status_list_container.jsx create mode 100644 app/assets/javascripts/components/features/ui/containers/upload_form_container.jsx create mode 100644 app/assets/javascripts/components/features/ui/index.jsx (limited to 'app/assets/javascripts/components/features') diff --git a/app/assets/javascripts/components/features/status/index.jsx b/app/assets/javascripts/components/features/status/index.jsx index 72ff6a944..7a810d474 100644 --- a/app/assets/javascripts/components/features/status/index.jsx +++ b/app/assets/javascripts/components/features/status/index.jsx @@ -31,12 +31,12 @@ const Status = React.createClass({ mixins: [PureRenderMixin], componentWillMount () { - this.props.dispatch(fetchStatus(this.props.params.statusId)); + this.props.dispatch(fetchStatus(Number(this.props.params.statusId))); }, componentWillReceiveProps (nextProps) { if (nextProps.params.statusId !== this.props.params.statusId && nextProps.params.statusId) { - this.props.dispatch(fetchStatus(nextProps.params.statusId)); + this.props.dispatch(fetchStatus(Number(nextProps.params.statusId))); } }, diff --git a/app/assets/javascripts/components/features/ui/components/character_counter.jsx b/app/assets/javascripts/components/features/ui/components/character_counter.jsx new file mode 100644 index 000000000..dd9218844 --- /dev/null +++ b/app/assets/javascripts/components/features/ui/components/character_counter.jsx @@ -0,0 +1,21 @@ +import PureRenderMixin from 'react-addons-pure-render-mixin'; + +const CharacterCounter = React.createClass({ + + propTypes: { + text: React.PropTypes.string.isRequired + }, + + mixins: [PureRenderMixin], + + render () { + return ( + + {this.props.text.length} + + ); + } + +}); + +export default CharacterCounter; diff --git a/app/assets/javascripts/components/features/ui/components/column.jsx b/app/assets/javascripts/components/features/ui/components/column.jsx new file mode 100644 index 000000000..7109bcc19 --- /dev/null +++ b/app/assets/javascripts/components/features/ui/components/column.jsx @@ -0,0 +1,76 @@ +import ColumnHeader from './column_header'; +import PureRenderMixin from 'react-addons-pure-render-mixin'; + +const easingOutQuint = (x, t, b, c, d) => c*((t=t/d-1)*t*t*t*t + 1) + b; + +const scrollTop = (node) => { + const startTime = Date.now(); + const offset = node.scrollTop; + const targetY = -offset; + const duration = 1000; + let interrupt = false; + + const step = () => { + const elapsed = Date.now() - startTime; + const percentage = elapsed / duration; + + if (percentage > 1 || interrupt) { + return; + } + + node.scrollTo(0, easingOutQuint(0, elapsed, offset, targetY, duration)); + requestAnimationFrame(step); + }; + + step(); + + return () => { + interrupt = true; + }; +}; + + +const Column = React.createClass({ + + propTypes: { + heading: React.PropTypes.string, + icon: React.PropTypes.string + }, + + mixins: [PureRenderMixin], + + handleHeaderClick () { + let node = ReactDOM.findDOMNode(this); + this._interruptScrollAnimation = scrollTop(node.querySelector('.scrollable')); + }, + + handleWheel () { + if (typeof this._interruptScrollAnimation !== 'undefined') { + this._interruptScrollAnimation(); + } + }, + + handleScroll () { + // todo + }, + + render () { + let header = ''; + + if (this.props.heading) { + header = ; + } + + const style = { width: '350px', flex: '0 0 auto', background: '#282c37', margin: '10px', marginRight: '0', display: 'flex', flexDirection: 'column' }; + + return ( +
+ {header} + {this.props.children} +
+ ); + } + +}); + +export default Column; diff --git a/app/assets/javascripts/components/features/ui/components/column_header.jsx b/app/assets/javascripts/components/features/ui/components/column_header.jsx new file mode 100644 index 000000000..21def69c7 --- /dev/null +++ b/app/assets/javascripts/components/features/ui/components/column_header.jsx @@ -0,0 +1,34 @@ +import PureRenderMixin from 'react-addons-pure-render-mixin'; + +const ColumnHeader = React.createClass({ + + propTypes: { + icon: React.PropTypes.string, + type: React.PropTypes.string, + onClick: React.PropTypes.func + }, + + mixins: [PureRenderMixin], + + handleClick () { + this.props.onClick(); + }, + + render () { + let icon = ''; + + if (this.props.icon) { + icon = ; + } + + return ( +
+ {icon} + {this.props.type} +
+ ); + } + +}); + +export default ColumnHeader; diff --git a/app/assets/javascripts/components/features/ui/components/columns_area.jsx b/app/assets/javascripts/components/features/ui/components/columns_area.jsx new file mode 100644 index 000000000..e45a6466d --- /dev/null +++ b/app/assets/javascripts/components/features/ui/components/columns_area.jsx @@ -0,0 +1,17 @@ +import PureRenderMixin from 'react-addons-pure-render-mixin'; + +const ColumnsArea = React.createClass({ + + mixins: [PureRenderMixin], + + render () { + return ( +
+ {this.props.children} +
+ ); + } + +}); + +export default ColumnsArea; diff --git a/app/assets/javascripts/components/features/ui/components/compose_form.jsx b/app/assets/javascripts/components/features/ui/components/compose_form.jsx new file mode 100644 index 000000000..1aa0b447f --- /dev/null +++ b/app/assets/javascripts/components/features/ui/components/compose_form.jsx @@ -0,0 +1,58 @@ +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 ReplyIndicator from './reply_indicator'; +import UploadButton from './upload_button'; + +const ComposeForm = React.createClass({ + + propTypes: { + text: React.PropTypes.string.isRequired, + is_submitting: React.PropTypes.bool, + in_reply_to: ImmutablePropTypes.map, + onChange: React.PropTypes.func.isRequired, + onSubmit: React.PropTypes.func.isRequired, + onCancelReply: React.PropTypes.func.isRequired + }, + + mixins: [PureRenderMixin], + + handleChange (e) { + this.props.onChange(e.target.value); + }, + + handleKeyUp (e) { + if (e.keyCode === 13 && e.ctrlKey) { + this.props.onSubmit(); + } + }, + + handleSubmit () { + this.props.onSubmit(); + }, + + render () { + let replyArea = ''; + + if (this.props.in_reply_to) { + replyArea = ; + } + + return ( +
+ {replyArea} + +