Show donor badge
This commit is contained in:
parent
4c6589637d
commit
44e882d7fc
8 changed files with 103 additions and 14 deletions
|
@ -4,28 +4,59 @@ export const PATRON_INSTANCE_FETCH_REQUEST = 'PATRON_INSTANCE_FETCH_REQUEST';
|
|||
export const PATRON_INSTANCE_FETCH_SUCCESS = 'PATRON_INSTANCE_FETCH_SUCCESS';
|
||||
export const PATRON_INSTANCE_FETCH_FAIL = 'PATRON_INSTANCE_FETCH_FAIL';
|
||||
|
||||
export const PATRON_ACCOUNT_FETCH_REQUEST = 'PATRON_ACCOUNT_FETCH_REQUEST';
|
||||
export const PATRON_ACCOUNT_FETCH_SUCCESS = 'PATRON_ACCOUNT_FETCH_SUCCESS';
|
||||
export const PATRON_ACCOUNT_FETCH_FAIL = 'PATRON_ACCOUNT_FETCH_FAIL';
|
||||
|
||||
export function fetchPatronInstance() {
|
||||
return (dispatch, getState) => {
|
||||
dispatch({ type: PATRON_INSTANCE_FETCH_REQUEST });
|
||||
api(getState).get('/api/patron/v1/instance').then(response => {
|
||||
dispatch(importFetchedFunding(response.data));
|
||||
dispatch(importFetchedInstance(response.data));
|
||||
}).catch(error => {
|
||||
dispatch(fetchFundingFail(error));
|
||||
dispatch(fetchInstanceFail(error));
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export function importFetchedFunding(instance) {
|
||||
export function fetchPatronAccount(apId) {
|
||||
return (dispatch, getState) => {
|
||||
apId = encodeURIComponent(apId);
|
||||
dispatch({ type: PATRON_ACCOUNT_FETCH_REQUEST });
|
||||
api(getState).get(`/api/patron/v1/accounts/${apId}`).then(response => {
|
||||
dispatch(importFetchedAccount(response.data));
|
||||
}).catch(error => {
|
||||
dispatch(fetchAccountFail(error));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function importFetchedInstance(instance) {
|
||||
return {
|
||||
type: PATRON_INSTANCE_FETCH_SUCCESS,
|
||||
instance,
|
||||
};
|
||||
}
|
||||
|
||||
export function fetchFundingFail(error) {
|
||||
function fetchInstanceFail(error) {
|
||||
return {
|
||||
type: PATRON_INSTANCE_FETCH_FAIL,
|
||||
error,
|
||||
skipAlert: true,
|
||||
};
|
||||
};
|
||||
|
||||
function importFetchedAccount(account) {
|
||||
return {
|
||||
type: PATRON_ACCOUNT_FETCH_SUCCESS,
|
||||
account,
|
||||
};
|
||||
}
|
||||
|
||||
function fetchAccountFail(error) {
|
||||
return {
|
||||
type: PATRON_ACCOUNT_FETCH_FAIL,
|
||||
error,
|
||||
skipAlert: true,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ const mapStateToProps = state => {
|
|||
return {
|
||||
account: getAccount(state, me),
|
||||
sidebarOpen: state.get('sidebar').sidebarOpen,
|
||||
donateUrl: state.getIn(['patron', 'url']),
|
||||
donateUrl: state.getIn(['patron', 'instance', 'url']),
|
||||
isStaff: isStaff(state.getIn(['accounts', me])),
|
||||
};
|
||||
};
|
||||
|
|
|
@ -13,6 +13,7 @@ import { FormattedMessage } from 'react-intl';
|
|||
import { fetchAccountIdentityProofs } from '../../actions/identity_proofs';
|
||||
import MissingIndicator from 'soapbox/components/missing_indicator';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
import { fetchPatronAccount } from '../../actions/patron';
|
||||
|
||||
const emptyList = ImmutableList();
|
||||
|
||||
|
@ -23,12 +24,14 @@ const mapStateToProps = (state, { params: { username }, withReplies = false }) =
|
|||
|
||||
let accountId = -1;
|
||||
let accountUsername = username;
|
||||
let accountApId = null;
|
||||
if (accountFetchError) {
|
||||
accountId = null;
|
||||
} else {
|
||||
let account = accounts.find(acct => username.toLowerCase() === acct.getIn(['acct'], '').toLowerCase());
|
||||
accountId = account ? account.getIn(['id'], null) : -1;
|
||||
accountUsername = account ? account.getIn(['acct'], '') : '';
|
||||
accountApId = account ? account.get('url') : '';
|
||||
}
|
||||
|
||||
const path = withReplies ? `${accountId}:with_replies` : accountId;
|
||||
|
@ -40,12 +43,14 @@ const mapStateToProps = (state, { params: { username }, withReplies = false }) =
|
|||
accountId,
|
||||
unavailable,
|
||||
accountUsername,
|
||||
accountApId,
|
||||
isAccount: !!state.getIn(['accounts', accountId]),
|
||||
statusIds: state.getIn(['timelines', `account:${path}`, 'items'], emptyList),
|
||||
featuredStatusIds: withReplies ? ImmutableList() : state.getIn(['timelines', `account:${accountId}:pinned`, 'items'], emptyList),
|
||||
isLoading: state.getIn(['timelines', `account:${path}`, 'isLoading']),
|
||||
hasMore: state.getIn(['timelines', `account:${path}`, 'hasMore']),
|
||||
me,
|
||||
patronEnabled: state.getIn(['soapbox', 'extensions', 'patron', 'enabled']),
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -65,7 +70,7 @@ class AccountTimeline extends ImmutablePureComponent {
|
|||
};
|
||||
|
||||
componentDidMount() {
|
||||
const { params: { username }, accountId, withReplies, me } = this.props;
|
||||
const { params: { username }, accountId, accountApId, withReplies, me, patronEnabled } = this.props;
|
||||
|
||||
if (accountId && accountId !== -1) {
|
||||
this.props.dispatch(fetchAccount(accountId));
|
||||
|
@ -75,6 +80,10 @@ class AccountTimeline extends ImmutablePureComponent {
|
|||
this.props.dispatch(expandAccountFeaturedTimeline(accountId));
|
||||
}
|
||||
|
||||
if (patronEnabled && accountApId) {
|
||||
this.props.dispatch(fetchPatronAccount(accountApId));
|
||||
}
|
||||
|
||||
this.props.dispatch(expandAccountTimeline(accountId, { withReplies }));
|
||||
} else {
|
||||
this.props.dispatch(fetchAccountByUsername(username));
|
||||
|
@ -82,7 +91,7 @@ class AccountTimeline extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
const { me, accountId, withReplies } = this.props;
|
||||
const { me, accountId, withReplies, accountApId, patronEnabled } = this.props;
|
||||
if (accountId && accountId !== -1 && (accountId !== prevProps.accountId && accountId) || withReplies !== prevProps.withReplies) {
|
||||
this.props.dispatch(fetchAccount(accountId));
|
||||
if (me) this.props.dispatch(fetchAccountIdentityProofs(accountId));
|
||||
|
@ -91,6 +100,10 @@ class AccountTimeline extends ImmutablePureComponent {
|
|||
this.props.dispatch(expandAccountFeaturedTimeline(accountId));
|
||||
}
|
||||
|
||||
if (patronEnabled && accountApId) {
|
||||
this.props.dispatch(fetchPatronAccount(accountApId));
|
||||
}
|
||||
|
||||
this.props.dispatch(expandAccountTimeline(accountId, { withReplies }));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import { injectIntl } from 'react-intl';
|
|||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import ProgressBar from '../../../components/progress_bar';
|
||||
import { fetchPatronInstance } from 'soapbox/actions/patron';
|
||||
import { Map as ImmutableMap } from 'immutable';
|
||||
|
||||
const moneyFormat = amount => (
|
||||
new Intl
|
||||
|
@ -63,7 +64,7 @@ class FundingPanel extends ImmutablePureComponent {
|
|||
|
||||
const mapStateToProps = state => {
|
||||
return {
|
||||
patron: state.get('patron'),
|
||||
patron: state.getIn(['patron', 'instance'], ImmutableMap()),
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -11,10 +11,12 @@ import SignUpPanel from '../features/ui/components/sign_up_panel';
|
|||
import ProfileInfoPanel from '../features/ui/components/profile_info_panel';
|
||||
import { acctFull } from 'soapbox/utils/accounts';
|
||||
import { getFeatures } from 'soapbox/utils/features';
|
||||
import { makeGetAccount } from '../selectors';
|
||||
|
||||
const mapStateToProps = (state, { params: { username }, withReplies = false }) => {
|
||||
const accounts = state.getIn(['accounts']);
|
||||
const accountFetchError = (state.getIn(['accounts', -1, 'username'], '').toLowerCase() === username.toLowerCase());
|
||||
const getAccount = makeGetAccount();
|
||||
|
||||
let accountId = -1;
|
||||
let account = null;
|
||||
|
@ -30,7 +32,7 @@ const mapStateToProps = (state, { params: { username }, withReplies = false }) =
|
|||
//Children components fetch information
|
||||
|
||||
return {
|
||||
account,
|
||||
account: accountId ? getAccount(state, accountId) : account,
|
||||
accountId,
|
||||
accountUsername,
|
||||
features: getFeatures(state.get('instance')),
|
||||
|
|
|
@ -1,8 +1,29 @@
|
|||
import reducer from '../patron';
|
||||
import { Map as ImmutableMap } from 'immutable';
|
||||
import { PATRON_ACCOUNT_FETCH_SUCCESS } from '../../actions/patron';
|
||||
import { Map as ImmutableMap, fromJS } from 'immutable';
|
||||
|
||||
describe('patron reducer', () => {
|
||||
it('should return the initial state', () => {
|
||||
expect(reducer(undefined, {})).toEqual(ImmutableMap());
|
||||
});
|
||||
|
||||
describe('PATRON_ACCOUNT_FETCH_SUCCESS', () => {
|
||||
it('should add the account', () => {
|
||||
const action = {
|
||||
type: PATRON_ACCOUNT_FETCH_SUCCESS,
|
||||
account: {
|
||||
url: 'https://gleasonator.com/users/alex',
|
||||
is_patron: true,
|
||||
},
|
||||
};
|
||||
const state = ImmutableMap();
|
||||
expect(reducer(state, action)).toEqual(fromJS({
|
||||
accounts: {
|
||||
'https://gleasonator.com/users/alex': {
|
||||
is_patron: true,
|
||||
},
|
||||
},
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,12 +1,22 @@
|
|||
import { PATRON_INSTANCE_FETCH_SUCCESS } from '../actions/patron';
|
||||
import {
|
||||
PATRON_INSTANCE_FETCH_SUCCESS,
|
||||
PATRON_ACCOUNT_FETCH_SUCCESS,
|
||||
} from '../actions/patron';
|
||||
import { Map as ImmutableMap, fromJS } from 'immutable';
|
||||
|
||||
const initialState = ImmutableMap();
|
||||
|
||||
const normalizePatronAccount = (state, account) => {
|
||||
const normalized = fromJS(account).deleteAll(['url']);
|
||||
return state.setIn(['accounts', account.url], normalized);
|
||||
};
|
||||
|
||||
export default function patron(state = initialState, action) {
|
||||
switch(action.type) {
|
||||
case PATRON_INSTANCE_FETCH_SUCCESS:
|
||||
return fromJS(action.instance);
|
||||
return state.set('instance', fromJS(action.instance));
|
||||
case PATRON_ACCOUNT_FETCH_SUCCESS:
|
||||
return normalizePatronAccount(state, action.account);
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
|
|
@ -5,9 +5,19 @@ const getAccountBase = (state, id) => state.getIn(['accounts', id], null
|
|||
const getAccountCounters = (state, id) => state.getIn(['accounts_counters', id], null);
|
||||
const getAccountRelationship = (state, id) => state.getIn(['relationships', id], null);
|
||||
const getAccountMoved = (state, id) => state.getIn(['accounts', state.getIn(['accounts', id, 'moved'])]);
|
||||
const getAccountPatron = (state, id) => {
|
||||
const url = state.getIn(['accounts', id, 'url']);
|
||||
return state.getIn(['patron', 'accounts', url]);
|
||||
};
|
||||
|
||||
export const makeGetAccount = () => {
|
||||
return createSelector([getAccountBase, getAccountCounters, getAccountRelationship, getAccountMoved], (base, counters, relationship, moved) => {
|
||||
return createSelector([
|
||||
getAccountBase,
|
||||
getAccountCounters,
|
||||
getAccountRelationship,
|
||||
getAccountMoved,
|
||||
getAccountPatron,
|
||||
], (base, counters, relationship, moved, patron) => {
|
||||
if (base === null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -15,6 +25,7 @@ export const makeGetAccount = () => {
|
|||
return base.merge(counters).withMutations(map => {
|
||||
map.set('relationship', relationship);
|
||||
map.set('moved', moved);
|
||||
map.set('patron', patron);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue