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) {
|
export function addPermission(accountIds, permissionGroup) {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
const nicknames = nicknamesFromIds(getState, accountIds);
|
const nicknames = nicknamesFromIds(getState, accountIds);
|
||||||
|
|
|
@ -3,7 +3,7 @@ import React from 'react';
|
||||||
|
|
||||||
interface IBadge {
|
interface IBadge {
|
||||||
title: string,
|
title: string,
|
||||||
slug: 'patron' | 'admin' | 'moderator' | 'bot' | 'opaque',
|
slug: 'patron' | 'donor' | 'admin' | 'moderator' | 'bot' | 'opaque',
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Badge to display on a user's profile. */
|
/** Badge to display on a user's profile. */
|
||||||
|
@ -12,6 +12,7 @@ const Badge: React.FC<IBadge> = ({ title, slug }) => (
|
||||||
data-testid='badge'
|
data-testid='badge'
|
||||||
className={classNames('inline-flex items-center px-2 py-0.5 rounded text-xs font-medium text-white', {
|
className={classNames('inline-flex items-center px-2 py-0.5 rounded text-xs font-medium text-white', {
|
||||||
'bg-fuchsia-700': slug === 'patron',
|
'bg-fuchsia-700': slug === 'patron',
|
||||||
|
'bg-yellow-500': slug === 'donor',
|
||||||
'bg-black': slug === 'admin',
|
'bg-black': slug === 'admin',
|
||||||
'bg-cyan-600': slug === 'moderator',
|
'bg-cyan-600': slug === 'moderator',
|
||||||
'bg-gray-100 text-gray-800': slug === 'bot',
|
'bg-gray-100 text-gray-800': slug === 'bot',
|
||||||
|
|
|
@ -36,6 +36,10 @@ const getBadges = (account) => {
|
||||||
badges.push(<Badge key='patron' slug='patron' title='Patron' />);
|
badges.push(<Badge key='patron' slug='patron' title='Patron' />);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (account.donor) {
|
||||||
|
badges.push(<Badge key='donor' slug='donor' title='Donor' />);
|
||||||
|
}
|
||||||
|
|
||||||
return badges;
|
return badges;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,8 @@ const messages = defineMessages({
|
||||||
deleteUser: { id: 'admin.users.actions.delete_user', defaultMessage: 'Delete @{name}' },
|
deleteUser: { id: 'admin.users.actions.delete_user', defaultMessage: 'Delete @{name}' },
|
||||||
verifyUser: { id: 'admin.users.actions.verify_user', defaultMessage: 'Verify @{name}' },
|
verifyUser: { id: 'admin.users.actions.verify_user', defaultMessage: 'Verify @{name}' },
|
||||||
unverifyUser: { id: 'admin.users.actions.unverify_user', defaultMessage: 'Unverify @{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' },
|
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' },
|
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' },
|
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({
|
menu.push({
|
||||||
text: intl.formatMessage(messages.unverifyUser, { name: account.get('username') }),
|
text: intl.formatMessage(messages.unverifyUser, { name: account.username }),
|
||||||
action: this.props.onUnverifyUser,
|
action: this.props.onUnverifyUser,
|
||||||
icon: require('@tabler/icons/icons/check.svg'),
|
icon: require('@tabler/icons/icons/check.svg'),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
menu.push({
|
menu.push({
|
||||||
text: intl.formatMessage(messages.verifyUser, { name: account.get('username') }),
|
text: intl.formatMessage(messages.verifyUser, { name: account.username }),
|
||||||
action: this.props.onVerifyUser,
|
action: this.props.onVerifyUser,
|
||||||
icon: require('@tabler/icons/icons/check.svg'),
|
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 (features.suggestionsV2 && meAccount.admin) {
|
||||||
if (account.getIn(['pleroma', 'is_suggested'])) {
|
if (account.getIn(['pleroma', 'is_suggested'])) {
|
||||||
menu.push({
|
menu.push({
|
||||||
|
|
|
@ -110,6 +110,14 @@ class Header extends ImmutablePureComponent {
|
||||||
this.props.onUnverifyUser(this.props.account);
|
this.props.onUnverifyUser(this.props.account);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleSetDonor = () => {
|
||||||
|
this.props.onSetDonor(this.props.account);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleRemoveDonor = () => {
|
||||||
|
this.props.onRemoveDonor(this.props.account);
|
||||||
|
}
|
||||||
|
|
||||||
handlePromoteToAdmin = () => {
|
handlePromoteToAdmin = () => {
|
||||||
this.props.onPromoteToAdmin(this.props.account);
|
this.props.onPromoteToAdmin(this.props.account);
|
||||||
}
|
}
|
||||||
|
@ -163,6 +171,8 @@ class Header extends ImmutablePureComponent {
|
||||||
onDeleteUser={this.handleDeleteUser}
|
onDeleteUser={this.handleDeleteUser}
|
||||||
onVerifyUser={this.handleVerifyUser}
|
onVerifyUser={this.handleVerifyUser}
|
||||||
onUnverifyUser={this.handleUnverifyUser}
|
onUnverifyUser={this.handleUnverifyUser}
|
||||||
|
onSetDonor={this.handleSetDonor}
|
||||||
|
onRemoveDonor={this.handleRemoveDonor}
|
||||||
onPromoteToAdmin={this.handlePromoteToAdmin}
|
onPromoteToAdmin={this.handlePromoteToAdmin}
|
||||||
onPromoteToModerator={this.handlePromoteToModerator}
|
onPromoteToModerator={this.handlePromoteToModerator}
|
||||||
onDemoteToUser={this.handleDemoteToUser}
|
onDemoteToUser={this.handleDemoteToUser}
|
||||||
|
|
|
@ -18,6 +18,8 @@ import {
|
||||||
import {
|
import {
|
||||||
verifyUser,
|
verifyUser,
|
||||||
unverifyUser,
|
unverifyUser,
|
||||||
|
setDonor,
|
||||||
|
removeDonor,
|
||||||
promoteToAdmin,
|
promoteToAdmin,
|
||||||
promoteToModerator,
|
promoteToModerator,
|
||||||
demoteToUser,
|
demoteToUser,
|
||||||
|
@ -47,6 +49,8 @@ const messages = defineMessages({
|
||||||
blockAndReport: { id: 'confirmations.block.block_and_report', defaultMessage: 'Block & Report' },
|
blockAndReport: { id: 'confirmations.block.block_and_report', defaultMessage: 'Block & Report' },
|
||||||
userVerified: { id: 'admin.users.user_verified_message', defaultMessage: '@{acct} was verified' },
|
userVerified: { id: 'admin.users.user_verified_message', defaultMessage: '@{acct} was verified' },
|
||||||
userUnverified: { id: 'admin.users.user_unverified_message', defaultMessage: '@{acct} was unverified' },
|
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' },
|
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' },
|
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' },
|
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(() => {});
|
.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) {
|
onPromoteToAdmin(account) {
|
||||||
const message = intl.formatMessage(messages.promotedToAdmin, { acct: account.get('acct') });
|
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' />);
|
badges.push(<Badge slug='patron' title='Patron' key='patron' />);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (account.donor) {
|
||||||
|
badges.push(<Badge slug='donor' title='Donor' key='donor' />);
|
||||||
|
}
|
||||||
|
|
||||||
return badges;
|
return badges;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,7 @@ export const AccountRecord = ImmutableRecord({
|
||||||
admin: false,
|
admin: false,
|
||||||
display_name_html: '',
|
display_name_html: '',
|
||||||
domain: '',
|
domain: '',
|
||||||
|
donor: false,
|
||||||
moderator: false,
|
moderator: false,
|
||||||
note_emojified: '',
|
note_emojified: '',
|
||||||
note_plain: '',
|
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 normalizeAvatar = (account: ImmutableMap<string, any>) => {
|
||||||
const avatar = account.get('avatar');
|
const avatar = account.get('avatar');
|
||||||
const avatarStatic = account.get('avatar_static');
|
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 normalizeHeader = (account: ImmutableMap<string, any>) => {
|
||||||
const header = account.get('header');
|
const header = account.get('header');
|
||||||
const headerStatic = account.get('header_static');
|
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>) => {
|
const normalizeFields = (account: ImmutableMap<string, any>) => {
|
||||||
return account.update('fields', ImmutableList(), fields => fields.map(FieldRecord));
|
return account.update('fields', ImmutableList(), fields => fields.map(FieldRecord));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Normalize emojis
|
/** Normalize emojis */
|
||||||
const normalizeEmojis = (entity: ImmutableMap<string, any>) => {
|
const normalizeEmojis = (entity: ImmutableMap<string, any>) => {
|
||||||
const emojis = entity.get('emojis', ImmutableList()).map(normalizeEmoji);
|
const emojis = entity.get('emojis', ImmutableList()).map(normalizeEmoji);
|
||||||
return entity.set('emojis', emojis);
|
return entity.set('emojis', emojis);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Normalize Pleroma/Fedibird birthday
|
/** Normalize Pleroma/Fedibird birthday */
|
||||||
const normalizeBirthday = (account: ImmutableMap<string, any>) => {
|
const normalizeBirthday = (account: ImmutableMap<string, any>) => {
|
||||||
const birthday = [
|
const birthday = [
|
||||||
account.getIn(['pleroma', 'birthday']),
|
account.getIn(['pleroma', 'birthday']),
|
||||||
|
@ -137,13 +138,13 @@ const normalizeBirthday = (account: ImmutableMap<string, any>) => {
|
||||||
return account.set('birthday', birthday);
|
return account.set('birthday', birthday);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get Pleroma tags
|
/** Get Pleroma tags */
|
||||||
const getTags = (account: ImmutableMap<string, any>): ImmutableList<any> => {
|
const getTags = (account: ImmutableMap<string, any>): ImmutableList<any> => {
|
||||||
const tags = account.getIn(['pleroma', 'tags']);
|
const tags = account.getIn(['pleroma', 'tags']);
|
||||||
return ImmutableList(ImmutableList.isList(tags) ? tags : []);
|
return ImmutableList(ImmutableList.isList(tags) ? tags : []);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Normalize Truth Social/Pleroma verified
|
/** Normalize Truth Social/Pleroma verified */
|
||||||
const normalizeVerified = (account: ImmutableMap<string, any>) => {
|
const normalizeVerified = (account: ImmutableMap<string, any>) => {
|
||||||
return account.update('verified', verified => {
|
return account.update('verified', verified => {
|
||||||
return [
|
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>) => {
|
const normalizeLocation = (account: ImmutableMap<string, any>) => {
|
||||||
return account.update('location', location => {
|
return account.update('location', location => {
|
||||||
return [
|
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 fixUsername = (account: ImmutableMap<string, any>) => {
|
||||||
const acct = account.get('acct') || '';
|
const acct = account.get('acct') || '';
|
||||||
const username = account.get('username') || '';
|
const username = account.get('username') || '';
|
||||||
return account.set('username', username || acct.split('@')[0]);
|
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 fixDisplayName = (account: ImmutableMap<string, any>) => {
|
||||||
const displayName = account.get('display_name') || '';
|
const displayName = account.get('display_name') || '';
|
||||||
return account.set('display_name', displayName.trim().length === 0 ? account.get('username') : displayName);
|
return account.set('display_name', displayName.trim().length === 0 ? account.get('username') : displayName);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Emojification, etc
|
/** Emojification, etc */
|
||||||
const addInternalFields = (account: ImmutableMap<string, any>) => {
|
const addInternalFields = (account: ImmutableMap<string, any>) => {
|
||||||
const emojiMap = makeEmojiMap(account.get('emojis'));
|
const emojiMap = makeEmojiMap(account.get('emojis'));
|
||||||
|
|
||||||
|
@ -258,6 +264,7 @@ export const normalizeAccount = (account: Record<string, any>) => {
|
||||||
normalizeHeader(account);
|
normalizeHeader(account);
|
||||||
normalizeFields(account);
|
normalizeFields(account);
|
||||||
normalizeVerified(account);
|
normalizeVerified(account);
|
||||||
|
normalizeDonor(account);
|
||||||
normalizeBirthday(account);
|
normalizeBirthday(account);
|
||||||
normalizeLocation(account);
|
normalizeLocation(account);
|
||||||
normalizeFqn(account);
|
normalizeFqn(account);
|
||||||
|
|
|
@ -91,6 +91,17 @@ const addTags = (
|
||||||
state.updateIn([id, 'pleroma', 'tags'], ImmutableList(), v =>
|
state.updateIn([id, 'pleroma', 'tags'], ImmutableList(), v =>
|
||||||
ImmutableOrderedSet(fromJS(v)).union(tags).toList(),
|
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 =>
|
state.updateIn([id, 'pleroma', 'tags'], ImmutableList(), v =>
|
||||||
ImmutableOrderedSet(fromJS(v)).subtract(tags).toList(),
|
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