From ee6b712d45138e752b855ae0ca97fbfebdbadeab Mon Sep 17 00:00:00 2001 From: Kiril Kartunov Date: Fri, 18 Nov 2022 19:12:50 +0200 Subject: [PATCH 01/10] fixed UAT --- .../Settings/__snapshots__/index.jsx.snap | 8 +- config/default.js | 1 + src/shared/app.jsx | 8 +- .../Gamification/SkillsNagModal/index.jsx | 163 ++++++++++++++ .../Gamification/SkillsNagModal/styles.scss | 113 ++++++++++ .../Gamification/YouGotSkillsModal/index.jsx | 148 +++++++++++++ .../YouGotSkillsModal/styles.scss | 113 ++++++++++ .../WorkSkills/Languages/index.jsx | 6 +- .../WorkSkills/Skills/styles.scss | 2 +- .../ExperienceAndSkills/WorkSkills/index.jsx | 8 +- .../Settings/ExperienceAndSkills/index.jsx | 10 +- src/shared/components/Settings/constants.js | 2 +- src/shared/containers/Gamification/index.jsx | 209 ++++++++++++++++++ 13 files changed, 772 insertions(+), 19 deletions(-) create mode 100644 src/shared/components/Gamification/SkillsNagModal/index.jsx create mode 100644 src/shared/components/Gamification/SkillsNagModal/styles.scss create mode 100644 src/shared/components/Gamification/YouGotSkillsModal/index.jsx create mode 100644 src/shared/components/Gamification/YouGotSkillsModal/styles.scss create mode 100644 src/shared/containers/Gamification/index.jsx diff --git a/__tests__/shared/components/Settings/__snapshots__/index.jsx.snap b/__tests__/shared/components/Settings/__snapshots__/index.jsx.snap index 73f0c5c1d3..ea529b623b 100644 --- a/__tests__/shared/components/Settings/__snapshots__/index.jsx.snap +++ b/__tests__/shared/components/Settings/__snapshots__/index.jsx.snap @@ -30,7 +30,7 @@ exports[`renders account setting page correctly 1`] = ` }, Object { "link": "skills", - "title": "Experience & Skills", + "title": "Skills & Experience", }, Object { "link": "tracks", @@ -787,7 +787,7 @@ exports[`renders preferences setting page correctly 1`] = ` }, Object { "link": "skills", - "title": "Experience & Skills", + "title": "Skills & Experience", }, Object { "link": "tracks", @@ -1541,7 +1541,7 @@ exports[`renders profile setting page correctly 1`] = ` }, Object { "link": "skills", - "title": "Experience & Skills", + "title": "Skills & Experience", }, Object { "link": "tracks", @@ -2301,7 +2301,7 @@ exports[`renders tools setting page correctly 1`] = ` }, Object { "link": "skills", - "title": "Experience & Skills", + "title": "Skills & Experience", }, Object { "link": "tracks", diff --git a/config/default.js b/config/default.js index 2a06bb3054..dd82e659e7 100644 --- a/config/default.js +++ b/config/default.js @@ -461,6 +461,7 @@ module.exports = { GAMIFICATION: { ORG_ID: '6052dd9b-ea80-494b-b258-edd1331e27a3', ENABLE_BADGE_UI: true, + ENABLE_SKILLS_REMIND_MODAL: true, }, PLATFORMUI_SITE_URL: 'https://platform-ui.topcoder-dev.com', DICE_VERIFY_URL: 'https://accounts-auth0.topcoder-dev.com', diff --git a/src/shared/app.jsx b/src/shared/app.jsx index 4199a32cf7..9f98dad665 100644 --- a/src/shared/app.jsx +++ b/src/shared/app.jsx @@ -14,6 +14,7 @@ import ErrorIcons from 'containers/ErrorIcons'; import { DevTools, isomorphy, config } from 'topcoder-react-utils'; import ExtendedReduxToastr from 'containers/Toastr'; +import Gamification from 'containers/Gamification'; import 'react-redux-toastr/lib/css/react-redux-toastr.min.css'; @@ -51,7 +52,12 @@ export default function App() { progressBar={false} showCloseButton /> - { isomorphy.isDevBuild() ? : undefined } + {isomorphy.isDevBuild() ? : undefined} + { + config.GAMIFICATION.ENABLE_SKILLS_REMIND_MODAL + && isomorphy.isClientSide() + ? : undefined + } ); } diff --git a/src/shared/components/Gamification/SkillsNagModal/index.jsx b/src/shared/components/Gamification/SkillsNagModal/index.jsx new file mode 100644 index 0000000000..598f96d32c --- /dev/null +++ b/src/shared/components/Gamification/SkillsNagModal/index.jsx @@ -0,0 +1,163 @@ +import React from 'react'; +import PT from 'prop-types'; +import { Modal } from 'topcoder-react-ui-kit'; +import { keys } from 'lodash'; + +import IconClose from 'assets/images/icon-close-green.svg'; +import style from './styles.scss'; + +const skillCountStatement = (count) => { + let statement = ''; + switch (count) { + case 0: + statement = 'don’t have any skills'; + break; + case 1: + statement = 'only have 1 skill'; + break; + default: + statement = `only have ${count} skills`; + } + return statement; +}; + +const SkillsNagModal = ({ + handle, + skills, + onCancel, + onCTA, + MIN_SKILLS_TO_REMIND, +}) => ( + +
+ +
+
+ Profile Skills Reminder +
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + {/* eslint-disable-next-line max-len */} + Hey {handle}, we have noticed that you {skillCountStatement(keys(skills).length)} added to your profile. To be able to match you with the best opportunities at Topcoder, please add at least {MIN_SKILLS_TO_REMIND} skills to your profile as soon as you can. + +
+ +
+ +
+ +
+
+); + +SkillsNagModal.propTypes = { + MIN_SKILLS_TO_REMIND: PT.number.isRequired, + handle: PT.string.isRequired, + skills: PT.shape().isRequired, + onCancel: PT.func.isRequired, + onCTA: PT.func.isRequired, +}; + +export default SkillsNagModal; diff --git a/src/shared/components/Gamification/SkillsNagModal/styles.scss b/src/shared/components/Gamification/SkillsNagModal/styles.scss new file mode 100644 index 0000000000..127e73c9b6 --- /dev/null +++ b/src/shared/components/Gamification/SkillsNagModal/styles.scss @@ -0,0 +1,113 @@ +@import "~styles/mixins"; +@import "~components/Contentful/brackets"; + +.nagModal { + display: flex; + flex-direction: column; + margin: 32px; + + @include xs-to-md { + flex-direction: column; + margin-top: 24px; + } + + .header { + display: flex; + align-items: flex-start; + justify-content: space-between; + border-bottom: 2px solid #e9e9e9; + + @include xs-to-md { + margin-top: 24px; + text-align: center; + } + + .title { + @include barlow-bold; + + color: $tco-black; + font-size: 22px; + font-weight: 600; + line-height: 26px; + margin-bottom: 12px; + text-transform: uppercase; + + @include xs-to-md { + text-align: center; + } + } + + .icon { + cursor: pointer; + } + } + + .description { + @include roboto-regular; + + font-weight: 400; + color: $tco-black; + font-size: 16px; + line-height: 24px; + margin-top: 24px; + + strong { + font-weight: 700; + } + + .badgeWrap { + display: flex; + justify-content: center; + margin-bottom: 12px; + } + } +} + +.container { + box-shadow: 0 1px 5px rgba(0, 0, 0, 0.2); + border-radius: 8px; + min-width: 600px; + + @include xs-to-sm { + width: 90%; + min-width: unset; + } +} + +.overlay { + background-color: #0c0c0c; + opacity: 0.85; +} + +.actionButtons { + display: flex; + align-items: center; + justify-content: flex-end; + margin-top: 32px; + padding-top: 24px; + border-top: 2px solid #e9e9e9; + + .primaryBtn { + background-color: #137d60; + border-radius: 24px; + color: #fff; + font-size: 13px; + font-weight: bolder; + text-decoration: none; + text-transform: uppercase; + line-height: 32px; + padding: 0 20px; + border: none; + outline: none; + display: flex; + + &:hover { + box-shadow: 0 1px 5px 0 rgba(0, 0, 0, 0.2); + background-color: #0ab88a; + } + + @include xs-to-sm { + margin-bottom: 20px; + } + } +} diff --git a/src/shared/components/Gamification/YouGotSkillsModal/index.jsx b/src/shared/components/Gamification/YouGotSkillsModal/index.jsx new file mode 100644 index 0000000000..370d414e0f --- /dev/null +++ b/src/shared/components/Gamification/YouGotSkillsModal/index.jsx @@ -0,0 +1,148 @@ +import React from 'react'; +import PT from 'prop-types'; +import { Modal } from 'topcoder-react-ui-kit'; + +import IconClose from 'assets/images/icon-close-green.svg'; +import style from './styles.scss'; + +const YouGotSkillsModal = ({ + MIN_SKILLS_TO_REMIND, + onCancel, + onCTA, +}) => ( + +
+ +
+
+ YOU’VE GOT SKILLS! +
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + {/* eslint-disable-next-line max-len */} + By having {MIN_SKILLS_TO_REMIND} or more skills associated with your profile, not only will you have a more curated experience here at Topcoder, but you will also be presented with more opportunities that align with your strengths and interests. + +
+ +
+ +
+ +
+
+); + +YouGotSkillsModal.propTypes = { + MIN_SKILLS_TO_REMIND: PT.number.isRequired, + onCancel: PT.func.isRequired, + onCTA: PT.func.isRequired, +}; + +export default YouGotSkillsModal; diff --git a/src/shared/components/Gamification/YouGotSkillsModal/styles.scss b/src/shared/components/Gamification/YouGotSkillsModal/styles.scss new file mode 100644 index 0000000000..d5f1a97568 --- /dev/null +++ b/src/shared/components/Gamification/YouGotSkillsModal/styles.scss @@ -0,0 +1,113 @@ +@import "~styles/mixins"; +@import "~components/Contentful/brackets"; + +.gotSkillsModal { + display: flex; + flex-direction: column; + margin: 32px; + + @include xs-to-md { + flex-direction: column; + margin-top: 24px; + } + + .header { + display: flex; + align-items: flex-start; + justify-content: space-between; + border-bottom: 2px solid #e9e9e9; + + @include xs-to-md { + margin-top: 24px; + text-align: center; + } + + .title { + @include barlow-bold; + + color: $tco-black; + font-size: 20px; + font-weight: 700; + line-height: 26px; + margin-bottom: 12px; + text-transform: uppercase; + + @include xs-to-md { + text-align: center; + } + } + + .icon { + cursor: pointer; + } + } + + .description { + @include roboto-regular; + + font-weight: 400; + color: $tco-black; + font-size: 16px; + line-height: 24px; + margin-top: 24px; + + strong { + font-weight: 700; + } + + .badgeWrap { + display: flex; + justify-content: center; + margin-bottom: 12px; + } + } +} + +.container { + box-shadow: 0 1px 5px rgba(0, 0, 0, 0.2); + border-radius: 8px; + min-width: 600px; + + @include xs-to-sm { + width: 90%; + min-width: unset; + } +} + +.overlay { + background-color: #0c0c0c; + opacity: 0.85; +} + +.actionButtons { + display: flex; + align-items: center; + justify-content: flex-end; + margin-top: 32px; + padding-top: 24px; + border-top: 2px solid #e9e9e9; + + .primaryBtn { + background-color: #137d60; + border-radius: 24px; + color: #fff; + font-size: 13px; + font-weight: bolder; + text-decoration: none; + text-transform: uppercase; + line-height: 32px; + padding: 0 20px; + border: none; + outline: none; + display: flex; + + &:hover { + box-shadow: 0 1px 5px 0 rgba(0, 0, 0, 0.2); + background-color: #0ab88a; + } + + @include xs-to-sm { + margin-bottom: 20px; + } + } +} diff --git a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Languages/index.jsx b/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Languages/index.jsx index 4721e00de2..b7d47b7bc6 100644 --- a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Languages/index.jsx +++ b/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Languages/index.jsx @@ -357,7 +357,7 @@ export default class Languages extends ConsentComponent {

- Language Skills + Spoken Languages

{ languageItems.length > 0 @@ -387,7 +387,7 @@ export default class Languages extends ConsentComponent { valueKey="name" clearable={false} /> - { isSubmit && formInvalid && ( + {isSubmit && formInvalid && ( )} - { isEdit && ( + {isEdit && (

Skills

+ -
); } diff --git a/src/shared/components/Settings/ExperienceAndSkills/index.jsx b/src/shared/components/Settings/ExperienceAndSkills/index.jsx index 6dfcd544ee..461ca66cff 100644 --- a/src/shared/components/Settings/ExperienceAndSkills/index.jsx +++ b/src/shared/components/Settings/ExperienceAndSkills/index.jsx @@ -94,14 +94,14 @@ export default class ExperienceAndSkills extends React.Component { return (
- +
{saveBtn}
@@ -111,7 +111,7 @@ export default class ExperienceAndSkills extends React.Component { ExperienceAndSkills.defaultProps = { isSaving: false, - setIsSaving: () => {}, + setIsSaving: () => { }, }; ExperienceAndSkills.propTypes = { diff --git a/src/shared/components/Settings/constants.js b/src/shared/components/Settings/constants.js index ef912b9e04..821aebf83a 100644 --- a/src/shared/components/Settings/constants.js +++ b/src/shared/components/Settings/constants.js @@ -7,7 +7,7 @@ export const SCREEN_SIZE = { export const SETTINGS_TABS = [ { title: 'Profile', link: TABS.PROFILE }, - { title: 'Experience & Skills', link: TABS.SKILLS }, + { title: 'Skills & Experience', link: TABS.SKILLS }, { title: 'Topcoder & You', link: TABS.TRACKS }, { title: 'Tools', link: TABS.TOOLS }, { title: 'Account', link: TABS.ACCOUNT }, diff --git a/src/shared/containers/Gamification/index.jsx b/src/shared/containers/Gamification/index.jsx new file mode 100644 index 0000000000..1046832dce --- /dev/null +++ b/src/shared/containers/Gamification/index.jsx @@ -0,0 +1,209 @@ +/** + * Gamification container + */ +/* global analytics */ +/* eslint-disable react/no-did-update-set-state */ +import React from 'react'; +import PT from 'prop-types'; +import { connect } from 'react-redux'; +import SkillsNagModal from 'components/Gamification/SkillsNagModal'; +import YouGotSkillsModal from 'components/Gamification/YouGotSkillsModal'; +import { keys } from 'lodash'; +import cookies from 'browser-cookies'; +import { actions } from 'topcoder-react-lib'; + +const REMIND_TIME_COOKIE_NAME = 'tc_skills_remind_time'; +const REMIND_TIME = 604800000; // a week +export const MIN_SKILLS_TO_REMIND = 5; + +class GamificationContainer extends React.Component { + constructor(props) { + super(props); + + this.state = { + showSkillsNagModal: false, + showYouGotSkillsModal: false, + }; + + this.onSkillsNagModalCancel = this.onSkillsNagModalCancel.bind(this); + this.onSkillsNagModalCTA = this.onSkillsNagModalCTA.bind(this); + this.onYouGotSkillsModalCancel = this.onYouGotSkillsModalCancel.bind(this); + this.onYouGotSkillsModalCTA = this.onYouGotSkillsModalCTA.bind(this); + } + + componentDidMount() { + const { auth, loadSkills } = this.props; + + if (auth.user.handle && auth.tokenV3) { + loadSkills(auth.user.handle); + } + } + + componentDidUpdate(prevProps) { + const { profile: prevProfile } = prevProps; + const { profile, auth } = this.props; + const { state } = this; + + if ( + !auth.tokenV3 + || (profile.profileForHandle && profile.profileForHandle !== auth.user.handle) + || (prevProfile.profileForHandle && prevProfile.profileForHandle !== auth.user.handle) + ) { + return; + } + + const lastNagTime = state.lastNagTime || cookies.get(`${REMIND_TIME_COOKIE_NAME}_${auth.user.handle}`); + const now = new Date().getTime(); + + // when to show YouGotSkills modal + if ( + prevProfile + && prevProfile.skills !== null + && profile.skills !== null + && keys(prevProfile.skills).length < MIN_SKILLS_TO_REMIND + && keys(profile.skills).length >= MIN_SKILLS_TO_REMIND + && state.showYouGotSkillsModal === false + ) { + this.setState({ + ...state, + showYouGotSkillsModal: true, + }); + } + + // when to show the nag modal + if ( + window.location.pathname !== '/settings/skills' + && !state.showSkillsNagModal + && (now - lastNagTime) > REMIND_TIME + && profile.skills !== null + && keys(profile.skills).length < MIN_SKILLS_TO_REMIND + ) { + this.setState({ + showSkillsNagModal: true, + lastNagTime: `${now}`, + }); + cookies.set(`${REMIND_TIME_COOKIE_NAME}_${auth.user.handle}`, `${now}`, { expires: 7 }); + } + } + + onYouGotSkillsModalCTA() { + const { profile, auth } = this.props; + const { state } = this; + this.setState({ + ...state, + showYouGotSkillsModal: false, + }); + // track the CTA event + analytics.track('Member clicked CTA button on YouGotSkills modal', { + ...profile, + }); + // Send them to profile page + window.location = `/members/${auth.user.handle}`; + } + + onYouGotSkillsModalCancel() { + const { state } = this; + this.setState({ + ...state, + showYouGotSkillsModal: false, + }); + } + + onSkillsNagModalCTA() { + const { profile } = this.props; + const { state } = this; + this.setState({ + ...state, + showSkillsNagModal: false, + }); + // track the CTA event + analytics.track('Member clicked CTA button on skills remind modal', { + ...profile, + }); + // navigate to skills + window.location = '/settings/skills'; + } + + onSkillsNagModalCancel() { + const { profile } = this.props; + const { state } = this; + this.setState({ + ...state, + showSkillsNagModal: false, + }); + // track the cancel event + analytics.track('Member canceled skills remind modal', { + ...profile, + }); + } + + render() { + const { profile, auth } = this.props; + const { state } = this; + + if (!auth.tokenV3) { + return null; + } + + return ( + + { + state.showSkillsNagModal && ( + + ) + } + { + state.showYouGotSkillsModal && ( + + ) + } + + ); + } +} + +GamificationContainer.defaultProps = { + profile: null, + auth: {}, +}; + +GamificationContainer.propTypes = { + profile: PT.shape(), + auth: PT.shape(), + loadSkills: PT.func.isRequired, +}; + +function mapDispatchToProps(dispatch) { + const profileActions = actions.profile; + const lookupActions = actions.lookup; + + return { + loadSkills: (handle) => { + dispatch(profileActions.getSkillsDone(handle)); + dispatch(lookupActions.getSkillTagsInit()); + dispatch(lookupActions.getSkillTagsDone()); + }, + }; +} + +function mapStateToProps(state) { + return { + auth: { ...state.auth }, + profile: state.profile, + }; +} + +export default connect( + mapStateToProps, + mapDispatchToProps, +)(GamificationContainer); From c7edf71eb36977fe9b26dcee34a1209ca64ead2a Mon Sep 17 00:00:00 2001 From: Kiril Kartunov Date: Fri, 18 Nov 2022 19:13:28 +0200 Subject: [PATCH 02/10] ci: on beta --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 604c51da97..9a644f2e52 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -370,7 +370,7 @@ workflows: filters: branches: only: - - beta-demo + - GAME-47-UAT # This is stage env for production QA releases - "build-prod-staging": context : org-global From 7079068bf139305cd2edf3c72f687c7085f683c1 Mon Sep 17 00:00:00 2001 From: Kiril Kartunov Date: Fri, 18 Nov 2022 19:30:50 +0200 Subject: [PATCH 03/10] fix no auth thrown error --- src/shared/containers/Gamification/index.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/containers/Gamification/index.jsx b/src/shared/containers/Gamification/index.jsx index 1046832dce..99858b13fc 100644 --- a/src/shared/containers/Gamification/index.jsx +++ b/src/shared/containers/Gamification/index.jsx @@ -34,7 +34,7 @@ class GamificationContainer extends React.Component { componentDidMount() { const { auth, loadSkills } = this.props; - if (auth.user.handle && auth.tokenV3) { + if (auth.tokenV3 && auth.user.handle) { loadSkills(auth.user.handle); } } From 0ca03d37666d27fe79b6a66b6d0096b237f867bf Mon Sep 17 00:00:00 2001 From: Kiril Kartunov Date: Mon, 21 Nov 2022 10:14:53 +0200 Subject: [PATCH 04/10] GAME-213 --- src/shared/components/Gamification/SkillsNagModal/index.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shared/components/Gamification/SkillsNagModal/index.jsx b/src/shared/components/Gamification/SkillsNagModal/index.jsx index 598f96d32c..bbaf4a01c3 100644 --- a/src/shared/components/Gamification/SkillsNagModal/index.jsx +++ b/src/shared/components/Gamification/SkillsNagModal/index.jsx @@ -33,7 +33,7 @@ const SkillsNagModal = ({
- Profile Skills Reminder + UPDATE PROFILE SKILLS
@@ -138,7 +138,7 @@ const SkillsNagModal = ({
{/* eslint-disable-next-line max-len */} - Hey {handle}, we have noticed that you {skillCountStatement(keys(skills).length)} added to your profile. To be able to match you with the best opportunities at Topcoder, please add at least {MIN_SKILLS_TO_REMIND} skills to your profile as soon as you can. + Hey {handle}, we have noticed that you {skillCountStatement(keys(skills).length)} added to your profile. To be able to match you with the best opportunities at Topcoder, please add skills to that you have at least {MIN_SKILLS_TO_REMIND} skills listed in your profile.
From a9f51d4473ce84741bfdb7288276ea35298de5fd Mon Sep 17 00:00:00 2001 From: Kiril Kartunov Date: Mon, 21 Nov 2022 11:56:32 +0200 Subject: [PATCH 05/10] GAME-214 & GAME-217 --- .../YouGotSkillsModal/YouGotSkillsBadge.jsx | 106 ++++++++++++++++++ .../Gamification/YouGotSkillsModal/index.jsx | 100 +---------------- .../WorkExperience/index.jsx | 4 +- .../WorkSkills/Interests/index.jsx | 2 +- .../Skills/AddSkillsModal/index.jsx | 40 +++---- .../Skills/AddSkillsModal/styles.scss | 1 + .../WorkSkills/Skills/index.jsx | 26 +++-- .../WorkSkills/Skills/styles.scss | 21 +++- .../ExperienceAndSkills/WorkSkills/index.jsx | 2 +- 9 files changed, 165 insertions(+), 137 deletions(-) create mode 100644 src/shared/components/Gamification/YouGotSkillsModal/YouGotSkillsBadge.jsx diff --git a/src/shared/components/Gamification/YouGotSkillsModal/YouGotSkillsBadge.jsx b/src/shared/components/Gamification/YouGotSkillsModal/YouGotSkillsBadge.jsx new file mode 100644 index 0000000000..eb68c710e0 --- /dev/null +++ b/src/shared/components/Gamification/YouGotSkillsModal/YouGotSkillsBadge.jsx @@ -0,0 +1,106 @@ +import React from 'react'; +import { MIN_SKILLS_TO_REMIND } from 'containers/Gamification'; + +export default function YouGotSkillsBadge() { + return ( + + {`You’ve added at least ${MIN_SKILLS_TO_REMIND} skills to your profile!`} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} diff --git a/src/shared/components/Gamification/YouGotSkillsModal/index.jsx b/src/shared/components/Gamification/YouGotSkillsModal/index.jsx index 370d414e0f..255ddc063c 100644 --- a/src/shared/components/Gamification/YouGotSkillsModal/index.jsx +++ b/src/shared/components/Gamification/YouGotSkillsModal/index.jsx @@ -3,6 +3,7 @@ import PT from 'prop-types'; import { Modal } from 'topcoder-react-ui-kit'; import IconClose from 'assets/images/icon-close-green.svg'; +import YouGotSkillsBadge from './YouGotSkillsBadge'; import style from './styles.scss'; const YouGotSkillsModal = ({ @@ -24,104 +25,7 @@ const YouGotSkillsModal = ({
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
{/* eslint-disable-next-line max-len */} diff --git a/src/shared/components/Settings/ExperienceAndSkills/WorkExperience/index.jsx b/src/shared/components/Settings/ExperienceAndSkills/WorkExperience/index.jsx index 4a1396d56b..5650321910 100644 --- a/src/shared/components/Settings/ExperienceAndSkills/WorkExperience/index.jsx +++ b/src/shared/components/Settings/ExperienceAndSkills/WorkExperience/index.jsx @@ -431,7 +431,7 @@ export default class Work extends ConsentComponent {
{ isEdit ? (Edit workplace) - : (Add a new workplace) + : (Jobs) }
{ @@ -567,7 +567,7 @@ export default class Work extends ConsentComponent { theme={{ button: styles.button }} onClick={this.onHandleAddWork} > - Add Another Job + Add Job )} diff --git a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Interests/index.jsx b/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Interests/index.jsx index f90fdb97e6..aefad8df48 100755 --- a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Interests/index.jsx +++ b/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Interests/index.jsx @@ -201,7 +201,7 @@ export default class Interests extends ConsentComponent {
- Select Your Interests at Topcoder + Interests at Topcoder
diff --git a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/AddSkillsModal/index.jsx b/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/AddSkillsModal/index.jsx index 357a115b92..4ba0d7b936 100755 --- a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/AddSkillsModal/index.jsx +++ b/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/AddSkillsModal/index.jsx @@ -16,7 +16,6 @@ const CATEGORIES = { }; export default function AddSkillsModal({ - allSkills, disabled, category: intialCategory, editingSkills, @@ -40,12 +39,6 @@ export default function AddSkillsModal({ const find = (arr, i) => arr && _.findIndex(arr, e => e.toLowerCase() === i.toLowerCase()) !== -1; const findSkill = (arr, skill) => arr && arr.find(a => a.id === skill.id); - const popularSkills = React.useMemo(() => allSkills - .filter(skill => find(skill.categories, category)) - .slice(0, 10) - .map(skill => _.cloneDeep(({ ...skill, isPopularSkill: true }))), - [allSkills, category]); - const handleSkillSelect = (skill) => { setEditingSkills([...editingSkills, skill]); }; @@ -66,15 +59,15 @@ export default function AddSkillsModal({ }; const allDisplayingSkills = displayingSkills; - popularSkills.forEach((skill) => { - if (!findSkill(displayingSkills, skill)) { - allDisplayingSkills.push(skill); - } - }); const lookupSkillsOptions = lookupSkills .filter(skill => !findSkill(allDisplayingSkills, skill)) - .filter(skill => find(skill.categories, category)); + .filter(skill => find(skill.categories, category)) + .sort((a, b) => { + if (a.name.toLowerCase() < b.name.toLowerCase()) return -1; + if (a.name.toLowerCase() > b.name.toLowerCase()) return 1; + return 0; + }); const skillList = allDisplayingSkills.map((skill) => { const isOtherCategorySkill = s => !find(s.categories, category); @@ -89,7 +82,7 @@ export default function AddSkillsModal({ role="button" onClick={() => !selected && toggleSkillSelection(skill)} tabIndex={0} - onKeyDown={() => {}} + onKeyDown={() => { }} > {_.truncate(skill.name, { length: 18, separator: ' ' })} @@ -98,7 +91,7 @@ export default function AddSkillsModal({ onClick={() => selected && toggleSkillSelection(skill)} styleName="close" tabIndex={0} - onKeyDown={() => {}} + onKeyDown={() => { }} > @@ -131,33 +124,33 @@ export default function AddSkillsModal({ styleName={tab === CATEGORIES.design ? 'active' : ''} role="presentation" onClick={() => setTab(CATEGORIES.design)} - onKeyDown={() => {}} + onKeyDown={() => { }} > - { getTabName(CATEGORIES.design) } + {getTabName(CATEGORIES.design)}
  • setTab(CATEGORIES.develop)} - onKeyDown={() => {}} + onKeyDown={() => { }} > - { getTabName(CATEGORIES.develop) } + {getTabName(CATEGORIES.develop)}
  • setTab(CATEGORIES.data_science)} - onKeyDown={() => {}} + onKeyDown={() => { }} > - { getTabName(CATEGORIES.data_science) } + {getTabName(CATEGORIES.data_science)}
  • setTab(CATEGORIES.qa)} - onKeyDown={() => {}} + onKeyDown={() => { }} > - { getTabName(CATEGORIES.qa) } + {getTabName(CATEGORIES.qa)}
  • @@ -200,7 +193,6 @@ export default function AddSkillsModal({ } AddSkillsModal.propTypes = { - allSkills: PT.arrayOf(PT.shape()).isRequired, disabled: PT.bool.isRequired, category: PT.string.isRequired, editingSkills: PT.arrayOf(PT.shape()).isRequired, diff --git a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/AddSkillsModal/styles.scss b/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/AddSkillsModal/styles.scss index 40820c3b49..a748173fa8 100755 --- a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/AddSkillsModal/styles.scss +++ b/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/AddSkillsModal/styles.scss @@ -46,6 +46,7 @@ margin: 32px; width: calc(100% - 64px); min-height: 700px; + min-width: 40vw; } .modal-header { diff --git a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/index.jsx b/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/index.jsx index b9f825f0a2..4b425197ce 100755 --- a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/index.jsx +++ b/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/index.jsx @@ -13,11 +13,12 @@ import ConfirmationModal from 'components/Settings/ConfirmationModal'; import AddItemIcon from 'assets/images/settings-add-item.svg'; import RemoveTagIcon from 'assets/images/icon-x-cancel.svg'; import { SettingBannerV2 as Collapse } from 'components/Settings/SettingsBanner'; -import AddSkillsModal from './AddSkillsModal'; +import { MIN_SKILLS_TO_REMIND } from 'containers/Gamification'; +import YouGotSkillsBadge from 'components/Gamification/YouGotSkillsModal/YouGotSkillsBadge'; +import AddSkillsModal from './AddSkillsModal'; import styles from './styles.scss'; - export default class Skills extends ConsentComponent { constructor(props) { super(props); @@ -317,7 +318,7 @@ export default class Skills extends ConsentComponent { { _.map(list, skill => (
  • - {_.includes(skill.sources, 'CHALLENGE') && } + {_.includes(skill.sources, 'CHALLENGE') && } {_.truncate(skill.name, { length: 18, separator: ' ' })} {}} + onKeyDown={() => { }} > @@ -356,9 +357,8 @@ export default class Skills extends ConsentComponent { /> ) } - { showAddSkillsModal && ( + {showAddSkillsModal && ( -

    - Add your skills -

    +
    = MIN_SKILLS_TO_REMIND ? 'center' : 'flex-start' }}> +

    Skills

    + { + userSkills.length < MIN_SKILLS_TO_REMIND ? ( + // eslint-disable-next-line max-len +

    To be able to match you with the best opportunities at Topcoder,
    please be sure you have at least {MIN_SKILLS_TO_REMIND} skills listed in your profile.

    + ) : ( + + ) + } +
    diff --git a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/styles.scss b/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/styles.scss index 78e2ebb102..d4c2e64648 100644 --- a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/styles.scss +++ b/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/styles.scss @@ -51,6 +51,17 @@ background-color: $color-tc-white; } +.title-wrap { + display: flex; + padding-bottom: 12px; + + p { + @include roboto-regular; + + line-height: 26px; + } +} + .form-title { @include barlow-semi-bold; @@ -58,7 +69,7 @@ line-height: 22px; color: inherit; text-transform: uppercase; - padding-bottom: $pad-xxxxl; + margin-right: 32px; } .form-content { @@ -125,12 +136,18 @@ padding: $pad-xxl $pad-lg; } + .title-wrap { + p { + font-size: 14px; + line-height: 24px; + } + } + .form-title { @include barlow-condensed-medium; font-size: 22px; line-height: 24px; - padding-bottom: $pad-xxl; } .form-content { diff --git a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/index.jsx b/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/index.jsx index 50109e7422..f5caa0b13e 100644 --- a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/index.jsx +++ b/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/index.jsx @@ -16,7 +16,7 @@ export default class WorkSkills extends React.Component { render() { return (
    -

    Skills

    +

    About You

    Date: Mon, 21 Nov 2022 11:57:22 +0200 Subject: [PATCH 06/10] ci:on beta --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 9a644f2e52..ee4a76c115 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -370,7 +370,7 @@ workflows: filters: branches: only: - - GAME-47-UAT + - GAME-193 # This is stage env for production QA releases - "build-prod-staging": context : org-global From 8280ccfd4e5c085e6bf7723ac0042eaa9f95c2bc Mon Sep 17 00:00:00 2001 From: Kiril Kartunov Date: Tue, 22 Nov 2022 08:58:16 +0200 Subject: [PATCH 07/10] fixed typo in skill nag modal --- src/shared/components/Gamification/SkillsNagModal/index.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/components/Gamification/SkillsNagModal/index.jsx b/src/shared/components/Gamification/SkillsNagModal/index.jsx index bbaf4a01c3..6571377375 100644 --- a/src/shared/components/Gamification/SkillsNagModal/index.jsx +++ b/src/shared/components/Gamification/SkillsNagModal/index.jsx @@ -138,7 +138,7 @@ const SkillsNagModal = ({
    {/* eslint-disable-next-line max-len */} - Hey {handle}, we have noticed that you {skillCountStatement(keys(skills).length)} added to your profile. To be able to match you with the best opportunities at Topcoder, please add skills to that you have at least {MIN_SKILLS_TO_REMIND} skills listed in your profile. + Hey {handle}, we have noticed that you {skillCountStatement(keys(skills).length)} added to your profile. To be able to match you with the best opportunities at Topcoder, please add skills so that you have at least {MIN_SKILLS_TO_REMIND} skills listed in your profile.
    From 4e0d488d6ad75e9782876e1f96a17323bc0c8249 Mon Sep 17 00:00:00 2001 From: Kiril Kartunov Date: Thu, 24 Nov 2022 09:45:30 +0200 Subject: [PATCH 08/10] GAME-218 color fix --- src/shared/components/Gamification/SkillsNagModal/index.jsx | 2 +- .../components/Gamification/SkillsNagModal/styles.scss | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/shared/components/Gamification/SkillsNagModal/index.jsx b/src/shared/components/Gamification/SkillsNagModal/index.jsx index 6571377375..cd3bd1550e 100644 --- a/src/shared/components/Gamification/SkillsNagModal/index.jsx +++ b/src/shared/components/Gamification/SkillsNagModal/index.jsx @@ -138,7 +138,7 @@ const SkillsNagModal = ({
    {/* eslint-disable-next-line max-len */} - Hey {handle}, we have noticed that you {skillCountStatement(keys(skills).length)} added to your profile. To be able to match you with the best opportunities at Topcoder, please add skills so that you have at least {MIN_SKILLS_TO_REMIND} skills listed in your profile. + Hey {handle}, we have noticed that you {skillCountStatement(keys(skills).length)} added to your profile. To be able to match you with the best opportunities at Topcoder, please add skills so that you have at least {MIN_SKILLS_TO_REMIND} skills listed in your profile.
  • diff --git a/src/shared/components/Gamification/SkillsNagModal/styles.scss b/src/shared/components/Gamification/SkillsNagModal/styles.scss index 127e73c9b6..3d1cde723d 100644 --- a/src/shared/components/Gamification/SkillsNagModal/styles.scss +++ b/src/shared/components/Gamification/SkillsNagModal/styles.scss @@ -60,6 +60,11 @@ justify-content: center; margin-bottom: 12px; } + + span span { + color: #137d60; + font-weight: bold; + } } } From 7b68016dec9566627c81f11cbf954c9f5387230d Mon Sep 17 00:00:00 2001 From: Kiril Kartunov Date: Wed, 30 Nov 2022 09:24:51 +0200 Subject: [PATCH 09/10] GAME-223 consolidate add skills --- .../WorkSkills/Skills/index.jsx | 26 +------------------ 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/index.jsx b/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/index.jsx index 4b425197ce..0c3beef01c 100755 --- a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/index.jsx +++ b/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/index.jsx @@ -399,31 +399,7 @@ export default class Skills extends ConsentComponent { disabled={!canModifyTrait} theme={{ button: styles['button-add'] }} > - Add Design / UX Skills - - - this.setState({ showAddSkillsModal: 'develop' })} - disabled={!canModifyTrait} - theme={{ button: styles['button-add'] }} - > - Add Developer Skills - - - this.setState({ showAddSkillsModal: 'data_science' })} - disabled={!canModifyTrait} - theme={{ button: styles['button-add'] }} - > - Add Data Science Skills - - - this.setState({ showAddSkillsModal: 'qa' })} - disabled={!canModifyTrait} - theme={{ button: styles['button-add'] }} - > - Add QA Skills + Add Skills
    From 5d7bf23e44017dae11c273e30e2baf0f6f2de9ce Mon Sep 17 00:00:00 2001 From: Kiril Kartunov Date: Fri, 2 Dec 2022 10:55:12 +0200 Subject: [PATCH 10/10] GAME-222 prominent add skills note --- .../WorkSkills/Skills/index.jsx | 29 ++++++++++++--- .../WorkSkills/Skills/styles.scss | 37 +++++++++++++++++++ 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/index.jsx b/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/index.jsx index 0c3beef01c..842bd30c4f 100755 --- a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/index.jsx +++ b/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/index.jsx @@ -1,3 +1,4 @@ +/* eslint-disable max-len */ /** * Child component of Settings/Profile renders "Skills" section of profile setting page. */ @@ -375,12 +376,7 @@ export default class Skills extends ConsentComponent {
    = MIN_SKILLS_TO_REMIND ? 'center' : 'flex-start' }}>

    Skills

    { - userSkills.length < MIN_SKILLS_TO_REMIND ? ( - // eslint-disable-next-line max-len -

    To be able to match you with the best opportunities at Topcoder,
    please be sure you have at least {MIN_SKILLS_TO_REMIND} skills listed in your profile.

    - ) : ( - - ) + userSkills.length >= MIN_SKILLS_TO_REMIND && }
    @@ -390,6 +386,27 @@ export default class Skills extends ConsentComponent {
    + { + userSkills.length < MIN_SKILLS_TO_REMIND && ( +
    + + + +

    To be able to match you with the best opportunities at Topcoder, please be sure you have at least {MIN_SKILLS_TO_REMIND} skills listed in your profile.

    +
    + ) + } {skillList}
    diff --git a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/styles.scss b/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/styles.scss index d4c2e64648..afd9ae5234 100644 --- a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/styles.scss +++ b/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/styles.scss @@ -1,3 +1,4 @@ +/* stylelint-disable no-descending-specificity */ @import "~styles/mixins"; .skillList { @@ -92,6 +93,8 @@ .form-body { flex: 0 0 calc(50% + 13px); + display: flex; + flex-direction: column; } .form-footer { @@ -131,6 +134,30 @@ } } +.skill-note { + display: flex; + background-color: $color-black-5; + padding: $pad-md $pad-lg; + border-radius: 4px; + margin-bottom: $pad-lg; + + svg { + margin-right: $margin-md; + min-width: 24px; + } + + p, + span { + @include roboto-medium; + + line-height: 24px; + } + + span { + color: $color-turq-160; + } +} + @include xs-to-md { .form-container { padding: $pad-xxl $pad-lg; @@ -179,3 +206,13 @@ } } } + +@include xs-to-sm { + .skill-note { + flex-direction: column; + + svg { + margin-bottom: $margin-md; + } + } +}