From d3e2cf40a48e86f1b9aa1d40cfe26f9e2d05ebed Mon Sep 17 00:00:00 2001 From: "Luiz R. Rodrigues" Date: Tue, 16 Feb 2021 14:18:19 -0300 Subject: [PATCH 1/2] Revert "Merge pull request #5356 from topcoder-platform/revert-5348-email-pref-revamp" This reverts commit 799ff7403b35f4af92f4d5f55ca7c9cdd9a92e98, reversing changes made to 51fc65ef0c263c64848adff3d2a64063082b289d. --- .circleci/config.yml | 2 +- .../Email/__snapshots__/index.jsx.snap | 87 ++++-------- package-lock.json | 131 ++++++++++-------- src/server/routes/mailchimp.js | 2 +- src/server/services/mailchimp.js | 2 +- src/shared/actions/newsletterPreferences.js | 59 ++++++-- .../ConfirmModal/style.scss | 4 + .../Settings/Preferences/Email/index.jsx | 114 ++++++++++----- .../Settings/Preferences/Email/styles.scss | 27 +++- .../Settings/ToggleableItem/index.jsx | 8 ++ .../containers/EmailSubscribeForm/index.jsx | 31 +++-- .../containers/NewsletterPreferences.jsx | 12 +- .../containers/NewsletterSignupForMembers.jsx | 32 +++-- src/shared/reducers/newsletterPreferences.js | 32 +++-- 14 files changed, 342 insertions(+), 201 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0e54b4a9b5..648740aecc 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -282,7 +282,7 @@ workflows: filters: branches: only: - - gsheet-contentful-develop + - email-pref-revamp-develop # This is alternate dev env for parallel testing - "build-qa": context : org-global diff --git a/__tests__/shared/components/Settings/Preferences/Email/__snapshots__/index.jsx.snap b/__tests__/shared/components/Settings/Preferences/Email/__snapshots__/index.jsx.snap index ab117b50c9..a3800f0773 100644 --- a/__tests__/shared/components/Settings/Preferences/Email/__snapshots__/index.jsx.snap +++ b/__tests__/shared/components/Settings/Preferences/Email/__snapshots__/index.jsx.snap @@ -10,69 +10,32 @@ exports[`renders email preferences setting page correctly 1`] = ` E-Mail Preferences
- Your preferences -
-
- Challenge Pipeline page." - value="Pipeline" - /> - Gig Work page." - value="Gig Work" - /> - - - - Topcoder Open you should definitely be subscribing to this one. Expect an update in your mailbox every Tuesday!" - value="TCO Tuesdays" - /> - +

+ You are not subscribed to receive Topcoder emails +

+

+ If this was a mistake or if you would like to resubscribe, please click the button below. +

+ + Resubscribe +
`; diff --git a/package-lock.json b/package-lock.json index 40807f5499..6f50f8f6d7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1727,7 +1727,7 @@ "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", "requires": { - "event-target-shim": "^5.0.0" + "event-target-shim": "5.0.1" } }, "accepts": { @@ -9400,11 +9400,11 @@ "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.1.0.tgz", "integrity": "sha512-vb0to8xzGnA2qcgywAjtshOKKVDf2eQhJoiL6fHhgW5tVN7wNk7egnYIO9zotfn3lQ3De1VPdf7V5/BWfCtCmg==", "requires": { - "abort-controller": "^3.0.0", - "extend": "^3.0.2", - "https-proxy-agent": "^5.0.0", - "is-stream": "^2.0.0", - "node-fetch": "^2.3.0" + "abort-controller": "3.0.0", + "extend": "3.0.2", + "https-proxy-agent": "5.0.0", + "is-stream": "2.0.0", + "node-fetch": "2.6.1" }, "dependencies": { "is-stream": { @@ -9433,8 +9433,8 @@ "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.2.1.tgz", "integrity": "sha512-tSk+REe5iq/N+K+SK1XjZJUrFPuDqGZVzCy2vocIHIGmPlTGsa8owXMJwGkrXr73NO0AzhPW4MF2DEHz7P2AVw==", "requires": { - "gaxios": "^4.0.0", - "json-bigint": "^1.0.0" + "gaxios": "4.1.0", + "json-bigint": "1.0.0" } }, "generic-names": { @@ -10223,23 +10223,42 @@ "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-6.1.6.tgz", "integrity": "sha512-Q+ZjUEvLQj/lrVHF/IQwRo6p3s8Nc44Zk/DALsN+ac3T4HY/g/3rrufkgtl+nZ1TW7DNAw5cTChdVp4apUXVgQ==", "requires": { - "arrify": "^2.0.0", - "base64-js": "^1.3.0", - "ecdsa-sig-formatter": "^1.0.11", - "fast-text-encoding": "^1.0.0", - "gaxios": "^4.0.0", - "gcp-metadata": "^4.2.0", - "gtoken": "^5.0.4", - "jws": "^4.0.0", - "lru-cache": "^6.0.0" + "arrify": "2.0.1", + "base64-js": "1.3.1", + "ecdsa-sig-formatter": "1.0.11", + "fast-text-encoding": "1.0.3", + "gaxios": "4.1.0", + "gcp-metadata": "4.2.1", + "gtoken": "5.2.1", + "jws": "4.0.0", + "lru-cache": "6.0.0" }, "dependencies": { + "jwa": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "5.1.2" + } + }, + "jws": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "requires": { + "jwa": "2.0.0", + "safe-buffer": "5.1.2" + } + }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "requires": { - "yallist": "^4.0.0" + "yallist": "4.0.0" } }, "yallist": { @@ -10254,7 +10273,7 @@ "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.0.3.tgz", "integrity": "sha512-wS0ek4ZtFx/ACKYF3JhyGe5kzH7pgiQ7J5otlumqR9psmWMYc+U9cErKlCYVYHoUaidXHdZ2xbo34kB+S+24hA==", "requires": { - "node-forge": "^0.10.0" + "node-forge": "0.10.0" }, "dependencies": { "node-forge": { @@ -10269,9 +10288,9 @@ "resolved": "https://registry.npmjs.org/google-spreadsheet/-/google-spreadsheet-3.1.15.tgz", "integrity": "sha512-S5477f3Gf3Mz6AXgCw7dbaYnzu5aHou1AX4sDqrGboQWnAytkxqJGKQiXN+zzRTTcYzSTJCe0g7KqCPZO9xiOw==", "requires": { - "axios": "^0.21.1", - "google-auth-library": "^6.1.3", - "lodash": "^4.17.20" + "axios": "0.21.1", + "google-auth-library": "6.1.6", + "lodash": "4.17.20" }, "dependencies": { "axios": { @@ -10279,7 +10298,7 @@ "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", "requires": { - "follow-redirects": "^1.10.0" + "follow-redirects": "1.13.2" } }, "follow-redirects": { @@ -10310,9 +10329,30 @@ "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.2.1.tgz", "integrity": "sha512-OY0BfPKe3QnMsY9MzTHTSKn+Vl2l1CcLe6BwDEQj00mbbkl5nyQ/7EUREstg4fQNZ8iYE7br4JJ7TdKeDOPWmw==", "requires": { - "gaxios": "^4.0.0", - "google-p12-pem": "^3.0.3", - "jws": "^4.0.0" + "gaxios": "4.1.0", + "google-p12-pem": "3.0.3", + "jws": "4.0.0" + }, + "dependencies": { + "jwa": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "5.1.2" + } + }, + "jws": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "requires": { + "jwa": "2.0.0", + "safe-buffer": "5.1.2" + } + } } }, "handlebars": { @@ -13385,7 +13425,7 @@ "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", "requires": { - "bignumber.js": "^9.0.0" + "bignumber.js": "9.0.1" }, "dependencies": { "bignumber.js": { @@ -13499,25 +13539,6 @@ "semver": "5.7.1" }, "dependencies": { - "jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "requires": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "requires": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, "ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -13579,13 +13600,13 @@ "integrity": "sha512-mjzgSOFzlrurlURaHVjnQodyPNvrHrf1TbQP2XU9NSqBtHQPuHZ+Eb6TAJP7ASeJN9h9K0KXoRTs8u6ouHBKvg==" }, "jwa": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", - "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", "requires": { "buffer-equal-constant-time": "1.0.1", "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" + "safe-buffer": "5.1.2" } }, "jwks-rsa": { @@ -13641,12 +13662,12 @@ } }, "jws": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", - "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", "requires": { - "jwa": "^2.0.0", - "safe-buffer": "^5.0.1" + "jwa": "1.4.1", + "safe-buffer": "5.1.2" } }, "kapellmeister": { diff --git a/src/server/routes/mailchimp.js b/src/server/routes/mailchimp.js index 0b8b2a98fe..2ebe70056c 100644 --- a/src/server/routes/mailchimp.js +++ b/src/server/routes/mailchimp.js @@ -20,7 +20,7 @@ routes.post('/:listId/members', (req, res, next) => new MailchimpService().doReg routes.get('/:listId/members/:emailHash', (req, res) => new MailchimpService().checkSubscription(req).then(res.send.bind(res))); -routes.put('/:listId/members/:emailHash', (req, res) => new MailchimpService().subscribeInterests(req).then(res.send.bind(res))); +routes.put('/:listId/members/:emailHash', (req, res) => new MailchimpService().updateMember(req).then(res.send.bind(res))); routes.post('/:listId/members/:emailHash/tags', (req, res) => new MailchimpService().subscribeTags(req).then(res.send.bind(res))); diff --git a/src/server/services/mailchimp.js b/src/server/services/mailchimp.js index 1a22665a24..1e06769f23 100644 --- a/src/server/services/mailchimp.js +++ b/src/server/services/mailchimp.js @@ -51,7 +51,7 @@ export default class MailchimpService { return res.json(); } - async subscribeInterests(req) { + async updateMember(req) { const formData = JSON.stringify(req.body); const res = await fetch(`${this.mailchimpBaseUrl}/lists/${req.params.listId}/members/${req.params.emailHash}`, { method: 'PUT', diff --git a/src/shared/actions/newsletterPreferences.js b/src/shared/actions/newsletterPreferences.js index 40a415c34a..84d08e3540 100644 --- a/src/shared/actions/newsletterPreferences.js +++ b/src/shared/actions/newsletterPreferences.js @@ -35,7 +35,8 @@ async function fetchDataDone(emailHash, listId = config.NEWSLETTER_SIGNUP.DEFAUL return { email: emailHash, - preferences: subs.tags, + preferences: subs.interests, + status: subs.status, error, }; } catch (error) { @@ -48,7 +49,7 @@ async function fetchDataDone(emailHash, listId = config.NEWSLETTER_SIGNUP.DEFAUL // Updates member newsletter subscription async function updateSubscriptionsDone( - emailHash, tagId, status, listId = config.NEWSLETTER_SIGNUP.DEFAUL_LIST_ID, + emailHash, groupId, status, listId = config.NEWSLETTER_SIGNUP.DEFAUL_LIST_ID, ) { /* NOTE: In the real life in most cases you don't want to use fetch() directly * in an action. You want to create a service for your calls and use it here. @@ -56,18 +57,16 @@ async function updateSubscriptionsDone( * directly here. */ try { let error = false; - const fetchUrl = `${PROXY_ENDPOINT}/${listId}/members/${emailHash}/tags`; + const fetchUrl = `${PROXY_ENDPOINT}/${listId}/members/${emailHash}`; const data = { - tags: [ - { name: tagId, status: status ? 'active' : 'inactive' }, - ], + interests: { [groupId]: !!status }, }; const formData = JSON.stringify(data); // use proxy for avoid 'Access-Control-Allow-Origin' bug await fetch(fetchUrl, { - method: 'POST', + method: 'PUT', headers: { 'Content-Type': 'application/json', }, @@ -79,14 +78,14 @@ async function updateSubscriptionsDone( }); return { - id: tagId, + id: groupId, checked: status, email: emailHash, error, }; } catch (error) { return { - id: tagId, + id: groupId, checked: status, email: emailHash, error, @@ -94,11 +93,53 @@ async function updateSubscriptionsDone( } } +/** + * Resubscribe member for TC emails/list + * @param {string} emailHash the email + */ +async function resubscribeDone(emailHash, listId = config.NEWSLETTER_SIGNUP.DEFAUL_LIST_ID) { + try { + let error = false; + const fetchUrl = `${PROXY_ENDPOINT}/${listId}/members/${emailHash}`; + + const data = { + status: 'subscribed', + }; + + const formData = JSON.stringify(data); + // use proxy for avoid 'Access-Control-Allow-Origin' bug + await fetch(fetchUrl, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + }, + body: formData, + }) + .then((result) => { + if (!result.ok) error = true; + return result.json(); + }); + + return { + email: emailHash, + resubscribe: true, + error, + }; + } catch (error) { + return { + email: emailHash, + error, + }; + } +} + export default createActions({ NEWSLETTER_PREFERENCES: { FETCH_DATA_INIT: fetchDataInit, FETCH_DATA_DONE: fetchDataDone, UPDATE_TAG_INIT: _.identity, UPDATE_TAG_DONE: updateSubscriptionsDone, + RESUBSCRIBE_INIT: _.identity, + RESUBSCRIBE_DONE: resubscribeDone, }, }); diff --git a/src/shared/components/NewsletterSignupForMembers/ConfirmModal/style.scss b/src/shared/components/NewsletterSignupForMembers/ConfirmModal/style.scss index 7f44328bda..ea3f288646 100644 --- a/src/shared/components/NewsletterSignupForMembers/ConfirmModal/style.scss +++ b/src/shared/components/NewsletterSignupForMembers/ConfirmModal/style.scss @@ -33,5 +33,9 @@ button { margin: 24px 12px 0; + + &:first-child { + margin-right: 12px !important; + } } } diff --git a/src/shared/components/Settings/Preferences/Email/index.jsx b/src/shared/components/Settings/Preferences/Email/index.jsx index b8666c7a80..443dbd3ad4 100644 --- a/src/shared/components/Settings/Preferences/Email/index.jsx +++ b/src/shared/components/Settings/Preferences/Email/index.jsx @@ -1,3 +1,4 @@ +/* eslint-disable max-len */ /** * Email Preferences component. */ @@ -5,6 +6,7 @@ import { debounce, map } from 'lodash'; import React from 'react'; import PT from 'prop-types'; import { toastr } from 'react-redux-toastr'; +import { PrimaryButton } from 'topcoder-react-ui-kit'; import ToggleableItem from 'components/Settings/ToggleableItem'; @@ -26,41 +28,48 @@ const SAVE_DELAY = 1000; const newsletters = [ { - id: 'Pipeline', + id: '9f950b43a1', name: 'Challenge Pipeline', desc: 'Subscribe to this newsletter if you want to get updates on the types of challenges coming up in the future. To view these challenges at your leisure you can always visit the Challenge Pipeline page.', }, { - id: 'Gig Work', + id: 'd0c48e9da3', name: 'Gig Work', desc: 'This newsletter gets sent out at various times, specifically when we have an opportunity of mass appeal. For more information you can visit the Gig Work page.', }, { - id: 'Monthly Newsletter', + id: 'a8f858cdf1', name: 'Monthly Newsletter', desc: 'This newsletter gets sent out at the end of every month and contains a variety of important information across all of our tracks.', }, { - id: 'Marathon Match Reminders', + id: '5e67dba327', name: 'Marathon Match Reminders', desc: 'Receive updates whenever a new marathon match is scheduled.', }, { - id: 'Single Round Match Reminders', + id: '9091b438cc', name: 'Single Round Match (SRM) Reminders', desc: 'Attention Competitive Programmers! If there is any newsletter you are subscribing too, it better be this one. Receive updates when a new SRM event is scheduled.', }, { - id: 'TCO Tuesdays', + id: '603c900c32', name: 'TCO Newsletter', desc: 'For all the latest updates surrounding the Topcoder Open you should definitely be subscribing to this one. Expect an update in your mailbox every Tuesday!', }, { - id: 'RDM', + id: '3460574ddd', name: 'Rapid Development Match (RDM) Reminders', desc: 'Receive notifications of our brand new RDMs! These rated, development matches will be a fun new way to engage with us!', }, ]; +const programs = [ + { + id: 'cafe98d7a7', + name: 'Beta Testers', + desc: 'If you have applied and been approved as a Beta Tester, you may control the emails you receive here.', + }, +]; export default class EmailPreferences extends React.Component { saveEmailPreferences = debounce((id, checked) => { @@ -72,6 +81,7 @@ export default class EmailPreferences extends React.Component { super(props); this.state = { emailPreferences: { ...props.preferences }, + status: props.status, }; this.onChange = this.onChange.bind(this); } @@ -82,14 +92,14 @@ export default class EmailPreferences extends React.Component { if (updated.error) { toastrError('Error! ', 'Failed to update Your email preferences :-('); } - const { emailPreferences } = this.state; + const { emailPreferences, status } = this.state; const { id, checked } = updated; - if (!emailPreferences[id]) emailPreferences[id] = { id, checked }; - else emailPreferences[id].checked = checked; + emailPreferences[id] = checked; // eslint-disable-next-line react/no-did-update-set-state this.setState({ emailPreferences, + status: updated.resubscribe ? 'subscribed' : status, }); toastrSuccess('Success! ', 'Your email preferences were updated.'); } @@ -101,34 +111,69 @@ export default class EmailPreferences extends React.Component { } render() { - const { emailPreferences } = this.state; + const { emailPreferences, status } = this.state; + const { resubscibeEmails, email } = this.props; return (

E-Mail Preferences

-
- Your preferences -
-
- { - map(newsletters, (newsletter) => { - const checked = emailPreferences[newsletter.id] - ? emailPreferences[newsletter.id].checked : false; - return ( - this.onChange(newsletter.id, e.target.checked)} - /> - ); - }) - } -
+ { + status !== 'subscribed' ? ( +
+

You are not subscribed to receive Topcoder emails

+

If this was a mistake or if you would like to resubscribe, please click the button below.

+ resubscibeEmails(email)} + > + Resubscribe + +
+ ) : ( + +
Newsletters
+
+ { + map(newsletters, (newsletter) => { + const checked = emailPreferences[newsletter.id]; + return ( + this.onChange(newsletter.id, e.target.checked)} + disabled={status !== 'subscribed'} + /> + ); + }) + } +
+
Programs
+
+ { + map(programs, (program) => { + const checked = emailPreferences[program.id]; + return ( + this.onChange(program.id, e.target.checked)} + disabled={status !== 'subscribed'} + /> + ); + }) + } +
+
+ ) + }
); } @@ -136,6 +181,7 @@ export default class EmailPreferences extends React.Component { EmailPreferences.defaultProps = { updated: null, + status: null, }; EmailPreferences.propTypes = { @@ -143,4 +189,6 @@ EmailPreferences.propTypes = { preferences: PT.shape().isRequired, saveEmailPreferences: PT.func.isRequired, updated: PT.shape(), + status: PT.string, + resubscibeEmails: PT.func.isRequired, }; diff --git a/src/shared/components/Settings/Preferences/Email/styles.scss b/src/shared/components/Settings/Preferences/Email/styles.scss index e0b07a58f1..25e81f8d12 100644 --- a/src/shared/components/Settings/Preferences/Email/styles.scss +++ b/src/shared/components/Settings/Preferences/Email/styles.scss @@ -13,7 +13,8 @@ } } - .sub-title { + .sub-title, + .sub-title-2 { @include roboto-light; color: #888894; @@ -28,7 +29,31 @@ } } + .sub-title-2 { + margin-top: 30px; + } + .preferences-container { border-top: 1px solid $tc-gray-neutral-dark; } + + .unsubscribed-msg { + @include sofia-pro-regular; + + display: flex; + flex-direction: column; + background-color: $tc-red-10; + border: 1px solid $tc-red-30; + color: $tc-red; + line-height: 20px; + margin-bottom: 25px; + padding: 10px; + text-align: left; + font-size: 13px; + align-items: flex-start; + + button { + margin: 20px 0 0 0; + } + } } diff --git a/src/shared/components/Settings/ToggleableItem/index.jsx b/src/shared/components/Settings/ToggleableItem/index.jsx index bbfe110863..d5d4552a71 100644 --- a/src/shared/components/Settings/ToggleableItem/index.jsx +++ b/src/shared/components/Settings/ToggleableItem/index.jsx @@ -18,6 +18,7 @@ export default function ToggleableItem({ primaryText, secondaryText, value, + disabled, }) { return (
@@ -38,6 +39,7 @@ export default function ToggleableItem({ checked={checked} onChange={onToggle} className="onoffswitch-checkbox" + disabled={disabled} />
`; diff --git a/src/shared/actions/newsletterPreferences.js b/src/shared/actions/newsletterPreferences.js index 84d08e3540..4e1d948896 100644 --- a/src/shared/actions/newsletterPreferences.js +++ b/src/shared/actions/newsletterPreferences.js @@ -93,53 +93,11 @@ async function updateSubscriptionsDone( } } -/** - * Resubscribe member for TC emails/list - * @param {string} emailHash the email - */ -async function resubscribeDone(emailHash, listId = config.NEWSLETTER_SIGNUP.DEFAUL_LIST_ID) { - try { - let error = false; - const fetchUrl = `${PROXY_ENDPOINT}/${listId}/members/${emailHash}`; - - const data = { - status: 'subscribed', - }; - - const formData = JSON.stringify(data); - // use proxy for avoid 'Access-Control-Allow-Origin' bug - await fetch(fetchUrl, { - method: 'PUT', - headers: { - 'Content-Type': 'application/json', - }, - body: formData, - }) - .then((result) => { - if (!result.ok) error = true; - return result.json(); - }); - - return { - email: emailHash, - resubscribe: true, - error, - }; - } catch (error) { - return { - email: emailHash, - error, - }; - } -} - export default createActions({ NEWSLETTER_PREFERENCES: { FETCH_DATA_INIT: fetchDataInit, FETCH_DATA_DONE: fetchDataDone, UPDATE_TAG_INIT: _.identity, UPDATE_TAG_DONE: updateSubscriptionsDone, - RESUBSCRIBE_INIT: _.identity, - RESUBSCRIBE_DONE: resubscribeDone, }, }); diff --git a/src/shared/components/Settings/Preferences/Email/index.jsx b/src/shared/components/Settings/Preferences/Email/index.jsx index 443dbd3ad4..d8d80ecfa3 100644 --- a/src/shared/components/Settings/Preferences/Email/index.jsx +++ b/src/shared/components/Settings/Preferences/Email/index.jsx @@ -6,7 +6,6 @@ import { debounce, map } from 'lodash'; import React from 'react'; import PT from 'prop-types'; import { toastr } from 'react-redux-toastr'; -import { PrimaryButton } from 'topcoder-react-ui-kit'; import ToggleableItem from 'components/Settings/ToggleableItem'; @@ -112,7 +111,7 @@ export default class EmailPreferences extends React.Component { render() { const { emailPreferences, status } = this.state; - const { resubscibeEmails, email } = this.props; + const { email } = this.props; return (

@@ -123,53 +122,54 @@ export default class EmailPreferences extends React.Component {

You are not subscribed to receive Topcoder emails

If this was a mistake or if you would like to resubscribe, please click the button below.

- resubscibeEmails(email)} - > - Resubscribe - +
+ + + + +
) : (
Newsletters
{ - map(newsletters, (newsletter) => { - const checked = emailPreferences[newsletter.id]; - return ( - this.onChange(newsletter.id, e.target.checked)} - disabled={status !== 'subscribed'} - /> - ); - }) - } + map(newsletters, (newsletter) => { + const checked = emailPreferences[newsletter.id]; + return ( + this.onChange(newsletter.id, e.target.checked)} + disabled={status !== 'subscribed'} + /> + ); + }) + }
Programs
{ - map(programs, (program) => { - const checked = emailPreferences[program.id]; - return ( - this.onChange(program.id, e.target.checked)} - disabled={status !== 'subscribed'} - /> - ); - }) - } + map(programs, (program) => { + const checked = emailPreferences[program.id]; + return ( + this.onChange(program.id, e.target.checked)} + disabled={status !== 'subscribed'} + /> + ); + }) + }
) @@ -190,5 +190,4 @@ EmailPreferences.propTypes = { saveEmailPreferences: PT.func.isRequired, updated: PT.shape(), status: PT.string, - resubscibeEmails: PT.func.isRequired, }; diff --git a/src/shared/components/Settings/Preferences/Email/styles.scss b/src/shared/components/Settings/Preferences/Email/styles.scss index 25e81f8d12..ff39f96171 100644 --- a/src/shared/components/Settings/Preferences/Email/styles.scss +++ b/src/shared/components/Settings/Preferences/Email/styles.scss @@ -57,3 +57,32 @@ } } } + +:global { + #mc-embedded-subscribe-form { + input { + display: none; + } + + #mc-embedded-subscribe { + @include roboto-medium; + + display: inline-block; + margin-top: 20px; + cursor: pointer; + height: 40px; + font-size: 15px; + font-weight: 500; + padding: 0; + width: 170px; + white-space: nowrap; + background-color: #006ad7; + color: white; + border-radius: 4px; + + &:hover { + background-image: linear-gradient(180deg, #3996ff, #127bf3); + } + } + } +} diff --git a/src/shared/containers/NewsletterPreferences.jsx b/src/shared/containers/NewsletterPreferences.jsx index 37f61ab3fc..18e1ae1063 100644 --- a/src/shared/containers/NewsletterPreferences.jsx +++ b/src/shared/containers/NewsletterPreferences.jsx @@ -20,7 +20,7 @@ class NewsletterPreferencesContainer extends React.Component { render() { const { - loading, error, preferences, saveEmailPreferences, email, updated, status, resubscibeEmails, + loading, error, preferences, saveEmailPreferences, email, updated, status, } = this.props; if (loading || !preferences) return ; if (error) { @@ -33,7 +33,6 @@ class NewsletterPreferencesContainer extends React.Component { saveEmailPreferences={saveEmailPreferences} updated={updated} status={status} - resubscibeEmails={resubscibeEmails} /> ); } @@ -56,7 +55,6 @@ NewsletterPreferencesContainer.propTypes = { email: PT.string.isRequired, updated: PT.shape(), status: PT.string, - resubscibeEmails: PT.func.isRequired, }; function mapStateToProps(state) { @@ -83,10 +81,6 @@ function mapDispatchToProps(dispatch) { dispatch(actions.newsletterPreferences.updateTagInit()); dispatch(actions.newsletterPreferences.updateTagDone(email, id, checked)); }, - resubscibeEmails: (email) => { - dispatch(actions.newsletterPreferences.resubscribeInit()); - dispatch(actions.newsletterPreferences.resubscribeDone(email)); - }, }; } diff --git a/src/shared/reducers/newsletterPreferences.js b/src/shared/reducers/newsletterPreferences.js index 4c5ee43894..6dab15735d 100644 --- a/src/shared/reducers/newsletterPreferences.js +++ b/src/shared/reducers/newsletterPreferences.js @@ -51,22 +51,6 @@ function onUpdateTagDone(state, { payload }) { }; } -function onResubscribeInit(state) { - return { - ...state, - updated: null, - }; -} - -function onResubscribeDone(state, { payload }) { - // eslint-disable-next-line no-param-reassign - state.preferences[payload.id] = payload.checked; - return { - ...state, - updated: payload, - }; -} - /** * Creates newsletterPreferences reducer with the specified initial state. * @param {Object} state Optional. If not given, the default one is @@ -79,8 +63,6 @@ function create(state = {}) { [actions.newsletterPreferences.fetchDataDone]: onDone, [actions.newsletterPreferences.updateTagInit]: onUpdateTagInit, [actions.newsletterPreferences.updateTagDone]: onUpdateTagDone, - [actions.newsletterPreferences.resubscribeInit]: onResubscribeInit, - [actions.newsletterPreferences.resubscribeDone]: onResubscribeDone, }, state); }