diff --git a/app/soapbox/actions/email_list.js b/app/soapbox/actions/email_list.js
new file mode 100644
index 000000000..9f440b001
--- /dev/null
+++ b/app/soapbox/actions/email_list.js
@@ -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');
+ };
+}
diff --git a/app/soapbox/features/admin/index.js b/app/soapbox/features/admin/index.js
index a0c4dbaa1..90ce7ac1b 100644
--- a/app/soapbox/features/admin/index.js
+++ b/app/soapbox/features/admin/index.js
@@ -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 {
{v.software} {v.version}
+ {supportsEmailList && }
);
diff --git a/app/soapbox/features/edit_profile/index.js b/app/soapbox/features/edit_profile/index.js
index e4560d179..9b5d179b4 100644
--- a/app/soapbox/features/edit_profile/index.js
+++ b/app/soapbox/features/edit_profile/index.js
@@ -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}
/>
- }
hint={}
name='accepts_email_list'
checked={this.state.accepts_email_list}
onChange={this.handleCheckboxChange}
- />
+ />}
diff --git a/app/soapbox/features/landing_page/components/registration_form.js b/app/soapbox/features/landing_page/components/registration_form.js
index 47856351a..b0518c704 100644
--- a/app/soapbox/features/landing_page/components/registration_form.js
+++ b/app/soapbox/features/landing_page/components/registration_form.js
@@ -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
/>
-
+ />}