diff --git a/__tests__/shared/components/__snapshots__/TopcoderFooter.jsx.snap b/__tests__/shared/components/__snapshots__/TopcoderFooter.jsx.snap index dafcdedca0..314898ca2b 100644 --- a/__tests__/shared/components/__snapshots__/TopcoderFooter.jsx.snap +++ b/__tests__/shared/components/__snapshots__/TopcoderFooter.jsx.snap @@ -601,7 +601,7 @@ exports[`Matches shallow shapshot 1`] = ` - © 2021 Topcoder + © 2022 Topcoder Topcoder © - 2021 + 2022

`; diff --git a/package.json b/package.json index 8db5c0da88..7232ef935b 100644 --- a/package.json +++ b/package.json @@ -153,7 +153,7 @@ "supertest": "^3.1.0", "tc-core-library-js": "github:appirio-tech/tc-core-library-js#v2.6.3", "tc-ui": "^1.0.12", - "topcoder-react-lib": "1.2.4", + "topcoder-react-lib": "1000.28.11", "topcoder-react-ui-kit": "2.0.1", "topcoder-react-utils": "0.7.8", "turndown": "^4.0.2", diff --git a/src/shared/components/Gigs/GigApply/index.jsx b/src/shared/components/Gigs/GigApply/index.jsx index bcd84a6782..90cc61c047 100644 --- a/src/shared/components/Gigs/GigApply/index.jsx +++ b/src/shared/components/Gigs/GigApply/index.jsx @@ -326,7 +326,7 @@ export default function GigApply(props) {
Login
-

Not a member? Register here.

+

Not a member? Register here.

diff --git a/src/shared/components/Gigs/LoginModal/index.jsx b/src/shared/components/Gigs/LoginModal/index.jsx index 47c1124533..4962fa0865 100644 --- a/src/shared/components/Gigs/LoginModal/index.jsx +++ b/src/shared/components/Gigs/LoginModal/index.jsx @@ -56,7 +56,7 @@ function LoginModal({ retUrl, onCancel, utmSource }) {
{ - window.location = `${config.URL.AUTH}/member/registration?retUrl=${encodeURIComponent(retUrl)}&mode=signUp&utm_source=${utmSource}`; + window.location = `${config.URL.AUTH}/member/registration?retUrl=${encodeURIComponent(retUrl)}&mode=signUp&utmSource=${utmSource}®Source=gigs`; }} theme={{ button: buttonThemes.tc['primary-green-md'], diff --git a/src/shared/components/Gigs/ReferralModal/index.jsx b/src/shared/components/Gigs/ReferralModal/index.jsx index f4af505232..47a2aa6ecf 100644 --- a/src/shared/components/Gigs/ReferralModal/index.jsx +++ b/src/shared/components/Gigs/ReferralModal/index.jsx @@ -110,7 +110,7 @@ function ReferralModal({ > LOGIN - REGISTER + REGISTER

Find out how the referral program works here.

diff --git a/src/shared/components/Settings/Profile/BasicInfo/index.jsx b/src/shared/components/Settings/Profile/BasicInfo/index.jsx index b1857da586..1bec3d5d08 100644 --- a/src/shared/components/Settings/Profile/BasicInfo/index.jsx +++ b/src/shared/components/Settings/Profile/BasicInfo/index.jsx @@ -38,41 +38,35 @@ export default class BasicInfo extends ConsentComponent { this.onSaveBasicInfo = this.onSaveBasicInfo.bind(this); this.onChange = this.onChange.bind(this); this.onCheckFormValue = this.onCheckFormValue.bind(this); + this.processBasicInfo = this.processBasicInfo.bind(this); const { userTraits } = props; this.state = { inputChanged: false, formInvalid: false, basicInfoTrait: this.loadBasicInfoTraits(userTraits), + profile: {}, personalizationTrait: this.loadPersonalizationTrait(userTraits), - newBasicInfo: { - handle: '', + newProfileInfo: { firstName: null, lastName: null, - gender: '', - ethnicBackground: null, - shortBio: '', - tshirtSize: '', - country: '', - primaryInterestInTopcoder: '', - currentLocation: '', - birthDate: null, - userId: '', + tracks: [], + status: null, + addresses: [], description: '', - otherLangName: null, - status: '', - email: '', - addresses: [{ - streetAddr1: '', - streetAddr2: '', - city: '', - stateCode: '', - zip: '', - type: 'Home', - }], + email: null, homeCountryCode: null, competitionCountryCode: null, - tracks: [], + photoURL: null, + }, + newBasicInfo: { + gender: null, + shortBio: '', + tshirtSize: null, + country: null, + primaryInterestInTopcoder: null, + currentLocation: null, + birthDate: null, }, }; } @@ -80,26 +74,34 @@ export default class BasicInfo extends ConsentComponent { componentDidMount() { const { basicInfoTrait } = this.state; const basicInfo = basicInfoTrait.traits ? basicInfoTrait.traits.data[0] : {}; - this.processBasicInfo(basicInfo); + this.processBasicInfo(basicInfo, this.props.profile); + this.setState({ profile: this.props.profile }); } componentWillReceiveProps(nextProps) { const basicInfoTrait = this.loadBasicInfoTraits(nextProps.userTraits); + const basicInfo = basicInfoTrait.traits ? basicInfoTrait.traits.data[0] : {}; + const previousBasicInfoTrait = this.loadBasicInfoTraits(this.props.userTraits); + const personalizationTrait = this.loadPersonalizationTrait(nextProps.userTraits); - if (basicInfoTrait.updatedAt !== this.loadBasicInfoTraits(this.props.userTraits).updatedAt) { - this.processBasicInfo(basicInfo); + if (!_.isEqual(basicInfoTrait, previousBasicInfoTrait)) { + this.processBasicInfo(basicInfo, nextProps.profile); this.setState({ basicInfoTrait, personalizationTrait, inputChanged: false, }); } + if (!_.isEqual(this.state.profile, nextProps.profile)) { + this.processBasicInfo(basicInfo, nextProps.profile); + this.setState({ profile: nextProps.profile }); + } if (nextProps.lookupData) { const { countries } = nextProps.lookupData; - const { newBasicInfo } = this.state; + const { newBasicInfo, newProfileInfo } = this.state; if (!newBasicInfo.country) { - const code = newBasicInfo.homeCountryCode || newBasicInfo.competitionCountryCode; + const code = newProfileInfo.homeCountryCode || newProfileInfo.competitionCountryCode; const { country } = countries.find(c => c.countryCode === code) || {}; newBasicInfo.country = country; this.setState({ newBasicInfo }); @@ -107,14 +109,14 @@ export default class BasicInfo extends ConsentComponent { } } - onCheckFormValue(newBasicInfo) { + onCheckFormValue(newBasicInfo, newProfileInfo) { let invalid = false; - if (!_.trim(newBasicInfo.firstName).length) { + if (!_.trim(newProfileInfo.firstName).length) { invalid = true; } - if (!_.trim(newBasicInfo.lastName).length) { + if (!_.trim(newProfileInfo.lastName).length) { invalid = true; } @@ -142,15 +144,10 @@ export default class BasicInfo extends ConsentComponent { Authorization: `Bearer ${tokenV3}`, }, }) - .then((result) => { - if (result.ok) { - return result.json(); - } - throw new Error(result.statusText); - }) - .then((content) => { - if (content.length > 0) { - const trait = content[0]; + .then(result => result.json()) + .then((dataResponse) => { + if (dataResponse.length > 0) { + const trait = dataResponse[0]; if (trait.createdAt) { isExists = true; } @@ -167,8 +164,8 @@ export default class BasicInfo extends ConsentComponent { onHandleSaveBasicInfo(e) { e.preventDefault(); this.setState({ isSaving: true, inputChange: true }); - const { newBasicInfo } = this.state; - if (this.onCheckFormValue(newBasicInfo)) { + const { newBasicInfo, newProfileInfo } = this.state; + if (this.onCheckFormValue(newBasicInfo, newProfileInfo)) { this.setState({ isSaving: false }); return; } @@ -180,12 +177,15 @@ export default class BasicInfo extends ConsentComponent { * @param answer user consent answer value */ async onSaveBasicInfo(answer) { - const { newBasicInfo, basicInfoTrait, personalizationTrait } = this.state; + const { + newBasicInfo, newProfileInfo, basicInfoTrait, personalizationTrait, + } = this.state; const { handle, tokenV3, addUserTrait, updateUserTrait, + updateProfileV5, } = this.props; try { const parsedDate = moment(newBasicInfo.birthDate).utc(); @@ -206,12 +206,15 @@ export default class BasicInfo extends ConsentComponent { newBasicInfo.tshirtSize = null; } - _.forEach(newBasicInfo.addresses[0], (value, key) => { - newBasicInfo.addresses[0][key] = _.trim(value); + _.forEach(newProfileInfo.addresses[0], (value, key) => { + newProfileInfo.addresses[0][key] = _.trim(value); }); - _.forEach(['currentLocation', 'primaryInterestInTopcoder', 'description'], (key) => { + _.forEach(['currentLocation', 'primaryInterestInTopcoder'], (key) => { newBasicInfo[key] = _.trim(newBasicInfo[key]); }); + _.forEach(['description'], (key) => { + newProfileInfo[key] = _.trim(newProfileInfo[key]); + }); // This is a hack to check if the user has an existing basic_info trait object const exists = await this.onCheckUserTrait('basic_info'); if (exists) { @@ -237,6 +240,12 @@ export default class BasicInfo extends ConsentComponent { } } + const updateProfileData = { + ...newProfileInfo, + }; + + await updateProfileV5(updateProfileData, handle, tokenV3); + this.setState({ isSaving: false }); } @@ -250,25 +259,40 @@ export default class BasicInfo extends ConsentComponent { } onUpdateInput(e) { - const { newBasicInfo: oldBasicInfo } = this.state; + const { newBasicInfo: oldBasicInfo, newProfileInfo: oldProfileInfo } = this.state; const newBasicInfo = { ...oldBasicInfo }; - switch (e.target.name) { + const newProfileInfo = { ...oldProfileInfo }; + const { name, value } = e.target; + switch (name) { case 'stateCode': case 'zip': case 'city': case 'streetAddr1': case 'streetAddr2': - newBasicInfo.addresses[0][e.target.name] = e.target.value; + if (newProfileInfo.addresses.length === 0) { + newProfileInfo.addresses.push({ + stateCode: '', + zip: '', + city: '', + streetAddr1: '', + streetAddr2: '', + }); + } + newProfileInfo.addresses[0][name] = value; break; case 'firstName': case 'lastName': - newBasicInfo[e.target.name] = e.target.value.replace(/[^a-zA-Z0-9,. -]/g, ''); + newProfileInfo[name] = value.replace(/[^a-zA-Z0-9,. -]/g, ''); break; default: - newBasicInfo[e.target.name] = e.target.value; + if (name in newProfileInfo) { + newProfileInfo[name] = value; + } else if (name in newBasicInfo) { + newBasicInfo[name] = value; + } } - this.setState({ newBasicInfo, inputChanged: true }); + this.setState({ newBasicInfo, newProfileInfo, inputChanged: true }); } onUpdateDate(date) { @@ -297,15 +321,15 @@ export default class BasicInfo extends ConsentComponent { * @param checked check value */ onChange(id, checked) { - const { newBasicInfo } = this.state; + const { newProfileInfo } = this.state; if (checked) { - newBasicInfo.tracks.push(id.toUpperCase()); + newProfileInfo.tracks.push(id.toUpperCase()); } else { - _.remove(newBasicInfo.tracks, track => ( + _.remove(newProfileInfo.tracks, track => ( track.toUpperCase() === id.toUpperCase() )); } - this.setState({ newBasicInfo, inputChanged: true }); + this.setState({ newProfileInfo, inputChanged: true }); } /** @@ -331,86 +355,23 @@ export default class BasicInfo extends ConsentComponent { /** * Process basic info state */ - processBasicInfo = (value) => { - const { newBasicInfo } = this.state; - const { handle, profile } = this.props; - newBasicInfo.handle = handle; - if (_.has(value, 'addresses') && value.addresses.length > 0) { - newBasicInfo.addresses[0].city = value.addresses[0].city ? value.addresses[0].city : ''; - newBasicInfo.addresses[0].stateCode = value.addresses[0].stateCode ? value.addresses[0].stateCode : ''; - newBasicInfo.addresses[0].streetAddr1 = value.addresses[0].streetAddr1 ? value.addresses[0].streetAddr1 : ''; - newBasicInfo.addresses[0].streetAddr2 = value.addresses[0].streetAddr2 ? value.addresses[0].streetAddr2 : ''; - newBasicInfo.addresses[0].zip = value.addresses[0].zip ? value.addresses[0].zip : ''; - if (newBasicInfo.addresses[0].streetAddr1 === '' && _.has(value, 'address')) { - newBasicInfo.addresses[0].streetAddr1 = value.address; - } - } else { - newBasicInfo.addresses[0].city = _.has(value, 'city') ? value.city : ''; - newBasicInfo.addresses[0].stateCode = _.has(value, 'state') ? value.state : ''; - newBasicInfo.addresses[0].streetAddr1 = _.has(value, 'address') ? value.address : ''; - newBasicInfo.addresses[0].zip = _.has(value, 'zipCode') ? value.zipCode : ''; - } - if (_.has(value, 'birthDate')) { - const newDate = moment(value.birthDate).utc(); - if (newDate.isValid()) { - newBasicInfo.birthDate = newDate; - } - } - if (_.has(value, 'competitionCountryCode')) { - newBasicInfo.competitionCountryCode = value.competitionCountryCode; - } else { - newBasicInfo.competitionCountryCode = profile.competitionCountryCode; - } - if (_.has(value, 'country')) { - newBasicInfo.country = value.country; - } - if (_.has(value, 'currentLocation')) { - newBasicInfo.currentLocation = value.currentLocation; - } - if (_.has(value, 'description')) { - if (_.trim(value.description).length) { - newBasicInfo.description = value.description; - } - } else { - newBasicInfo.description = profile.description ? profile.description : ''; - } - if (_.has(value, 'email')) { - newBasicInfo.email = value.email; - } else { - newBasicInfo.email = profile.email; - } - if (_.has(value, 'firstName')) { - newBasicInfo.firstName = value.firstName; - } else { - newBasicInfo.firstName = ''; - } - if (_.has(value, 'gender')) { - newBasicInfo.gender = value.gender; - } else { - newBasicInfo.gender = profile.gender; - } - if (_.has(value, 'homeCountryCode')) { - newBasicInfo.homeCountryCode = value.homeCountryCode; - } else { - newBasicInfo.homeCountryCode = profile.homeCountryCode; - } - if (_.has(value, 'lastName')) { - newBasicInfo.lastName = value.lastName; - } else { - newBasicInfo.lastName = ''; - } - if (_.has(value, 'primaryInterestInTopcoder')) { - newBasicInfo.primaryInterestInTopcoder = value.primaryInterestInTopcoder; - } - if (_.has(value, 'status')) { - newBasicInfo.status = value.status; - } else { - newBasicInfo.status = profile.status; - } - if (_.has(value, 'tracks')) { - newBasicInfo.tracks = value.tracks ? value.tracks : []; - } else { - newBasicInfo.tracks = profile.tracks ? profile.tracks : []; + processBasicInfo = (value, profile) => { + const { newBasicInfo, newProfileInfo: profileInfo } = this.state; + if (_.has(profile, 'handle')) { + const newProfileInfo = Object.keys(profileInfo).reduce((acc, key) => { + if (_.has(profileInfo, key)) { + acc[key] = profile[key] || profileInfo[key]; + } + return acc; + }, {}); + const basicInfo = Object.keys(newBasicInfo).reduce((acc, key) => { + if (_.has(value, key)) { + acc[key] = value[key]; + newBasicInfo[key] = value[key]; + } + return acc; + }, {}); + this.setState({ newBasicInfo: basicInfo, newProfileInfo }); } if (_.has(value, 'tshirtSize')) { newBasicInfo.tshirtSize = value.tshirtSize; @@ -428,21 +389,24 @@ export default class BasicInfo extends ConsentComponent { * @returns {boolean} */ shouldDisableSave() { - const { newBasicInfo, inputChanged } = this.state; + const { newBasicInfo, inputChanged, newProfileInfo } = this.state; + + const { addresses } = newProfileInfo; - const invalid = !_.trim(newBasicInfo.firstName).length - || !_.trim(newBasicInfo.lastName).length + const invalid = !_.trim(newProfileInfo.firstName).length + || !_.trim(newProfileInfo.lastName).length || !_.trim(newBasicInfo.gender).length || !_.trim(newBasicInfo.tshirtSize).length || !_.trim(newBasicInfo.country).length || !_.trim(newBasicInfo.primaryInterestInTopcoder).length || !_.trim(newBasicInfo.currentLocation).length || !_.trim(newBasicInfo.birthDate).length - || (newBasicInfo.addresses.length > 0 && !_.trim(newBasicInfo.addresses[0].city).length) - || (newBasicInfo.addresses.length > 0 && !_.trim(newBasicInfo.addresses[0].stateCode).length) - || (newBasicInfo.addresses.length > 0 && !_.trim(newBasicInfo.addresses[0].zip).length) - || (newBasicInfo.addresses.length > 0 - && !_.trim(newBasicInfo.addresses[0].streetAddr1).length); + || (addresses.length > 0 && !_.trim(addresses[0].city).length) + || (addresses.length > 0 && !_.trim(addresses[0].stateCode).length) + || (addresses.length > 0 && !_.trim(addresses[0].zip).length) + || (addresses.length > 0 + && !_.trim(addresses[0].streetAddr1).length); + // Invalid value, can not save if (invalid) { return true; @@ -455,6 +419,7 @@ export default class BasicInfo extends ConsentComponent { render() { const { newBasicInfo, + newProfileInfo, inputChanged, } = this.state; @@ -495,8 +460,8 @@ export default class BasicInfo extends ConsentComponent {
* Required - - + +
@@ -508,8 +473,8 @@ export default class BasicInfo extends ConsentComponent {
* Required - - + +
@@ -541,7 +506,7 @@ export default class BasicInfo extends ConsentComponent {
- 0 ? newBasicInfo.addresses[0].streetAddr1 : ''}`} maxLength="64" required /> + 0 && newProfileInfo.addresses[0].streetAddr1 != null ? newProfileInfo.addresses[0].streetAddr1 : ''}`} maxLength="64" required />
@@ -552,7 +517,7 @@ export default class BasicInfo extends ConsentComponent {
- 0 ? newBasicInfo.addresses[0].streetAddr2 : ''}`} maxLength="64" /> + 0 && newProfileInfo.addresses[0].streetAddr2 != null ? newProfileInfo.addresses[0].streetAddr2 : ''}`} maxLength="64" />
@@ -563,7 +528,7 @@ export default class BasicInfo extends ConsentComponent {
- 0 ? newBasicInfo.addresses[0].city : ''}`} maxLength="64" required /> + 0 && newProfileInfo.addresses[0].city != null ? newProfileInfo.addresses[0].city : ''}`} maxLength="64" required />
@@ -574,7 +539,7 @@ export default class BasicInfo extends ConsentComponent {
- 0 ? newBasicInfo.addresses[0].stateCode : ''}`} maxLength="64" required /> + 0 && newProfileInfo.addresses[0].stateCode != null ? newProfileInfo.addresses[0].stateCode : ''}`} maxLength="64" required />
@@ -585,7 +550,7 @@ export default class BasicInfo extends ConsentComponent {
- 0 ? newBasicInfo.addresses[0].zip : ''}`} maxLength="64" required /> + 0 && newProfileInfo.addresses[0].zip != null ? newProfileInfo.addresses[0].zip : ''}`} maxLength="64" required />
@@ -694,10 +659,10 @@ export default class BasicInfo extends ConsentComponent {
- {newBasicInfo.description.length}/240 + {newProfileInfo.description.length}/240
-