about summary refs log tree commit diff
path: root/app/javascript/flavours/glitch/features/hashtag_timeline/components/column_settings.js
blob: ede8907e50bd6156b9267dcd2fd6ae79aa5f504e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import React from 'react';
import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import Toggle from 'react-toggle';
import AsyncSelect from 'react-select/async';
import { NonceProvider } from 'react-select';
import SettingToggle from '../../notifications/components/setting_toggle';

const messages = defineMessages({
  placeholder: { id: 'hashtag.column_settings.select.placeholder', defaultMessage: 'Enter hashtags…' },
  noOptions: { id: 'hashtag.column_settings.select.no_options_message', defaultMessage: 'No suggestions found' },
});

export default @injectIntl
class ColumnSettings extends React.PureComponent {

  static propTypes = {
    settings: ImmutablePropTypes.map.isRequired,
    onChange: PropTypes.func.isRequired,
    onLoad: PropTypes.func.isRequired,
    intl: PropTypes.object.isRequired,
  };

  state = {
    open: this.hasTags(),
  };

  hasTags () {
    return ['all', 'any', 'none'].map(mode => this.tags(mode).length > 0).includes(true);
  }

  tags (mode) {
    let tags = this.props.settings.getIn(['tags', mode]) || [];

    if (tags.toJS) {
      return tags.toJS();
    } else {
      return tags;
    }
  };

  onSelect = mode => value => {
    const oldValue = this.tags(mode);

    // Prevent changes that add more than 4 tags, but allow removing
    // tags that were already added before
    if ((value.length > 4) && !(value < oldValue)) {
      return;
    }

    this.props.onChange(['tags', mode], value);
  };

  onToggle = () => {
    if (this.state.open && this.hasTags()) {
      this.props.onChange('tags', {});
    }

    this.setState({ open: !this.state.open });
  };

  noOptionsMessage = () => this.props.intl.formatMessage(messages.noOptions);

  modeSelect (mode) {
    return (
      <div className='column-settings__row'>
        <span className='column-settings__section'>
          {this.modeLabel(mode)}
        </span>

        <NonceProvider nonce={document.querySelector('meta[name=style-nonce]').content} cacheKey='tags'>
          <AsyncSelect
            isMulti
            autoFocus
            value={this.tags(mode)}
            onChange={this.onSelect(mode)}
            loadOptions={this.props.onLoad}
            className='column-select__container'
            classNamePrefix='column-select'
            name='tags'
            placeholder={this.props.intl.formatMessage(messages.placeholder)}
            noOptionsMessage={this.noOptionsMessage}
          />
        </NonceProvider>
      </div>
    );
  }

  modeLabel (mode) {
    switch(mode) {
    case 'any':
      return <FormattedMessage id='hashtag.column_settings.tag_mode.any' defaultMessage='Any of these' />;
    case 'all':
      return <FormattedMessage id='hashtag.column_settings.tag_mode.all' defaultMessage='All of these' />;
    case 'none':
      return <FormattedMessage id='hashtag.column_settings.tag_mode.none' defaultMessage='None of these' />;
    default:
      return '';
    }
  };

  render () {
    const { settings, onChange } = this.props;

    return (
      <div>
        <div className='column-settings__row'>
          <div className='setting-toggle'>
            <Toggle id='hashtag.column_settings.tag_toggle' onChange={this.onToggle} checked={this.state.open} />

            <span className='setting-toggle__label'>
              <FormattedMessage id='hashtag.column_settings.tag_toggle' defaultMessage='Include additional tags in this column' />
            </span>
          </div>
        </div>

        {this.state.open && (
          <div className='column-settings__hashtags'>
            {this.modeSelect('any')}
            {this.modeSelect('all')}
            {this.modeSelect('none')}
          </div>
        )}

        <div className='column-settings__row'>
          <SettingToggle settings={settings} settingPath={['local']} onChange={onChange} label={<FormattedMessage id='community.column_settings.local_only' defaultMessage='Local only' />} />
        </div>
      </div>
    );
  }

}