diff options
author | Eugen Rochko <eugen@zeonfederated.com> | 2017-05-03 02:04:16 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-05-03 02:04:16 +0200 |
commit | f5bf5ebb82e3af420dcd23d602b1be6cc86838e1 (patch) | |
tree | 92eef08642a038cf44ccbc6d16a884293e7a0814 /app/assets/javascripts/components/features/notifications | |
parent | 26bc5915727e0a0173c03cb49f5193dd612fb888 (diff) |
Replace sprockets/browserify with Webpack (#2617)
* Replace browserify with webpack * Add react-intl-translations-manager * Do not minify in development, add offline-plugin for ServiceWorker background cache updates * Adjust tests and dependencies * Fix production deployments * Fix tests * More optimizations * Improve travis cache for npm stuff * Re-run travis * Add back support for custom.scss as before * Remove offline-plugin and babili * Fix issue with Immutable.List().unshift(...values) not working as expected * Make travis load schema instead of running all migrations in sequence * Fix missing React import in WarningContainer. Optimize rendering performance by using ImmutablePureComponent instead of React.PureComponent. ImmutablePureComponent uses Immutable.is() to compare props. Replace dynamic callback bindings in <UI /> * Add react definitions to places that use JSX * Add Procfile.dev for running rails, webpack and streaming API at the same time
Diffstat (limited to 'app/assets/javascripts/components/features/notifications')
7 files changed, 0 insertions, 382 deletions
diff --git a/app/assets/javascripts/components/features/notifications/components/clear_column_button.jsx b/app/assets/javascripts/components/features/notifications/components/clear_column_button.jsx deleted file mode 100644 index 206b05f91..000000000 --- a/app/assets/javascripts/components/features/notifications/components/clear_column_button.jsx +++ /dev/null @@ -1,26 +0,0 @@ -import PropTypes from 'prop-types'; -import { defineMessages, injectIntl } from 'react-intl'; - -const messages = defineMessages({ - clear: { id: 'notifications.clear', defaultMessage: 'Clear notifications' } -}); - -class ClearColumnButton extends React.Component { - - render () { - const { intl } = this.props; - - return ( - <div role='button' title={intl.formatMessage(messages.clear)} className='column-icon column-icon-clear' tabIndex='0' onClick={this.props.onClick}> - <i className='fa fa-eraser' /> - </div> - ); - } -} - -ClearColumnButton.propTypes = { - onClick: PropTypes.func.isRequired, - intl: PropTypes.object.isRequired -}; - -export default injectIntl(ClearColumnButton); diff --git a/app/assets/javascripts/components/features/notifications/components/column_settings.jsx b/app/assets/javascripts/components/features/notifications/components/column_settings.jsx deleted file mode 100644 index 30063010c..000000000 --- a/app/assets/javascripts/components/features/notifications/components/column_settings.jsx +++ /dev/null @@ -1,70 +0,0 @@ -import PropTypes from 'prop-types'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; -import ColumnCollapsable from '../../../components/column_collapsable'; -import SettingToggle from './setting_toggle'; - -const messages = defineMessages({ - settings: { id: 'notifications.settings', defaultMessage: 'Column settings' } -}); - -class ColumnSettings extends React.PureComponent { - - render () { - const { settings, intl, onChange, onSave } = this.props; - - const alertStr = <FormattedMessage id='notifications.column_settings.alert' defaultMessage='Desktop notifications' />; - const showStr = <FormattedMessage id='notifications.column_settings.show' defaultMessage='Show in column' />; - const soundStr = <FormattedMessage id='notifications.column_settings.sound' defaultMessage='Play sound' />; - - return ( - <ColumnCollapsable icon='sliders' title={intl.formatMessage(messages.settings)} fullHeight={616} onCollapse={onSave}> - <div className='column-settings__outer'> - <span className='column-settings__section'><FormattedMessage id='notifications.column_settings.follow' defaultMessage='New followers:' /></span> - - <div className='column-settings__row'> - <SettingToggle settings={settings} settingKey={['alerts', 'follow']} onChange={onChange} label={alertStr} /> - <SettingToggle settings={settings} settingKey={['shows', 'follow']} onChange={onChange} label={showStr} /> - <SettingToggle settings={settings} settingKey={['sounds', 'follow']} onChange={onChange} label={soundStr} /> - </div> - - <span className='column-settings__section'><FormattedMessage id='notifications.column_settings.favourite' defaultMessage='Favourites:' /></span> - - <div className='column-settings__row'> - <SettingToggle settings={settings} settingKey={['alerts', 'favourite']} onChange={onChange} label={alertStr} /> - <SettingToggle settings={settings} settingKey={['shows', 'favourite']} onChange={onChange} label={showStr} /> - <SettingToggle settings={settings} settingKey={['sounds', 'favourite']} onChange={onChange} label={soundStr} /> - </div> - - <span className='column-settings__section'><FormattedMessage id='notifications.column_settings.mention' defaultMessage='Mentions:' /></span> - - <div className='column-settings__row'> - <SettingToggle settings={settings} settingKey={['alerts', 'mention']} onChange={onChange} label={alertStr} /> - <SettingToggle settings={settings} settingKey={['shows', 'mention']} onChange={onChange} label={showStr} /> - <SettingToggle settings={settings} settingKey={['sounds', 'mention']} onChange={onChange} label={soundStr} /> - </div> - - <span className='column-settings__section'><FormattedMessage id='notifications.column_settings.reblog' defaultMessage='Boosts:' /></span> - - <div className='column-settings__row'> - <SettingToggle settings={settings} settingKey={['alerts', 'reblog']} onChange={onChange} label={alertStr} /> - <SettingToggle settings={settings} settingKey={['shows', 'reblog']} onChange={onChange} label={showStr} /> - <SettingToggle settings={settings} settingKey={['sounds', 'reblog']} onChange={onChange} label={soundStr} /> - </div> - </div> - </ColumnCollapsable> - ); - } - -} - -ColumnSettings.propTypes = { - settings: ImmutablePropTypes.map.isRequired, - onChange: PropTypes.func.isRequired, - onSave: PropTypes.func.isRequired, - intl: PropTypes.shape({ - formatMessage: PropTypes.func.isRequired - }).isRequired -}; - -export default injectIntl(ColumnSettings); diff --git a/app/assets/javascripts/components/features/notifications/components/notification.jsx b/app/assets/javascripts/components/features/notifications/components/notification.jsx deleted file mode 100644 index 34dd76bb7..000000000 --- a/app/assets/javascripts/components/features/notifications/components/notification.jsx +++ /dev/null @@ -1,88 +0,0 @@ -import ImmutablePropTypes from 'react-immutable-proptypes'; -import StatusContainer from '../../../containers/status_container'; -import AccountContainer from '../../../containers/account_container'; -import { FormattedMessage } from 'react-intl'; -import Permalink from '../../../components/permalink'; -import emojify from '../../../emoji'; -import escapeTextContentForBrowser from 'escape-html'; - -class Notification extends React.PureComponent { - - renderFollow (account, link) { - return ( - <div className='notification notification-follow'> - <div className='notification__message'> - <div className='notification__favourite-icon-wrapper'> - <i className='fa fa-fw fa-user-plus' /> - </div> - - <FormattedMessage id='notification.follow' defaultMessage='{name} followed you' values={{ name: link }} /> - </div> - - <AccountContainer id={account.get('id')} withNote={false} /> - </div> - ); - } - - renderMention (notification) { - return <StatusContainer id={notification.get('status')} />; - } - - renderFavourite (notification, link) { - return ( - <div className='notification notification-favourite'> - <div className='notification__message'> - <div className='notification__favourite-icon-wrapper'> - <i className='fa fa-fw fa-star star-icon'/> - </div> - - <FormattedMessage id='notification.favourite' defaultMessage='{name} favourited your status' values={{ name: link }} /> - </div> - - <StatusContainer id={notification.get('status')} muted={true} /> - </div> - ); - } - - renderReblog (notification, link) { - return ( - <div className='notification notification-reblog'> - <div className='notification__message'> - <div className='notification__favourite-icon-wrapper'> - <i className='fa fa-fw fa-retweet' /> - </div> - - <FormattedMessage id='notification.reblog' defaultMessage='{name} boosted your status' values={{ name: link }} /> - </div> - - <StatusContainer id={notification.get('status')} muted={true} /> - </div> - ); - } - - render () { // eslint-disable-line consistent-return - const { notification } = this.props; - const account = notification.get('account'); - const displayName = account.get('display_name').length > 0 ? account.get('display_name') : account.get('username'); - const displayNameHTML = { __html: emojify(escapeTextContentForBrowser(displayName)) }; - const link = <Permalink className='notification__display-name' href={account.get('url')} title={account.get('acct')} to={`/accounts/${account.get('id')}`} dangerouslySetInnerHTML={displayNameHTML} />; - - switch(notification.get('type')) { - case 'follow': - return this.renderFollow(account, link); - case 'mention': - return this.renderMention(notification); - case 'favourite': - return this.renderFavourite(notification, link); - case 'reblog': - return this.renderReblog(notification, link); - } - } - -} - -Notification.propTypes = { - notification: ImmutablePropTypes.map.isRequired -}; - -export default Notification; diff --git a/app/assets/javascripts/components/features/notifications/components/setting_toggle.jsx b/app/assets/javascripts/components/features/notifications/components/setting_toggle.jsx deleted file mode 100644 index e9bca5928..000000000 --- a/app/assets/javascripts/components/features/notifications/components/setting_toggle.jsx +++ /dev/null @@ -1,20 +0,0 @@ -import PropTypes from 'prop-types'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import Toggle from 'react-toggle'; - -const SettingToggle = ({ settings, settingKey, label, onChange, htmlFor = '' }) => ( - <label htmlFor={htmlFor} className='setting-toggle__label'> - <Toggle checked={settings.getIn(settingKey)} onChange={(e) => onChange(settingKey, e.target.checked)} /> - <span className='setting-toggle'>{label}</span> - </label> -); - -SettingToggle.propTypes = { - settings: ImmutablePropTypes.map.isRequired, - settingKey: PropTypes.array.isRequired, - label: PropTypes.node.isRequired, - onChange: PropTypes.func.isRequired, - htmlFor: PropTypes.string -}; - -export default SettingToggle; diff --git a/app/assets/javascripts/components/features/notifications/containers/column_settings_container.jsx b/app/assets/javascripts/components/features/notifications/containers/column_settings_container.jsx deleted file mode 100644 index bc24c75e0..000000000 --- a/app/assets/javascripts/components/features/notifications/containers/column_settings_container.jsx +++ /dev/null @@ -1,21 +0,0 @@ -import { connect } from 'react-redux'; -import ColumnSettings from '../components/column_settings'; -import { changeSetting, saveSettings } from '../../../actions/settings'; - -const mapStateToProps = state => ({ - settings: state.getIn(['settings', 'notifications']) -}); - -const mapDispatchToProps = dispatch => ({ - - onChange (key, checked) { - dispatch(changeSetting(['notifications', ...key], checked)); - }, - - onSave () { - dispatch(saveSettings()); - } - -}); - -export default connect(mapStateToProps, mapDispatchToProps)(ColumnSettings); diff --git a/app/assets/javascripts/components/features/notifications/containers/notification_container.jsx b/app/assets/javascripts/components/features/notifications/containers/notification_container.jsx deleted file mode 100644 index 4ca1b1b7b..000000000 --- a/app/assets/javascripts/components/features/notifications/containers/notification_container.jsx +++ /dev/null @@ -1,15 +0,0 @@ -import { connect } from 'react-redux'; -import { makeGetNotification } from '../../../selectors'; -import Notification from '../components/notification'; - -const makeMapStateToProps = () => { - const getNotification = makeGetNotification(); - - const mapStateToProps = (state, props) => ({ - notification: getNotification(state, props.notification, props.accountId) - }); - - return mapStateToProps; -}; - -export default connect(makeMapStateToProps)(Notification); diff --git a/app/assets/javascripts/components/features/notifications/index.jsx b/app/assets/javascripts/components/features/notifications/index.jsx deleted file mode 100644 index da3ce2f62..000000000 --- a/app/assets/javascripts/components/features/notifications/index.jsx +++ /dev/null @@ -1,142 +0,0 @@ -import { connect } from 'react-redux'; -import PropTypes from 'prop-types'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import Column from '../ui/components/column'; -import { expandNotifications, clearNotifications, scrollTopNotifications } from '../../actions/notifications'; -import NotificationContainer from './containers/notification_container'; -import { ScrollContainer } from 'react-router-scroll'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; -import ColumnSettingsContainer from './containers/column_settings_container'; -import { createSelector } from 'reselect'; -import Immutable from 'immutable'; -import LoadMore from '../../components/load_more'; -import ClearColumnButton from './components/clear_column_button'; -import { openModal } from '../../actions/modal'; - -const messages = defineMessages({ - title: { id: 'column.notifications', defaultMessage: 'Notifications' }, - clearMessage: { id: 'notifications.clear_confirmation', defaultMessage: 'Are you sure you want to permanently clear all your notifications?' }, - clearConfirm: { id: 'notifications.clear', defaultMessage: 'Clear notifications' } -}); - -const getNotifications = createSelector([ - state => Immutable.List(state.getIn(['settings', 'notifications', 'shows']).filter(item => !item).keys()), - state => state.getIn(['notifications', 'items']) -], (excludedTypes, notifications) => notifications.filterNot(item => excludedTypes.includes(item.get('type')))); - -const mapStateToProps = state => ({ - notifications: getNotifications(state), - isLoading: state.getIn(['notifications', 'isLoading'], true), - isUnread: state.getIn(['notifications', 'unread']) > 0 -}); - -class Notifications extends React.PureComponent { - - constructor (props, context) { - super(props, context); - this.handleScroll = this.handleScroll.bind(this); - this.handleLoadMore = this.handleLoadMore.bind(this); - this.handleClear = this.handleClear.bind(this); - this.setRef = this.setRef.bind(this); - } - - handleScroll (e) { - const { scrollTop, scrollHeight, clientHeight } = e.target; - const offset = scrollHeight - scrollTop - clientHeight; - this._oldScrollPosition = scrollHeight - scrollTop; - - if (250 > offset && !this.props.isLoading) { - this.props.dispatch(expandNotifications()); - } else if (scrollTop < 100) { - this.props.dispatch(scrollTopNotifications(true)); - } else { - this.props.dispatch(scrollTopNotifications(false)); - } - } - - componentDidUpdate (prevProps) { - if (this.node.scrollTop > 0 && (prevProps.notifications.size < this.props.notifications.size && prevProps.notifications.first() !== this.props.notifications.first() && !!this._oldScrollPosition)) { - this.node.scrollTop = this.node.scrollHeight - this._oldScrollPosition; - } - } - - handleLoadMore (e) { - e.preventDefault(); - this.props.dispatch(expandNotifications()); - } - - handleClear () { - const { dispatch, intl } = this.props; - - dispatch(openModal('CONFIRM', { - message: intl.formatMessage(messages.clearMessage), - confirm: intl.formatMessage(messages.clearConfirm), - onConfirm: () => dispatch(clearNotifications()) - })); - } - - setRef (c) { - this.node = c; - } - - render () { - const { intl, notifications, shouldUpdateScroll, isLoading, isUnread } = this.props; - - let loadMore = ''; - let scrollableArea = ''; - let unread = ''; - - if (!isLoading && notifications.size > 0) { - loadMore = <LoadMore onClick={this.handleLoadMore} />; - } - - if (isUnread) { - unread = <div className='notifications__unread-indicator' />; - } - - if (isLoading || notifications.size > 0) { - scrollableArea = ( - <div className='scrollable' onScroll={this.handleScroll} ref={this.setRef}> - {unread} - - <div> - {notifications.map(item => <NotificationContainer key={item.get('id')} notification={item} accountId={item.get('account')} />)} - {loadMore} - </div> - </div> - ); - } else { - scrollableArea = ( - <div className='empty-column-indicator' ref={this.setRef}> - <FormattedMessage id='empty_column.notifications' defaultMessage="You don't have any notifications yet. Interact with others to start the conversation." /> - </div> - ); - } - - return ( - <Column icon='bell' active={isUnread} heading={intl.formatMessage(messages.title)}> - <ColumnSettingsContainer /> - <ClearColumnButton onClick={this.handleClear} /> - <ScrollContainer scrollKey='notifications' shouldUpdateScroll={shouldUpdateScroll}> - {scrollableArea} - </ScrollContainer> - </Column> - ); - } - -} - -Notifications.propTypes = { - notifications: ImmutablePropTypes.list.isRequired, - dispatch: PropTypes.func.isRequired, - shouldUpdateScroll: PropTypes.func, - intl: PropTypes.object.isRequired, - isLoading: PropTypes.bool, - isUnread: PropTypes.bool -}; - -Notifications.defaultProps = { - trackScroll: true -}; - -export default connect(mapStateToProps)(injectIntl(Notifications)); |