Add antenna exclusion adder dialog
This commit is contained in:
parent
1461ab0a2f
commit
4fbebebcb3
12 changed files with 143 additions and 28 deletions
|
@ -0,0 +1,18 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::Accounts::ExcludeAntennasController < Api::BaseController
|
||||
before_action -> { doorkeeper_authorize! :read, :'read:lists' }
|
||||
before_action :require_user!
|
||||
before_action :set_account
|
||||
|
||||
def index
|
||||
@antennas = @account.suspended? ? [] : current_account.antennas.where('exclude_accounts @> \'[?]\'', @account.id)
|
||||
render json: @antennas, each_serializer: REST::AntennaSerializer
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_account
|
||||
@account = Account.find(params[:account_id])
|
||||
end
|
||||
end
|
|
@ -122,6 +122,10 @@ export const ANTENNA_ADDER_ANTENNAS_FETCH_REQUEST = 'ANTENNA_ADDER_ANTENNAS_FETC
|
|||
export const ANTENNA_ADDER_ANTENNAS_FETCH_SUCCESS = 'ANTENNA_ADDER_ANTENNAS_FETCH_SUCCESS';
|
||||
export const ANTENNA_ADDER_ANTENNAS_FETCH_FAIL = 'ANTENNA_ADDER_ANTENNAS_FETCH_FAIL';
|
||||
|
||||
export const ANTENNA_ADDER_EXCLUDE_ANTENNAS_FETCH_REQUEST = 'ANTENNA_ADDER_EXCLUDE_ANTENNAS_FETCH_REQUEST';
|
||||
export const ANTENNA_ADDER_EXCLUDE_ANTENNAS_FETCH_SUCCESS = 'ANTENNA_ADDER_EXCLUDE_ANTENNAS_FETCH_SUCCESS';
|
||||
export const ANTENNA_ADDER_EXCLUDE_ANTENNAS_FETCH_FAIL = 'ANTENNA_ADDER_EXCLUDE_ANTENNAS_FETCH_FAIL';
|
||||
|
||||
export const fetchAntenna = id => (dispatch, getState) => {
|
||||
if (getState().getIn(['antennas', id])) {
|
||||
return;
|
||||
|
@ -905,6 +909,15 @@ export const setupAntennaAdder = accountId => (dispatch, getState) => {
|
|||
dispatch(fetchAccountAntennas(accountId));
|
||||
};
|
||||
|
||||
export const setupExcludeAntennaAdder = accountId => (dispatch, getState) => {
|
||||
dispatch({
|
||||
type: ANTENNA_ADDER_SETUP,
|
||||
account: getState().getIn(['accounts', accountId]),
|
||||
});
|
||||
dispatch(fetchAntennas());
|
||||
dispatch(fetchExcludeAccountAntennas(accountId));
|
||||
};
|
||||
|
||||
export const fetchAccountAntennas = accountId => (dispatch, getState) => {
|
||||
dispatch(fetchAccountAntennasRequest(accountId));
|
||||
|
||||
|
@ -930,6 +943,31 @@ export const fetchAccountAntennasFail = (id, err) => ({
|
|||
err,
|
||||
});
|
||||
|
||||
export const fetchExcludeAccountAntennas = accountId => (dispatch, getState) => {
|
||||
dispatch(fetchExcludeAccountAntennasRequest(accountId));
|
||||
|
||||
api(getState).get(`/api/v1/accounts/${accountId}/exclude_antennas`)
|
||||
.then(({ data }) => dispatch(fetchExcludeAccountAntennasSuccess(accountId, data)))
|
||||
.catch(err => dispatch(fetchExcludeAccountAntennasFail(accountId, err)));
|
||||
};
|
||||
|
||||
export const fetchExcludeAccountAntennasRequest = id => ({
|
||||
type:ANTENNA_ADDER_EXCLUDE_ANTENNAS_FETCH_REQUEST,
|
||||
id,
|
||||
});
|
||||
|
||||
export const fetchExcludeAccountAntennasSuccess = (id, antennas) => ({
|
||||
type: ANTENNA_ADDER_EXCLUDE_ANTENNAS_FETCH_SUCCESS,
|
||||
id,
|
||||
antennas,
|
||||
});
|
||||
|
||||
export const fetchExcludeAccountAntennasFail = (id, err) => ({
|
||||
type: ANTENNA_ADDER_EXCLUDE_ANTENNAS_FETCH_FAIL,
|
||||
id,
|
||||
err,
|
||||
});
|
||||
|
||||
export const addToAntennaAdder = antennaId => (dispatch, getState) => {
|
||||
dispatch(addToAntenna(antennaId, getState().getIn(['antennaAdder', 'accountId'])));
|
||||
};
|
||||
|
@ -938,3 +976,11 @@ export const removeFromAntennaAdder = antennaId => (dispatch, getState) => {
|
|||
dispatch(removeFromAntenna(antennaId, getState().getIn(['antennaAdder', 'accountId'])));
|
||||
};
|
||||
|
||||
export const addExcludeToAntennaAdder = antennaId => (dispatch, getState) => {
|
||||
dispatch(addExcludeToAntenna(antennaId, getState().getIn(['antennaAdder', 'accountId'])));
|
||||
};
|
||||
|
||||
export const removeExcludeFromAntennaAdder = antennaId => (dispatch, getState) => {
|
||||
dispatch(removeExcludeFromAntenna(antennaId, getState().getIn(['antennaAdder', 'accountId'])));
|
||||
};
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ const messages = defineMessages({
|
|||
unendorse: { id: 'account.unendorse', defaultMessage: 'Don\'t feature on profile' },
|
||||
add_or_remove_from_list: { id: 'account.add_or_remove_from_list', defaultMessage: 'Add or Remove from lists' },
|
||||
add_or_remove_from_antenna: { id: 'account.add_or_remove_from_antenna', defaultMessage: 'Add or Remove from antennas' },
|
||||
add_or_remove_from_exclude_antenna: { id: 'account.add_or_remove_from_exclude_antenna', defaultMessage: 'Add or Remove from antennas as exclusion' },
|
||||
add_or_remove_from_circle: { id: 'account.add_or_remove_from_circle', defaultMessage: 'Add or Remove from circles' },
|
||||
admin_account: { id: 'status.admin_account', defaultMessage: 'Open moderation interface for @{name}' },
|
||||
admin_domain: { id: 'status.admin_domain', defaultMessage: 'Open moderation interface for {domain}' },
|
||||
|
@ -106,6 +107,7 @@ class Header extends ImmutablePureComponent {
|
|||
onEndorseToggle: PropTypes.func.isRequired,
|
||||
onAddToList: PropTypes.func.isRequired,
|
||||
onAddToAntenna: PropTypes.func.isRequired,
|
||||
onAddToExcludeAntenna: PropTypes.func.isRequired,
|
||||
onAddToCircle: PropTypes.func.isRequired,
|
||||
onEditAccountNote: PropTypes.func.isRequired,
|
||||
onChangeLanguages: PropTypes.func.isRequired,
|
||||
|
@ -332,6 +334,7 @@ class Header extends ImmutablePureComponent {
|
|||
menu.push({ text: intl.formatMessage(messages.add_or_remove_from_list), action: this.props.onAddToList });
|
||||
}
|
||||
menu.push({ text: intl.formatMessage(messages.add_or_remove_from_antenna), action: this.props.onAddToAntenna });
|
||||
menu.push({ text: intl.formatMessage(messages.add_or_remove_from_exclude_antenna), action: this.props.onAddToExcludeAntenna });
|
||||
if (account.getIn(['relationship', 'followed_by'])) {
|
||||
menu.push({ text: intl.formatMessage(messages.add_or_remove_from_circle), action: this.props.onAddToCircle });
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ export default class Header extends ImmutablePureComponent {
|
|||
onEndorseToggle: PropTypes.func.isRequired,
|
||||
onAddToList: PropTypes.func.isRequired,
|
||||
onAddToAntenna: PropTypes.func.isRequired,
|
||||
onAddToExcludeAntenna: PropTypes.func.isRequired,
|
||||
onAddToCircle: PropTypes.func.isRequired,
|
||||
onChangeLanguages: PropTypes.func.isRequired,
|
||||
onInteractionModal: PropTypes.func.isRequired,
|
||||
|
@ -102,6 +103,10 @@ export default class Header extends ImmutablePureComponent {
|
|||
this.props.onAddToAntenna(this.props.account);
|
||||
};
|
||||
|
||||
handleAddToExcludeAntenna = () => {
|
||||
this.props.onAddToExcludeAntenna(this.props.account);
|
||||
};
|
||||
|
||||
handleAddToCircle = () => {
|
||||
this.props.onAddToCircle(this.props.account);
|
||||
};
|
||||
|
@ -149,6 +154,7 @@ export default class Header extends ImmutablePureComponent {
|
|||
onEndorseToggle={this.handleEndorseToggle}
|
||||
onAddToList={this.handleAddToList}
|
||||
onAddToAntenna={this.handleAddToAntenna}
|
||||
onAddToExcludeAntenna={this.handleAddToExcludeAntenna}
|
||||
onAddToCircle={this.handleAddToCircle}
|
||||
onEditAccountNote={this.handleEditAccountNote}
|
||||
onChangeLanguages={this.handleChangeLanguages}
|
||||
|
|
|
@ -169,6 +169,17 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
|
|||
modalType: 'ANTENNA_ADDER',
|
||||
modalProps: {
|
||||
accountId: account.get('id'),
|
||||
isExclude: false,
|
||||
},
|
||||
}));
|
||||
},
|
||||
|
||||
onAddToExcludeAntenna (account) {
|
||||
dispatch(openModal({
|
||||
modalType: 'ANTENNA_ADDER',
|
||||
modalProps: {
|
||||
accountId: account.get('id'),
|
||||
isExclude: true,
|
||||
},
|
||||
}));
|
||||
},
|
||||
|
|
|
@ -8,7 +8,7 @@ import { connect } from 'react-redux';
|
|||
|
||||
import { Icon } from 'mastodon/components/icon';
|
||||
|
||||
import { removeFromAntennaAdder, addToAntennaAdder } from '../../../actions/antennas';
|
||||
import { removeFromAntennaAdder, addToAntennaAdder, removeExcludeFromAntennaAdder, addExcludeToAntennaAdder } from '../../../actions/antennas';
|
||||
import { IconButton } from '../../../components/icon_button';
|
||||
|
||||
const messages = defineMessages({
|
||||
|
@ -24,15 +24,20 @@ const MapStateToProps = (state, { antennaId, added }) => ({
|
|||
const mapDispatchToProps = (dispatch, { antennaId }) => ({
|
||||
onRemove: () => dispatch(removeFromAntennaAdder(antennaId)),
|
||||
onAdd: () => dispatch(addToAntennaAdder(antennaId)),
|
||||
onExcludeRemove: () => dispatch(removeExcludeFromAntennaAdder(antennaId)),
|
||||
onExcludeAdd: () => dispatch(addExcludeToAntennaAdder(antennaId)),
|
||||
});
|
||||
|
||||
class Antenna extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
antenna: ImmutablePropTypes.map.isRequired,
|
||||
isExclude: PropTypes.bool.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
onRemove: PropTypes.func.isRequired,
|
||||
onAdd: PropTypes.func.isRequired,
|
||||
onExcludeRemove: PropTypes.func.isRequired,
|
||||
onExcludeAdd: PropTypes.func.isRequired,
|
||||
added: PropTypes.bool,
|
||||
};
|
||||
|
||||
|
@ -40,15 +45,31 @@ class Antenna extends ImmutablePureComponent {
|
|||
added: false,
|
||||
};
|
||||
|
||||
handleRemove = () => {
|
||||
if (this.props.isExclude) {
|
||||
this.props.onExcludeRemove();
|
||||
} else {
|
||||
this.props.onRemove();
|
||||
}
|
||||
};
|
||||
|
||||
handleAdd = () => {
|
||||
if (this.props.isExclude) {
|
||||
this.props.onExcludeAdd();
|
||||
} else {
|
||||
this.props.onAdd();
|
||||
}
|
||||
};
|
||||
|
||||
render () {
|
||||
const { antenna, intl, onRemove, onAdd, added } = this.props;
|
||||
const { antenna, intl, added } = this.props;
|
||||
|
||||
let button;
|
||||
|
||||
if (added) {
|
||||
button = <IconButton icon='times' title={intl.formatMessage(messages.remove)} onClick={onRemove} />;
|
||||
button = <IconButton icon='times' title={intl.formatMessage(messages.remove)} onClick={this.handleRemove} />;
|
||||
} else {
|
||||
button = <IconButton icon='plus' title={intl.formatMessage(messages.add)} onClick={onAdd} />;
|
||||
button = <IconButton icon='plus' title={intl.formatMessage(messages.add)} onClick={this.handleAdd} />;
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
|
@ -7,7 +7,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
|
|||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
|
||||
import { setupAntennaAdder, resetAntennaAdder } from '../../actions/antennas';
|
||||
import { setupAntennaAdder, resetAntennaAdder, setupExcludeAntennaAdder } from '../../actions/antennas';
|
||||
import NewAntennaForm from '../antennas/components/new_antenna_form';
|
||||
import Account from '../list_adder/components/account';
|
||||
|
||||
|
@ -28,6 +28,7 @@ const mapStateToProps = state => ({
|
|||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
onInitialize: accountId => dispatch(setupAntennaAdder(accountId)),
|
||||
onExcludeInitialize: accountId => dispatch(setupExcludeAntennaAdder(accountId)),
|
||||
onReset: () => dispatch(resetAntennaAdder()),
|
||||
});
|
||||
|
||||
|
@ -35,17 +36,23 @@ class AntennaAdder extends ImmutablePureComponent {
|
|||
|
||||
static propTypes = {
|
||||
accountId: PropTypes.string.isRequired,
|
||||
isExclude: PropTypes.bool.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
onInitialize: PropTypes.func.isRequired,
|
||||
onExcludeInitialize: PropTypes.func.isRequired,
|
||||
onReset: PropTypes.func.isRequired,
|
||||
antennaIds: ImmutablePropTypes.list.isRequired,
|
||||
};
|
||||
|
||||
componentDidMount () {
|
||||
const { onInitialize, accountId } = this.props;
|
||||
const { isExclude, onInitialize, onExcludeInitialize, accountId } = this.props;
|
||||
if (isExclude) {
|
||||
onExcludeInitialize(accountId);
|
||||
} else {
|
||||
onInitialize(accountId);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
const { onReset } = this.props;
|
||||
|
@ -53,7 +60,7 @@ class AntennaAdder extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
render () {
|
||||
const { accountId, antennaIds } = this.props;
|
||||
const { accountId, antennaIds, isExclude } = this.props;
|
||||
|
||||
return (
|
||||
<div className='modal-root__modal list-adder'>
|
||||
|
@ -65,7 +72,7 @@ class AntennaAdder extends ImmutablePureComponent {
|
|||
|
||||
|
||||
<div className='list-adder__lists'>
|
||||
{antennaIds.map(antennaId => <Antenna key={antennaId} antennaId={antennaId} />)}
|
||||
{antennaIds.map(antennaId => <Antenna key={antennaId} antennaId={antennaId} isExclude={isExclude} />)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -20,9 +20,9 @@ const messages = defineMessages({
|
|||
const makeMapStateToProps = () => {
|
||||
const getAccount = makeGetAccount();
|
||||
|
||||
const mapStateToProps = (state, { accountId, added, isExclude }) => ({
|
||||
const mapStateToProps = (state, { accountId, added }) => ({
|
||||
account: getAccount(state, accountId),
|
||||
added: typeof added === 'undefined' ? state.getIn(['antennaEditor', isExclude ? 'excludeAccounts' : 'accounts', 'items']).includes(accountId) : added,
|
||||
added: typeof added === 'undefined' ? state.getIn(['antennaEditor', 'accounts', 'items']).includes(accountId) : added,
|
||||
});
|
||||
|
||||
return mapStateToProps;
|
||||
|
|
|
@ -15,8 +15,8 @@ import Account from './components/account';
|
|||
import EditAntennaForm from './components/edit_antenna_form';
|
||||
import Search from './components/search';
|
||||
|
||||
const mapStateToProps = (state, { isExclude }) => ({
|
||||
accountIds: state.getIn(['antennaEditor', isExclude ? 'excludeAccounts' : 'accounts', 'items']),
|
||||
const mapStateToProps = (state) => ({
|
||||
accountIds: state.getIn(['antennaEditor', 'accounts', 'items']),
|
||||
searchAccountIds: state.getIn(['antennaEditor', 'suggestions', 'items']),
|
||||
});
|
||||
|
||||
|
|
|
@ -6,8 +6,13 @@ import {
|
|||
ANTENNA_ADDER_ANTENNAS_FETCH_REQUEST,
|
||||
ANTENNA_ADDER_ANTENNAS_FETCH_SUCCESS,
|
||||
ANTENNA_ADDER_ANTENNAS_FETCH_FAIL,
|
||||
ANTENNA_ADDER_EXCLUDE_ANTENNAS_FETCH_REQUEST,
|
||||
ANTENNA_ADDER_EXCLUDE_ANTENNAS_FETCH_SUCCESS,
|
||||
ANTENNA_ADDER_EXCLUDE_ANTENNAS_FETCH_FAIL,
|
||||
ANTENNA_EDITOR_ADD_SUCCESS,
|
||||
ANTENNA_EDITOR_REMOVE_SUCCESS,
|
||||
ANTENNA_EDITOR_ADD_EXCLUDE_SUCCESS,
|
||||
ANTENNA_EDITOR_REMOVE_EXCLUDE_SUCCESS,
|
||||
} from '../actions/antennas';
|
||||
|
||||
const initialState = ImmutableMap({
|
||||
|
@ -29,18 +34,23 @@ export default function antennaAdderReducer(state = initialState, action) {
|
|||
map.set('accountId', action.account.get('id'));
|
||||
});
|
||||
case ANTENNA_ADDER_ANTENNAS_FETCH_REQUEST:
|
||||
case ANTENNA_ADDER_EXCLUDE_ANTENNAS_FETCH_REQUEST:
|
||||
return state.setIn(['antennas', 'isLoading'], true);
|
||||
case ANTENNA_ADDER_ANTENNAS_FETCH_FAIL:
|
||||
case ANTENNA_ADDER_EXCLUDE_ANTENNAS_FETCH_FAIL:
|
||||
return state.setIn(['antennas', 'isLoading'], false);
|
||||
case ANTENNA_ADDER_ANTENNAS_FETCH_SUCCESS:
|
||||
case ANTENNA_ADDER_EXCLUDE_ANTENNAS_FETCH_SUCCESS:
|
||||
return state.update('antennas', antennas => antennas.withMutations(map => {
|
||||
map.set('isLoading', false);
|
||||
map.set('loaded', true);
|
||||
map.set('items', ImmutableList(action.antennas.map(item => item.id)));
|
||||
}));
|
||||
case ANTENNA_EDITOR_ADD_SUCCESS:
|
||||
case ANTENNA_EDITOR_ADD_EXCLUDE_SUCCESS:
|
||||
return state.updateIn(['antennas', 'items'], antenna => antenna.unshift(action.antennaId));
|
||||
case ANTENNA_EDITOR_REMOVE_SUCCESS:
|
||||
case ANTENNA_EDITOR_REMOVE_EXCLUDE_SUCCESS:
|
||||
return state.updateIn(['antennas', 'items'], antenna => antenna.filterNot(item => item === action.antennaId));
|
||||
default:
|
||||
return state;
|
||||
|
|
|
@ -38,12 +38,6 @@ const initialState = ImmutableMap({
|
|||
isLoading: false,
|
||||
}),
|
||||
|
||||
excludeAccounts: ImmutableMap({
|
||||
items: ImmutableList(),
|
||||
loaded: false,
|
||||
isLoading: false,
|
||||
}),
|
||||
|
||||
suggestions: ImmutableMap({
|
||||
value: '',
|
||||
items: ImmutableList(),
|
||||
|
@ -92,11 +86,11 @@ export default function antennaEditorReducer(state = initialState, action) {
|
|||
map.set('items', ImmutableList(action.accounts.map(item => item.id)));
|
||||
}));
|
||||
case ANTENNA_EXCLUDE_ACCOUNTS_FETCH_REQUEST:
|
||||
return state.setIn(['excludeAccounts', 'isLoading'], true);
|
||||
return state.setIn(['accounts', 'isLoading'], true);
|
||||
case ANTENNA_EXCLUDE_ACCOUNTS_FETCH_FAIL:
|
||||
return state.setIn(['excludeAccounts', 'isLoading'], false);
|
||||
return state.setIn(['accounts', 'isLoading'], false);
|
||||
case ANTENNA_EXCLUDE_ACCOUNTS_FETCH_SUCCESS:
|
||||
return state.update('excludeAccounts', accounts => accounts.withMutations(map => {
|
||||
return state.update('accounts', accounts => accounts.withMutations(map => {
|
||||
map.set('isLoading', false);
|
||||
map.set('loaded', true);
|
||||
map.set('items', ImmutableList(action.accounts.map(item => item.id)));
|
||||
|
@ -111,13 +105,11 @@ export default function antennaEditorReducer(state = initialState, action) {
|
|||
map.set('value', '');
|
||||
}));
|
||||
case ANTENNA_EDITOR_ADD_SUCCESS:
|
||||
case ANTENNA_EDITOR_ADD_EXCLUDE_SUCCESS:
|
||||
return state.updateIn(['accounts', 'items'], antenna => antenna.unshift(action.accountId));
|
||||
case ANTENNA_EDITOR_REMOVE_SUCCESS:
|
||||
return state.updateIn(['accounts', 'items'], antenna => antenna.filterNot(item => item === action.accountId));
|
||||
case ANTENNA_EDITOR_ADD_EXCLUDE_SUCCESS:
|
||||
return state.updateIn(['excludeAccounts', 'items'], antenna => antenna.unshift(action.accountId));
|
||||
case ANTENNA_EDITOR_REMOVE_EXCLUDE_SUCCESS:
|
||||
return state.updateIn(['excludeAccounts', 'items'], antenna => antenna.filterNot(item => item === action.accountId));
|
||||
return state.updateIn(['accounts', 'items'], antenna => antenna.filterNot(item => item === action.accountId));
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
|
|
@ -180,6 +180,7 @@ namespace :api, format: false do
|
|||
resources :following, only: :index, controller: 'accounts/following_accounts'
|
||||
resources :lists, only: :index, controller: 'accounts/lists'
|
||||
resources :antennas, only: :index, controller: 'accounts/antennas'
|
||||
resources :exclude_antennas, only: :index, controller: 'accounts/exclude_antennas'
|
||||
resources :circles, only: :index, controller: 'accounts/circles'
|
||||
resources :identity_proofs, only: :index, controller: 'accounts/identity_proofs'
|
||||
resources :featured_tags, only: :index, controller: 'accounts/featured_tags'
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue