about summary refs log tree commit diff
path: root/app/assets/javascripts/components/features/notifications
diff options
context:
space:
mode:
authorEugen Rochko <eugen@zeonfederated.com>2017-01-02 14:09:57 +0100
committerEugen Rochko <eugen@zeonfederated.com>2017-01-02 14:09:57 +0100
commit65647a24720c1fa1dda832a8ce0f48f48f4cf358 (patch)
tree9f29be394bf72d110c773cc67610903118304718 /app/assets/javascripts/components/features/notifications
parent75122e162d7b933d34c6b694c6c5a0b2533f547f (diff)
See #244 - Added notifications column settings to filter what's displayed
in the column and what appears as desktop notifications. Settings do not
persist yet
Diffstat (limited to 'app/assets/javascripts/components/features/notifications')
-rw-r--r--app/assets/javascripts/components/features/notifications/components/column_settings.jsx150
-rw-r--r--app/assets/javascripts/components/features/notifications/containers/column_settings_container.jsx17
-rw-r--r--app/assets/javascripts/components/features/notifications/index.jsx14
3 files changed, 179 insertions, 2 deletions
diff --git a/app/assets/javascripts/components/features/notifications/components/column_settings.jsx b/app/assets/javascripts/components/features/notifications/components/column_settings.jsx
new file mode 100644
index 000000000..b4035c20d
--- /dev/null
+++ b/app/assets/javascripts/components/features/notifications/components/column_settings.jsx
@@ -0,0 +1,150 @@
+import PureRenderMixin from 'react-addons-pure-render-mixin';
+import ImmutablePropTypes from 'react-immutable-proptypes';
+import Toggle from 'react-toggle';
+import { Motion, spring } from 'react-motion';
+import { FormattedMessage } from 'react-intl';
+
+const outerStyle = {
+  background: '#373b4a',
+  padding: '15px'
+};
+
+const iconStyle = {
+  fontSize: '16px',
+  padding: '15px',
+  position: 'absolute',
+  right: '0',
+  top: '-48px',
+  cursor: 'pointer'
+};
+
+const labelStyle = {
+  display: 'block',
+  lineHeight: '24px',
+  verticalAlign: 'middle'
+};
+
+const labelSpanStyle = {
+  display: 'inline-block',
+  verticalAlign: 'middle',
+  marginBottom: '14px',
+  marginLeft: '8px',
+  color: '#9baec8'
+};
+
+const sectionStyle = {
+  cursor: 'default',
+  display: 'block',
+  fontWeight: '500',
+  color: '#9baec8',
+  marginBottom: '10px'
+};
+
+const rowStyle = {
+
+};
+
+const ColumnSettings = React.createClass({
+
+  propTypes: {
+    settings: ImmutablePropTypes.map.isRequired,
+    onChange: React.PropTypes.func.isRequired
+  },
+
+  getInitialState () {
+    return {
+      collapsed: true
+    };
+  },
+
+  mixins: [PureRenderMixin],
+
+  handleToggleCollapsed () {
+    this.setState({ collapsed: !this.state.collapsed });
+  },
+
+  handleChange (key, e) {
+    this.props.onChange(key, e.target.checked);
+  },
+
+  render () {
+    const { settings }  = this.props;
+    const { collapsed } = this.state;
+
+    const alertStr = <FormattedMessage id='notifications.column_settings.alert' defaultMessage='Desktop notifications' />;
+    const showStr  = <FormattedMessage id='notifications.column_settings.show' defaultMessage='Show in column' />;
+
+    return (
+      <div style={{ position: 'relative' }}>
+        <div style={{...iconStyle, color: collapsed ? '#9baec8' : '#fff', background: collapsed ? '#2f3441' : '#373b4a' }} onClick={this.handleToggleCollapsed}><i className='fa fa-sliders' /></div>
+
+        <Motion defaultStyle={{ opacity: 0, height: 0 }} style={{ opacity: spring(collapsed ? 0 : 100), height: spring(collapsed ? 0 : 458) }}>
+          {({ opacity, height }) =>
+            <div style={{ overflow: 'hidden', height: `${height}px`, opacity: opacity / 100 }}>
+              <div style={outerStyle}>
+                <span style={sectionStyle}><FormattedMessage id='notifications.column_settings.follow' defaultMessage='New followers:' /></span>
+
+                <div style={rowStyle}>
+                  <label style={labelStyle}>
+                    <Toggle checked={settings.getIn(['alerts', 'follow'])} onChange={this.handleChange.bind(this, ['alerts', 'follow'])} />
+                    <span style={labelSpanStyle}>{alertStr}</span>
+                  </label>
+
+                  <label style={labelStyle}>
+                    <Toggle checked={settings.getIn(['shows', 'follow'])} onChange={this.handleChange.bind(this, ['shows', 'follow'])} />
+                    <span style={labelSpanStyle}>{showStr}</span>
+                  </label>
+                </div>
+
+                <span style={sectionStyle}><FormattedMessage id='notifications.column_settings.favourite' defaultMessage='Favourites:' /></span>
+
+                <div style={rowStyle}>
+                  <label style={labelStyle}>
+                    <Toggle checked={settings.getIn(['alerts', 'favourite'])} onChange={this.handleChange.bind(this, ['alerts', 'favourite'])} />
+                    <span style={labelSpanStyle}>{alertStr}</span>
+                  </label>
+
+                  <label style={labelStyle}>
+                    <Toggle checked={settings.getIn(['shows', 'favourite'])} onChange={this.handleChange.bind(this, ['shows', 'favourite'])} />
+                    <span style={labelSpanStyle}>{showStr}</span>
+                  </label>
+                </div>
+
+                <span style={sectionStyle}><FormattedMessage id='notifications.column_settings.mention' defaultMessage='Mentions:' /></span>
+
+                <div style={rowStyle}>
+                  <label style={labelStyle}>
+                    <Toggle checked={settings.getIn(['alerts', 'mention'])} onChange={this.handleChange.bind(this, ['alerts', 'mention'])} />
+                    <span style={labelSpanStyle}>{alertStr}</span>
+                  </label>
+
+                  <label style={labelStyle}>
+                    <Toggle checked={settings.getIn(['shows', 'mention'])} onChange={this.handleChange.bind(this, ['shows', 'mention'])} />
+                    <span style={labelSpanStyle}>{showStr}</span>
+                  </label>
+                </div>
+
+                <span style={sectionStyle}><FormattedMessage id='notifications.column_settings.reblog' defaultMessage='Boosts:' /></span>
+
+                <div style={rowStyle}>
+                  <label style={labelStyle}>
+                    <Toggle checked={settings.getIn(['alerts', 'reblog'])} onChange={this.handleChange.bind(this, ['alerts', 'reblog'])} />
+                    <span style={labelSpanStyle}>{alertStr}</span>
+                  </label>
+
+                  <label style={labelStyle}>
+                    <Toggle checked={settings.getIn(['shows', 'reblog'])} onChange={this.handleChange.bind(this, ['shows', 'reblog'])} />
+                    <span style={labelSpanStyle}>{showStr}</span>
+                  </label>
+                </div>
+              </div>
+            </div>
+          }
+        </Motion>
+      </div>
+    );
+  }
+
+});
+
+export default ColumnSettings;
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
new file mode 100644
index 000000000..6907fd351
--- /dev/null
+++ b/app/assets/javascripts/components/features/notifications/containers/column_settings_container.jsx
@@ -0,0 +1,17 @@
+import { connect } from 'react-redux';
+import ColumnSettings from '../components/column_settings';
+import { changeNotificationsSetting } from '../../../actions/notifications';
+
+const mapStateToProps = state => ({
+  settings: state.getIn(['notifications', 'settings'])
+});
+
+const mapDispatchToProps = dispatch => ({
+
+  onChange (key, checked) {
+    dispatch(changeNotificationsSetting(key, checked));
+  }
+
+});
+
+export default connect(mapStateToProps, mapDispatchToProps)(ColumnSettings);
diff --git a/app/assets/javascripts/components/features/notifications/index.jsx b/app/assets/javascripts/components/features/notifications/index.jsx
index 218196cfd..7e706ad6a 100644
--- a/app/assets/javascripts/components/features/notifications/index.jsx
+++ b/app/assets/javascripts/components/features/notifications/index.jsx
@@ -9,13 +9,21 @@ import {
 import NotificationContainer from './containers/notification_container';
 import { ScrollContainer } from 'react-router-scroll';
 import { defineMessages, injectIntl } from 'react-intl';
+import ColumnSettingsContainer from './containers/column_settings_container';
+import { createSelector } from 'reselect';
+import Immutable from 'immutable';
 
 const messages = defineMessages({
   title: { id: 'column.notifications', defaultMessage: 'Notifications' }
 });
 
+const getNotifications = createSelector([
+  state => Immutable.List(state.getIn(['notifications', 'settings', 'shows']).filter(item => !item).keys()),
+  state => state.getIn(['notifications', 'items'])
+], (excludedTypes, notifications) => notifications.filterNot(item => excludedTypes.includes(item.get('type'))));
+
 const mapStateToProps = state => ({
-  notifications: state.getIn(['notifications', 'items'])
+  notifications: getNotifications(state)
 });
 
 const Notifications = React.createClass({
@@ -23,7 +31,8 @@ const Notifications = React.createClass({
   propTypes: {
     notifications: ImmutablePropTypes.list.isRequired,
     dispatch: React.PropTypes.func.isRequired,
-    trackScroll: React.PropTypes.bool
+    trackScroll: React.PropTypes.bool,
+    intl: React.PropTypes.object.isRequired
   },
 
   getDefaultProps () {
@@ -69,6 +78,7 @@ const Notifications = React.createClass({
     } else {
       return (
         <Column icon='bell' heading={intl.formatMessage(messages.title)}>
+          <ColumnSettingsContainer />
           {scrollableArea}
         </Column>
       );