Skip to content

Commit fb7a9dc

Browse files
Merge pull request #1181 from nauhil/new-develop
Profile Settings - Organizations, Hobbies and User Consent
2 parents dcf579c + fa5bb09 commit fb7a9dc

File tree

39 files changed

+2415
-99
lines changed

39 files changed

+2415
-99
lines changed
Lines changed: 7 additions & 0 deletions
Loading
Lines changed: 8 additions & 0 deletions
Loading

src/shared/components/Settings/Profile/BasicInfo/Track/index.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export default function Track({
3737
</div>
3838
</div>
3939
</div>
40-
<div className="onoffswitch" styleName="onoffswitch-no-padding-right">
40+
<div styleName="onoffswitch-no-padding-right">
4141
<input
4242
type="checkbox"
4343
name="eprf-onoffswitch"

src/shared/components/Settings/Profile/BasicInfo/Track/styles.scss

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
@import "~styles/mixins";
22

3+
@mixin switch-transition {
4+
transition: all 0.15s ease-in-out;
5+
}
6+
7+
$switch-active-color: $tc-dark-blue-110;
8+
$switch-inactive-color: $tc-gray-20;
9+
$switch-width: 34px;
10+
$switch-height: 20px;
11+
312
.track-container {
413
display: flex;
514
flex-direction: row;
@@ -57,4 +66,17 @@
5766
.onoffswitch-no-padding-right {
5867
margin-right: 10px;
5968
margin-left: 30px;
69+
70+
@include switch-transition;
71+
72+
align-self: center;
73+
background-color: $switch-inactive-color;
74+
border-radius: $switch-height;
75+
box-sizing: border-box;
76+
height: $switch-height;
77+
width: $switch-width;
78+
position: relative;
79+
-webkit-user-select: none;
80+
-moz-user-select: none;
81+
-ms-user-select: none;
6082
}

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

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import moment from 'moment';
1212

1313
import { PrimaryButton } from 'topcoder-react-ui-kit';
1414
import { getAllCountryObjects } from 'utils/countries';
15-
15+
import UserConsentModal from 'components/Settings/UserConsentModal';
1616
import Select from 'components/Select';
1717
import ImageInput from '../ImageInput';
1818
import Track from './Track';
@@ -34,11 +34,14 @@ export default class BasicInfo extends React.Component {
3434
this.onUpdateInput = this.onUpdateInput.bind(this);
3535
this.onSaveBasicInfo = this.onSaveBasicInfo.bind(this);
3636
this.onChange = this.onChange.bind(this);
37+
this.onShowUserConsent = this.onShowUserConsent.bind(this);
3738

3839
this.state = {
40+
showUserConsent: false,
3941
savingBasicInfo: false,
4042
inputChanged: false,
4143
basicInfoTrait: this.loadBasicInfoTraits(props.userTraits),
44+
personalizationTrait: this.loadPersonalizationTrait(props.userTraits),
4245
newBasicInfo: {
4346
handle: '',
4447
firstName: '',
@@ -81,21 +84,35 @@ export default class BasicInfo extends React.Component {
8184
componentWillReceiveProps(nextProps) {
8285
const basicInfoTrait = this.loadBasicInfoTraits(nextProps.userTraits);
8386
const basicInfo = basicInfoTrait.traits ? basicInfoTrait.traits.data[0] : {};
87+
const personalizationTrait = this.loadPersonalizationTrait(nextProps.userTraits);
8488
this.processBasicInfo(basicInfo);
8589
this.setState({
8690
basicInfoTrait,
91+
personalizationTrait,
8792
savingBasicInfo: false,
8893
inputChanged: false,
8994
});
9095
}
9196

97+
/**
98+
* Show User Consent Modal
99+
* @param {*} e event
100+
*/
101+
onShowUserConsent(e) {
102+
e.preventDefault();
103+
this.setState({ showUserConsent: true });
104+
}
105+
92106
/**
93107
* Save Basic Info
108+
* @param e form submit event
109+
* @param answer user consent answer value
94110
*/
95-
onSaveBasicInfo(e) {
111+
onSaveBasicInfo(e, answer) {
96112
e.preventDefault();
97113
this.setState({
98114
savingBasicInfo: true,
115+
showUserConsent: false,
99116
});
100117

101118
const {
@@ -104,7 +121,7 @@ export default class BasicInfo extends React.Component {
104121
addUserTrait,
105122
updateUserTrait,
106123
} = this.props;
107-
const { newBasicInfo, basicInfoTrait } = this.state;
124+
const { newBasicInfo, basicInfoTrait, personalizationTrait } = this.state;
108125
newBasicInfo.birthDate = new Date(newBasicInfo.birthDate).toISOString();
109126

110127
if (basicInfoTrait.traits && basicInfoTrait.traits.data.length > 0) {
@@ -117,6 +134,18 @@ export default class BasicInfo extends React.Component {
117134
data.push(newBasicInfo);
118135
addUserTrait(handle, 'basic_info', data, tokenV3);
119136
}
137+
138+
// save personalization
139+
if (_.isEmpty(personalizationTrait)) {
140+
const personalizationData = { userConsent: answer };
141+
addUserTrait(handle, 'personalization', [personalizationData], tokenV3);
142+
} else {
143+
const trait = personalizationTrait.traits.data[0];
144+
if (trait.userConsent !== answer) {
145+
const personalizationData = { userConsent: answer };
146+
updateUserTrait(handle, 'personalization', [personalizationData], tokenV3);
147+
}
148+
}
120149
}
121150

122151
onUpdateSelect(option) {
@@ -182,6 +211,16 @@ export default class BasicInfo extends React.Component {
182211
return _.assign({}, basicInfo);
183212
}
184213

214+
/**
215+
* Get personalization trait
216+
* @param userTraits the all user traits
217+
*/
218+
loadPersonalizationTrait = (userTraits) => {
219+
const trait = userTraits.filter(t => t.traitId === 'personalization');
220+
const personalization = trait.length === 0 ? {} : trait[0];
221+
return _.assign({}, personalization);
222+
}
223+
185224
/**
186225
* Process basic info state
187226
*/
@@ -322,10 +361,14 @@ export default class BasicInfo extends React.Component {
322361
const {
323362
savingBasicInfo,
324363
newBasicInfo,
364+
showUserConsent,
325365
} = this.state;
326366

327367
return (
328368
<div styleName="basic-info-container">
369+
{
370+
showUserConsent && (<UserConsentModal onSaveTrait={this.onSaveBasicInfo} />)
371+
}
329372
<div styleName="about-me-container">
330373
<div styleName="user-icon">
331374
<ImageInput
@@ -522,7 +565,7 @@ export default class BasicInfo extends React.Component {
522565
<div styleName="button-save">
523566
<PrimaryButton
524567
styleName="white-label"
525-
onClick={this.onSaveBasicInfo}
568+
onClick={this.onShowUserConsent}
526569
disabled={this.shouldDisableSave() || savingBasicInfo}
527570
>
528571
{

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

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,3 +252,44 @@
252252
margin: 0;
253253
}
254254
}
255+
256+
/*
257+
* React Select component styling
258+
*/
259+
.basic-info-container .form-container .row .field :global .Select,
260+
.basic-info-container .form-container .row .field :global .Select-value span,
261+
.basic-info-container .form-container .row .field :global .Select-menu-outer,
262+
.basic-info-container.form-container .row .field :global .Select-placeholder,
263+
.basic-info-container .form-container .row .field :global .Select-input input {
264+
color: $tc-gray-80;
265+
font-size: 15px;
266+
267+
@include xs-to-sm {
268+
margin-top: 5px;
269+
}
270+
}
271+
272+
.basic-info-container div[class="Select-control"] {
273+
height: 40px;
274+
275+
div[class="Select-input"] {
276+
height: 38px;
277+
}
278+
279+
div[class="Select-placeholder"] {
280+
height: 38px;
281+
line-height: 40px !important;
282+
283+
@include xs-to-sm {
284+
line-height: 27px !important;
285+
}
286+
}
287+
288+
div[class="Select-value"] {
289+
line-height: 40px !important;
290+
}
291+
}
292+
293+
.basic-info-container .form-container .row .field :global .Select-placeholder {
294+
color: $tc-gray-50;
295+
}

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

Lines changed: 62 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import _ from 'lodash';
88
import React from 'react';
99
import PT from 'prop-types';
10-
10+
import UserConsentModal from 'components/Settings/UserConsentModal';
1111
import Item from './Item';
1212
import data from './data';
1313

@@ -18,12 +18,18 @@ const SAVE_DELAY = 1000;
1818
class Community extends React.Component {
1919
constructor(props) {
2020
super(props);
21+
this.onShowUserConsent = this.onShowUserConsent.bind(this);
2122
this.state = {
2223
communityTrait: this.loadCommunityTrait(props.userTraits),
24+
showUserConsent: false,
25+
personalizationTrait: this.loadPersonalizationTrait(props.userTraits),
26+
newCommunity: null,
27+
communityChecked: false,
2328
isAdd: false,
2429
};
2530

2631
this.loadCommunityTrait = this.loadCommunityTrait.bind(this);
32+
this.loadPersonalizationTrait = this.loadPersonalizationTrait.bind(this);
2733
this.onChange = this.onChange.bind(this);
2834
}
2935

@@ -40,22 +46,40 @@ class Community extends React.Component {
4046
const trait = userTraits.filter(t => t.traitId === 'communities');
4147
this.setState({
4248
isAdd: trait.length === 0 ? true : false,
49+
newCommunity: null,
50+
communityChecked: false,
4351
});
4452
const communityTrait = this.loadCommunityTrait(nextProps.userTraits);
45-
this.setState({ communityTrait });
53+
const personalizationTrait = this.loadPersonalizationTrait(nextProps.userTraits);
54+
this.setState({ communityTrait, personalizationTrait });
55+
}
56+
57+
/**
58+
* Show User Consent Modal
59+
* @param e event
60+
* @param item the community object
61+
* @param checked the check value
62+
*/
63+
onShowUserConsent(e, item, checked) {
64+
e.preventDefault();
65+
this.setState({
66+
showUserConsent: true,
67+
newCommunity: item,
68+
communityChecked: checked,
69+
});
4670
}
4771

4872
/**
4973
* Add or Update CommunityTrait
5074
*/
51-
onProcessCommunities = _.debounce(() => {
75+
onProcessCommunities = _.debounce((answer) => {
5276
const {
5377
handle,
5478
tokenV3,
5579
updateUserTrait,
5680
addUserTrait,
5781
} = this.props;
58-
const { isAdd, communityTrait } = this.state;
82+
const { isAdd, communityTrait, personalizationTrait } = this.state;
5983
if (isAdd) {
6084
const newCommunities = [];
6185
newCommunities.push(communityTrait);
@@ -65,22 +89,43 @@ class Community extends React.Component {
6589
newCommunities.push(communityTrait);
6690
updateUserTrait(handle, 'communities', newCommunities, tokenV3);
6791
}
92+
// save personalization
93+
if (_.isEmpty(personalizationTrait)) {
94+
const personalizationData = { userConsent: answer };
95+
addUserTrait(handle, 'personalization', [personalizationData], tokenV3);
96+
} else {
97+
const trait = personalizationTrait.traits.data[0];
98+
if (trait.userConsent !== answer) {
99+
const personalizationData = { userConsent: answer };
100+
updateUserTrait(handle, 'personalization', [personalizationData], tokenV3);
101+
}
102+
}
68103
}, SAVE_DELAY);
69104

70105

71106
/**
72107
* Change toggle button check value
73-
* @param item community object
74-
* @param checked check value
108+
* @param e form submit event
109+
* @param answer user consent answer value
75110
*/
76-
onChange(item, checked) {
77-
const { communityTrait } = this.state;
78-
communityTrait[item.id] = checked;
111+
onChange(e, answer) {
112+
this.setState({ showUserConsent: false });
113+
const { communityTrait, newCommunity, communityChecked } = this.state;
114+
communityTrait[newCommunity.id] = communityChecked;
79115
this.setState({
80116
communityTrait,
81-
}, () => this.onProcessCommunities(item.programID));
117+
}, () => this.onProcessCommunities(answer));
82118
}
83119

120+
/**
121+
* Get personalization trait
122+
* @param userTraits the all user traits
123+
*/
124+
loadPersonalizationTrait = (userTraits) => {
125+
const trait = userTraits.filter(t => t.traitId === 'personalization');
126+
const personalization = trait.length === 0 ? {} : trait[0];
127+
return _.assign({}, personalization);
128+
}
84129

85130
/**
86131
* Get community trait
@@ -99,14 +144,19 @@ class Community extends React.Component {
99144

100145
render() {
101146
const { settingsUI } = this.props;
102-
const { communityTrait } = this.state;
147+
const { communityTrait, showUserConsent } = this.state;
103148
const tabs = settingsUI.TABS.PROFILE;
104149
const currentTab = settingsUI.currentProfileTab;
105150
const containerStyle = currentTab === tabs.COMMUNITY ? '' : 'hide';
106151
const communityItems = communityTrait;
107152

108153
return (
109154
<div styleName={containerStyle}>
155+
{
156+
showUserConsent && (
157+
<UserConsentModal onSaveTrait={this.onChange} />
158+
)
159+
}
110160
<div styleName="community-container">
111161
<h1>
112162
Community
@@ -125,7 +175,7 @@ class Community extends React.Component {
125175
title={item.name}
126176
programID={item.programID}
127177
description={item.description}
128-
onToggle={event => this.onChange(item, event.target.checked)}
178+
onToggle={event => this.onShowUserConsent(event, item, event.target.checked)}
129179
/>
130180
);
131181
})

0 commit comments

Comments
 (0)