Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit d9d2671

Browse files
authoredFeb 22, 2021
Merge pull request #5363 from topcoder-platform/email-pref-revamp-develop
Email pref revamp develop
2 parents 3692d7b + c8da3e8 commit d9d2671

File tree

14 files changed

+321
-202
lines changed

14 files changed

+321
-202
lines changed
 

‎.circleci/config.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ workflows:
282282
filters:
283283
branches:
284284
only:
285-
- gsheet-contentful-develop
285+
- free
286286
# This is alternate dev env for parallel testing
287287
- "build-qa":
288288
context : org-global
@@ -303,7 +303,7 @@ workflows:
303303
filters:
304304
branches:
305305
only:
306-
- develop
306+
- email-pref-revamp-develop
307307
- "approve-smoke-test-on-staging":
308308
type: approval
309309
requires:

‎__tests__/shared/components/Settings/Preferences/Email/__snapshots__/index.jsx.snap

Lines changed: 41 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -10,69 +10,48 @@ exports[`renders email preferences setting page correctly 1`] = `
1010
E-Mail Preferences
1111
</h1>
1212
<div
13-
className="src-shared-components-Settings-Preferences-Email-___styles__sub-title___2Fh1W"
13+
className="src-shared-components-Settings-Preferences-Email-___styles__unsubscribed-msg___3yh6s"
1414
>
15-
Your preferences
16-
</div>
17-
<div
18-
className="src-shared-components-Settings-Preferences-Email-___styles__preferences-container___38AVF"
19-
>
20-
<ToggleableItem
21-
checked={false}
22-
id="Pipeline"
23-
onToggle={[Function]}
24-
primaryText="Challenge Pipeline"
25-
secondaryText="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 <a href=\\"https://www.topcoder.com/community/pipeline\\" style=\\"color:#0d61bf;text-decoration:underline\\">Challenge Pipeline</a> page."
26-
value="Pipeline"
27-
/>
28-
<ToggleableItem
29-
checked={false}
30-
id="Gig Work"
31-
onToggle={[Function]}
32-
primaryText="Gig Work"
33-
secondaryText="This newsletter gets sent out at various times, specifically when we have an opportunity of mass appeal. For more information you can visit the <a href=\\"https://www.topcoder.com/community/taas\\" style=\\"color:#0d61bf;text-decoration:underline\\">Gig Work</a> page."
34-
value="Gig Work"
35-
/>
36-
<ToggleableItem
37-
checked={false}
38-
id="Monthly Newsletter"
39-
onToggle={[Function]}
40-
primaryText="Monthly Newsletter"
41-
secondaryText="This newsletter gets sent out at the end of every month and contains a variety of important information across all of our tracks."
42-
value="Monthly Newsletter"
43-
/>
44-
<ToggleableItem
45-
checked={false}
46-
id="Marathon Match Reminders"
47-
onToggle={[Function]}
48-
primaryText="Marathon Match Reminders"
49-
secondaryText="Receive updates whenever a new marathon match is scheduled."
50-
value="Marathon Match Reminders"
51-
/>
52-
<ToggleableItem
53-
checked={false}
54-
id="Single Round Match Reminders"
55-
onToggle={[Function]}
56-
primaryText="Single Round Match (SRM) Reminders"
57-
secondaryText="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."
58-
value="Single Round Match Reminders"
59-
/>
60-
<ToggleableItem
61-
checked={false}
62-
id="TCO Tuesdays"
63-
onToggle={[Function]}
64-
primaryText="TCO Newsletter"
65-
secondaryText="For all the latest updates surrounding the <a href=\\"https://www.topcoder.com/community/member-programs/topcoder-open\\" style=\\"color:#0d61bf;text-decoration:underline\\">Topcoder Open</a> you should definitely be subscribing to this one. Expect an update in your mailbox every Tuesday!"
66-
value="TCO Tuesdays"
67-
/>
68-
<ToggleableItem
69-
checked={false}
70-
id="RDM"
71-
onToggle={[Function]}
72-
primaryText="Rapid Development Match (RDM) Reminders"
73-
secondaryText="Receive notifications of our brand new RDMs! These rated, development matches will be a fun new way to engage with us!"
74-
value="RDM"
75-
/>
15+
<h3>
16+
You are not subscribed to receive Topcoder emails
17+
</h3>
18+
<p>
19+
If this was a mistake or if you would like to resubscribe, please click the button below.
20+
</p>
21+
<form
22+
action="https://topcoder.us13.list-manage.com/subscribe/post?u=65bd5a1857b73643aad556093&id=28bfd3c062"
23+
id="mc-embedded-subscribe-form"
24+
method="post"
25+
name="mc-embedded-subscribe-form"
26+
noValidate={true}
27+
>
28+
<input
29+
id="mce-EMAIL"
30+
name="EMAIL"
31+
readOnly={true}
32+
type="email"
33+
value="test@test.com"
34+
/>
35+
<input
36+
id="gdpr_11101"
37+
name="gdpr[11101]"
38+
type="checkbox"
39+
value="Y"
40+
/>
41+
<input
42+
name="b_65bd5a1857b73643aad556093_28bfd3c062"
43+
tabIndex="-1"
44+
type="text"
45+
value=""
46+
/>
47+
<input
48+
className="submit-button"
49+
id="mc-embedded-subscribe"
50+
name="subscribe"
51+
type="submit"
52+
value="Subscribe"
53+
/>
54+
</form>
7655
</div>
7756
</div>
7857
`;

‎package-lock.json

Lines changed: 76 additions & 55 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎src/server/routes/mailchimp.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ routes.post('/:listId/members', (req, res, next) => new MailchimpService().doReg
2020

2121
routes.get('/:listId/members/:emailHash', (req, res) => new MailchimpService().checkSubscription(req).then(res.send.bind(res)));
2222

23-
routes.put('/:listId/members/:emailHash', (req, res) => new MailchimpService().subscribeInterests(req).then(res.send.bind(res)));
23+
routes.put('/:listId/members/:emailHash', (req, res) => new MailchimpService().updateMember(req).then(res.send.bind(res)));
2424

2525
routes.post('/:listId/members/:emailHash/tags', (req, res) => new MailchimpService().subscribeTags(req).then(res.send.bind(res)));
2626

‎src/server/services/mailchimp.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export default class MailchimpService {
5151
return res.json();
5252
}
5353

54-
async subscribeInterests(req) {
54+
async updateMember(req) {
5555
const formData = JSON.stringify(req.body);
5656
const res = await fetch(`${this.mailchimpBaseUrl}/lists/${req.params.listId}/members/${req.params.emailHash}`, {
5757
method: 'PUT',

‎src/shared/actions/newsletterPreferences.js

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ async function fetchDataDone(emailHash, listId = config.NEWSLETTER_SIGNUP.DEFAUL
3535

3636
return {
3737
email: emailHash,
38-
preferences: subs.tags,
38+
preferences: subs.interests,
39+
status: subs.status,
3940
error,
4041
};
4142
} catch (error) {
@@ -48,26 +49,24 @@ async function fetchDataDone(emailHash, listId = config.NEWSLETTER_SIGNUP.DEFAUL
4849

4950
// Updates member newsletter subscription
5051
async function updateSubscriptionsDone(
51-
emailHash, tagId, status, listId = config.NEWSLETTER_SIGNUP.DEFAUL_LIST_ID,
52+
emailHash, groupId, status, listId = config.NEWSLETTER_SIGNUP.DEFAUL_LIST_ID,
5253
) {
5354
/* NOTE: In the real life in most cases you don't want to use fetch() directly
5455
* in an action. You want to create a service for your calls and use it here.
5556
* However, in this example, to keep it a bit more compact, we use fetch()
5657
* directly here. */
5758
try {
5859
let error = false;
59-
const fetchUrl = `${PROXY_ENDPOINT}/${listId}/members/${emailHash}/tags`;
60+
const fetchUrl = `${PROXY_ENDPOINT}/${listId}/members/${emailHash}`;
6061

6162
const data = {
62-
tags: [
63-
{ name: tagId, status: status ? 'active' : 'inactive' },
64-
],
63+
interests: { [groupId]: !!status },
6564
};
6665

6766
const formData = JSON.stringify(data);
6867
// use proxy for avoid 'Access-Control-Allow-Origin' bug
6968
await fetch(fetchUrl, {
70-
method: 'POST',
69+
method: 'PUT',
7170
headers: {
7271
'Content-Type': 'application/json',
7372
},
@@ -79,14 +78,14 @@ async function updateSubscriptionsDone(
7978
});
8079

8180
return {
82-
id: tagId,
81+
id: groupId,
8382
checked: status,
8483
email: emailHash,
8584
error,
8685
};
8786
} catch (error) {
8887
return {
89-
id: tagId,
88+
id: groupId,
9089
checked: status,
9190
email: emailHash,
9291
error,

‎src/shared/components/NewsletterSignupForMembers/ConfirmModal/style.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,9 @@
3333

3434
button {
3535
margin: 24px 12px 0;
36+
37+
&:first-child {
38+
margin-right: 12px !important;
39+
}
3640
}
3741
}
Lines changed: 80 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable max-len */
12
/**
23
* Email Preferences component.
34
*/
@@ -26,41 +27,48 @@ const SAVE_DELAY = 1000;
2627

2728
const newsletters = [
2829
{
29-
id: 'Pipeline',
30+
id: '9f950b43a1',
3031
name: 'Challenge Pipeline',
3132
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 <a href="https://www.topcoder.com/community/pipeline" style="color:#0d61bf;text-decoration:underline">Challenge Pipeline</a> page.',
3233
},
3334
{
34-
id: 'Gig Work',
35+
id: 'd0c48e9da3',
3536
name: 'Gig Work',
3637
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 <a href="https://www.topcoder.com/community/taas" style="color:#0d61bf;text-decoration:underline">Gig Work</a> page.',
3738
},
3839
{
39-
id: 'Monthly Newsletter',
40+
id: 'a8f858cdf1',
4041
name: 'Monthly Newsletter',
4142
desc: 'This newsletter gets sent out at the end of every month and contains a variety of important information across all of our tracks.',
4243
},
4344
{
44-
id: 'Marathon Match Reminders',
45+
id: '5e67dba327',
4546
name: 'Marathon Match Reminders',
4647
desc: 'Receive updates whenever a new marathon match is scheduled.',
4748
},
4849
{
49-
id: 'Single Round Match Reminders',
50+
id: '9091b438cc',
5051
name: 'Single Round Match (SRM) Reminders',
5152
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.',
5253
},
5354
{
54-
id: 'TCO Tuesdays',
55+
id: '603c900c32',
5556
name: 'TCO Newsletter',
5657
desc: 'For all the latest updates surrounding the <a href="https://www.topcoder.com/community/member-programs/topcoder-open" style="color:#0d61bf;text-decoration:underline">Topcoder Open</a> you should definitely be subscribing to this one. Expect an update in your mailbox every Tuesday!',
5758
},
5859
{
59-
id: 'RDM',
60+
id: '3460574ddd',
6061
name: 'Rapid Development Match (RDM) Reminders',
6162
desc: 'Receive notifications of our brand new RDMs! These rated, development matches will be a fun new way to engage with us!',
6263
},
6364
];
65+
const programs = [
66+
{
67+
id: 'cafe98d7a7',
68+
name: 'Beta Testers',
69+
desc: 'If you have applied and been approved as a <a href="https://www.topcoder.com/community/member-programs/beta-testers" style="color:#0d61bf;text-decoration:underline">Beta Tester</a>, you may control the emails you receive here.',
70+
},
71+
];
6472

6573
export default class EmailPreferences extends React.Component {
6674
saveEmailPreferences = debounce((id, checked) => {
@@ -72,6 +80,7 @@ export default class EmailPreferences extends React.Component {
7280
super(props);
7381
this.state = {
7482
emailPreferences: { ...props.preferences },
83+
status: props.status,
7584
};
7685
this.onChange = this.onChange.bind(this);
7786
}
@@ -82,14 +91,14 @@ export default class EmailPreferences extends React.Component {
8291
if (updated.error) {
8392
toastrError('Error! ', 'Failed to update Your email preferences :-(');
8493
}
85-
const { emailPreferences } = this.state;
94+
const { emailPreferences, status } = this.state;
8695
const { id, checked } = updated;
87-
if (!emailPreferences[id]) emailPreferences[id] = { id, checked };
88-
else emailPreferences[id].checked = checked;
96+
emailPreferences[id] = checked;
8997

9098
// eslint-disable-next-line react/no-did-update-set-state
9199
this.setState({
92100
emailPreferences,
101+
status: updated.resubscribe ? 'subscribed' : status,
93102
});
94103
toastrSuccess('Success! ', 'Your email preferences were updated.');
95104
}
@@ -101,46 +110,84 @@ export default class EmailPreferences extends React.Component {
101110
}
102111

103112
render() {
104-
const { emailPreferences } = this.state;
113+
const { emailPreferences, status } = this.state;
114+
const { email } = this.props;
105115
return (
106116
<div styleName="EmailPreferences">
107117
<h1 styleName="title">
108118
E-Mail Preferences
109119
</h1>
110-
<div styleName="sub-title">
111-
Your preferences
112-
</div>
113-
<div styleName="preferences-container">
114-
{
115-
map(newsletters, (newsletter) => {
116-
const checked = emailPreferences[newsletter.id]
117-
? emailPreferences[newsletter.id].checked : false;
118-
return (
119-
<ToggleableItem
120-
key={newsletter.id}
121-
id={newsletter.id}
122-
value={newsletter.id}
123-
checked={checked}
124-
primaryText={newsletter.name}
125-
secondaryText={newsletter.desc}
126-
onToggle={e => this.onChange(newsletter.id, e.target.checked)}
127-
/>
128-
);
129-
})
130-
}
131-
</div>
120+
{
121+
status !== 'subscribed' ? (
122+
<div styleName="unsubscribed-msg">
123+
<h3>You are not subscribed to receive Topcoder emails</h3>
124+
<p>If this was a mistake or if you would like to resubscribe, please click the button below.</p>
125+
<form action="https://topcoder.us13.list-manage.com/subscribe/post?u=65bd5a1857b73643aad556093&amp;id=28bfd3c062" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" noValidate>
126+
<input type="email" value={email} readOnly name="EMAIL" id="mce-EMAIL" />
127+
<input type="checkbox" id="gdpr_11101" name="gdpr[11101]" value="Y" />
128+
<input type="text" name="b_65bd5a1857b73643aad556093_28bfd3c062" tabIndex="-1" value="" />
129+
<input type="submit" value="Subscribe" name="subscribe" id="mc-embedded-subscribe" className="submit-button" />
130+
</form>
131+
</div>
132+
) : (
133+
<React.Fragment>
134+
<div styleName="sub-title">Newsletters</div>
135+
<div styleName="preferences-container">
136+
{
137+
map(newsletters, (newsletter) => {
138+
const checked = emailPreferences[newsletter.id];
139+
return (
140+
<ToggleableItem
141+
key={newsletter.id}
142+
id={newsletter.id}
143+
value={newsletter.id}
144+
checked={checked}
145+
primaryText={newsletter.name}
146+
secondaryText={newsletter.desc}
147+
onToggle={e => this.onChange(newsletter.id, e.target.checked)}
148+
disabled={status !== 'subscribed'}
149+
/>
150+
);
151+
})
152+
}
153+
</div>
154+
<div styleName="sub-title-2">Programs</div>
155+
<div styleName="preferences-container">
156+
{
157+
map(programs, (program) => {
158+
const checked = emailPreferences[program.id];
159+
return (
160+
<ToggleableItem
161+
key={program.id}
162+
id={program.id}
163+
value={program.id}
164+
checked={checked}
165+
primaryText={program.name}
166+
secondaryText={program.desc}
167+
onToggle={e => this.onChange(program.id, e.target.checked)}
168+
disabled={status !== 'subscribed'}
169+
/>
170+
);
171+
})
172+
}
173+
</div>
174+
</React.Fragment>
175+
)
176+
}
132177
</div>
133178
);
134179
}
135180
}
136181

137182
EmailPreferences.defaultProps = {
138183
updated: null,
184+
status: null,
139185
};
140186

141187
EmailPreferences.propTypes = {
142188
email: PT.string.isRequired,
143189
preferences: PT.shape().isRequired,
144190
saveEmailPreferences: PT.func.isRequired,
145191
updated: PT.shape(),
192+
status: PT.string,
146193
};

‎src/shared/components/Settings/Preferences/Email/styles.scss

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
}
1414
}
1515

16-
.sub-title {
16+
.sub-title,
17+
.sub-title-2 {
1718
@include roboto-light;
1819

1920
color: #888894;
@@ -28,7 +29,60 @@
2829
}
2930
}
3031

32+
.sub-title-2 {
33+
margin-top: 30px;
34+
}
35+
3136
.preferences-container {
3237
border-top: 1px solid $tc-gray-neutral-dark;
3338
}
39+
40+
.unsubscribed-msg {
41+
@include sofia-pro-regular;
42+
43+
display: flex;
44+
flex-direction: column;
45+
background-color: $tc-red-10;
46+
border: 1px solid $tc-red-30;
47+
color: $tc-red;
48+
line-height: 20px;
49+
margin-bottom: 25px;
50+
padding: 10px;
51+
text-align: left;
52+
font-size: 13px;
53+
align-items: flex-start;
54+
55+
button {
56+
margin: 20px 0 0 0;
57+
}
58+
}
59+
}
60+
61+
:global {
62+
#mc-embedded-subscribe-form {
63+
input {
64+
display: none;
65+
}
66+
67+
#mc-embedded-subscribe {
68+
@include roboto-medium;
69+
70+
display: inline-block;
71+
margin-top: 20px;
72+
cursor: pointer;
73+
height: 40px;
74+
font-size: 15px;
75+
font-weight: 500;
76+
padding: 0;
77+
width: 170px;
78+
white-space: nowrap;
79+
background-color: #006ad7;
80+
color: white;
81+
border-radius: 4px;
82+
83+
&:hover {
84+
background-image: linear-gradient(180deg, #3996ff, #127bf3);
85+
}
86+
}
87+
}
3488
}

‎src/shared/components/Settings/ToggleableItem/index.jsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export default function ToggleableItem({
1818
primaryText,
1919
secondaryText,
2020
value,
21+
disabled,
2122
}) {
2223
return (
2324
<div styleName="ToggleableItem">
@@ -38,6 +39,7 @@ export default function ToggleableItem({
3839
checked={checked}
3940
onChange={onToggle}
4041
className="onoffswitch-checkbox"
42+
disabled={disabled}
4143
/>
4244
<label htmlFor={`pre-onoffswitch-${id}`} className="onoffswitch-label">
4345
<span className="onoffswitch-inner" />
@@ -54,6 +56,7 @@ export default function ToggleableItem({
5456
checked={checked}
5557
onChange={onToggle}
5658
className="onoffswitch-checkbox"
59+
disabled={disabled}
5760
/>
5861
<label htmlFor={`pre-onoffswitch-${id}`} className="onoffswitch-label">
5962
<span className="onoffswitch-inner" />
@@ -65,11 +68,16 @@ export default function ToggleableItem({
6568
);
6669
}
6770

71+
ToggleableItem.defaultProps = {
72+
disabled: false,
73+
};
74+
6875
ToggleableItem.propTypes = {
6976
id: PT.string.isRequired,
7077
value: PT.string.isRequired,
7178
checked: PT.bool.isRequired,
7279
primaryText: PT.string.isRequired,
7380
secondaryText: PT.string.isRequired,
7481
onToggle: PT.func.isRequired,
82+
disabled: PT.bool,
7583
};

‎src/shared/containers/EmailSubscribeForm/index.jsx

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,41 +32,42 @@ class SubscribeMailChimpTagContainer extends React.Component {
3232
this.setState((state) => {
3333
const { formData, formErrors } = state;
3434
if (_.isEmpty(formErrors)) {
35-
const { listId, tags } = this.props;
36-
const fetchUrl = `${PROXY_ENDPOINT}/${listId}/members/${formData.email}/tags`;
35+
const { listId, interests } = this.props;
36+
const fetchUrl = `${PROXY_ENDPOINT}/${listId}/members/${formData.email}`;
3737
const data = {
38-
email_address: formData.email,
3938
status: 'subscribed',
40-
tags: tags.map(t => ({ name: t, status: 'active' })),
41-
merge_fields: {
42-
FNAME: formData.fname,
43-
LNAME: formData.lname,
44-
},
39+
interests,
4540
};
4641
fetch(fetchUrl, {
47-
method: 'POST',
42+
method: 'PUT',
4843
headers: {
4944
'Content-Type': 'application/json',
5045
},
5146
body: JSON.stringify(data),
5247
}).then(result => result.json()).then((dataResponse) => {
53-
if (dataResponse.status === 204) {
48+
if (dataResponse.status === 'subscribed') {
5449
// regist success
5550
return this.setState({
5651
subscribing: false,
5752
subsribed: true,
5853
error: '',
5954
});
6055
}
61-
if (dataResponse.status === 404) {
56+
if (dataResponse.status === 400) {
6257
// new email register it for list and add tags
63-
data.tags = tags;
6458
return fetch(`${PROXY_ENDPOINT}/${listId}/members`, {
6559
method: 'POST',
6660
headers: {
6761
'Content-Type': 'application/json',
6862
},
69-
body: JSON.stringify(data),
63+
body: JSON.stringify({
64+
...data,
65+
email_address: formData.email,
66+
merge_fields: {
67+
FNAME: formData.fname,
68+
LNAME: formData.lname,
69+
},
70+
}),
7071
})
7172
.then(result => result.json()).then((rsp) => {
7273
this.setState({
@@ -79,7 +80,7 @@ class SubscribeMailChimpTagContainer extends React.Component {
7980
return this.setState({
8081
subscribing: false,
8182
subsribed: false,
82-
error: `Error ${dataResponse.status} when assigning tags to ${formData.email}`,
83+
error: `Error ${dataResponse.status} when subscribing ${formData.email}`,
8384
});
8485
})
8586
.catch((e) => {
@@ -209,7 +210,7 @@ SubscribeMailChimpTagContainer.defaultProps = {
209210

210211
SubscribeMailChimpTagContainer.propTypes = {
211212
listId: PT.string.isRequired,
212-
tags: PT.arrayOf(PT.string).isRequired,
213+
interests: PT.shape().isRequired,
213214
title: PT.string,
214215
btnText: PT.string,
215216
successTitle: PT.string,

‎src/shared/containers/NewsletterPreferences.jsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class NewsletterPreferencesContainer extends React.Component {
2020

2121
render() {
2222
const {
23-
loading, error, preferences, saveEmailPreferences, email, updated,
23+
loading, error, preferences, saveEmailPreferences, email, updated, status,
2424
} = this.props;
2525
if (loading || !preferences) return <LoadingIndicator />;
2626
if (error) {
@@ -32,6 +32,7 @@ class NewsletterPreferencesContainer extends React.Component {
3232
preferences={preferences}
3333
saveEmailPreferences={saveEmailPreferences}
3434
updated={updated}
35+
status={status}
3536
/>
3637
);
3738
}
@@ -42,6 +43,7 @@ NewsletterPreferencesContainer.defaultProps = {
4243
error: null,
4344
preferences: null,
4445
updated: null,
46+
status: null,
4547
};
4648

4749
NewsletterPreferencesContainer.propTypes = {
@@ -52,6 +54,7 @@ NewsletterPreferencesContainer.propTypes = {
5254
preferences: PT.shape(),
5355
email: PT.string.isRequired,
5456
updated: PT.shape(),
57+
status: PT.string,
5558
};
5659

5760
function mapStateToProps(state) {
@@ -61,6 +64,7 @@ function mapStateToProps(state) {
6164
loading: newsletterPreferences.loading,
6265
error: newsletterPreferences.error,
6366
preferences: newsletterPreferences.preferences,
67+
status: newsletterPreferences.status,
6468
updated: newsletterPreferences.updated,
6569
};
6670
}

‎src/shared/containers/NewsletterSignupForMembers.jsx

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,11 @@ class NewsletterSignupForMembersContainer extends React.Component {
3131

3232
// Get interestIds and interest request object for mailchimp api
3333
// to use in checkSubscription and subscribe function
34-
const { tags } = props;
35-
this.tagsIds = null;
36-
if (tags !== '') {
37-
this.tagsIds = tags.split(/ *, */);
38-
this.tagsIds[this.tagsIds.length - 1] = this.tagsIds[this.tagsIds.length - 1].replace(/^\s+|\s+$/g, '');
34+
const { groups } = props;
35+
this.groupsIds = null;
36+
if (groups !== '') {
37+
this.groupsIds = groups.split(/ *, */);
38+
this.groupsIds[this.groupsIds.length - 1] = this.groupsIds[this.groupsIds.length - 1].replace(/^\s+|\s+$/g, '');
3939
}
4040
this.isSubscribed = false;
4141

@@ -89,9 +89,9 @@ class NewsletterSignupForMembersContainer extends React.Component {
8989
.then((dataResponse) => {
9090
if (dataResponse.status === 'subscribed') {
9191
this.isSubscribed = true;
92-
const subscribedTags = dataResponse.tags.map(t => t.name);
92+
const subscribedTags = _.keys(_.pickBy(dataResponse.interests, v => v));
9393
if (subscribedTags.length) {
94-
if (_.intersection(subscribedTags, this.tagsIds).length) {
94+
if (_.intersection(subscribedTags, this.groupsIds).length) {
9595
this.setState({ signupState: SIGNUP_NEWSLETTER.HIDDEN });
9696
}
9797
} else {
@@ -108,7 +108,7 @@ class NewsletterSignupForMembersContainer extends React.Component {
108108
listId, user,
109109
} = this.props;
110110

111-
const fetchUrl = `${PROXY_ENDPOINT}/${listId}/members/${this.emailHash}/tags`;
111+
const fetchUrl = `${PROXY_ENDPOINT}/${listId}/members/${this.emailHash}`;
112112

113113
let data = {};
114114
if (!this.isSubscribed) {
@@ -122,18 +122,24 @@ class NewsletterSignupForMembersContainer extends React.Component {
122122
};
123123
}
124124

125-
if (this.tagsIds) data.tags = this.tagsIds.map(t => ({ name: t, status: 'active' }));
125+
if (this.groupsIds) {
126+
data.interests = {};
127+
// eslint-disable-next-line array-callback-return
128+
this.groupsIds.map((group) => {
129+
data.interests[group] = true;
130+
});
131+
}
126132

127133
const formData = JSON.stringify(data);
128134
// use proxy for avoid 'Access-Control-Allow-Origin' bug
129135
await fetch(fetchUrl, {
130-
method: 'POST',
136+
method: 'PUT',
131137
headers: {
132138
'Content-Type': 'application/json',
133139
},
134140
body: formData,
135141
}).then(result => result.json()).then((dataResponse) => {
136-
if (dataResponse.status === 204) {
142+
if (dataResponse.status === 'subscribed') {
137143
// regist success
138144
this.setState({ signupState: SIGNUP_NEWSLETTER.SIGNEDUP });
139145
} else {
@@ -183,7 +189,7 @@ class NewsletterSignupForMembersContainer extends React.Component {
183189
NewsletterSignupForMembersContainer.defaultProps = {
184190
token: '',
185191
label: 'Subscribe for Newsletter',
186-
tags: '',
192+
groups: '',
187193
user: null,
188194
buttonTheme: 'primary-green-md',
189195
title: 'Sign up for the Topcoder Newsletter',
@@ -194,7 +200,7 @@ NewsletterSignupForMembersContainer.propTypes = {
194200
authenticating: PT.bool.isRequired,
195201
token: PT.string,
196202
label: PT.string,
197-
tags: PT.string,
203+
groups: PT.string,
198204
listId: PT.string.isRequired,
199205
user: PT.shape(),
200206
buttonTheme: PT.string,

‎src/shared/reducers/newsletterPreferences.js

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ function onInit(state, { payload }) {
1414
return {
1515
...state,
1616
email: payload,
17-
preferences: [],
17+
preferences: {},
18+
status: null,
1819
loading: true,
1920
};
2021
}
@@ -25,15 +26,10 @@ function onInit(state, { payload }) {
2526
* @param {Object} action The action.
2627
*/
2728
function onDone(state, { payload }) {
28-
const preferences = {};
29-
if (payload.preferences) {
30-
payload.preferences.forEach((record) => {
31-
preferences[record.name] = { ...record, checked: true };
32-
});
33-
}
3429
return {
3530
...state,
36-
preferences: payload.error ? null : preferences,
31+
preferences: payload.error ? null : payload.preferences,
32+
status: payload.error ? null : payload.status,
3733
error: payload.error,
3834
loading: false,
3935
};
@@ -48,7 +44,7 @@ function onUpdateTagInit(state) {
4844

4945
function onUpdateTagDone(state, { payload }) {
5046
// eslint-disable-next-line no-param-reassign
51-
state.preferences[payload.id] = { name: payload.id, checked: payload.checked };
47+
state.preferences[payload.id] = payload.checked;
5248
return {
5349
...state,
5450
updated: payload,

0 commit comments

Comments
 (0)
Please sign in to comment.