From eb006202e71fdb3315c2c0c9add8f679ef466a22 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Tue, 15 Jun 2021 15:02:36 -0500 Subject: [PATCH] EmailList: let csv links be clickable, add combined.csv support, conditionally display elements --- app/soapbox/actions/email_list.js | 19 ++++++++ app/soapbox/features/admin/index.js | 46 ++++++++++++++++++- app/soapbox/features/edit_profile/index.js | 8 ++-- .../components/registration_form.js | 8 ++-- app/soapbox/utils/features.js | 3 ++ app/styles/components/admin.scss | 4 ++ 6 files changed, 81 insertions(+), 7 deletions(-) create mode 100644 app/soapbox/actions/email_list.js 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 /> - + />}