kopia lustrzana https://gitlab.com/soapbox-pub/soapbox
Add "Donor" badge
rodzic
09ad4f0252
commit
73f086c680
|
@ -274,6 +274,18 @@ export function unverifyUser(accountId) {
|
|||
};
|
||||
}
|
||||
|
||||
export function setDonor(accountId) {
|
||||
return (dispatch, getState) => {
|
||||
return dispatch(tagUsers([accountId], ['donor']));
|
||||
};
|
||||
}
|
||||
|
||||
export function removeDonor(accountId) {
|
||||
return (dispatch, getState) => {
|
||||
return dispatch(untagUsers([accountId], ['donor']));
|
||||
};
|
||||
}
|
||||
|
||||
export function addPermission(accountIds, permissionGroup) {
|
||||
return (dispatch, getState) => {
|
||||
const nicknames = nicknamesFromIds(getState, accountIds);
|
||||
|
|
|
@ -3,7 +3,7 @@ import React from 'react';
|
|||
|
||||
interface IBadge {
|
||||
title: string,
|
||||
slug: 'patron' | 'admin' | 'moderator' | 'bot' | 'opaque',
|
||||
slug: 'patron' | 'donor' | 'admin' | 'moderator' | 'bot' | 'opaque',
|
||||
}
|
||||
|
||||
/** Badge to display on a user's profile. */
|
||||
|
@ -12,6 +12,7 @@ const Badge: React.FC<IBadge> = ({ title, slug }) => (
|
|||
data-testid='badge'
|
||||
className={classNames('inline-flex items-center px-2 py-0.5 rounded text-xs font-medium text-white', {
|
||||
'bg-fuchsia-700': slug === 'patron',
|
||||
'bg-yellow-500': slug === 'donor',
|
||||
'bg-black': slug === 'admin',
|
||||
'bg-cyan-600': slug === 'moderator',
|
||||
'bg-gray-100 text-gray-800': slug === 'bot',
|
||||
|
|
|
@ -36,6 +36,10 @@ const getBadges = (account) => {
|
|||
badges.push(<Badge key='patron' slug='patron' title='Patron' />);
|
||||
}
|
||||
|
||||
if (account.donor) {
|
||||
badges.push(<Badge key='donor' slug='donor' title='Donor' />);
|
||||
}
|
||||
|
||||
return badges;
|
||||
};
|
||||
|
||||
|
|
|
@ -54,6 +54,8 @@ const messages = defineMessages({
|
|||
deleteUser: { id: 'admin.users.actions.delete_user', defaultMessage: 'Delete @{name}' },
|
||||
verifyUser: { id: 'admin.users.actions.verify_user', defaultMessage: 'Verify @{name}' },
|
||||
unverifyUser: { id: 'admin.users.actions.unverify_user', defaultMessage: 'Unverify @{name}' },
|
||||
setDonor: { id: 'admin.users.actions.set_donor', defaultMessage: 'Set @{name} as a donor' },
|
||||
removeDonor: { id: 'admin.users.actions.remove_donor', defaultMessage: 'Remove @{name} as a donor' },
|
||||
promoteToAdmin: { id: 'admin.users.actions.promote_to_admin', defaultMessage: 'Promote @{name} to an admin' },
|
||||
promoteToModerator: { id: 'admin.users.actions.promote_to_moderator', defaultMessage: 'Promote @{name} to a moderator' },
|
||||
demoteToModerator: { id: 'admin.users.actions.demote_to_moderator', defaultMessage: 'Demote @{name} to a moderator' },
|
||||
|
@ -386,20 +388,34 @@ class Header extends ImmutablePureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
if (account.get('verified')) {
|
||||
if (account.verified) {
|
||||
menu.push({
|
||||
text: intl.formatMessage(messages.unverifyUser, { name: account.get('username') }),
|
||||
text: intl.formatMessage(messages.unverifyUser, { name: account.username }),
|
||||
action: this.props.onUnverifyUser,
|
||||
icon: require('@tabler/icons/icons/check.svg'),
|
||||
});
|
||||
} else {
|
||||
menu.push({
|
||||
text: intl.formatMessage(messages.verifyUser, { name: account.get('username') }),
|
||||
text: intl.formatMessage(messages.verifyUser, { name: account.username }),
|
||||
action: this.props.onVerifyUser,
|
||||
icon: require('@tabler/icons/icons/check.svg'),
|
||||
});
|
||||
}
|
||||
|
||||
if (account.donor) {
|
||||
menu.push({
|
||||
text: intl.formatMessage(messages.removeDonor, { name: account.username }),
|
||||
action: this.props.onRemoveDonor,
|
||||
icon: require('@tabler/icons/icons/coin.svg'),
|
||||
});
|
||||
} else {
|
||||
menu.push({
|
||||
text: intl.formatMessage(messages.setDonor, { name: account.username }),
|
||||
action: this.props.onSetDonor,
|
||||
icon: require('@tabler/icons/icons/coin.svg'),
|
||||
});
|
||||
}
|
||||
|
||||
if (features.suggestionsV2 && meAccount.admin) {
|
||||
if (account.getIn(['pleroma', 'is_suggested'])) {
|
||||
menu.push({
|
||||
|
|
|
@ -110,6 +110,14 @@ class Header extends ImmutablePureComponent {
|
|||
this.props.onUnverifyUser(this.props.account);
|
||||
}
|
||||
|
||||
handleSetDonor = () => {
|
||||
this.props.onSetDonor(this.props.account);
|
||||
}
|
||||
|
||||
handleRemoveDonor = () => {
|
||||
this.props.onRemoveDonor(this.props.account);
|
||||
}
|
||||
|
||||
handlePromoteToAdmin = () => {
|
||||
this.props.onPromoteToAdmin(this.props.account);
|
||||
}
|
||||
|
@ -163,6 +171,8 @@ class Header extends ImmutablePureComponent {
|
|||
onDeleteUser={this.handleDeleteUser}
|
||||
onVerifyUser={this.handleVerifyUser}
|
||||
onUnverifyUser={this.handleUnverifyUser}
|
||||
onSetDonor={this.handleSetDonor}
|
||||
onRemoveDonor={this.handleRemoveDonor}
|
||||
onPromoteToAdmin={this.handlePromoteToAdmin}
|
||||
onPromoteToModerator={this.handlePromoteToModerator}
|
||||
onDemoteToUser={this.handleDemoteToUser}
|
||||
|
|
|
@ -18,6 +18,8 @@ import {
|
|||
import {
|
||||
verifyUser,
|
||||
unverifyUser,
|
||||
setDonor,
|
||||
removeDonor,
|
||||
promoteToAdmin,
|
||||
promoteToModerator,
|
||||
demoteToUser,
|
||||
|
@ -47,6 +49,8 @@ const messages = defineMessages({
|
|||
blockAndReport: { id: 'confirmations.block.block_and_report', defaultMessage: 'Block & Report' },
|
||||
userVerified: { id: 'admin.users.user_verified_message', defaultMessage: '@{acct} was verified' },
|
||||
userUnverified: { id: 'admin.users.user_unverified_message', defaultMessage: '@{acct} was unverified' },
|
||||
setDonor: { id: 'admin.users.set_donor_message', defaultMessage: '@{acct} was set as a donor' },
|
||||
removeDonor: { id: 'admin.users.remove_donor_message', defaultMessage: '@{acct} was removed as a donor' },
|
||||
promotedToAdmin: { id: 'admin.users.actions.promote_to_admin_message', defaultMessage: '@{acct} was promoted to an admin' },
|
||||
promotedToModerator: { id: 'admin.users.actions.promote_to_moderator_message', defaultMessage: '@{acct} was promoted to a moderator' },
|
||||
demotedToModerator: { id: 'admin.users.actions.demote_to_moderator_message', defaultMessage: '@{acct} was demoted to a moderator' },
|
||||
|
@ -206,6 +210,23 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
|
|||
.catch(() => {});
|
||||
},
|
||||
|
||||
onSetDonor(account) {
|
||||
const message = intl.formatMessage(messages.setDonor, { acct: account.get('acct') });
|
||||
|
||||
dispatch(setDonor(account.get('id')))
|
||||
.then(() => dispatch(snackbar.success(message)))
|
||||
.catch(() => {});
|
||||
},
|
||||
|
||||
onRemoveDonor(account) {
|
||||
const message = intl.formatMessage(messages.removeDonor, { acct: account.get('acct') });
|
||||
|
||||
dispatch(removeDonor(account.get('id')))
|
||||
.then(() => dispatch(snackbar.success(message)))
|
||||
.catch(() => {});
|
||||
},
|
||||
|
||||
|
||||
onPromoteToAdmin(account) {
|
||||
const message = intl.formatMessage(messages.promotedToAdmin, { acct: account.get('acct') });
|
||||
|
||||
|
|
|
@ -72,6 +72,10 @@ class ProfileInfoPanel extends ImmutablePureComponent {
|
|||
badges.push(<Badge slug='patron' title='Patron' key='patron' />);
|
||||
}
|
||||
|
||||
if (account.donor) {
|
||||
badges.push(<Badge slug='donor' title='Donor' key='donor' />);
|
||||
}
|
||||
|
||||
return badges;
|
||||
}
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@ export const AccountRecord = ImmutableRecord({
|
|||
admin: false,
|
||||
display_name_html: '',
|
||||
domain: '',
|
||||
donor: false,
|
||||
moderator: false,
|
||||
note_emojified: '',
|
||||
note_plain: '',
|
||||
|
@ -92,7 +93,7 @@ const normalizePleromaLegacyFields = (account: ImmutableMap<string, any>) => {
|
|||
});
|
||||
};
|
||||
|
||||
// Add avatar, if missing
|
||||
/** Add avatar, if missing */
|
||||
const normalizeAvatar = (account: ImmutableMap<string, any>) => {
|
||||
const avatar = account.get('avatar');
|
||||
const avatarStatic = account.get('avatar_static');
|
||||
|
@ -104,7 +105,7 @@ const normalizeAvatar = (account: ImmutableMap<string, any>) => {
|
|||
});
|
||||
};
|
||||
|
||||
// Add header, if missing
|
||||
/** Add header, if missing */
|
||||
const normalizeHeader = (account: ImmutableMap<string, any>) => {
|
||||
const header = account.get('header');
|
||||
const headerStatic = account.get('header_static');
|
||||
|
@ -116,18 +117,18 @@ const normalizeHeader = (account: ImmutableMap<string, any>) => {
|
|||
});
|
||||
};
|
||||
|
||||
// Normalize custom fields
|
||||
/** Normalize custom fields */
|
||||
const normalizeFields = (account: ImmutableMap<string, any>) => {
|
||||
return account.update('fields', ImmutableList(), fields => fields.map(FieldRecord));
|
||||
};
|
||||
|
||||
// Normalize emojis
|
||||
/** Normalize emojis */
|
||||
const normalizeEmojis = (entity: ImmutableMap<string, any>) => {
|
||||
const emojis = entity.get('emojis', ImmutableList()).map(normalizeEmoji);
|
||||
return entity.set('emojis', emojis);
|
||||
};
|
||||
|
||||
// Normalize Pleroma/Fedibird birthday
|
||||
/** Normalize Pleroma/Fedibird birthday */
|
||||
const normalizeBirthday = (account: ImmutableMap<string, any>) => {
|
||||
const birthday = [
|
||||
account.getIn(['pleroma', 'birthday']),
|
||||
|
@ -137,13 +138,13 @@ const normalizeBirthday = (account: ImmutableMap<string, any>) => {
|
|||
return account.set('birthday', birthday);
|
||||
};
|
||||
|
||||
// Get Pleroma tags
|
||||
/** Get Pleroma tags */
|
||||
const getTags = (account: ImmutableMap<string, any>): ImmutableList<any> => {
|
||||
const tags = account.getIn(['pleroma', 'tags']);
|
||||
return ImmutableList(ImmutableList.isList(tags) ? tags : []);
|
||||
};
|
||||
|
||||
// Normalize Truth Social/Pleroma verified
|
||||
/** Normalize Truth Social/Pleroma verified */
|
||||
const normalizeVerified = (account: ImmutableMap<string, any>) => {
|
||||
return account.update('verified', verified => {
|
||||
return [
|
||||
|
@ -153,7 +154,12 @@ const normalizeVerified = (account: ImmutableMap<string, any>) => {
|
|||
});
|
||||
};
|
||||
|
||||
// Normalize Fedibird/Truth Social/Pleroma location
|
||||
/** Get donor status from tags. */
|
||||
const normalizeDonor = (account: ImmutableMap<string, any>) => {
|
||||
return account.set('donor', getTags(account).includes('donor'));
|
||||
};
|
||||
|
||||
/** Normalize Fedibird/Truth Social/Pleroma location */
|
||||
const normalizeLocation = (account: ImmutableMap<string, any>) => {
|
||||
return account.update('location', location => {
|
||||
return [
|
||||
|
@ -164,20 +170,20 @@ const normalizeLocation = (account: ImmutableMap<string, any>) => {
|
|||
});
|
||||
};
|
||||
|
||||
// Set username from acct, if applicable
|
||||
/** Set username from acct, if applicable */
|
||||
const fixUsername = (account: ImmutableMap<string, any>) => {
|
||||
const acct = account.get('acct') || '';
|
||||
const username = account.get('username') || '';
|
||||
return account.set('username', username || acct.split('@')[0]);
|
||||
};
|
||||
|
||||
// Set display name from username, if applicable
|
||||
/** Set display name from username, if applicable */
|
||||
const fixDisplayName = (account: ImmutableMap<string, any>) => {
|
||||
const displayName = account.get('display_name') || '';
|
||||
return account.set('display_name', displayName.trim().length === 0 ? account.get('username') : displayName);
|
||||
};
|
||||
|
||||
// Emojification, etc
|
||||
/** Emojification, etc */
|
||||
const addInternalFields = (account: ImmutableMap<string, any>) => {
|
||||
const emojiMap = makeEmojiMap(account.get('emojis'));
|
||||
|
||||
|
@ -258,6 +264,7 @@ export const normalizeAccount = (account: Record<string, any>) => {
|
|||
normalizeHeader(account);
|
||||
normalizeFields(account);
|
||||
normalizeVerified(account);
|
||||
normalizeDonor(account);
|
||||
normalizeBirthday(account);
|
||||
normalizeLocation(account);
|
||||
normalizeFqn(account);
|
||||
|
|
|
@ -91,6 +91,17 @@ const addTags = (
|
|||
state.updateIn([id, 'pleroma', 'tags'], ImmutableList(), v =>
|
||||
ImmutableOrderedSet(fromJS(v)).union(tags).toList(),
|
||||
);
|
||||
|
||||
tags.forEach(tag => {
|
||||
switch(tag) {
|
||||
case 'verified':
|
||||
state.setIn([id, 'verified'], true);
|
||||
break;
|
||||
case 'donor':
|
||||
state.setIn([id, 'donor'], true);
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
@ -105,6 +116,17 @@ const removeTags = (
|
|||
state.updateIn([id, 'pleroma', 'tags'], ImmutableList(), v =>
|
||||
ImmutableOrderedSet(fromJS(v)).subtract(tags).toList(),
|
||||
);
|
||||
|
||||
tags.forEach(tag => {
|
||||
switch(tag) {
|
||||
case 'verified':
|
||||
state.setIn([id, 'verified'], false);
|
||||
break;
|
||||
case 'donor':
|
||||
state.setIn([id, 'donor'], false);
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
Ładowanie…
Reference in New Issue