sforkowany z mirror/soapbox
EmailList: let csv links be clickable, add combined.csv support, conditionally display elements
rodzic
6255ba4976
commit
eb006202e7
|
@ -0,0 +1,19 @@
|
|||
import api from '../api';
|
||||
|
||||
export function getSubscribersCsv() {
|
||||
return (dispatch, getState) => {
|
||||
return api(getState).get('/api/v1/pleroma/admin/email_list/subscribers.csv');
|
||||
};
|
||||
}
|
||||
|
||||
export function getUnsubscribersCsv() {
|
||||
return (dispatch, getState) => {
|
||||
return api(getState).get('/api/v1/pleroma/admin/email_list/unsubscribers.csv');
|
||||
};
|
||||
}
|
||||
|
||||
export function getCombinedCsv() {
|
||||
return (dispatch, getState) => {
|
||||
return api(getState).get('/api/v1/pleroma/admin/email_list/combined.csv');
|
||||
};
|
||||
}
|
|
@ -8,6 +8,19 @@ import Column from '../ui/components/column';
|
|||
import RegistrationModePicker from './components/registration_mode_picker';
|
||||
import { parseVersion } from 'soapbox/utils/features';
|
||||
import sourceCode from 'soapbox/utils/code';
|
||||
import { getSubscribersCsv, getUnsubscribersCsv, getCombinedCsv } from 'soapbox/actions/email_list';
|
||||
import { getFeatures } from 'soapbox/utils/features';
|
||||
|
||||
// https://stackoverflow.com/a/53230807
|
||||
const download = (response, filename) => {
|
||||
const url = URL.createObjectURL(new Blob([response.data]));
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
link.setAttribute('download', filename);
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
link.remove();
|
||||
};
|
||||
|
||||
const messages = defineMessages({
|
||||
heading: { id: 'column.admin.dashboard', defaultMessage: 'Dashboard' },
|
||||
|
@ -15,6 +28,7 @@ const messages = defineMessages({
|
|||
|
||||
const mapStateToProps = (state, props) => ({
|
||||
instance: state.get('instance'),
|
||||
supportsEmailList: getFeatures(state.get('instance')).emailList,
|
||||
});
|
||||
|
||||
export default @connect(mapStateToProps)
|
||||
|
@ -24,10 +38,32 @@ class Dashboard extends ImmutablePureComponent {
|
|||
static propTypes = {
|
||||
intl: PropTypes.object.isRequired,
|
||||
instance: ImmutablePropTypes.map.isRequired,
|
||||
supportsEmailList: PropTypes.bool,
|
||||
};
|
||||
|
||||
handleSubscribersClick = e => {
|
||||
this.props.dispatch(getSubscribersCsv()).then((response) => {
|
||||
download(response, 'subscribers.csv');
|
||||
}).catch(() => {});
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
handleUnsubscribersClick = e => {
|
||||
this.props.dispatch(getUnsubscribersCsv()).then((response) => {
|
||||
download(response, 'unsubscribers.csv');
|
||||
}).catch(() => {});
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
handleCombinedClick = e => {
|
||||
this.props.dispatch(getCombinedCsv()).then((response) => {
|
||||
download(response, 'combined.csv');
|
||||
}).catch(() => {});
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
render() {
|
||||
const { intl, instance } = this.props;
|
||||
const { intl, instance, supportsEmailList } = this.props;
|
||||
const v = parseVersion(instance.get('version'));
|
||||
const userCount = instance.getIn(['stats', 'user_count']);
|
||||
const mau = instance.getIn(['pleroma', 'stats', 'mau']);
|
||||
|
@ -96,6 +132,14 @@ class Dashboard extends ImmutablePureComponent {
|
|||
<li>{v.software} <span className='pull-right'>{v.version}</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
{supportsEmailList && <div className='dashwidget'>
|
||||
<h4><FormattedMessage id='admin.dashwidgets.email_list_header' defaultMessage='Email list' /></h4>
|
||||
<ul>
|
||||
<li><a href='#' onClick={this.handleSubscribersClick} target='_blank'>subscribers.csv</a></li>
|
||||
<li><a href='#' onClick={this.handleUnsubscribersClick} target='_blank'>unsubscribers.csv</a></li>
|
||||
<li><a href='#' onClick={this.handleCombinedClick} target='_blank'>combined.csv</a></li>
|
||||
</ul>
|
||||
</div>}
|
||||
</div>
|
||||
</Column>
|
||||
);
|
||||
|
|
|
@ -24,6 +24,7 @@ import { updateNotificationSettings } from 'soapbox/actions/accounts';
|
|||
import { unescape } from 'lodash';
|
||||
import { isVerified } from 'soapbox/utils/accounts';
|
||||
import { getSoapboxConfig } from 'soapbox/actions/soapbox';
|
||||
import { getFeatures } from 'soapbox/utils/features';
|
||||
|
||||
const messages = defineMessages({
|
||||
heading: { id: 'column.edit_profile', defaultMessage: 'Edit profile' },
|
||||
|
@ -41,6 +42,7 @@ const mapStateToProps = state => {
|
|||
account,
|
||||
maxFields: state.getIn(['instance', 'pleroma', 'metadata', 'fields_limits', 'max_fields'], 4),
|
||||
verifiedCanEditName: soapbox.get('verifiedCanEditName'),
|
||||
supportsEmailList: getFeatures(state.get('instance')).emailList,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -182,7 +184,7 @@ class EditProfile extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { intl, maxFields, account, verifiedCanEditName } = this.props;
|
||||
const { intl, maxFields, account, verifiedCanEditName, supportsEmailList } = this.props;
|
||||
const verified = isVerified(account);
|
||||
const canEditName = verifiedCanEditName || !verified;
|
||||
|
||||
|
@ -249,13 +251,13 @@ class EditProfile extends ImmutablePureComponent {
|
|||
checked={this.state.stranger_notifications}
|
||||
onChange={this.handleCheckboxChange}
|
||||
/>
|
||||
<Checkbox
|
||||
{supportsEmailList && <Checkbox
|
||||
label={<FormattedMessage id='edit_profile.fields.accepts_email_list_label' defaultMessage='Subscribe to newsletter' />}
|
||||
hint={<FormattedMessage id='edit_profile.hints.accepts_email_list' defaultMessage='Opt-in to news and marketing updates.' />}
|
||||
name='accepts_email_list'
|
||||
checked={this.state.accepts_email_list}
|
||||
onChange={this.handleCheckboxChange}
|
||||
/>
|
||||
/>}
|
||||
</FieldsGroup>
|
||||
<FieldsGroup>
|
||||
<div className='fields-row__column fields-group'>
|
||||
|
|
|
@ -18,6 +18,7 @@ import { Map as ImmutableMap } from 'immutable';
|
|||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { getSettings } from 'soapbox/actions/settings';
|
||||
import { openModal } from 'soapbox/actions/modal';
|
||||
import { getFeatures } from 'soapbox/utils/features';
|
||||
|
||||
const messages = defineMessages({
|
||||
username: { id: 'registration.fields.username_placeholder', defaultMessage: 'Username' },
|
||||
|
@ -36,6 +37,7 @@ const mapStateToProps = (state, props) => ({
|
|||
locale: getSettings(state).get('locale'),
|
||||
needsConfirmation: state.getIn(['instance', 'pleroma', 'metadata', 'account_activation_required']),
|
||||
needsApproval: state.getIn(['instance', 'approval_required']),
|
||||
supportsEmailList: getFeatures(state.get('instance')).emailList,
|
||||
});
|
||||
|
||||
export default @connect(mapStateToProps)
|
||||
|
@ -136,7 +138,7 @@ class RegistrationForm extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { instance, intl } = this.props;
|
||||
const { instance, intl, supportsEmailList } = this.props;
|
||||
const { params } = this.state;
|
||||
const isOpen = instance.get('registrations');
|
||||
const isLoading = this.state.captchaLoading || this.state.submissionLoading;
|
||||
|
@ -233,11 +235,11 @@ class RegistrationForm extends ImmutablePureComponent {
|
|||
onChange={this.onCheckboxChange}
|
||||
required
|
||||
/>
|
||||
<Checkbox
|
||||
{supportsEmailList && <Checkbox
|
||||
label={intl.formatMessage(messages.newsletter)}
|
||||
name='accepts_email_list'
|
||||
onChange={this.onCheckboxChange}
|
||||
/>
|
||||
/>}
|
||||
</div>
|
||||
<div className='actions'>
|
||||
<button name='button' type='submit' className='btn button button-primary'>
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
// Detect backend features to conditionally render elements
|
||||
import gte from 'semver/functions/gte';
|
||||
import { List as ImmutableList } from 'immutable';
|
||||
|
||||
export const getFeatures = instance => {
|
||||
const v = parseVersion(instance.get('version'));
|
||||
const f = instance.getIn(['pleroma', 'metadata', 'features'], ImmutableList());
|
||||
return {
|
||||
suggestions: v.software === 'Mastodon' && gte(v.compatVersion, '2.4.3'),
|
||||
trends: v.software === 'Mastodon' && gte(v.compatVersion, '3.0.0'),
|
||||
|
@ -11,6 +13,7 @@ export const getFeatures = instance => {
|
|||
attachmentLimit: v.software === 'Pleroma' ? Infinity : 4,
|
||||
focalPoint: v.software === 'Mastodon' && gte(v.compatVersion, '2.3.0'),
|
||||
importMutes: v.software === 'Pleroma' && gte(v.version, '2.2.0'),
|
||||
emailList: f.includes('email_list'),
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -68,6 +68,10 @@
|
|||
margin-bottom: 8px;
|
||||
border-bottom: 1px solid var(--accent-color--med);
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--brand-color);
|
||||
}
|
||||
}
|
||||
|
||||
.unapproved-account {
|
||||
|
|
Ładowanie…
Reference in New Issue