Skip to content

Commit 50d2fbf

Browse files
Merge pull request #5904 from topcoder-platform/ca-profile-bug-bash
[Bug Bash] Ca profile bug bash - round 3
2 parents dd3826e + fa2590f commit 50d2fbf

File tree

13 files changed

+148
-32
lines changed

13 files changed

+148
-32
lines changed

src/shared/components/InputSelect/index.jsx

+7-3
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ export default class InputSelect extends Component {
111111
let i = 0;
112112
let node = e.target;
113113
const REG = new RegExp(_id);
114-
while (node && i < 5) {
114+
while (node && i < 20) {
115115
if (REG.test(node.className)) {
116116
return true;
117117
}
@@ -131,6 +131,7 @@ export default class InputSelect extends Component {
131131
placeholder,
132132
labelKey,
133133
options,
134+
onKeyPress,
134135
} = this.props;
135136

136137
const {
@@ -139,9 +140,10 @@ export default class InputSelect extends Component {
139140
filterVal,
140141
} = this.state;
141142

143+
const escapeRegExp = stringToGoIntoTheRegex => stringToGoIntoTheRegex.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); /* eslint-disable-line no-useless-escape */
142144
let fiterList = options;
143145
if (filterVal) {
144-
const REG = new RegExp(filterVal, 'i');
146+
const REG = new RegExp(escapeRegExp(filterVal), 'i');
145147
fiterList = filter(options, o => REG.test(o[labelKey]));
146148
}
147149
const list = map(fiterList, o => (
@@ -171,7 +173,7 @@ export default class InputSelect extends Component {
171173
<div styleName="modal">
172174
<div styleName="modal-input-container">
173175

174-
<input type="text" onChange={this.onFilterChange} placeholder="Search" />
176+
<input type="text" onChange={this.onFilterChange} placeholder="Search" onKeyPress={onKeyPress} />
175177
</div>
176178
<div styleName="modal-list-container" onScroll={this.onLoadMore}>
177179
{list}
@@ -195,6 +197,7 @@ InputSelect.defaultProps = {
195197
isLoading: false,
196198
onChange: () => {},
197199
onLoadMore: () => {},
200+
onKeyPress: () => {},
198201
};
199202

200203
InputSelect.propTypes = {
@@ -205,6 +208,7 @@ InputSelect.propTypes = {
205208
placeholder: PT.string,
206209
onChange: PT.func,
207210
onLoadMore: PT.func,
211+
onKeyPress: PT.func,
208212
hasMore: PT.bool,
209213
isLoading: PT.bool,
210214
disabled: PT.bool,

src/shared/components/Settings/Account/MyAccount/index.jsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -585,7 +585,7 @@ export default class MyAccount extends ConsentComponent {
585585
</div>
586586
</div>
587587
{
588-
get(profileState, 'credential.hasPassword', false) === false && (
588+
get(profileState, 'credential.hasPassword') === false && (
589589
<div styleName="error-message">
590590
Since you joined Topcoder using your &lt;SSO Service&gt; account,
591591
any email updates will need to be handled by logging in to

src/shared/components/Settings/Preferences/Email/index.jsx

+19-9
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,13 @@ const programs = [
7272

7373
export default class EmailPreferences extends React.Component {
7474
saveEmailPreferences = debounce((id, checked) => {
75+
// update local state
76+
const { emailPreferences, status } = this.state;
77+
emailPreferences[id] = checked;
78+
this.setState({
79+
emailPreferences,
80+
status: checked ? 'subscribed' : status,
81+
});
7582
const { email, saveEmailPreferences } = this.props;
7683
saveEmailPreferences(email, id, checked);
7784
}, SAVE_DELAY);
@@ -93,19 +100,22 @@ export default class EmailPreferences extends React.Component {
93100
}
94101
const { emailPreferences, status } = this.state;
95102
const { id, checked } = updated;
96-
emailPreferences[id] = checked;
103+
if (emailPreferences[id] !== checked) {
104+
emailPreferences[id] = checked;
97105

98-
// eslint-disable-next-line react/no-did-update-set-state
99-
this.setState({
100-
emailPreferences,
101-
status: updated.resubscribe ? 'subscribed' : status,
102-
});
106+
// eslint-disable-next-line react/no-did-update-set-state
107+
this.setState({
108+
emailPreferences,
109+
status: updated.resubscribe ? 'subscribed' : status,
110+
});
111+
}
103112
toastrSuccess('Success! ', 'Your email preferences were updated.');
104113
}
105114
}
106115

107116
onChange(id, checked) {
108-
document.querySelectorAll(`#pre-onoffswitch-${id}`).forEach((el) => { el.checked = checked; }); // eslint-disable-line no-param-reassign
117+
// document.querySelectorAll(`#pre-onoffswitch-${id}`).forEach((el) => { el.checked = checked; }); // eslint-disable-line no-param-reassign
118+
// update remote state
109119
this.saveEmailPreferences(id, checked);
110120
}
111121

@@ -144,7 +154,7 @@ export default class EmailPreferences extends React.Component {
144154
checked={checked}
145155
primaryText={newsletter.name}
146156
secondaryText={newsletter.desc}
147-
onToggle={e => this.onChange(newsletter.id, e.target.checked)}
157+
onToggle={c => this.onChange(newsletter.id, c)}
148158
disabled={status !== 'subscribed'}
149159
/>
150160
);
@@ -164,7 +174,7 @@ export default class EmailPreferences extends React.Component {
164174
checked={checked}
165175
primaryText={program.name}
166176
secondaryText={program.desc}
167-
onToggle={e => this.onChange(program.id, e.target.checked)}
177+
onToggle={c => this.onChange(program.id, c)}
168178
disabled={status !== 'subscribed'}
169179
/>
170180
);

src/shared/components/Settings/Preferences/Personalization/index.jsx

+9-1
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,16 @@
22
* Personalization component.
33
*/
44
import React from 'react';
5+
import { debounce } from 'lodash';
6+
57
import PT from 'prop-types';
68

79
import ToggleableItem from 'components/Settings/ToggleableItem';
810

911
import './styles.scss';
1012

13+
const SAVE_DELAY = 1000;
14+
1115
export default function Personalization({
1216
addUserTrait,
1317
handle,
@@ -51,6 +55,10 @@ export default function Personalization({
5155
}
5256
};
5357

58+
const debounceUpdateConsent = debounce(() => {
59+
updateConsent();
60+
}, SAVE_DELAY);
61+
5462
return (
5563
<div styleName="Personalization">
5664
<div styleName="user-consent-container">
@@ -60,7 +68,7 @@ export default function Personalization({
6068
checked={getUserConsent()}
6169
primaryText={primaryText}
6270
secondaryText={secondaryText}
63-
onToggle={updateConsent}
71+
onToggle={debounceUpdateConsent}
6472
/>
6573
</div>
6674
</div>

src/shared/components/Settings/Profile/Language/index.jsx

+17-5
Original file line numberDiff line numberDiff line change
@@ -244,11 +244,11 @@ export default class Language extends ConsentComponent {
244244
const newLanguageTrait = _.cloneDeep(languageTrait);
245245

246246
if (isEdit) {
247-
newLanguageTrait.traits.data.splice(indexNo, 1);
247+
newLanguageTrait.traits.data.splice(indexNo, 1, language);
248+
} else {
249+
newLanguageTrait.traits.data.push(language);
248250
}
249251

250-
newLanguageTrait.traits.data.push(language);
251-
252252
updateUserTrait(handle, 'languages', newLanguageTrait.traits.data, tokenV3);
253253
} else {
254254
const newLanguages = [];
@@ -441,7 +441,13 @@ export default class Language extends ConsentComponent {
441441
<Select
442442
name="spokenLevel"
443443
options={dropdowns.spokenLevel}
444-
onChange={this.onUpdateSelect}
444+
onChange={(option) => {
445+
if (option) {
446+
this.onUpdateSelect(option);
447+
} else {
448+
this.onUpdateSelect({ key: 'spokenLevel', name: '' });
449+
}
450+
}}
445451
value={newLanguage.spokenLevel}
446452
placeholder="Spoken level"
447453
labelKey="name"
@@ -461,7 +467,13 @@ export default class Language extends ConsentComponent {
461467
<Select
462468
name="writtenLevel"
463469
options={dropdowns.writtenLevel}
464-
onChange={this.onUpdateSelect}
470+
onChange={(option) => {
471+
if (option) {
472+
this.onUpdateSelect(option);
473+
} else {
474+
this.onUpdateSelect({ key: 'writtenLevel', name: '' });
475+
}
476+
}}
465477
value={newLanguage.writtenLevel}
466478
placeholder="Written level"
467479
labelKey="name"

src/shared/components/Settings/Profile/Work/index.jsx

+22-6
Original file line numberDiff line numberDiff line change
@@ -139,12 +139,10 @@ export default class Work extends ConsentComponent {
139139
}
140140

141141
onUpdateDate(date, timePeriod) {
142-
if (date) {
143-
const { newWork: oldWork } = this.state;
144-
const newWork = { ...oldWork };
145-
newWork[timePeriod] = date;
146-
this.setState({ newWork, isSubmit: false });
147-
}
142+
const { newWork: oldWork } = this.state;
143+
const newWork = { ...oldWork };
144+
newWork[timePeriod] = date;
145+
this.setState({ newWork, isSubmit: false });
148146
}
149147

150148
/**
@@ -174,6 +172,16 @@ export default class Work extends ConsentComponent {
174172

175173
this.setState({
176174
showConfirmation: false,
175+
newWork: {
176+
company: '',
177+
position: '',
178+
cityTown: '',
179+
timePeriodFrom: '',
180+
timePeriodTo: '',
181+
industry: '',
182+
working: false,
183+
},
184+
isEdit: false,
177185
indexNo: null,
178186
isSubmit: false,
179187
formInvalid: false,
@@ -482,11 +490,13 @@ export default class Work extends ConsentComponent {
482490
<div styleName="field col-2">
483491
<DatePicker
484492
readOnly
493+
showClearDate
485494
numberOfMonths={1}
486495
isOutsideRange={moment().subtract(1, 'd')}
487496
date={newWork.timePeriodFrom}
488497
id="date-from1"
489498
onDateChange={date => this.onUpdateDate(date, 'timePeriodFrom')}
499+
onClearDate={date => this.onUpdateDate('', 'timePeriodFrom')} // eslint-disable-line no-unused-vars
490500
placeholder="dd/mm/yyyy"
491501
/>
492502
{
@@ -509,12 +519,14 @@ export default class Work extends ConsentComponent {
509519
<div styleName="field col-2">
510520
<DatePicker
511521
readOnly
522+
showClearDate
512523
disabled={endDateDisabled}
513524
numberOfMonths={1}
514525
isOutsideRange={moment().subtract(1, 'd')}
515526
date={newWork.timePeriodTo}
516527
id="date-to1"
517528
onDateChange={date => this.onUpdateDate(date, 'timePeriodTo')}
529+
onClearDate={date => this.onUpdateDate('', 'timePeriodTo')} // eslint-disable-line no-unused-vars
518530
placeholder="dd/mm/yyyy"
519531
/>
520532
{
@@ -633,11 +645,13 @@ export default class Work extends ConsentComponent {
633645
</label>
634646
<DatePicker
635647
readOnly
648+
showClearDate
636649
numberOfMonths={1}
637650
isOutsideRange={moment().subtract(1, 'd')}
638651
date={newWork.timePeriodFrom}
639652
id="date-from2"
640653
onDateChange={date => this.onUpdateDate(date, 'timePeriodFrom')}
654+
onClearDate={date => this.onUpdateDate('', 'timePeriodFrom')} // eslint-disable-line no-unused-vars
641655
placeholder="dd/mm/yyyy"
642656
/>
643657
{
@@ -656,12 +670,14 @@ export default class Work extends ConsentComponent {
656670
</label>
657671
<DatePicker
658672
readOnly
673+
showClearDate
659674
disabled={endDateDisabled}
660675
numberOfMonths={1}
661676
isOutsideRange={moment().subtract(1, 'd')}
662677
date={newWork.timePeriodTo}
663678
id="date-to2"
664679
onDateChange={date => this.onUpdateDate(date, 'timePeriodTo')}
680+
onClearDate={date => this.onUpdateDate('', 'timePeriodTo')} // eslint-disable-line no-unused-vars
665681
placeholder="dd/mm/yyyy"
666682
/>
667683
{

src/shared/components/Settings/Profile/Work/styles.scss

+14
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,20 @@ label {
349349
display: none;
350350
}
351351
}
352+
353+
:global {
354+
.SingleDatePickerInput_clearDate {
355+
height: 35px;
356+
width: 35px;
357+
display: flex;
358+
align-items: center;
359+
top: calc(50% - 5px);
360+
}
361+
362+
.SingleDatePickerInput__showClearDate {
363+
padding-right: 0;
364+
}
365+
}
352366
}
353367

354368
.button-container {

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

+19-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* text, a gray secondary text and a toggle that triggers a function
66
* passed via props.
77
*/
8-
import React from 'react';
8+
import React, { useRef } from 'react';
99
import PT from 'prop-types';
1010
import ReactHtmlParser from 'react-html-parser';
1111

@@ -20,6 +20,20 @@ export default function ToggleableItem({
2020
value,
2121
disabled,
2222
}) {
23+
const inputRef = useRef();
24+
const inputMobileRef = useRef();
25+
26+
const onChange = () => {
27+
if (inputRef.current) {
28+
inputRef.current.checked = !inputRef.current.checked;
29+
onToggle(inputRef.current.checked);
30+
}
31+
if (inputMobileRef.current) {
32+
inputMobileRef.current.checked = !inputMobileRef.current.checked;
33+
onToggle(inputMobileRef.current.checked);
34+
}
35+
};
36+
2337
return (
2438
<div styleName="ToggleableItem">
2539
<div styleName="body">
@@ -32,12 +46,13 @@ export default function ToggleableItem({
3246
</div>
3347
<div className="onoffswitch" styleName="onoffswitch-no-padding-right">
3448
<input
49+
ref={inputRef}
3550
type="checkbox"
3651
name="eprf-onoffswitch"
3752
id={`pre-onoffswitch-${id}`}
3853
value={value}
3954
checked={checked}
40-
onChange={onToggle}
55+
onChange={onChange}
4156
className="onoffswitch-checkbox"
4257
disabled={disabled}
4358
/>
@@ -49,12 +64,13 @@ export default function ToggleableItem({
4964
</div>
5065
<div className="onoffswitch-mobile" styleName="onoffswitch-no-padding-right">
5166
<input
67+
ref={inputMobileRef}
5268
type="checkbox"
5369
name="eprf-onoffswitch"
5470
id={`pre-onoffswitch-${id}`}
5571
value={value}
5672
checked={checked}
57-
onChange={onToggle}
73+
onChange={onChange}
5874
className="onoffswitch-checkbox"
5975
disabled={disabled}
6076
/>

0 commit comments

Comments
 (0)