diff --git a/src/shared/components/InputSelect/index.jsx b/src/shared/components/InputSelect/index.jsx index a91c088093..bd43cbbdcc 100644 --- a/src/shared/components/InputSelect/index.jsx +++ b/src/shared/components/InputSelect/index.jsx @@ -111,7 +111,7 @@ export default class InputSelect extends Component { let i = 0; let node = e.target; const REG = new RegExp(_id); - while (node && i < 5) { + while (node && i < 20) { if (REG.test(node.className)) { return true; } @@ -131,6 +131,7 @@ export default class InputSelect extends Component { placeholder, labelKey, options, + onKeyPress, } = this.props; const { @@ -139,9 +140,10 @@ export default class InputSelect extends Component { filterVal, } = this.state; + const escapeRegExp = stringToGoIntoTheRegex => stringToGoIntoTheRegex.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); /* eslint-disable-line no-useless-escape */ let fiterList = options; if (filterVal) { - const REG = new RegExp(filterVal, 'i'); + const REG = new RegExp(escapeRegExp(filterVal), 'i'); fiterList = filter(options, o => REG.test(o[labelKey])); } const list = map(fiterList, o => ( @@ -171,7 +173,7 @@ export default class InputSelect extends Component {
- +
{list} @@ -195,6 +197,7 @@ InputSelect.defaultProps = { isLoading: false, onChange: () => {}, onLoadMore: () => {}, + onKeyPress: () => {}, }; InputSelect.propTypes = { @@ -205,6 +208,7 @@ InputSelect.propTypes = { placeholder: PT.string, onChange: PT.func, onLoadMore: PT.func, + onKeyPress: PT.func, hasMore: PT.bool, isLoading: PT.bool, disabled: PT.bool, diff --git a/src/shared/components/Settings/Account/MyAccount/index.jsx b/src/shared/components/Settings/Account/MyAccount/index.jsx index b7e688ba22..21f0adeecb 100644 --- a/src/shared/components/Settings/Account/MyAccount/index.jsx +++ b/src/shared/components/Settings/Account/MyAccount/index.jsx @@ -585,7 +585,7 @@ export default class MyAccount extends ConsentComponent {
{ - get(profileState, 'credential.hasPassword', false) === false && ( + get(profileState, 'credential.hasPassword') === false && (
Since you joined Topcoder using your <SSO Service> account, any email updates will need to be handled by logging in to diff --git a/src/shared/components/Settings/Preferences/Email/index.jsx b/src/shared/components/Settings/Preferences/Email/index.jsx index d8d80ecfa3..9b2948d851 100644 --- a/src/shared/components/Settings/Preferences/Email/index.jsx +++ b/src/shared/components/Settings/Preferences/Email/index.jsx @@ -72,6 +72,13 @@ const programs = [ export default class EmailPreferences extends React.Component { saveEmailPreferences = debounce((id, checked) => { + // update local state + const { emailPreferences, status } = this.state; + emailPreferences[id] = checked; + this.setState({ + emailPreferences, + status: checked ? 'subscribed' : status, + }); const { email, saveEmailPreferences } = this.props; saveEmailPreferences(email, id, checked); }, SAVE_DELAY); @@ -93,19 +100,22 @@ export default class EmailPreferences extends React.Component { } const { emailPreferences, status } = this.state; const { id, checked } = updated; - emailPreferences[id] = checked; + if (emailPreferences[id] !== checked) { + emailPreferences[id] = checked; - // eslint-disable-next-line react/no-did-update-set-state - this.setState({ - emailPreferences, - status: updated.resubscribe ? 'subscribed' : status, - }); + // 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.'); } } onChange(id, checked) { - document.querySelectorAll(`#pre-onoffswitch-${id}`).forEach((el) => { el.checked = checked; }); // eslint-disable-line no-param-reassign + // document.querySelectorAll(`#pre-onoffswitch-${id}`).forEach((el) => { el.checked = checked; }); // eslint-disable-line no-param-reassign + // update remote state this.saveEmailPreferences(id, checked); } @@ -144,7 +154,7 @@ export default class EmailPreferences extends React.Component { checked={checked} primaryText={newsletter.name} secondaryText={newsletter.desc} - onToggle={e => this.onChange(newsletter.id, e.target.checked)} + onToggle={c => this.onChange(newsletter.id, c)} disabled={status !== 'subscribed'} /> ); @@ -164,7 +174,7 @@ export default class EmailPreferences extends React.Component { checked={checked} primaryText={program.name} secondaryText={program.desc} - onToggle={e => this.onChange(program.id, e.target.checked)} + onToggle={c => this.onChange(program.id, c)} disabled={status !== 'subscribed'} /> ); diff --git a/src/shared/components/Settings/Preferences/Personalization/index.jsx b/src/shared/components/Settings/Preferences/Personalization/index.jsx index 67a65c68d8..60b2d9f5d1 100644 --- a/src/shared/components/Settings/Preferences/Personalization/index.jsx +++ b/src/shared/components/Settings/Preferences/Personalization/index.jsx @@ -2,12 +2,16 @@ * Personalization component. */ import React from 'react'; +import { debounce } from 'lodash'; + import PT from 'prop-types'; import ToggleableItem from 'components/Settings/ToggleableItem'; import './styles.scss'; +const SAVE_DELAY = 1000; + export default function Personalization({ addUserTrait, handle, @@ -51,6 +55,10 @@ export default function Personalization({ } }; + const debounceUpdateConsent = debounce(() => { + updateConsent(); + }, SAVE_DELAY); + return (
@@ -60,7 +68,7 @@ export default function Personalization({ checked={getUserConsent()} primaryText={primaryText} secondaryText={secondaryText} - onToggle={updateConsent} + onToggle={debounceUpdateConsent} />
diff --git a/src/shared/components/Settings/Profile/Language/index.jsx b/src/shared/components/Settings/Profile/Language/index.jsx index 57ba250dc9..c61fa0b13a 100644 --- a/src/shared/components/Settings/Profile/Language/index.jsx +++ b/src/shared/components/Settings/Profile/Language/index.jsx @@ -244,11 +244,11 @@ export default class Language extends ConsentComponent { const newLanguageTrait = _.cloneDeep(languageTrait); if (isEdit) { - newLanguageTrait.traits.data.splice(indexNo, 1); + newLanguageTrait.traits.data.splice(indexNo, 1, language); + } else { + newLanguageTrait.traits.data.push(language); } - newLanguageTrait.traits.data.push(language); - updateUserTrait(handle, 'languages', newLanguageTrait.traits.data, tokenV3); } else { const newLanguages = []; @@ -441,7 +441,13 @@ export default class Language extends ConsentComponent { { + if (option) { + this.onUpdateSelect(option); + } else { + this.onUpdateSelect({ key: 'writtenLevel', name: '' }); + } + }} value={newLanguage.writtenLevel} placeholder="Written level" labelKey="name" diff --git a/src/shared/components/Settings/Profile/Work/index.jsx b/src/shared/components/Settings/Profile/Work/index.jsx index bbff9e769d..5ec1e52cc7 100644 --- a/src/shared/components/Settings/Profile/Work/index.jsx +++ b/src/shared/components/Settings/Profile/Work/index.jsx @@ -139,12 +139,10 @@ export default class Work extends ConsentComponent { } onUpdateDate(date, timePeriod) { - if (date) { - const { newWork: oldWork } = this.state; - const newWork = { ...oldWork }; - newWork[timePeriod] = date; - this.setState({ newWork, isSubmit: false }); - } + const { newWork: oldWork } = this.state; + const newWork = { ...oldWork }; + newWork[timePeriod] = date; + this.setState({ newWork, isSubmit: false }); } /** @@ -174,6 +172,16 @@ export default class Work extends ConsentComponent { this.setState({ showConfirmation: false, + newWork: { + company: '', + position: '', + cityTown: '', + timePeriodFrom: '', + timePeriodTo: '', + industry: '', + working: false, + }, + isEdit: false, indexNo: null, isSubmit: false, formInvalid: false, @@ -482,11 +490,13 @@ export default class Work extends ConsentComponent {
this.onUpdateDate(date, 'timePeriodFrom')} + onClearDate={date => this.onUpdateDate('', 'timePeriodFrom')} // eslint-disable-line no-unused-vars placeholder="dd/mm/yyyy" /> { @@ -509,12 +519,14 @@ export default class Work extends ConsentComponent {
this.onUpdateDate(date, 'timePeriodTo')} + onClearDate={date => this.onUpdateDate('', 'timePeriodTo')} // eslint-disable-line no-unused-vars placeholder="dd/mm/yyyy" /> { @@ -633,11 +645,13 @@ export default class Work extends ConsentComponent { this.onUpdateDate(date, 'timePeriodFrom')} + onClearDate={date => this.onUpdateDate('', 'timePeriodFrom')} // eslint-disable-line no-unused-vars placeholder="dd/mm/yyyy" /> { @@ -656,12 +670,14 @@ export default class Work extends ConsentComponent { this.onUpdateDate(date, 'timePeriodTo')} + onClearDate={date => this.onUpdateDate('', 'timePeriodTo')} // eslint-disable-line no-unused-vars placeholder="dd/mm/yyyy" /> { diff --git a/src/shared/components/Settings/Profile/Work/styles.scss b/src/shared/components/Settings/Profile/Work/styles.scss index 937adc83e5..a8e9a790f5 100644 --- a/src/shared/components/Settings/Profile/Work/styles.scss +++ b/src/shared/components/Settings/Profile/Work/styles.scss @@ -349,6 +349,20 @@ label { display: none; } } + + :global { + .SingleDatePickerInput_clearDate { + height: 35px; + width: 35px; + display: flex; + align-items: center; + top: calc(50% - 5px); + } + + .SingleDatePickerInput__showClearDate { + padding-right: 0; + } + } } .button-container { diff --git a/src/shared/components/Settings/ToggleableItem/index.jsx b/src/shared/components/Settings/ToggleableItem/index.jsx index d5d4552a71..3aee1334a4 100644 --- a/src/shared/components/Settings/ToggleableItem/index.jsx +++ b/src/shared/components/Settings/ToggleableItem/index.jsx @@ -5,7 +5,7 @@ * text, a gray secondary text and a toggle that triggers a function * passed via props. */ -import React from 'react'; +import React, { useRef } from 'react'; import PT from 'prop-types'; import ReactHtmlParser from 'react-html-parser'; @@ -20,6 +20,20 @@ export default function ToggleableItem({ value, disabled, }) { + const inputRef = useRef(); + const inputMobileRef = useRef(); + + const onChange = () => { + if (inputRef.current) { + inputRef.current.checked = !inputRef.current.checked; + onToggle(inputRef.current.checked); + } + if (inputMobileRef.current) { + inputMobileRef.current.checked = !inputMobileRef.current.checked; + onToggle(inputMobileRef.current.checked); + } + }; + return (
@@ -32,12 +46,13 @@ export default function ToggleableItem({
@@ -49,12 +64,13 @@ export default function ToggleableItem({
diff --git a/src/shared/components/Settings/Tools/Devices/index.jsx b/src/shared/components/Settings/Tools/Devices/index.jsx index ff3ab7da46..d941f5bbb4 100644 --- a/src/shared/components/Settings/Tools/Devices/index.jsx +++ b/src/shared/components/Settings/Tools/Devices/index.jsx @@ -516,6 +516,7 @@ export default class Devices extends ConsentComponent { valueKey="name" labelKey="name" disabled={!canModifyTrait} + onKeyPress={e => e.key === 'Enter' && e.preventDefault()} /> { isSubmit && ( @@ -541,6 +542,7 @@ export default class Devices extends ConsentComponent { valueKey="name" labelKey="name" disabled={!canModifyTrait} + onKeyPress={e => e.key === 'Enter' && e.preventDefault()} />
@@ -564,6 +566,7 @@ export default class Devices extends ConsentComponent { isLoading={isModelsLoading} hasMore={hasMoreModels} disabled={!canModifyTrait} + onKeyPress={e => e.key === 'Enter' && e.preventDefault()} />
@@ -587,6 +590,7 @@ export default class Devices extends ConsentComponent { isLoading={isOsesLoading} onLoadMore={this.onLoadMoreOses} disabled={!canModifyTrait} + onKeyPress={e => e.key === 'Enter' && e.preventDefault()} />
@@ -651,6 +655,7 @@ export default class Devices extends ConsentComponent { valueKey="name" labelKey="name" disabled={!canModifyTrait} + onKeyPress={e => e.key === 'Enter' && e.preventDefault()} /> { isSubmit && ( @@ -672,6 +677,7 @@ export default class Devices extends ConsentComponent { valueKey="name" labelKey="name" disabled={!canModifyTrait} + onKeyPress={e => e.key === 'Enter' && e.preventDefault()} /> @@ -693,6 +699,7 @@ export default class Devices extends ConsentComponent { isLoading={isModelsLoading} hasMore={hasMoreModels} disabled={!canModifyTrait} + onKeyPress={e => e.key === 'Enter' && e.preventDefault()} />
@@ -712,6 +719,7 @@ export default class Devices extends ConsentComponent { isLoading={isOsesLoading} onLoadMore={this.onLoadMoreOses} disabled={!canModifyTrait} + onKeyPress={e => e.key === 'Enter' && e.preventDefault()} />
diff --git a/src/shared/components/Settings/Tools/ServiceProviders/index.jsx b/src/shared/components/Settings/Tools/ServiceProviders/index.jsx index ced86d9d34..84352a6129 100644 --- a/src/shared/components/Settings/Tools/ServiceProviders/index.jsx +++ b/src/shared/components/Settings/Tools/ServiceProviders/index.jsx @@ -161,6 +161,7 @@ export default class ServiceProviders extends ConsentComponent { } this.setState({ showConfirmation: false, + isEdit: false, indexNo: null, formInvalid: false, isSubmit: false, diff --git a/src/shared/components/Settings/Tools/Software/index.jsx b/src/shared/components/Settings/Tools/Software/index.jsx index a1bc02e312..1433ab74d3 100644 --- a/src/shared/components/Settings/Tools/Software/index.jsx +++ b/src/shared/components/Settings/Tools/Software/index.jsx @@ -147,6 +147,7 @@ export default class Software extends ConsentComponent { showConfirmation: false, indexNo: null, isSubmit: false, + isEdit: false, formInvalid: false, }); } @@ -380,7 +381,7 @@ export default class Software extends ConsentComponent { { isSubmit && ( - + ) } diff --git a/src/shared/components/Settings/Tools/Subscriptions/index.jsx b/src/shared/components/Settings/Tools/Subscriptions/index.jsx index b4691b4cd9..8cdd86eaad 100644 --- a/src/shared/components/Settings/Tools/Subscriptions/index.jsx +++ b/src/shared/components/Settings/Tools/Subscriptions/index.jsx @@ -153,6 +153,7 @@ export default class Subscription extends ConsentComponent { showConfirmation: false, indexNo: null, formInvalid: false, + isEdit: false, isSubmit: false, }); } @@ -328,7 +329,18 @@ export default class Subscription extends ConsentComponent {
* Required - + e.key === 'Enter' && e.preventDefault()} + required + /> { isSubmit && ( @@ -380,7 +392,18 @@ export default class Subscription extends ConsentComponent { * Required - + e.key === 'Enter' && e.preventDefault()} + required + /> { isSubmit && ( diff --git a/src/shared/components/challenge-listing/Filters/DatePicker.jsx b/src/shared/components/challenge-listing/Filters/DatePicker.jsx index deec2ef21e..724b3e163b 100644 --- a/src/shared/components/challenge-listing/Filters/DatePicker.jsx +++ b/src/shared/components/challenge-listing/Filters/DatePicker.jsx @@ -12,6 +12,7 @@ import './_fix_SingleDatePicker.css'; const propTypes = { autoFocus: PropTypes.bool, + showClearDate: PropTypes.bool, allowFutureYear: PropTypes.bool, ...omit({}, [ @@ -25,6 +26,7 @@ const propTypes = { const defaultProps = { autoFocus: false, allowFutureYear: false, + showClearDate: false, }; class DatePicker extends React.Component { @@ -53,7 +55,7 @@ class DatePicker extends React.Component { render() { const { focused, allowFutureYear } = this.state; const { - id, date, onDateChange, isOutsideRange, + id, date, onDateChange, isOutsideRange, showClearDate, } = this.props; const props = omit(this.props, [ @@ -75,6 +77,7 @@ class DatePicker extends React.Component { focused={focused} onDateChange={onDateChange} onFocusChange={this.onFocusChange} + showClearDate={showClearDate} renderMonthElement={({ month, onMonthSelect, onYearSelect }) => (