diff --git a/__tests__/shared/components/Settings/Header/__snapshots__/index.jsx.snap b/__tests__/shared/components/Settings/Header/__snapshots__/index.jsx.snap deleted file mode 100644 index bbd94fba03..0000000000 --- a/__tests__/shared/components/Settings/Header/__snapshots__/index.jsx.snap +++ /dev/null @@ -1,33 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`renders setting page header correctly 1`] = ` -
- - - SAVE CHANGES - - -
-`; diff --git a/__tests__/shared/components/Settings/Header/index.jsx b/__tests__/shared/components/Settings/Header/index.jsx deleted file mode 100644 index 03de63ce50..0000000000 --- a/__tests__/shared/components/Settings/Header/index.jsx +++ /dev/null @@ -1,17 +0,0 @@ -import React from 'react'; -import Renderer from 'react-test-renderer/shallow'; - -import Header from 'components/Settings/Header'; - -import profileState from '../__mocks__/profile-state.json'; - -const rnd = new Renderer(); - -it('renders setting page header correctly', () => { - rnd.render((
{}} - />)); - expect(rnd.getRenderOutput()).toMatchSnapshot(); -}); diff --git a/__tests__/shared/components/Settings/Preferences/Email/__snapshots__/index.jsx.snap b/__tests__/shared/components/Settings/Preferences/Email/__snapshots__/index.jsx.snap deleted file mode 100644 index 585e1c49bf..0000000000 --- a/__tests__/shared/components/Settings/Preferences/Email/__snapshots__/index.jsx.snap +++ /dev/null @@ -1,20 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`renders email preferences setting page correctly 1`] = ` -
- -
-`; diff --git a/__tests__/shared/components/Settings/Preferences/Email/index.jsx b/__tests__/shared/components/Settings/Preferences/Email/index.jsx deleted file mode 100644 index f49efaae8d..0000000000 --- a/__tests__/shared/components/Settings/Preferences/Email/index.jsx +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react'; -import Renderer from 'react-test-renderer/shallow'; - -import Email from 'components/Settings/Preferences/Email'; - -const rnd = new Renderer(); - -it('renders email preferences setting page correctly', () => { - rnd.render(()); - expect(rnd.getRenderOutput()).toMatchSnapshot(); -}); diff --git a/__tests__/shared/components/Settings/__mocks__/profile-state.json b/__tests__/shared/components/Settings/__mocks__/profile-state.json deleted file mode 100644 index abd05d4852..0000000000 --- a/__tests__/shared/components/Settings/__mocks__/profile-state.json +++ /dev/null @@ -1,593 +0,0 @@ -{ - "achievements": [ - { - "date": "2016-09-02T00:00:00.000-04:00", - "description": "iOS Developer Challenger Badge" - }, - { - "date": "2015-08-05T00:00:00.000-04:00", - "description": "Participant Badge" - }, - { - "date": "2015-08-05T00:00:00.000-04:00", - "description": "iOS Participant Badge" - }, - { - "date": "2014-07-01T00:00:00.000-04:00", - "description": "Digital Run Top Five" - }, - { - "date": "2014-07-01T00:00:00.000-04:00", - "description": "Digital Run Winner" - }, - { - "date": "2014-02-11T00:00:00.000-05:00", - "description": "First Milestone Prize" - }, - { - "date": "2013-03-15T00:00:00.000-04:00", - "description": "First Forum Post" - }, - { - "date": "2013-03-04T00:00:00.000-05:00", - "description": "First Passing Submission" - }, - { - "date": "2013-02-28T00:00:00.000-05:00", - "description": "First Placement" - }, - { - "date": "2013-02-28T00:00:00.000-05:00", - "description": "First Win" - }, - { - "date": "2012-11-09T00:00:00.000-05:00", - "description": "One Hundred Forum Posts" - }, - { - "date": "2010-10-09T00:00:00.000-04:00", - "description": "Five Hundred Forum Posts" - }, - { - "date": "2009-04-04T00:00:00.000-04:00", - "description": "Twenty Five Placements" - }, - { - "date": "2008-07-01T00:00:00.000-04:00", - "description": "Twenty Five First Placement Win" - }, - { - "date": "2008-06-11T00:00:00.000-04:00", - "description": "One Thousand Forum Posts" - }, - { - "date": "2008-05-12T00:00:00.000-04:00", - "description": "Fifty Passing Submissions" - }, - { - "date": "2008-05-03T00:00:00.000-04:00", - "description": "Fifty Placements" - }, - { - "date": "2008-05-01T00:00:00.000-04:00", - "description": "TopCoder Development Coder of the Month for May 2008" - }, - { - "date": "2007-03-30T00:00:00.000-04:00", - "description": "Fifty First Placement Win" - }, - { - "date": "2006-11-03T00:00:00.000-05:00", - "description": "One Hundred Passing Submissions" - }, - { - "date": "2006-10-28T00:00:00.000-04:00", - "description": "One Hundred First Placement Win" - }, - { - "date": "2006-10-28T00:00:00.000-04:00", - "description": "One hundred Placements" - }, - { - "date": "2006-10-28T00:00:00.000-04:00", - "description": "SRM Engagement Honor" - } - ], - "copilot": false, - "country": "China", - "info": null, - "loadingError": false, - "skills": { - "100": { - "tagName": ".NET", - "hidden": false, - "score": 2, - "sources": [ - "CHALLENGE" - ] - }, - "101": { - "tagName": "ActionScript", - "hidden": false, - "score": 1, - "sources": [ - "CHALLENGE" - ] - }, - "109": { - "tagName": "Android", - "hidden": false, - "score": 1, - "sources": [ - "CHALLENGE" - ] - }, - "110": { - "tagName": "AngularJS", - "hidden": false, - "score": 10, - "sources": [ - "CHALLENGE" - ] - }, - "115": { - "tagName": "Apache Kafka", - "hidden": false, - "score": 1, - "sources": [ - "USER_ENTERED" - ] - }, - "117": { - "tagName": "API", - "hidden": false, - "score": 4, - "sources": [ - "CHALLENGE" - ] - }, - "127": { - "tagName": "Blackberry SDK", - "hidden": false, - "score": 1, - "sources": [ - "CHALLENGE" - ] - }, - "132": { - "tagName": "C#", - "hidden": false, - "score": 1, - "sources": [ - "CHALLENGE" - ] - }, - "153": { - "tagName": "CSS", - "hidden": false, - "score": 10, - "sources": [ - "CHALLENGE" - ] - }, - "154": { - "tagName": "CSS3", - "hidden": false, - "score": 1, - "sources": [ - "USER_ENTERED" - ] - }, - "163": { - "tagName": "Docker", - "hidden": false, - "score": 5, - "sources": [ - "CHALLENGE" - ] - }, - "170": { - "tagName": "EJB", - "hidden": false, - "score": 18, - "sources": [ - "CHALLENGE" - ] - }, - "171": { - "tagName": "Elasticsearch", - "hidden": false, - "score": 1, - "sources": [ - "CHALLENGE" - ] - }, - "177": { - "tagName": "Express", - "hidden": false, - "score": 1, - "sources": [ - "CHALLENGE" - ] - }, - "182": { - "tagName": "Flex", - "hidden": false, - "score": 3, - "sources": [ - "CHALLENGE", - "USER_ENTERED" - ] - }, - "186": { - "tagName": "Force.Com Sites", - "hidden": false, - "score": 1, - "sources": [ - "CHALLENGE" - ] - }, - "211": { - "tagName": "Hibernate", - "hidden": false, - "score": 12, - "sources": [ - "CHALLENGE" - ] - }, - "212": { - "tagName": "HTML", - "hidden": false, - "score": 6, - "sources": [ - "CHALLENGE" - ] - }, - "213": { - "tagName": "HTML5", - "hidden": false, - "score": 12, - "sources": [ - "CHALLENGE", - "USER_ENTERED" - ] - }, - "214": { - "tagName": "HTTP", - "hidden": false, - "score": 3, - "sources": [ - "CHALLENGE" - ] - }, - "219": { - "tagName": "IBM DB2", - "hidden": false, - "score": 5, - "sources": [ - "CHALLENGE", - "USER_ENTERED" - ] - }, - "229": { - "tagName": "IBM Websphere Application Server", - "hidden": false, - "score": 3, - "sources": [ - "CHALLENGE" - ] - }, - "232": { - "tagName": "IBM WebSphere MQ", - "hidden": false, - "score": 1, - "sources": [ - "CHALLENGE" - ] - }, - "244": { - "tagName": "J2EE", - "hidden": false, - "score": 15, - "sources": [ - "CHALLENGE" - ] - }, - "247": { - "tagName": "Java", - "hidden": false, - "score": 123, - "sources": [ - "CHALLENGE" - ] - }, - "248": { - "tagName": "JavaScript", - "hidden": false, - "score": 20, - "sources": [ - "CHALLENGE" - ] - }, - "249": { - "tagName": "JBoss Seam", - "hidden": false, - "score": 3, - "sources": [ - "CHALLENGE" - ] - }, - "250": { - "tagName": "JDBC", - "hidden": false, - "score": 3, - "sources": [ - "CHALLENGE" - ] - }, - "254": { - "tagName": "JPA", - "hidden": false, - "score": 9, - "sources": [ - "CHALLENGE" - ] - }, - "255": { - "tagName": "jQuery", - "hidden": false, - "score": 2, - "sources": [ - "CHALLENGE" - ] - }, - "258": { - "tagName": "JSF", - "hidden": false, - "score": 2, - "sources": [ - "CHALLENGE", - "USER_ENTERED" - ] - }, - "259": { - "tagName": "JSON", - "hidden": false, - "score": 1, - "sources": [ - "CHALLENGE" - ] - }, - "260": { - "tagName": "JSP", - "hidden": false, - "score": 21, - "sources": [ - "CHALLENGE", - "USER_ENTERED" - ] - }, - "276": { - "tagName": "Maven", - "hidden": false, - "score": 1, - "sources": [ - "CHALLENGE" - ] - }, - "281": { - "tagName": "MongoDB", - "hidden": false, - "score": 1, - "sources": [ - "CHALLENGE" - ] - }, - "284": { - "tagName": "MySql", - "hidden": false, - "score": 7, - "sources": [ - "CHALLENGE", - "USER_ENTERED" - ] - }, - "286": { - "tagName": "Node.js", - "hidden": false, - "score": 18, - "sources": [ - "CHALLENGE", - "USER_ENTERED" - ] - }, - "295": { - "tagName": "Oracle Database", - "hidden": false, - "score": 14, - "sources": [ - "CHALLENGE" - ] - }, - "303": { - "tagName": "PHP", - "hidden": false, - "score": 1, - "sources": [ - "CHALLENGE" - ] - }, - "306": { - "tagName": "PostgreSQL", - "hidden": false, - "score": 8, - "sources": [ - "CHALLENGE" - ] - }, - "315": { - "tagName": "React.js", - "hidden": false, - "score": 1, - "sources": [ - "USER_ENTERED" - ] - }, - "323": { - "tagName": "REST", - "hidden": false, - "score": 5, - "sources": [ - "CHALLENGE" - ] - }, - "328": { - "tagName": "Salesforce", - "hidden": false, - "score": 2, - "sources": [ - "CHALLENGE" - ] - }, - "337": { - "tagName": "Servlet", - "hidden": false, - "score": 2, - "sources": [ - "CHALLENGE" - ] - }, - "344": { - "tagName": "Sharepoint 3.0", - "hidden": false, - "score": 2, - "sources": [ - "CHALLENGE", - "USER_ENTERED" - ] - }, - "354": { - "tagName": "Spring", - "hidden": false, - "score": 15, - "sources": [ - "CHALLENGE" - ] - }, - "355": { - "tagName": "SQL", - "hidden": false, - "score": 4, - "sources": [ - "CHALLENGE" - ] - }, - "356": { - "tagName": "SQL Server", - "hidden": false, - "score": 2, - "sources": [ - "CHALLENGE" - ] - }, - "362": { - "tagName": "Struts", - "hidden": false, - "score": 3, - "sources": [ - "CHALLENGE" - ] - }, - "387": { - "tagName": "Web Services", - "hidden": false, - "score": 8, - "sources": [ - "CHALLENGE" - ] - }, - "401": { - "tagName": "XML", - "hidden": false, - "score": 6, - "sources": [ - "CHALLENGE" - ] - }, - "402": { - "tagName": "XSL", - "hidden": false, - "score": 2, - "sources": [ - "CHALLENGE", - "USER_ENTERED" - ] - } - }, - "stats": null, - "profileForHandle": "tcscoder", - "linkedAccounts": [ - { - "userId": "623633", - "name": "tcscoder", - "email": "tcscoder@gmail.com", - "providerType": "github", - "provider": null, - "context": null, - "social": true, - "enterprise": false, - "emailVerified": false - }, - { - "userId": "1233342", - "name": "1233342", - "email": "", - "providerType": "stackoverflow", - "provider": null, - "context": null, - "social": true, - "enterprise": false, - "emailVerified": false - } - ], - "externalLinks": [ - { - "userId": 22655076, - "key": "4c7136cdbbf227274e49c475e7541abf", - "handle": "tcscoder", - "description": "Search the world's information, including webpages, images, videos and more. Google has many special features to help you find exactly what you're looking for.", - "entities": null, - "keywords": null, - "title": "Google", - "images": "https://www.google.com/images/branding/googlelogo/1x/googlelogo_white_background_color_272x92dp.png", - "source": "embed.ly", - "synchronizedAt": 1525560141959, - "URL": "https://www.google.com" - } - ], - "externalAccounts": { - "userId": 22655076, - "handle": "tcscoder", - "behance": null, - "bitbucket": null, - "dribbble": null, - "github": null, - "linkedin": null, - "stackoverflow": null, - "twitter": null, - "updatedAt": null, - "createdAt": null, - "createdBy": null, - "updatedBy": null - }, - "emailPreferences": { - "TOPCODER_NL_DESIGN": true, - "TOPCODER_NL_DEV": true, - "TOPCODER_NL_GEN": true - }, - "credential": { - "activationCode": "SDUUH(HFS", - "resetToken": null, - "hasPassword": true - } -} \ No newline at end of file diff --git a/__tests__/shared/components/Settings/__mocks__/props-match.json b/__tests__/shared/components/Settings/__mocks__/props-match.json deleted file mode 100644 index 3995d403ea..0000000000 --- a/__tests__/shared/components/Settings/__mocks__/props-match.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "isExact": true, - "params": { - "settingsTab": "profile" - }, - "path": "/settings/:settingsTab(profile|tools|account|preferences)", - "url": "/settings/profile" -} \ No newline at end of file diff --git a/__tests__/shared/components/Settings/__mocks__/user-profile.json b/__tests__/shared/components/Settings/__mocks__/user-profile.json deleted file mode 100644 index b2dd0838f0..0000000000 --- a/__tests__/shared/components/Settings/__mocks__/user-profile.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "maxRating": { - "rating": 2162, - "track": "DEVELOP", - "subTrack": "DEVELOPMENT" - }, - "userId": 22655076, - "firstName": "Mike", - "lastName": "Smith", - "description": "Hello", - "otherLangName": "Som", - "handle": "tcscoder", - "handleLower": "tcscoder", - "status": "ACTIVE", - "email": "tcscoder@gmail.com", - "addresses": [ - { - "streetAddr1": "Street line 1, #432", - "streetAddr2": "", - "city": "Cheng Du", - "zip": "610101", - "stateCode": "Sichuan", - "type": "HOME", - "updatedAt": null, - "createdAt": null, - "createdBy": "", - "updatedBy": "" - } - ], - "homeCountryCode": "CHN", - "competitionCountryCode": "CHN", - "photoURL": "https://topcoder-prod-media.s3.amazonaws.com/member/profile/tcscoder-1525559661069.png", - "tracks": [ - "DEVELOP" - ], - "updatedAt": "2018-05-05T22:34Z", - "createdAt": "2006-10-06T08:49Z", - "createdBy": "22655076", - "updatedBy": "22655076", - "groups": [ - { - "id": "20000010", - "modifiedBy": null, - "modifiedAt": null, - "createdBy": "8547899", - "createdAt": "2017-09-11T13:54:47.000Z", - "name": "Blockchain", - "description": "Blockchain", - "privateGroup": true, - "selfRegister": true, - "subGroups": null, - "parentGroup": null - }, - { - "id": "20000013", - "modifiedBy": null, - "modifiedAt": null, - "createdBy": "8547899", - "createdAt": "2017-10-19T10:54:47.000Z", - "name": "Veterans", - "description": "Veterans", - "privateGroup": true, - "selfRegister": true, - "subGroups": null, - "parentGroup": null - }, - { - "id": "20000015", - "modifiedBy": null, - "modifiedAt": null, - "createdBy": "8547899", - "createdAt": "2017-11-06T15:49:35.000Z", - "name": "Cognitive", - "description": "Cognitive Community", - "privateGroup": true, - "selfRegister": true, - "subGroups": null, - "parentGroup": null - } - ] -} \ No newline at end of file diff --git a/__tests__/shared/components/Settings/__snapshots__/index.jsx.snap b/__tests__/shared/components/Settings/__snapshots__/index.jsx.snap deleted file mode 100644 index d73c732fee..0000000000 --- a/__tests__/shared/components/Settings/__snapshots__/index.jsx.snap +++ /dev/null @@ -1,3042 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`renders account setting page correctly 1`] = ` -
- -
-
- - -
-
-`; - -exports[`renders preferences setting page correctly 1`] = ` -
- -
-
- - -
-
-`; - -exports[`renders profile setting page correctly 1`] = ` -
- -
-
- - -
-
-`; - -exports[`renders tools setting page correctly 1`] = ` -
- -
-
- - -
-
-`; diff --git a/__tests__/shared/components/Settings/index.jsx b/__tests__/shared/components/Settings/index.jsx deleted file mode 100644 index 98fcde7a81..0000000000 --- a/__tests__/shared/components/Settings/index.jsx +++ /dev/null @@ -1,83 +0,0 @@ -import React from 'react'; -import Renderer from 'react-test-renderer/shallow'; - -import Settings from 'components/Settings'; - -import userProfile from './__mocks__/user-profile.json'; -import profileState from './__mocks__/profile-state.json'; -import propsMatch from './__mocks__/props-match.json'; - -const rnd = new Renderer(); - -it('renders profile setting page correctly', () => { - rnd.render(( {}} - showXlBadge={() => {}} - profile={userProfile} - profileState={profileState} - settingsPageState={{}} - lookupData={{}} - updateProfile={() => {}} - uploadPhoto={() => {}} - deletePhoto={() => {}} - addSkill={() => {}} - hideSkill={() => {}} - match={propsMatch} - />)); - expect(rnd.getRenderOutput()).toMatchSnapshot(); -}); - -it('renders account setting page correctly', () => { - rnd.render(( {}} - showXlBadge={() => {}} - profile={userProfile} - profileState={profileState} - settingsPageState={{}} - updatePassword={() => {}} - clearIncorrectPassword={() => {}} - updateProfile={() => {}} - match={propsMatch} - />)); - expect(rnd.getRenderOutput()).toMatchSnapshot(); -}); - -it('renders tools setting page correctly', () => { - rnd.render(( {}} - showXlBadge={() => {}} - profile={userProfile} - profileState={profileState} - settingsPageState={{}} - match={propsMatch} - />)); - expect(rnd.getRenderOutput()).toMatchSnapshot(); -}); - -it('renders preferences setting page correctly', () => { - rnd.render(( {}} - showXlBadge={() => {}} - profile={userProfile} - profileState={profileState} - settingsPageState={{}} - match={propsMatch} - />)); - expect(rnd.getRenderOutput()).toMatchSnapshot(); -}); diff --git a/__tests__/shared/components/tc-communities/NewsletterSignup.jsx b/__tests__/shared/components/tc-communities/NewsletterSignup.jsx deleted file mode 100644 index 4fdbfe1737..0000000000 --- a/__tests__/shared/components/tc-communities/NewsletterSignup.jsx +++ /dev/null @@ -1,72 +0,0 @@ -import React from 'react'; -import Rnd from 'react-test-renderer/shallow'; -import TU from 'react-dom/test-utils'; -import NewsletterSignup from 'components/tc-communities/NewsletterSignup'; - -const rnd = new Rnd(); - -test('Snapshot match', () => { - rnd.render(( - - )); - expect(rnd.getRenderOutput()).toMatchSnapshot(); - - rnd.render(( - - )); - expect(rnd.getRenderOutput()).toMatchSnapshot(); -}); - -class Wrapper extends React.Component { - componentDidMount() {} - - render() { - return ( - - ); - } -} - -const instance = TU.renderIntoDocument(( - -)); - -describe('handle click', () => { - beforeEach(() => jest.clearAllMocks()); - - test('onTitleClick', () => { - const matches = TU.scryRenderedDOMComponentsWithTag(instance, 'button'); - expect(matches.length).toBe(1); - TU.Simulate.click(matches[0]); - }); -}); diff --git a/__tests__/shared/components/tc-communities/__snapshots__/NewsletterSignup.jsx.snap b/__tests__/shared/components/tc-communities/__snapshots__/NewsletterSignup.jsx.snap deleted file mode 100644 index dd6ae1c390..0000000000 --- a/__tests__/shared/components/tc-communities/__snapshots__/NewsletterSignup.jsx.snap +++ /dev/null @@ -1,47 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Snapshot match 1`] = ` - -`; - -exports[`Snapshot match 2`] = ` - -`; diff --git a/__tests__/shared/components/tc-communities/communities/community-2/__snapshots__/Learn.jsx.snap b/__tests__/shared/components/tc-communities/communities/community-2/__snapshots__/Learn.jsx.snap index 922eede706..07cfe014b4 100644 --- a/__tests__/shared/components/tc-communities/communities/community-2/__snapshots__/Learn.jsx.snap +++ b/__tests__/shared/components/tc-communities/communities/community-2/__snapshots__/Learn.jsx.snap @@ -255,19 +255,5 @@ exports[`Match shadow snapshot 1`] = ` title="Useful Links" /> - `; diff --git a/__tests__/shared/components/tc-communities/communities/demo-expert/__snapshots__/Learn.jsx.snap b/__tests__/shared/components/tc-communities/communities/demo-expert/__snapshots__/Learn.jsx.snap index 442c1cebdf..22130a3c9f 100644 --- a/__tests__/shared/components/tc-communities/communities/demo-expert/__snapshots__/Learn.jsx.snap +++ b/__tests__/shared/components/tc-communities/communities/demo-expert/__snapshots__/Learn.jsx.snap @@ -410,19 +410,5 @@ exports[`Snapshot match 1`] = ` title="Useful Links" /> - `; diff --git a/__tests__/shared/components/tc-communities/communities/taskforce/__snapshots__/Home.jsx.snap b/__tests__/shared/components/tc-communities/communities/taskforce/__snapshots__/Home.jsx.snap index ac2d5bdc21..efb0463e56 100644 --- a/__tests__/shared/components/tc-communities/communities/taskforce/__snapshots__/Home.jsx.snap +++ b/__tests__/shared/components/tc-communities/communities/taskforce/__snapshots__/Home.jsx.snap @@ -212,19 +212,5 @@ exports[`Match shadow snapshot 1`] = ` } } /> - `; diff --git a/__tests__/shared/components/tc-communities/communities/tc-prod-dev/__snapshots__/Learn.jsx.snap b/__tests__/shared/components/tc-communities/communities/tc-prod-dev/__snapshots__/Learn.jsx.snap index 54022b665c..cb16633b29 100644 --- a/__tests__/shared/components/tc-communities/communities/tc-prod-dev/__snapshots__/Learn.jsx.snap +++ b/__tests__/shared/components/tc-communities/communities/tc-prod-dev/__snapshots__/Learn.jsx.snap @@ -395,19 +395,5 @@ exports[`Snapshot match 1`] = ` title="Useful Links" /> - `; diff --git a/docs/contentful/AppComponent.md b/docs/contentful/AppComponent.md index 12c3980e17..a937f7b942 100644 --- a/docs/contentful/AppComponent.md +++ b/docs/contentful/AppComponent.md @@ -46,8 +46,6 @@ Render top spots and list of competitors on specific TCO track. A block that fetches and renders a job listing page driven by recruitCRM. -### Type = `EmailSubscribeForm` - Generic subscribe for MailChimp tags component. - **listId** | **String (Required).** diff --git a/docs/contentful/custom-inline-components-in-markdown-fields.md b/docs/contentful/custom-inline-components-in-markdown-fields.md index da252c165b..4961ffe946 100644 --- a/docs/contentful/custom-inline-components-in-markdown-fields.md +++ b/docs/contentful/custom-inline-components-in-markdown-fields.md @@ -69,22 +69,6 @@ other types too. | listId | | ID of MailChimp list to subscribe. | | interests | empty string | Optional. commas separated string of group ids to which user should be subscribed | -- #### NewsletterSignupForMembers - **Sample use:** `` - - Renders a newsletter signup button that takes user email from his profile - information. If the user is not-authenticated, it gets him to the login or - registration page, and subscribes him on return. Accepts the following props: - - | Param | Default | Description | - | --- | --- | --- | - | label | Subscribe for Newsletter | Optional. Custom label to show on the button. | - | listId | | ID of MailChimp list to subscribe. | - | tags | | ID of MailChimp tags to subscribe. | - | buttonTheme | primary-green-md | Theme key(`tc-` is omitted) for the button. See https://community-app.topcoder.com/examples/contentful/contentblock/3k7k1JpnSvIRrJYWs4izYi | - | title | Sign up for the Topcoder Newsletter | Modal title | - | desc | Do you want to subscribe to this newsletter? | Modal description | - - #### VideoModalButton *Example:* `` @@ -98,14 +82,6 @@ other types too. component works only with YouTube videos, and the URL should be similar to `https://www.youtube.com/embed/mD12LIqdxqk` (). -- #### NewsletterArchive - *Example:* `` - - A list of archive links sorted by descending `sent_date` from a MailChimp's campaign folder. Sould be working under any MarkdownParser component. - - The properties are: - - `name` - the unique name of the camplaing foler. It has to be only one name entity. If those duplicate first found will be picked up and rest ignored. - ## Links - #### Link diff --git a/src/server/index.js b/src/server/index.js index 8ef7eefde4..fa11203491 100644 --- a/src/server/index.js +++ b/src/server/index.js @@ -24,7 +24,6 @@ import { getRates as getExchangeRates } from 'services/money'; import { toJson as xmlToJson } from 'utils/xml2json'; import cdnRouter from './routes/cdn'; -import mailChimpRouter from './routes/mailchimp'; import mockDocuSignFactory from './__mocks__/docu-sign-mock'; import recruitCRMRouter from './routes/recruitCRM'; import mmLeaderboardRouter from './routes/mmLeaderboard'; @@ -240,7 +239,6 @@ async function onExpressJsSetup(server) { }); server.use('/api/cdn', cdnRouter); - server.use('/api/mailchimp', mailChimpRouter); server.use('/api/recruit', recruitCRMRouter); server.use('/api/mml', mmLeaderboardRouter); @@ -288,19 +286,6 @@ async function onExpressJsSetup(server) { ); */ - /* Proxy endpoint for POST requests (to fetch data from resources prohibiting - * cross-origin requests). */ - server.use('/community-app-assets/api/proxy-post', checkAuthorizationHeader, (req, res) => { - fetch(req.query.url, { - body: qs.stringify(req.body), - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - }, - method: 'POST', - }).then(x => x.text()) - .then(x => res.send(x)); - }); - /* Returns currency exchange rates, cached at the server-side (thus drastically * reducing amount of calls to openexchangerates.com). */ server.use('/community-app-assets/api/exchange-rates', checkAuthorizationHeader, (req, res) => { diff --git a/src/server/routes/mailchimp.js b/src/server/routes/mailchimp.js deleted file mode 100644 index 6fea34ebcf..0000000000 --- a/src/server/routes/mailchimp.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * The routes that expose our content to Content Delivery Networks. - */ - -import express from 'express'; -import MailchimpService from '../services/mailchimp'; -import { sendEmail } from '../services/sendGrid'; - -const routes = express.Router(); -/* Sets Access-Control-Allow-Origin header to avoid CORS error. - * TODO: Replace the wildcard value by an appropriate origin filtering. */ -routes.use((req, res, next) => { - res.set('Access-Control-Allow-Origin', '*'); - res.set('Access-Control-Allow-Headers', 'authorization, content-type'); - res.set('Access-Control-Allow-Methods', 'GET,POST,PUT,OPTIONS'); - next(); -}); - -/* do regist member to mailchimp server. */ -routes.post('/:listId/members', (req, res, next) => new MailchimpService().doRegistMember(req).then(res.send.bind(res), next)); - -routes.get('/:listId/members/:emailHash', (req, res) => new MailchimpService().checkSubscription(req).then(res.send.bind(res))); - -routes.put('/:listId/members/:emailHash', (req, res) => new MailchimpService().updateMember(req).then(res.send.bind(res))); - -routes.post('/:listId/members/:emailHash/tags', (req, res) => new MailchimpService().subscribeTags(req).then(res.send.bind(res))); - -routes.get('/campaign-folders', (req, res) => new MailchimpService().getCampaignFolder(req).then(res.send.bind(res))); - -routes.get('/campaigns', (req, res) => new MailchimpService().getCampaigns(req).then(res.send.bind(res))); - -routes.post('/email', (req, res) => sendEmail(req, res).then(res.send.bind(res))); - -export default routes; diff --git a/src/server/services/mailchimp.js b/src/server/services/mailchimp.js deleted file mode 100644 index 1e06769f23..0000000000 --- a/src/server/services/mailchimp.js +++ /dev/null @@ -1,111 +0,0 @@ -/** - * Server-side functions necessary for effective integration with mailchimp - */ -import fetch from 'isomorphic-fetch'; -import config from 'config'; -import qs from 'qs'; - -/** - * Auxiliary class that handles communication with mailchimp - * APIs in the same uniform manner. - */ -export default class MailchimpService { - /** - * Creates a new service instance. - * @param {String} baseUrl The base API endpoint. - */ - constructor(baseUrl) { - this.private = { baseUrl }; - const credentials = config.SECRET.MAILCHIMP.default; - this.mailchimpBaseUrl = credentials.MAILCHIMP_BASE_URL; - this.apiKey = credentials.API_KEY; - this.authorization = `Basic ${Buffer.from(`apikey:${this.apiKey}`).toString('base64')}`; - } - - /** - * Gets data from the specified endpoint. - * @return {Promise} - * @param {Object} the request. - */ - async checkSubscription(req) { - const res = await fetch(`${this.mailchimpBaseUrl}/lists/${req.params.listId}/members/${req.params.emailHash}`, { - method: 'GET', - headers: { - 'Content-Type': req.headers['content-type'], - Authorization: this.authorization, - }, - }); - return res.json(); - } - - async doRegistMember(req) { - const formData = JSON.stringify(req.body); - const res = await fetch(`${this.mailchimpBaseUrl}/lists/${req.params.listId}/members`, { - method: 'POST', - headers: { - 'Content-Type': req.headers['content-type'], - Authorization: this.authorization, - }, - body: formData, - }); - return res.json(); - } - - async updateMember(req) { - const formData = JSON.stringify(req.body); - const res = await fetch(`${this.mailchimpBaseUrl}/lists/${req.params.listId}/members/${req.params.emailHash}`, { - method: 'PUT', - headers: { - 'Content-Type': req.headers['content-type'], - Authorization: this.authorization, - }, - body: formData, - }); - return res.json(); - } - - async subscribeTags(req) { - const formData = JSON.stringify(req.body); - const res = await fetch(`${this.mailchimpBaseUrl}/lists/${req.params.listId}/members/${req.params.emailHash}/tags`, { - method: 'POST', - headers: { - 'Content-Type': req.headers['content-type'], - Authorization: this.authorization, - }, - body: formData, - }); - return { status: res.status }; - } - - /** - * Gets campaign-folders endpoint. - * @return {Promise} - * @param {Object} the request. - */ - async getCampaignFolder(req) { - const res = await fetch(`${this.mailchimpBaseUrl}/campaign-folders?count=500`, { - method: 'GET', - headers: { - 'Content-Type': req.headers['content-type'], - Authorization: this.authorization, - }, - }); - return res.json(); - } - - /** - * Gets campaigns endpoint. - * @return {Promise} - * @param {Object} the request. - */ - async getCampaigns(req) { - const res = await fetch(`${this.mailchimpBaseUrl}/campaigns?${qs.stringify(req.query)}`, { - method: 'GET', - headers: { - 'Content-Type': req.headers['content-type'], - Authorization: this.authorization, - }, - }); - return res.json(); - } -} diff --git a/src/shared/actions/newsletterArchive.js b/src/shared/actions/newsletterArchive.js deleted file mode 100644 index 67e55af59b..0000000000 --- a/src/shared/actions/newsletterArchive.js +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Actions for the Newsletter archive container. - */ - -/* global fetch */ -import _ from 'lodash'; -import { createActions } from 'redux-actions'; -import { config } from 'topcoder-react-utils'; - -// Fetching init -function fetchDataInit(name) { - return name; -} - -// Fetching done -async function fetchDataDone(name) { - /* NOTE: In the real life in most cases you don't want to use fetch() directly - * in an action. You want to create a service for your calls and use it here. - * However, in this example, to keep it a bit more compact, we use fetch() - * directly here. - * - * 1st we fetch all folders to try assicaite an `id` to the folder name - * 2nd we fetch the campaign details */ - try { - const PROXY_ENDPOINT = `${config.URL.COMMUNITY_APP}/api/mailchimp`; - let res = await fetch(`${PROXY_ENDPOINT}/campaign-folders`, { - headers: { - 'Content-Type': 'application/json', - }, - }); - if (!res.ok) throw new Error(res.statusText); - res = await res.json(); - const folder = _.find(res.folders, { name }); - if (!folder) throw new Error(`Folder '${name}' does not exist`); - let res2 = await fetch(`${PROXY_ENDPOINT}/campaigns?count=10000&sort_field=send_time&sort_dir=DESC&folder_id=${folder.id}`, { - headers: { - 'Content-Type': 'application/json', - }, - }); - if (!res2.ok) throw new Error(res2.statusText); - res2 = await res2.json(); - - return { - name, - archive: res2, - }; - } catch (error) { - return { - name, - error, - }; - } -} - -export default createActions({ - NEWSLETTER_ARCHIVE: { - FETCH_DATA_INIT: fetchDataInit, - FETCH_DATA_DONE: fetchDataDone, - }, -}); diff --git a/src/shared/actions/newsletterPreferences.js b/src/shared/actions/newsletterPreferences.js deleted file mode 100644 index 0e512d3837..0000000000 --- a/src/shared/actions/newsletterPreferences.js +++ /dev/null @@ -1,110 +0,0 @@ -/** - * Actions for the Newsletter preference container. - */ - -/* global fetch */ -import _ from 'lodash'; -import { createActions } from 'redux-actions'; -import { config } from 'topcoder-react-utils'; - -const PROXY_ENDPOINT = `${config.URL.COMMUNITY_APP}/api/mailchimp`; - -// Fetching member's newsletter preferences init -function fetchDataInit(email) { - return email; -} - -// Fetching member's newsletter preferences -async function fetchDataDone(emailHash, listId = config.NEWSLETTER_SIGNUP.DEFAUL_LIST_ID) { - /* NOTE: In the real life in most cases you don't want to use fetch() directly - * in an action. You want to create a service for your calls and use it here. - * However, in this example, to keep it a bit more compact, we use fetch() - * directly here. */ - try { - let error = false; - const subs = await fetch(`${PROXY_ENDPOINT}/${listId}/members/${emailHash}`, { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - }, - }) - .then((result) => { - if (result.status !== 200) error = true; - return result.json(); - }); - - let preferences = []; - let status = 'notsubscribed'; - if (!error && subs.status === 'subscribed') { - status = 'subscribed'; - preferences = subs.interests; - } - - return { - email: emailHash, - preferences, - status, - error, - }; - } catch (error) { - return { - email: emailHash, - error, - }; - } -} - -// Updates member newsletter subscription -async function updateSubscriptionsDone( - emailHash, groupId, status, listId = config.NEWSLETTER_SIGNUP.DEFAUL_LIST_ID, -) { - /* NOTE: In the real life in most cases you don't want to use fetch() directly - * in an action. You want to create a service for your calls and use it here. - * However, in this example, to keep it a bit more compact, we use fetch() - * directly here. */ - try { - let error = false; - const fetchUrl = `${PROXY_ENDPOINT}/${listId}/members/${emailHash}`; - - const data = { - interests: { [groupId]: !!status }, - }; - - const formData = JSON.stringify(data); - // use proxy for avoid 'Access-Control-Allow-Origin' bug - await fetch(fetchUrl, { - method: 'PUT', - headers: { - 'Content-Type': 'application/json', - }, - body: formData, - }) - .then((result) => { - if (!result.ok) error = true; - return result.json(); - }); - - return { - id: groupId, - checked: status, - email: emailHash, - error, - }; - } catch (error) { - return { - id: groupId, - checked: status, - email: emailHash, - error, - }; - } -} - -export default createActions({ - NEWSLETTER_PREFERENCES: { - FETCH_DATA_INIT: fetchDataInit, - FETCH_DATA_DONE: fetchDataDone, - UPDATE_TAG_INIT: _.identity, - UPDATE_TAG_DONE: updateSubscriptionsDone, - }, -}); diff --git a/src/shared/components/Contentful/AppComponent/index.jsx b/src/shared/components/Contentful/AppComponent/index.jsx index 8328df7e6e..22ba9de307 100644 --- a/src/shared/components/Contentful/AppComponent/index.jsx +++ b/src/shared/components/Contentful/AppComponent/index.jsx @@ -10,7 +10,6 @@ import React from 'react'; import { errors } from 'topcoder-react-lib'; import Leaderboard from 'containers/tco/Leaderboard'; import RecruitCRMJobs from 'containers/Gigs/RecruitCRMJobs'; -import EmailSubscribeForm from 'containers/EmailSubscribeForm'; import GSheet from 'containers/GSheet'; import PathSelector from 'components/MemberPath/PathSelector'; @@ -56,9 +55,6 @@ export function AppComponentSwitch(appComponent) { if (type === 'RecruitCRM-Jobs') { return ; } - if (type === 'EmailSubscribeForm') { - return ; - } if (type === 'GSheet') { return ; } diff --git a/src/shared/components/Settings/FormField/index.jsx b/src/shared/components/Form/FormField/index.jsx similarity index 100% rename from src/shared/components/Settings/FormField/index.jsx rename to src/shared/components/Form/FormField/index.jsx diff --git a/src/shared/components/Settings/FormField/styles.scss b/src/shared/components/Form/FormField/styles.scss similarity index 100% rename from src/shared/components/Settings/FormField/styles.scss rename to src/shared/components/Form/FormField/styles.scss diff --git a/src/shared/components/Settings/FormInputCheckbox/index.jsx b/src/shared/components/Form/FormInputCheckbox/index.jsx similarity index 100% rename from src/shared/components/Settings/FormInputCheckbox/index.jsx rename to src/shared/components/Form/FormInputCheckbox/index.jsx diff --git a/src/shared/components/Settings/FormInputCheckbox/styles.scss b/src/shared/components/Form/FormInputCheckbox/styles.scss similarity index 100% rename from src/shared/components/Settings/FormInputCheckbox/styles.scss rename to src/shared/components/Form/FormInputCheckbox/styles.scss diff --git a/src/shared/components/Settings/FormInputDatePicker/index.jsx b/src/shared/components/Form/FormInputDatePicker/index.jsx similarity index 100% rename from src/shared/components/Settings/FormInputDatePicker/index.jsx rename to src/shared/components/Form/FormInputDatePicker/index.jsx diff --git a/src/shared/components/Settings/FormInputDatePicker/styles.scss b/src/shared/components/Form/FormInputDatePicker/styles.scss similarity index 100% rename from src/shared/components/Settings/FormInputDatePicker/styles.scss rename to src/shared/components/Form/FormInputDatePicker/styles.scss diff --git a/src/shared/components/Settings/FormInputSelect/index.jsx b/src/shared/components/Form/FormInputSelect/index.jsx similarity index 100% rename from src/shared/components/Settings/FormInputSelect/index.jsx rename to src/shared/components/Form/FormInputSelect/index.jsx diff --git a/src/shared/components/Settings/FormInputSelect/styles.scss b/src/shared/components/Form/FormInputSelect/styles.scss similarity index 100% rename from src/shared/components/Settings/FormInputSelect/styles.scss rename to src/shared/components/Form/FormInputSelect/styles.scss diff --git a/src/shared/components/Settings/FormInputText/index.jsx b/src/shared/components/Form/FormInputText/index.jsx similarity index 100% rename from src/shared/components/Settings/FormInputText/index.jsx rename to src/shared/components/Form/FormInputText/index.jsx diff --git a/src/shared/components/Settings/FormInputText/styles.scss b/src/shared/components/Form/FormInputText/styles.scss similarity index 100% rename from src/shared/components/Settings/FormInputText/styles.scss rename to src/shared/components/Form/FormInputText/styles.scss diff --git a/src/shared/components/Settings/FormInputTextArea/index.jsx b/src/shared/components/Form/FormInputTextArea/index.jsx similarity index 100% rename from src/shared/components/Settings/FormInputTextArea/index.jsx rename to src/shared/components/Form/FormInputTextArea/index.jsx diff --git a/src/shared/components/Settings/FormInputTextArea/styles.scss b/src/shared/components/Form/FormInputTextArea/styles.scss similarity index 100% rename from src/shared/components/Settings/FormInputTextArea/styles.scss rename to src/shared/components/Form/FormInputTextArea/styles.scss diff --git a/src/shared/components/Gigs/GigDetails/index.jsx b/src/shared/components/Gigs/GigDetails/index.jsx index 7d752fd1cd..c4d26969a7 100644 --- a/src/shared/components/Gigs/GigDetails/index.jsx +++ b/src/shared/components/Gigs/GigDetails/index.jsx @@ -11,7 +11,6 @@ import { connect } from 'react-redux'; import { Link, config } from 'topcoder-react-utils'; import ReactHtmlParser from 'react-html-parser'; import { getSalaryType, getCustomField } from 'utils/gigs'; -import SubscribeMailChimpTag from 'containers/SubscribeMailChimpTag'; import './style.scss'; import IconLocation from 'assets/images/icon-location.svg'; import IconMoney from 'assets/images/icon-payment.svg'; @@ -139,10 +138,6 @@ function GigDetails(props) {
-
-
SUBSCRIBE TO WEEKLY GIG UPDATES
- -

At Topcoder, we pride ourselves in bringing our customers the very best candidates to help fill their needs. Want to improve your chances? You can do a few things:

    diff --git a/src/shared/components/NewsletterArchive/index.jsx b/src/shared/components/NewsletterArchive/index.jsx deleted file mode 100644 index 7e4c9cc089..0000000000 --- a/src/shared/components/NewsletterArchive/index.jsx +++ /dev/null @@ -1,118 +0,0 @@ -import _ from 'lodash'; -import moment from 'moment'; -import React, { Component } from 'react'; -import PT from 'prop-types'; -import { themr } from 'react-css-super-themr'; -import cn from 'classnames'; -import defaultStyle from './style.scss'; - -/* Date/time format to use in the link. */ -const FORMAT = 'MMM DD, YYYY'; - -class NewsletterArchive extends Component { - constructor(props) { - super(props); - - this.state = { - sortParam: { - order: '', - field: '', - }, - }; - } - - render() { - const { - archive, - } = this.props; - const { sortParam } = this.state; - const archiveOrdered = _.orderBy(archive.campaigns, [sortParam.field], [sortParam.order]); - - return ( - - - - - - - - - - { - archiveOrdered.map((archiveItem, indx) => ( - - - - - - )) - } - -
    Item -
    - NEWSLETTER - -
    -
    -
    - SEND DATE - -
    -
    {indx + 1} - - {archiveItem.settings.title} - - - {moment(archiveItem.send_time).format(FORMAT)} -
    - ); - } -} - -NewsletterArchive.propTypes = { - archive: PT.arrayOf().isRequired, -}; - -export default themr('NewsletterArchive', defaultStyle)(NewsletterArchive); diff --git a/src/shared/components/NewsletterArchive/style.scss b/src/shared/components/NewsletterArchive/style.scss deleted file mode 100644 index 6c0292052c..0000000000 --- a/src/shared/components/NewsletterArchive/style.scss +++ /dev/null @@ -1,114 +0,0 @@ -@import "~styles/mixins"; - -$light-gray: #d4d4d4; - -.archive-link { - display: block; - font-size: 15px; - color: $tc-dark-blue-110; - - &:active, - &:focus, - &:visited, - &:hover { - color: $tc-dark-blue-110; - } -} - -.archive-date { - color: $tc-gray-80; - font-size: 12px; - line-height: 15px; - margin-bottom: 10px; - display: block; -} - -.history-table { - width: 100%; - margin-bottom: 62px; - - thead { - th { - color: #2a2a2a; - font-family: Roboto, sans-serif; - font-size: 14px; - font-weight: 500; - letter-spacing: 0.5px; - line-height: 18px; - text-align: left; - text-transform: uppercase; - border-bottom: 1px solid #d4d4d4; - padding-bottom: 15px; - } - } - - .row { - border-bottom: 1px solid #d4d4d4; - - td { - padding: 0; - border-bottom: 1px solid #d4d4d4; - } - - .name { - .archive-link { - color: #0d61bf; - font-size: 14px; - font-weight: 500; - line-height: 51px; - text-decoration: underline; - - &:hover { - text-decoration: none; - } - } - } - - .index, - .sent-date { - color: #2a2a2a; - font-size: 14px; - font-weight: 400; - line-height: 51px; - } - } -} - -.header-table-content { - display: flex; - align-items: center; -} - -.sort-container { - display: flex; - flex-direction: column; - margin-left: 5px; - padding: 0; - border: none; - outline: none; - background: transparent; -} - -.sort-container > div { - width: 0; - height: 0; - border-left: 4px solid transparent; - border-right: 4px solid transparent; -} - -.sort-up { - border-bottom: 4px solid $light-gray; - margin-bottom: 2px; - - &.active { - border-bottom: 4px solid $tc-black; - } -} - -.sort-down { - border-top: 4px solid $light-gray; - - &.active { - border-top: 4px solid $tc-black; - } -} diff --git a/src/shared/components/NewsletterSignup/index.jsx b/src/shared/components/NewsletterSignup/index.jsx deleted file mode 100644 index b352e37c70..0000000000 --- a/src/shared/components/NewsletterSignup/index.jsx +++ /dev/null @@ -1,193 +0,0 @@ -/** - * Join Community component. It includes 'Join Community' button, which is - * automatically hidden, when a user is already member of community. Button - * text changes to the loading symbol, when the joining is underway. And a - * modal is shown on success. - */ -import PT from 'prop-types'; -import fetch from 'isomorphic-fetch'; -import React from 'react'; -import { themr } from 'react-css-super-themr'; -import { Modal, PrimaryButton } from 'topcoder-react-ui-kit'; -import { config } from 'topcoder-react-utils'; -import forge from 'node-forge'; -// import qs from 'qs'; -import _ from 'lodash'; -import defaultStyle from './style.scss'; - -/* Holds the base URL of Community App endpoints that proxy HTTP request to - * mailchimp APIs. */ -const PROXY_ENDPOINT = `${config.URL.COMMUNITY_APP}/api/mailchimp`; - -class NewsletterSignup extends React.Component { - constructor(props) { - super(props); - this.onSubmit = this.onSubmit.bind(this); - this.handleEmailChange = this.handleEmailChange.bind(this); - this.handleKeyPress = this.handleKeyPress.bind(this); - this.checkSubscription = this.checkSubscription.bind(this); - this.state = { email: '', message: '', invalidEmail: false }; - } - - async onSubmit() { - const { listId, interests } = this.props; - - const { email } = this.state; - - if (!this.isEmailValid()) { - this.setState({ invalidEmail: true }); - return; - } - - const md = forge.md.md5.create(); - md.update(email); - const md5Hash = md.digest().toHex(); - this.setState({ invalidEmail: false }); - - let data = null; - const { isSubscribed, subscribedInterests } = await this.checkSubscription(md5Hash); - const interestsReqObj = {}; - let interestIds = null; - - if (interests !== '') { - interestIds = interests.split(/ *, */); - interestIds[interestIds.length - 1] = interestIds[interestIds.length - 1].replace(/^\s+|\s+$/g, ''); - _.map(interestIds, (id) => { interestsReqObj[id] = true; }); - } - - if (isSubscribed) { - if (interests === '') { - this.setState({ message: 'Already Subscribed' }); - return; - } - let allInterestsSubscribed = true; - _.map(interestIds, (id) => { - if (!subscribedInterests[id]) allInterestsSubscribed = false; - }); - if (allInterestsSubscribed) { - this.setState({ message: 'Already Subscribed' }); - return; - } - - - data = { - interests: interestsReqObj, - }; - } else { - data = { - email_address: email, - status: 'subscribed', - merge_fields: { - fname: '', - lname: '', - }, - }; - if (interests !== '') { - data.interests = interestsReqObj; - } - } - - let fetchUrl = `${PROXY_ENDPOINT}/${listId}/members`; - let method = 'POST'; - if (isSubscribed) { - fetchUrl += `/${md5Hash}`; - method = 'PUT'; - } - const formData = JSON.stringify(data); - // use proxy for avoid 'Access-Control-Allow-Origin' bug - await fetch(fetchUrl, { - method, - headers: { - 'Content-Type': 'application/json', - }, - body: formData, - }).then(result => result.json()).then((dataResponse) => { - if (dataResponse.status === 'subscribed') { - // regist success - this.setState({ message: 'Subcribed successfully' }); - } else { - // regist fail - this.setState({ message: dataResponse.title }); - } - }); - } - - async checkSubscription(emailHash) { - const { listId } = this.props; - - let isSubscribed = false; - let subscribedInterests = null; - await fetch(`${PROXY_ENDPOINT}/${listId}/members/${emailHash}`, { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - }, - }) - .then(result => result.json()) - .then((dataResponse) => { - if (dataResponse.status === 'subscribed') { - subscribedInterests = dataResponse.interests; - isSubscribed = true; - } - }); - return { isSubscribed, subscribedInterests }; - } - - isEmailValid() { - const { email } = this.state; - const re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; /* eslint-disable-line no-useless-escape */ - return re.test(String(email).toLowerCase()); - } - - handleEmailChange(e) { - this.setState({ email: e.target.value }); - } - - handleKeyPress(e) { - if (e.key === 'Enter') { - this.onSubmit(); - } - } - - render() { - const { theme } = this.props; - const { email, message, invalidEmail } = this.state; - return ( - - { message && ( - { this.setState({ message: '' }); }}> -

    - { message } -

    - { this.setState({ message: '' }); }} - theme={{ - button: defaultStyle.returnToCommunityButton, - }} - > - Ok - -
    - )} - * Invalid email - - - - -
    - ); - } -} - -NewsletterSignup.defaultProps = { - interests: '', - theme: {}, -}; - -NewsletterSignup.propTypes = { - listId: PT.string.isRequired, - interests: PT.string, - theme: PT.shape(), -}; - -export default themr('Modal', defaultStyle)(NewsletterSignup); diff --git a/src/shared/components/NewsletterSignup/style.scss b/src/shared/components/NewsletterSignup/style.scss deleted file mode 100644 index 7c2104f618..0000000000 --- a/src/shared/components/NewsletterSignup/style.scss +++ /dev/null @@ -1,108 +0,0 @@ -@import "~styles/mixins"; - -.error { - @include roboto-regular; - - color: red; - font-size: 13px; - - &.hide { - color: transparent; - } -} - -.form { - @include roboto-regular; - - display: flex; - background-color: $tc-black; - width: 80%; - - input { - color: $tc-white !important; - background-color: $tc-black !important; - font-size: 15px !important; - height: 43px !important; - line-height: 19px !important; - margin: 8px 0 !important; - padding: 9px 10px 10px !important; - box-shadow: none !important; - width: 55%; - - &.invalid { - border-color: $tc-red !important; - border-width: 2px; - - &:focus { - border-color: $tc-red !important; - border-width: 2px; - } - } - - &.valid { - border: none !important; - - &:focus { - border: none !important; - } - } - - &:focus { - box-shadow: none !important; - color: $tc-white !important; - } - } - - button { - height: 59px; - background-color: #1fc13d; - color: $tc-white; - border: none; - outline: 0; - font-size: 21px; - font-weight: 700; - width: 45%; - - &:hover { - background-color: $tc-gray-80; - } - } - - [placeholder]:focus::-webkit-input-placeholder { - color: $tc-white !important; - } - - ::-webkit-input-placeholder { /* Chrome/Opera/Safari */ - color: $tc-white !important; - text-transform: none; - font-size: 15px; - } - - ::-moz-placeholder { /* Firefox 19+ */ - color: $tc-white !important; - text-transform: none; - font-size: 15px; - } - - :-ms-input-placeholder { /* IE 10+ */ - color: $tc-white !important; - text-transform: none; - font-size: 15px; - } - - :-moz-placeholder { /* Firefox 18- */ - color: $tc-white !important; - text-transform: none; - font-size: 15px; - } -} - -.returnToCommunityButton { - display: block !important; - margin: auto !important; -} - -.modalTitle { - color: $tc-black; - text-align: center; -} diff --git a/src/shared/components/NewsletterSignupForMembers/ConfirmModal/index.jsx b/src/shared/components/NewsletterSignupForMembers/ConfirmModal/index.jsx deleted file mode 100644 index 68c49a979e..0000000000 --- a/src/shared/components/NewsletterSignupForMembers/ConfirmModal/index.jsx +++ /dev/null @@ -1,139 +0,0 @@ -/** - * The modal asking visitor to confirm that he wants to signup for Newsletter where - * NewsletterSignupForMembers component is rendered. If visitor is authenticated it shows - * Signup / Cancel buttons that do what they are supposed to do; otherwise it - * shows Register & Signup / Log In & Signup / Cancel buttons, first of which get - * visitor to registration / login flows, with return url making the signup to - * happen automatically. - */ - -/* global window */ - -import PT from 'prop-types'; -import React from 'react'; -import { Modal, PrimaryButton } from 'topcoder-react-ui-kit'; -import { config } from 'topcoder-react-utils'; -import { themr } from 'react-css-super-themr'; -import tc from 'components/buttons/themed/tc.scss'; -import defaultStyle from './style.scss'; -import modalStyle from '../modal.scss'; - -/** Themes for buttons - * those overwrite PrimaryButton style to match achieve various styles. - * Should implement pattern of classes. - */ -const buttonThemes = { - tc, -}; - - -function ConfirmModal({ - customTcAuthModalText, - signup, - resetSignupButton, - skipConfirmSignup, - token, - theme, - title, - desc, -}) { - let text; - if (token) { - text = ( -
    -

    {title}

    -

    {desc}

    -
    - ); - if (skipConfirmSignup) { - setImmediate(() => signup()); - } - } else { - text = customTcAuthModalText || ( -
    -

    {title}

    -

    - You must be a Topcoder member before you can signup for Newsletter. - To signup, login if you are already a member. If not, register first. -

    -
    - ); - } - - const autoSignupUrl = `${window.location.href.match(/[^?]*/)[0]}?subscribeme=true`; - - return ( - -
    - {text} -
    - { token ? ( -
    - - CANCEL - - signup()} - theme={{ - button: buttonThemes.tc['primary-green-md'], - }} - > - Ok - -
    - ) : ( -
    - { - const url = encodeURIComponent(autoSignupUrl); - window.location = `${config.URL.AUTH}/member?retUrl=${url}`; - }} - theme={{ - button: buttonThemes.tc['primary-white-md'], - }} - > - LOGIN - - { - let url = encodeURIComponent(autoSignupUrl); - url = encodeURIComponent(`${config.URL.AUTH}/member?retUrl=${url}`); - url = encodeURIComponent(url); - window.location = `${config.URL.AUTH}/member/registration?retUrl=${url}`; - }} - theme={{ - button: buttonThemes.tc['primary-green-md'], - }} - > - REGISTER - -
    - )} -
    - ); -} - -ConfirmModal.defaultProps = { - token: null, -}; - -ConfirmModal.propTypes = { - customTcAuthModalText: PT.node.isRequired, - signup: PT.func.isRequired, - resetSignupButton: PT.func.isRequired, - skipConfirmSignup: PT.bool.isRequired, - theme: PT.shape().isRequired, - token: PT.string, - title: PT.string.isRequired, - desc: PT.string.isRequired, -}; - -export default themr('NewsletterSignupForMembers-Modal', defaultStyle)(ConfirmModal); diff --git a/src/shared/components/NewsletterSignupForMembers/ConfirmModal/style.scss b/src/shared/components/NewsletterSignupForMembers/ConfirmModal/style.scss deleted file mode 100644 index ea3f288646..0000000000 --- a/src/shared/components/NewsletterSignupForMembers/ConfirmModal/style.scss +++ /dev/null @@ -1,41 +0,0 @@ -@import "~styles/mixins"; - -.container { - padding: 90px 60px; - width: 629px; - height: 440px; - border-radius: 10px; - display: flex; - flex-direction: column; - justify-content: center; -} - -.overlay { - background-color: #2a2a2a; - opacity: 0.95; -} - -.confirmMsg { - text-align: center; - - h4 { - margin-bottom: 20px; - } - - p { - padding: 0 50px; - } -} - -.signupButtons, -.loginButtons { - text-align: center; - - button { - margin: 24px 12px 0; - - &:first-child { - margin-right: 12px !important; - } - } -} diff --git a/src/shared/components/NewsletterSignupForMembers/index.jsx b/src/shared/components/NewsletterSignupForMembers/index.jsx deleted file mode 100644 index 085f45d634..0000000000 --- a/src/shared/components/NewsletterSignupForMembers/index.jsx +++ /dev/null @@ -1,179 +0,0 @@ -/** - * NewsletterSignupForMembers component. It includes 'Subscribed for Newletter' button, which is - * automatically hidden, when a user have already subscribed for Newletter. Button - * text changes to the loading symbol, when the signing is underway. And a - * modal is shown on success. - */ - -import _ from 'lodash'; -import LoadingIndicator from 'components/LoadingIndicator'; -import PT from 'prop-types'; -import React from 'react'; -import { Modal, PrimaryButton } from 'topcoder-react-ui-kit'; -import tc from 'components/buttons/themed/tc.scss'; -import style from './style.scss'; -import modalStyle from './modal.scss'; - -import ConfirmModal from './ConfirmModal'; - -/** Themes for buttons - * those overwrite PrimaryButton style to match achieve various styles. - * Should implement pattern of classes. - */ -const buttonThemes = { - tc, -}; - -export const STATE = { - CONFIRM_SIGNUP: 'confirm-signup', - DEFAULT: 'default', - HIDDEN: 'hidden', - SIGNEDUP: 'signedup', - SIGNING: 'signing', - ERROR: 'error', -}; - -export default function NewsletterSignupForMembers({ - customSignupConfirmationText, - customSignupErrorText, - customTcAuthModalText, - hideSignupButton, - signup, - label, - resetSignupButton, - skipConfirmSignup, - showSignupConfirmModal, - state, - theme, - token, - buttonTheme, - title, - desc, -}) { - return ( -
    - { - state !== STATE.HIDDEN ? ( - { - switch (state) { - case STATE.SIGNEDUP: - case STATE.SIGNING: - return; - default: - } - showSignupConfirmModal(); - }} - className={state === STATE.SIGNING ? style.signing : ''} - theme={{ - button: buttonThemes.tc[buttonTheme], - disabled: buttonThemes.tc.themedButtonDisabled, - }} - > - {state === STATE.SIGNING ? ( -
    - - Signing... - - -
    - ) : label} -
    - ) : null - } - {state === STATE.SIGNEDUP ? ( - -
    -

    Congratulations!

    -

    - { - customSignupConfirmationText - || 'You are now subscribed.' - } -

    -
    -
    - - RETURN TO PAGE - -
    -
    - ) : null} - {state === STATE.CONFIRM_SIGNUP ? ( - - ) : null} - {state === STATE.ERROR ? ( - -
    -

    Sorry

    -

    - { - customSignupErrorText - || 'We are not able to subscribe you now. Please try later.' - } -

    -
    -
    - - Close - -
    -
    - ) : null} -
    - ); -} - -NewsletterSignupForMembers.defaultProps = { - customSignupConfirmationText: '', - customSignupErrorText: '', - customTcAuthModalText: '', - skipConfirmSignup: false, - theme: {}, - token: null, -}; - -NewsletterSignupForMembers.propTypes = { - customSignupConfirmationText: PT.string, - customSignupErrorText: PT.string, - customTcAuthModalText: PT.string, - signup: PT.func.isRequired, - label: PT.string.isRequired, - hideSignupButton: PT.func.isRequired, - showSignupConfirmModal: PT.func.isRequired, - resetSignupButton: PT.func.isRequired, - skipConfirmSignup: PT.bool, - state: PT.oneOf(_.values(STATE)).isRequired, - theme: PT.shape(), - token: PT.string, - buttonTheme: PT.string.isRequired, - title: PT.string.isRequired, - desc: PT.string.isRequired, -}; diff --git a/src/shared/components/NewsletterSignupForMembers/modal.scss b/src/shared/components/NewsletterSignupForMembers/modal.scss deleted file mode 100644 index 143b6ce4b8..0000000000 --- a/src/shared/components/NewsletterSignupForMembers/modal.scss +++ /dev/null @@ -1,51 +0,0 @@ -@import "~styles/mixins"; -@import "~components/Contentful/default"; - -.container { - padding: 90px 60px; - width: 629px; - height: 440px; - border-radius: 10px; - display: flex; - flex-direction: column; - justify-content: center; -} - -.overlay { - background-color: #2a2a2a; - opacity: 0.95; -} - -.modalMsg { - @include tc-body-md; - @include gui-kit-headers; - - margin: 24px 0; - color: #2a2a2a; - font-size: 16px; - font-weight: 400; - line-height: 26px; - text-align: center; - - h1, - h2, - h3, - h4, - h5, - h6 { - color: #1e94a3; - text-align: center; - } - - h4 { - margin-bottom: 20px; - } - - p { - padding: 0 50px; - } -} - -.buttons { - text-align: center; -} diff --git a/src/shared/components/NewsletterSignupForMembers/style.scss b/src/shared/components/NewsletterSignupForMembers/style.scss deleted file mode 100644 index 2810d52757..0000000000 --- a/src/shared/components/NewsletterSignupForMembers/style.scss +++ /dev/null @@ -1,27 +0,0 @@ -@import "~styles/mixins"; - -.signing:hover { - background: $tc-white; - cursor: default; -} - -.signingContainer { - align-items: center; - display: flex; -} - -.loadingIndicator { - display: inline-block; - height: 32px; - padding-left: 10px; - width: 32px; -} - -.placeholder { - height: 24px; -} - -.returnToCommunityButton { - display: block !important; - margin: auto !important; -} diff --git a/src/shared/components/Settings/Accordion/index.jsx b/src/shared/components/Settings/Accordion/index.jsx deleted file mode 100644 index cc582836ff..0000000000 --- a/src/shared/components/Settings/Accordion/index.jsx +++ /dev/null @@ -1,131 +0,0 @@ -/** - * Accordion component - * - * Used to render the mobile view for the Settings pages. - */ -import React from 'react'; -import PT from 'prop-types'; - -import ArrowDown from 'assets/images/arrow-down.svg'; -import ErrorWrapper from 'components/Settings/ErrorWrapper'; - -import './styles.scss'; - -export default class Accordion extends React.Component { - constructor(props) { - super(props); - - this.isOpened = this.isOpened.bind(this); - this.toggleItem = this.toggleItem.bind(this); - - this.state = { - /* - * hasToggled makes sure that the initial state for the Accordion - * is completely closed. It will sync with the sidebar only after - * the user has clicked the Accordion. - */ - hasToggled: false, - /* - * the current Accordion item is different from this.props.currentSidebarTab - * as it can be undefined, when the Accordion is completely closed. - */ - currentItem: undefined, - }; - } - - componentDidMount() { - const { currentSidebarTab } = this.props; - this.setState({ currentItem: currentSidebarTab }); - } - - /* - * Returns whether a tab is opened or closed. - */ - isOpened(tab) { - const { currentItem } = this.state; - return currentItem === tab; - } - - toggleItem(tab) { - const { hasToggled, currentItem } = this.state; - const { toggleSidebarTab } = this.props; - // update hasToggled so the Accordion can be sync with the Sidebar - if (!hasToggled) { - this.setState({ hasToggled: true }); - } - - if (currentItem === tab) { - // closing the current tab - this.setState({ currentItem: undefined }); - } else { - // opening a new tab, both on the Accordion and the Sidebar - this.setState({ currentItem: tab }); - toggleSidebarTab(tab); - } - } - - render() { - const { - icons, - names, - renderTabContent, - } = this.props; - - /* - * Simple rendering function used to add the props (width & height) - * only once instead of having to add them on each element - */ - const renderSvgIcon = (svgIcon) => { - const componentProps = { - width: '30px', - height: '26px', - }; - return React.cloneElement(svgIcon, componentProps); - }; - - return ( -
    - { - names.map((name, index) => ( -
    -
    this.toggleItem(name)} - onKeyPress={() => this.toggleItem(name)} - > - - {renderSvgIcon(icons[name])} - -

    - {name} -

    - - - -
    - { - this.isOpened(name) ? ( -
    - - {renderTabContent(name)} - -
    - ) : null - } -
    - )) - } -
    - ); - } -} - -Accordion.propTypes = { - currentSidebarTab: PT.string.isRequired, - icons: PT.shape().isRequired, - names: PT.arrayOf(PT.string).isRequired, - renderTabContent: PT.func.isRequired, - toggleSidebarTab: PT.func.isRequired, -}; diff --git a/src/shared/components/Settings/Accordion/styles.scss b/src/shared/components/Settings/Accordion/styles.scss deleted file mode 100644 index 596e68695c..0000000000 --- a/src/shared/components/Settings/Accordion/styles.scss +++ /dev/null @@ -1,42 +0,0 @@ -@import "../style"; - -.Accordion { - width: 100%; - - .header { - display: flex; - flex-direction: row; - align-items: center; - height: 60px; - border-bottom: 1px solid $tc-gray-10; - cursor: pointer; - outline: 0; - } - - .icon-container { - padding: 0 20px; - } - - .name { - @include tc-body-md; - - flex: 1; - color: $tc-black; - font-weight: 500; - text-transform: capitalize; - } - - .arrow-container { - padding-right: 15px; - - .up { - transform: rotate(180deg); - } - - &.closed { - svg { - filter: invert(100%); - } - } - } -} diff --git a/src/shared/components/Settings/ComingSoon/index.jsx b/src/shared/components/Settings/ComingSoon/index.jsx deleted file mode 100644 index 3acd0f6567..0000000000 --- a/src/shared/components/Settings/ComingSoon/index.jsx +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react'; - -import './styles.scss'; - -export default () => ( -
    - This feature is coming soon! -
    - Stay tuned! -
    -); diff --git a/src/shared/components/Settings/ComingSoon/styles.scss b/src/shared/components/Settings/ComingSoon/styles.scss deleted file mode 100644 index 494854882b..0000000000 --- a/src/shared/components/Settings/ComingSoon/styles.scss +++ /dev/null @@ -1,15 +0,0 @@ -@import "../style"; - -.coming-soon { - @include merriweather-sans-regular; - - width: 100%; - display: flex; - align-items: center; - justify-content: center; - font-size: 28px; - text-align: center; - padding: 60px; - color: $tc-black; - line-height: 50px; -} diff --git a/src/shared/components/Settings/ConfirmationModal/index.jsx b/src/shared/components/Settings/ConfirmationModal/index.jsx deleted file mode 100644 index 83189a68cb..0000000000 --- a/src/shared/components/Settings/ConfirmationModal/index.jsx +++ /dev/null @@ -1,45 +0,0 @@ -import React from 'react'; -import PT from 'prop-types'; -import { - Modal, PrimaryButton, Button, GhostButton, -} from 'topcoder-react-ui-kit'; -import IconClose from 'assets/images/icon-close-green.svg'; - -import styles from './styles.scss'; - -export default function ConfirmationModal(props) { - const { onConfirm, onCancel, name } = props; - return ( - -
    -
    -
    - DELETE CONFIRMATION - - - -
    -
    - - Are you sure you want to delete{' '}{name}? This action cannot be undone. - -
    -
    -
    - Yes, Delete -
    -
    - -
    -
    -
    -
    -
    - ); -} - -ConfirmationModal.propTypes = { - onConfirm: PT.func.isRequired, - onCancel: PT.func.isRequired, - name: PT.string.isRequired, -}; diff --git a/src/shared/components/Settings/ConfirmationModal/styles.scss b/src/shared/components/Settings/ConfirmationModal/styles.scss deleted file mode 100644 index 32e0788bb3..0000000000 --- a/src/shared/components/Settings/ConfirmationModal/styles.scss +++ /dev/null @@ -1,191 +0,0 @@ -@import "~styles/mixins"; - -.modal-overlay { - background-color: rgba($color-tc-black, 0.85); -} - -.modal { - display: flex; - flex-direction: column; - align-items: center; - justify-content: flex-start; - width: 100%; - height: 100%; - max-width: none; - max-height: none; - border-radius: 8px; - overflow-y: auto; - background: none; - top: 0; - left: 0; - transform: none; - - .close { - padding: 0; - margin: 0 0 0 auto; - min-height: 0; - } -} - -.modal-dialog { - flex: 0 0 auto; - display: flex; - flex-direction: column; - margin: auto; -} - -.modal-content { - flex: auto; - display: flex; - flex-direction: column; - color: $color-black-100; - max-width: 794px; - background-color: $color-tc-white; - border-radius: 8px; - box-shadow: 0 4px 4px rgba(0, 0, 0, 0.25); - margin: 32px; - width: 100%; -} - -.modal-header { - @include barlow-bold; - - font-size: 22px; - line-height: 26px; - font-weight: 600; - text-transform: uppercase; - display: flex; - align-items: center; - padding: $pad-xxxl $pad-xxxxl $pad-xxxxl; - border-radius: 8px 8px 0 0; -} - -.modal-body { - @include roboto-bold; - - flex: auto; - display: flex; - padding: 0 $pad-xxxxl; - - .title { - font-size: 16px; - line-height: 24px; - font-weight: 400; - padding: 24px 0; - align-items: center; - border-top: 2px solid $color-black-10; - border-bottom: 2px solid $color-black-10; - width: 100%; - - span { - font-weight: 800; - margin-left: 5px; - } - - @include xs-to-sm { - font-size: 16px; - } - } -} - -.modal-footer { - display: flex; - flex-direction: row-reverse; - align-items: flex-end; - padding: 24px 0; - border-radius: 0 0 8px 8px; - margin-right: 24px; - - @include xs-to-md { - padding: $pad-lg; - margin: 0 $margin-lg 0; - width: 100%; - padding-right: 24px !important; - } -} - -@include xs-to-md { - .modal { - padding: 0 20px; - overflow-y: auto; - height: 100%; - max-height: 100%; - border: none; - box-shadow: none; - border-radius: 0; - z-index: 999999; - } - - .modal-content { - min-height: 120px; - } - - .modal-header { - @include roboto-bold; - - font-size: 16px; - line-height: 20px; - padding: $pad-lg; - border-radius: 0; - } - - .modal-body { - padding: 0 $pad-lg; - flex-direction: column; - } - - .modal-footer { - padding: $pad-lg; - margin: 0 $margin-lg 0; - border-radius: 0; - } -} - -@include xs-to-sm { - .modal-content { - width: 100%; - margin: 0; - border-radius: 0; - } -} - -.button-save-ghost { - @include roboto-bold; - - font-weight: 700; - font-size: 16px; - line-height: 24px; - border-radius: 50px !important; - color: #137d60 !important; - text-transform: uppercase; - background-color: #fff !important; - border: 2px solid #137d60 !important; - - &:hover { - background-color: #fff !important; - background-image: none !important; - border-color: #137d60 !important; - } - - @include xs-to-md { - font-size: 14px; - line-height: 20px; - } -} - -.button-save { - @include roboto-bold; - - font-weight: 700; - font-size: 16px; - line-height: 24px; - border-radius: 50px !important; - background: $color-turq-160 !important; - color: $color-tc-white !important; - text-transform: uppercase; - - @include xs-to-md { - font-size: 14px; - line-height: 20px; - } -} diff --git a/src/shared/components/Settings/ConsentComponent/index.jsx b/src/shared/components/Settings/ConsentComponent/index.jsx deleted file mode 100644 index f8a165339c..0000000000 --- a/src/shared/components/Settings/ConsentComponent/index.jsx +++ /dev/null @@ -1,86 +0,0 @@ -/** - * Abstract component that enables sub-classes to have user consent form functionality - */ -/* eslint-disable react/forbid-prop-types */ -/* eslint-disable no-nested-ternary */ -/* eslint-disable jsx-a11y/label-has-for */ -import React from 'react'; -import UserConsentModal from 'components/Settings/UserConsentModal'; -import PT from 'prop-types'; - -export default class ConsentComponent extends React.Component { - constructor(props) { - super(props); - this.onHandleConsent = this.onHandleConsent.bind(this); - this.shouldRenderConsent = this.shouldRenderConsent.bind(this); - this.renderConsent = this.renderConsent.bind(this); - this.showConsent = this.showConsent.bind(this); - ConsentComponent.getTraitData = ConsentComponent.getTraitData.bind(this); - ConsentComponent.getUserConsent = ConsentComponent.getUserConsent.bind(this); - - this.state = { - onConsent: undefined, - }; - } - - onHandleConsent(e, answer) { - e.preventDefault(); - const { onConsent } = this.state; - this.setState({ onConsent: undefined }); - if (onConsent === undefined) { - return; - } - onConsent(answer); - } - - static getTraitData(userTraits) { - const trait = userTraits.filter(t => t.traitId === 'personalization'); - if (trait.length !== 0) { - return trait[0].traits.data[0]; - } - return null; - } - - static getUserConsent(userTraits) { - const traitData = ConsentComponent.getTraitData(userTraits); - - if (traitData && typeof traitData.userConsent === 'boolean') { - return traitData.userConsent; - } - // by default, when personalization user trait hasn't been - // created yet, user doesn't give consent - return false; - } - - /** - * Show User Consent Modal - * @param onConsent callback after consent - */ - showConsent(onConsent) { - const { userTraits } = this.props; - const userConsent = ConsentComponent.getUserConsent(userTraits); - if (userConsent === undefined) { - this.setState({ onConsent }); - } else { - onConsent(userConsent); - } - } - - /** - * Determines if view show render consent - * - * @return {boolean} - */ - shouldRenderConsent() { - const { onConsent } = this.state; - return onConsent; - } - - renderConsent() { - return (); - } -} - -ConsentComponent.propTypes = { - userTraits: PT.array.isRequired, -}; diff --git a/src/shared/components/Settings/ErrorMessage/index.jsx b/src/shared/components/Settings/ErrorMessage/index.jsx deleted file mode 100644 index a26d8d81c4..0000000000 --- a/src/shared/components/Settings/ErrorMessage/index.jsx +++ /dev/null @@ -1,30 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; - -import './styles.scss'; - -const marginTop = (value) => { - if (value) { - return 'active-margin'; - } - - return 'active'; -}; - -const ErrorMessage = ({ invalid, message, addMargin }) => ( - - {message} - -); - -ErrorMessage.defaultProps = { - addMargin: false, -}; - -ErrorMessage.propTypes = { - invalid: PropTypes.bool.isRequired, - message: PropTypes.string.isRequired, - addMargin: PropTypes.bool, -}; - -export default ErrorMessage; diff --git a/src/shared/components/Settings/ErrorMessage/styles.scss b/src/shared/components/Settings/ErrorMessage/styles.scss deleted file mode 100644 index c68e85e9fd..0000000000 --- a/src/shared/components/Settings/ErrorMessage/styles.scss +++ /dev/null @@ -1,25 +0,0 @@ -@import "../style"; - -.error-message { - display: none; - - &.active { - @include roboto-medium; - - display: block; - border-radius: 5px; - color: $tc-red-110; - font-size: 12px; - margin: 10px 0 0 10px; - } - - &.active-margin { - @include roboto-medium; - - display: inline; - border-radius: 5px; - color: $tc-red-110; - font-size: 12px; - margin: 10px auto 0 10px; - } -} diff --git a/src/shared/components/Settings/ErrorWrapper/index.jsx b/src/shared/components/Settings/ErrorWrapper/index.jsx deleted file mode 100644 index 3612074b5a..0000000000 --- a/src/shared/components/Settings/ErrorWrapper/index.jsx +++ /dev/null @@ -1,45 +0,0 @@ -/* eslint-disable react/forbid-prop-types */ -import React from 'react'; -import PT from 'prop-types'; -import { logger } from 'topcoder-react-lib'; - -import './styles.scss'; - -export default class ErrorWrapper extends React.Component { - constructor(props) { - super(props); - this.state = { - error: null, - errorInfo: null, - }; - } - - componentDidCatch(error, errorInfo) { - // Catch errors in any child components and re-renders with an error message - this.setState({ - error, - errorInfo, - }); - } - - render() { - const { error, errorInfo } = this.state; - const { children } = this.props; - - if (error) { - logger.error(error, errorInfo); - - return ( -
    - { process.env.NODE_ENV !== 'production' ? `${error.name}: ${error.message}` : 'There was an issue loading the page' } -
    - ); - } - - return children; - } -} - -ErrorWrapper.propTypes = { - children: PT.any.isRequired, -}; diff --git a/src/shared/components/Settings/ErrorWrapper/styles.scss b/src/shared/components/Settings/ErrorWrapper/styles.scss deleted file mode 100644 index 1d77131803..0000000000 --- a/src/shared/components/Settings/ErrorWrapper/styles.scss +++ /dev/null @@ -1,9 +0,0 @@ -@import "../style"; - -.container { - background-color: $tc-red-10; - color: $tc-red-110; - width: 100%; - height: auto; - border-radius: 6px; -} diff --git a/src/shared/components/Settings/ExperienceAndSkills/WorkExperience/WorkplaceList/Item/index.jsx b/src/shared/components/Settings/ExperienceAndSkills/WorkExperience/WorkplaceList/Item/index.jsx deleted file mode 100644 index b6696e0430..0000000000 --- a/src/shared/components/Settings/ExperienceAndSkills/WorkExperience/WorkplaceList/Item/index.jsx +++ /dev/null @@ -1,117 +0,0 @@ -/** - * render work Item - */ -import _ from 'lodash'; -import React from 'react'; -import PT from 'prop-types'; -import ReactSVG from 'react-svg'; -import moment from 'moment'; -import Tooltip from 'components/Tooltip'; -import { isomorphy } from 'topcoder-react-utils'; - -import './styles.scss'; - -let assets; -if (isomorphy.isClientSide()) { - assets = require.context('assets/images/profile', false, /svg/); -} - -export default function Item(props) { - const { - work, - index, - onDeleteItem, - onEditItem, - } = props; - - const hasSecondLine = () => { - if (_.isEmpty(work.timePeriodFrom) && _.isEmpty(work.timePeriodTo) - && _.isEmpty(work.position) && !work.working) { - return false; - } - - return true; - }; - - const current = work.working ? '- Current' : ''; - - const deleteTip = ( -
    -

    Delete

    -
    - ); - - const editTip = ( -
    -

    Edit

    -
    - ); - - return ( -
    -
    -
    - -
    -
    -
    - { `${work.company}${_.isEmpty(work.industry) ? '' : ` | ${work.industry}`}${_.isEmpty(work.cityTown) ? '' : ` | ${work.cityTown}`}` } -
    -
    - { `${!_.isEmpty(work.timePeriodFrom) ? moment(work.timePeriodFrom).format('YYYY') : ''}${!_.isEmpty(work.timePeriodTo) ? ` - ${moment(work.timePeriodTo).format('YYYY')}` : ` ${current}`} ${!_.isEmpty(work.position) && (!_.isEmpty(work.timePeriodTo) || !_.isEmpty(work.timePeriodFrom)) ? ' | ' : ''}${!_.isEmpty(work.position) ? `${work.position}` : ''}` } -
    -
    -

    - {`${!_.isEmpty(work.timePeriodFrom) ? moment(work.timePeriodFrom).format('YYYY') : ''}${!_.isEmpty(work.timePeriodTo) ? ` - ${moment(work.timePeriodTo).format('YYYY')}` : ` ${current}`}`} -

    -

    - {`${!_.isEmpty(work.position) ? `${work.position}` : ''}`} -

    -
    -
    -
    - -
    - ); -} - -Item.propTypes = { - work: PT.shape().isRequired, - index: PT.number.isRequired, - onDeleteItem: PT.func.isRequired, - onEditItem: PT.func.isRequired, -}; diff --git a/src/shared/components/Settings/ExperienceAndSkills/WorkExperience/WorkplaceList/Item/styles.scss b/src/shared/components/Settings/ExperienceAndSkills/WorkExperience/WorkplaceList/Item/styles.scss deleted file mode 100644 index 6e017384ab..0000000000 --- a/src/shared/components/Settings/ExperienceAndSkills/WorkExperience/WorkplaceList/Item/styles.scss +++ /dev/null @@ -1,207 +0,0 @@ -@import "../../../../style"; - -.container { - display: flex; - flex-direction: row; - justify-items: center; - justify-content: space-between; - align-items: center; - min-height: 96px; - width: 100%; - border-bottom: none; - background-color: $tc-white; - padding: $pad-lg; - border: 1px solid $color-black-20; - border-radius: 8px; -} - -.work-info { - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; -} - -.work-icon { - display: flex; - align-items: center; - justify-content: center; - flex: 0 0 64px; - width: 64px; - height: 64px; - background: $color-black-5; - border-radius: 4px; - margin-right: $margin-lg; -} - -.work-parameters { - @include roboto-medium; - - display: flex; - flex-direction: column; - justify-items: center; - justify-content: center; - font-size: 15px; - line-height: 20px; - text-transform: capitalize; - padding-right: 20px; - - &.single-line { - flex-direction: row; - align-items: center; - } -} - -.parameter-first-line { - @include roboto-bold; - - color: $tc-black; - font-weight: 700; - font-size: 16px; - line-height: 20px; - letter-spacing: 0.5px; - text-transform: capitalize; - word-break: break-all; - - &.single-line { - margin-bottom: 0; - } - - @include upto-sm { - margin-bottom: 0; - } -} - -.parameter-second-line, -.parameter-third-line, -.parameter-second-line-mobile { - @include roboto-medium; - - color: $color-black-60; - font-weight: 400; - font-size: 16px; - line-height: 24px; - word-break: break-all; - - @include upto-sm { - display: none; - } -} - -.parameter-second-line-mobile { - display: none; - - @include upto-sm { - display: flex; - flex-direction: column; - - p { - word-break: break-all; - } - } -} - -.tctooltiptext { - background: $tooltip-gray; - color: $tc-white; - border-radius: 8px; - padding: 10px; - - p { - @include roboto-medium; - - font-weight: 400; - font-size: 14px; - line-height: 22px; - } -} - -.tctooltiptext::after { - content: ""; - position: absolute; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; - bottom: 4px; - margin-left: -5px; - border-width: 5px 5px 0; - left: 50%; - border-top-color: $tc-black; - z-index: 1000; -} - -.operation-container { - display: flex; - flex-direction: row; - justify-content: space-between; - - .delete-wrapper { - margin-left: $margin-xl; - margin-right: $margin-xs; - - @include xs-to-sm { - margin-left: $margin-lg; - margin-right: 0; - } - - @media screen and (max-width: 320px) { - margin-right: 0; - margin-left: 6px; - } - } - - .delete { - display: flex; - flex-direction: column; - justify-items: center; - justify-content: center; - cursor: pointer; - outline-style: none; - - img { - width: 20px; - height: 20px; - } - - p { - @include roboto-regular; - - font-size: 11px; - line-height: 15px; - font-weight: 400; - color: $tc-gray-50; - - @include upto-sm { - display: none; - } - } - } - - .edit { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - cursor: pointer; - outline-style: none; - - img { - width: 20px; - height: 20px; - } - - p { - @include roboto-regular; - - font-size: 11px; - line-height: 15px; - font-weight: 400; - color: $tc-gray-50; - - @include upto-sm { - display: none; - } - } - } -} diff --git a/src/shared/components/Settings/ExperienceAndSkills/WorkExperience/WorkplaceList/index.jsx b/src/shared/components/Settings/ExperienceAndSkills/WorkExperience/WorkplaceList/index.jsx deleted file mode 100644 index a45950d3ee..0000000000 --- a/src/shared/components/Settings/ExperienceAndSkills/WorkExperience/WorkplaceList/index.jsx +++ /dev/null @@ -1,36 +0,0 @@ -/** - * render Work list - */ -import React from 'react'; -import PT from 'prop-types'; -import Item from './Item'; - -import './styles.scss'; - -export default function WorkList(props) { - const { - workList, - onDeleteItem, - onEditItem, - } = props; - - return ( -
    -
      - { - workList.items.map((work, index) => ( -
    • - -
    • - )) - } -
    -
    - ); -} - -WorkList.propTypes = { - workList: PT.shape().isRequired, - onDeleteItem: PT.func.isRequired, - onEditItem: PT.func.isRequired, -}; diff --git a/src/shared/components/Settings/ExperienceAndSkills/WorkExperience/WorkplaceList/styles.scss b/src/shared/components/Settings/ExperienceAndSkills/WorkExperience/WorkplaceList/styles.scss deleted file mode 100644 index 92dda54439..0000000000 --- a/src/shared/components/Settings/ExperienceAndSkills/WorkExperience/WorkplaceList/styles.scss +++ /dev/null @@ -1,19 +0,0 @@ -@import "../../../style"; -@import "~styles/mixins"; - -.container { - width: 100%; - background-color: $tc-white; - padding: 0 0; - margin: 0 0 $margin-xxxxl; - - ul { - display: flex; - flex-direction: column; - justify-items: center; - - li { - margin-bottom: $margin-md; - } - } -} diff --git a/src/shared/components/Settings/ExperienceAndSkills/WorkExperience/index.jsx b/src/shared/components/Settings/ExperienceAndSkills/WorkExperience/index.jsx deleted file mode 100644 index 5650321910..0000000000 --- a/src/shared/components/Settings/ExperienceAndSkills/WorkExperience/index.jsx +++ /dev/null @@ -1,606 +0,0 @@ -/** - * Child component of Settings/Profile/ renders the - * 'Work' page. - */ -/* eslint-disable react/forbid-prop-types */ -/* eslint-disable no-nested-ternary */ -/* eslint-disable jsx-a11y/label-has-for */ -/* eslint-disable no-undef */ -import React from 'react'; -import PT from 'prop-types'; -import _ from 'lodash'; -import moment from 'moment'; -import ConsentComponent from 'components/Settings/ConsentComponent'; -import { PrimaryButton, SecondaryButton } from 'topcoder-react-ui-kit'; -import ErrorMessage from 'components/Settings/ErrorMessage'; -import { validateStartDate, validateEndDate } from 'utils/settings'; -import FormField from 'components/Settings/FormField'; -import FormInputText from 'components/Settings/FormInputText'; -import FormInputCheckbox from 'components/Settings/FormInputCheckbox'; -import FormInputDatePicker from 'components/Settings/FormInputDatePicker'; -import AddItemIcon from 'assets/images/settings-add-item.svg'; -import { SettingBannerV2 as Collapse } from 'components/Settings/SettingsBanner'; -import WorkplaceList from './WorkplaceList'; -import ConfirmationModal from '../../ConfirmationModal'; - -import styles from './styles.scss'; - -export default class Work extends ConsentComponent { - constructor(props) { - super(props); - this.onHandleDeleteWork = this.onHandleDeleteWork.bind(this); - this.onDeleteWork = this.onDeleteWork.bind(this); - this.onEditWork = this.onEditWork.bind(this); - this.loadWorkTrait = this.loadWorkTrait.bind(this); - this.onUpdateInput = this.onUpdateInput.bind(this); - this.onHandleAddWork = this.onHandleAddWork.bind(this); - this.onAddWork = this.onAddWork.bind(this); - this.loadPersonalizationTrait = this.loadPersonalizationTrait.bind(this); - this.onUpdateDate = this.onUpdateDate.bind(this); - this.onCancelEditStatus = this.onCancelEditStatus.bind(this); - - const { userTraits } = props; - this.state = { - formInvalid: false, - startDateInvalid: false, - startDateInvalidMsg: '', - endDateInvalid: false, - endDateDisabled: false, - endDateInvalidMsg: '', - isSumbit: false, - workTrait: this.loadWorkTrait(userTraits), - personalizationTrait: this.loadPersonalizationTrait(userTraits), - newWork: { - company: '', - position: '', - cityTown: '', - timePeriodFrom: '', - timePeriodTo: '', - industry: '', - working: false, - }, - isEdit: false, - indexNo: null, - showConfirmation: false, - windowInnerWidth: 0, - }; - } - - componentWillReceiveProps(nextProps) { - const workTrait = this.loadWorkTrait(nextProps.userTraits); - const personalizationTrait = this.loadPersonalizationTrait(nextProps.userTraits); - this.setState({ - workTrait, - personalizationTrait, - isSubmit: false, - formInvalid: false, - startDateInvalid: false, - startDateInvalidMsg: '', - endDateInvalid: false, - endDateDisabled: false, - endDateInvalidMsg: '', - }); - } - - componentDidMount() { - this.handleResize(); - window.addEventListener('resize', this.handleResize); - } - - componentWillUnmount() { - window.removeEventListener('resize', this.handleResize); - } - - handleResize = () => { - this.setState({ windowInnerWidth: window.innerWidth }); - } - - /** - * Show User Consent Modal - * @param e event - */ - onHandleAddWork(e) { - if (e) e.preventDefault(); - const { newWork } = this.state; - this.setState({ isSubmit: true }); - if (this.onCheckFormValue(newWork)) { - return; - } - this.showConsent(this.onAddWork.bind(this)); - } - - /** - * Check form fields value, - * Invalid value, can not save - * @param newWork object - */ - onCheckFormValue(newWork) { - let invalid = false; - - if (!_.trim(newWork.company).length) { - invalid = true; - } - - const fromDateValidResult = validateStartDate(newWork.working, - newWork.timePeriodFrom, newWork.timePeriodTo); - const endDateValidResult = validateEndDate(newWork.working, - newWork.timePeriodFrom, newWork.timePeriodTo); - const formInvalid = invalid || fromDateValidResult.invalid || endDateValidResult.invalid; - - this.setState({ - formInvalid, - startDateInvalid: fromDateValidResult.invalid, - startDateInvalidMsg: fromDateValidResult.message, - endDateInvalid: endDateValidResult.invalid, - endDateInvalidMsg: endDateValidResult.message, - }); - - return formInvalid; - } - - onHandleDeleteWork(indexNo) { - this.setState({ - showConfirmation: true, - indexNo, - }); - } - - onUpdateDate(date, timePeriod) { - const { newWork: oldWork } = this.state; - const newWork = { ...oldWork }; - newWork[timePeriod] = date; - this.setState({ newWork, isSubmit: false }); - } - - /** - * Delete work by index - * @param indexNo the work index no - */ - onDeleteWork(indexNo) { - const { workTrait } = this.state; - const newWorkTrait = { ...workTrait }; - newWorkTrait.traits.data.splice(indexNo, 1); - this.setState({ - workTrait: newWorkTrait, - }); - - const { - handle, - tokenV3, - updateUserTrait, - deleteUserTrait, - } = this.props; - - if (newWorkTrait.traits.data.length > 0) { - updateUserTrait(handle, 'work', newWorkTrait.traits.data, tokenV3); - } else { - deleteUserTrait(handle, 'work', tokenV3); - } - - this.setState({ - showConfirmation: false, - newWork: { - company: '', - position: '', - cityTown: '', - timePeriodFrom: '', - timePeriodTo: '', - industry: '', - working: false, - }, - isEdit: false, - indexNo: null, - isSubmit: false, - formInvalid: false, - startDateInvalid: false, - startDateInvalidMsg: '', - endDateInvalid: false, - endDateDisabled: false, - endDateInvalidMsg: '', - }); - } - - /** - * Edit work by index - * @param indexNo the work index no - */ - onEditWork(indexNo) { - const { workTrait } = this.state; - const isEmpty = val => val == null || val === ''; - - this.setState({ - newWork: { - company: workTrait.traits.data[indexNo].company, - position: isEmpty(workTrait.traits.data[indexNo].position) ? '' : workTrait.traits.data[indexNo].position, - cityTown: isEmpty(workTrait.traits.data[indexNo].cityTown) ? '' : workTrait.traits.data[indexNo].cityTown, - timePeriodFrom: isEmpty(workTrait.traits.data[indexNo].timePeriodFrom) ? '' : workTrait.traits.data[indexNo].timePeriodFrom, - timePeriodTo: isEmpty(workTrait.traits.data[indexNo].timePeriodTo) ? '' : workTrait.traits.data[indexNo].timePeriodTo, - industry: isEmpty(workTrait.traits.data[indexNo].industry) ? '' : workTrait.traits.data[indexNo].industry, - working: workTrait.traits.data[indexNo].working, - }, - isEdit: true, - indexNo, - formInvalid: false, - startDateInvalid: false, - startDateInvalidMsg: '', - endDateInvalid: false, - endDateDisabled: workTrait.traits.data[indexNo].working, - endDateInvalidMsg: '', - isSubmit: false, - }); - } - - /** - * Add new work - * @param answer user consent answer value - */ - onAddWork(answer) { - const { - newWork, personalizationTrait, isEdit, indexNo, - } = this.state; - const isEmpty = val => val == null || val === ''; - const isEmptyObject = val => _.isEmpty(val); - - const { - handle, - tokenV3, - updateUserTrait, - addUserTrait, - } = this.props; - - const { workTrait } = this.state; - - const work = _.clone(newWork); - if (isEmpty(work.position)) { - delete work.position; - } - if (isEmpty(work.cityTown)) { - delete work.cityTown; - } - if (isEmpty(work.timePeriodFrom)) { - delete work.timePeriodFrom; - } else { - work.timePeriodFrom = new Date(work.timePeriodFrom).getTime(); - } - if (isEmpty(work.timePeriodTo)) { - delete work.timePeriodTo; - } else { - work.timePeriodTo = new Date(work.timePeriodTo).getTime(); - } - if (isEmpty(work.industry)) { - delete work.industry; - } - - if (workTrait.traits && workTrait.traits.data.length > 0) { - const newWorkTrait = _.cloneDeep(workTrait); - if (isEdit) { - newWorkTrait.traits.data.splice(indexNo, 1); - } - newWorkTrait.traits.data.push(work); - updateUserTrait(handle, 'work', newWorkTrait.traits.data, tokenV3); - } else { - const newWorks = []; - newWorks.push(work); - addUserTrait(handle, 'work', newWorks, tokenV3); - } - this.setState({ - isEdit: false, - indexNo: null, - isSubmit: false, - }); - // save personalization - if (isEmptyObject(personalizationTrait)) { - const personalizationData = { userConsent: answer }; - addUserTrait(handle, 'personalization', [personalizationData], tokenV3); - } else { - const trait = personalizationTrait.traits.data[0]; - if (trait.userConsent !== answer) { - const personalizationData = { userConsent: answer }; - updateUserTrait(handle, 'personalization', [personalizationData], tokenV3); - } - } - - this.clearForm(); - } - - clearForm() { - this.setState({ - newWork: { - company: '', - position: '', - cityTown: '', - timePeriodFrom: '', - timePeriodTo: '', - industry: '', - working: false, - }, - }); - } - - /** - * Update input value - * @param e event - */ - onUpdateInput(e) { - const { newWork: oldWork } = this.state; - const newWork = { ...oldWork }; - let endDateDisabled = newWork.working; - if (e.target.type !== 'checkbox') { - newWork[e.target.name] = e.target.value; - } else { - newWork[e.target.name] = e.target.checked; - if (e.target.checked) { // if working nullify toDate - newWork.timePeriodTo = ''; - endDateDisabled = true; - } else { - endDateDisabled = false; - } - } - this.setState({ newWork, isSubmit: false, endDateDisabled }); - } - - /** - * Get work trait - * @param userTraits the all user traits - */ - loadWorkTrait = (userTraits) => { - const trait = userTraits.filter(t => t.traitId === 'work'); - const works = trait.length === 0 ? {} : trait[0]; - return _.assign({}, works); - } - - /** - * Get personalization trait - * @param userTraits the all user traits - */ - loadPersonalizationTrait = (userTraits) => { - const trait = userTraits.filter(t => t.traitId === 'personalization'); - const personalization = trait.length === 0 ? {} : trait[0]; - return _.assign({}, personalization); - } - - onCancelEditStatus() { - const { isEdit } = this.state; - if (isEdit) { - this.setState({ - isEdit: false, - isSubmit: false, - indexNo: null, - newWork: { - company: '', - position: '', - cityTown: '', - timePeriodFrom: '', - timePeriodTo: '', - industry: '', - working: false, - }, - formInvalid: false, - startDateInvalid: false, - startDateInvalidMsg: '', - endDateInvalid: false, - endDateDisabled: false, - endDateInvalidMsg: '', - }); - } - } - - render() { - const { - workTrait, - isEdit, - showConfirmation, - indexNo, - formInvalid, - startDateInvalid, - startDateInvalidMsg, - endDateInvalid, - endDateDisabled, - endDateInvalidMsg, - isSubmit, - windowInnerWidth, - } = this.state; - const workItems = workTrait.traits - ? workTrait.traits.data.slice() : []; - const { newWork } = this.state; - - return ( - - { - this.shouldRenderConsent() && this.renderConsent() - } - { - showConfirmation && ( - this.showConsent(this.onDeleteWork.bind(this, indexNo))} - onCancel={() => this.setState({ - showConfirmation: false, - indexNo: null, - })} - name={workTrait.traits.data[indexNo].company} - /> - ) - } -
    -

    - Work Experience -

    - -
    - -
    - { - isEdit ? (Edit workplace) - : (Jobs) - } -
    - { - workItems.length > 0 - && ( - - ) - } -
    -
    - Enter your work experience to show customers the roles and responsibilites - you have held in the past. -
    -
    -
    - - - {isSubmit && formInvalid && ( - - )} - - - - - - - - - - - - - - - - moment(date).add(-1, 'days').isAfter()} - value={newWork.timePeriodFrom} - id="date-from1" - onChange={date => this.onUpdateDate(date, 'timePeriodFrom')} - /> - { - isSubmit && formInvalid && ( - - ) - } - - - - moment(date).add(-1, 'days').isAfter()} - value={newWork.timePeriodTo} - id="date-to1" - onChange={date => this.onUpdateDate(date, 'timePeriodTo')} - anchorDirection="right" - disabled={endDateDisabled} - /> - { - isSubmit && formInvalid && ( - - ) - } - - - - - -
    -
    -
    - {!isEdit && ( - - Add Job - - )} - - { isEdit && ( - - - Edit workplace to your list - - - Cancel - - - )} -
    -
    -
    -
    -
    - ); - } -} - -Work.propTypes = { - tokenV3: PT.string.isRequired, - handle: PT.string.isRequired, - userTraits: PT.array.isRequired, - addUserTrait: PT.func.isRequired, - updateUserTrait: PT.func.isRequired, - deleteUserTrait: PT.func.isRequired, -}; diff --git a/src/shared/components/Settings/ExperienceAndSkills/WorkExperience/styles.scss b/src/shared/components/Settings/ExperienceAndSkills/WorkExperience/styles.scss deleted file mode 100644 index 5ebf2df8c6..0000000000 --- a/src/shared/components/Settings/ExperienceAndSkills/WorkExperience/styles.scss +++ /dev/null @@ -1,139 +0,0 @@ -@import "~styles/mixins"; - -.work-container { - padding: $pad-xxxxl; - margin: $margin-xxxxl 0; - background-color: $color-black-5; - border-radius: 8px; - - .title { - @include barlow-semi-bold; - - font-size: 20px; - line-height: 22px; - color: inherit; - padding: 0 0 40px; - text-transform: uppercase; - } - - .workplace-form { - display: flex; - flex-wrap: wrap; - } -} - -.form-container { - padding: $pad-xxxxl; - background-color: $color-tc-white; - border-radius: 4px; -} - -.form-title { - @include barlow-semi-bold; - - font-size: 20px; - line-height: 22px; - color: inherit; - text-transform: uppercase; - padding-bottom: $pad-xxxxl; -} - -.form-content { - display: flex; - flex-wrap: wrap; - align-items: flex-start; -} - -.form-label { - flex: 0 0 calc(50% - 13px); - padding-right: 48px; - - @include roboto-regular; - - font-size: 16px; - line-height: 26px; - color: inherit; -} - -.form-body { - flex: 0 0 calc(50% + 13px); -} - -.form-footer { - display: flex; - align-items: center; - justify-content: flex-start; - margin-left: calc(50% - 13px); - padding: $pad-sm 0; - gap: 8px 16px; - - .button { - @include roboto-bold; - - font-size: 14px; - line-height: 14px; - color: $color-turq-160; - min-height: 0; - margin: 0; - padding: 0; - background: transparent !important; - border: none; - cursor: pointer; - - &:hover, - &:active, - &:focus { - outline: none !important; - color: lighten($color-turq-160, 5%); - background: transparent !important; - box-shadow: none !important; - } - - .icon { - margin-right: $margin-xs; - } - } -} - -@include xs-to-md { - .work-container { - padding: $pad-xxl $pad-lg; - margin: $margin-xxl 0; - - .title { - @include barlow-condensed-medium; - - font-size: 27px; - line-height: 28px; - padding: 0 0 $pad-lg; - } - } - - .form-container { - padding: $pad-xxl $pad-lg; - } - - .form-title { - @include barlow-condensed-medium; - - font-size: 22px; - line-height: 24px; - padding-bottom: $pad-xxl; - } - - .form-label { - flex: 1 1 100%; - padding: 0; - margin-bottom: $margin-xxl; - font-size: 14px; - line-height: 20px; - } - - .form-body { - flex: 1 1 100%; - } - - .form-footer { - margin: 0; - } -} diff --git a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Interests/index.jsx b/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Interests/index.jsx deleted file mode 100755 index aefad8df48..0000000000 --- a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Interests/index.jsx +++ /dev/null @@ -1,242 +0,0 @@ -/** - * Child component of Settings/Profile/ renders the - * 'Basic Info' page. - */ - -import _ from 'lodash'; -import React from 'react'; -import PT from 'prop-types'; -import fetch from 'isomorphic-fetch'; -import { config } from 'topcoder-react-utils'; -import ConsentComponent from 'components/Settings/ConsentComponent'; -import { SettingBannerV2 as Collapse } from 'components/Settings/SettingsBanner'; -import { INTERESTS_AT_TOPCODER } from '../../../constants'; -import './styles.scss'; - -export default class Interests extends ConsentComponent { - constructor(props) { - super(props); - - this.save = this.save.bind(this); - this.processBasicInfo = this.processBasicInfo.bind(this); - this.loadInterests = this.loadInterests.bind(this); - this.updateInterest = this.updateInterest.bind(this); - - const { userTraits } = props; - this.state = { - allInterestData: INTERESTS_AT_TOPCODER, - interestData: [], - basicInfoTrait: this.loadBasicInfoTraits(userTraits), - profile: {}, - newBasicInfo: { - primaryInterestInTopcoder: '', - }, - }; - - this.previousInterestData = null; - } - - componentDidMount() { - const { basicInfoTrait } = this.state; - const basicInfo = basicInfoTrait.traits ? basicInfoTrait.traits.data[0] : {}; - 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); - - if (!_.isEqual(basicInfoTrait, previousBasicInfoTrait)) { - this.processBasicInfo(basicInfo, nextProps.profile); - this.setState({ - basicInfoTrait, - }); - } - if (!_.isEqual(this.state.profile, nextProps.profile)) { - this.processBasicInfo(basicInfo, nextProps.profile); - this.setState({ profile: nextProps.profile }); - } - } - - async onCheckUserTrait(traitId) { - const { handle, tokenV3 } = this.props; - let isExists = false; - await fetch(`${config.API.V5}/members/${handle}/traits?traitIds=${traitId}`, { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - Authorization: `Bearer ${tokenV3}`, - }, - }) - .then(result => result.json()) - .then((dataResponse) => { - if (dataResponse.length > 0) { - const trait = dataResponse[0]; - if (trait.createdAt) { - isExists = true; - } - } - }); - - return isExists; - } - - /** - * Show User Consent Modal - * @param {*} e event - */ - save() { - this.setState({ isSaving: true }); - this.showConsent(this.onSave.bind(this)); - } - - /** - * Save Basic Info - * @param answer user consent answer value - */ - async onSave(/* answer */) { - const { - newBasicInfo, basicInfoTrait, - } = this.state; - const { - handle, - tokenV3, - addUserTrait, - updateUserTrait, - } = this.props; - - // 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) { - const newBasicInfoTrait = { ...basicInfoTrait }; - newBasicInfoTrait.traits.data = []; - newBasicInfoTrait.traits.data.push(newBasicInfo); - await updateUserTrait(handle, 'basic_info', newBasicInfoTrait.traits.data, tokenV3); - } else { - const data = []; - data.push(newBasicInfo); - await addUserTrait(handle, 'basic_info', data, tokenV3); - } - - this.setState({ isSaving: false }); - this.previousInterestData = null; - } - - /** - * Get basic info trait - * @param userTraits the all user traits - */ - loadBasicInfoTraits = (userTraits) => { - const trait = userTraits.filter(t => t.traitId === 'basic_info'); - const basicInfo = trait.length === 0 ? {} : trait[trait.length - 1]; - return _.assign({}, basicInfo); - } - - - /** - * Process basic info state - */ - processBasicInfo = (value, profile) => { - const { newBasicInfo } = this.state; - if (_.has(profile, 'handle')) { - Object.keys(/* newBasicInfo */value).reduce((acc, key) => { - // if (_.has(value, key)) { - newBasicInfo[key] = value[key]; - // } - return acc; - }, {}); - } - this.setState({ newBasicInfo }, () => { - this.loadInterests(); - }); - } - - loadInterests() { - const { newBasicInfo: { primaryInterestInTopcoder }, allInterestData } = this.state; - - const isValid = i => allInterestData.indexOf(i) !== -1; - const isNotDeduplicated = (i, index, array) => array.indexOf(i) === index; - const compareByIndex = (a, b) => allInterestData.indexOf(a) - allInterestData.indexOf(b); - - const interestData = primaryInterestInTopcoder - .split(',') - .map(i => i.trim()) - .filter(isValid) - .filter(isNotDeduplicated) - .sort(compareByIndex); - - this.setState({ interestData }); - } - - updateInterest(item) { - const { interestData, newBasicInfo, allInterestData } = this.state; - - let updated; - if (interestData.indexOf(item) !== -1) { - updated = interestData.filter(i => i !== item); - } else { - updated = [...interestData, item].sort( - (a, b) => allInterestData.indexOf(a) - allInterestData.indexOf(b), - ); - } - - const primaryInterestInTopcoder = updated.join(','); - this.setState({ - interestData: updated, - newBasicInfo: { ...newBasicInfo, primaryInterestInTopcoder }, - }); - - this.previousInterestData = interestData; - } - - render() { - const { interestData, allInterestData } = this.state; - const canModifyTrait = !this.props.traitRequestCount; - const isSelected = item => interestData.indexOf(item) !== -1; - - return ( -
    - -
    - Interests at Topcoder -
    -
    -
    - What do you want to do at Topcoder? Compete? Learn? Earn extra money? - Get a full time gig? There are no wrong answers. -
    -
    -
    - { allInterestData.map(item => ( - canModifyTrait && this.updateInterest(item)} - tabIndex={0} - onKeyDown={() => {}} - > - {item} - - ))} -
    -
    -
    -
    -
    - ); - } -} - -Interests.propTypes = { - tokenV3: PT.string.isRequired, - handle: PT.string.isRequired, - profile: PT.shape().isRequired, - userTraits: PT.array.isRequired, - addUserTrait: PT.func.isRequired, - updateUserTrait: PT.func.isRequired, - traitRequestCount: PT.number.isRequired, -}; diff --git a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Interests/styles.scss b/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Interests/styles.scss deleted file mode 100644 index c4ad4f45df..0000000000 --- a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Interests/styles.scss +++ /dev/null @@ -1,113 +0,0 @@ -@import "~styles/mixins"; - -.form-container { - padding: $pad-xxxxl; - margin: $margin-sm 0 0; - background-color: $color-tc-white; -} - -.form-title { - @include barlow-semi-bold; - - font-size: 20px; - line-height: 22px; - color: inherit; - text-transform: uppercase; - padding-bottom: $pad-xxxxl; -} - -.form-content { - display: flex; - flex-wrap: wrap; - padding: $pad-xxxxl 0 0; - border-top: 2px solid $color-black-10; -} - -.form-label { - flex: 0 0 calc(50% - 13px); - padding-right: 48px; - - @include roboto-regular; - - font-size: 16px; - line-height: 26px; - color: inherit; -} - -.form-body { - flex: 0 0 calc(50% + 13px); -} - -.form-footer { - // empty -} - -.interestList { - display: flex; - flex-wrap: wrap; - align-items: flex-start; - justify-items: flex-start; - gap: 16px 8px; - - .interestListItem { - @include roboto-medium; - - font-size: 14px; - line-height: 16px; - letter-spacing: 0.5px; - text-transform: capitalize; - padding: ($pad-sm - 1px) ($pad-lg - 1px); - border: 1px solid $color-black-100; - border-radius: 4px; - cursor: pointer; - white-space: nowrap; - - &.selected { - color: $color-tc-white; - background-color: $color-turq-160; - border-color: $color-turq-160; - } - } - - @include xs-to-md { - gap: 8px; - - .interestListItem { - padding: ($pad-xs - 1px) ($pad-lg - 1px); - } - } -} - -@include xs-to-md { - .form-container { - padding: $pad-xxl $pad-lg; - } - - .form-title { - @include barlow-condensed-medium; - - font-size: 22px; - line-height: 24px; - padding-bottom: $pad-xxl; - } - - .form-content { - padding: $pad-xxl 0 0; - } - - .form-label { - flex: 1 1 100%; - padding: 0; - margin-bottom: $margin-xxl; - font-size: 14px; - line-height: 20px; - } - - .form-body { - flex: 1 1 100%; - } - - .form-footer { - margin: 0; - } -} diff --git a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Languages/List/Item/index.jsx b/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Languages/List/Item/index.jsx deleted file mode 100644 index 1b6b24a867..0000000000 --- a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Languages/List/Item/index.jsx +++ /dev/null @@ -1,138 +0,0 @@ -/** - * render language Item - */ -import _ from 'lodash'; -import React from 'react'; -import PT from 'prop-types'; -import { isomorphy } from 'topcoder-react-utils'; -import Tooltip from 'components/Tooltip'; - -import languageIcon from 'assets/images/profile/language.png'; - -import './styles.scss'; - -let assets; -if (isomorphy.isClientSide()) { - assets = require.context('assets/images/profile', false, /svg/); -} - -export default function Item(props) { - const { - language, - index, - onDeleteItem, - onEditItem, - } = props; - - const hasOptions = () => { - if (_.isEmpty(language.spokenLevel) && _.isEmpty(language.writtenLevel)) { - return false; - } - - return true; - }; - - const deleteTip = ( -
    -

    Delete

    -
    - ); - - const editTip = ( -
    -

    Edit

    -
    - ); - - return ( -
    -
    -
    - language -
    -
    -
    - { language.language } -
    - { - (!_.isEmpty(language.spokenLevel) || !_.isEmpty(language.writtenLevel)) && ( -
    - { - (!_.isEmpty(language.spokenLevel) && !_.isEmpty(language.writtenLevel)) && (`Spoken: ${language.spokenLevel.toUpperCase()} | Written: ${language.writtenLevel.toUpperCase()}`) - } - { - (!_.isEmpty(language.spokenLevel) && _.isEmpty(language.writtenLevel)) && (`Spoken: ${language.spokenLevel.toUpperCase()}`) - } - { - (_.isEmpty(language.spokenLevel) && !_.isEmpty(language.writtenLevel)) && (`Written: ${language.writtenLevel.toUpperCase()}`) - } -
    - ) - } - { - (!_.isEmpty(language.spokenLevel) || !_.isEmpty(language.writtenLevel)) && ( -
    - { - !_.isEmpty(language.spokenLevel) && ( -

    - {`Spoken: ${language.spokenLevel.toUpperCase()}`} -

    - ) - } - { - !_.isEmpty(language.writtenLevel) && ( -

    - {`Written: ${language.writtenLevel.toUpperCase()}`} -

    - ) - } -
    - ) - } -
    -
    - -
    - ); -} - -Item.propTypes = { - language: PT.shape().isRequired, - index: PT.number.isRequired, - onDeleteItem: PT.func.isRequired, - onEditItem: PT.func.isRequired, -}; diff --git a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Languages/List/Item/styles.scss b/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Languages/List/Item/styles.scss deleted file mode 100644 index 4744847f5e..0000000000 --- a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Languages/List/Item/styles.scss +++ /dev/null @@ -1,211 +0,0 @@ -@import "../../../../../style"; - -.container { - display: flex; - flex-direction: row; - justify-items: center; - justify-content: space-between; - align-items: center; - min-height: 96px; - width: 100%; - border-bottom: none; - background-color: $tc-white; - padding: $pad-lg; - border: 1px solid $color-black-20; - border-radius: 8px; -} - -.language-info { - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; -} - -.language-icon { - display: flex; - align-items: center; - justify-content: center; - flex: 0 0 64px; - width: 64px; - height: 64px; - background: $color-black-5; - border-radius: 4px; - margin-right: $margin-lg; - - img { - width: 32px; - height: 32px; - } -} - -.language-parameters { - @include roboto-medium; - - display: flex; - flex-direction: column; - justify-items: center; - justify-content: left; - font-size: 15px; - line-height: 20px; - text-transform: capitalize; - margin-right: 20px; - - @include upto-sm { - margin-right: 0; - } - - &.single-line { - flex-direction: row; - align-items: center; - } -} - -.parameter-first-line { - @include roboto-bold; - - color: $tc-black; - font-weight: 700; - font-size: 16px; - line-height: 20px; - letter-spacing: 0.5px; - text-transform: capitalize; - word-break: break-all; - - &.single-line { - margin-bottom: 0; - } - - @include upto-sm { - margin-bottom: 0; - } -} - -.parameter-second-line, -.parameter-second-line-mobile { - @include roboto-medium; - - color: $color-black-60; - font-weight: 400; - font-size: 16px; - line-height: 24px; - word-break: break-all; - - @include upto-sm { - display: none; - } -} - -.parameter-second-line-mobile { - display: none; - - @include upto-sm { - display: flex; - flex-direction: column; - } -} - -.tctooltiptext { - background: $tooltip-gray; - color: $tc-white; - border-radius: 8px; - padding: 10px; - - p { - @include roboto-medium; - - font-weight: 400; - font-size: 14px; - line-height: 22px; - } -} - -.tctooltiptext::after { - content: ""; - position: absolute; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; - bottom: 4px; - margin-left: -5px; - border-width: 5px 5px 0; - left: 50%; - border-top-color: $tc-black; - z-index: 1000; -} - -.operation-container { - display: flex; - flex-direction: row; - justify-content: space-between; - - .delete-wrapper { - margin-left: $margin-xl; - margin-right: $margin-xs; - - @include xs-to-sm { - margin-left: $margin-lg; - margin-right: 0; - } - - @media screen and (max-width: 320px) { - margin-right: 0; - margin-left: 6px; - } - } - - .delete { - display: flex; - flex-direction: column; - justify-items: center; - justify-content: center; - cursor: pointer; - outline-style: none; - - img { - width: 20px; - height: 20px; - } - - p { - @include roboto-regular; - - font-size: 11px; - line-height: 15px; - font-weight: 400; - color: $tc-gray-50; - - @include upto-sm { - display: none; - } - } - } - - .edit { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - cursor: pointer; - outline-style: none; - - img { - width: 20px; - height: 20px; - } - - p { - @include roboto-regular; - - font-size: 11px; - line-height: 15px; - font-weight: 400; - color: $tc-gray-50; - - @include upto-sm { - display: none; - } - } - } -} diff --git a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Languages/List/index.jsx b/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Languages/List/index.jsx deleted file mode 100644 index e9a2cc522a..0000000000 --- a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Languages/List/index.jsx +++ /dev/null @@ -1,41 +0,0 @@ -/** - * render Language list - */ -import React from 'react'; -import PT from 'prop-types'; -import Item from './Item'; - -import './styles.scss'; - -export default function LanguageList(props) { - const { - languageList, - onDeleteItem, - onEditItem, - } = props; - - return ( -
    -
      - { - languageList.items.map((language, index) => ( -
    • - -
    • - )) - } -
    -
    - ); -} - -LanguageList.propTypes = { - languageList: PT.shape().isRequired, - onDeleteItem: PT.func.isRequired, - onEditItem: PT.func.isRequired, -}; diff --git a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Languages/List/styles.scss b/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Languages/List/styles.scss deleted file mode 100644 index e78e1de213..0000000000 --- a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Languages/List/styles.scss +++ /dev/null @@ -1,26 +0,0 @@ -@import "../../../../style"; - -.container { - width: 100%; - background-color: $tc-white; - padding: 0; - margin-bottom: $margin-xxxxl; - - // &.active { - // margin-top: 20px; - - // @include upto-sm { - // margin-top: 0; - // } - // } - - ul { - display: flex; - flex-direction: column; - justify-items: center; - - li { - margin-bottom: $margin-md; - } - } -} diff --git a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Languages/dropdowns.json b/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Languages/dropdowns.json deleted file mode 100644 index 98fbe6c398..0000000000 --- a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Languages/dropdowns.json +++ /dev/null @@ -1,782 +0,0 @@ -{ - "language": [ - { - "key": "language", - "name": "Afar" - }, - { - "key": "language", - "name": "Abkhazian" - }, - { - "key": "language", - "name": "Avestan" - }, - { - "key": "language", - "name": "Afrikaans" - }, - { - "key": "language", - "name": "Akan" - }, - { - "key": "language", - "name": "Amharic" - }, - { - "key": "language", - "name": "Aragonese" - }, - { - "key": "language", - "name": "Arabic" - }, - { - "key": "language", - "name": "Assamese" - }, - { - "key": "language", - "name": "Avaric" - }, - { - "key": "language", - "name": "Aymara" - }, - { - "key": "language", - "name": "Azerbaijani" - }, - { - "key": "language", - "name": "Bashkir" - }, - { - "key": "language", - "name": "Belarusian" - }, - { - "key": "language", - "name": "Bulgarian" - }, - { - "key": "language", - "name": "Bihari languages" - }, - { - "key": "language", - "name": "Bislama" - }, - { - "key": "language", - "name": "Bambara" - }, - { - "key": "language", - "name": "Bengali" - }, - { - "key": "language", - "name": "Tibetan" - }, - { - "key": "language", - "name": "Breton" - }, - { - "key": "language", - "name": "Bosnian" - }, - { - "key": "language", - "name": "Catalan; Valencian" - }, - { - "key": "language", - "name": "Chechen" - }, - { - "key": "language", - "name": "Chamorro" - }, - { - "key": "language", - "name": "Corsican" - }, - { - "key": "language", - "name": "Cree" - }, - { - "key": "language", - "name": "Czech" - }, - { - "key": "language", - "name": "Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; Old Church Slavonic" - }, - { - "key": "language", - "name": "Chuvash" - }, - { - "key": "language", - "name": "Welsh" - }, - { - "key": "language", - "name": "Danish" - }, - { - "key": "language", - "name": "German" - }, - { - "key": "language", - "name": "Divehi; Dhivehi; Maldivian" - }, - { - "key": "language", - "name": "Dzongkha" - }, - { - "key": "language", - "name": "Ewe" - }, - { - "key": "language", - "name": "\"Greek", - "field3": "Modern (1453-)\"" - }, - { - "key": "language", - "name": "English" - }, - { - "key": "language", - "name": "Esperanto" - }, - { - "key": "language", - "name": "Spanish; Castilian" - }, - { - "key": "language", - "name": "Estonian" - }, - { - "key": "language", - "name": "Basque" - }, - { - "key": "language", - "name": "Persian" - }, - { - "key": "language", - "name": "Fulah" - }, - { - "key": "language", - "name": "Finnish" - }, - { - "key": "language", - "name": "Fijian" - }, - { - "key": "language", - "name": "Faroese" - }, - { - "key": "language", - "name": "French" - }, - { - "key": "language", - "name": "Western Frisian" - }, - { - "key": "language", - "name": "Irish" - }, - { - "key": "language", - "name": "Gaelic; Scottish Gaelic" - }, - { - "key": "language", - "name": "Galician" - }, - { - "key": "language", - "name": "Guarani" - }, - { - "key": "language", - "name": "Gujarati" - }, - { - "key": "language", - "name": "Manx" - }, - { - "key": "language", - "name": "Hausa" - }, - { - "key": "language", - "name": "Hebrew" - }, - { - "key": "language", - "name": "Hindi" - }, - { - "key": "language", - "name": "Hiri Motu" - }, - { - "key": "language", - "name": "Croatian" - }, - { - "key": "language", - "name": "Haitian; Haitian Creole" - }, - { - "key": "language", - "name": "Hungarian" - }, - { - "key": "language", - "name": "Armenian" - }, - { - "key": "language", - "name": "Herero" - }, - { - "key": "language", - "name": "Interlingua (International Auxiliary Language Association)" - }, - { - "key": "language", - "name": "Indonesian" - }, - { - "key": "language", - "name": "Interlingue; Occidental" - }, - { - "key": "language", - "name": "Igbo" - }, - { - "key": "language", - "name": "Sichuan Yi; Nuosu" - }, - { - "key": "language", - "name": "Inupiaq" - }, - { - "key": "language", - "name": "Ido" - }, - { - "key": "language", - "name": "Icelandic" - }, - { - "key": "language", - "name": "Italian" - }, - { - "key": "language", - "name": "Inuktitut" - }, - { - "key": "language", - "name": "Japanese" - }, - { - "key": "language", - "name": "Javanese" - }, - { - "key": "language", - "name": "Georgian" - }, - { - "key": "language", - "name": "Kongo" - }, - { - "key": "language", - "name": "Kikuyu; Gikuyu" - }, - { - "key": "language", - "name": "Kuanyama; Kwanyama" - }, - { - "key": "language", - "name": "Kazakh" - }, - { - "key": "language", - "name": "Kalaallisut; Greenlandic" - }, - { - "key": "language", - "name": "Central Khmer" - }, - { - "key": "language", - "name": "Kannada" - }, - { - "key": "language", - "name": "Korean" - }, - { - "key": "language", - "name": "Kanuri" - }, - { - "key": "language", - "name": "Kashmiri" - }, - { - "key": "language", - "name": "Kurdish" - }, - { - "key": "language", - "name": "Komi" - }, - { - "key": "language", - "name": "Cornish" - }, - { - "key": "language", - "name": "Kirghiz; Kyrgyz" - }, - { - "key": "language", - "name": "Latin" - }, - { - "key": "language", - "name": "Luxembourgish; Letzeburgesch" - }, - { - "key": "language", - "name": "Ganda" - }, - { - "key": "language", - "name": "Limburgan; Limburger; Limburgish" - }, - { - "key": "language", - "name": "Lingala" - }, - { - "key": "language", - "name": "Lao" - }, - { - "key": "language", - "name": "Lithuanian" - }, - { - "key": "language", - "name": "Luba-Katanga" - }, - { - "key": "language", - "name": "Latvian" - }, - { - "key": "language", - "name": "Malagasy" - }, - { - "key": "language", - "name": "Marshallese" - }, - { - "key": "language", - "name": "Maori" - }, - { - "key": "language", - "name": "Macedonian" - }, - { - "key": "language", - "name": "Malayalam" - }, - { - "key": "language", - "name": "Mongolian" - }, - { - "key": "language", - "name": "Marathi" - }, - { - "key": "language", - "name": "Malay" - }, - { - "key": "language", - "name": "Maltese" - }, - { - "key": "language", - "name": "Burmese" - }, - { - "key": "language", - "name": "Nauru" - }, - { - "key": "language", - "name": "\"Bokmål", - "field3": "Norwegian; Norwegian Bokmål\"" - }, - { - "key": "language", - "name": "\"Ndebele", - "field3": "North; North Ndebele\"" - }, - { - "key": "language", - "name": "Nepali" - }, - { - "key": "language", - "name": "Ndonga" - }, - { - "key": "language", - "name": "Dutch; Flemish" - }, - { - "key": "language", - "name": "\"Norwegian Nynorsk; Nynorsk", - "field3": "Norwegian\"" - }, - { - "key": "language", - "name": "Norwegian" - }, - { - "key": "language", - "name": "\"Ndebele", - "field3": "South; South Ndebele\"" - }, - { - "key": "language", - "name": "Navajo; Navaho" - }, - { - "key": "language", - "name": "Chichewa; Chewa; Nyanja" - }, - { - "key": "language", - "name": "Occitan (post 1500); Provençal" - }, - { - "key": "language", - "name": "Ojibwa" - }, - { - "key": "language", - "name": "Oromo" - }, - { - "key": "language", - "name": "Oriya" - }, - { - "key": "language", - "name": "Ossetian; Ossetic" - }, - { - "key": "language", - "name": "Panjabi; Punjabi" - }, - { - "key": "language", - "name": "Pali" - }, - { - "key": "language", - "name": "Polish" - }, - { - "key": "language", - "name": "Pushto; Pashto" - }, - { - "key": "language", - "name": "Portuguese" - }, - { - "key": "language", - "name": "Quechua" - }, - { - "key": "language", - "name": "Romansh" - }, - { - "key": "language", - "name": "Rundi" - }, - { - "key": "language", - "name": "Romanian; Moldavian; Moldovan" - }, - { - "key": "language", - "name": "Russian" - }, - { - "key": "language", - "name": "Kinyarwanda" - }, - { - "key": "language", - "name": "Sanskrit" - }, - { - "key": "language", - "name": "Sardinian" - }, - { - "key": "language", - "name": "Sindhi" - }, - { - "key": "language", - "name": "Northern Sami" - }, - { - "key": "language", - "name": "Sango" - }, - { - "key": "language", - "name": "Sinhala; Sinhalese" - }, - { - "key": "language", - "name": "Slovak" - }, - { - "key": "language", - "name": "Slovenian" - }, - { - "key": "language", - "name": "Samoan" - }, - { - "key": "language", - "name": "Shona" - }, - { - "key": "language", - "name": "Somali" - }, - { - "key": "language", - "name": "Albanian" - }, - { - "key": "language", - "name": "Serbian" - }, - { - "key": "language", - "name": "Swati" - }, - { - "key": "language", - "name": "\"Sotho", - "field3": "Southern\"" - }, - { - "key": "language", - "name": "Sundanese" - }, - { - "key": "language", - "name": "Swedish" - }, - { - "key": "language", - "name": "Swahili" - }, - { - "key": "language", - "name": "Tamil" - }, - { - "key": "language", - "name": "Telugu" - }, - { - "key": "language", - "name": "Tajik" - }, - { - "key": "language", - "name": "Thai" - }, - { - "key": "language", - "name": "Tigrinya" - }, - { - "key": "language", - "name": "Turkmen" - }, - { - "key": "language", - "name": "Tagalog" - }, - { - "key": "language", - "name": "Tswana" - }, - { - "key": "language", - "name": "Tonga (Tonga Islands)" - }, - { - "key": "language", - "name": "Turkish" - }, - { - "key": "language", - "name": "Tsonga" - }, - { - "key": "language", - "name": "Tatar" - }, - { - "key": "language", - "name": "Twi" - }, - { - "key": "language", - "name": "Tahitian" - }, - { - "key": "language", - "name": "Uighur; Uyghur" - }, - { - "key": "language", - "name": "Ukrainian" - }, - { - "key": "language", - "name": "Urdu" - }, - { - "key": "language", - "name": "Uzbek" - }, - { - "key": "language", - "name": "Venda" - }, - { - "key": "language", - "name": "Vietnamese" - }, - { - "key": "language", - "name": "Volapük" - }, - { - "key": "language", - "name": "Walloon" - }, - { - "key": "language", - "name": "Wolof" - }, - { - "key": "language", - "name": "Xhosa" - }, - { - "key": "language", - "name": "Yiddish" - }, - { - "key": "language", - "name": "Yoruba" - }, - { - "key": "language", - "name": "Zhuang; Chuang" - }, - { - "key": "language", - "name": "Chinese" - }, - { - "key": "language", - "name": "Zulu" - } - ], - "spokenLevel": [ - { - "key": "spokenLevel", - "name": "Basic" - }, - { - "key": "spokenLevel", - "name": "Intermediate" - }, - { - "key": "spokenLevel", - "name": "Advanced" - }, - { - "key": "spokenLevel", - "name": "Native" - } - ], - "writtenLevel": [ - { - "key": "writtenLevel", - "name": "Basic" - }, - { - "key": "writtenLevel", - "name": "Intermediate" - }, - { - "key": "writtenLevel", - "name": "Advanced" - }, - { - "key": "writtenLevel", - "name": "Native" - } - ] -} diff --git a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Languages/index.jsx b/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Languages/index.jsx deleted file mode 100644 index b7d47b7bc6..0000000000 --- a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Languages/index.jsx +++ /dev/null @@ -1,482 +0,0 @@ -/** - * Child component of Settings/Profile/ renders the - * 'Language' page. - */ -/* eslint-disable react/forbid-prop-types */ -/* eslint-disable no-nested-ternary */ -/* eslint-disable jsx-a11y/label-has-for */ -/* eslint-disable no-undef */ -/* eslint-disable react/jsx-boolean-value */ -import React from 'react'; -import PT from 'prop-types'; -import _ from 'lodash'; -import { PrimaryButton, SecondaryButton } from 'topcoder-react-ui-kit'; -import ConsentComponent from 'components/Settings/ConsentComponent'; -import ErrorMessage from 'components/Settings/ErrorMessage'; -import ConfirmationModal from 'components/Settings//ConfirmationModal'; -import FormField from 'components/Settings/FormField'; -import FormInputSelect from 'components/Settings/FormInputSelect'; -import AddItemIcon from 'assets/images/settings-add-item.svg'; -import { SettingBannerV2 as Collapse } from 'components/Settings/SettingsBanner'; -import LanguageList from './List'; -import dropdowns from './dropdowns.json'; - -import styles from './styles.scss'; - - -export default class Languages extends ConsentComponent { - constructor(props) { - super(props); - this.onHandleDeleteLanguage = this.onHandleDeleteLanguage.bind(this); - this.onDeleteLanguage = this.onDeleteLanguage.bind(this); - this.onEditLanguage = this.onEditLanguage.bind(this); - this.onUpdateSelect = this.onUpdateSelect.bind(this); - this.loadLanguageTrait = this.loadLanguageTrait.bind(this); - this.onHandleAddLanguage = this.onHandleAddLanguage.bind(this); - this.onAddLanguage = this.onAddLanguage.bind(this); - this.onUpdateInput = this.onUpdateInput.bind(this); - this.loadPersonalizationTrait = this.loadPersonalizationTrait.bind(this); - this.onCancelEditStatus = this.onCancelEditStatus.bind(this); - - const { userTraits } = props; - this.state = { - formInvalid: false, - languageNameInvalid: false, - languageNameInvalidMsg: '', - languageTrait: this.loadLanguageTrait(userTraits), - personalizationTrait: this.loadPersonalizationTrait(userTraits), - newLanguage: { - language: '', - spokenLevel: '', - writtenLevel: '', - }, - isEdit: false, - indexNo: null, - showConfirmation: false, - isSubmit: false, - }; - } - - componentWillReceiveProps(nextProps) { - const languageTrait = this.loadLanguageTrait(nextProps.userTraits); - const personalizationTrait = this.loadPersonalizationTrait(nextProps.userTraits); - this.setState({ - languageTrait, - personalizationTrait, - formInvalid: false, - languageNameInvalid: false, - languageNameInvalidMsg: '', - newLanguage: { - language: '', - spokenLevel: '', - writtenLevel: '', - }, - isSubmit: false, - }); - } - - /** - * Update input value - * @param e event - */ - onUpdateInput(e) { - const { newLanguage: oldLanguage } = this.state; - const newLanguage = { ...oldLanguage }; - newLanguage[e.target.name] = e.target.value.trim(); - this.setState({ newLanguage, isSubmit: false }); - } - - onHandleDeleteLanguage(indexNo) { - this.setState({ - showConfirmation: true, - indexNo, - }); - } - - /** - * Delete language by index - * @param indexNo the language index no - */ - onDeleteLanguage(indexNo) { - const { languageTrait } = this.state; - const newLanguageTrait = { ...languageTrait }; - newLanguageTrait.traits.data.splice(indexNo, 1); - this.setState({ - languageTrait: newLanguageTrait, - isEdit: false, - formInvalid: false, - languageNameInvalid: false, - languageNameInvalidMsg: '', - }); - - const { - handle, - tokenV3, - updateUserTrait, - deleteUserTrait, - } = this.props; - - if (newLanguageTrait.traits.data.length > 0) { - updateUserTrait(handle, 'languages', newLanguageTrait.traits.data, tokenV3); - } else { - deleteUserTrait(handle, 'languages', tokenV3); - } - this.setState({ - showConfirmation: false, - indexNo: null, - isSubmit: false, - }); - } - - /** - * Edit language by index - * @param indexNo the language index no - */ - onEditLanguage(indexNo) { - const { languageTrait } = this.state; - this.setState({ - newLanguage: { - language: languageTrait.traits.data[indexNo].language, - spokenLevel: _.isEmpty(languageTrait.traits.data[indexNo].spokenLevel) ? '' : languageTrait.traits.data[indexNo].spokenLevel, - writtenLevel: _.isEmpty(languageTrait.traits.data[indexNo].writtenLevel) ? '' : languageTrait.traits.data[indexNo].writtenLevel, - }, - isEdit: true, - indexNo, - formInvalid: false, - languageNameInvalid: false, - languageNameInvalidMsg: '', - isSubmit: false, - }); - } - - /** - * Check form fields value, - * Invalid value, can not save - */ - onCheckFormValue() { - const { - languageTrait, newLanguage, isEdit, indexNo, - } = this.state; - - let invalid = false; - let languageNameInvalid = false; - let languageNameInvalidMsg = ''; - - if (_.isEmpty(newLanguage.language.trim())) { - invalid = true; - languageNameInvalid = true; - languageNameInvalidMsg = 'Language cannot be empty'; - } - - if (isEdit) { - const result = _.filter(languageTrait.traits.data, (item, index) => ( - item.language.toLowerCase() === newLanguage.language.toLowerCase() && index !== indexNo - )); - - if (result && result.length > 0) { - invalid = true; - languageNameInvalid = true; - languageNameInvalidMsg = 'Language already added'; - } - } else if (!_.isEmpty(languageTrait)) { - const result = _.filter(languageTrait.traits.data, item => ( - item.language.toLowerCase() === newLanguage.language.toLowerCase() - )); - - if (result && result.length > 0) { - invalid = true; - languageNameInvalid = true; - languageNameInvalidMsg = 'Language already added'; - } - } - - this.setState({ - formInvalid: invalid, - languageNameInvalid, - languageNameInvalidMsg, - }); - return invalid; - } - - onHandleAddLanguage(e) { - if (e) e.preventDefault(); - this.setState({ isSubmit: true }); - if (this.onCheckFormValue()) { - return; - } - this.showConsent(this.onAddLanguage.bind(this)); - } - - /** - * Add new language - * @param e form submit event - * @param answer user consent answer value - */ - onAddLanguage(answer) { - const { - newLanguage, personalizationTrait, isEdit, indexNo, - } = this.state; - - const { - handle, - tokenV3, - updateUserTrait, - addUserTrait, - } = this.props; - const { languageTrait } = this.state; - const language = _.clone(newLanguage); - if (_.isEmpty(language.spokenLevel)) { - delete language.spokenLevel; - } - if (_.isEmpty(language.writtenLevel)) { - delete language.writtenLevel; - } - if (languageTrait.traits && languageTrait.traits.data.length > 0) { - const newLanguageTrait = _.cloneDeep(languageTrait); - - if (isEdit) { - newLanguageTrait.traits.data.splice(indexNo, 1, language); - } else { - newLanguageTrait.traits.data.push(language); - } - - updateUserTrait(handle, 'languages', newLanguageTrait.traits.data, tokenV3); - } else { - const newLanguages = []; - newLanguages.push(language); - addUserTrait(handle, 'languages', newLanguages, tokenV3); - } - const empty = { - language: '', - spokenLevel: '', - writtenLevel: '', - }; - this.setState({ - newLanguage: empty, - isEdit: false, - indexNo: null, - isSubmit: false, - }); - // save personalization - if (_.isEmpty(personalizationTrait)) { - const personalizationData = { userConsent: answer }; - addUserTrait(handle, 'personalization', [personalizationData], tokenV3); - } else { - const trait = personalizationTrait.traits.data[0]; - if (trait.userConsent !== answer) { - const personalizationData = { userConsent: answer }; - updateUserTrait(handle, 'personalization', [personalizationData], tokenV3); - } - } - } - - /** - * Update select value - * @param option selected value - */ - onUpdateSelect(option) { - if (option) { - const { newLanguage: oldLanguage } = this.state; - const newLanguage = { ...oldLanguage }; - newLanguage[option.key] = option.name; - this.setState({ newLanguage, isSubmit: false }); - } - } - - onCancelEditStatus() { - const { isEdit } = this.state; - if (isEdit) { - this.setState({ - isEdit: false, - indexNo: null, - isSubmit: false, - formInvalid: false, - languageNameInvalid: false, - languageNameInvalidMsg: '', - newLanguage: { - language: '', - spokenLevel: '', - writtenLevel: '', - }, - }); - } - } - - /** - * Get language trait - * @param userTraits the all user traits - */ - loadLanguageTrait = (userTraits) => { - const trait = userTraits.filter(t => t.traitId === 'languages'); - const languages = trait.length === 0 ? {} : trait[0]; - return _.assign({}, languages); - } - - /** - * Get personalization trait - * @param userTraits the all user traits - */ - loadPersonalizationTrait = (userTraits) => { - const trait = userTraits.filter(t => t.traitId === 'personalization'); - const personalization = trait.length === 0 ? {} : trait[0]; - return _.assign({}, personalization); - }; - - render() { - const { - languageTrait, - isEdit, - formInvalid, - showConfirmation, - indexNo, - languageNameInvalid, - languageNameInvalidMsg, - isSubmit, - } = this.state; - const languageItems = languageTrait.traits - ? languageTrait.traits.data.slice() : []; - const { newLanguage } = this.state; - - return ( - - { - this.shouldRenderConsent() && this.renderConsent() - } - { - showConfirmation && ( - this.showConsent(this.onDeleteLanguage.bind(this, indexNo))} - onCancel={() => this.setState({ - showConfirmation: false, - indexNo: null, - })} - name={languageTrait.traits.data[indexNo].language} - /> - ) - } -
    - -

    - Spoken Languages -

    - { - languageItems.length > 0 - && ( - - ) - } -
    -
    - Let customers know the langagues you speak. - Multilingual? Magnifique. -
    -
    -
    - - - {isSubmit && formInvalid && ( - - ) - } - - - - { - if (option) { - this.onUpdateSelect(option); - } else { - this.onUpdateSelect({ key: 'spokenLevel', name: '' }); - } - }} - placeholder="Level" - labelKey="name" - valueKey="name" - clearable={false} - /> - - - - { - if (option) { - this.onUpdateSelect(option); - } else { - this.onUpdateSelect({ key: 'writtenLevel', name: '' }); - } - }} - placeholder="Level" - labelKey="name" - valueKey="name" - clearable={false} - /> - -
    -
    -
    - {!isEdit && ( - - Add language to your list - - )} - - {isEdit && ( - - - Edit language to your list - - - Cancel - - - )} -
    -
    -
    -
    -
    - ); - } -} - -Languages.propTypes = { - tokenV3: PT.string.isRequired, - handle: PT.string.isRequired, - userTraits: PT.array.isRequired, - addUserTrait: PT.func.isRequired, - updateUserTrait: PT.func.isRequired, - deleteUserTrait: PT.func.isRequired, - // settingsUI: PT.shape().isRequired, -}; diff --git a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Languages/styles.scss b/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Languages/styles.scss deleted file mode 100644 index b60b935439..0000000000 --- a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Languages/styles.scss +++ /dev/null @@ -1,109 +0,0 @@ -@import "~styles/mixins"; - -.form-container { - padding: $pad-xxxxl; - background-color: $color-tc-white; - border-radius: 4px; - - .language-form { - display: flex; - flex-wrap: wrap; - } -} - -.form-title { - @include barlow-semi-bold; - - font-size: 20px; - line-height: 22px; - color: inherit; - text-transform: uppercase; - padding-bottom: $pad-xxxxl; -} - -.form-content { - display: flex; - flex-wrap: wrap; - align-items: flex-start; -} - -.form-label { - flex: 0 0 calc(50% - 13px); - padding-right: 230px; - - @include roboto-regular; - - font-size: 16px; - line-height: 26px; - color: inherit; -} - -.form-body { - flex: 0 0 calc(50% + 13px); -} - -.form-footer { - display: flex; - align-items: center; - justify-content: flex-start; - margin-left: calc(50% - 13px); - padding: $pad-sm 0; - gap: 8px 16px; - - .button { - @include roboto-bold; - - font-size: 14px; - line-height: 14px; - color: $color-turq-160; - min-height: 0; - margin: 0; - padding: 0; - background: transparent !important; - border: none; - cursor: pointer; - - &:hover, - &:active, - &:focus { - outline: none !important; - color: lighten($color-turq-160, 5%); - background: transparent !important; - box-shadow: none !important; - } - - .icon { - margin-right: $margin-xs; - } - } -} - -@include xs-to-md { - .form-container { - padding: $pad-xxl $pad-lg; - } - - .form-title { - @include barlow-condensed-medium; - - font-size: 22px; - line-height: 24px; - padding-bottom: $pad-xxl; - } - - .form-label { - flex: 1 1 100%; - padding: 0; - margin-bottom: $margin-xxl; - font-size: 14px; - line-height: 20px; - } - - .form-body { - flex: 1 1 100%; - } - - .form-footer { - margin: 0; - } -} diff --git a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/AddSkillsModal/index.jsx b/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/AddSkillsModal/index.jsx deleted file mode 100755 index 67d192c4fb..0000000000 --- a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/AddSkillsModal/index.jsx +++ /dev/null @@ -1,140 +0,0 @@ -import React from 'react'; -import PT from 'prop-types'; -import _ from 'lodash'; -import { Modal, PrimaryButton, GhostButton } from 'topcoder-react-ui-kit'; -import FormField from 'components/Settings/FormField'; -import FormInputSelect from 'components/Settings/FormInputSelect'; -import IconClose from 'assets/images/icon-close.svg'; -import RemoveTagIcon from 'assets/images/icon-x-cancel.svg'; -import styles from './styles.scss'; - -export default function AddSkillsModal({ - disabled, - editingSkills, - lookupSkills, - userSkills, - onClose, - onSave, - setEditingSkills, -}) { - const [tempStr, setTempStr] = React.useState(''); - const [displayingSkills, setDisplayingSkills] = React.useState([]); - - // onInit - React.useEffect(() => { - setEditingSkills([...userSkills]); - setDisplayingSkills([...userSkills]); - }, [userSkills]); - - const findSkill = (arr, skill) => arr && arr.find(a => a.id === skill.id); - - const handleSkillSelect = (skill) => { - setEditingSkills([...editingSkills, skill]); - }; - const handleSkillUnselect = (skill) => { - setEditingSkills(editingSkills.filter(i => i.id !== skill.id)); - }; - const toggleSkillSelection = (skill) => { - if (findSkill(editingSkills, skill)) { - handleSkillUnselect(skill); - } else { - handleSkillSelect(skill); - } - }; - const updateDisplayingSkills = (skill) => { - if (!findSkill(displayingSkills, skill)) { - setDisplayingSkills([...displayingSkills, skill]); - } - }; - - const allDisplayingSkills = displayingSkills; - - const lookupSkillsOptions = lookupSkills - .filter(skill => !findSkill(allDisplayingSkills, skill)) - .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 selected = findSkill(editingSkills, skill); - return ( -
  • - !selected && toggleSkillSelection(skill)} - tabIndex={0} - onKeyDown={() => { }} - > - {_.truncate(skill.name, { length: 18, separator: ' ' })} - - selected && toggleSkillSelection(skill)} - styleName="close" - tabIndex={0} - onKeyDown={() => { }} - > - - -
  • - ); - }); - - return ( - -
    -
    -

    - Add Skills - - - -

    -
    -

    Select Skills

    - - - { - handleSkillSelect(skill); - setTempStr(skill.name); - updateDisplayingSkills(skill); - }} - matchPos="any" - matchProp="name" - labelKey="name" - valueKey="name" - placeholder="Add new skill" - clearable={false} - disabled={disabled} - value={tempStr} - /> - - -
      - {skillList} -
    -
    -
    - - Save - -
    -
    -
    -
    - ); -} - -AddSkillsModal.propTypes = { - disabled: PT.bool.isRequired, - editingSkills: PT.arrayOf(PT.shape()).isRequired, - lookupSkills: PT.arrayOf(PT.shape()).isRequired, - userSkills: PT.arrayOf(PT.shape()).isRequired, - onClose: PT.func.isRequired, - onSave: PT.func.isRequired, - setEditingSkills: PT.func.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 deleted file mode 100755 index b48467e069..0000000000 --- a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/AddSkillsModal/styles.scss +++ /dev/null @@ -1,270 +0,0 @@ -@import "~styles/mixins"; - -.modal-overlay { - background-color: rgba($color-tc-black, 0.85); -} - -.modal { - display: flex; - flex-direction: column; - align-items: center; - justify-content: flex-start; - width: 100%; - height: 100%; - max-width: none; - max-height: none; - border-radius: 8px; - overflow-y: auto; - background: none; - top: 0; - left: 0; - transform: none; - - .close { - padding: 0; - margin: 0 0 0 auto; - min-height: 0; - } -} - -.modal-dialog { - flex: 0 0 auto; - display: flex; - flex-direction: column; - margin: auto; -} - -.modal-content { - flex: auto; - display: flex; - flex-direction: column; - color: $color-black-100; - max-width: 794px; - background-color: $color-tc-white; - border-radius: 8px; - box-shadow: 0 4px 4px rgba(0, 0, 0, 0.25); - margin: 32px; - width: calc(100% - 64px); - min-height: 700px; - min-width: 40vw; -} - -.modal-header { - @include barlow-condensed-medium; - - font-size: 34px; - line-height: 32px; - text-transform: uppercase; - display: flex; - align-items: center; - padding: $pad-xxxl $pad-xxxxl $pad-xxxxl; - border-radius: 8px 8px 0 0; -} - -.modal-body { - flex: auto; - display: flex; - padding: 0 $pad-xxxxl; - flex-direction: column; -} - -.modal-footer { - display: flex; - flex-direction: row-reverse; - align-items: flex-end; - padding: $pad-xxxxl 0; - margin: $margin-xxxl $margin-xxxxl 0; - border-top: 2px solid $color-black-10; - border-radius: 0 0 8px 8px; - - @include xs-to-md { - padding: $pad-lg; - margin: 0 $margin-lg 0; - } -} - -@include xs-to-md { - .modal { - padding: 0; - overflow-y: auto; - height: 100%; - max-height: 100%; - border: none; - box-shadow: none; - border-radius: 0; - z-index: 999999; - } - - .modal-content { - min-height: 568px; - } - - .modal-header { - @include barlow-semi-bold; - - font-size: 16px; - line-height: 20px; - padding: $pad-lg; - border-radius: 0; - } - - .modal-body { - padding: 0 $pad-lg; - flex-direction: column; - } - - .modal-footer { - padding: $pad-lg; - margin: 0 $margin-lg 0; - border-radius: 0; - } -} - -@include xs-to-sm { - .modal-content { - width: 100%; - margin: 0; - border-radius: 0; - } -} - -.tabs { - border-right: 2px solid $color-black-10; - - li { - @include roboto-regular; - - font-weight: 500; - font-size: 16px; - line-height: 20px; - letter-spacing: 0.5px; - color: $color-black-80; - padding: $pad-sm $pad-xxxxl $pad-sm 0; - margin-top: -$margin-sm; - white-space: nowrap; - cursor: pointer; - - &.active, - &:hover { - color: $color-turq-160; - } - } -} - -.tabContent { - flex: 0 0 auto; - padding-left: $pad-xxxxl; - width: calc(100% - 134px); - - .title { - @include barlow-semi-bold; - - font-size: 20px; - line-height: 20px; - color: inherit; - margin-bottom: $margin-xxl; - } -} - -@include xs-to-md { - .tabs { - border: none; - } - - .tabContent { - flex: 1 1 auto; - display: flex; - flex-direction: column; - width: 100%; - padding: $pad-lg 0 0; - margin: $margin-sm 0 0; - border-top: 2px solid $color-black-10; - - .title { - font-size: 16px; - line-height: 20px; - margin-bottom: margin-lg; - } - } -} - -.skillList { - display: flex; - flex-wrap: wrap; - align-content: flex-start; - gap: 8px 4px; - min-height: 152px; - - @include xs-to-md { - flex: 1 1 auto; - height: calc(100vh - 450px); - overflow-y: auto; - } - - @include xs-to-sm { - height: calc(100vh - 386px); - } -} - -.skillListItem { - @include roboto-regular; - - font-weight: 500; - font-size: 14px; - line-height: 20px; - letter-spacing: 0.5px; - color: $color-tc-white; - text-transform: capitalize; - white-space: nowrap; - display: flex; - align-items: center; - gap: 4px; - padding: $pad-xs $pad-sm; - background-color: $color-teal-140; - border: 1px solid $color-teal-140; - border-radius: 4px; - cursor: default; - - .close { - cursor: pointer; - - svg { - display: block; - } - } - - &.non-removable { - color: $color-black-100; - background-color: $color-tc-white; - - .close { - display: none; - } - - &.selected { - color: $color-tc-white; - background-color: $color-teal-140; - - .close { - display: block; - } - } - } -} - -.button-save { - @include roboto-bold; - - font-weight: 700; - font-size: 16px; - line-height: 24px; - border-radius: 50px !important; - background: $color-turq-160 !important; - color: $color-tc-white !important; - text-transform: uppercase; - - @include xs-to-md { - font-size: 14px; - line-height: 20px; - } -} diff --git a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/index.jsx b/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/index.jsx deleted file mode 100755 index a08ae7644e..0000000000 --- a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/index.jsx +++ /dev/null @@ -1,444 +0,0 @@ -/* eslint-disable max-len */ -/** - * Child component of Settings/Profile renders "Skills" section of profile setting page. - */ - -import _ from 'lodash'; -import React from 'react'; -import PT from 'prop-types'; -import { PrimaryButton } from 'topcoder-react-ui-kit'; -import ConsentComponent from 'components/Settings/ConsentComponent'; - -import VerifiedBadgeIcon from 'assets/images/verified-skill-badge-green.svg'; -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 { 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); - this.onHandleAddSkill = this.onHandleAddSkill.bind(this); - this.onHandleDeleteSkills = this.onHandleDeleteSkills.bind(this); - this.onAddSkill = this.onAddSkill.bind(this); - this.toggleSkill = this.toggleSkill.bind(this); - this.loadPersonalizationTrait = this.loadPersonalizationTrait.bind(this); - this.lastValidInputPosition = 0; - this.setEditingSkills = this.setEditingSkills.bind(this); - this.onModalClose = this.onModalClose.bind(this); - this.onModalSave = this.onModalSave.bind(this); - - const { userTraits } = props; - this.state = { - personalizationTrait: this.loadPersonalizationTrait(userTraits), - userSkills: [], - editingSkills: [], - newSkill: { - design: [], - develop: [], - data_science: [], - qa: [], - }, - skillsToDelete: null, - showConfirmation: false, - showAddSkillsModal: null, - }; - } - - componentWillMount() { - this.processUserSkills(this.props); - } - - componentDidUpdate() { - this.removeHover(); - } - - componentWillReceiveProps(nextProps) { - const personalizationTrait = this.loadPersonalizationTrait(nextProps.userTraits); - this.setState({ - personalizationTrait, - userSkills: [], - editingSkills: [], - newSkill: { - design: [], - develop: [], - data_science: [], - qa: [], - }, - }); - - this.processUserSkills(nextProps); - } - - /** - * Show User Consent Modal - * @param e event - */ - onHandleAddSkill(selectedSkill) { - this.showConsent(this.onAddSkill.bind(this, selectedSkill)); - } - - setEditingSkills(updatedEdittingSkills) { - this.setState({ - editingSkills: updatedEdittingSkills, - }); - } - - /** - * Add new skill - * @param answer user consent answer value - */ - onAddSkill(selectedSkill, answer) { - const { newSkill, personalizationTrait } = this.state; - const { - handle, - tokenV3, - addUserSkill, - addUserTrait, - updateUserTrait, - } = this.props; - - let category = ''; - switch (selectedSkill.categories[0]) { - case 'develop': - category = 'develop'; - break; - case 'data_science': - category = 'data_science'; - break; - case 'design': - category = 'design'; - break; - case 'qa': - category = 'qa'; - break; - default: - category = 'design'; - break; - } - - const index = _.findIndex(newSkill[category], skill => ( - skill.name.toLowerCase() === selectedSkill.name.toLowerCase() - )); - - if (index > -1) { - return; - } - - newSkill[category].push(selectedSkill); - addUserSkill(handle, selectedSkill, tokenV3); - // save personalization - if (_.isEmpty(personalizationTrait)) { - const personalizationData = { userConsent: answer }; - addUserTrait(handle, 'personalization', [personalizationData], tokenV3); - } else { - const trait = personalizationTrait.traits.data[0]; - if (trait.userConsent !== answer) { - const personalizationData = { userConsent: answer }; - updateUserTrait(handle, 'personalization', [personalizationData], tokenV3); - } - } - } - - onHandleDeleteSkills(skill) { - const skillsToDelete = Array.isArray(skill) ? skill : [skill]; - this.setState({ - showConfirmation: true, - skillsToDelete, - }); - } - - /** - * Get personalization trait - * @param userTraits the all user traits - */ - loadPersonalizationTrait = (userTraits) => { - const trait = userTraits.filter(t => t.traitId === 'personalization'); - const personalization = trait.length === 0 ? {} : trait[0]; - return _.assign({}, personalization); - } - - /** - * Process user skills - */ - processUserSkills = (props) => { - const { lookupData, skills } = props; - - // All lookup skills - const lookupSkills = lookupData.skillTags || []; - - // Construct user skills - const filterUserSkills = []; - - const arraySkill = _.map(skills, (skill, tagId) => ({ tagId: Number(tagId), ...skill })); - const design = []; - const develop = []; - const dataScience = []; - const qa = []; - if (arraySkill.length > 0) { - for (let i = 0; i < arraySkill.length; i += 1) { - const result = _.filter(lookupSkills, skill => ( - skill.id === arraySkill[i].tagId - )); - if (result && result.length > 0) { - result[0].sources = arraySkill[i].sources; - filterUserSkills.push(result[0]); - if (_.some(result[0].categories, category => category.toLowerCase() === 'design')) { - design.push(result[0]); - } - if (_.some(result[0].categories, category => category.toLowerCase() === 'develop')) { - develop.push(result[0]); - } - if (_.some(result[0].categories, category => category.toLowerCase() === 'data_science')) { - dataScience.push(result[0]); - } - if (_.some(result[0].categories, category => category.toLowerCase() === 'qa')) { - qa.push(result[0]); - } - } - } - - const { newSkill } = this.state; - newSkill.design = design.length > 0 ? design.slice() : []; - newSkill.develop = develop.length > 0 ? develop.slice() : []; - newSkill.data_science = dataScience.length > 0 ? dataScience.slice() : []; - newSkill.qa = qa.length > 0 ? qa.slice() : []; - - this.setState({ newSkill, userSkills: filterUserSkills }); - } - } - - removeHover = () => { - setTimeout(() => { - const btn = document.querySelector('a:hover'); - if (btn) { - const par = btn.parentNode; - const next = btn.nextSibling; - par.removeChild(btn); - setTimeout(() => { par.insertBefore(btn, next); }, 0); - } - }, 100); - } - - /** - * Toggle Skill to delete selected skill - */ - toggleSkill = (skillsToDelete/* , consentAnswer */) => { - const { newSkill } = this.state; - const { - handle, - tokenV3, - deleteUserSkill, - } = this.props; - - skillsToDelete.forEach((skill) => { - let category = ''; - switch (skill.categories[0]) { - case 'develop': - category = 'develop'; - break; - case 'data_science': - category = 'data_science'; - break; - case 'design': - category = 'design'; - break; - case 'qa': - category = 'qa'; - break; - default: - category = 'design'; - break; - } - const result = _.remove(newSkill[category], item => ( - item.name.toLowerCase() !== skill.name.toLowerCase() - )); - newSkill[category] = result.length > 0 ? result.slice() : []; - deleteUserSkill(handle, skill, tokenV3); - }); - - this.setState({ - skillsToDelete: null, - showConfirmation: false, - }); - }; - - onModalClose() { - this.setState({ showAddSkillsModal: null }); - } - - onModalSave() { - this.onModalClose(); - - const { userSkills, editingSkills } = this.state; - - const diffAdd = (target, source) => target.filter(t => !source.find(s => s.id === t.id)); - const diffRemove = (target, source) => source.filter(s => !target.find(t => t.id === s.id)); - - const toAdd = diffAdd(editingSkills, userSkills); - const toRemove = diffRemove(editingSkills, userSkills); - - toAdd.forEach(skill => this.onAddSkill(skill)); - if (toRemove.length) { - this.onHandleDeleteSkills(toRemove); - } - } - - render() { - const { - lookupData, - } = this.props; - - const { - userSkills, - showConfirmation, - skillsToDelete, - editingSkills, - showAddSkillsModal, - } = this.state; - - const canModifyTrait = !this.props.traitRequestCount; - // All lookup skills - const allSkills = lookupData.skillTags ? lookupData.skillTags : []; - let list = userSkills; - list = _.orderBy(list, [skill => skill.name.toLowerCase()], ['asc']); // Use Lodash to sort array by 'name' - - // // filter out already added skills - const lookupSkills = _.sortBy( - _.filter(allSkills, skill => _.findIndex(userSkills, l => l.id === skill.id) === -1), - s => s.name, - ); - - const skillList = ( - - ); - - return ( - - { - this.shouldRenderConsent() && this.renderConsent() - } - { - showConfirmation && ( - this.showConsent(this.toggleSkill - .bind(this, skillsToDelete))} - onCancel={() => this.setState({ - showConfirmation: false, - skillsToDelete: null, - })} - name={skillsToDelete.map(s => s.name).join(', ')} - /> - ) - } - {showAddSkillsModal && ( - - )} - -
    - -
    = MIN_SKILLS_TO_REMIND ? 'center' : 'flex-start' }}> -

    Skills

    - { - userSkills.length >= MIN_SKILLS_TO_REMIND && - } -
    - -
    -
    - Add skills to your profile. You can add or update your skills any time. -
    - -
    - { - 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} -
    - -
    - this.setState({ showAddSkillsModal: 'design' })} - disabled={!canModifyTrait} - theme={{ button: styles['button-add'] }} - > - Add Skills - -
    -
    -
    -
    -
    - ); - } -} - -Skills.defaultProps = { - skills: {}, -}; - -Skills.propTypes = { - handle: PT.string.isRequired, - tokenV3: PT.string.isRequired, - lookupData: PT.shape().isRequired, - addUserSkill: PT.func.isRequired, - deleteUserSkill: PT.func.isRequired, - /* eslint-disable react/no-unused-prop-types */ - skills: PT.shape(), - userTraits: PT.array.isRequired, - traitRequestCount: PT.number.isRequired, - updateUserTrait: PT.func.isRequired, -}; diff --git a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/styles.scss b/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/styles.scss deleted file mode 100644 index afd9ae5234..0000000000 --- a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/Skills/styles.scss +++ /dev/null @@ -1,218 +0,0 @@ -/* stylelint-disable no-descending-specificity */ -@import "~styles/mixins"; - -.skillList { - display: flex; - flex-wrap: wrap; - align-items: flex-start; - justify-items: flex-start; - gap: 8px 4px; - margin-bottom: $margin-lg; -} - -.skillListItem { - @include roboto-medium; - - font-size: 14px; - line-height: 16px; - letter-spacing: 0.5px; - color: $color-tc-white; - text-transform: capitalize; - white-space: nowrap; - display: flex; - align-items: center; - gap: 4px; - padding: ($pad-xs - 1px) ($pad-sm - 1px); - background-color: $color-teal-140; - border: 1px solid $color-teal-140; - border-radius: 4px; - cursor: default; - - .close { - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; - - svg { - width: 16px; - height: 16px; - display: block; - } - } - - .verified-badge { - margin-right: $margin-xs; - } -} - -.form-container { - padding: $pad-xxxxl; - margin: $margin-sm 0; - 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; - - font-size: 20px; - line-height: 22px; - color: inherit; - text-transform: uppercase; - margin-right: 32px; -} - -.form-content { - display: flex; - flex-wrap: wrap; - padding: $pad-xxxxl 0 0; - border-top: 2px solid $color-black-10; -} - -.form-label { - flex: 0 0 calc(50% - 13px); - padding-right: 48px; - - @include roboto-regular; - - font-size: 16px; - line-height: 26px; - color: inherit; -} - -.form-body { - flex: 0 0 calc(50% + 13px); - display: flex; - flex-direction: column; -} - -.form-footer { - display: flex; - flex-wrap: wrap; - justify-content: flex-start; - align-items: center; - margin-left: calc(50% - 13px); - padding: $pad-sm 0; - gap: $margin-sm 40px; - - .button-add { - @include roboto-bold; - - font-size: 14px; - line-height: 14px; - color: $color-turq-160; - min-height: 0; - margin: 0; - padding: 0; - background: transparent !important; - border: none; - cursor: pointer; - - &:hover, - &:active, - &:focus { - outline: none !important; - color: lighten($color-turq-160, 5%); - background: transparent !important; - box-shadow: none !important; - } - - .icon { - margin-right: $margin-xs; - } - } -} - -.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; - } - - .title-wrap { - p { - font-size: 14px; - line-height: 24px; - } - } - - .form-title { - @include barlow-condensed-medium; - - font-size: 22px; - line-height: 24px; - } - - .form-content { - padding: $pad-xxl 0 0; - } - - .form-label { - flex: 1 1 100%; - padding: 0; - margin-bottom: $margin-xxl; - font-size: 14px; - line-height: 20px; - } - - .form-body { - flex: 1 1 100%; - } - - .form-footer { - padding: 0; - margin: 0; - gap: 0; - display: flex; - flex-direction: column; - align-items: flex-start; - - .button-add { - padding: $pad-sm 0; - } - } -} - -@include xs-to-sm { - .skill-note { - flex-direction: column; - - svg { - margin-bottom: $margin-md; - } - } -} diff --git a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/index.jsx b/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/index.jsx deleted file mode 100644 index f5caa0b13e..0000000000 --- a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/index.jsx +++ /dev/null @@ -1,35 +0,0 @@ -import React from 'react'; -import Interests from './Interests'; -import Languages from './Languages'; -import Skills from './Skills'; - -import './styles.scss'; - -export default class WorkSkills extends React.Component { - constructor(props) { - super(props); - this.interestsRef = React.createRef(); - this.languagesRef = React.createRef(); - this.skillsRef = React.createRef(); - } - - render() { - return ( -
    -

    About You

    - - - -
    - ); - } -} diff --git a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/styles.scss b/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/styles.scss deleted file mode 100644 index 04e4ac42ef..0000000000 --- a/src/shared/components/Settings/ExperienceAndSkills/WorkSkills/styles.scss +++ /dev/null @@ -1,33 +0,0 @@ -@import "~styles/mixins"; - -.workSkills { - padding: $pad-xxxxl; - margin: $margin-xxxxl 0; - background-color: $color-black-5; - border-radius: 8px; - - .title { - @include barlow-semi-bold; - - font-size: 20px; - line-height: 22px; - color: inherit; - padding-bottom: 40px; - text-transform: uppercase; - } -} - -@include xs-to-md { - .workSkills { - padding: $pad-xxl $pad-lg; - margin: $margin-xxl 0; - - .title { - @include barlow-condensed-medium; - - font-size: 27px; - line-height: 28px; - padding: 0 0 $pad-lg; - } - } -} diff --git a/src/shared/components/Settings/ExperienceAndSkills/index.jsx b/src/shared/components/Settings/ExperienceAndSkills/index.jsx deleted file mode 100644 index 461ca66cff..0000000000 --- a/src/shared/components/Settings/ExperienceAndSkills/index.jsx +++ /dev/null @@ -1,121 +0,0 @@ -/* eslint-disable prefer-destructuring */ -import React from 'react'; -import PT from 'prop-types'; -import _ from 'lodash'; -import { PrimaryButton } from 'topcoder-react-ui-kit'; -import WorkExperience from './WorkExperience'; -import WorkSkills from './WorkSkills'; -import ErrorWrapper from '../ErrorWrapper'; - -import styles from './styles.scss'; - -export default class ExperienceAndSkills extends React.Component { - constructor(props) { - super(props); - this.save = this.save.bind(this); - this.workExperienceRef = React.createRef(); - this.workSkillsRef = React.createRef(); - } - - componentWillReceiveProps(nextProps) { - const { isSaving, setIsSaving } = this.props; - if (isSaving && nextProps.userTraits) { - setIsSaving(false); - } - } - - save() { - const { isSaving, setIsSaving } = this.props; - if (isSaving) { - return; - } - - const newWork = this.workExperienceRef.current.state.newWork; - const newWorkDirty = newWork.company !== '' - || newWork.position !== '' - || newWork.cityTown !== '' - || newWork.timePeriodFrom !== '' - || newWork.timePeriodTo !== '' - || newWork.industry !== '' - || newWork.working; - - const newLanguage = this.workSkillsRef.current.languagesRef.current.state.newLanguage; - const newLanguageDirty = newLanguage.language !== '' - || newLanguage.spokenLevel !== '' - || newLanguage.writtenLevel !== ''; - - const interestData = this.workSkillsRef.current.interestsRef.current.state.interestData; - const previousInterestData = this.workSkillsRef.current.interestsRef.current - .previousInterestData; - const interestDataDirty = previousInterestData - && !_.isEqual(interestData, previousInterestData); - - let valid = true; - let dirty; - - if (newWorkDirty) { - valid = valid && !this.workExperienceRef.current.onCheckFormValue(newWork); - dirty = true; - } - - if (newLanguageDirty) { - valid = valid && !this.workSkillsRef.current.languagesRef.current - .onCheckFormValue(newLanguage); - dirty = true; - } - - if (interestDataDirty) { - valid = valid && true; - dirty = true; - } - - if (newWorkDirty) this.workExperienceRef.current.onHandleAddWork(); - if (newLanguageDirty) this.workSkillsRef.current.languagesRef.current.onHandleAddLanguage(); - if (interestDataDirty && valid) this.workSkillsRef.current.interestsRef.current.save(); - - if (dirty && valid) setIsSaving(true); - } - - render() { - const { isSaving } = this.props; - - const saveBtn = ( - - Save Changes - - ); - - return ( - -
    - - -
    {saveBtn}
    -
    -
    - ); - } -} - -ExperienceAndSkills.defaultProps = { - isSaving: false, - setIsSaving: () => { }, -}; - -ExperienceAndSkills.propTypes = { - userTraits: PT.array.isRequired, - isSaving: PT.bool, - setIsSaving: PT.func, -}; diff --git a/src/shared/components/Settings/ExperienceAndSkills/styles.scss b/src/shared/components/Settings/ExperienceAndSkills/styles.scss deleted file mode 100644 index aaa5000547..0000000000 --- a/src/shared/components/Settings/ExperienceAndSkills/styles.scss +++ /dev/null @@ -1,46 +0,0 @@ -@import '~styles/mixins'; - -.experience-and-skills { - display: flex; - flex-direction: column; - margin: 9px 0 0; - color: $color-black-100; - - @include xs-to-md { - display: block; - margin: 0; - } -} - -.footer { - display: flex; - flex-direction: row-reverse; - - .save-changes-btn { - @include roboto-bold; - - font-weight: 700; - font-size: 16px; - line-height: 24px; - border-radius: 50px !important; - background: #137d60 !important; - color: #fff !important; - text-transform: uppercase; - padding: 11px 23px; - margin: 0; - - &.disabled { - opacity: 0.5; - } - } - - @include xs-to-md { - padding: $pad-xxxxl 0 $pad-sm; - border-top: 2px solid $color-black-10; - - .save-changes-btn { - font-size: 14px; - line-height: 20px; - } - } -} diff --git a/src/shared/components/Settings/Header/index.jsx b/src/shared/components/Settings/Header/index.jsx deleted file mode 100644 index d7fa27b5f9..0000000000 --- a/src/shared/components/Settings/Header/index.jsx +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Header component for settings page - */ -import React from 'react'; -import { Button } from 'topcoder-react-ui-kit'; -import PT from 'prop-types'; - -import style from './styles.scss'; - -export default function Header({ saveSettings, isSaving }) { - return ( -
    - -
    - ); -} - -Header.defaultProps = { - isSaving: false, -}; - -Header.propTypes = { - saveSettings: PT.func.isRequired, - isSaving: PT.bool, -}; diff --git a/src/shared/components/Settings/Header/styles.scss b/src/shared/components/Settings/Header/styles.scss deleted file mode 100644 index 282c843105..0000000000 --- a/src/shared/components/Settings/Header/styles.scss +++ /dev/null @@ -1,44 +0,0 @@ -@import "~styles/mixins"; - -.Header { - display: flex; - flex-direction: row; - justify-content: flex-end; - align-items: flex-start; - background: $tc-white; - border-bottom: 2px solid $color-black-10; - padding: 0 0 $pad-xxl 0; - - .saveButton { - @include roboto-bold; - - border: 0 !important; - font-weight: 700; - font-size: 16px; - line-height: 24px; - border-radius: 50px !important; - background: #137d60 !important; - color: #fff !important; - text-transform: uppercase; - padding: 11px 23px; - margin: 0; - - &.disabled { - opacity: 0.5; - } - } - - @include xs-to-md { - padding: 0 0 $pad-lg; - - .title { - h1 { - font-size: 28px; - } - } - - .saveButton { - display: none; - } - } -} diff --git a/src/shared/components/Settings/PageRow/index.jsx b/src/shared/components/Settings/PageRow/index.jsx deleted file mode 100644 index a6e4a884f6..0000000000 --- a/src/shared/components/Settings/PageRow/index.jsx +++ /dev/null @@ -1,42 +0,0 @@ -/** - * PageUl - * - * page content row (flex -> row) - */ -import React from 'react'; -import PT from 'prop-types'; -import cn from 'classnames'; -import './styles.scss'; - -const PageRow = ({ - children, half = false, row, styleName, ...props -}) => ( -
    - {children} -
    -); - -PageRow.defaultProps = { - children: null, - half: false, - row: true, - styleName: {}, -}; - -PageRow.propTypes = { - children: PT.node, - half: PT.bool, - row: PT.bool, - styleName: PT.shape(), -}; - -export default PageRow; diff --git a/src/shared/components/Settings/PageRow/styles.scss b/src/shared/components/Settings/PageRow/styles.scss deleted file mode 100644 index 43caf313a9..0000000000 --- a/src/shared/components/Settings/PageRow/styles.scss +++ /dev/null @@ -1,47 +0,0 @@ -@import "~styles/mixins"; - -.page-row { - display: flex; - - @include md-to-xl { - &.page-col { - flex-direction: column; - - & > div { - width: 100%; - } - } - - &.page-row-half { - & > div { - width: 50%; - } - - & > div:nth-child(1) { - margin-right: 0; - } - - & > div:nth-child(2) { - margin-left: 20px; - } - } - - &.page-row-normal > div:nth-child(1) { - width: 50%; - padding-right: 100px; - min-width: 500px; - } - - &.page-row-normal > div:nth-child(2) { - width: 52%; - } - } - - @include xs-to-md { - flex-direction: column; - - & > div { - width: 100%; - } - } -} diff --git a/src/shared/components/Settings/Payment/EmailDetails/index.jsx b/src/shared/components/Settings/Payment/EmailDetails/index.jsx deleted file mode 100644 index aed513288e..0000000000 --- a/src/shared/components/Settings/Payment/EmailDetails/index.jsx +++ /dev/null @@ -1,47 +0,0 @@ -/* eslint-disable react/no-danger */ -import React from 'react'; -import PT from 'prop-types'; - -import { PAYMENT_METHOD_DETAILS_MAP, PAYMENT_METHOD_MAP } from '../constants'; -import './styles.scss'; - -/** - * This component shows the steps to be done to - * subscribe to this payment method - * @returns - */ -const EmailDetails = ({ paymentMethod }) => { - const { instructions } = PAYMENT_METHOD_DETAILS_MAP[paymentMethod]; - - return ( -
    -
    - Do you have your {PAYMENT_METHOD_MAP[paymentMethod]} account details? - Great! -
    -
      - {instructions.map(instruction => ( -
    • - -
        - {instruction.children - && instruction.children.map(child => ( -
      • - ))} -
      -
    • - ))} -
    -
    - ); -}; - -EmailDetails.defaultProps = { - paymentMethod: '', -}; - -EmailDetails.propTypes = { - paymentMethod: PT.string, -}; - -export default EmailDetails; diff --git a/src/shared/components/Settings/Payment/EmailDetails/styles.scss b/src/shared/components/Settings/Payment/EmailDetails/styles.scss deleted file mode 100644 index 7ad4f8fc38..0000000000 --- a/src/shared/components/Settings/Payment/EmailDetails/styles.scss +++ /dev/null @@ -1,43 +0,0 @@ -@import '~styles/mixins'; - -.email-details { - padding: 16px; - background-color: $color-orange-25; - margin-right: 32px; - border-radius: 8px; - margin-bottom: 16px; - - @include xs-to-sm { - margin-right: 0; - } - - .title { - @include barlow; - - font-size: 18px; - line-height: 22px; - font-weight: 600; - margin-bottom: 24px; - color: $tco-black; - text-transform: uppercase; - } - - .instructions { - list-style: disc; - list-style-position: outside; - padding-left: 23px; - - li { - @include roboto-regular; - - font-size: 16px; - line-height: 24px; - font-weight: 400; - color: $tco-black; - - a { - color: #2e55b9; - } - } - } -} diff --git a/src/shared/components/Settings/Payment/PaymentInfo/index.jsx b/src/shared/components/Settings/Payment/PaymentInfo/index.jsx deleted file mode 100644 index 9cc54633d8..0000000000 --- a/src/shared/components/Settings/Payment/PaymentInfo/index.jsx +++ /dev/null @@ -1,35 +0,0 @@ -import React from 'react'; -import cn from 'classnames'; -import PT from 'prop-types'; - -import './styles.scss'; - -const PaymentInfo = ({ - icon, label, value, isLastChild, -}) => ( -
    -
    -
    {icon}
    -
    {label}
    -
    -
    -
    {value}
    -
    -
    -); - -PaymentInfo.defaultProps = { - icon: null, - label: '', - value: '', - isLastChild: false, -}; - -PaymentInfo.propTypes = { - icon: PT.node, - label: PT.string, - value: PT.string, - isLastChild: PT.bool, -}; - -export default PaymentInfo; diff --git a/src/shared/components/Settings/Payment/PaymentInfo/styles.scss b/src/shared/components/Settings/Payment/PaymentInfo/styles.scss deleted file mode 100644 index 13427c3b3d..0000000000 --- a/src/shared/components/Settings/Payment/PaymentInfo/styles.scss +++ /dev/null @@ -1,64 +0,0 @@ -@import '~styles/mixins'; - -.payment-info { - display: flex; - flex-direction: column; - margin-bottom: 22px; - - .header { - display: flex; - margin-left: -4px; - margin-top: -6px; - } - - .icon-wrapper { - margin-right: 5px; - - svg { - width: 13px; - height: 13px; - } - } - - .label { - font-weight: 700; - font-size: 12px; - - @include roboto-bold; - - line-height: 16px; - color: $color-teal-140; - letter-spacing: 1px; - text-transform: uppercase; - - @include xs-to-sm { - font-size: 10px; - line-height: 12px; - } - } - - .content { - display: flex; - - .value { - font-weight: 400; - font-size: 16px; - - @include roboto-regular; - - line-height: 24px; - color: $tco-black; - margin-top: 4px; - margin-left: -4px; - - @include xs-to-sm { - font-size: 14px; - line-height: 24px; - } - } - } - - &.last-child { - margin-bottom: 0; - } -} diff --git a/src/shared/components/Settings/Payment/PaymentMethod/index.jsx b/src/shared/components/Settings/Payment/PaymentMethod/index.jsx deleted file mode 100644 index 757000a40a..0000000000 --- a/src/shared/components/Settings/Payment/PaymentMethod/index.jsx +++ /dev/null @@ -1,158 +0,0 @@ -/* eslint-disable react/no-danger */ -import React, { useState } from 'react'; -import PT from 'prop-types'; - -import { Modal, Button } from 'topcoder-react-ui-kit'; - -import IconClose from 'assets/images/icon-close-green.svg'; -import Checkbox from 'components/GUIKit/Checkbox'; -import EmailDetails from '../EmailDetails'; - -import { - PAYMENT_METHOD_MAP, - PAYMENT_METHOD_DETAILS_MAP, - PAYMENT_PROVIDER, -} from '../constants'; - -import styles from './styles.scss'; - -const PaymentMethod = ({ - paymentMethod, - show, - handleClose, - handleConfirm, - handle, - setSelectedMode, - setPaymentService, -}) => { - const [emailedDetails, setEmailedDetails] = useState(false); - - - const onChange = () => { - setEmailedDetails(!emailedDetails); - }; - - const { important, conditions, url } = PAYMENT_METHOD_DETAILS_MAP[ - paymentMethod - ]; - - const onVisitPaymentProvider = () => { - window.open(url, '_blank'); - }; - - const onConfirm = () => { - localStorage.setItem( - `${handle}_${PAYMENT_PROVIDER}`, - paymentMethod, - ); - setPaymentService(paymentMethod); - handleConfirm(); - handleClose(); - setSelectedMode(true); - }; - - return ( - -
    -
    -
    -
    -
    -
    - {`connect your ${PAYMENT_METHOD_MAP[paymentMethod]} account`} -
    -
    -
    - -
    -
    -
    - -
    -
    - -
    - - - Yes, I have emailed my details to{' '} - - support@topcoder.com - - -
    -
    -
    -
    {`Create ${PAYMENT_METHOD_MAP[paymentMethod]} account`}
    -

    {important}

    -
    -
    - -
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    - - ); -}; - - -PaymentMethod.defaultProps = { - paymentMethod: '', - show: false, - handle: '', - handleClose: () => {}, - handleConfirm: () => {}, - setPaymentService: () => {}, - setSelectedMode: () => {}, -}; - -PaymentMethod.propTypes = { - paymentMethod: PT.string, - show: PT.bool, - handle: PT.string, - handleClose: PT.func, - handleConfirm: PT.func, - setSelectedMode: PT.func, - setPaymentService: PT.func, -}; - -export default PaymentMethod; diff --git a/src/shared/components/Settings/Payment/PaymentMethod/styles.scss b/src/shared/components/Settings/Payment/PaymentMethod/styles.scss deleted file mode 100644 index 69e8a6294b..0000000000 --- a/src/shared/components/Settings/Payment/PaymentMethod/styles.scss +++ /dev/null @@ -1,392 +0,0 @@ -@import '~styles/mixins'; - -.page-wrapper { - padding: 0; - - /* rc checkbox custom style */ - :global { - .rc-checkbox.payment-service-rc-checkbox { - display: flex; - margin-top: 3px; - - .rc-checkbox-inner { - width: 24px !important; - height: 24px !important; - } - - &.rc-checkbox-checked { - .rc-checkbox-inner { - background-color: #0ab88a; - border-color: #0ab88a; - } - } - - .rc-checkbox-inner::after { - left: 7px !important; - top: 0 !important; - width: 8px !important; - height: 16px !important; - } - } - } - - .page-title { - background-color: white; - padding: 12px 24px; - box-shadow: 0 1px 5px rgba(0, 0, 0, 0.2); - border-radius: 0 0 8px 8px; - text-transform: uppercase; - - @include barlow-condensed; - - font-size: 17px; - font-weight: 500; - color: $tco-black; - } - - .payment-method { - @include xs-to-sm { - padding: 16px 8px 16px 8px; - } - - .page-content { - margin: 0; - - @include xs-to-sm { - padding: 16px 19px; - margin: 0; - } - - .page-header { - display: flex; - margin-bottom: 24px; - - .left-pane { - flex: 1; - display: flex; - flex-direction: column; - - .payment-service-title { - @include barlow; - - margin: 0; - font-size: 22px; - line-height: 26px; - font-weight: 500; - text-transform: uppercase; - - @include xs-to-sm { - font-weight: 600; - font-size: 16px; - line-height: 16px; - } - } - } - - .right-pane { - width: 400px; - display: flex; - align-items: center; - padding: 0 24px; - - @include xs-to-sm { - width: 100%; - margin-top: 23px; - padding: 0 16px; - margin-bottom: 13px; - } - } - } - - .user-name { - margin-top: 30px; - font-size: 16px; - line-height: 26px; - - @include roboto-regular; - - color: $tco-black; - - @include xs-to-sm { - font-size: 14px; - line-height: 20px; - font-weight: 500; - } - } - - .container { - display: flex; - margin-top: 25px; - margin-bottom: 29px; - - @include xs-to-sm { - flex-direction: column; - margin-bottom: 32px; - } - - .left-pane { - width: 34.5%; - display: flex; - border-right: 2px solid $profile-border-gray; - flex-direction: column; - - @include xs-to-sm { - width: auto; - border-right: 0; - border-bottom: 2px solid $profile-border-gray; - padding-bottom: 32px; - } - - .form-input-checkbox { - display: flex; - align-items: flex-start; - margin-top: 17px; - - .label { - font-size: 16px; - line-height: 26px; - margin-left: 10px; - - @include roboto-regular; - - font-weight: 400; - - .support-email { - color: #2e55b9; - } - } - } - } - - .right-pane { - display: flex; - flex: 1; - flex-direction: column; - margin-left: 32px; - - @include xs-to-sm { - margin-left: 0; - } - - .title { - @include barlow; - - font-weight: 600; - font-size: 18px; - line-height: 22px; - text-transform: uppercase; - - @include xs-to-sm { - font-weight: 600; - font-size: 16px; - line-height: 20px; - margin: 24px 0; - color: $tco-black; - } - } - - .important-text { - @include roboto-regular; - - font-weight: 700; - font-size: 16px; - line-height: 24px; - color: $color-red-120; - margin-bottom: 16px; - margin-top: 22px; - - @include xs-to-sm { - margin-top: 0; - font-size: 14px; - line-height: 22px; - } - } - - .condition-text { - p { - @include roboto-regular; - - font-weight: 400; - font-size: 16px; - color: $tco-black; - margin-bottom: 16px; - line-height: 24px; - } - } - - .visit-button-wrapper { - margin-top: 12px; - - .visit-button-desktop-disabled { - @include roboto-bold; - - font-weight: 700; - font-size: 13px; - line-height: 24px; - height: 32px !important; - padding: 4px 20px !important; - border-radius: 24px; - color: #767676 !important; - background: #fff !important; - border: 2px solid #f4f4f4 !important; - text-transform: uppercase; - } - - .visit-button-desktop { - @include roboto-bold; - - font-weight: 700; - font-size: 13px; - height: 32px !important; - padding: 4px 20px !important; - border-radius: 24px; - line-height: 24px; - text-transform: uppercase; - border: 1px solid #137d60 !important; - background-color: #137d60 !important; - color: #fff !important; - - &:hover { - border: 1px solid #137d60 !important; - background: #137d60 !important; - color: #fff !important; - opacity: 0.8; - } - } - - .visit-button-mobile { - @include roboto-bold; - - font-weight: 700; - font-size: 14px; - padding: 14px 20px; - height: 40px; - border-radius: 25px; - display: none; - - @include xs-to-sm { - height: 32px; - padding: 10px 15px; - font-size: 12px; - display: flex; - } - } - } - } - } - - .footer { - margin-top: 18px; - margin-bottom: 32px; - - @include xs-to-sm { - flex-direction: row; - align-items: center !important; - justify-content: center !important; - margin-top: 32px; - } - - .footer-back-button { - padding: 18px 30px 18px 34px; - border-radius: 25px; - height: 48px; - - @include xs-to-sm { - height: 40px; - padding: 14px 14px 14px 24px; - } - - .footer-back-button-text { - margin-left: 9px; - font-size: 20px; - font-weight: 700; - - @include roboto-bold; - - @include xs-to-sm { - font-size: 14px; - line-height: 12px; - } - } - } - - .confirm-button-wrapper { - flex: 1; - display: flex; - justify-content: flex-end; - - @include xs-to-sm { - margin-bottom: 0; - } - - .footer-confirm-button { - height: 48px; - font-size: 16px !important; - line-height: 24px !important; - color: $tc-white !important; - font-weight: 700; - background: #137d60 !important; - border-radius: 50px !important; - padding: 12px 24px !important; - text-transform: uppercase; - - @include roboto-bold; - - @include xs-to-sm { - height: 40px; - padding: 14px 20px; - font-size: 14px; - line-height: 12px; - } - } - } - } - } - - .page-divider { - border-bottom: 2px solid $profile-border-gray; - } - } -} - -@media screen and (max-width: 425px) { - .footer { - .footer-back-button { - padding: 14px 24px 14px 24px !important; - } - } -} - -.modal-inner-no-max-width { - max-width: none !important; -} - -.modal-overlay { - background: #000; -} - -.modal-container { - width: 1200px; - min-height: 596px; - max-width: 1232px; - border-radius: 8px; - padding: 32px 32px 0 32px; - gap: 24px; - overflow-y: scroll; - - @include xs-to-md { - width: 100%; - max-width: 100% !important; - height: 100% !important; - max-height: 100% !important; - padding: 24px 16px 48px 16px; - } -} - -.icon { - width: 14.4px; - height: 14.4px; - margin-right: 5px; - margin-top: 4px; - cursor: pointer !important; -} diff --git a/src/shared/components/Settings/Payment/PaymentProvider/index.jsx b/src/shared/components/Settings/Payment/PaymentProvider/index.jsx deleted file mode 100644 index 232b50d744..0000000000 --- a/src/shared/components/Settings/Payment/PaymentProvider/index.jsx +++ /dev/null @@ -1,221 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import cn from 'classnames'; -import PT from 'prop-types'; - -import { Button } from 'topcoder-react-ui-kit'; - -import ChevronDownGreen from 'assets/images/chevron-down-green.svg'; -import IconDollar from 'assets/images/icon-dollar.svg'; -import IconSpeed from 'assets/images/icon-speed.svg'; -import IconWorld from 'assets/images/icon-world.svg'; -import SelectedPaymentLogo from 'assets/images/selected-payment.svg'; -import PayoneerLogo from 'assets/images/Payoneer_log_gray.svg'; -import PayPalLogo from 'assets/images/PayPal_logo_gray.svg'; -import WesternUnionLogo from 'assets/images/Western_Union_Logo_gray.svg'; -import PaymentInfo from '../PaymentInfo'; -import PaymentMethod from '../PaymentMethod'; - -import { PAYMENT_METHODS, PAYMENT_METHOD_MAP, PAYMENT_PROVIDER } from '../constants'; - -import styles from './styles.scss'; - - -const PaymentProvider = ({ handleConfirm, handle }) => { - const [collapse, setCollapse] = useState(true); - const [selectedMethod, setSelectedMethod] = useState(''); - const [paymentService, setPaymentService] = useState( - localStorage.getItem(`${handle}_${PAYMENT_PROVIDER}`), - ); - const [selectedMode, setSelectedMode] = useState(false); - - useEffect(() => { - if (paymentService) { - setSelectedMode(true); - } - }, []); - - const onRemove = () => { - localStorage.removeItem(`${handle}_${PAYMENT_PROVIDER}`); - setPaymentService(null); - setSelectedMethod(''); - }; - - return ( -
    -
    -

    PAYMENT PROVIDER

    - - setCollapse(!collapse)} - > - - -
    - - { - collapse && ( -
    -
    - Topcoder is partnered with several payment - providers to send payments to our community members. - Once a provider is set up, payments will be routed to your selected payment - provider at the completion of work. - Currently, members can be paid through one of the following providers: - Payoneer®, PayPal®, or Western Union. - -
    - - { - selectedMode ? ( -
    -
    -
    - -
    -
    -

    Payment Provider Detail Submitted

    - -

    - You have submitted account details to use {paymentService} as your - payment service provider. - Processing may take up to 48 hours. -

    -
    -
    - -
    - -
    - -
    - ) : null - } - - { - paymentService && !selectedMode ? ( -
    -
    -

    - - Your currently selected payment provider is:{' '} - {PAYMENT_METHOD_MAP[paymentService]} - -

    - -

    - Note: You have chosen to change your - selected payment provider. - This change may take up to 48 hours to be reflected in your account. -

    -
    - - -
    - ) : null - } - - { - !selectedMode ? ( -
    -
    - {PAYMENT_METHODS.map(method => ( -
    -
    - {PAYMENT_METHOD_MAP[method.name] === 'Payoneer' && ( - - )} - {PAYMENT_METHOD_MAP[method.name] === 'PayPal' && } - {PAYMENT_METHOD_MAP[method.name] === 'Western Union' && ( - - )} -
    -
    -
    - } - label="Fees" - value={method.fees} - isLastChild={false} - /> - } - label="countries" - value={`Available in ${method.countries}+ countries`} - isLastChild={false} - /> - } - label="Speed" - value={`Up to ${method.speed} Business Day`} - isLastChild - /> -
    -
    - -
    -
    - ))} - - {selectedMethod && ( - { - setSelectedMethod(''); - }} - handleConfirm={() => { - handleConfirm(); - }} - paymentService={paymentService} - setPaymentService={setPaymentService} - setSelectedMode={setSelectedMode} - /> - )} -
    -
    - The information above is gathered from each payment provider's - respective website. We encourage you to do any additional information - gathering you see fit prior to making a payment provider decision. -
    -
    - ) : null - } -
    - ) - } -
    - ); -}; - -PaymentProvider.defaultProps = { - handleConfirm: () => {}, - handle: '', -}; - -PaymentProvider.propTypes = { - handleConfirm: PT.func, - handle: PT.string, -}; - -export default PaymentProvider; diff --git a/src/shared/components/Settings/Payment/PaymentProvider/styles.scss b/src/shared/components/Settings/Payment/PaymentProvider/styles.scss deleted file mode 100644 index b4cc35b6fd..0000000000 --- a/src/shared/components/Settings/Payment/PaymentProvider/styles.scss +++ /dev/null @@ -1,327 +0,0 @@ -@import '~styles/mixins'; - -.platform-banner { - background-color: $tc-white; - border-radius: 4px; - width: 100%; - padding: 32px; - - @include xs-to-sm { - padding: 24px 16px; - } -} - -.banner-title { - @include xs-to-sm { - font-size: 18px; - } -} - -.header { - display: flex; - justify-content: space-between; - - h3 { - @include barlow-bold; - - font-size: 22px; - line-height: 26px; - font-weight: 600; - color: $tco-black; - } - - .icon { - margin-top: 5px; - margin-right: 6px; - cursor: pointer; - - &.up { - transform: rotate(180deg); - } - } -} - -.content { - margin-top: 33px; - - .description { - @include roboto-regular; - - font-size: 16px; - line-height: 24px; - font-weight: 400; - color: $tco-black; - padding-right: calc(38% - 18px); - - @include sm-to-md { - padding-right: 77px; - } - - @include xs-to-sm { - width: unset; - font-size: 14px; - padding-right: 0; - } - } -} - -.selected-payment-logo { - width: 64px; - height: 64px; - min-height: 64px; - border-radius: 4px; - min-width: 64px; - background: linear-gradient(264.69deg, #198807 2.17%, #017c6d 97.49%); - align-self: center; - justify-content: center; - display: flex; - margin-right: 20px; - flex-direction: column; - - @include xs-to-sm { - align-self: flex-start; - margin-bottom: 12px; - } - - svg { - margin: 0 auto; - } -} - -.payment-logo { - height: 40px; - margin-top: -4px; - - svg { - height: 56px; - - @include xs-to-sm { - width: -webkit-fill-available; - } - } -} - -.payment-methods { - display: flex; - margin-top: 32px; - flex-wrap: wrap; - - @include xs-to-sm { - flex-direction: column; - margin-top: 16px; - } - - .payment-method-card { - background-color: $tc-white; - border: 1px solid $listing-light-gray; - border-radius: 8px; - padding: 30px; - display: flex; - min-width: 31%; - max-width: 31%; - flex: 1; - margin-right: 2%; - flex-direction: column; - - svg { - max-width: 68vw !important; - } - - @include xs-to-md { - margin-bottom: 32px; - } - - @include xs-to-sm { - margin-right: 0; - margin-bottom: 16px; - min-width: unset; - max-width: 100% !important; - } - - .button-wrapper { - margin-top: 18px; - margin-left: -10px; - - @include xs-to-sm { - margin-top: 24px; - } - } - - .content-wrapper { - flex-direction: column; - } - } - - .payment-method-card:last-child { - margin-right: 0; - - @include xs-to-sm { - margin-bottom: 0; - } - } -} - -.info-text { - font-family: Roboto, sans-serif; - font-size: 14px; - line-height: 22px; - margin-top: 24px; - margin-bottom: 24px; -} - -.divider { - margin-top: 36px; - margin-bottom: 30px; - height: 2px; - border-radius: 1px; - background: $profile-border-gray; -} - -.payment-method-card .button { - @include roboto-bold; - - font-size: 14px; - font-weight: 700; - line-height: 24px; - height: 40px; - color: #137d60 !important; - border: 2px solid #137d60 !important; - border-radius: 24px !important; - text-transform: uppercase; - padding: 5px 17px !important; - letter-spacing: 0.008em; - - &:hover { - background-image: unset !important; - color: #219174 !important; - border: 2px solid #219174 !important; - } - - &:focus, - &:focus-within, - &:focus-visible { - outline: 0 !important; - box-shadow: none !important; - color: #219174 !important; - border: 2px solid #219174 !important; - } - - @include xs-to-sm { - height: 32px; - } -} - -.desc-container { - display: flex; - justify-content: space-between; - margin-top: 32px; - margin-bottom: 32px; - - @include xs-to-sm { - display: flex; - flex-direction: column; - } -} - -.desc { - @include roboto-regular; - - font-size: 16px; - line-height: 24px; - - strong { - @include roboto-bold; - - font-weight: 700; - } - - @include xs-to-sm { - margin-bottom: 24px; - font-size: 14px; - } -} - -.desc-button { - @include roboto-bold; - - padding: 4px 20px !important; - border: 2px solid #137d60 !important; - border-radius: 24px !important; - background: #fff !important; - font-weight: 700; - font-size: 13px; - color: #137d60 !important; - line-height: 24px; - white-space: nowrap; - height: 32px; - - &:hover { - background-image: unset !important; - color: #219174 !important; - border: 2px solid #219174 !important; - } - - @include xs-to-sm { - height: 32px; - width: 162px; - margin: 0; - } -} - -.selectedWrapper { - display: flex; - justify-content: space-between; - border: 1px solid #d4d4d4; - border-radius: 8px; - background: #fff; - height: 96px; - margin-top: 32px; - padding: 24px 10px; - - .selected-left { - display: flex; - - @include xs-to-sm { - flex-direction: column; - } - } - - @include xs-to-md { - min-height: 96px; - height: unset; - } - - @include xs-to-sm { - height: auto; - flex-direction: column; - } -} - -.payment-wrapper { - @include xs-to-sm { - width: 87%; - } -} - -.payment-title { - @include roboto-bold; - - font-weight: 700; - font-size: 16px; - line-height: 20px; - letter-spacing: 0.5px; -} - -.payment-desc { - @include roboto-regular; - - font-weight: 400; - font-size: 16px; - line-height: 20px; - letter-spacing: 0.5px; - color: #767676; - - @include xs-to-sm { - margin-bottom: 24px; - } -} diff --git a/src/shared/components/Settings/Payment/constants.js b/src/shared/components/Settings/Payment/constants.js deleted file mode 100644 index f1c5f161bf..0000000000 --- a/src/shared/components/Settings/Payment/constants.js +++ /dev/null @@ -1,123 +0,0 @@ -export const PAYMENT_PROVIDER = 'payment_provider'; - -/** - * List of payment methods supported - */ -export const PAYMENT_METHODS = [ - { - name: 'payoneer', - fees: '$0–$3 + Currency Conversion Rates May Apply', - countries: 150, - speed: 1, - }, - { - name: 'paypal', - fees: '3.49% + an international fee (non US) + a fixed fee depending upon currency', - countries: 200, - speed: 1, - }, - { - name: 'western-union', - fees: '$8 per transaction (your bank may charge additional fees)', - countries: 200, - speed: 3, - }, -]; - -/** - * Map of payment method to the display name - */ -export const PAYMENT_METHOD_MAP = { - payoneer: 'Payoneer', - paypal: 'PayPal', - 'western-union': 'Western Union', -}; - -/** - * The payment method details map - */ -export const PAYMENT_METHOD_DETAILS_MAP = { - payoneer: { - instructions: [ - { - label: - "Email support@topcoder.com", - }, - { - label: 'Subject Line: Topcoder Payment Provider', - }, - { - label: 'In the email include:', - children: [ - 'Topcoder handle (your username when registering)', - 'Payoneer Customer ID', - 'Payoneer Email Address', - ], - }, - ], - conditions: ` -

    You can elect to receive payments through Payoneer either to your Payoneer prepaid MasterCard or by using their Global Bank Transfer service. The Payoneer Bank Transfer Service offers a local bank transfer option (where available) and a wire transfer option. Certain fees may apply.

    - `, - important: - 'Important: After you create an account, please email support@topcoder.com with the information outlined', - url: 'https://www.payoneer.com', - }, - paypal: { - instructions: [ - { - label: - "Email support@topcoder.com", - }, - { - label: 'Subject Line: Topcoder Payment Provider', - }, - { - label: 'In the email include:', - children: [ - 'Topcoder handle (your username when registering)', - 'PayPal Email Address', - ], - }, - { - label: - 'Please DO NOT provide a link to your PayPal account. We only need your PayPal email address.', - }, - ], - conditions: ` -

    You can elect to receive payments deposited directly to your PayPal account. Certain fees may apply.

    - `, - important: - 'Important: After you create an account, please email support@topcoder.com with the information outlined', - url: 'https://www.paypal.com/cgi-bin/webscr?cmd=_registration-run', - }, - 'western-union': { - instructions: [ - { - label: - "Email support@topcoder.com", - }, - { - label: 'Subject Line: Topcoder Payment Provider', - }, - { - label: 'In the email include:', - children: [ - 'Topcoder handle (your username when registering)', - 'Topcoder Email Address (the email address you used to register)', - ], - }, - ], - conditions: ` -

    You can elect to be paid via wire transfer through Western Union. There is a US $8 charge for each payment processed by Western Union, which will be deducted from the amount owed to you. You can elect to be paid in either USD or your local currency. However, Western Union does not disclose it’s fees to convert to your local currency so we recommend you choose to receive USD. You may then be subject to conversion fees by your local bank.

    -

    Important: Use your Topcoder handle as the Payee ID during registration. Use the Preferred Form of Payment as “Fastest,” rather than “Least Cost.” “Least Cost” uses ACH as a form of payment, which is not supported in all countries.

    -

    If you elect to be paid by Western Union, your payment request will be queued and processed semi-monthly, on the 15th and last business day of the month. If the 15th or last day of the month falls on a weekend or holiday, Western Union payments will be processed the next business day.

    -

    In order to be included in the semi-monthly payments, you need to select which payments you would like to be paid for by 10:00 AM EST on the day of the scheduled payment.

    - `, - important: - 'Important: After you create an account, please return to this screen and enter the appropriate account details.', - url: - 'https://payee.globalpay.westernunion.com/PayeeManager/BeneficiaryEnrollment/SpecifyPayeeID.aspx?id=9E63C90B520F830246DA2FD728CDAEBF', - }, -}; - -export default undefined; diff --git a/src/shared/components/Settings/Payment/index.jsx b/src/shared/components/Settings/Payment/index.jsx deleted file mode 100644 index 0313bbe0a3..0000000000 --- a/src/shared/components/Settings/Payment/index.jsx +++ /dev/null @@ -1,63 +0,0 @@ -/* eslint-disable prefer-destructuring */ -import React from 'react'; -import PT from 'prop-types'; - -import ArrowRightIcon from 'assets/images/arrow-right-green.svg'; -import { PrimaryButton } from 'topcoder-react-ui-kit'; - -import { getPaymentPageUrl } from 'utils/url'; - -import ErrorWrapper from '../ErrorWrapper'; -import PaymentProvider from './PaymentProvider'; - - -import styles from './styles.scss'; - -export default class Payment extends React.Component { - constructor(props) { - super(props); - this.state = {}; - } - - render() { - const { handle } = this.props; - - return ( - -
    -
    -

    Payment Settings

    - - - Manage Your Payments - - -
    - {}} /> - - Manage Your Payments - - -
    -
    - - Save Changes - -
    -
    - ); - } -} - -Payment.defaultProps = { - handle: '', -}; - -Payment.propTypes = { - handle: PT.string, -}; diff --git a/src/shared/components/Settings/Payment/styles.scss b/src/shared/components/Settings/Payment/styles.scss deleted file mode 100644 index 2cbca1a034..0000000000 --- a/src/shared/components/Settings/Payment/styles.scss +++ /dev/null @@ -1,119 +0,0 @@ -@import '~styles/mixins'; - -.payment-container { - background-color: $listing-filter-bg; - padding: $pad-xxxxl; - border-radius: 8px; - margin: 40px 0 32px; - - @include xs-to-sm { - padding: $pad-xxl $pad-lg; - } - - .header { - margin: 0 0 40px; - display: flex; - justify-content: space-between; - - @include xs-to-sm { - margin: 24px 0 24px; - flex-direction: column; - } - - h3 { - @include barlow-bold; - - font-size: 24px; - font-weight: 600; - line-height: 28px; - color: $tco-black; - text-transform: uppercase; - - @include xs-to-md { - @include barlow-condensed-semi-bold; - - font-weight: 500; - font-size: 20px; - line-height: 24px; - } - } - } - - .header__link { - @include roboto-bold; - - font-weight: 700; - font-size: 16px; - line-height: 16px; - text-transform: uppercase; - color: $listing-checkbox-green; - margin-right: 1px; - margin-top: 7px; - - span { - margin-right: 4px; - } - - @include xs-to-sm { - display: none; - } - } - - .header__link__mobile { - display: none; - - @include xs-to-sm { - @include roboto-bold; - - display: inline-block; - font-weight: 700; - font-size: 16px; - line-height: 16px; - text-transform: uppercase; - color: $listing-checkbox-green; - margin-top: 24px; - margin-left: 16px; - - span { - margin-right: 4px; - } - } - } -} - -.footer { - display: flex; - flex-direction: row-reverse; - - .save-changes-btn { - @include roboto-bold; - - font-weight: 700; - font-size: 16px; - line-height: 24px; - border-radius: 50px !important; - background: #137d60 !important; - color: #fff !important; - text-transform: uppercase; - padding: 11px 23px; - margin: 0; - - &.disabled { - opacity: 0.5; - } - - &:hover { - background: #219174 !important; - } - } - - @include xs-to-md { - padding: $pad-xxxxl 0 $pad-sm; - border-top: 2px solid $color-black-10; - - .save-changes-btn { - font-size: 14px; - line-height: 20px; - } - } -} diff --git a/src/shared/components/Settings/Preferences/Email/data.jsx b/src/shared/components/Settings/Preferences/Email/data.jsx deleted file mode 100644 index 25ba7886b5..0000000000 --- a/src/shared/components/Settings/Preferences/Email/data.jsx +++ /dev/null @@ -1,20 +0,0 @@ - -export const subscribe = { - id: 'subscribe', - icon: 'email', - name: 'You are not subscribed to receive topcoder emails', - description: 'If this was a mistake or if you would like to resubscribe, please click the “Subscribe” button.', - linkTitle: 'SUBSCRIBE', - formLink: 'https://topcoder.us13.list-manage.com/subscribe/post?u=65bd5a1857b73643aad556093&id=28bfd3c062', - value: 'subscribe', -}; - -export const unsubscribe = { - id: 'unsubscribe', - icon: 'email', - name: 'You are currently subscribed to receive topcoder emails', - description: 'If this was a mistake or if you would like to unsubscribe, please click the “Unsubscribe” button.', - linkTitle: 'UNSUBSCRIBE', - formLink: 'https://topcoder.us13.list-manage.com/unsubscribe?u=65bd5a1857b73643aad556093&id=28bfd3c062', - value: 'unsubscribe', -}; diff --git a/src/shared/components/Settings/Preferences/Email/index.jsx b/src/shared/components/Settings/Preferences/Email/index.jsx deleted file mode 100644 index f6f79b718c..0000000000 --- a/src/shared/components/Settings/Preferences/Email/index.jsx +++ /dev/null @@ -1,199 +0,0 @@ -/* eslint-disable max-len */ -/** - * Email Preferences component. - */ -import { debounce, map } from 'lodash'; -import React from 'react'; -import PT from 'prop-types'; -import { toastr } from 'react-redux-toastr'; -import ToggleableItem from 'components/Settings/ToggleableItem'; -import Item from '../List/Item'; -import { subscribe, unsubscribe } from './data'; - -import './styles.scss'; - -function toastrSuccess(title, message) { - setImmediate(() => { - toastr.success(title, message); - }); -} - -function toastrError(title, message) { - setImmediate(() => { - toastr.error(title, message); - }); -} - -const SAVE_DELAY = 1000; - -const newsletters = [ - { - id: 'd0c48e9da3', - name: 'Work Opportunities', - desc: 'A weekly summary of available ways to earn, including gig work, challenges, and Thrive articles.', - }, - { - id: 'a8f858cdf1', - name: 'Monthly Newsletter', - desc: 'A monthly newsletter with recent highlights from the Topcoder community.', - }, - { - id: '5e67dba327', - name: 'Marathon Match Reminders', - desc: 'Receive updates whenever a new marathon match is scheduled.', - }, - { - id: '9091b438cc', - name: 'Single Round Match (SRM) Reminders', - desc: 'Attention Competitive Programmers! If there is any newsletter you are subscribing too, it better be this one. Receive updates when a new SRM event is scheduled.', - }, - { - id: '3460574ddd', - name: 'Rapid Development Match (RDM) Reminders', - desc: 'Receive notifications of our brand new RDMs! These rated, development matches will be a fun new way to engage with us!', - }, -]; -const programs = [ - { - id: 'cafe98d7a7', - name: 'Beta Testers', - desc: 'If you have applied and been approved as a Beta Tester, you may control the emails you receive here.', - }, -]; - -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); - - constructor(props) { - super(props); - this.state = { - emailPreferences: { ...props.preferences }, - status: props.status, - }; - this.onChange = this.onChange.bind(this); - } - - componentDidUpdate(prevProps) { - const { updated } = this.props; - if (updated && updated !== prevProps.updated) { - if (updated.error) { - toastrError('Error! ', 'Failed to update Your email preferences :-('); - } - const { emailPreferences, status } = this.state; - const { id, checked } = updated; - 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, - }); - } - 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 - // update remote state - this.saveEmailPreferences(id, checked); - } - - render() { - const { emailPreferences, status } = this.state; - const { email } = this.props; - return ( -
    - { - status !== 'subscribed' ? ( - - ) : ( - - - { - map(newsletters, (newsletter) => { - const checked = emailPreferences[newsletter.id]; - return ( - this.onChange(newsletter.id, c)} - disabled={status !== 'subscribed'} - /> - ); - }) - } - { - map(programs, (program) => { - const checked = emailPreferences[program.id]; - return ( - this.onChange(program.id, c)} - disabled={status !== 'subscribed'} - /> - ); - }) - } - - ) - } -
    - ); - } -} - -EmailPreferences.defaultProps = { - updated: null, - status: null, -}; - -EmailPreferences.propTypes = { - email: PT.string.isRequired, - preferences: PT.shape().isRequired, - saveEmailPreferences: PT.func.isRequired, - updated: PT.shape(), - status: PT.string, -}; diff --git a/src/shared/components/Settings/Preferences/Email/styles.scss b/src/shared/components/Settings/Preferences/Email/styles.scss deleted file mode 100644 index 6d2f4c6067..0000000000 --- a/src/shared/components/Settings/Preferences/Email/styles.scss +++ /dev/null @@ -1,102 +0,0 @@ -@import "../../style"; -@import "~styles/mixins"; - -.EmailPreferences { - display: flex; - flex-direction: column; - gap: $margin-xxxxl; - margin-bottom: $margin-xxxxl; - - @include upto-sm { - gap: $margin-xxl; - margin-bottom: $margin-xxl; - } - - .title { - @include tc-heading-lg; - - margin-bottom: 25px; - - @include upto-sm { - font-size: 20px; - line-height: 30px; - margin: 20px; - } - } - - .sub-title, - .sub-title-2 { - @include roboto-light; - - color: #888894; - line-height: 35px; - font-weight: 300; - font-size: 28px; - margin-bottom: 30px; - margin-top: 5px; - - @include upto-sm { - display: none; - } - } - - .sub-title-2 { - margin-top: 30px; - } - - .unsubscribed-msg { - @include roboto-regular; - - display: flex; - flex-direction: column; - background-color: $tc-red-10; - border: 1px solid $tc-red-30; - color: $tc-red; - line-height: 20px; - margin-bottom: 25px; - padding: 10px; - text-align: left; - font-size: 13px; - align-items: flex-start; - - button { - margin: 20px 0 0 0; - } - } -} - -:global { - #mc-embedded-subscribe-form { - input { - display: none; - } - - #mc-embedded-subscribe { - @include roboto-bold; - - display: inline-block; - text-align: center; - margin: 0; - height: 48px; - font-size: 16px; - line-height: 24px; - letter-spacing: 0.008em; - text-transform: uppercase; - color: $color-turq-160 !important; - padding: 12px 22px; - background: $tc-white; - border: 2px solid $color-turq-160; - border-radius: 50px; - box-shadow: none; - cursor: pointer; - } - } - - // .subscribe-container { - // margin-bottom: $margin-xxxxl; - - // @include upto-sm { - // margin-bottom: $margin-xxl; - // } - // } -} diff --git a/src/shared/components/Settings/Preferences/List/Item/index.jsx b/src/shared/components/Settings/Preferences/List/Item/index.jsx deleted file mode 100644 index 0cb8f2c79d..0000000000 --- a/src/shared/components/Settings/Preferences/List/Item/index.jsx +++ /dev/null @@ -1,80 +0,0 @@ -/** - * Render item of preferences - */ -import React from 'react'; -import PT from 'prop-types'; -import ReactSVG from 'react-svg'; -import cn from 'classnames'; -import { isomorphy } from 'topcoder-react-utils'; - -import './styles.scss'; - -let assets; -if (isomorphy.isClientSide()) { - assets = require.context('assets/images/preferences', false, /svg/); -} - -export default function Item({ - icon, - title, - description, - link, - status, - linkTitle, - email, - formLink, - value, - isForm, -}) { - return ( -
    -
    -
    - { assets && assets.keys().includes(`./${icon.toLowerCase()}.svg`) ? : '' } -
    -
    -
    - { title } -
    -
    - { description } -
    -
    - { - status && isForm && ( -
    - - - - -
    - ) - } - - { !isForm && { linkTitle }} -
    -
    - ); -} - -Item.defaultProps = { - link: '', - email: '', - status: '', - value: '', - formLink: '', - isForm: false, -}; - -Item.propTypes = { - linkTitle: PT.string.isRequired, - title: PT.string.isRequired, - description: PT.string.isRequired, - status: PT.string, - link: PT.string, - isForm: PT.bool, - formLink: PT.string, - value: PT.string, - email: PT.string, - icon: PT.string.isRequired, -}; diff --git a/src/shared/components/Settings/Preferences/List/Item/styles.scss b/src/shared/components/Settings/Preferences/List/Item/styles.scss deleted file mode 100644 index 39f09efc91..0000000000 --- a/src/shared/components/Settings/Preferences/List/Item/styles.scss +++ /dev/null @@ -1,166 +0,0 @@ -@import "../../../style"; -@import "~styles/mixins"; - -.item-container { - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; - border-top: 0; - padding: 16px; - background: $tc-white; - border: 1px solid $listing-light-gray; - border-radius: 8px; - - &.subscribed { - margin-bottom: 0 !important; - } -} - -.item-container:not(:last-child) { - margin-bottom: $margin-xxxxl; - - @include upto-sm { - margin-bottom: $margin-xxl; - } -} - -.body { - display: flex; - flex-direction: row; - flex: 1; - align-items: center; - - @include upto-sm { - flex-direction: column; - align-items: flex-start; - } -} - -.icon-wrapper { - display: flex; - align-items: center; - justify-content: center; - flex: 0 0 64px; - width: 64px; - height: 64px; - background: $color-black-5; - border-radius: 4px; - margin-right: $margin-lg; - - @include upto-sm { - margin-bottom: $pad-lg; - } - - svg { - display: block; - } -} - -.link-btn { - @include roboto-bold; - - font-weight: 700; - text-align: center; - margin: 0; - height: 48px; - font-size: 16px; - line-height: 24px; - letter-spacing: 0.008em; - text-transform: uppercase; - color: $color-turq-160 !important; - padding: 12px 22px; - background: $tc-white; - border: 2px solid $color-turq-160; - border-radius: 50px; - cursor: pointer; -} - -.info { - display: flex; - flex-direction: column; - flex: 1; - - @include upto-sm { - margin-bottom: $pad-lg; - } -} - -.info-first-line { - @include roboto-regular; - - font-size: 16px; - line-height: 20px; - font-weight: 700; - letter-spacing: 0.5px; - text-transform: capitalize; -} - -.info-second-line { - @include roboto-regular; - - font-size: 16px; - line-height: 24px; - padding-right: 74px; - color: $color-black-60; - - @include upto-sm { - padding-right: 0; - } -} - -.mobile-view { - display: none; - - @include upto-sm { - display: flex; - flex-direction: column; - justify-content: space-between; - - .mobile-first-line { - @include roboto-regular; - - display: flex; - flex-direction: row; - justify-content: left; - width: 100%; - font-weight: 700; - font-size: 16px; - line-height: 20px; - letter-spacing: 0.5px; - text-transform: capitalize; - - .mobile-icon { - width: 80px; - height: 80px; - - @media screen and (max-width: 320px) { - width: 42px; - height: 42px; - } - } - - .mobile-title { - @include roboto-medium; - - font-size: 15px; - color: #262628; - width: 68%; - margin-left: 16px; - } - } - - .mobile-second-line { - @include roboto-regular; - - line-height: 20px; - text-align: justify; - font-weight: 400; - margin-top: 10px; - margin-bottom: 12px; - font-size: 14px; - color: #767676; - width: 100%; - } - } -} diff --git a/src/shared/components/Settings/Preferences/List/data.jsx b/src/shared/components/Settings/Preferences/List/data.jsx deleted file mode 100644 index 53aa8a817a..0000000000 --- a/src/shared/components/Settings/Preferences/List/data.jsx +++ /dev/null @@ -1,15 +0,0 @@ - -import { config } from 'topcoder-react-utils'; - -const data = [ - { - id: 'forum', - icon: 'forum', - name: 'Forum', - description: 'To setup your forum preferences, please click the “Go To Forum” button.', - link: `${config.URL.FORUMS_VANILLA}/profile/preferences`, - linkTitle: 'GO TO FORUM', - }, -]; - -export default data; diff --git a/src/shared/components/Settings/Preferences/List/index.jsx b/src/shared/components/Settings/Preferences/List/index.jsx deleted file mode 100644 index 4fb824c8ae..0000000000 --- a/src/shared/components/Settings/Preferences/List/index.jsx +++ /dev/null @@ -1,43 +0,0 @@ -/* eslint-disable jsx-a11y/label-has-for */ -/** - * Preferences - * Forum and Payment preferences List - */ -import _ from 'lodash'; -import React from 'react'; -import PT from 'prop-types'; -import Item from './Item'; -import data from './data'; - -const preferenceList = ({ paymentSetupCompleted }) => ( -
    - { - _.map(data, (item) => { - let itemLink; - if (item.id !== 'payment' || paymentSetupCompleted === true) { - itemLink = item.link; - } else { - itemLink = item.altLink; - } - - return ( - - ); - }) - } -
    -); - -export default preferenceList; - -preferenceList.propTypes = { - paymentSetupCompleted: PT.bool.isRequired, -}; diff --git a/src/shared/components/Settings/Preferences/Personalization/index.jsx b/src/shared/components/Settings/Preferences/Personalization/index.jsx deleted file mode 100644 index 310f3834bc..0000000000 --- a/src/shared/components/Settings/Preferences/Personalization/index.jsx +++ /dev/null @@ -1,82 +0,0 @@ -/** - * 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, - tokenV3, - updateUserTrait, - userTraits, -}) { - const primaryText = 'User Consent'; - const secondaryText = 'I allow Topcoder to use my information to make my experience more personal.'; - - const getTraitData = () => { - const trait = userTraits.filter(t => t.traitId === 'personalization'); - if (trait.length !== 0) { - return trait[0].traits.data[0]; - } - return null; - }; - - const getUserConsent = () => { - const traitData = getTraitData(); - - if (traitData && typeof traitData.userConsent === 'boolean') { - return traitData.userConsent; - } - // by default, when personalization user trait hasn't been - // created yet, user doesn't give consent - return false; - }; - - const updateConsent = () => { - const traitData = getTraitData(); - - // personalization data might not have been created yet; if so, add new trait - if (traitData && typeof traitData.userConsent === 'boolean') { - const personalizationData = { userConsent: !traitData.userConsent }; - updateUserTrait(handle, 'personalization', [personalizationData], tokenV3); - } else if (!traitData) { - // update the default (userConsent: false) when creating the new trait - const personalizationData = { userConsent: true }; - addUserTrait(handle, 'personalization', [personalizationData], tokenV3); - } - }; - - const debounceUpdateConsent = debounce(() => { - updateConsent(); - }, SAVE_DELAY); - - return ( -
    - -
    - ); -} - -Personalization.propTypes = { - tokenV3: PT.string.isRequired, - handle: PT.string.isRequired, - userTraits: PT.arrayOf(PT.shape()).isRequired, - addUserTrait: PT.func.isRequired, - updateUserTrait: PT.func.isRequired, -}; diff --git a/src/shared/components/Settings/Preferences/Personalization/styles.scss b/src/shared/components/Settings/Preferences/Personalization/styles.scss deleted file mode 100644 index 51720c6016..0000000000 --- a/src/shared/components/Settings/Preferences/Personalization/styles.scss +++ /dev/null @@ -1,15 +0,0 @@ -@import "../../style"; - -.Personalization { - .title { - @include tc-heading-lg; - - margin-bottom: 25px; - - @include upto-sm { - font-size: 20px; - line-height: 30px; - margin: 20px; - } - } -} diff --git a/src/shared/components/Settings/Preferences/index.jsx b/src/shared/components/Settings/Preferences/index.jsx deleted file mode 100644 index 2553304179..0000000000 --- a/src/shared/components/Settings/Preferences/index.jsx +++ /dev/null @@ -1,113 +0,0 @@ -/* eslint-disable prefer-destructuring */ -import _ from 'lodash'; -import React from 'react'; -import PT from 'prop-types'; -import { PrimaryButton } from 'topcoder-react-ui-kit'; -import NewsletterPreferencesContainer from 'containers/NewsletterPreferences'; -import PreferenceList from './List'; - -import ErrorWrapper from '../ErrorWrapper'; - -import styles from './styles.scss'; - -export default class Preferences extends React.Component { - constructor(props) { - super(props); - this.save = this.save.bind(this); - this.loadOnboardingChecklistTrait = this.loadOnboardingChecklistTrait.bind(this); - this.newsRef = React.createRef(); - - const { userTraits } = props; - this.state = { - onboardingChecklistTrait: this.loadOnboardingChecklistTrait(userTraits), - }; - } - - componentWillReceiveProps(nextProps) { - const { isSaving, setIsSaving } = this.props; - const onboardingChecklistTrait = this.loadOnboardingChecklistTrait(nextProps.userTraits); - this.setState({ - onboardingChecklistTrait, - }); - if (isSaving !== nextProps.isSaving) { - setTimeout(() => { - setIsSaving(false); - }, 600); - } - } - - /** - * Get onboarding checklist trait - * @param userTraits the all user traits - */ - loadOnboardingChecklistTrait = (userTraits) => { - const trait = userTraits.filter(t => t.traitId === 'onboarding_checklist'); - const onboardingChecklist = trait.length === 0 ? {} : trait[0]; - return _.assign({}, onboardingChecklist); - } - - save() { - const { isSaving, setIsSaving } = this.props; - if (isSaving) { - return; - } - setIsSaving(true); - - this.newsRef.current.getWrappedInstance().save(); - } - - render() { - const { profile: { email }, isSaving } = this.props; - const { onboardingChecklistTrait } = this.state; - let paymentSetupCompleted = false; - - if (onboardingChecklistTrait.traits && onboardingChecklistTrait.traits.data.length > 0) { - const traitData = onboardingChecklistTrait.traits.data[0]; - if (_.has(traitData, 'user_payment_method')) { - paymentSetupCompleted = !_.isEmpty(traitData.user_payment_method.payment_method) - && traitData.user_payment_method.status === 'completed'; - } - } - - const saveBtn = ( - - Save Changes - - ); - - return ( - -
    -
    -

    Platform preferences

    -
    -
    - - -
    -
    -
    {saveBtn}
    -
    - ); - } -} - -Preferences.defaultProps = { - isSaving: false, -}; - -Preferences.propTypes = { - profile: PT.shape().isRequired, - isSaving: PT.bool, - setIsSaving: PT.func.isRequired, - userTraits: PT.array.isRequired, -}; diff --git a/src/shared/components/Settings/Preferences/styles.scss b/src/shared/components/Settings/Preferences/styles.scss deleted file mode 100644 index 7ce7617a31..0000000000 --- a/src/shared/components/Settings/Preferences/styles.scss +++ /dev/null @@ -1,83 +0,0 @@ -@import '~styles/mixins'; - -.preferences-container { - background-color: $listing-filter-bg; - padding: $pad-xxxxl; - border-radius: 8px; - margin: 32px 0 32px; - - @include xs-to-sm { - padding: $pad-xxl $pad-lg; - margin: 24px 0 24px; - } - - .header { - margin: 0 0 40px; - - @include xs-to-sm { - margin: 0 0 $pad-xxl; - } - - h3 { - @include barlow-bold; - - font-size: 20px; - font-weight: 600; - line-height: 22px; - color: $tco-black; - text-transform: uppercase; - - @include xs-to-md { - @include barlow-condensed-semi-bold; - - font-weight: 500; - font-size: 22px; - line-height: 24px; - } - } - } - - .platform-banner { - background-color: $tc-white; - border-radius: 4px; - width: 100%; - padding: 32px; - - @include xs-to-sm { - padding: 24px 16px; - } - } -} - -.footer { - display: flex; - flex-direction: row-reverse; - - .save-changes-btn { - @include roboto-bold; - - font-weight: 700; - font-size: 16px; - line-height: 24px; - border-radius: 50px !important; - background: #137d60 !important; - color: #fff !important; - text-transform: uppercase; - padding: 11px 23px; - margin: 0; - - &.disabled { - opacity: 0.5; - } - } - - @include xs-to-md { - padding: $pad-xxxxl 0 $pad-sm; - border-top: 2px solid $color-black-10; - - .save-changes-btn { - font-size: 14px; - line-height: 20px; - } - } -} diff --git a/src/shared/components/Settings/ProfileSettings/AboutYou/index.jsx b/src/shared/components/Settings/ProfileSettings/AboutYou/index.jsx deleted file mode 100644 index 747073bdb8..0000000000 --- a/src/shared/components/Settings/ProfileSettings/AboutYou/index.jsx +++ /dev/null @@ -1,75 +0,0 @@ -/** - * About You Form - * Profile Settings Page - */ -import React from 'react'; -import PT from 'prop-types'; -import FormField from 'components/Settings/FormField'; -import FormInputText from 'components/Settings/FormInputText'; -import FormInputTextArea from 'components/Settings/FormInputTextArea'; - -import '../styles.scss'; - -const AboutYou = (props) => { - const { - canModifyTrait, - newProfileInfo, - newBasicInfo, - onUpdateInput, - } = props; - - return ( -
    -
    -
    - {/* Current Location */} - - - - - {/* Primary interests */} - - - -
    -
    -
    - ); -}; - -AboutYou.defaultProps = { - canModifyTrait: false, - newProfileInfo: {}, - newBasicInfo: {}, -}; - -AboutYou.propTypes = { - canModifyTrait: PT.bool, - newProfileInfo: PT.shape(), - newBasicInfo: PT.shape(), - onUpdateInput: PT.func.isRequired, -}; - -export default AboutYou; diff --git a/src/shared/components/Settings/ProfileSettings/Hobbies/List/Item/index.jsx b/src/shared/components/Settings/ProfileSettings/Hobbies/List/Item/index.jsx deleted file mode 100644 index 23e6795188..0000000000 --- a/src/shared/components/Settings/ProfileSettings/Hobbies/List/Item/index.jsx +++ /dev/null @@ -1,111 +0,0 @@ -/** - * render hobby Item - */ -import _ from 'lodash'; -import React from 'react'; -import PT from 'prop-types'; -import ReactSVG from 'react-svg'; -import Tooltip from 'components/Tooltip'; - -import { isomorphy } from 'topcoder-react-utils'; - - -import './styles.scss'; - -let assets; -if (isomorphy.isClientSide()) { - assets = require.context('assets/images/profile', false, /svg/); -} - -export default function Item(props) { - const { - hobby, - index, - onDeleteItem, - onEditItem, - } = props; - - const hasSecondLine = () => { - if (_.isEmpty(hobby.description)) { - return false; - } - - return true; - }; - - const deleteTip = ( -
    -

    Delete

    -
    - ); - - const editTip = ( -
    -

    Edit

    -
    - ); - - return ( - - ); -} - -Item.propTypes = { - hobby: PT.shape().isRequired, - index: PT.number.isRequired, - onDeleteItem: PT.func.isRequired, - onEditItem: PT.func.isRequired, -}; diff --git a/src/shared/components/Settings/ProfileSettings/Hobbies/List/Item/styles.scss b/src/shared/components/Settings/ProfileSettings/Hobbies/List/Item/styles.scss deleted file mode 100644 index 6ec48cef73..0000000000 --- a/src/shared/components/Settings/ProfileSettings/Hobbies/List/Item/styles.scss +++ /dev/null @@ -1,193 +0,0 @@ -@import "../../../../style"; - -.container { - display: flex; - flex-direction: row; - justify-items: center; - justify-content: space-between; - align-items: center; - min-height: 96px; - width: 100%; - border-bottom: none; - background-color: $tc-white; - padding: $pad-lg; - border: 1px solid $color-black-20; - border-radius: 8px; -} - -.hobby-info { - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; -} - -.hobby-icon { - display: flex; - align-items: center; - justify-content: center; - flex: 0 0 64px; - width: 64px; - height: 64px; - background: $color-black-5; - border-radius: 4px; - margin-right: $margin-lg; - - svg { - display: block; - } -} - -.hobby-parameters { - @include roboto-medium; - - display: flex; - flex-direction: column; - justify-items: center; - justify-content: center; - font-size: 15px; - line-height: 20px; - text-transform: capitalize; - padding-right: 20px; - - &.single-line { - flex-direction: row; - align-items: center; - } -} - -.parameter-first-line { - @include roboto-bold; - - color: $tc-black; - font-weight: 700; - font-size: 16px; - line-height: 20px; - letter-spacing: 0.5px; - text-transform: capitalize; - word-break: break-all; - - &.single-line { - margin-bottom: 0; - } - - @include upto-sm { - margin-bottom: 0; - } -} - -.parameter-second-line, -.parameter-third-line { - @include roboto-medium; - - color: $color-black-60; - font-weight: 400; - font-size: 16px; - line-height: 24px; - word-break: break-all; -} - -.tctooltiptext { - background: $tooltip-gray; - color: $tc-white; - border-radius: 8px; - padding: 10px; - - p { - @include roboto-medium; - - font-weight: 400; - font-size: 14px; - line-height: 22px; - } -} - -.tctooltiptext::after { - content: ""; - position: absolute; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; - bottom: 4px; - margin-left: -5px; - border-width: 5px 5px 0; - left: 50%; - border-top-color: $tc-black; - z-index: 1000; -} - -.operation-container { - display: flex; - flex-direction: row; - justify-content: space-between; - - .delete-wrapper { - margin-left: $margin-xl; - margin-right: $margin-xs; - - @include xs-to-sm { - margin-left: $margin-lg; - margin-right: 0; - } - - @media screen and (max-width: 320px) { - margin-right: 0; - margin-left: 6px; - } - } - - .delete { - display: flex; - flex-direction: column; - justify-items: center; - justify-content: center; - cursor: pointer; - outline-style: none; - - img { - width: 20px; - height: 20px; - } - - p { - @include roboto-regular; - - font-size: 11px; - line-height: 15px; - font-weight: 400; - color: $tc-gray-50; - - @include upto-sm { - display: none; - } - } - } - - .edit { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - cursor: pointer; - outline-style: none; - - img { - width: 20px; - height: 20px; - } - - p { - @include roboto-regular; - - font-size: 11px; - line-height: 15px; - font-weight: 400; - color: $tc-gray-50; - - @include upto-sm { - display: none; - } - } - } -} diff --git a/src/shared/components/Settings/ProfileSettings/Hobbies/List/index.jsx b/src/shared/components/Settings/ProfileSettings/Hobbies/List/index.jsx deleted file mode 100644 index 34767a332a..0000000000 --- a/src/shared/components/Settings/ProfileSettings/Hobbies/List/index.jsx +++ /dev/null @@ -1,41 +0,0 @@ -/** - * render Hobby list - */ -import React from 'react'; -import PT from 'prop-types'; -import Item from './Item'; - -import './styles.scss'; - -export default function HobbyList(props) { - const { - hobbyList, - onDeleteItem, - onEditItem, - } = props; - - return ( -
    0 ? 'active' : ''}`}> -
      - { - hobbyList.items.map((hobby, index) => ( -
    • - -
    • - )) - } -
    -
    - ); -} - -HobbyList.propTypes = { - hobbyList: PT.shape().isRequired, - onDeleteItem: PT.func.isRequired, - onEditItem: PT.func.isRequired, -}; diff --git a/src/shared/components/Settings/ProfileSettings/Hobbies/List/styles.scss b/src/shared/components/Settings/ProfileSettings/Hobbies/List/styles.scss deleted file mode 100644 index 53bec1cf29..0000000000 --- a/src/shared/components/Settings/ProfileSettings/Hobbies/List/styles.scss +++ /dev/null @@ -1,30 +0,0 @@ -@import "../../../style"; - -.container { - width: 100%; - background-color: $tc-white; - padding: 0; - margin-bottom: 20px; - - @include upto-sm { - margin-top: 32px; - } - - &.active { - margin-top: 0; - - @include upto-sm { - margin-top: 0; - } - } - - ul { - display: flex; - flex-direction: column; - justify-items: center; - - li { - margin-bottom: $margin-md; - } - } -} diff --git a/src/shared/components/Settings/ProfileSettings/Hobbies/index.jsx b/src/shared/components/Settings/ProfileSettings/Hobbies/index.jsx deleted file mode 100644 index 59f283a31d..0000000000 --- a/src/shared/components/Settings/ProfileSettings/Hobbies/index.jsx +++ /dev/null @@ -1,127 +0,0 @@ -/* eslint-disable jsx-a11y/label-has-for */ -/** - * Hobbies Form - * Profile Settings Page - */ -import _ from 'lodash'; -import React from 'react'; -import PT from 'prop-types'; - -import ErrorMessage from 'components/Settings/ErrorMessage'; -import FormInputText from 'components/Settings/FormInputText'; -import FormInputTextArea from 'components/Settings/FormInputTextArea'; -import FormField from 'components/Settings/FormField'; -import AddItemIcon from 'assets/images/settings-add-item.svg'; - -import './styles.scss'; - -const Hobbies = (props) => { - const { - isEdit, - canModifyTrait, - isSubmit, - formInvalid, - newHobby, - onUpdateInput, - onHandleAddHobby, - onCancelEditStatus, - } = props; - - return ( -
    -
    -
    - {/* Hobby */} - - - { - isSubmit && formInvalid && ( - - ) - } - - - {/* Description */} - - - -
    -
    - {!isEdit && ( - - Add hobby to your list - - )} - - { isEdit && ( - - - Edit hobby to your list - - - - Cancel - - - - )} -
    -
    -
    - ); -}; - -Hobbies.defaultProps = { - isEdit: false, - formInvalid: false, - isSubmit: false, - newHobby: {}, -}; - -Hobbies.propTypes = { - isEdit: PT.bool, - canModifyTrait: PT.bool.isRequired, - formInvalid: PT.bool, - isSubmit: PT.bool, - newHobby: PT.shape(), - onUpdateInput: PT.func.isRequired, - onHandleAddHobby: PT.func.isRequired, - onCancelEditStatus: PT.func.isRequired, -}; - -export default Hobbies; diff --git a/src/shared/components/Settings/ProfileSettings/Hobbies/styles.scss b/src/shared/components/Settings/ProfileSettings/Hobbies/styles.scss deleted file mode 100644 index f1efdaf9e2..0000000000 --- a/src/shared/components/Settings/ProfileSettings/Hobbies/styles.scss +++ /dev/null @@ -1,324 +0,0 @@ -@import "~styles/mixins"; -@import "../../style.scss"; - -.edit-text-wrapper { - cursor: pointer; - display: flex; - align-items: center; - gap: 8px 36px; -} - -.edit-text { - @include roboto-bold; - - font-weight: 700; - font-size: 14px; - line-height: 22px; - text-align: center; - color: $listing-checkbox-green; - cursor: pointer; - display: flex; - align-items: center; - gap: 4px; -} - -.hide { - display: none; -} - -textarea { - @include placeholder { - text-transform: uppercase; - } -} - -.hobby-container { - display: flex; - flex-direction: column; - align-items: left; - - h1 { - @include roboto-regular; - - font-size: 28px; - line-height: 35px; - font-weight: 400; - color: $tc-black; - margin-bottom: 20px; - - @include upto-sm { - display: none; - } - } - - .sub-title { - @include roboto-light; - - color: #888894; - line-height: 35px; - font-weight: 300; - font-size: 28px; - margin-bottom: 10px; - - &.second { - margin-top: 50px; - margin-bottom: 30px; - } - - &.first { - margin-bottom: 30px; - } - - &.hidden { - display: none; - } - - @include upto-sm { - display: none; - } - } - - @include upto-sm { - margin-top: 32px; - } -} - -.error-message { - display: none; - - &.active { - @include roboto-medium; - - display: block; - border-radius: 5px; - background-color: $tc-red-10; - color: $tc-red-110; - font-size: 15px; - padding: 15px; - margin: 15px 0; - } -} - -.form-container-default { - @include form-container-default; - - input { - @include roboto-regular; - - height: 40px; - font-size: 15px; - line-height: 20px; - font-weight: 400; - color: $tc-black; - border: 1px solid $tc-gray-20; - border-radius: $corner-radius * 2 $corner-radius * 2 $corner-radius * 2 $corner-radius * 2; - margin-bottom: 0; - } - - .text-required { - @include roboto-medium; - - font-size: 10px; - color: $tc-red-110; - margin-bottom: 5px; - text-align: right; - } - - .description { - display: flex; - flex-direction: column; - - .first-line { - display: flex; - justify-content: flex-end; - - .description-counts { - @include roboto-medium; - - font-size: 11px; - color: $tc-dark-blue-110; - text-align: right; - margin-right: 10px; - } - } - - .description-text { - height: 70px; - border-radius: 4px; - margin-bottom: 10px; - } - } -} - -.form-container-mobile { - display: none; - - @include upto-sm { - display: flex; - flex-direction: column; - border-radius: 6px; - border: 1px solid $tc-gray-10; - padding: 20px 20px 20px 20px; - background-color: $tc-gray-neutral-light; - } - - p { - @include roboto-regular; - - font-size: 20px; - line-height: 30px; - font-weight: 400; - color: $tc-black; - margin-bottom: 10px; - - @include upto-sm { - margin-bottom: 20px; - } - } - - .row { - display: flex; - flex-direction: row; - margin-bottom: 10px; - align-content: space-between; - - @include upto-sm { - width: 100%; - display: block; - margin-bottom: 0; - } - - .field { - display: flex; - flex: 1; - flex-direction: column; - margin-right: 10px; - - @include upto-sm { - display: flex; - flex-direction: column; - padding-bottom: 10px; - } - - label { - @include roboto-medium; - - display: block; - font-size: 12px; - line-height: 15px; - font-weight: 500; - color: $tc-gray-80; - - .text-required { - font-size: 10px; - color: $tc-red-110; - margin-left: 5px; - } - } - - &.col-1, - &.col-1-no-padding { - // width: auto; - } - - &.col-2 { - // width: auto; - } - - &.row-1 { - width: 280px; - - @include from-sm-to-lg { - width: 383px; - } - - @include upto-sm { - width: 100%; - } - } - - &.row-2 { - min-width: 100%; - } - - .description-label { - display: flex; - justify-content: space-between; - } - - .description-text { - height: 70px; - border-radius: 4px; - margin-top: 6px; - margin-bottom: 10px; - resize: vertical; - } - - .description-counts { - @include roboto-medium; - - font-size: 11px; - color: $tc-dark-blue-110; - } - } - - div.field:last-child { - margin-right: 0; - } - } - - input { - @include roboto-regular; - - height: 36px; - margin: 0; - font-size: 15px; - line-height: 20px; - font-weight: 400; - color: $tc-black; - border: 1px solid $tc-gray-20; - border-radius: $corner-radius * 2 $corner-radius * 2 $corner-radius * 2 $corner-radius * 2; - margin-top: 6px; - } - - textarea { - resize: vertical; - min-width: 100%; - } - - @include upto-sm { - border: 0; - border-radius: 0; - } -} - -.button-container { - display: flex; - justify-content: center; - align-items: center; - - .button-save, - .button-cancel { - align-self: center; - - button, - a { - @include roboto-medium; - - height: 40px; - font-size: 15px; - font-weight: 500; - margin: 0; - padding: 0; - min-width: 200px; - } - - .complete { - color: $tc-white; - } - } - - .button-cancel { - margin-left: 10px; - } -} diff --git a/src/shared/components/Settings/ProfileSettings/ImageInput/index.jsx b/src/shared/components/Settings/ProfileSettings/ImageInput/index.jsx deleted file mode 100644 index 4a691e7fde..0000000000 --- a/src/shared/components/Settings/ProfileSettings/ImageInput/index.jsx +++ /dev/null @@ -1,154 +0,0 @@ -/** - * render a user icom input component. - */ -/* global document */ -/* eslint-disable react/forbid-prop-types */ -import React, { useState } from 'react'; -import PT from 'prop-types'; - -import { Button } from 'topcoder-react-ui-kit'; -import IconEdit from 'assets/images/icon-edit.svg'; -import IconUpload from 'assets/images/icon-upload.svg'; -import loadImage from 'blueimp-load-image'; - -import _ from 'lodash'; -import style from './styles.scss'; -import PageRow from '../../PageRow'; - - -const ImageInput = ({ - handle, tokenV3, - uploadPhoto, uploadPhotoInit, profileState, profile, -}) => { - const { photoURL } = profile; - const [isImageOversize, setIsImageOversize] = useState(false); - const [isImageFile, setIsImageFile] = useState(true); - - const onChangeImage = (e) => { - e.preventDefault(); - if (!_.isEmpty(profileState) && profileState.uploadingPhoto) { - return; - } - const fileInput = document.querySelector('#change-image-input'); - fileInput.click(); - }; - - const onUploadPhoto = (e) => { - e.preventDefault(); - if (profileState.uploadingPhoto) { - return; - } - const fileInput = document.querySelector('#change-image-input'); - const file = fileInput.files[0]; - if (file === undefined) { - return; - } - const allowedTypes = ['image/png', 'image/jpg', 'image/jpeg']; - if (!allowedTypes.includes(file.type)) { - setIsImageFile(false); - return; - } - if (file.size > 2 * 1024 * 1024) { - // If file size is greater than 2 MB, show error message - setIsImageOversize(true); - return; - } - setIsImageOversize(false); - setIsImageFile(true); - uploadPhotoInit(); - loadImage.parseMetaData(file, (data) => { - let orientation = 0; - if (data.exif) { - orientation = data.exif.get('Orientation'); - } - loadImage( - file, - (img) => { - img.toBlob( - (blobResult) => { - uploadPhoto(handle, tokenV3, blobResult); - }, - ); - }, { - canvas: true, - orientation, - }, - ); - }); - }; - - const { uploadingPhoto } = profileState; - - return ( -
    - -
    -

    ADD YOUR IMAGE

    -
    -

    Show the community who you are. Don't worry, you look great.

    - Requirements: -
      -
    • PNG or JPG format.
    • -
    • Maximum size: 2MB.
    • -
    -
    -
    - {!photoURL && ( -
    -
    - -
    - )} - {photoURL && ( -
    -
    - -
    - )} - - - {!isImageFile &&
    Please select jpg, jpeg or png image files only
    } - {isImageFile && isImageOversize &&
    Please select an image smaller than 2MB
    } -
    - ); -}; - -ImageInput.defaultProps = { - profile: {}, - profileState: {}, -}; - -ImageInput.propTypes = { - handle: PT.string.isRequired, - tokenV3: PT.string.isRequired, - profile: PT.shape(), - profileState: PT.shape(), - uploadPhoto: PT.func.isRequired, - uploadPhotoInit: PT.func.isRequired, -}; - -export default ImageInput; diff --git a/src/shared/components/Settings/ProfileSettings/ImageInput/styles.scss b/src/shared/components/Settings/ProfileSettings/ImageInput/styles.scss deleted file mode 100644 index df73030983..0000000000 --- a/src/shared/components/Settings/ProfileSettings/ImageInput/styles.scss +++ /dev/null @@ -1,134 +0,0 @@ -@import "~styles/mixins"; - -.image-input { - border-top: 1px solid $listing-light-gray; - margin-top: 42px; - margin-bottom: 40px; - padding-top: 32px; - - @include xs-to-md { - margin-top: 22px; - } - - .title { - @include barlow-bold; - - font-weight: 600; - line-height: 26px; - font-size: 22px; - color: $tco-black; - - @include xs-to-md { - @include barlow-condensed-semi-bold; - - line-height: 24px; - } - } - - .sub-title { - @include roboto-regular; - - font-weight: 400; - font-size: 16px; - line-height: 24px; - color: $tco-black; - margin-top: 24px; - - @include xs-to-md { - margin-top: 22px; - font-size: 14px; - line-height: 20px; - } - - p { - margin-bottom: 8px; - } - - ul { - list-style: unset; - margin-left: 24px; - } - } -} - -.upload-profile-photo { - display: flex; - align-items: center; - margin-top: 50px; - - @include xs-to-md { - margin: 35px 16px; - } - - & > button { - margin-left: 15px !important; - } - - .profile-photo { - width: 104px; - height: 104px; - border-radius: 50%; - background-size: cover; - background-position: center; - background-repeat: no-repeat; - margin-right: -30px; - } - - .profile-photo-void { - width: 100px; - height: 100px; - border-radius: 50%; - background: #fafafa; - background-size: cover; - background-position: center; - background-repeat: no-repeat; - margin-right: -30px; - border: 2px dashed #ddd; - } - - .icon-edit { - width: 20px; - } - - .icon-upload { - width: 20px; - margin: 0 5px 0 0; - } - - .uploadButton { - background-color: $listing-checkbox-green; - padding: 8px 24px 8px 20px; - border-radius: 24px; - border: 0 !important; - height: 40px; - color: $tc-white; - - &:hover { - background: darken($listing-checkbox-green, 5%); - } - - span { - @include roboto-bold; - - font-weight: 700; - font-size: 14px; - line-height: 24px; - } - } -} - -.error-message { - @include roboto-medium; - - display: block; - border-radius: 5px; - background-color: $tc-red-10; - color: $tc-red-110; - font-size: 15px; - padding: 15px; - margin: 15px 0; -} - -.uploading { - width: 155px; -} diff --git a/src/shared/components/Settings/ProfileSettings/Learning/List/Item/index.jsx b/src/shared/components/Settings/ProfileSettings/Learning/List/Item/index.jsx deleted file mode 100644 index 19fdd9b684..0000000000 --- a/src/shared/components/Settings/ProfileSettings/Learning/List/Item/index.jsx +++ /dev/null @@ -1,176 +0,0 @@ -/** - * render education Item - */ -import _ from 'lodash'; -import React from 'react'; -import PT from 'prop-types'; -import ReactSVG from 'react-svg'; -import moment from 'moment'; -import { isomorphy } from 'topcoder-react-utils'; -import Tooltip from 'components/Tooltip'; - -import './styles.scss'; - -let assets; -if (isomorphy.isClientSide()) { - assets = require.context('assets/images/profile', false, /svg/); -} - -export default function Item(props) { - const { - education, - index, - onDeleteItem, - onEditItem, - } = props; - - const hasSecondLine = () => { - if (_.isEmpty(education.timePeriodFrom) && _.isEmpty(education.timePeriodTo) - && !education.graduated) { - return false; - } - - return true; - }; - - const getDate = () => { - let start = ''; - if (!_.isEmpty(education.timePeriodFrom)) { - start = moment(education.timePeriodFrom).format('YYYY'); - } - let end = ''; - if (!_.isEmpty(education.timePeriodTo)) { - end = moment(education.timePeriodTo).format('YYYY'); - } - - if (_.isEmpty(start) && _.isEmpty(end)) { - return ''; - } - - if (!_.isEmpty(start) && !_.isEmpty(end)) { - return `${start} - ${end} `; - } - - if (!_.isEmpty(start) && _.isEmpty(end)) { - return `${start} `; - } - - if (_.isEmpty(start) && !_.isEmpty(end)) { - return `${end} `; - } - - return ''; - }; - - const getGraduated = () => { - const date = getDate(); - if (!_.isEmpty(date)) { - if (education.graduated) { - return '| Graduated'; - } - - return ''; - } - - if (education.graduated) { - return 'Graduated'; - } - return ''; - }; - - const deleteTip = ( -
    -

    Delete

    -
    - ); - - const editTip = ( -
    -

    Edit

    -
    - ); - - return ( -
    -
    -
    - -
    -
    -
    - { education.major ? `${education.schoolCollegeName} | ${education.major}` : `${education.schoolCollegeName}`} -
    - { - hasSecondLine() && ( - -
    - { - `${getDate()}${getGraduated()}` - } -
    -
    - { - !_.isEmpty(getDate()) && ( -

    - {`${getDate()}`} -

    - ) - } - { - education.graduated && ( -

    - Graduated -

    - ) - } -
    -
    - ) - } -
    -
    - -
    - ); -} - -Item.propTypes = { - education: PT.shape().isRequired, - index: PT.number.isRequired, - onDeleteItem: PT.func.isRequired, - onEditItem: PT.func.isRequired, -}; diff --git a/src/shared/components/Settings/ProfileSettings/Learning/List/Item/styles.scss b/src/shared/components/Settings/ProfileSettings/Learning/List/Item/styles.scss deleted file mode 100644 index 6cdaa4ebb3..0000000000 --- a/src/shared/components/Settings/ProfileSettings/Learning/List/Item/styles.scss +++ /dev/null @@ -1,211 +0,0 @@ -@import "../../../../style"; - -.container { - display: flex; - flex-direction: row; - justify-items: center; - justify-content: space-between; - align-items: center; - min-height: 96px; - width: 100%; - border-bottom: none; - background-color: $tc-white; - padding: $pad-lg; - border: 1px solid $color-black-20; - border-radius: 8px; -} - -.education-info { - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; -} - -.education-icon { - display: flex; - align-items: center; - justify-content: center; - flex: 0 0 64px; - width: 64px; - height: 64px; - background: $color-black-5; - border-radius: 4px; - margin-right: $margin-lg; - - svg { - display: block; - } -} - -.education-parameters { - @include roboto-medium; - - display: flex; - flex-direction: column; - justify-items: center; - justify-content: center; - font-size: 15px; - line-height: 20px; - text-transform: capitalize; - padding-right: 20px; - - &.single-line { - flex-direction: row; - align-items: center; - } -} - -.parameter-first-line { - @include roboto-bold; - - color: $tc-black; - font-weight: 700; - font-size: 16px; - line-height: 20px; - letter-spacing: 0.5px; - text-transform: capitalize; - word-break: break-all; - - &.single-line { - margin-bottom: 0; - } - - @include upto-sm { - margin-bottom: 0; - } -} - -.parameter-second-line, -.parameter-third-line, -.parameter-second-line-mobile { - @include roboto-medium; - - color: $color-black-60; - font-weight: 400; - font-size: 16px; - line-height: 24px; - word-break: break-all; - - @include upto-sm { - display: none; - } -} - -.parameter-second-line-mobile { - display: none; - - @include upto-sm { - display: flex; - flex-direction: column; - - p { - word-break: break-all; - } - } -} - -.tctooltiptext { - background: $tooltip-gray; - color: $tc-white; - border-radius: 8px; - padding: 10px; - - p { - @include roboto-medium; - - font-weight: 400; - font-size: 14px; - line-height: 22px; - } -} - -.tctooltiptext::after { - content: ""; - position: absolute; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; - bottom: 4px; - margin-left: -5px; - border-width: 5px 5px 0; - left: 50%; - border-top-color: $tc-black; - z-index: 1000; -} - -.operation-container { - display: flex; - flex-direction: row; - justify-content: space-between; - - .delete-wrapper { - margin-left: $margin-xl; - margin-right: $margin-xs; - - @include xs-to-sm { - margin-left: $margin-lg; - margin-right: 0; - } - - @media screen and (max-width: 320px) { - margin-right: 0; - margin-left: 6px; - } - } - - .delete { - display: flex; - flex-direction: column; - justify-items: center; - justify-content: center; - cursor: pointer; - outline-style: none; - - img { - width: 20px; - height: 20px; - } - - p { - @include roboto-regular; - - font-size: 11px; - line-height: 15px; - font-weight: 400; - color: $tc-gray-50; - - @include upto-sm { - display: none; - } - } - } - - .edit { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - cursor: pointer; - outline-style: none; - - img { - width: 20px; - height: 20px; - } - - p { - @include roboto-regular; - - font-size: 11px; - line-height: 15px; - font-weight: 400; - color: $tc-gray-50; - - @include upto-sm { - display: none; - } - } - } -} diff --git a/src/shared/components/Settings/ProfileSettings/Learning/List/index.jsx b/src/shared/components/Settings/ProfileSettings/Learning/List/index.jsx deleted file mode 100644 index 624afdc5f3..0000000000 --- a/src/shared/components/Settings/ProfileSettings/Learning/List/index.jsx +++ /dev/null @@ -1,41 +0,0 @@ -/** - * render Education list - */ -import React from 'react'; -import PT from 'prop-types'; -import Item from './Item'; - -import './styles.scss'; - -export default function EducationList(props) { - const { - educationList, - onDeleteItem, - onEditItem, - } = props; - - return ( -
    0 ? 'active' : ''}`}> -
      - { - educationList.items.map((education, index) => ( -
    • - -
    • - )) - } -
    -
    - ); -} - -EducationList.propTypes = { - educationList: PT.shape().isRequired, - onDeleteItem: PT.func.isRequired, - onEditItem: PT.func.isRequired, -}; diff --git a/src/shared/components/Settings/ProfileSettings/Learning/List/styles.scss b/src/shared/components/Settings/ProfileSettings/Learning/List/styles.scss deleted file mode 100644 index 8dcf8b2f15..0000000000 --- a/src/shared/components/Settings/ProfileSettings/Learning/List/styles.scss +++ /dev/null @@ -1,30 +0,0 @@ -@import "../../../style"; - -.container { - width: 100%; - background-color: $tc-white; - padding: 0 0; - margin-bottom: 20px; - - @include upto-sm { - margin-top: 32px; - } - - &.active { - margin-top: 0; - - @include upto-sm { - margin-top: 0; - } - } - - ul { - display: flex; - flex-direction: column; - justify-items: center; - - li { - margin-bottom: $margin-md; - } - } -} diff --git a/src/shared/components/Settings/ProfileSettings/Learning/index.jsx b/src/shared/components/Settings/ProfileSettings/Learning/index.jsx deleted file mode 100644 index 86b1cf3f23..0000000000 --- a/src/shared/components/Settings/ProfileSettings/Learning/index.jsx +++ /dev/null @@ -1,219 +0,0 @@ -/* eslint-disable react/prop-types */ -/* eslint-disable react/jsx-no-bind */ -/** - * Learning And Education Form - * Profile Settings Page - */ -import _ from 'lodash'; -import React from 'react'; -import PT from 'prop-types'; -import moment from 'moment'; - -import ErrorMessage from 'components/Settings/ErrorMessage'; -import FormInputText from 'components/Settings/FormInputText'; -import FormField from 'components/Settings/FormField'; -import AddItemIcon from 'assets/images/settings-add-item.svg'; -import FormInputDatePicker from 'components/Settings/FormInputDatePicker'; - -import './styles.scss'; - -const Learning = (props) => { - const { - formInvalid, - isSubmit, - isEdit, - startDateInvalid, - startDateInvalidMsg, - endDateInvalid, - endDateInvalidMsg, - newEducation, - onUpdateInput, - onUpdateDate, - onHandleAddEducation, - onCancelEditStatus, - } = props; - - return ( -
    -
    -
    - {/* Name of College or University */} - - - { - isSubmit && formInvalid && ( - - ) - } - - - {/* Degree */} - - - - -
    - {/* Start Date */} - - - onUpdateDate(date, 'timePeriodFrom')} - /> - - {isSubmit && ( - - )} - - - {/* End Date */} - - - { - newEducation.graduated ? ( - onUpdateDate(date, 'timePeriodTo')} - /> - ) : ( - onUpdateDate(date, 'timePeriodTo')} - allowFutureYear - /> - ) - } - - { - isSubmit && ( - - ) - } - -
    - -
    -
    - - -
    - -
    -
    -
    - {!isEdit && ( - - Add School / Degree - - )} - - { isEdit && ( - - - Edit School / Degree - - - - Cancel - - - - )} -
    -
    -
    - ); -}; - -Learning.defaultProps = { - formInvalid: false, - isSubmit: false, - isEdit: false, - newEducation: {}, - startDateInvalid: false, - startDateInvalidMsg: '', - endDateInvalid: false, - endDateInvalidMsg: '', -}; - -Learning.propTypes = { - formInvalid: PT.bool, - isSubmit: PT.bool, - isEdit: PT.bool, - startDateInvalid: PT.bool, - startDateInvalidMsg: PT.string, - endDateInvalid: PT.bool, - endDateInvalidMsg: PT.string, - newEducation: PT.shape(), - onUpdateInput: PT.func.isRequired, - onUpdateDate: PT.func.isRequired, - onHandleAddEducation: PT.func.isRequired, - onCancelEditStatus: PT.func.isRequired, -}; - -export default Learning; diff --git a/src/shared/components/Settings/ProfileSettings/Learning/styles.scss b/src/shared/components/Settings/ProfileSettings/Learning/styles.scss deleted file mode 100644 index 911f4828ae..0000000000 --- a/src/shared/components/Settings/ProfileSettings/Learning/styles.scss +++ /dev/null @@ -1,468 +0,0 @@ -/* stylelint-disable property-no-unknown */ -/* stylelint-disable no-descending-specificity */ -@import "~styles/mixins"; -@import "../../style.scss"; - -$checkbox-size: $base-unit * 4; -$checkbox-bg-empty: $tc-gray-neutral-light; -$checkbox-bg-selected: $tc-dark-blue; - -.date-wrapper { - display: flex; - width: 100%; - justify-content: space-between; - gap: 10px; - - & > div { - width: 100%; - } -} - -.datePicker { - input { - border: 0 !important; - padding-top: 0 !important; - padding-bottom: 0 !important; - height: 25px !important; - } -} - -.tc-checkbox { - height: $checkbox-size; - width: $checkbox-size; - margin-bottom: 130px; - position: absolute; - display: inline-block; - bottom: auto; - - @include upto-sm { - margin-bottom: 10px; - } - - input[type=checkbox] { - display: none; - } - - label { - cursor: pointer; - position: absolute; - display: inline-block; - width: $checkbox-size; - height: $checkbox-size; - top: 0; - left: 0; - border-radius: $corner-radius; - box-shadow: none; - border: 1px solid $tc-gray-50; - background: $tc-gray-neutral-light; - - &::after { - opacity: 0; - content: ''; - position: absolute; - width: 13px; - height: 7px; - background: transparent; - top: 4px; - left: 3px; - border: 3px solid $tc-dark-blue; - border-top: none; - border-right: none; - transform: rotate(-45deg); - } - - &:hover::after { - opacity: 0.3; - } - } - - input[type=checkbox]:checked ~ label { - background: $checkbox-bg-selected; - border-color: $checkbox-bg-selected; - } - - input[type=checkbox]:checked + label::after { - opacity: 1; - border-color: $tc-white; - } -} - -.checkbox-wrapper { - display: flex; - margin-left: -4px; - - .checkbox-input-wrapper { - input[type=checkbox] { - accent-color: #137d60 !important; - box-sizing: border-box; - visibility: visible; - border: 1.5px solid #7f7f7f; - border-radius: 3px; - height: $checkbox-size; - width: $checkbox-size; - } - } - - .graduated { - @include roboto-regular; - - font-weight: 400; - font-size: 16px; - line-height: 24px; - color: $tco-black; - margin: 0; - } - - .checkbox-input-label { - display: inline-block; - - @include roboto-regular; - - font-size: 13px; - line-height: $checkbox-size; - vertical-align: middle; - margin-left: $base-unit * 6; - user-select: none; - cursor: pointer; - } -} - -.edit-text-wrapper { - cursor: pointer; - display: flex; - align-items: center; - gap: 8px 36px; -} - -.edit-text { - @include roboto-bold; - - font-weight: 700; - font-size: 14px; - line-height: 22px; - text-align: center; - color: $listing-checkbox-green; - display: flex; - align-items: center; - gap: 4px; -} - -.hide { - display: none; -} - -.education-container { - display: flex; - flex-direction: column; - align-items: left; - - :global { - .SingleDatePickerInput { - &__showClearDate { - padding-right: 0; - } - - &_clearDate { - padding: 8px 10px; - top: 20px; - background: transparent; - } - } - } - - @include upto-sm { - padding-bottom: 0; - margin-top: 32px; - } -} - -.error-message { - display: none; - - &.active { - @include roboto-medium; - - display: block; - border-radius: 5px; - background-color: $tc-red-10; - color: $tc-red-110; - font-size: 15px; - line-height: 21px; - padding: 12px 15px; - margin-bottom: 15px; - white-space: pre-line; - } -} - -label { - @include roboto-medium; - - display: block; - font-size: 12px; - line-height: 15px; - font-weight: 500; - color: $tc-gray-80; - margin-bottom: 5px; - - .text-required { - font-size: 10px; - color: $tc-red-110; - margin-left: 5px; - } -} - -.form-container-default { - @include form-container-default; - - input { - @include roboto-regular; - - height: 40px; - font-size: 15px; - line-height: 20px; - font-weight: 400; - color: $tc-black; - border: 1px solid $tc-gray-20; - border-radius: $corner-radius * 2 $corner-radius * 2 $corner-radius * 2 $corner-radius * 2; - margin-bottom: 0; - } - - .text-required { - @include roboto-medium; - - font-size: 10px; - color: $tc-red-110; - margin-bottom: 5px; - text-align: right; - } - - .tc-checkbox-label { - display: inline-block; - - @include roboto-regular; - - font-size: 13px; - line-height: $checkbox-size; - vertical-align: middle; - margin-left: $base-unit * 6; - user-select: none; - cursor: pointer; - } - - .row { - .field { - &.col-1, - &.col-1-no-padding { - max-width: 200px; - min-width: 200px; - } - } - } -} - -.form-container-mobile { - display: none; - - @include upto-sm { - border: 0; - border-radius: 0; - display: flex; - flex-direction: column; - padding: 20px 20px 20px 20px; - background-color: $tc-gray-neutral-light; - } - - p { - @include roboto-regular; - - font-size: 20px; - line-height: 30px; - font-weight: 400; - color: $tc-black; - - @include upto-sm { - margin-bottom: 20px; - } - } - - .row { - display: flex; - flex-direction: row; - margin-bottom: 20px; - align-content: space-between; - width: 100%; - - @include upto-sm { - display: block; - margin-bottom: 0; - } - - div:last-child { - margin-right: 0; - } - - .field { - display: flex; - flex-direction: column; - margin-right: 10px; - - @include upto-sm { - display: flex; - flex-direction: column; - padding-bottom: 10px; - } - - .tc-checkbox-label { - display: inline-block; - - @include roboto-regular; - - font-size: 13px; - line-height: $checkbox-size; - vertical-align: middle; - margin-left: $base-unit * 6; - user-select: none; - cursor: pointer; - } - - .date-input { - display: flex; - align-items: center; - } - - &.col-1, - &.col-1-no-padding { - width: 23%; - - @include upto-sm { - width: 100%; - } - } - - &.col-2 { - width: 51%; - - @include upto-sm { - width: 100%; - } - } - - &.col-3 { - width: 26%; - - @include upto-sm { - width: 100%; - } - } - - &.col-date { - width: 175px; - - @include upto-sm { - width: 100%; - } - } - - &.col-checkbox { - position: relative; - - @include upto-sm { - top: 25px; - } - } - } - } - - input { - @include roboto-regular; - - height: 36px; - margin: 0; - font-size: 15px; - line-height: 20px; - font-weight: 400; - color: $tc-black; - border: 1px solid $tc-gray-20; - border-radius: $corner-radius * 2 $corner-radius * 2 $corner-radius * 2 $corner-radius * 2; - - @include upto-sm { - margin-top: 5px; - } - } -} - -.button-container { - display: flex; - justify-content: center; - align-items: center; - - .button-save, - .button-cancel { - align-self: center; - - @include upto-sm { - margin-top: 30px; - } - - button, - a { - @include roboto-medium; - - height: 40px; - font-size: 15px; - font-weight: 500; - margin: 0; - padding: 0; - width: 250px; - - @include upto-sm { - width: 156px; - } - } - } - - .button-cancel { - margin-left: 10px; - } -} - -/* - * React Select component styling - */ -.education-container .form-container .row .field :global .Select, -.education-container .form-container .row .field :global .Select-value span, -.education-container .form-container .row .field :global .Select-menu-outer, -.education-container .form-container .row .field :global .Select-placeholder, -.education-container .form-container .row .field :global .Select-input input { - color: $tc-gray-80; - font-size: 15px; - - @include upto-sm { - margin-top: 5px; - } -} - -.education-container div[class="Select-control"] { - height: 40px; - - div[class="Select-input"] { - height: 38px; - } - - div[class="Select-placeholder"] { - height: 38px; - line-height: 40px !important; - - @include upto-sm { - line-height: 38px !important; - } - } - - div[class="Select-value"] { - line-height: 40px !important; - } -} - -.education-container .form-container .row .field :global .Select-placeholder { - color: $tc-gray-50; -} diff --git a/src/shared/components/Settings/ProfileSettings/PersonalDetails/index.jsx b/src/shared/components/Settings/ProfileSettings/PersonalDetails/index.jsx deleted file mode 100644 index e497e304c9..0000000000 --- a/src/shared/components/Settings/ProfileSettings/PersonalDetails/index.jsx +++ /dev/null @@ -1,240 +0,0 @@ -/* eslint-disable react/prop-types */ -/* eslint-disable react/jsx-no-bind */ -/** - * Personal Details Form - * Profile Settings Page - */ -import _ from 'lodash'; -import React from 'react'; -import PT from 'prop-types'; -import moment from 'moment'; -import ErrorMessage from 'components/Settings/ErrorMessage'; -import FormInputText from 'components/Settings/FormInputText'; -import Select from 'components/Settings/FormInputSelect'; -import FormField from 'components/Settings/FormField'; -import FormInputDatePicker from 'components/Settings/FormInputDatePicker'; - -import '../styles.scss'; - -const PersonalDetails = (props) => { - const { - canModifyTrait, - countries, - newProfileInfo, - newBasicInfo, - onUpdateDate, - onUpdateInput, - inputChanged, - onUpdateCountry, - } = props; - - return ( -
    -
    -
    - - {/* First Name */} - - - - - - {/* Last Name */} - - - - - - {/* Birth Date */} - - onUpdateDate(date)} - /> - - - {/* Address */} - - 0 - && newProfileInfo.addresses[0].streetAddr1 != null - ? newProfileInfo.addresses[0].streetAddr1 - : '' - }`} - maxLength="64" - required - /> - - - {/* Address 2 */} - - 0 - && newProfileInfo.addresses[0].streetAddr2 != null - ? newProfileInfo.addresses[0].streetAddr2 - : '' - }`} - maxLength="64" - /> - - - {/* City */} - - 0 - && newProfileInfo.addresses[0].city != null - ? newProfileInfo.addresses[0].city - : '' - }`} - maxLength="64" - required - /> - - - {/* State */} - - 0 - && newProfileInfo.addresses[0].stateCode != null - ? newProfileInfo.addresses[0].stateCode - : '' - }`} - maxLength="64" - required - /> - - - {/* Zip */} - - 0 - && newProfileInfo.addresses[0].zip != null - ? newProfileInfo.addresses[0].zip - : '' - }`} - maxLength="64" - required - /> - - - {/* Country */} - - - -
    -
    - - -
    -
    - ); -} - -ToggleableItem.defaultProps = { - disabled: false, -}; - -ToggleableItem.propTypes = { - id: PT.string.isRequired, - value: PT.string.isRequired, - checked: PT.bool.isRequired, - primaryText: PT.string.isRequired, - secondaryText: PT.string.isRequired, - onToggle: PT.func.isRequired, - disabled: PT.bool, -}; diff --git a/src/shared/components/Settings/ToggleableItem/styles.scss b/src/shared/components/Settings/ToggleableItem/styles.scss deleted file mode 100644 index f3c5d976b3..0000000000 --- a/src/shared/components/Settings/ToggleableItem/styles.scss +++ /dev/null @@ -1,52 +0,0 @@ -@import "../style"; - -.ToggleableItem { - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; - padding: $pad-lg; - background: $tc-white; - border: 1px solid $color-black-20; - border-radius: 8px; - - .body { - display: flex; - flex-direction: column; - padding-right: 20px; - - @media (max-width: 374px) { - padding-right: 16px; - } - } - - p.primary { - @include roboto-bold; - - font-size: 16px; - line-height: 20px; - letter-spacing: 0.5px; - text-transform: capitalize; - color: $tco-black; - } - - p.secondary { - @include roboto-medium; - - font-weight: 400; - font-size: 16px; - line-height: 24px; - color: $color-black-60; - } - - .onoffswitch-no-padding-right { - margin-right: 9px; - margin-left: 0; - margin-top: 10px; - align-self: flex-start; - - @media (max-width: 374px) { - margin-right: 0; - } - } -} diff --git a/src/shared/components/Settings/Tools/Devices/List/Item/index.jsx b/src/shared/components/Settings/Tools/Devices/List/Item/index.jsx deleted file mode 100644 index 5e6206e261..0000000000 --- a/src/shared/components/Settings/Tools/Devices/List/Item/index.jsx +++ /dev/null @@ -1,114 +0,0 @@ -/** - * render device item. - */ -import _ from 'lodash'; -import React from 'react'; -import PT from 'prop-types'; -import ReactSVG from 'react-svg'; -import cn from 'classnames'; -import { isomorphy } from 'topcoder-react-utils'; -import Tooltip from 'components/Tooltip'; - -import './styles.scss'; - -let assets; -if (isomorphy.isClientSide()) { - assets = require.context('assets/images/tools/device-types', false, /svg/); -} - -export default function Item(props) { - const { - device, - index, - isEditing, - onDeleteItem, - onEditItem, - } = props; - - const hasModel = !_.isEmpty(device.model); - const secondLineItems = []; - if (device.manufacturer) { - secondLineItems.push(device.manufacturer); - } - if (device.operatingSystem) { - secondLineItems.push(device.operatingSystem); - } - - secondLineItems.push(device.deviceType); - const secondLine = secondLineItems.join(' | '); - - const deleteTip = ( -
    -

    Delete

    -
    - ); - - const editTip = ( -
    -

    Edit

    -
    - ); - - return ( -
    -
    -
    - { assets && assets.keys().includes(`./${device.deviceType.toLowerCase()}.svg`) ? : '' } -
    -
    - {hasModel ? ( -
    - {device.model} -
    - ) : null} -
    - {secondLine} -
    -
    -
    - -
    - ); -} - -Item.propTypes = { - device: PT.shape().isRequired, - index: PT.number.isRequired, - isEditing: PT.bool.isRequired, - onDeleteItem: PT.func.isRequired, - onEditItem: PT.func.isRequired, -}; diff --git a/src/shared/components/Settings/Tools/Devices/List/Item/styles.scss b/src/shared/components/Settings/Tools/Devices/List/Item/styles.scss deleted file mode 100644 index d5d2893f7a..0000000000 --- a/src/shared/components/Settings/Tools/Devices/List/Item/styles.scss +++ /dev/null @@ -1,209 +0,0 @@ -@import "../../../../style"; - -.container { - display: flex; - flex-direction: row; - justify-items: center; - justify-content: space-between; - align-items: center; - min-height: 96px; - width: 100%; - border-bottom: none; - background-color: $tc-white; - padding: $pad-lg; - border: 1px solid $color-black-20; - border-radius: 8px; - - @include xs { - padding: $pad-sm; - } -} - -.device-info { - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; -} - -.device-icon { - display: flex; - align-items: center; - justify-content: center; - flex: 0 0 64px; - width: 64px; - height: 64px; - background: $color-black-5; - border-radius: 4px; - margin-right: $margin-lg; - - svg { - display: block; - } -} - -.device-parameters { - @include roboto-medium; - - display: flex; - flex-direction: column; - justify-items: center; - justify-content: center; - font-size: 15px; - line-height: 20px; - text-transform: capitalize; - padding-right: 20px; - - &.single-line { - flex-direction: row; - align-items: center; - } - - > div:first-child { - @include roboto-bold; - - color: $tc-black; - font-weight: 700; - font-size: 16px; - line-height: 20px; - letter-spacing: 0.5px; - text-transform: capitalize; - word-break: break-all; - - &.single-line { - margin-bottom: 0; - } - - @include upto-sm { - margin-bottom: 0; - } - } -} - -.parameter-second-line, -.parameter-third-line, -.parameter-second-line-mobile { - @include roboto-medium; - - color: $color-black-60; - font-weight: 400; - font-size: 16px; - line-height: 24px; - word-break: break-all; -} - -.parameter-second-line-mobile { - @include upto-sm { - display: flex; - flex-direction: column; - - p { - word-break: break-all; - } - } -} - -.tctooltiptext { - background: $tooltip-gray; - color: $tc-white; - border-radius: 8px; - padding: 10px; - - p { - @include roboto-medium; - - font-weight: 400; - font-size: 14px; - line-height: 22px; - } -} - -.tctooltiptext::after { - content: ""; - position: absolute; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; - bottom: 4px; - margin-left: -5px; - border-width: 5px 5px 0; - left: 50%; - border-top-color: $tc-black; - z-index: 1000; -} - -.operation-container { - display: flex; - flex-direction: row; - justify-content: space-between; - - .delete-wrapper { - margin-left: $margin-xl; - margin-right: $margin-xs; - - @include xs-to-sm { - margin-left: $margin-lg; - margin-right: 0; - } - - @media screen and (max-width: 320px) { - margin-right: 0; - margin-left: 6px; - } - } - - .delete { - display: flex; - flex-direction: column; - justify-items: center; - justify-content: center; - cursor: pointer; - outline-style: none; - - img { - width: 20px; - height: 20px; - } - - p { - @include roboto-regular; - - font-size: 11px; - line-height: 15px; - font-weight: 400; - color: $tc-gray-50; - - @include upto-sm { - display: none; - } - } - } - - .edit { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - cursor: pointer; - outline-style: none; - - img { - width: 20px; - height: 20px; - } - - p { - @include roboto-regular; - - font-size: 11px; - line-height: 15px; - font-weight: 400; - color: $tc-gray-50; - - @include upto-sm { - display: none; - } - } - } -} diff --git a/src/shared/components/Settings/Tools/Devices/List/index.jsx b/src/shared/components/Settings/Tools/Devices/List/index.jsx deleted file mode 100644 index 5c934f3d65..0000000000 --- a/src/shared/components/Settings/Tools/Devices/List/index.jsx +++ /dev/null @@ -1,54 +0,0 @@ -/** - * render Device list - */ -import React from 'react'; -import PT from 'prop-types'; -import Item from './Item'; - -import './styles.scss'; - -export default function DeviceList(props) { - const { - deviceList, - onDeleteItem, - disabled, - onEditItem, - indexNo, - } = props; - - return ( -
    0 ? 'active' : ''} ${disabled ? 'disabled' : ''}`}> -
      - { - deviceList.items.map((device, index) => ( - device - ? ( -
    • - -
    • - ) : undefined - )) - } -
    -
    - ); -} - -DeviceList.propTypes = { - deviceList: PT.shape().isRequired, - onDeleteItem: PT.func.isRequired, - onEditItem: PT.func.isRequired, - disabled: PT.bool, - indexNo: PT.number, -}; - -DeviceList.defaultProps = { - disabled: false, - indexNo: null, -}; diff --git a/src/shared/components/Settings/Tools/Devices/List/styles.scss b/src/shared/components/Settings/Tools/Devices/List/styles.scss deleted file mode 100644 index b799bc7594..0000000000 --- a/src/shared/components/Settings/Tools/Devices/List/styles.scss +++ /dev/null @@ -1,32 +0,0 @@ -@import "../../../style"; - -.container { - width: 100%; - background-color: $tc-white; - padding: 0; - margin-bottom: 30px; - - &.active { - margin-top: 20px; - - @include upto-sm { - margin-top: 0; - } - } - - ul { - display: flex; - flex-direction: column; - justify-items: center; - - li { - margin-bottom: $margin-md; - } - } - - &.disabled { - opacity: 0.7; - pointer-events: none; - user-select: none; - } -} diff --git a/src/shared/components/Settings/Tools/Devices/index.jsx b/src/shared/components/Settings/Tools/Devices/index.jsx deleted file mode 100644 index a4194f1303..0000000000 --- a/src/shared/components/Settings/Tools/Devices/index.jsx +++ /dev/null @@ -1,615 +0,0 @@ -/** - * Child component of Settings/Tools/ renders the - * 'Devices' page. - */ -/* eslint-disable react/forbid-prop-types */ -/* eslint-disable no-nested-ternary */ -/* eslint-disable jsx-a11y/label-has-for */ -/* eslint-disable no-undef */ -import _ from 'lodash'; -import React from 'react'; -import PT from 'prop-types'; -import ConsentComponent from 'components/Settings/ConsentComponent'; -import ErrorMessage from 'components/Settings/ErrorMessage'; -import FormField from 'components/Settings/FormField'; -import AddItemIcon from 'assets/images/settings-add-item.svg'; -import { SettingBannerV2 as Collapse } from 'components/Settings/SettingsBanner'; -import { PrimaryButton, SecondaryButton } from 'topcoder-react-ui-kit'; -import FormInputSelect from 'components/Settings/FormInputSelect'; -import { toastr } from 'react-redux-toastr'; -import ConfirmationModal from '../../ConfirmationModal'; -import DeviceList from './List'; - -import styles from './styles.scss'; - -export default class Devices extends ConsentComponent { - constructor(props) { - super(props); - this.onHandleDeleteDevice = this.onHandleDeleteDevice.bind(this); - this.onDeleteDevice = this.onDeleteDevice.bind(this); - this.onEditDevice = this.onEditDevice.bind(this); - this.loadDeviceTrait = this.loadDeviceTrait.bind(this); - this.onHandleAddDevice = this.onHandleAddDevice.bind(this); - this.onAddDevice = this.onAddDevice.bind(this); - this.loadPersonalizationTrait = this.loadPersonalizationTrait.bind(this); - this.updatePredicate = this.updatePredicate.bind(this); - this.onCancelEditStatus = this.onCancelEditStatus.bind(this); - this.onUpdateType = this.onUpdateType.bind(this); - this.onUpdateManufacturer = this.onUpdateManufacturer.bind(this); - this.onUpdateModel = this.onUpdateModel.bind(this); - this.onUpdateOs = this.onUpdateOs.bind(this); - this.onLoadMoreModels = this.onLoadMoreModels.bind(this); - this.onLoadMoreOses = this.onLoadMoreOses.bind(this); - - const { userTraits } = props; - this.state = { - isSubmit: false, - formInvalid: false, - deviceTrait: this.loadDeviceTrait(userTraits), - personalizationTrait: this.loadPersonalizationTrait(userTraits), - newDevice: { - deviceType: '', - manufacturer: '', - model: '', - operatingSystem: '', - }, - isMobileView: false, - screenSM: 767, - showConfirmation: false, - indexNo: null, - isEdit: false, - }; - } - - componentDidMount() { - this.updatePredicate(); - window.addEventListener('resize', this.updatePredicate); - } - - componentWillReceiveProps(nextProps) { - const deviceTrait = this.loadDeviceTrait(nextProps.userTraits); - const personalizationTrait = this.loadPersonalizationTrait(nextProps.userTraits); - this.setState({ - deviceTrait, - personalizationTrait, - formInvalid: false, - isSubmit: false, - }); - } - - componentWillUnmount() { - window.removeEventListener('resize', this.updatePredicate); - } - - /** - * Show User Consent Modal - * @param e event - */ - onHandleAddDevice(e) { - if (e) e.preventDefault(); - const { newDevice, deviceTrait } = this.state; - const { clearDeviceState } = this.props; - this.setState({ isSubmit: true }); - if (this.onCheckFormValue(newDevice)) { - return; - } - const deviceItems = deviceTrait.traits - ? deviceTrait.traits.data.slice() : []; - let exist = false; - // eslint-disable-next-line no-restricted-syntax - for (const item of deviceItems) { - if (item.deviceType === newDevice.deviceType - && item.manufacturer === newDevice.manufacturer - && item.model === newDevice.model - && item.operatingSystem === newDevice.operatingSystem) { - exist = true; - break; - } - } - if (exist === true) { - const empty = { - deviceType: '', - manufacturer: '', - model: '', - operatingSystem: '', - }; - this.setState({ - newDevice: empty, - isEdit: false, - indexNo: null, - isSubmit: false, - }); - clearDeviceState(); - setImmediate(() => { - toastr.error('Looks like you\'ve already entered this device.'); - }); - return; - } - this.showConsent(this.onAddDevice.bind(this)); - } - - onHandleDeleteDevice(indexNo) { - this.setState({ - showConfirmation: true, - indexNo, - }); - } - - /** - * Delete device by index - * @param indexNo the device index no - */ - onDeleteDevice(indexNo) { - const { deviceTrait, isEdit } = this.state; - const newDeviceTrait = { ...deviceTrait }; - newDeviceTrait.traits.data.splice(indexNo, 1); - this.setState({ - deviceTrait: newDeviceTrait, - }); - - const { - handle, - tokenV3, - updateUserTrait, - deleteUserTrait, - } = this.props; - - if (newDeviceTrait.traits.data.length > 0) { - updateUserTrait(handle, 'device', newDeviceTrait.traits.data, tokenV3); - } else { - deleteUserTrait(handle, 'device', tokenV3); - } - this.setState({ - showConfirmation: false, - indexNo: null, - isSubmit: false, - formInvalid: false, - }); - if (isEdit) { - this.onCancelEditStatus(); - } - } - - /** - * Edit device by index - * @param indexNo the device index no - */ - onEditDevice(indexNo) { - const { deviceTrait } = this.state; - const { - getManufacturers, - getModels, - getOses, - } = this.props; - this.setState({ - newDevice: { - deviceType: deviceTrait.traits.data[indexNo].deviceType, - manufacturer: _.isEmpty(deviceTrait.traits.data[indexNo].manufacturer) ? '' : deviceTrait.traits.data[indexNo].manufacturer, - model: _.isEmpty(deviceTrait.traits.data[indexNo].model) ? '' : deviceTrait.traits.data[indexNo].model, - operatingSystem: _.isEmpty(deviceTrait.traits.data[indexNo].operatingSystem) ? '' : deviceTrait.traits.data[indexNo].operatingSystem, - }, - isEdit: true, - indexNo, - isSubmit: false, - }); - const selectDevice = deviceTrait.traits.data[indexNo]; - const { - deviceType, - manufacturer, - model, - } = selectDevice; - - // preload all select - getManufacturers(deviceType); - getModels(1, deviceType, manufacturer); - getOses(1, deviceType, manufacturer, model); - } - - /** - * Add new device - * @param answer user consent answer value - */ - onAddDevice(answer) { - const { - newDevice, personalizationTrait, isEdit, indexNo, - } = this.state; - - const { - handle, - tokenV3, - updateUserTrait, - addUserTrait, - clearDeviceState, - } = this.props; - const { - deviceTrait, - } = this.state; - const device = _.clone(newDevice); - if (_.isEmpty(device.manufacturer)) { - delete device.manufacturer; - } - if (_.isEmpty(device.model)) { - delete device.model; - } - if (_.isEmpty(device.operatingSystem)) { - delete device.operatingSystem; - } - if (deviceTrait.traits && deviceTrait.traits.data.length > 0) { - const newDeviceTrait = _.cloneDeep(deviceTrait); - if (isEdit) { - newDeviceTrait.traits.data.splice(indexNo, 1); - } - newDeviceTrait.traits.data.push(device); - updateUserTrait(handle, 'device', newDeviceTrait.traits.data, tokenV3); - } else { - const newDevices = []; - newDevices.push(device); - addUserTrait(handle, 'device', newDevices, tokenV3); - } - const empty = { - deviceType: '', - manufacturer: '', - model: '', - operatingSystem: '', - }; - this.setState({ - newDevice: empty, - isEdit: false, - indexNo: null, - isSubmit: false, - }); - clearDeviceState(); - // save personalization - if (_.isEmpty(personalizationTrait)) { - const personalizationData = { userConsent: answer }; - addUserTrait(handle, 'personalization', [personalizationData], tokenV3); - } else { - const trait = personalizationTrait.traits.data[0]; - if (trait.userConsent !== answer) { - const personalizationData = { userConsent: answer }; - updateUserTrait(handle, 'personalization', [personalizationData], tokenV3); - } - } - } - - /** - * Check form fields value, - * Invalid value, can not save - * @param newDevice object - */ - onCheckFormValue(newDevice, updateState = true) { - let invalid = false; - - if (!_.trim(newDevice.deviceType).length) { - invalid = true; - } - - if (updateState) { - this.setState({ formInvalid: invalid }); - } - return invalid; - } - - /** - * Update deviceType - * @param option selected value - */ - onUpdateType(val) { - const { - getManufacturers, - } = this.props; - - const newDevice = { deviceType: val.name }; - newDevice.manufacturer = ''; - newDevice.model = ''; - newDevice.operatingSystem = ''; - this.setState({ newDevice, isSubmit: false }); - - // preload manufacturers - getManufacturers(val.name); - } - - /** - * Update manufacturer - * @param e event - */ - onUpdateManufacturer(val) { - const { - getModels, - } = this.props; - const { newDevice: device } = this.state; - const newDevice = { ..._.pick(device, ['deviceType']) }; - newDevice.manufacturer = val.name; - newDevice.model = ''; - newDevice.operatingSystem = ''; - this.setState({ newDevice, isSubmit: false }); - // preload models - getModels(1, newDevice.deviceType, newDevice.manufacturer); - } - - /** - * Update model - * @param e event - */ - onUpdateModel(val) { - const { - getOses, - // lookupData: {modelPage} - } = this.props; - const { newDevice: device } = this.state; - const newDevice = { ..._.pick(device, ['deviceType', 'manufacturer']) }; - newDevice.model = val.model; - newDevice.operatingSystem = ''; - this.setState({ newDevice, isSubmit: false }); - - // preload oses - getOses(1, newDevice.deviceType, newDevice.manufacturer, newDevice.model); - } - - /** - * Update operatingSystem - * @param e event - */ - onUpdateOs(val) { - const { newDevice: device } = this.state; - const newDevice = { ..._.pick(device, ['deviceType', 'manufacturer', 'model']) }; - newDevice.operatingSystem = val.operatingSystem; - this.setState({ newDevice, isSubmit: false }); - } - - onLoadMoreModels() { - const { - lookupData: { - modelPage, - }, - getMoreModels, - } = this.props; - - const { - newDevice: { - deviceType, - manufacturer, - }, - } = this.state; - getMoreModels(modelPage + 1, deviceType, manufacturer); - } - - onLoadMoreOses() { - const { - lookupData: { - osPage, - }, - getMoreOses, - } = this.props; - const { - newDevice: { - deviceType, - manufacturer, model, - }, - } = this.state; - getMoreOses(osPage + 1, deviceType, manufacturer, model); - } - - /** - * Get device trait - * @param userTraits the all user traits - */ - loadDeviceTrait = (userTraits) => { - const trait = userTraits.filter(t => t.traitId === 'device'); - const devices = trait.length === 0 ? {} : trait[0]; - return _.assign({}, devices); - } - - /** - * Get personalization trait - * @param userTraits the all user traits - */ - loadPersonalizationTrait = (userTraits) => { - const trait = userTraits.filter(t => t.traitId === 'personalization'); - const personalization = trait.length === 0 ? {} : trait[0]; - return _.assign({}, personalization); - } - - updatePredicate() { - const { screenSM } = this.state; - this.setState({ isMobileView: window.innerWidth <= screenSM }); - } - - isFormValid() { - const { newDevice } = this.state; - return this.onCheckFormValue(newDevice, false); - } - - onCancelEditStatus() { - const { clearDeviceState } = this.props; - const { isEdit } = this.state; - if (isEdit) { - this.setState({ - isEdit: false, - isSubmit: false, - indexNo: null, - formInvalid: false, - newDevice: { - deviceType: '', - manufacturer: '', - model: '', - operatingSystem: '', - }, - }); - clearDeviceState(); - } - } - - render() { - const { - lookupData, - } = this.props; - const { - types, - manufacturers, - models, - oses, - hasMoreModels, - hasMoreOses, - isModelsLoading, - isOsesLoading, - } = lookupData; - const { - deviceTrait, showConfirmation, indexNo, isEdit, - formInvalid, isSubmit, - } = this.state; - const deviceItems = deviceTrait.traits - ? deviceTrait.traits.data.slice() : []; - const { newDevice } = this.state; - const canModifyTrait = !this.props.traitRequestCount; - - return ( - - { - this.shouldRenderConsent() && this.renderConsent() - } - {showConfirmation - && ( - this.showConsent(this.onDeleteDevice.bind(this, indexNo))} - onCancel={() => this.setState({ showConfirmation: false, indexNo: null })} - name={`${deviceTrait.traits.data[indexNo].deviceType}${!_.isEmpty(deviceTrait.traits.data[indexNo].manufacturer) ? ` ${deviceTrait.traits.data[indexNo].manufacturer}` : ''}`} - /> - )} -
    - -

    - Your Devices -

    - { - deviceItems.length > 0 - && ( - - ) - } -
    -
    - Add a new device to your devices list -
    -
    - - - e.key === 'Enter' && e.preventDefault()} - /> - { isSubmit && formInvalid && ( - - ) - } - - - - e.key === 'Enter' && e.preventDefault()} - /> - - - - e.key === 'Enter' && e.preventDefault()} - /> - - - - e.key === 'Enter' && e.preventDefault()} - /> - - -
    -
    - {!isEdit && ( - - Add Device to Your List - - )} - - { isEdit && ( - - - Edit Device to Your List - - - Cancel - - - )} -
    -
    -
    -
    -
    - ); - } -} - -Devices.propTypes = { - tokenV3: PT.string.isRequired, - handle: PT.string.isRequired, - traitRequestCount: PT.number.isRequired, - userTraits: PT.array.isRequired, - addUserTrait: PT.func.isRequired, - updateUserTrait: PT.func.isRequired, - deleteUserTrait: PT.func.isRequired, -}; diff --git a/src/shared/components/Settings/Tools/Devices/styles.scss b/src/shared/components/Settings/Tools/Devices/styles.scss deleted file mode 100644 index c37516d5eb..0000000000 --- a/src/shared/components/Settings/Tools/Devices/styles.scss +++ /dev/null @@ -1,110 +0,0 @@ -@import "~styles/mixins"; - -.form-container { - padding: $pad-xxxxl; - background-color: $color-tc-white; - border-radius: 4px; - margin: $margin-sm 0 0; - - .device-form { - display: flex; - flex-wrap: wrap; - } -} - -.form-title { - @include barlow-semi-bold; - - font-size: 20px; - line-height: 22px; - color: inherit; - text-transform: uppercase; - padding-bottom: $pad-xxxxl; -} - -.form-content { - display: flex; - flex-wrap: wrap; - align-items: flex-start; -} - -.form-label { - flex: 0 0 calc(50% - 13px); - padding-right: 230px; - - @include roboto-regular; - - font-size: 16px; - line-height: 26px; - color: inherit; -} - -.form-body { - flex: 0 0 calc(50% + 13px); -} - -.form-footer { - display: flex; - align-items: center; - justify-content: flex-start; - margin-left: calc(50% - 13px); - padding: $pad-sm 0; - gap: 8px 16px; - - .button { - @include roboto-bold; - - font-size: 14px; - line-height: 14px; - color: $color-turq-160; - min-height: 0; - margin: 0; - padding: 0; - background: transparent !important; - border: none; - cursor: pointer; - - &:hover, - &:active, - &:focus { - outline: none !important; - color: lighten($color-turq-160, 5%); - background: transparent !important; - box-shadow: none !important; - } - - .icon { - margin-right: $margin-xs; - } - } -} - -@include xs-to-md { - .form-container { - padding: $pad-xxl $pad-lg; - } - - .form-title { - @include barlow-condensed-medium; - - font-size: 22px; - line-height: 24px; - padding-bottom: $pad-xxl; - } - - .form-label { - flex: 1 1 100%; - padding: 0; - margin-bottom: $margin-xxl; - font-size: 14px; - line-height: 20px; - } - - .form-body { - flex: 1 1 100%; - } - - .form-footer { - margin: 0; - } -} diff --git a/src/shared/components/Settings/Tools/ServiceProviders/List/Item/index.jsx b/src/shared/components/Settings/Tools/ServiceProviders/List/Item/index.jsx deleted file mode 100644 index a6f5754162..0000000000 --- a/src/shared/components/Settings/Tools/ServiceProviders/List/Item/index.jsx +++ /dev/null @@ -1,96 +0,0 @@ -/** - * render serviceProvider Item - */ -import React from 'react'; -import PT from 'prop-types'; -import ReactSVG from 'react-svg'; -import { isomorphy } from 'topcoder-react-utils'; -import Tooltip from 'components/Tooltip'; - -import './styles.scss'; - -let assets; -if (isomorphy.isClientSide()) { - assets = require.context('assets/images/tools/service-provider-types', false, /svg/); -} - -export default function Item(props) { - const { - serviceProvider, - index, - onDeleteItem, - onEditItem, - } = props; - - const deleteTip = ( -
    -

    Delete

    -
    - ); - - const editTip = ( -
    -

    Edit

    -
    - ); - - return ( - - ); -} - -Item.propTypes = { - serviceProvider: PT.shape().isRequired, - index: PT.number.isRequired, - onDeleteItem: PT.func.isRequired, - onEditItem: PT.func.isRequired, -}; diff --git a/src/shared/components/Settings/Tools/ServiceProviders/List/Item/styles.scss b/src/shared/components/Settings/Tools/ServiceProviders/List/Item/styles.scss deleted file mode 100644 index 2dd0a796d8..0000000000 --- a/src/shared/components/Settings/Tools/ServiceProviders/List/Item/styles.scss +++ /dev/null @@ -1,209 +0,0 @@ -@import "../../../../style"; - -.container { - display: flex; - flex-direction: row; - justify-items: center; - justify-content: space-between; - align-items: center; - min-height: 96px; - width: 100%; - border-bottom: none; - background-color: $tc-white; - padding: $pad-lg; - border: 1px solid $color-black-20; - border-radius: 8px; - - @media screen and (max-width: 374px) { - padding: $pad-sm; - } -} - -.service-provider-info { - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; -} - -.service-provider-icon { - display: flex; - align-items: center; - justify-content: center; - flex: 0 0 64px; - width: 64px; - height: 64px; - background: $color-black-5; - border-radius: 4px; - margin-right: $margin-lg; - - svg { - display: block; - } -} - -.service-provider-parameters { - @include roboto-medium; - - display: flex; - flex-direction: column; - justify-items: center; - justify-content: center; - font-size: 15px; - line-height: 20px; - text-transform: capitalize; - padding-right: 20px; - - &.single-line { - flex-direction: row; - align-items: center; - } -} - -.parameter-first-line { - @include roboto-bold; - - color: $tc-black; - font-weight: 700; - font-size: 16px; - line-height: 20px; - letter-spacing: 0.5px; - text-transform: capitalize; - word-break: break-all; - - &.single-line { - margin-bottom: 0; - } - - @include upto-sm { - margin-bottom: 0; - } -} - -.parameter-second-line, -.parameter-third-line, -.parameter-second-line-mobile { - @include roboto-medium; - - color: $color-black-60; - font-weight: 400; - font-size: 16px; - line-height: 24px; - word-break: break-all; -} - -.parameter-second-line-mobile { - @include upto-sm { - display: flex; - flex-direction: column; - - p { - word-break: break-all; - } - } -} - -.tctooltiptext { - background: $tooltip-gray; - color: $tc-white; - border-radius: 8px; - padding: 10px; - - p { - @include roboto-medium; - - font-weight: 400; - font-size: 14px; - line-height: 22px; - } -} - -.tctooltiptext::after { - content: ""; - position: absolute; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; - bottom: 4px; - margin-left: -5px; - border-width: 5px 5px 0; - left: 50%; - border-top-color: $tc-black; - z-index: 1000; -} - -.operation-container { - display: flex; - flex-direction: row; - justify-content: space-between; - - .delete-wrapper { - margin-left: $margin-xl; - margin-right: $margin-xs; - - @include xs-to-sm { - margin-left: $margin-lg; - margin-right: 0; - } - - @media screen and (max-width: 320px) { - margin-right: 0; - margin-left: 6px; - } - } - - .delete { - display: flex; - flex-direction: column; - justify-items: center; - justify-content: center; - cursor: pointer; - outline-style: none; - - img { - width: 20px; - height: 20px; - } - - p { - @include roboto-regular; - - font-size: 11px; - line-height: 15px; - font-weight: 400; - color: $tc-gray-50; - - @include upto-sm { - display: none; - } - } - } - - .edit { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - cursor: pointer; - outline-style: none; - - img { - width: 20px; - height: 20px; - } - - p { - @include roboto-regular; - - font-size: 11px; - line-height: 15px; - font-weight: 400; - color: $tc-gray-50; - - @include upto-sm { - display: none; - } - } - } -} diff --git a/src/shared/components/Settings/Tools/ServiceProviders/List/index.jsx b/src/shared/components/Settings/Tools/ServiceProviders/List/index.jsx deleted file mode 100644 index a04c0e69f6..0000000000 --- a/src/shared/components/Settings/Tools/ServiceProviders/List/index.jsx +++ /dev/null @@ -1,47 +0,0 @@ -/** - * render ServiceProvider list - */ -import React from 'react'; -import PT from 'prop-types'; -import Item from './Item'; - -import './styles.scss'; - -export default function ServiceProviderList(props) { - const { - serviceProviderList, - onDeleteItem, - disabled, - onEditItem, - } = props; - - return ( -
    0 ? 'active' : ''} ${disabled ? 'disabled' : ''}`}> -
      - { - serviceProviderList.items.map((serviceProvider, index) => ( -
    • - -
    • - )) - } -
    -
    - ); -} - -ServiceProviderList.propTypes = { - serviceProviderList: PT.shape().isRequired, - onDeleteItem: PT.func.isRequired, - onEditItem: PT.func.isRequired, - disabled: PT.bool, -}; - -ServiceProviderList.defaultProps = { - disabled: false, -}; diff --git a/src/shared/components/Settings/Tools/ServiceProviders/List/styles.scss b/src/shared/components/Settings/Tools/ServiceProviders/List/styles.scss deleted file mode 100644 index 979df1bf53..0000000000 --- a/src/shared/components/Settings/Tools/ServiceProviders/List/styles.scss +++ /dev/null @@ -1,32 +0,0 @@ -@import "../../../style"; - -.container { - width: 100%; - background-color: $tc-white; - padding: 0; - margin: 0 0 $margin-xxxxl; - - &.active { - margin-top: 20px; - - @include upto-sm { - margin-top: 0; - } - } - - ul { - display: flex; - flex-direction: column; - justify-items: center; - - li { - margin-bottom: $margin-md; - } - } - - &.disabled { - opacity: 0.7; - pointer-events: none; - user-select: none; - } -} diff --git a/src/shared/components/Settings/Tools/ServiceProviders/dropdowns.json b/src/shared/components/Settings/Tools/ServiceProviders/dropdowns.json deleted file mode 100644 index 891141c4f1..0000000000 --- a/src/shared/components/Settings/Tools/ServiceProviders/dropdowns.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "serviceProviderType": [ - { - "key": "serviceProviderType", - "name": "Internet Service Provider" - }, - { - "key": "serviceProviderType", - "name": "Mobile Carrier" - }, - { - "key": "serviceProviderType", - "name": "Television" - }, - { - "key": "serviceProviderType", - "name": "Financial Institution" - }, - { - "key": "serviceProviderType", - "name": "Other" - } - ] -} diff --git a/src/shared/components/Settings/Tools/ServiceProviders/index.jsx b/src/shared/components/Settings/Tools/ServiceProviders/index.jsx deleted file mode 100644 index f75225272d..0000000000 --- a/src/shared/components/Settings/Tools/ServiceProviders/index.jsx +++ /dev/null @@ -1,421 +0,0 @@ -/** - * Child component of Settings/Tools/ renders the - * 'ServiceProvider' page. - */ -/* eslint-disable react/forbid-prop-types */ -/* eslint-disable no-nested-ternary */ -/* eslint-disable jsx-a11y/label-has-for */ -/* eslint-disable no-undef */ -import React from 'react'; -import PT from 'prop-types'; -import _ from 'lodash'; -import ConsentComponent from 'components/Settings/ConsentComponent'; -import ErrorMessage from 'components/Settings/ErrorMessage'; -import FormField from 'components/Settings/FormField'; -import FormInputText from 'components/Settings/FormInputText'; -import AddItemIcon from 'assets/images/settings-add-item.svg'; -import FormInputSelect from 'components/Settings/FormInputSelect'; -import { SettingBannerV2 as Collapse } from 'components/Settings/SettingsBanner'; -import { PrimaryButton, SecondaryButton } from 'topcoder-react-ui-kit'; -import ConfirmationModal from '../../ConfirmationModal'; -import dropdowns from './dropdowns.json'; -import ServiceProviderList from './List'; - -import styles from './styles.scss'; - -export default class ServiceProviders extends ConsentComponent { - constructor(props) { - super(props); - this.onHandleDeleteServiceProvider = this.onHandleDeleteServiceProvider.bind(this); - this.onDeleteServiceProvider = this.onDeleteServiceProvider.bind(this); - this.onEditServiceProvider = this.onEditServiceProvider.bind(this); - this.onUpdateSelect = this.onUpdateSelect.bind(this); - this.loadServiceProviderTrait = this.loadServiceProviderTrait.bind(this); - this.onUpdateInput = this.onUpdateInput.bind(this); - this.onHandleAddServiceProvider = this.onHandleAddServiceProvider.bind(this); - this.onAddServiceProvider = this.onAddServiceProvider.bind(this); - this.loadPersonalizationTrait = this.loadPersonalizationTrait.bind(this); - this.updatePredicate = this.updatePredicate.bind(this); - this.isFormValid = this.isFormValid.bind(this); - this.onCancelEditStatus = this.onCancelEditStatus.bind(this); - - const { userTraits } = props; - this.state = { - formInvalid: false, - isSubmit: false, - serviceProviderTrait: this.loadServiceProviderTrait(userTraits), - personalizationTrait: this.loadPersonalizationTrait(userTraits), - newServiceProvider: { - serviceProviderType: '', - name: '', - }, - isMobileView: false, - screenSM: 767, - showConfirmation: false, - indexNo: null, - isEdit: false, - }; - } - - componentDidMount() { - this.updatePredicate(); - window.addEventListener('resize', this.updatePredicate); - } - - componentWillReceiveProps(nextProps) { - const serviceProviderTrait = this.loadServiceProviderTrait(nextProps.userTraits); - const personalizationTrait = this.loadPersonalizationTrait(nextProps.userTraits); - this.setState({ - serviceProviderTrait, - personalizationTrait, - formInvalid: false, - isSubmit: false, - }); - } - - componentWillUnmount() { - window.removeEventListener('resize', this.updatePredicate); - } - - /** - * Show User Consent Modal - * @param e event - */ - onHandleAddServiceProvider(e) { - if (e) e.preventDefault(); - const { newServiceProvider } = this.state; - this.setState({ isSubmit: true }); - if (this.onCheckFormValue(newServiceProvider)) { - return; - } - this.showConsent(this.onAddServiceProvider.bind(this)); - } - - /** - * Edit Service Provider by index - * @param indexNo the Service Provider index no - */ - onEditServiceProvider(indexNo) { - const { serviceProviderTrait } = this.state; - this.setState({ - newServiceProvider: { - serviceProviderType: serviceProviderTrait.traits.data[indexNo].serviceProviderType, - name: serviceProviderTrait.traits.data[indexNo].name, - }, - isEdit: true, - indexNo, - isSubmit: false, - }); - } - - /** - * Check form fields value, - * Invalid value, can not save - * @param newServiceProvider object - */ - onCheckFormValue(newServiceProvider) { - let invalid = false; - - if (!_.trim(newServiceProvider.serviceProviderType).length) { - invalid = true; - } - - if (!_.trim(newServiceProvider.name).length) { - invalid = true; - } - - this.setState({ formInvalid: invalid }); - return invalid; - } - - onHandleDeleteServiceProvider(indexNo) { - this.setState({ - showConfirmation: true, - indexNo, - }); - } - - /** - * Delete serviceProvider by index - * @param indexNo the serviceProvider index no - */ - onDeleteServiceProvider(indexNo) { - const { serviceProviderTrait } = this.state; - const newServiceProviderTrait = { ...serviceProviderTrait }; - newServiceProviderTrait.traits.data.splice(indexNo, 1); - this.setState({ - serviceProviderTrait: newServiceProviderTrait, - }); - - const { - handle, - tokenV3, - updateUserTrait, - deleteUserTrait, - } = this.props; - - if (newServiceProviderTrait.traits.data.length > 0) { - updateUserTrait(handle, 'service_provider', newServiceProviderTrait.traits.data, tokenV3); - } else { - deleteUserTrait(handle, 'service_provider', tokenV3); - } - this.setState({ - showConfirmation: false, - isEdit: false, - indexNo: null, - formInvalid: false, - isSubmit: false, - }); - } - - /** - * Add new serviceProvider - * @param answer user consent answer value - */ - onAddServiceProvider(answer) { - const { - newServiceProvider, personalizationTrait, isEdit, indexNo, - } = this.state; - - const { - handle, - tokenV3, - updateUserTrait, - addUserTrait, - } = this.props; - const { serviceProviderTrait } = this.state; - if (serviceProviderTrait.traits && serviceProviderTrait.traits.data.length > 0) { - const newServiceProviderTrait = _.cloneDeep(serviceProviderTrait); - if (isEdit) { - newServiceProviderTrait.traits.data.splice(indexNo, 1); - } - newServiceProviderTrait.traits.data.push(newServiceProvider); - updateUserTrait(handle, 'service_provider', newServiceProviderTrait.traits.data, tokenV3); - } else { - const newServiceProviders = []; - newServiceProviders.push(newServiceProvider); - addUserTrait(handle, 'service_provider', newServiceProviders, tokenV3); - } - const empty = { - serviceProviderType: '', - name: '', - }; - this.setState({ - newServiceProvider: empty, - isEdit: false, - indexNo: null, - isSubmit: false, - }); - // save personalization - if (_.isEmpty(personalizationTrait)) { - const personalizationData = { userConsent: answer }; - addUserTrait(handle, 'personalization', [personalizationData], tokenV3); - } else { - const trait = personalizationTrait.traits.data[0]; - if (trait.userConsent !== answer) { - const personalizationData = { userConsent: answer }; - updateUserTrait(handle, 'personalization', [personalizationData], tokenV3); - } - } - } - - /** - * Update input value - * @param e event - */ - onUpdateInput(e) { - const { newServiceProvider: oldServiceProvider } = this.state; - const newServiceProvider = { ...oldServiceProvider }; - newServiceProvider[e.target.name] = e.target.value; - this.setState({ newServiceProvider, isSubmit: false }); - } - - /** - * Update select value - * @param option selected value - */ - onUpdateSelect(option) { - if (option) { - const { newServiceProvider: oldServiceProvider } = this.state; - const newServiceProvider = { ...oldServiceProvider }; - newServiceProvider[option.key] = option.name; - this.setState({ newServiceProvider, isSubmit: false }); - } - } - - /** - * Get serviceProvider trait - * @param userTraits the all user traits - */ - loadServiceProviderTrait = (userTraits) => { - const trait = userTraits.filter(t => t.traitId === 'service_provider'); - const serviceProviders = trait.length === 0 ? {} : trait[0]; - return _.assign({}, serviceProviders); - } - - /** - * Get personalization trait - * @param userTraits the all user traits - */ - loadPersonalizationTrait = (userTraits) => { - const trait = userTraits.filter(t => t.traitId === 'personalization'); - const personalization = trait.length === 0 ? {} : trait[0]; - return _.assign({}, personalization); - } - - updatePredicate() { - const { screenSM } = this.state; - this.setState({ isMobileView: window.innerWidth <= screenSM }); - } - - isFormValid() { - const { newServiceProvider } = this.state; - if (newServiceProvider.serviceProviderType && (newServiceProvider.name.trim().length !== 0)) { - return true; - } - return false; - } - - onCancelEditStatus() { - const { isEdit } = this.state; - if (isEdit) { - this.setState({ - isEdit: false, - isSubmit: false, - indexNo: null, - formInvalid: false, - newServiceProvider: { - serviceProviderType: '', - name: '', - }, - }); - } - } - - render() { - const { - serviceProviderTrait, showConfirmation, indexNo, isEdit, - formInvalid, isSubmit, - } = this.state; - const serviceProviderItems = serviceProviderTrait.traits - ? serviceProviderTrait.traits.data.slice() : []; - const { newServiceProvider } = this.state; - const canModifyTrait = !this.props.traitRequestCount; - return ( - - { - this.shouldRenderConsent() && this.renderConsent() - } - {showConfirmation - && ( - this.showConsent(this.onDeleteServiceProvider.bind(this, indexNo))} - onCancel={() => this.setState({ showConfirmation: false, indexNo: null })} - name={serviceProviderTrait.traits.data[indexNo].name} - /> - )} -
    - -

    - Service Provider -

    - { - serviceProviderItems.length > 0 - && ( - - ) - } -
    -
    - Add a new service provider -
    -
    -
    - - - { - isSubmit && ( - - ) - } - - - - - { - isSubmit && ( - - ) - } - -
    -
    -
    - {!isEdit && ( - - Add Service Provider to Your List - - )} - - { isEdit && ( - - - Edit Service Provider to Your List - - - Cancel - - - )} -
    -
    -
    -
    -
    - ); - } -} - -ServiceProviders.propTypes = { - tokenV3: PT.string.isRequired, - handle: PT.string.isRequired, - traitRequestCount: PT.number.isRequired, - userTraits: PT.array.isRequired, - addUserTrait: PT.func.isRequired, - updateUserTrait: PT.func.isRequired, - deleteUserTrait: PT.func.isRequired, -}; diff --git a/src/shared/components/Settings/Tools/ServiceProviders/styles.scss b/src/shared/components/Settings/Tools/ServiceProviders/styles.scss deleted file mode 100644 index bb83ee57d8..0000000000 --- a/src/shared/components/Settings/Tools/ServiceProviders/styles.scss +++ /dev/null @@ -1,117 +0,0 @@ -@import "~styles/mixins"; - -.form-container { - padding: $pad-xxxxl; - background-color: $color-tc-white; - border-radius: 4px; - margin: $margin-sm 0 0; - - .service-provider-form { - display: flex; - flex-wrap: wrap; - } -} - -.form-title { - @include barlow-semi-bold; - - font-size: 20px; - line-height: 22px; - color: inherit; - text-transform: uppercase; - padding-bottom: $pad-xxxxl; -} - -.form-content { - display: flex; - flex-wrap: wrap; - align-items: flex-start; -} - -.form-label { - flex: 0 0 calc(50% - 13px); - padding-right: 230px; - - @include roboto-regular; - - font-size: 16px; - line-height: 26px; - color: inherit; -} - -.form-body { - flex: 0 0 calc(50% + 13px); -} - -.form-footer { - display: flex; - align-items: center; - justify-content: flex-start; - margin-left: calc(50% - 13px); - padding: $pad-sm 0; - gap: 8px 16px; - flex-wrap: wrap; - - .button { - @include roboto-bold; - - font-size: 14px; - line-height: 14px; - text-align: left; - color: $color-turq-160; - min-height: 0; - margin: 0; - padding: 0; - background: transparent !important; - border: none; - cursor: pointer; - - &:hover, - &:active, - &:focus { - outline: none !important; - color: lighten($color-turq-160, 5%); - background: transparent !important; - box-shadow: none !important; - } - - .icon { - margin-right: $margin-xs; - - @media screen and (max-width: 335px) { - position: relative; - bottom: 12px; - } - } - } -} - -@include xs-to-md { - .form-container { - padding: $pad-xxl $pad-lg; - } - - .form-title { - @include barlow-condensed-medium; - - font-size: 22px; - line-height: 24px; - padding-bottom: $pad-xxl; - } - - .form-label { - flex: 1 1 100%; - padding: 0; - margin-bottom: $margin-xxl; - font-size: 14px; - line-height: 20px; - } - - .form-body { - flex: 1 1 100%; - } - - .form-footer { - margin: 0; - } -} diff --git a/src/shared/components/Settings/Tools/Software/List/Item/index.jsx b/src/shared/components/Settings/Tools/Software/List/Item/index.jsx deleted file mode 100644 index 483ea9f0b7..0000000000 --- a/src/shared/components/Settings/Tools/Software/List/Item/index.jsx +++ /dev/null @@ -1,96 +0,0 @@ -/** - * render software Item - */ -import React from 'react'; -import PT from 'prop-types'; -import ReactSVG from 'react-svg'; -import { isomorphy } from 'topcoder-react-utils'; -import Tooltip from 'components/Tooltip'; - -import './styles.scss'; - -let assets; -if (isomorphy.isClientSide()) { - assets = require.context('assets/images/tools/software-types', false, /svg/); -} - -export default function Item(props) { - const { - software, - index, - onDeleteItem, - onEditItem, - } = props; - - const deleteTip = ( -
    -

    Delete

    -
    - ); - - const editTip = ( -
    -

    Edit

    -
    - ); - - return ( - - ); -} - -Item.propTypes = { - software: PT.shape().isRequired, - index: PT.number.isRequired, - onDeleteItem: PT.func.isRequired, - onEditItem: PT.func.isRequired, -}; diff --git a/src/shared/components/Settings/Tools/Software/List/Item/styles.scss b/src/shared/components/Settings/Tools/Software/List/Item/styles.scss deleted file mode 100644 index 2cfbd41f53..0000000000 --- a/src/shared/components/Settings/Tools/Software/List/Item/styles.scss +++ /dev/null @@ -1,209 +0,0 @@ -@import "../../../../style"; - -.container { - display: flex; - flex-direction: row; - justify-items: center; - justify-content: space-between; - align-items: center; - min-height: 96px; - width: 100%; - border-bottom: none; - background-color: $tc-white; - padding: $pad-lg; - border: 1px solid $color-black-20; - border-radius: 8px; - - @media screen and (max-width: 374px) { - padding: $pad-sm; - } -} - -.software-info { - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; -} - -.software-icon { - display: flex; - align-items: center; - justify-content: center; - flex: 0 0 64px; - width: 64px; - height: 64px; - background: $color-black-5; - border-radius: 4px; - margin-right: $margin-lg; - - svg { - display: block; - } -} - -.software-parameters { - @include roboto-medium; - - display: flex; - flex-direction: column; - justify-items: center; - justify-content: center; - font-size: 15px; - line-height: 20px; - text-transform: capitalize; - padding-right: 20px; - - &.single-line { - flex-direction: row; - align-items: center; - } -} - -.parameter-first-line { - @include roboto-bold; - - color: $tc-black; - font-weight: 700; - font-size: 16px; - line-height: 20px; - letter-spacing: 0.5px; - text-transform: capitalize; - word-break: break-all; - - &.single-line { - margin-bottom: 0; - } - - @include upto-sm { - margin-bottom: 0; - } -} - -.parameter-second-line, -.parameter-third-line, -.parameter-second-line-mobile { - @include roboto-medium; - - color: $color-black-60; - font-weight: 400; - font-size: 16px; - line-height: 24px; - word-break: break-all; -} - -.parameter-second-line-mobile { - @include upto-sm { - display: flex; - flex-direction: column; - - p { - word-break: break-all; - } - } -} - -.tctooltiptext { - background: $tooltip-gray; - color: $tc-white; - border-radius: 8px; - padding: 10px; - - p { - @include roboto-medium; - - font-weight: 400; - font-size: 14px; - line-height: 22px; - } -} - -.tctooltiptext::after { - content: ""; - position: absolute; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; - bottom: 4px; - margin-left: -5px; - border-width: 5px 5px 0; - left: 50%; - border-top-color: $tc-black; - z-index: 1000; -} - -.operation-container { - display: flex; - flex-direction: row; - justify-content: space-between; - - .delete-wrapper { - margin-left: $margin-xl; - margin-right: $margin-xs; - - @include xs-to-sm { - margin-left: $margin-lg; - margin-right: 0; - } - - @media screen and (max-width: 320px) { - margin-right: 0; - margin-left: 6px; - } - } - - .delete { - display: flex; - flex-direction: column; - justify-items: center; - justify-content: center; - cursor: pointer; - outline-style: none; - - img { - width: 20px; - height: 20px; - } - - p { - @include roboto-regular; - - font-size: 11px; - line-height: 15px; - font-weight: 400; - color: $tc-gray-50; - - @include upto-sm { - display: none; - } - } - } - - .edit { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - cursor: pointer; - outline-style: none; - - img { - width: 20px; - height: 20px; - } - - p { - @include roboto-regular; - - font-size: 11px; - line-height: 15px; - font-weight: 400; - color: $tc-gray-50; - - @include upto-sm { - display: none; - } - } - } -} diff --git a/src/shared/components/Settings/Tools/Software/List/index.jsx b/src/shared/components/Settings/Tools/Software/List/index.jsx deleted file mode 100644 index 31909f2d15..0000000000 --- a/src/shared/components/Settings/Tools/Software/List/index.jsx +++ /dev/null @@ -1,44 +0,0 @@ -/** - * render Software list - */ -import React from 'react'; -import PT from 'prop-types'; -import Item from './Item'; - -import './styles.scss'; - -export default function SoftwareList(props) { - const { - softwareList, - onDeleteItem, - onEditItem, - } = props; - - return ( -
    -
      - { - softwareList.items.map((software, index) => ( -
    • - -
    • - )) - } -
    -
    - ); -} - -SoftwareList.propTypes = { - softwareList: PT.shape().isRequired, - onDeleteItem: PT.func.isRequired, - onEditItem: PT.func.isRequired, -}; - -SoftwareList.defaultProps = { -}; diff --git a/src/shared/components/Settings/Tools/Software/List/styles.scss b/src/shared/components/Settings/Tools/Software/List/styles.scss deleted file mode 100644 index cd428a461a..0000000000 --- a/src/shared/components/Settings/Tools/Software/List/styles.scss +++ /dev/null @@ -1,27 +0,0 @@ -@import "../../../style"; -@import "~styles/mixins"; - -.container { - width: 100%; - background-color: $tc-white; - padding: 0 0; - margin: 0 0 $margin-xxxxl; - - &.active { - margin-top: 20px; - - @include upto-sm { - margin-top: 0; - } - } - - ul { - display: flex; - flex-direction: column; - justify-items: center; - - li { - margin-bottom: $margin-md; - } - } -} diff --git a/src/shared/components/Settings/Tools/Software/dropdowns.json b/src/shared/components/Settings/Tools/Software/dropdowns.json deleted file mode 100644 index 9fad06ef9c..0000000000 --- a/src/shared/components/Settings/Tools/Software/dropdowns.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "type": [ - { - "key": "softwareType", - "name": "Developer Tools" - }, - { - "key": "softwareType", - "name": "Browser" - }, - { - "key": "softwareType", - "name": "Productivity" - }, - { - "key": "softwareType", - "name": "Graphics & Design" - }, - { - "key": "softwareType", - "name": "Utilities" - } - ] -} \ No newline at end of file diff --git a/src/shared/components/Settings/Tools/Software/index.jsx b/src/shared/components/Settings/Tools/Software/index.jsx deleted file mode 100644 index 9251db202d..0000000000 --- a/src/shared/components/Settings/Tools/Software/index.jsx +++ /dev/null @@ -1,427 +0,0 @@ -/** - * Child component of Settings/Tools/ renders the - * 'Software' page. - */ -/* eslint-disable react/forbid-prop-types */ -/* eslint-disable no-nested-ternary */ -/* eslint-disable jsx-a11y/label-has-for */ -/* eslint-disable no-undef */ -import React from 'react'; -import PT from 'prop-types'; -import _ from 'lodash'; -import ConsentComponent from 'components/Settings/ConsentComponent'; -import ErrorMessage from 'components/Settings/ErrorMessage'; -import FormField from 'components/Settings/FormField'; -import FormInputText from 'components/Settings/FormInputText'; -import AddItemIcon from 'assets/images/settings-add-item.svg'; -import FormInputSelect from 'components/Settings/FormInputSelect'; -import { SettingBannerV2 as Collapse } from 'components/Settings/SettingsBanner'; -import { PrimaryButton, SecondaryButton } from 'topcoder-react-ui-kit'; -import ConfirmationModal from '../../ConfirmationModal'; -import dropdowns from './dropdowns.json'; -import SoftwareList from './List'; - -import styles from './styles.scss'; - - -export default class Software extends ConsentComponent { - constructor(props) { - super(props); - this.onHandleDeleteSoftware = this.onHandleDeleteSoftware.bind(this); - this.onDeleteSoftware = this.onDeleteSoftware.bind(this); - this.onEditSoftware = this.onEditSoftware.bind(this); - this.onUpdateSelect = this.onUpdateSelect.bind(this); - this.loadSoftwareTrait = this.loadSoftwareTrait.bind(this); - this.onUpdateInput = this.onUpdateInput.bind(this); - this.onHandleAddSoftware = this.onHandleAddSoftware.bind(this); - this.onAddSoftware = this.onAddSoftware.bind(this); - this.loadPersonalizationTrait = this.loadPersonalizationTrait.bind(this); - this.updatePredicate = this.updatePredicate.bind(this); - this.onCancelEditStatus = this.onCancelEditStatus.bind(this); - - const { userTraits } = props; - this.state = { - formInvalid: false, - isSubmit: false, - softwareTrait: this.loadSoftwareTrait(userTraits), - personalizationTrait: this.loadPersonalizationTrait(userTraits), - newSoftware: { - softwareType: '', - name: '', - }, - isMobileView: false, - screenSM: 767, - showConfirmation: false, - indexNo: null, - isEdit: false, - }; - } - - componentDidMount() { - this.updatePredicate(); - window.addEventListener('resize', this.updatePredicate); - } - - componentWillReceiveProps(nextProps) { - const softwareTrait = this.loadSoftwareTrait(nextProps.userTraits); - const personalizationTrait = this.loadPersonalizationTrait(nextProps.userTraits); - this.setState({ - softwareTrait, - personalizationTrait, - formInvalid: false, - isSubmit: false, - }); - } - - componentWillUnmount() { - window.removeEventListener('resize', this.updatePredicate); - } - - /** - * Show User Consent Modal - * @param e event - */ - onHandleAddSoftware(e) { - if (e) e.preventDefault(); - const { newSoftware } = this.state; - this.setState({ isSubmit: true }); - if (this.onCheckFormValue(newSoftware)) { - return; - } - this.showConsent(this.onAddSoftware.bind(this)); - } - - /** - * Check form fields value, - * Invalid value, can not save - * @param newSoftware object - */ - onCheckFormValue(newSoftware) { - let invalid = false; - - if (!_.trim(newSoftware.softwareType).length) { - invalid = true; - } - - if (!_.trim(newSoftware.name).length) { - invalid = true; - } - - this.setState({ formInvalid: invalid }); - return invalid; - } - - onHandleDeleteSoftware(indexNo) { - this.setState({ - showConfirmation: true, - indexNo, - isSubmit: false, - }); - } - - /** - * Delete software by index - * @param indexNo the software index no - */ - onDeleteSoftware(indexNo) { - const { softwareTrait } = this.state; - const newSoftwareTrait = { ...softwareTrait }; - newSoftwareTrait.traits.data.splice(indexNo, 1); - this.setState({ - softwareTrait: newSoftwareTrait, - }); - - const { - handle, - tokenV3, - updateUserTrait, - deleteUserTrait, - } = this.props; - - if (newSoftwareTrait.traits.data.length > 0) { - updateUserTrait(handle, 'software', newSoftwareTrait.traits.data, tokenV3); - } else { - deleteUserTrait(handle, 'software', tokenV3); - } - this.setState({ - showConfirmation: false, - indexNo: null, - isSubmit: false, - isEdit: false, - formInvalid: false, - }); - } - - /** - * Edit software by index - * @param indexNo the software index no - */ - onEditSoftware(indexNo) { - const { softwareTrait } = this.state; - this.setState({ - newSoftware: { - softwareType: softwareTrait.traits.data[indexNo].softwareType, - name: softwareTrait.traits.data[indexNo].name, - }, - isEdit: true, - indexNo, - isSubmit: false, - }); - } - - /** - * Add new software - * @param answer user consent answer value - */ - onAddSoftware(answer) { - const { - newSoftware, personalizationTrait, isEdit, indexNo, - } = this.state; - - const { - handle, - tokenV3, - updateUserTrait, - addUserTrait, - } = this.props; - const { softwareTrait } = this.state; - if (softwareTrait.traits && softwareTrait.traits.data.length > 0) { - const newSoftwareTrait = _.cloneDeep(softwareTrait); - if (isEdit) { - newSoftwareTrait.traits.data.splice(indexNo, 1); - } - newSoftwareTrait.traits.data.push(newSoftware); - updateUserTrait(handle, 'software', newSoftwareTrait.traits.data, tokenV3); - } else { - const newSoftwares = []; - newSoftwares.push(newSoftware); - addUserTrait(handle, 'software', newSoftwares, tokenV3); - } - const empty = { - softwareType: '', - name: '', - }; - this.setState({ - newSoftware: empty, - isEdit: false, - indexNo: null, - inputChanged: false, - isSubmit: false, - }); - // save personalization - if (_.isEmpty(personalizationTrait)) { - const personalizationData = { userConsent: answer }; - addUserTrait(handle, 'personalization', [personalizationData], tokenV3); - } else { - const trait = personalizationTrait.traits.data[0]; - if (trait.userConsent !== answer) { - const personalizationData = { userConsent: answer }; - updateUserTrait(handle, 'personalization', [personalizationData], tokenV3); - } - } - } - - /** - * Update input value - * @param e event - */ - onUpdateInput(e) { - const { newSoftware: oldSoftware } = this.state; - const newSoftware = { ...oldSoftware }; - newSoftware[e.target.name] = e.target.value; - this.setState({ newSoftware, isSubmit: false }); - } - - /** - * Update select value - * @param option selected value - */ - onUpdateSelect(option) { - if (option) { - const { newSoftware: oldSoftware } = this.state; - const newSoftware = { ...oldSoftware }; - newSoftware[option.key] = option.name; - this.setState({ newSoftware, isSubmit: false }); - } - } - - /** - * Get software trait - * @param userTraits the all user traits - */ - loadSoftwareTrait = (userTraits) => { - const trait = userTraits.filter(t => t.traitId === 'software'); - const softwares = trait.length === 0 ? {} : trait[0]; - return _.assign({}, softwares); - } - - /** - * Get personalization trait - * @param userTraits the all user traits - */ - loadPersonalizationTrait = (userTraits) => { - const trait = userTraits.filter(t => t.traitId === 'personalization'); - const personalization = trait.length === 0 ? {} : trait[0]; - return _.assign({}, personalization); - } - - updatePredicate() { - const { screenSM } = this.state; - this.setState({ isMobileView: window.innerWidth <= screenSM }); - } - - isFormValid() { - const { newSoftware } = this.state; - if (newSoftware.softwareType && (newSoftware.name.trim().length !== 0)) { - return true; - } - return false; - } - - onCancelEditStatus() { - const { isEdit } = this.state; - if (isEdit) { - this.setState({ - isEdit: false, - indexNo: null, - inputChanged: false, - formInvalid: false, - newSoftware: { - softwareType: '', - name: '', - }, - isSubmit: false, - }); - } - } - - render() { - const { - softwareTrait, showConfirmation, indexNo, isEdit, - formInvalid, isSubmit, - } = this.state; - const softwareItems = softwareTrait.traits - ? softwareTrait.traits.data.slice() : []; - const { newSoftware } = this.state; - const canModifyTrait = !this.props.traitRequestCount; - return ( - - { - this.shouldRenderConsent() && this.renderConsent() - } - {showConfirmation - && ( - this.showConsent(this.onDeleteSoftware.bind(this, indexNo))} - onCancel={() => this.setState({ showConfirmation: false, indexNo: null })} - name={softwareTrait.traits.data[indexNo].name} - /> - )} -
    - -

    - Software -

    - { - softwareItems.length > 0 - && ( - - ) - } -
    -
    - { - isEdit ? (Edit software) - : (Add a new software) - } -
    -
    -
    - - - { - isSubmit && ( - - ) - } - - - - - { - isSubmit && ( - - ) - } - -
    -
    -
    - {!isEdit && ( - - Add Software to Your List - - )} - - { isEdit && ( - - - Edit Software to Your List - - - Cancel - - - )} -
    -
    -
    -
    -
    - ); - } -} - -Software.propTypes = { - tokenV3: PT.string.isRequired, - handle: PT.string.isRequired, - traitRequestCount: PT.number.isRequired, - userTraits: PT.array.isRequired, - addUserTrait: PT.func.isRequired, - updateUserTrait: PT.func.isRequired, - deleteUserTrait: PT.func.isRequired, -}; diff --git a/src/shared/components/Settings/Tools/Software/styles.scss b/src/shared/components/Settings/Tools/Software/styles.scss deleted file mode 100644 index b39a854adb..0000000000 --- a/src/shared/components/Settings/Tools/Software/styles.scss +++ /dev/null @@ -1,110 +0,0 @@ -@import "~styles/mixins"; - -.form-container { - padding: $pad-xxxxl; - background-color: $color-tc-white; - border-radius: 4px; - margin: $margin-sm 0 0; - - .software-form { - display: flex; - flex-wrap: wrap; - } -} - -.form-title { - @include barlow-semi-bold; - - font-size: 20px; - line-height: 22px; - color: inherit; - text-transform: uppercase; - padding-bottom: $pad-xxxxl; -} - -.form-content { - display: flex; - flex-wrap: wrap; - align-items: flex-start; -} - -.form-label { - flex: 0 0 calc(50% - 13px); - padding-right: 230px; - - @include roboto-regular; - - font-size: 16px; - line-height: 26px; - color: inherit; -} - -.form-body { - flex: 0 0 calc(50% + 13px); -} - -.form-footer { - display: flex; - align-items: center; - justify-content: flex-start; - margin-left: calc(50% - 13px); - padding: $pad-sm 0; - gap: 8px 16px; - - .button { - @include roboto-bold; - - font-size: 14px; - line-height: 14px; - color: $color-turq-160; - min-height: 0; - margin: 0; - padding: 0; - background: transparent !important; - border: none; - cursor: pointer; - - &:hover, - &:active, - &:focus { - outline: none !important; - color: lighten($color-turq-160, 5%); - background: transparent !important; - box-shadow: none !important; - } - - .icon { - margin-right: $margin-xs; - } - } -} - -@include xs-to-md { - .form-container { - padding: $pad-xxl $pad-lg; - } - - .form-title { - @include barlow-condensed-medium; - - font-size: 22px; - line-height: 24px; - padding-bottom: $pad-xxl; - } - - .form-label { - flex: 1 1 100%; - padding: 0; - margin-bottom: $margin-xxl; - font-size: 14px; - line-height: 20px; - } - - .form-body { - flex: 1 1 100%; - } - - .form-footer { - margin: 0; - } -} diff --git a/src/shared/components/Settings/Tools/Subscriptions/List/Item/index.jsx b/src/shared/components/Settings/Tools/Subscriptions/List/Item/index.jsx deleted file mode 100644 index e3a796e7cd..0000000000 --- a/src/shared/components/Settings/Tools/Subscriptions/List/Item/index.jsx +++ /dev/null @@ -1,92 +0,0 @@ -/** - * render subscription Item - */ -import React from 'react'; -import PT from 'prop-types'; -import ReactSVG from 'react-svg'; -import { isomorphy } from 'topcoder-react-utils'; -import Tooltip from 'components/Tooltip'; - -import './styles.scss'; - -let assets; -if (isomorphy.isClientSide()) { - assets = require.context('assets/images/tools/subscription-types', false, /svg/); -} - -export default function Item(props) { - const { - subscription, - index, - onDeleteItem, - onEditItem, - } = props; - - const deleteTip = ( -
    -

    Delete

    -
    - ); - - const editTip = ( -
    -

    Edit

    -
    - ); - - return ( - - ); -} - -Item.propTypes = { - subscription: PT.shape().isRequired, - index: PT.number.isRequired, - onDeleteItem: PT.func.isRequired, - onEditItem: PT.func.isRequired, -}; diff --git a/src/shared/components/Settings/Tools/Subscriptions/List/Item/styles.scss b/src/shared/components/Settings/Tools/Subscriptions/List/Item/styles.scss deleted file mode 100644 index 4be737d917..0000000000 --- a/src/shared/components/Settings/Tools/Subscriptions/List/Item/styles.scss +++ /dev/null @@ -1,215 +0,0 @@ -@import "../../../../style"; - -.container { - display: flex; - flex-direction: row; - justify-items: center; - justify-content: space-between; - align-items: center; - min-height: 96px; - width: 100%; - border-bottom: none; - background-color: $tc-white; - padding: $pad-lg; - border: 1px solid $color-black-20; - border-radius: 8px; - - @media screen and (max-width: 374px) { - padding: $pad-sm; - } -} - -.subscription-info { - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; -} - -.subscription-icon { - display: flex; - align-items: center; - justify-content: center; - flex: 0 0 64px; - width: 64px; - height: 64px; - background: $color-black-5; - border-radius: 4px; - margin-right: $margin-lg; - - svg { - display: block; - } -} - -.subscription-parameters { - @include roboto-medium; - - display: flex; - flex-direction: column; - justify-items: center; - justify-content: center; - font-size: 15px; - line-height: 20px; - text-transform: capitalize; - padding-right: 20px; - - &.single-line { - flex-direction: row; - align-items: center; - } -} - -.parameter-first-line { - @include roboto-bold; - - color: $tc-black; - font-weight: 700; - font-size: 16px; - line-height: 20px; - letter-spacing: 0.5px; - text-transform: capitalize; - word-break: break-all; - - &.single-line { - margin-bottom: 0; - } - - @include upto-sm { - margin-bottom: 0; - } -} - -.parameter-second-line, -.parameter-third-line, -.parameter-second-line-mobile { - @include roboto-medium; - - color: $color-black-60; - font-weight: 400; - font-size: 16px; - line-height: 24px; - word-break: break-all; - - @include upto-sm { - display: none; - } -} - -.parameter-second-line-mobile { - display: none; - - @include upto-sm { - display: flex; - flex-direction: column; - - p { - word-break: break-all; - } - } -} - -.tctooltiptext { - background: $tooltip-gray; - color: $tc-white; - border-radius: 8px; - padding: 10px; - - p { - @include roboto-medium; - - font-weight: 400; - font-size: 14px; - line-height: 22px; - } -} - -.tctooltiptext::after { - content: ""; - position: absolute; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; - bottom: 4px; - margin-left: -5px; - border-width: 5px 5px 0; - left: 50%; - border-top-color: $tc-black; - z-index: 1000; -} - -.operation-container { - display: flex; - flex-direction: row; - justify-content: space-between; - - .delete-wrapper { - margin-left: $margin-xl; - margin-right: $margin-xs; - - @include xs-to-sm { - margin-left: $margin-lg; - margin-right: 0; - } - - @media screen and (max-width: 320px) { - margin-right: 0; - margin-left: 6px; - } - } - - .delete { - display: flex; - flex-direction: column; - justify-items: center; - justify-content: center; - cursor: pointer; - outline-style: none; - - img { - width: 20px; - height: 20px; - } - - p { - @include roboto-regular; - - font-size: 11px; - line-height: 15px; - font-weight: 400; - color: $tc-gray-50; - - @include upto-sm { - display: none; - } - } - } - - .edit { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - cursor: pointer; - outline-style: none; - - img { - width: 20px; - height: 20px; - } - - p { - @include roboto-regular; - - font-size: 11px; - line-height: 15px; - font-weight: 400; - color: $tc-gray-50; - - @include upto-sm { - display: none; - } - } - } -} diff --git a/src/shared/components/Settings/Tools/Subscriptions/List/index.jsx b/src/shared/components/Settings/Tools/Subscriptions/List/index.jsx deleted file mode 100644 index c782774d96..0000000000 --- a/src/shared/components/Settings/Tools/Subscriptions/List/index.jsx +++ /dev/null @@ -1,44 +0,0 @@ -/** - * render Subscription list - */ -import React from 'react'; -import PT from 'prop-types'; -import Item from './Item'; - -import './styles.scss'; - -export default function SubscriptionList(props) { - const { - subscriptionList, - onDeleteItem, - onEditItem, - } = props; - - return ( -
    -
      - { - subscriptionList.items.map((subscription, index) => ( -
    • - -
    • - )) - } -
    -
    - ); -} - -SubscriptionList.propTypes = { - subscriptionList: PT.shape().isRequired, - onDeleteItem: PT.func.isRequired, - onEditItem: PT.func.isRequired, -}; - -SubscriptionList.defaultProps = { -}; diff --git a/src/shared/components/Settings/Tools/Subscriptions/List/styles.scss b/src/shared/components/Settings/Tools/Subscriptions/List/styles.scss deleted file mode 100644 index 979df1bf53..0000000000 --- a/src/shared/components/Settings/Tools/Subscriptions/List/styles.scss +++ /dev/null @@ -1,32 +0,0 @@ -@import "../../../style"; - -.container { - width: 100%; - background-color: $tc-white; - padding: 0; - margin: 0 0 $margin-xxxxl; - - &.active { - margin-top: 20px; - - @include upto-sm { - margin-top: 0; - } - } - - ul { - display: flex; - flex-direction: column; - justify-items: center; - - li { - margin-bottom: $margin-md; - } - } - - &.disabled { - opacity: 0.7; - pointer-events: none; - user-select: none; - } -} diff --git a/src/shared/components/Settings/Tools/Subscriptions/index.jsx b/src/shared/components/Settings/Tools/Subscriptions/index.jsx deleted file mode 100644 index eb815cb425..0000000000 --- a/src/shared/components/Settings/Tools/Subscriptions/index.jsx +++ /dev/null @@ -1,387 +0,0 @@ -/** - * Child component of Settings/Tools/ renders the - * 'Subscription' page. - */ -/* eslint-disable react/forbid-prop-types */ -/* eslint-disable no-nested-ternary */ -/* eslint-disable jsx-a11y/label-has-for */ -/* eslint-disable no-undef */ -import React from 'react'; -import PT from 'prop-types'; -import _ from 'lodash'; -import ConsentComponent from 'components/Settings/ConsentComponent'; -import ErrorMessage from 'components/Settings/ErrorMessage'; -import FormField from 'components/Settings/FormField'; -import FormInputText from 'components/Settings/FormInputText'; -import AddItemIcon from 'assets/images/settings-add-item.svg'; -import { SettingBannerV2 as Collapse } from 'components/Settings/SettingsBanner'; -import { PrimaryButton, SecondaryButton } from 'topcoder-react-ui-kit'; -import ConfirmationModal from '../../ConfirmationModal'; -import SubscriptionList from './List'; - -import styles from './styles.scss'; - -export default class Subscription extends ConsentComponent { - constructor(props) { - super(props); - this.onHandleDeleteSubscription = this.onHandleDeleteSubscription.bind(this); - this.onDeleteSubscription = this.onDeleteSubscription.bind(this); - this.onEditSubscription = this.onEditSubscription.bind(this); - this.onUpdateSelect = this.onUpdateSelect.bind(this); - this.loadSubscriptionTrait = this.loadSubscriptionTrait.bind(this); - this.onUpdateInput = this.onUpdateInput.bind(this); - this.onHandleAddSubscription = this.onHandleAddSubscription.bind(this); - this.onAddSubscription = this.onAddSubscription.bind(this); - this.loadPersonalizationTrait = this.loadPersonalizationTrait.bind(this); - this.updatePredicate = this.updatePredicate.bind(this); - this.onCancelEditStatus = this.onCancelEditStatus.bind(this); - - const { userTraits } = props; - this.state = { - formInvalid: false, - isSubmit: false, - subscriptionTrait: this.loadSubscriptionTrait(userTraits), - personalizationTrait: this.loadPersonalizationTrait(userTraits), - newSubscription: { - name: '', - }, - isMobileView: false, - screenSM: 767, - showConfirmation: false, - indexNo: null, - isEdit: false, - }; - } - - componentDidMount() { - this.updatePredicate(); - window.addEventListener('resize', this.updatePredicate); - } - - componentWillReceiveProps(nextProps) { - const personalizationTrait = this.loadPersonalizationTrait(nextProps.userTraits); - const subscriptionTrait = this.loadSubscriptionTrait(nextProps.userTraits); - this.setState({ - subscriptionTrait, - personalizationTrait, - formInvalid: false, - isSubmit: false, - }); - } - - componentWillUnmount() { - window.removeEventListener('resize', this.updatePredicate); - } - - /** - * Show User Consent Modal - * @param e event - */ - onHandleAddSubscription(e) { - if (e) e.preventDefault(); - const { newSubscription } = this.state; - this.setState({ isSubmit: true }); - if (this.onCheckFormValue(newSubscription)) { - return; - } - this.showConsent(this.onAddSubscription.bind(this)); - } - - /** - * Edit Subscription by index - * @param indexNo the Subscription index no - */ - onEditSubscription(indexNo) { - const { subscriptionTrait } = this.state; - this.setState({ - newSubscription: { - name: subscriptionTrait.traits.data[indexNo].name, - }, - isEdit: true, - indexNo, - isSubmit: false, - }); - } - - /** - * Check form fields value, - * Invalid value, can not save - * @param newSubscription object - */ - onCheckFormValue(newSubscription) { - let invalid = false; - - if (!_.trim(newSubscription.name).length) { - invalid = true; - } - - this.setState({ formInvalid: invalid }); - return invalid; - } - - onHandleDeleteSubscription(indexNo) { - this.setState({ - showConfirmation: true, - indexNo, - }); - } - - /** - * Delete subscription by index - * @param indexNo the subscription index no - */ - onDeleteSubscription(indexNo) { - const { subscriptionTrait } = this.state; - const newSubscriptionTrait = { ...subscriptionTrait }; - newSubscriptionTrait.traits.data.splice(indexNo, 1); - this.setState({ - subscriptionTrait: newSubscriptionTrait, - }); - - const { - handle, - tokenV3, - updateUserTrait, - deleteUserTrait, - } = this.props; - - if (newSubscriptionTrait.traits.data.length > 0) { - updateUserTrait(handle, 'subscription', newSubscriptionTrait.traits.data, tokenV3); - } else { - deleteUserTrait(handle, 'subscription', tokenV3); - } - this.setState({ - showConfirmation: false, - indexNo: null, - formInvalid: false, - isEdit: false, - isSubmit: false, - }); - } - - /** - * Add new subscription - * @param answer user consent answer value - */ - onAddSubscription(answer) { - const { - newSubscription, personalizationTrait, isEdit, indexNo, - } = this.state; - - const { - handle, - tokenV3, - updateUserTrait, - addUserTrait, - } = this.props; - const { subscriptionTrait } = this.state; - if (subscriptionTrait.traits && subscriptionTrait.traits.data.length > 0) { - const newSubscriptionTrait = _.cloneDeep(subscriptionTrait); - if (isEdit) { - newSubscriptionTrait.traits.data.splice(indexNo, 1); - } - newSubscriptionTrait.traits.data.push(newSubscription); - updateUserTrait(handle, 'subscription', newSubscriptionTrait.traits.data, tokenV3); - } else { - const newSubscriptions = []; - newSubscriptions.push(newSubscription); - addUserTrait(handle, 'subscription', newSubscriptions, tokenV3); - } - const empty = { - name: '', - }; - this.setState({ - newSubscription: empty, - isEdit: false, - indexNo: null, - inputChanged: false, - isSubmit: false, - }); - // save personalization - if (_.isEmpty(personalizationTrait)) { - const personalizationData = { userConsent: answer }; - addUserTrait(handle, 'personalization', [personalizationData], tokenV3); - } else { - const trait = personalizationTrait.traits.data[0]; - if (trait.userConsent !== answer) { - const personalizationData = { userConsent: answer }; - updateUserTrait(handle, 'personalization', [personalizationData], tokenV3); - } - } - } - - /** - * Update input value - * @param e event - */ - onUpdateInput(e) { - const { newSubscription: oldSubscription } = this.state; - const newSubscription = { ...oldSubscription }; - newSubscription[e.target.name] = e.target.value; - this.setState({ newSubscription, isSubmit: false }); - } - - /** - * Update select value - * @param option selected value - */ - onUpdateSelect(option) { - if (option) { - const { newSubscription: oldSubscription } = this.state; - const newSubscription = { ...oldSubscription }; - newSubscription[option.key] = option.name; - this.setState({ newSubscription, isSubmit: false }); - } - } - - /** - * Get subscription trait - * @param userTraits the all user traits - */ - loadSubscriptionTrait = (userTraits) => { - const trait = userTraits.filter(t => t.traitId === 'subscription'); - const subscriptions = trait.length === 0 ? {} : trait[0]; - return _.assign({}, subscriptions); - } - - /** - * Get personalization trait - * @param userTraits the all user traits - */ - loadPersonalizationTrait = (userTraits) => { - const trait = userTraits.filter(t => t.traitId === 'personalization'); - const personalization = trait.length === 0 ? {} : trait[0]; - return _.assign({}, personalization); - } - - updatePredicate() { - const { screenSM } = this.state; - this.setState({ isMobileView: window.innerWidth <= screenSM }); - } - - onCancelEditStatus() { - const { isEdit } = this.state; - if (isEdit) { - this.setState({ - isEdit: false, - indexNo: null, - formInvalid: false, - isSubmit: false, - newSubscription: { - name: '', - }, - }); - } - } - - render() { - const { - subscriptionTrait, showConfirmation, indexNo, isEdit, isSubmit, - } = this.state; - const subscriptionItems = subscriptionTrait.traits - ? subscriptionTrait.traits.data.slice() : []; - const { newSubscription, formInvalid } = this.state; - const canModifyTrait = !this.props.traitRequestCount; - - return ( - - { - this.shouldRenderConsent() && this.renderConsent() - } - {showConfirmation - && ( - this.showConsent(this.onDeleteSubscription.bind(this, indexNo))} - onCancel={() => this.setState({ showConfirmation: false, indexNo: null })} - name={subscriptionTrait.traits.data[indexNo].name} - /> - )} -
    - -

    - Subscriptions -

    - { - subscriptionItems.length > 0 - && ( - - ) - } -
    -
    - { - isEdit ? (Edit subscription) - : (Add a new subscription) - } -
    -
    -
    - - - { - isSubmit && ( - - ) - } - -
    -
    -
    - {!isEdit && ( - - Add Subscription to Your List - - )} - - { isEdit && ( - - - Edit Subscription to Your List - - - Cancel - - - )} -
    -
    -
    -
    -
    - ); - } -} - -Subscription.propTypes = { - tokenV3: PT.string.isRequired, - handle: PT.string.isRequired, - traitRequestCount: PT.number.isRequired, - userTraits: PT.array.isRequired, - addUserTrait: PT.func.isRequired, - updateUserTrait: PT.func.isRequired, - deleteUserTrait: PT.func.isRequired, -}; diff --git a/src/shared/components/Settings/Tools/Subscriptions/styles.scss b/src/shared/components/Settings/Tools/Subscriptions/styles.scss deleted file mode 100644 index f99f50c91a..0000000000 --- a/src/shared/components/Settings/Tools/Subscriptions/styles.scss +++ /dev/null @@ -1,111 +0,0 @@ -@import "~styles/mixins"; - -.form-container { - padding: $pad-xxxxl; - background-color: $color-tc-white; - border-radius: 4px; - margin: $margin-sm 0 0; - - .subscription-form { - display: flex; - flex-wrap: wrap; - } -} - -.form-title { - @include barlow-semi-bold; - - font-size: 20px; - line-height: 22px; - color: inherit; - text-transform: uppercase; - padding-bottom: $pad-xxxxl; -} - -.form-content { - display: flex; - flex-wrap: wrap; - align-items: flex-start; -} - -.form-label { - flex: 0 0 calc(50% - 13px); - padding-right: 230px; - - @include roboto-regular; - - font-size: 16px; - line-height: 26px; - color: inherit; -} - -.form-body { - flex: 0 0 calc(50% + 13px); -} - -.form-footer { - display: flex; - align-items: center; - justify-content: flex-start; - margin-left: calc(50% - 13px); - padding: $pad-sm 0; - flex-wrap: wrap; - gap: 8px 16px; - - .button { - @include roboto-bold; - - font-size: 14px; - line-height: 14px; - color: $color-turq-160; - min-height: 0; - margin: 0; - padding: 0; - background: transparent !important; - border: none; - cursor: pointer; - - &:hover, - &:active, - &:focus { - outline: none !important; - color: lighten($color-turq-160, 5%); - background: transparent !important; - box-shadow: none !important; - } - - .icon { - margin-right: $margin-xs; - } - } -} - -@include xs-to-md { - .form-container { - padding: $pad-xxl $pad-lg; - } - - .form-title { - @include barlow-condensed-medium; - - font-size: 22px; - line-height: 24px; - padding-bottom: $pad-xxl; - } - - .form-label { - flex: 1 1 100%; - padding: 0; - margin-bottom: $margin-xxl; - font-size: 14px; - line-height: 20px; - } - - .form-body { - flex: 1 1 100%; - } - - .form-footer { - margin: 0; - } -} diff --git a/src/shared/components/Settings/Tools/index.jsx b/src/shared/components/Settings/Tools/index.jsx deleted file mode 100644 index 6759da7598..0000000000 --- a/src/shared/components/Settings/Tools/index.jsx +++ /dev/null @@ -1,139 +0,0 @@ -/* eslint-disable prefer-destructuring */ -import React from 'react'; -import PT from 'prop-types'; -import { PrimaryButton } from 'topcoder-react-ui-kit'; -import Devices from './Devices'; -import Software from './Software'; -import ServiceProviders from './ServiceProviders'; -import Subscriptions from './Subscriptions'; -import ErrorWrapper from '../ErrorWrapper'; - -import styles from './styles.scss'; - -export default class Tools extends React.Component { - constructor(props) { - super(props); - this.save = this.save.bind(this); - this.deviceRef = React.createRef(); - this.softwareRef = React.createRef(); - this.serviceProviderRef = React.createRef(); - this.subscriptionRef = React.createRef(); - } - - componentWillReceiveProps(nextProps) { - const { isSaving, setIsSaving } = this.props; - if (isSaving && nextProps.userTraits) { - setIsSaving(false); - } - } - - save() { - const { isSaving, setIsSaving } = this.props; - if (isSaving) { - return; - } - const newDevice = this.deviceRef.current.state.newDevice; - const newDeviceDirty = newDevice.deviceType !== '' - || newDevice.manufacturer !== '' - || newDevice.model !== '' - || newDevice.operatingSystem !== ''; - - const newSoftware = this.softwareRef.current.state.newSoftware; - const newSoftwareDirty = newSoftware.softwareType !== '' - || newSoftware.name !== ''; - - const newServiceProvider = this.serviceProviderRef.current.state.newServiceProvider; - const newServiceProviderDirty = newServiceProvider.serviceProviderType !== '' - || newServiceProvider.name !== ''; - - const newSubscription = this.subscriptionRef.current.state.newSubscription; - const newSubscriptionDirty = newSubscription.name !== ''; - - let valid = true; - let dirty; - - if (newDeviceDirty) { - valid = valid && !this.deviceRef.current.onCheckFormValue(newDevice); - dirty = true; - } - - if (newSoftwareDirty) { - valid = valid && !this.softwareRef.current.onCheckFormValue(newSoftware); - dirty = true; - } - - if (newServiceProviderDirty) { - valid = valid && !this.serviceProviderRef.current.onCheckFormValue(newServiceProvider); - dirty = true; - } - - if (newSubscriptionDirty) { - valid = valid && !this.subscriptionRef.current.onCheckFormValue(newSubscription); - dirty = true; - } - if (newDeviceDirty) this.deviceRef.current.onHandleAddDevice(); - if (newSoftwareDirty) this.softwareRef.current.onHandleAddSoftware(); - if (newServiceProviderDirty) { - this.serviceProviderRef.current.onHandleAddServiceProvider(); - } - if (newSubscriptionDirty) { - this.subscriptionRef.current.onHandleAddSubscription(); - } - - if (dirty && valid) setIsSaving(true); - } - - render() { - const { isSaving } = this.props; - - const saveBtn = ( - - Save Changes - - ); - - return ( - -
    -
    -

    Devices And Softwares

    -
    - - - - -
    -
    {saveBtn}
    -
    - ); - } -} - -Tools.defaultProps = { - isSaving: false, - setIsSaving: () => {}, -}; - -Tools.propTypes = { - userTraits: PT.array.isRequired, - isSaving: PT.bool, - setIsSaving: PT.func, -}; diff --git a/src/shared/components/Settings/Tools/styles.scss b/src/shared/components/Settings/Tools/styles.scss deleted file mode 100644 index 06d789534e..0000000000 --- a/src/shared/components/Settings/Tools/styles.scss +++ /dev/null @@ -1,67 +0,0 @@ -@import '~styles/mixins'; - -.tools-container { - background-color: $listing-filter-bg; - padding: 32px; - border-radius: 8px; - margin: 32px 0 32px; - - @include xs-to-md { - margin-top: 24px; - } - - .header { - h3 { - @include barlow-bold; - - font-size: 20px; - line-height: 22px; - color: $tco-black; - text-transform: uppercase; - - @include xs-to-md { - @include barlow-condensed-semi-bold; - - font-size: 27px; - line-height: 28px; - } - } - } - - @include xs-to-md { - padding: 24px 16px; - } -} - -.footer { - display: flex; - flex-direction: row-reverse; - - .save-changes-btn { - @include roboto-bold; - - font-weight: 700; - font-size: 16px; - line-height: 24px; - border-radius: 50px !important; - background: #137d60 !important; - color: #fff !important; - text-transform: uppercase; - padding: 11px 23px; - margin: 0; - - &.disabled { - opacity: 0.5; - } - } - - @include xs-to-md { - padding: $pad-xxxxl 0 $pad-sm; - border-top: 2px solid $color-black-10; - - .save-changes-btn { - font-size: 14px; - line-height: 20px; - } - } -} diff --git a/src/shared/components/Settings/TopcoderAndYou/Community/Item/index.jsx b/src/shared/components/Settings/TopcoderAndYou/Community/Item/index.jsx deleted file mode 100644 index 8e9f44d0b1..0000000000 --- a/src/shared/components/Settings/TopcoderAndYou/Community/Item/index.jsx +++ /dev/null @@ -1,90 +0,0 @@ -/** - * Render item of community - */ -import React from 'react'; -import PT from 'prop-types'; - -import './styles.scss'; - -export default function Item({ - checked, - id, - onToggle, - title, - description, - link, - value, - icon, -}) { - return ( -
    -
    - community icon -
    -
    - { title } -
    -
    - { description } -
    - LEARN MORE -
    -
    -
    - {id} -
    - { title } -
    -
    - - -
    -
    -
    - { description } -
    - LEARN MORE -
    -
    -
    - - -
    -
    - ); -} - -Item.propTypes = { - id: PT.string.isRequired, - icon: PT.string.isRequired, - value: PT.string.isRequired, - checked: PT.bool.isRequired, - title: PT.string.isRequired, - description: PT.string.isRequired, - link: PT.string.isRequired, - onToggle: PT.func.isRequired, -}; diff --git a/src/shared/components/Settings/TopcoderAndYou/Community/Item/styles.scss b/src/shared/components/Settings/TopcoderAndYou/Community/Item/styles.scss deleted file mode 100644 index d589c579fb..0000000000 --- a/src/shared/components/Settings/TopcoderAndYou/Community/Item/styles.scss +++ /dev/null @@ -1,177 +0,0 @@ -@import "../../../style"; -@import "~styles/mixins"; - -@mixin switch-transition { - transition: all 0.15s ease-in-out; -} - -$switch-active-color: $listing-checkbox-green; -$switch-inactive-color: #aaa; -$switch-width: 37px; -$switch-height: 20px; -$switch-border-radius: 12px; - -.item-container { - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; - border-top: 0; - padding: 16px; - background: $tc-white; - border: 1px solid $listing-light-gray; - border-radius: 8px; -} - -.item-container:not(:last-child) { - margin-bottom: 16px; -} - -.body { - display: flex; - flex-direction: row; - flex: 1; - align-items: center; -} - -.icon { - margin-right: 16px; - max-height: 80px; - min-height: 80px; - max-width: 80px; - min-width: 80px; - margin-bottom: auto; - - @include upto-sm { - display: none; - } -} - -.learn-more-btn { - @include roboto-bold; - - font-weight: 700; - text-align: center; - margin: 0; - font-size: 12px; - line-height: 24px; - letter-spacing: 0.008em; - text-transform: uppercase; - color: #137d60 !important; - width: 107px; - background: $tc-white; - border: 1.5px solid #137d60; - border-radius: 24px; - cursor: pointer; -} - -.info { - display: flex; - flex-direction: column; - flex: 1; - - @include upto-sm { - display: none; - } -} - -.info-first-line { - @include roboto-regular; - - font-size: 16px; - line-height: 20px; - font-weight: 700; - margin-bottom: 12px; - letter-spacing: 0.5px; - text-transform: capitalize; -} - -.info-second-line { - @include roboto-regular; - - font-size: 16px; - line-height: 24px; - text-align: justify; - padding-right: 74px; - margin-bottom: 12px; - color: #767676; -} - -.mobile-view { - display: none; - - @include upto-sm { - display: flex; - flex-direction: column; - justify-content: space-between; - - .mobile-first-line { - @include roboto-regular; - - display: flex; - flex-direction: row; - justify-content: left; - width: 100%; - font-weight: 700; - font-size: 16px; - line-height: 20px; - letter-spacing: 0.5px; - text-transform: capitalize; - - .mobile-icon { - width: 80px; - height: 80px; - - @media screen and (max-width: 320px) { - width: 42px; - height: 42px; - } - } - - .mobile-title { - @include roboto-medium; - - font-size: 15px; - color: #262628; - width: 68%; - margin-left: 16px; - } - } - - .mobile-second-line { - @include roboto-regular; - - line-height: 20px; - text-align: justify; - font-weight: 400; - margin-top: 10px; - margin-bottom: 12px; - font-size: 14px; - color: #767676; - width: 100%; - } - } -} - -.onoffswitch-no-padding-right { - margin-right: 10px; - margin-left: 30px; - margin-top: 10px; - - @include switch-transition; - - align-self: flex-start; - background-color: $switch-inactive-color; - border-radius: $switch-border-radius; - box-sizing: border-box; - height: $switch-height; - width: $switch-width; - position: relative; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - - @include upto-sm { - display: none; - } -} diff --git a/src/shared/components/Settings/TopcoderAndYou/Community/data.jsx b/src/shared/components/Settings/TopcoderAndYou/Community/data.jsx deleted file mode 100644 index 0cd19c4cd6..0000000000 --- a/src/shared/components/Settings/TopcoderAndYou/Community/data.jsx +++ /dev/null @@ -1,32 +0,0 @@ -import ethereum from 'assets/images/profile/community/ico-ethereum.png'; -import ibmCloud from 'assets/images/profile/community/ico-ibmcloud.png'; -import veteran from 'assets/images/profile/community/ico-veteran.png'; - -const data = [ - { - id: 'blockchain', - icon: ethereum, - programID: 20000010, - name: 'Topcoder Blockchain Community', - description: 'Meet like-minded peers from around the world, share tips and insights, and collaborate with customers to build cutting-edge solutions. The Topcoder Blockchain Community provides opportunities to learn from Ethereum experts and work with top companies that are embracing blockchain technology.', - link: 'https://blockchain.topcoder.com/', - }, - { - id: 'cognitive', - icon: ibmCloud, - programID: 3449, - name: 'Topcoder Cognitive Community', - description: 'By becoming a member of the Topcoder Community and registering for this specialized community, you can compete in fun cognitive challenges, access educational resources, and win money by solving real-life business problems for companies in need of cognitive expertise. ', - link: 'https://cognitive.topcoder.com/', - }, - { - id: 'veteran', - icon: veteran, - programID: 3450, - name: 'Topcoder Veterans Community', - description: 'We help military service members and veterans transition to a career in technology with the world\'s premier crowdsourcing platform.', - link: 'https://veterans.topcoder.com/', - }, -]; - -export default data; diff --git a/src/shared/components/Settings/TopcoderAndYou/Community/index.jsx b/src/shared/components/Settings/TopcoderAndYou/Community/index.jsx deleted file mode 100644 index ccdf0ca430..0000000000 --- a/src/shared/components/Settings/TopcoderAndYou/Community/index.jsx +++ /dev/null @@ -1,56 +0,0 @@ -/* eslint-disable jsx-a11y/label-has-for */ -/** - * Communities - * Topcoder And You Settings Page - */ -import _ from 'lodash'; -import React from 'react'; -import PT from 'prop-types'; -import Item from './Item'; -import data from './data'; - -import './styles.scss'; - -const Community = (props) => { - const { - communityItems, - onCommunityChange, - } = props; - - return ( -
    -
    - { - _.map(data, (item) => { - const checked = communityItems[item.id] || false; - return ( - onCommunityChange(event, item, event.target.checked)} - /> - ); - }) - } -
    -
    - ); -}; - -Community.defaultProps = { - communityItems: [], -}; - -Community.propTypes = { - communityItems: PT.arrayOf(PT.shape()), - onCommunityChange: PT.func.isRequired, -}; - -export default Community; diff --git a/src/shared/components/Settings/TopcoderAndYou/Community/styles.scss b/src/shared/components/Settings/TopcoderAndYou/Community/styles.scss deleted file mode 100644 index 8a1dc96fc2..0000000000 --- a/src/shared/components/Settings/TopcoderAndYou/Community/styles.scss +++ /dev/null @@ -1,60 +0,0 @@ -@import "~styles/mixins"; -@import "../../style.scss"; - -.hide { - display: none; -} - -.community-container { - h1 { - margin-bottom: 20px; - - @include upto-sm { - line-height: 70px; - margin-bottom: 0; - font-size: 20px; - padding: 0 20px; - } - } - - // margin-bottom: 40px; - - @include from-sm-to-lg { - margin-bottom: 0; - } - - @include upto-sm { - margin-bottom: 0; - } - - .title { - @include tc-heading-lg; - - margin-bottom: 25px; - - @include upto-sm { - font-size: 20px; - line-height: 30px; - margin: 20px; - } - } - - .sub-title { - @include roboto-light; - - color: #888894; - line-height: 35px; - font-weight: 300; - font-size: 28px; - margin-bottom: 30px; - margin-top: 10px; - - @include upto-sm { - display: none; - } - } - - .community-list { - // border-top: 1px solid $tc-gray-neutral-dark; - } -} diff --git a/src/shared/components/Settings/TopcoderAndYou/Tracks/Track/index.jsx b/src/shared/components/Settings/TopcoderAndYou/Tracks/Track/index.jsx deleted file mode 100644 index 404376aade..0000000000 --- a/src/shared/components/Settings/TopcoderAndYou/Tracks/Track/index.jsx +++ /dev/null @@ -1,67 +0,0 @@ -/** - * Render Track Component - */ -import React from 'react'; -import PT from 'prop-types'; -import ReactSVG from 'react-svg'; -import { isomorphy } from 'topcoder-react-utils'; - -import './styles.scss'; - -let assets; -if (isomorphy.isClientSide()) { - assets = require.context('assets/images/profile/tracks', false, /svg/); -} - -export default function Track({ - checked, - id, - onToggle, - title, - description, - value, -}) { - const icon = `./${id.toLowerCase()}.svg`; - return ( -
    -
    -
    - { assets && assets.keys().includes(icon) ? : '' } -
    -
    -
    - { title } -
    -
    - { description } -
    -
    -
    -
    - - -
    -
    - ); -} - -Track.propTypes = { - id: PT.string.isRequired, - value: PT.string.isRequired, - checked: PT.bool.isRequired, - title: PT.string.isRequired, - description: PT.string.isRequired, - onToggle: PT.func.isRequired, -}; diff --git a/src/shared/components/Settings/TopcoderAndYou/Tracks/Track/styles.scss b/src/shared/components/Settings/TopcoderAndYou/Tracks/Track/styles.scss deleted file mode 100644 index f4c9302ecc..0000000000 --- a/src/shared/components/Settings/TopcoderAndYou/Tracks/Track/styles.scss +++ /dev/null @@ -1,90 +0,0 @@ -@import "~styles/mixins"; - -@mixin switch-transition { - transition: all 0.15s ease-in-out; -} - -$switch-active-color: $listing-checkbox-green; -$switch-inactive-color: #aaa; -$switch-width: 37px; -$switch-height: 20px; -$switch-border-radius: 12px; - -.track-container { - display: flex; - flex-direction: row; - align-items: center; - padding: 16px; - border: 1px solid #e9e9e9; - border-radius: 8px; - justify-content: space-between; - background-color: $tc-white; -} - -.track-container:not(:last-child) { - margin-bottom: 16px; -} - -.body { - display: flex; - flex-direction: row; -} - -.icon { - margin-right: 16px; - max-height: 48px; - min-height: 48px; - max-width: 48px; - min-width: 48px; - margin-bottom: auto; -} - -.info { - display: flex; - flex-direction: column; -} - -.info-first-line { - @include roboto-medium; - - font-size: 16px; - line-height: 20px; - font-weight: 700; - letter-spacing: 0.5px; - margin-bottom: 4px; - text-transform: capitalize; -} - -.info-second-line { - @include roboto-medium; - - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: $listing-placeholder-gray; -} - -.onoffswitch-no-padding-right { - margin-right: 10px; - margin-left: 30px; - margin-top: 10px; - - @include switch-transition; - - align-self: flex-start; - background-color: $switch-inactive-color; - border-radius: $switch-border-radius; - box-sizing: border-box; - height: $switch-height; - width: $switch-width; - position: relative; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - - @media screen and (max-width: 320px) { - margin-top: 28px; - margin-right: 0; - margin-left: 0; - } -} diff --git a/src/shared/components/Settings/TopcoderAndYou/Tracks/index.jsx b/src/shared/components/Settings/TopcoderAndYou/Tracks/index.jsx deleted file mode 100644 index e38fb6004e..0000000000 --- a/src/shared/components/Settings/TopcoderAndYou/Tracks/index.jsx +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Tracks - * Topcoder & You Settings Page - */ - -import _ from 'lodash'; -import React from 'react'; -import PT from 'prop-types'; -import tracks from './tracks'; -import Track from './Track'; - -import '../styles.scss'; - -const Tracks = (props) => { - const { - newProfileInfo, - onChange, - } = props; - - return ( -
    -
    - { - _.map(tracks, (track) => { - const result = newProfileInfo.tracks.filter(item => ( - item.toUpperCase() === track.id.toUpperCase() - )); - const checked = result.length !== 0; - return ( - onChange(track.id, event.target.checked)} - /> - ); - }) - } -
    -
    - ); -}; - -Tracks.defaultProps = { - newProfileInfo: {}, -}; - -Tracks.propTypes = { - newProfileInfo: PT.shape(), - onChange: PT.func.isRequired, -}; - -export default Tracks; diff --git a/src/shared/components/Settings/TopcoderAndYou/Tracks/tracks.jsx b/src/shared/components/Settings/TopcoderAndYou/Tracks/tracks.jsx deleted file mode 100644 index eb9ab4e430..0000000000 --- a/src/shared/components/Settings/TopcoderAndYou/Tracks/tracks.jsx +++ /dev/null @@ -1,20 +0,0 @@ - -const tracks = { - DESIGN: { - id: 'design', - name: 'Design', - description: 'Website, mobile, and product design; UI and UX', - }, - DEVELOP: { - id: 'develop', - name: 'Development', - description: 'Software architecture, component assembly, application development, and bug hunting', - }, - DATA_SCIENCE: { - id: 'data_science', - name: 'Data Science', - description: 'Algorithms and data structures, statistical analysis', - }, -}; - -export default tracks; diff --git a/src/shared/components/Settings/TopcoderAndYou/index.jsx b/src/shared/components/Settings/TopcoderAndYou/index.jsx deleted file mode 100644 index fd47ed657f..0000000000 --- a/src/shared/components/Settings/TopcoderAndYou/index.jsx +++ /dev/null @@ -1,489 +0,0 @@ -import _ from 'lodash'; -import React from 'react'; -import PT from 'prop-types'; -import moment from 'moment'; - -import ConsentComponent from 'components/Settings/ConsentComponent'; - -import fetch from 'isomorphic-fetch'; -import { config } from 'topcoder-react-utils'; -import { PrimaryButton } from 'topcoder-react-ui-kit'; - -import SettingsBanner from '../SettingsBanner'; -import Community from './Community'; - -import style from './styles.scss'; - -import { TOPCODER_AND_YOU } from '../constants'; -import Tracks from './Tracks'; - -class TopcoderAndYou extends ConsentComponent { - constructor(props) { - super(props); - - this.onHandleSaveTopcoderAndYou = this.onHandleSaveTopcoderAndYou.bind(this); - this.onSaveTopcoderAndYou = this.onSaveTopcoderAndYou.bind(this); - this.onChange = this.onChange.bind(this); - this.processBasicInfo = this.processBasicInfo.bind(this); - - this.loadPersonalizationTrait = this.loadPersonalizationTrait.bind(this); - - this.loadCommunityTrait = this.loadCommunityTrait.bind(this); - this.loadPersonalizationTrait = this.loadPersonalizationTrait.bind(this); - this.onCommunityChange = this.onCommunityChange.bind(this); - - const { userTraits } = props; - this.state = { - inputChanged: false, - formInvalid: false, - basicInfoTrait: this.loadBasicInfoTraits(userTraits), - profile: {}, - isSubmit: false, - isMobileView: false, - screenSM: 767, - isEdit: false, - indexNo: null, - showConfirmation: false, - personalizationTrait: this.loadPersonalizationTrait(userTraits), - newProfileInfo: { - firstName: null, - lastName: null, - tracks: [], - status: null, - addresses: [], - description: '', - email: null, - homeCountryCode: null, - competitionCountryCode: null, - photoURL: null, - }, - newBasicInfo: { - gender: null, - shortBio: '', - tshirtSize: null, - country: null, - primaryInterestInTopcoder: null, - currentLocation: null, - birthDate: null, - }, - communityTrait: this.loadCommunityTrait(userTraits), - isAdd: false, - }; - } - - componentDidMount() { - const { basicInfoTrait } = this.state; - const basicInfo = basicInfoTrait.traits ? basicInfoTrait.traits.data[0] : {}; - this.processBasicInfo(basicInfo, this.props.profile); - this.setState({ profile: this.props.profile }); - - const { userTraits } = this.props; - const trait = userTraits.filter(t => t.traitId === 'communities'); - this.setState({ - isAdd: trait.length === 0, - }); - this.updatePredicate(); - window.addEventListener('resize', this.updatePredicate); - } - - componentWillReceiveProps(nextProps) { - const basicInfoTrait = this.loadBasicInfoTraits(nextProps.userTraits); - - const basicInfo = basicInfoTrait.traits ? basicInfoTrait.traits.data[0] : {}; - const previousBasicInfoTrait = this.loadBasicInfoTraits(this.props.userTraits); - - - const { userTraits } = nextProps; - const trait = userTraits.filter(t => t.traitId === 'communities'); - this.setState({ - isAdd: trait.length === 0, - }); - const communityTrait = this.loadCommunityTrait(nextProps.userTraits); - const personalizationTrait = this.loadPersonalizationTrait(nextProps.userTraits); - this.setState({ communityTrait, personalizationTrait }); - - 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, newProfileInfo } = this.state; - if (!newBasicInfo.country) { - const code = newProfileInfo.homeCountryCode || newProfileInfo.competitionCountryCode; - const { country } = countries.find(c => c.countryCode === code) || {}; - newBasicInfo.country = country; - this.setState({ newBasicInfo }); - } - } - - this.setState({ - personalizationTrait, - formInvalid: false, - }); - } - - componentWillUnmount() { - window.removeEventListener('resize', this.updatePredicate); - } - - // onCheckFormValue(newBasicInfo, newProfileInfo) { - // let invalid = false; - - // if (!_.trim(newProfileInfo.firstName).length) { - // invalid = true; - // } - - // if (!_.trim(newProfileInfo.lastName).length) { - // invalid = true; - // } - - // if (!_.trim(newBasicInfo.country).length) { - // invalid = true; - // } - - // if (_.trim(newBasicInfo.birthDate).length > 0) { - // if (!moment().isAfter(newBasicInfo.birthDate)) { - // invalid = true; - // } - // } - - // this.setState({ formInvalid: invalid }); - // return invalid; - // } - - async onCheckUserTrait(traitId) { - const { handle, tokenV3 } = this.props; - let isExists = false; - await fetch(`${config.API.V5}/members/${handle}/traits?traitIds=${traitId}`, { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - Authorization: `Bearer ${tokenV3}`, - }, - }) - .then(result => result.json()) - .then((dataResponse) => { - if (dataResponse.length > 0) { - const trait = dataResponse[0]; - if (trait.createdAt) { - isExists = true; - } - } - }); - - return isExists; - } - - /** - * Save Personal Details - * @param {*} e event - */ - onHandleSaveTopcoderAndYou(e) { - e.preventDefault(); - const { setIsSaving } = this.props; - this.setState({ inputChange: true }); - setIsSaving(true); - this.showConsent(this.onSaveTopcoderAndYou.bind(this)); - } - - /** - * Save Basic Info - * @param answer user consent answer value - */ - async onSaveTopcoderAndYou(answer) { - const { - newBasicInfo, newProfileInfo, basicInfoTrait, personalizationTrait, - } = this.state; - const { - handle, - tokenV3, - addUserTrait, - updateUserTrait, - updateProfileV5, - } = this.props; - try { - const parsedDate = moment(newBasicInfo.birthDate).utc(); - if (parsedDate.isValid()) { - newBasicInfo.birthDate = `${parsedDate.format('YYYY-MM-DD')}T00:00:00.000Z`; - } else { - newBasicInfo.birthDate = null; - } - } catch (error) { // eslint-disable-line - newBasicInfo.birthDate = null; - } - - if (newBasicInfo.gender === '') { - newBasicInfo.gender = null; - } - - if (newBasicInfo.tshirtSize === '') { - newBasicInfo.tshirtSize = null; - } - - newProfileInfo.addresses[0] = _.omit(newProfileInfo.addresses[0], ['createdAt', 'updatedBy', 'createdBy', 'updatedAt']); - _.forEach(newProfileInfo.addresses[0], (value, key) => { - newProfileInfo.addresses[0][key] = _.trim(value); - }); - _.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) { - const newBasicInfoTrait = { ...basicInfoTrait }; - newBasicInfoTrait.traits.data = []; - newBasicInfoTrait.traits.data.push(newBasicInfo); - await updateUserTrait(handle, 'basic_info', newBasicInfoTrait.traits.data, tokenV3); - } else { - const data = []; - data.push(newBasicInfo); - await addUserTrait(handle, 'basic_info', data, tokenV3); - } - - // save personalization - if (_.isEmpty(personalizationTrait)) { - const personalizationData = { userConsent: answer }; - await addUserTrait(handle, 'personalization', [personalizationData], tokenV3); - } else { - const trait = personalizationTrait.traits.data[0]; - if (trait.userConsent !== answer) { - const personalizationData = { userConsent: answer }; - await updateUserTrait(handle, 'personalization', [personalizationData], tokenV3); - } - } - - if (newProfileInfo.homeCountryCode == null) { - delete newProfileInfo.homeCountryCode; - } - - const updateProfileData = { - ...newProfileInfo, - }; - - await updateProfileV5(updateProfileData, handle, tokenV3); - - this.props.setIsSaving(false); - } - - /** - * Change toggle button check value - * @param id community id - * @param checked check value - */ - onChange(id, checked) { - const { newProfileInfo } = this.state; - if (checked) { - newProfileInfo.tracks.push(id.toUpperCase()); - } else { - _.remove(newProfileInfo.tracks, track => ( - track.toUpperCase() === id.toUpperCase() - )); - } - this.setState({ newProfileInfo, inputChanged: true }); - } - - /** - * Show User Consent Modal - * @param e event - * @param item the community object - * @param checked the check value - */ - onCommunityChange(e, item, checked) { - e.preventDefault(); - this.showConsent(this.onUpdateCommunity.bind(this, item, checked)); - } - - /** - * Add or Update CommunityTrait - */ - onProcessCommunities = _.debounce((answer) => { - const { - handle, - tokenV3, - updateUserTrait, - addUserTrait, - } = this.props; - const { isAdd, communityTrait, personalizationTrait } = this.state; - if (isAdd) { - const newCommunities = []; - newCommunities.push(communityTrait); - addUserTrait(handle, 'communities', newCommunities, tokenV3); - } else { - const newCommunities = []; - newCommunities.push(communityTrait); - updateUserTrait(handle, 'communities', newCommunities, tokenV3); - } - // save personalization - if (_.isEmpty(personalizationTrait)) { - const personalizationData = { userConsent: answer }; - addUserTrait(handle, 'personalization', [personalizationData], tokenV3); - } else { - const trait = personalizationTrait.traits.data[0]; - if (trait.userConsent !== answer) { - const personalizationData = { userConsent: answer }; - updateUserTrait(handle, 'personalization', [personalizationData], tokenV3); - } - } - }); - - /** - * Get personalization trait - * @param userTraits the all user traits - */ - loadPersonalizationTrait = (userTraits) => { - const trait = userTraits.filter(t => t.traitId === 'personalization'); - const personalization = trait.length === 0 ? {} : trait[0]; - return _.assign({}, personalization); - } - - /** - * Change toggle button check value - * @param answer user consent answer value - */ - onUpdateCommunity(newCommunity, communityChecked, answer) { - const { communityTrait } = this.state; - communityTrait[newCommunity.id] = communityChecked; - this.setState({ - communityTrait, - }, () => this.onProcessCommunities(answer)); - } - - /** - * Get community trait - * @param userTraits the all user traits - */ - loadCommunityTrait = (userTraits) => { - const trait = userTraits.filter(t => t.traitId === 'communities'); - const communities = trait.length === 0 ? { - cognitive: false, - blockchain: false, - veteran: false, - } : trait[0].traits.data[0]; - return _.assign({}, communities); - } - - /** - * Get basic info trait - * @param userTraits the all user traits - */ - loadBasicInfoTraits = (userTraits) => { - const trait = userTraits.filter(t => t.traitId === 'basic_info'); - const basicInfo = trait.length === 0 ? {} : trait[trait.length - 1]; - return _.assign({}, basicInfo); - } - - /** - * Process basic info state - */ - 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; - } - if (_.has(value, 'userId')) { - newBasicInfo.userId = value.userId; - } else { - newBasicInfo.userId = profile.userId; - } - this.setState({ newBasicInfo }); - } - - updatePredicate() { - const { screenSM } = this.state; - this.setState({ isMobileView: window.innerWidth <= screenSM }); - } - - render() { - const { - tracks, community, - } = TOPCODER_AND_YOU; - - const { communityTrait } = this.state; - const communityItems = communityTrait; - - const { - newProfileInfo, - } = this.state; - - return ( - -
    -
    -

    YOU AND TOPCODER

    -
    - { this.shouldRenderConsent() && this.renderConsent() } - - - - - - -
    -
    - - Save Changes - -
    -
    - ); - } -} - -TopcoderAndYou.defaultProps = { - profile: {}, - isSaving: false, -}; - -TopcoderAndYou.propTypes = { - tokenV3: PT.string.isRequired, - handle: PT.string.isRequired, - profile: PT.shape(), - userTraits: PT.array.isRequired, - addUserTrait: PT.func.isRequired, - updateUserTrait: PT.func.isRequired, - updateProfileV5: PT.func.isRequired, - traitRequestCount: PT.number.isRequired, - isSaving: PT.bool, - setIsSaving: PT.func.isRequired, -}; - -export default TopcoderAndYou; diff --git a/src/shared/components/Settings/TopcoderAndYou/styles.scss b/src/shared/components/Settings/TopcoderAndYou/styles.scss deleted file mode 100644 index 597106c19d..0000000000 --- a/src/shared/components/Settings/TopcoderAndYou/styles.scss +++ /dev/null @@ -1,100 +0,0 @@ -@import "~styles/mixins"; -@import "../style.scss"; - -.footer { - display: flex; - flex-direction: row-reverse; - - .save-changes-btn { - @include roboto-bold; - - font-weight: 700; - font-size: 16px; - line-height: 24px; - border-radius: 50px !important; - background: #137d60 !important; - color: #fff !important; - text-transform: uppercase; - padding: 11px 23px; - margin: 0; - - &.disabled { - opacity: 0.5; - } - } - - @include xs-to-md { - padding: $pad-xxxxl 0 $pad-sm; - border-top: 2px solid $color-black-10; - - .save-changes-btn { - font-size: 14px; - line-height: 20px; - } - } -} - -.profile-settings-container { - background-color: $listing-filter-bg; - padding: 32px; - border-radius: 8px; - margin: 40px 0 32px; - - .header { - h3 { - @include barlow-bold; - - font-size: 20px; - line-height: 22px; - color: $tco-black; - text-transform: uppercase; - - @include xs-to-md { - @include barlow-condensed-semi-bold; - - font-size: 27px; - line-height: 28px; - } - } - } - - @include xs-to-md { - padding: 10px 16px; - } -} - -.button-save { - display: flex; - justify-content: flex-end; - margin-top: 20px; - margin-bottom: 32px; -} - -.you-and-topcoder-container { - display: flex; - flex-direction: column; - - @include upto-sm { - padding: 0; - margin-top: 24px; - } - - h1 { - @include roboto-regular; - - font-size: 28px; - line-height: 35px; - font-weight: 400; - color: $tc-black; - margin-bottom: 20px; - } -} - -.track-list { - margin-top: 32px; - - @include upto-sm { - padding: 0; - margin-top: 24px; - } -} diff --git a/src/shared/components/Settings/UserConsentModal/index.jsx b/src/shared/components/Settings/UserConsentModal/index.jsx deleted file mode 100644 index cf7139af23..0000000000 --- a/src/shared/components/Settings/UserConsentModal/index.jsx +++ /dev/null @@ -1,43 +0,0 @@ -/** - * User Consent Modal - */ -import React from 'react'; -import PT from 'prop-types'; -import { Modal, PrimaryButton, Button } from 'topcoder-react-ui-kit'; -import modal from './styles.scss'; - -export default function UserConsentModal(props) { - const { onSaveTrait } = props; - return ( - -
    -
    -
    - Topcoder would like to use your information for - to make your experience more personal. -
    -
    - You can opt out from personalization any time in the - future in at Preferences > Personalization. -
    -
    -
    - -
    -
    - onSaveTrait(e, true)}> - Allow - -
    -
    -
    -
    -
    - ); -} - -UserConsentModal.propTypes = { - onSaveTrait: PT.func.isRequired, -}; diff --git a/src/shared/components/Settings/UserConsentModal/styles.scss b/src/shared/components/Settings/UserConsentModal/styles.scss deleted file mode 100644 index 6f83407d68..0000000000 --- a/src/shared/components/Settings/UserConsentModal/styles.scss +++ /dev/null @@ -1,113 +0,0 @@ -@import "~styles/mixins"; - -.container { - @include roboto-regular; - - padding: 0; - position: fixed; - overflow: auto; - z-index: 10000; - top: 0; - right: 0; - bottom: 0; - left: 0; - box-sizing: border-box; - width: auto; - max-width: none; - transform: none; - background: transparent; - - .userconsent-confirmation-container { - background: transparent; - opacity: 1; - position: relative; - padding: 30px; - width: 100%; - height: 100%; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - border-radius: 0; - color: #444; - font-size: 15px; - line-height: 1.5em; - margin: 0 auto; - max-width: 100%; - } -} - -.userconsent-confirmation { - display: flex; - flex-flow: column wrap; - justify-content: space-around; - align-items: center; - background-color: $tc-white; - opacity: 1; - border-radius: 4px; - padding: 40px 30px; - width: 430px; - height: 265px; - box-shadow: 0 0 14px 1px rgba(38, 38, 40, 0.15); -} - -.userconsent-confirmation-title { - @include roboto-bold; - - line-height: 25px; - color: $tc-gray-80; - text-align: center; - margin-bottom: 15px; -} - -.userconsent-confirmation-message { - @include roboto-regular; - - line-height: 25px; - color: $tc-gray-60; - text-align: center; - margin-bottom: 40px; -} - -.userconsent-confirmation-buttons { - display: flex; - flex-flow: row wrap; - - .userconsent-confirmation-button-no { - button { - height: 30px; - width: 100px; - min-height: 30px; - border: 1px solid #c3c3c8; - padding: 0 0; - margin: 0; - - @include roboto-medium; - - font-size: 13px; - line-height: 0; - color: #47474f; - } - } - - .userconsent-confirmation-button-yes { - margin-left: 10px; - - button { - @include roboto-medium; - - font-size: 13px; - line-height: 0; - height: 30px; - width: 80px; - min-height: 30px; - padding: 0 0; - margin: 0; - - &:hover { - color: $tc-white; - background-color: $tc-dark-blue; - } - } - } -} diff --git a/src/shared/components/Settings/constants.js b/src/shared/components/Settings/constants.js deleted file mode 100644 index c46fe2fd9a..0000000000 --- a/src/shared/components/Settings/constants.js +++ /dev/null @@ -1,62 +0,0 @@ - -import { TABS } from '../../actions/page/settings'; - -export const SCREEN_SIZE = { - SM: 767, -}; - -export const SETTINGS_TABS = [ - { title: 'Profile', link: TABS.PROFILE }, - { title: 'Skills & Experience', link: TABS.SKILLS }, - { title: 'Topcoder & You', link: TABS.TRACKS }, - { title: 'Tools', link: TABS.TOOLS }, - { title: 'Account', link: TABS.ACCOUNT }, - { title: 'Preferences', link: TABS.PREFERENCES }, - { title: 'Payment', link: TABS.PAYMENT }, -]; - -export const PROFILE_SETTINGS = { - personalDetails: { - title: 'Personal Details', - description: - 'By keeping this information up to date we may contact you about relevant freelance opportunites at Topcoder, or even surprise you with a cool T-shirt. Sharing your contact details will never result in robocalls about health insurance plans or junk mail.', - }, - aboutYou: { - title: 'About You', - description: - 'Enter a short bio to help potential customers know you.', - }, - learningAndEducations: { - title: 'Learning & Education', - description: 'Enter information about your schooling and degrees.', - }, - hobbies: { - title: 'Hobbies', - description: 'Tell us about what you love to do in your free time.', - }, -}; - -export const TOPCODER_AND_YOU = { - tracks: { - title: 'Tracks', - description: 'Topcoder\'s three categories of challenges... please pick at least one based on your skills and interests.', - }, - community: { - title: 'Your Communities', - }, -}; - -export const INTERESTS_AT_TOPCODER = [ - 'Top Paying Work', - 'Skill Building / Upskilling', - 'Work with Top Companies', - 'Compete (Code & Design Challenges)', - 'Full Time Freelance Work', - 'Have Fun', - 'Gain Technical Experience', - 'Prepare for an interview', - 'Competitive Programming', - 'Earn Extra Money', - 'Connect With Smart People', - 'Explore / Not Sure', -]; diff --git a/src/shared/components/Settings/index.jsx b/src/shared/components/Settings/index.jsx deleted file mode 100644 index bc16cdb271..0000000000 --- a/src/shared/components/Settings/index.jsx +++ /dev/null @@ -1,154 +0,0 @@ -/** - * Settings page component. - */ -import React, { useState } from 'react'; -import PT from 'prop-types'; -import MetaTags from 'components/MetaTags'; - -import { TABS } from 'actions/page/settings'; - -import _ from 'lodash'; -import Header from './Header'; -import ExperienceAndSkills from './ExperienceAndSkills'; -import TopcoderAndYou from './TopcoderAndYou'; -import Tools from './Tools'; - -import './style.scss'; -import Preferences from './Preferences'; -import Payment from './Payment'; -import TabSelector from './TabSelector'; -import { SETTINGS_TABS } from './constants'; - -import ProfileSettings from './ProfileSettings'; - -export default function Settings(props) { - const newProps = { ...props }; - if (newProps.settingsTab === newProps.match.params.settingsTab) { - newProps.settingsTab = newProps.settingsTab; - } else { - newProps.settingsTab = newProps.match.params.settingsTab; - } - - const selectTab = (tab) => { - newProps.selectTab(tab); - newProps.history.push(`/settings/${tab}`); - }; - - const currentTab = _.find(SETTINGS_TABS, { link: newProps.settingsTab }); - const title = currentTab ? currentTab.title : 'Settings'; - - const profileRef = React.useRef(); - const tracksRef = React.useRef(); - const experienceAndSkillsRef = React.useRef(); - const toolsRef = React.useRef(); - const accountRef = React.useRef(); - const preferencesRef = React.useRef(); - - const [isSaving, setIsSaving] = useState(false); - - return ( -
    {}}> - -
    -
    { - if (newProps.settingsTab === TABS.TRACKS) { - tracksRef.current.onSaveTopcoderAndYou(); - } else if (newProps.settingsTab === TABS.PROFILE) { - profileRef.current.onSaveProfile(); - } else if (newProps.settingsTab === TABS.SKILLS) { - experienceAndSkillsRef.current.save(); - } else if (newProps.settingsTab === TABS.TOOLS) { - toolsRef.current.save(); - } else if (newProps.settingsTab === TABS.ACCOUNT) { - accountRef.current.save(); - } else if (newProps.settingsTab === TABS.PREFERENCES) { - preferencesRef.current.save(); - } - }} - isSaving={isSaving} - /> - - { - newProps.settingsTab === TABS.PROFILE - && ( - - ) - } - { - newProps.settingsTab === TABS.SKILLS - && ( - - ) - } - { - newProps.settingsTab === TABS.TRACKS - && ( - - ) - } - { - newProps.settingsTab === TABS.TOOLS - && ( - - ) - } - { - newProps.settingsTab === TABS.PREFERENCES - && ( - - ) - } - { - newProps.settingsTab === TABS.PAYMENT - && ( - - ) - } -
    -
    - ); -} - -Settings.defaultProps = { - handle: '', -}; - -Settings.propTypes = { - settingsTab: PT.string.isRequired, - profileState: PT.shape().isRequired, - settingsPageState: PT.shape().isRequired, - history: PT.shape().isRequired, - selectTab: PT.func.isRequired, - handle: PT.string, -}; diff --git a/src/shared/components/Settings/style.scss b/src/shared/components/Settings/style.scss deleted file mode 100644 index 31b057118b..0000000000 --- a/src/shared/components/Settings/style.scss +++ /dev/null @@ -1,470 +0,0 @@ -/* stylelint-disable no-descending-specificity */ -@import "~styles/mixins"; - -$screen-sm: 768px !default; -$screen-md: 1024px !default; -$screen-lg: 1280px !default; - -$checkbox-size: $base-unit * 4; -$checkbox-bg-empty: $tc-gray-neutral-light; -$checkbox-bg-selected: $tc-dark-blue; - -@mixin upto-sm { - @media (max-width: #{$screen-sm - 1px}) { - @content; - } -} - -@mixin from-sm-to-lg { - @media (min-width: #{$screen-sm}) and (max-width: #{$screen-md}) { - @content; - } -} - -@mixin md-to-lg { - @media (min-width: #{$screen-sm + 1px}) and (max-width: #{$screen-md}) { - @content; - } -} - -@mixin xs-to-sm { - @media (max-width: #{$screen-sm}) { - @content; - } -} - -@mixin screen1025-to-screen1280 { - @media (min-width: #{$screen-md + 1px}) and (max-width: #{$screen-lg}) { - @content; - } -} - -.container { - background: $tc-white; - width: 100%; - max-width: 1440px; - margin: 0 auto; - padding: $pad-xxxxl $pad-xxxxl $pad-xxxl; - - @include xs-to-md { - padding: $pad-lg; - } -} - -.page { - background: $tc-white; -} - -@mixin form-container-default { - display: flex; - flex-direction: column; - - .row { - width: 100%; - display: flex; - flex-direction: row; - margin-bottom: 20px; - align-content: space-between; - justify-content: flex-start; - - .field { - @include upto-sm { - display: block; - padding-bottom: 10px; - } - - label { - @include roboto-bold; - - font-size: 15px; - line-height: 20px; - font-weight: 700; - color: $tc-gray-80; - } - - .passwordCheckbox { - @include roboto-medium; - - font-size: 10px; - line-height: 15px; - font-weight: 500; - color: $tc-gray-80; - margin-bottom: 5px; - } - - &.col-1 { - max-width: 152px; - min-width: 152px; - margin-right: 14px; - align-self: left; - margin-bottom: auto; - margin-top: auto; - padding-top: 10px; - white-space: nowrap; - } - - &.col-2 { - align-self: right; - width: 80%; - margin-bottom: auto; - margin-top: auto; - display: flex; - flex-direction: column; - } - - &.col-percent50 { - align-self: right; - width: 50%; - margin-bottom: auto; - margin-top: auto; - display: flex; - flex-direction: column; - } - - &.col-percent35 { - align-self: right; - width: 35%; - margin-bottom: auto; - margin-top: auto; - display: flex; - flex-direction: column; - } - - .date-input { - display: flex; - align-items: center; - } - - &.col-1-no-padding { - max-width: 152px; - min-width: 152px; - margin-right: 14px; - align-self: flex-start; - margin-bottom: auto; - margin-top: auto; - padding-top: 0; - white-space: nowrap; - } - - &.col-long-text { - max-width: 220px; - min-width: 220px; - margin-right: 14px; - align-self: flex-start; - margin-bottom: auto; - margin-top: auto; - padding-top: 0; - white-space: nowrap; - } - - &.col-1-long-text { - max-width: 220px; - min-width: 220px; - margin-right: 14px; - align-self: left; - margin-bottom: auto; - margin-top: auto; - padding-top: 10px; - white-space: nowrap; - } - } - - &.hide { - display: none; - } - } -} - -:global { - .profile-settings { - .Select-input, - .Select-placeholder, - .Select-value-label, - .Select-menu-outer { - @include roboto-sans-regular; - - padding-top: 0; - } - - input { - &::placeholder { - opacity: 0.75; - } - } - } - - .settings-section { - display: flex; - box-sizing: border-box; - flex-direction: column; - align-items: center; - width: 100%; - margin: 20px auto; - - @media only screen and (min-width: 768px) { - flex-direction: row; - margin: 30px auto 0; - padding-bottom: 30px; - - .section-info { - h2 { - font-size: 18px; - } - - .description { - margin-top: 10px; - } - } - - .section-fields { - width: 100%; - } - - &.skills { - input { - width: 100%; - } - } - } - - border-bottom: 1px solid; - border-color: $tc-gray-20; - - .section-info { - display: flex; - flex-direction: column; - justify-content: flex-start; - align-self: flex-start; - - @media only screen and (min-width: 768px) { - width: 270px; - margin-right: 30px; - } - - h2 { - @include roboto-medium; - - font-size: 16px; - text-transform: uppercase; - } - - .description { - font-size: 13px; - line-height: 20px; - color: $tc-gray-40; - - @include merriweather-sans-regular; - - font-style: italic; - margin-top: 5px; - } - } - - .section-fields { - display: flex; - flex-direction: column; - - @media only screen and (min-width: 768px) { - border-left: 6px solid #f6f6f6; - padding-left: 60px; - max-width: 816px; - } - - .form-field { - background: white; - color: black; - max-width: 360px; - - &:disabled { - color: #b7b7b7; - } - - &.grey { - background-color: #fcfcfc; - } - } - - .form-label { - @include roboto-medium; - - color: $tc-gray-90; - font-size: 12px; - margin-bottom: 5px; - margin-top: 5px; - text-transform: uppercase; - max-width: 100%; - - .mandatory { - color: $tc-dark-blue-70; - float: right; - text-transform: none; - } - - .grey { - color: $tc-gray-40; - } - } - - .form-input-error { - @include roboto-regular; - - background-color: $tc-red-10; - border: 1px solid $tc-red-30; - color: $tc-red; - line-height: 20px; - margin-bottom: 10px; - padding: 10px; - text-align: left; - font-size: 13px; - } - } - } - - .save-section { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - } - - // Switch location - $switch-width: 37px; - $switch-height: 20px; - $switch-border-radius: 10px; - $switch-handle-offset: 3px; - $switch-handle-size: $switch-height - (2 * $switch-handle-offset); - $switch-active-color: $listing-checkbox-green; - $switch-inactive-color: $tc-gray-40; - - @mixin switch-transition { - transition: all 0.15s ease-in-out; - } - - .onoffswitch { - @include switch-transition; - - align-self: center; - margin-right: 10px; - margin-left: 22px; - background-color: $switch-inactive-color; - border-radius: $switch-border-radius; - box-sizing: border-box; - height: $switch-height; - width: $switch-width; - position: relative; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - - @include upto-sm { - display: none; - } - } - - .onoffswitch-mobile { - display: none; - - @include upto-sm { - @include switch-transition; - - display: block; - align-self: flex-start; - margin-right: 10px; - margin-left: 15px; - margin-top: 10px; - background-color: $switch-inactive-color; - border-radius: $switch-height; - box-sizing: border-box; - height: $switch-height; - width: $switch-width; - position: relative; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - } - } - - .onoffswitch-checkbox { - display: none; - } - - .onoffswitch-label { - border-radius: $switch-height; - cursor: pointer; - display: block; - width: $switch-width; - overflow: hidden; - } - - .onoffswitch-inner { - @include switch-transition; - - display: block; - width: 200%; - margin-left: -100%; - } - - // Pseudo-elements that slide to create background of the switch; TODO: Remove those - .onoffswitch-inner::before, - .onoffswitch-inner::after { - box-sizing: border-box; - color: $tc-white; - display: block; - float: left; - height: $switch-height; - width: 50%; - font-size: 15px; - font-weight: bold; - line-height: $switch-height; - padding: 0; - } - - // SWITCH HANDLE - .onoffswitch-switch { - @include switch-transition; - - background: $tc-white; - background-color: $tc-white; - border: none; - border-radius: $switch-height; - bottom: 0; - color: $tc-white; - display: block; - height: $switch-handle-size; - width: $switch-handle-size; - margin: $switch-handle-offset; - position: absolute; - top: 0; - } - - .onoffswitch-checkbox + .onoffswitch-label { - @include switch-transition; - - background-color: $switch-inactive-color; - } - - .onoffswitch-checkbox:checked + .onoffswitch-label { - background-color: $switch-active-color; - - & .onoffswitch-switch { - right: 0; - } - } - - // Switch is on - .onoffswitch-inner::before { - background-color: transparent; //$switch-active-color; - color: transparent; // $switch-active-color; - content: ""; - padding-left: 10px; - } - - // switch is off - .onoffswitch-inner::after { - background-color: transparent; // $switch-inactive-color; - color: transparent; // $switch-inactive-color; - content: ""; - padding-right: 10px; - text-align: right; - } -} diff --git a/src/shared/components/tc-communities/NewsletterSignup/index.jsx b/src/shared/components/tc-communities/NewsletterSignup/index.jsx deleted file mode 100644 index fea707eb36..0000000000 --- a/src/shared/components/tc-communities/NewsletterSignup/index.jsx +++ /dev/null @@ -1,115 +0,0 @@ -/** - * NewsletterSignup component - */ - -/* global window */ - -import fetch from 'isomorphic-fetch'; -import React from 'react'; -import PT from 'prop-types'; -import { PrimaryButton } from 'topcoder-react-ui-kit'; -import { themr } from 'react-css-super-themr'; -import { errors } from 'topcoder-react-lib'; -import qs from 'qs'; - -import { config } from 'topcoder-react-utils'; - -import defaultStyle from './style.scss'; - -const { fireErrorMessage } = errors; - -class NewsletterSignup extends React.Component { - subscribe() { - const { apikey, url } = this.props; - if (!apikey || !url) { - fireErrorMessage('NewsletterSignup logic is not implemented yet!', ''); - } else { - const formData = qs.stringify({ - [apikey]: '', - EMAIL: this.email.value, - }); - fetch(`/community-app-assets/api/proxy-post?url=${encodeURIComponent(url)}`, { - body: formData, - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - Authorization: `ApiKey ${config.SERVER_API_KEY}`, - }, - method: 'POST', - }).then(res => res.text()) - .then((res) => { window.document.write(res); }); - } - } - - render() { - const { - imageSrc, - title, - text, - buttonText, - emailPlaceholder, - theme, - } = this.props; - return ( -
    -
    -

    - {title} -

    -

    - {text} -

    -
    - { this.email = node; }} - onKeyPress={(e) => { - if (e.key === 'Enter') this.subscribe(); - }} - type="email" - /> - this.subscribe()} - size="md" - theme={{ button: theme.formButton }} - > - {buttonText} - -
    -
    -
    - ); - } -} - -NewsletterSignup.defaultProps = { - apikey: '', - emailPlaceholder: 'Email address', - buttonText: 'Sign Up', - theme: {}, - url: '', -}; - -NewsletterSignup.propTypes = { - apikey: PT.string, - imageSrc: PT.string.isRequired, - title: PT.string.isRequired, - text: PT.string.isRequired, - emailPlaceholder: PT.string, - buttonText: PT.string, - theme: PT.shape({ - container: PT.string, - content: PT.string, - title: PT.string, - text: PT.string, - form: PT.string, - formEmail: PT.string, - formButton: PT.string, - }), - url: PT.string, -}; - -export default themr('tcCommunities-NewsletterSignup', defaultStyle)(NewsletterSignup); diff --git a/src/shared/components/tc-communities/NewsletterSignup/style.scss b/src/shared/components/tc-communities/NewsletterSignup/style.scss deleted file mode 100644 index c39bca6fb0..0000000000 --- a/src/shared/components/tc-communities/NewsletterSignup/style.scss +++ /dev/null @@ -1,108 +0,0 @@ -@import '~styles/mixins'; - -.container { - display: flex; - background: center no-repeat; - background-size: cover; - height: 300px; - position: relative; - align-items: center; - text-align: center; - - &::before { - background-color: rgba(#394146, 0.7); - bottom: 0; - content: ''; - display: block; - left: 0; - position: absolute; - top: 0; - width: 100%; - } - - @include xs-to-sm { - height: auto; - } -} - -.content { - margin: 0 auto; - position: relative; - width: 960px; - - @include md { - width: 720px; - } - - @include xs-to-sm { - padding: 20px 15px 37px; - width: auto; - } -} - -.title { - color: #fff; - font: 600 32px/134.38% 'Open Sans', sans-serif; - - @include xs-to-sm { - font-size: 24px; - } -} - -.text { - color: #fff; - font: 18px/133.33% 'Open Sans', sans-serif; - margin-top: 20px; - - @include xs-to-sm { - font-size: 15px; - margin-top: 10px; - } -} - -.form { - display: inline-block; - border-radius: 25px; - margin-top: 40px; - overflow: hidden; - - @include xs-to-sm { - display: flex; - margin-top: 20px; - width: 100%; - } -} - -input:not([type="checkbox"]).formEmail { - background-color: #fff; - border: 0; - color: #394146; - font: 14px/50px 'Open Sans', sans-serif; - height: 50px; - margin: 0; - outline: none; - padding: 0 25px; - width: 326px; - - @include placeholder { - color: #a3a3ae; - font: 14px/50px 'Open Sans', sans-serif; - text-transform: none; - } - - &:hover, - &:active, - &:focus { - border: 0; - } - - @include xs-to-sm { - flex-grow: 1; - width: 100%; - } -} - -.formButton { - margin: 0 !important; - text-transform: uppercase; -} diff --git a/src/shared/components/tc-communities/communities/community-2/Learn/index.jsx b/src/shared/components/tc-communities/communities/community-2/Learn/index.jsx index 05e7100639..fbedfdf65c 100644 --- a/src/shared/components/tc-communities/communities/community-2/Learn/index.jsx +++ b/src/shared/components/tc-communities/communities/community-2/Learn/index.jsx @@ -12,7 +12,6 @@ import Section from 'components/tc-communities/Section'; import Accordion from 'components/tc-communities/Accordion/Accordion'; import AccordionItem from 'components/tc-communities/Accordion/AccordionItem'; import Banner from 'components/tc-communities/Banner'; -import NewsletterSignup from 'components/tc-communities/NewsletterSignup'; import ArticleCard from 'components/tc-communities/ArticleCard'; import LinksCard from 'components/tc-communities/LinksCard'; import Text from 'components/tc-communities/Text'; @@ -161,11 +160,6 @@ export default function Learn() { /> - ); } diff --git a/src/shared/components/tc-communities/communities/demo-expert/Home/index.jsx b/src/shared/components/tc-communities/communities/demo-expert/Home/index.jsx index 7d50832ecf..0e3aafda39 100644 --- a/src/shared/components/tc-communities/communities/demo-expert/Home/index.jsx +++ b/src/shared/components/tc-communities/communities/demo-expert/Home/index.jsx @@ -11,7 +11,6 @@ import Section from 'components/tc-communities/Section'; import Banner from 'components/tc-communities/Banner'; import ImageText from 'components/tc-communities/ImageText'; import ResourceCard from 'components/tc-communities/ResourceCard'; -import NewsletterSignup from 'components/tc-communities/NewsletterSignup'; import NewsSection from 'components/tc-communities/NewsSection'; import PT from 'prop-types'; @@ -105,12 +104,6 @@ export default function Home({ news }) { - - ); } diff --git a/src/shared/components/tc-communities/communities/demo-expert/Learn/index.jsx b/src/shared/components/tc-communities/communities/demo-expert/Learn/index.jsx index 77e91eb84b..b89efa466b 100644 --- a/src/shared/components/tc-communities/communities/demo-expert/Learn/index.jsx +++ b/src/shared/components/tc-communities/communities/demo-expert/Learn/index.jsx @@ -12,7 +12,6 @@ import Section from 'components/tc-communities/Section'; import Accordion from 'components/tc-communities/Accordion/Accordion'; import AccordionItem from 'components/tc-communities/Accordion/AccordionItem'; import Banner from 'components/tc-communities/Banner'; -import NewsletterSignup from 'components/tc-communities/NewsletterSignup'; import ArticleCard from 'components/tc-communities/ArticleCard'; import LinksCard from 'components/tc-communities/LinksCard'; import Text from 'components/tc-communities/Text'; @@ -213,11 +212,6 @@ export default function Learn() { /> - ); } diff --git a/src/shared/components/tc-communities/communities/srmx/Learn/index.jsx b/src/shared/components/tc-communities/communities/srmx/Learn/index.jsx index bf23e6b544..dacc8b405d 100644 --- a/src/shared/components/tc-communities/communities/srmx/Learn/index.jsx +++ b/src/shared/components/tc-communities/communities/srmx/Learn/index.jsx @@ -12,7 +12,6 @@ import Section from 'components/tc-communities/Section'; import Accordion from 'components/tc-communities/Accordion/Accordion'; import AccordionItem from 'components/tc-communities/Accordion/AccordionItem'; import Banner from 'components/tc-communities/Banner'; -import NewsletterSignup from 'components/tc-communities/NewsletterSignup'; import ArticleCard from 'components/tc-communities/ArticleCard'; import LinksCard from 'components/tc-communities/LinksCard'; import Text from 'components/tc-communities/Text'; @@ -210,12 +209,6 @@ export default function Learn() { }]} /> - - ); } diff --git a/src/shared/components/tc-communities/communities/taskforce/Home/index.jsx b/src/shared/components/tc-communities/communities/taskforce/Home/index.jsx index 8ced88ff0d..bc3767fde8 100644 --- a/src/shared/components/tc-communities/communities/taskforce/Home/index.jsx +++ b/src/shared/components/tc-communities/communities/taskforce/Home/index.jsx @@ -11,7 +11,6 @@ import Section from 'components/tc-communities/Section'; import Banner from 'components/tc-communities/Banner'; import ImageText from 'components/tc-communities/ImageText'; import ResourceCard from 'components/tc-communities/ResourceCard'; -import NewsletterSignup from 'components/tc-communities/NewsletterSignup'; import NewsSection from 'components/tc-communities/NewsSection'; import PT from 'prop-types'; import Text from 'components/tc-communities/Text'; @@ -137,12 +136,6 @@ export default function Home({ news }) { - - ); } diff --git a/src/shared/components/tc-communities/communities/tc-prod-dev/Home/index.jsx b/src/shared/components/tc-communities/communities/tc-prod-dev/Home/index.jsx index 8931aff209..a14e292afc 100644 --- a/src/shared/components/tc-communities/communities/tc-prod-dev/Home/index.jsx +++ b/src/shared/components/tc-communities/communities/tc-prod-dev/Home/index.jsx @@ -11,7 +11,6 @@ import Section from 'components/tc-communities/Section'; import Banner from 'components/tc-communities/Banner'; import ImageText from 'components/tc-communities/ImageText'; import ResourceCard from 'components/tc-communities/ResourceCard'; -import NewsletterSignup from 'components/tc-communities/NewsletterSignup'; import NewsSection from 'components/tc-communities/NewsSection'; import PT from 'prop-types'; @@ -105,12 +104,6 @@ export default function Home({ news }) { - - ); } diff --git a/src/shared/components/tc-communities/communities/tc-prod-dev/Learn/index.jsx b/src/shared/components/tc-communities/communities/tc-prod-dev/Learn/index.jsx index 3194780c2a..85bdad2c35 100644 --- a/src/shared/components/tc-communities/communities/tc-prod-dev/Learn/index.jsx +++ b/src/shared/components/tc-communities/communities/tc-prod-dev/Learn/index.jsx @@ -12,7 +12,6 @@ import Section from 'components/tc-communities/Section'; import Accordion from 'components/tc-communities/Accordion/Accordion'; import AccordionItem from 'components/tc-communities/Accordion/AccordionItem'; import Banner from 'components/tc-communities/Banner'; -import NewsletterSignup from 'components/tc-communities/NewsletterSignup'; import ArticleCard from 'components/tc-communities/ArticleCard'; import LinksCard from 'components/tc-communities/LinksCard'; import Text from 'components/tc-communities/Text'; @@ -211,11 +210,6 @@ export default function Learn() { /> - ); } diff --git a/src/shared/components/tc-communities/communities/wipro/Home/index.jsx b/src/shared/components/tc-communities/communities/wipro/Home/index.jsx index 4246468661..bd28e35775 100644 --- a/src/shared/components/tc-communities/communities/wipro/Home/index.jsx +++ b/src/shared/components/tc-communities/communities/wipro/Home/index.jsx @@ -13,7 +13,6 @@ import ImageText from 'components/tc-communities/ImageText'; import LoadingIndicator from 'components/LoadingIndicator'; /* import ResourceCard from 'components/tc-communities/ResourceCard'; -import NewsletterSignup from 'components/tc-communities/NewsletterSignup'; import NewsSection from 'components/tc-communities/NewsSection'; */ @@ -209,79 +208,6 @@ export default function Home(props) {
    - {/* - NOTE: Commented out until we get a better content for these sections. - -
    - -
    - -
    -
    - -
    -
    - -
    -
    -
    - - - - - */} - ); } diff --git a/src/shared/components/tc-communities/communities/wipro/Learn/index.jsx b/src/shared/components/tc-communities/communities/wipro/Learn/index.jsx index 73ca34ffbc..9c595d0a49 100644 --- a/src/shared/components/tc-communities/communities/wipro/Learn/index.jsx +++ b/src/shared/components/tc-communities/communities/wipro/Learn/index.jsx @@ -15,7 +15,6 @@ import AccordionItem from 'components/tc-communities/Accordion/AccordionItem'; */ import Banner from 'components/tc-communities/Banner'; /* -import NewsletterSignup from 'components/tc-communities/NewsletterSignup'; import ArticleCard from 'components/tc-communities/ArticleCard'; import LinksCard from 'components/tc-communities/LinksCard'; import Text from 'components/tc-communities/Text'; @@ -181,12 +180,6 @@ export default function Learn() { }]} /> - - */} ); diff --git a/src/shared/containers/EmailSubscribeForm/index.jsx b/src/shared/containers/EmailSubscribeForm/index.jsx deleted file mode 100644 index e041e06387..0000000000 --- a/src/shared/containers/EmailSubscribeForm/index.jsx +++ /dev/null @@ -1,222 +0,0 @@ -/** - * Genetic subscribe for MailChimp tags component - */ -import React from 'react'; -import PT from 'prop-types'; -import { isValidEmail } from 'utils/tc'; -import TextInput from 'components/GUIKit/TextInput'; -import _ from 'lodash'; -import LoadingIndicator from 'components/LoadingIndicator'; -import { Link } from 'topcoder-react-utils'; -import defaulTheme from './style.scss'; - -/* Holds the base URL of Community App endpoints that proxy HTTP request to - * mailchimp APIs. */ -const PROXY_ENDPOINT = '/api/mailchimp'; - -class SubscribeMailChimpTagContainer extends React.Component { - constructor(props) { - super(props); - this.state = { - formErrors: {}, - formData: {}, - }; - this.onSubscribeClick = this.onSubscribeClick.bind(this); - this.onFormInputChange = this.onFormInputChange.bind(this); - this.validateForm = this.validateForm.bind(this); - } - - onSubscribeClick() { - this.validateForm(); - // eslint-disable-next-line consistent-return - this.setState((state) => { - const { formData, formErrors } = state; - if (_.isEmpty(formErrors)) { - const { listId, interests } = this.props; - const fetchUrl = `${PROXY_ENDPOINT}/${listId}/members/${formData.email}`; - const data = { - status: 'subscribed', - interests, - }; - fetch(fetchUrl, { - method: 'PUT', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(data), - }).then(result => result.json()).then((dataResponse) => { - if (dataResponse.status === 'subscribed') { - // regist success - return this.setState({ - subscribing: false, - subsribed: true, - error: '', - }); - } - if (dataResponse.status === 400) { - // new email register it for list and add tags - return fetch(`${PROXY_ENDPOINT}/${listId}/members`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - ...data, - email_address: formData.email, - merge_fields: { - FNAME: formData.fname, - LNAME: formData.lname, - }, - }), - }) - .then(result => result.json()).then((rsp) => { - this.setState({ - subscribing: false, - subsribed: !rsp.detail, - error: rsp.detail ? rsp.title : '', - }); - }); - } - return this.setState({ - subscribing: false, - subsribed: false, - error: `Error ${dataResponse.status} when subscribing ${formData.email}`, - }); - }) - .catch((e) => { - this.setState({ - subscribing: false, - subsribed: false, - error: e.message, - }); - }); - return { subscribing: true }; - } - }); - } - - onFormInputChange(key, val) { - this.setState((state) => { - const { formData } = state; - formData[key] = val; - return { - ...state, - formData, - }; - }); - this.validateForm(key); - } - - validateForm(key) { - this.setState((state) => { - const { formData, formErrors } = state; - if (key) { - // validate only the key - if (!formData[key] || !_.trim(formData[key])) formErrors[key] = 'Required field'; - else if (key === 'email' && !(isValidEmail(formData.email))) formErrors.email = 'Invalid email'; - else delete formErrors[key]; - } else { - _.each(['fname', 'lname', 'email'], (rkey) => { - if (!formData[rkey] || !_.trim(formData[rkey])) formErrors[rkey] = 'Required field'; - else if (rkey === 'email' && !(isValidEmail(formData.email))) formErrors.email = 'Invalid email'; - else delete formErrors[key]; - }); - } - // updated state - return { - ...state, - formErrors, - }; - }); - } - - render() { - const { - formData, formErrors, subscribing, subsribed, error, - } = this.state; - const { - btnText, title, successTitle, successText, successLink, successLinkText, - } = this.props; - return ( -
    - { - subscribing ? ( -
    - -

    - Processing your subscription... -

    -
    - ) : null - } - { - subsribed || error ? ( -
    -

    {error ? 'OOPS!' : successTitle}

    -

    {error || successText}

    - { - error - ? - : {successLinkText} - } -
    - ) : null - } - { - !subscribing && !subsribed && !error ? ( - -
    {title}
    - this.onFormInputChange('fname', val)} - errorMsg={formErrors.fname} - value={formData.fname} - required - /> - this.onFormInputChange('lname', val)} - errorMsg={formErrors.lname} - value={formData.lname} - required - /> - this.onFormInputChange('email', val)} - errorMsg={formErrors.email} - value={formData.email} - required - /> - -
    - ) : null - } -
    - ); - } -} - -SubscribeMailChimpTagContainer.defaultProps = { - title: '', - btnText: '', - successTitle: 'Success!', - successText: '', - successLink: '', - successLinkText: '', -}; - -SubscribeMailChimpTagContainer.propTypes = { - listId: PT.string.isRequired, - interests: PT.shape().isRequired, - title: PT.string, - btnText: PT.string, - successTitle: PT.string, - successText: PT.string, - successLink: PT.string, - successLinkText: PT.string, -}; - -export default SubscribeMailChimpTagContainer; diff --git a/src/shared/containers/EmailSubscribeForm/style.scss b/src/shared/containers/EmailSubscribeForm/style.scss deleted file mode 100644 index 4355e4cfd6..0000000000 --- a/src/shared/containers/EmailSubscribeForm/style.scss +++ /dev/null @@ -1,98 +0,0 @@ -@import "~components/Contentful/default"; - -.loadingWrap { - margin: 0; - padding: 0 34px; - - @include gui-kit-headers; - @include gui-kit-content; - @include roboto-regular; - - .loadingText { - font-family: Roboto, sans-serif; - color: #2a2a2a; - text-align: center; - margin-top: 26px; - } -} - -.subscribedWrap { - display: flex; - flex-direction: column; - align-items: center; - padding: 0 34px; - - @include gui-kit-headers; - @include gui-kit-content; - @include roboto-regular; - - > h4 { - margin-bottom: 16px !important; - } - - > p { - font-size: 24px !important; - line-height: 36px !important; - text-align: center; - - &.errorMsg { - color: #ef476f; - } - } -} - -.wrapper { - display: flex; - flex-direction: column; - color: #2a2a2a; - - @include gui-kit-headers; - @include gui-kit-content; - @include roboto-regular; - - h6 { - margin-top: 41px; - - @include xs-to-sm { - margin-top: 0; - } - } - - > div { - margin-bottom: 8px; - } - - .button { - background-color: #137d60; - border-radius: 20px; - color: #fff !important; - font-size: 14px; - font-weight: bolder; - text-decoration: none; - text-transform: uppercase; - line-height: 40px; - padding: 0 20px; - border: none; - outline: none; - margin-top: 13px; - margin-bottom: 41px; - max-width: 150px; - - &:hover { - box-shadow: 0 1px 5px 0 rgba(0, 0, 0, 0.2); - background-color: #0ab88a; - } - - @include xs-to-sm { - margin-bottom: 20px; - } - - &:disabled { - background-color: #e9e9e9 !important; - border: none !important; - text-decoration: none !important; - color: #fafafb !important; - box-shadow: none !important; - } - } -} diff --git a/src/shared/containers/NewsletterArchive.jsx b/src/shared/containers/NewsletterArchive.jsx deleted file mode 100644 index 1310f51913..0000000000 --- a/src/shared/containers/NewsletterArchive.jsx +++ /dev/null @@ -1,78 +0,0 @@ -import _ from 'lodash'; -import React from 'react'; -import PT from 'prop-types'; -import { connect } from 'react-redux'; -import actions from 'actions/newsletterArchive'; -import LoadingIndicator from 'components/LoadingIndicator'; -import NewsletterArchive from 'components/NewsletterArchive'; - -class NewsletterArchiveContainer extends React.Component { - componentDidMount() { - const { - loading, - name, - getNewsletterArchiveDone, - } = this.props; - if (!loading) { - getNewsletterArchiveDone(name); - } - } - - render() { - const { - loading, error, archive, limit, - } = this.props; - if (loading) return ; - if (error) { - return Error loading MailChimp archive: {error.message}; - } - if (!archive || !archive.campaigns) return null; - if (limit > 1) archive.campaigns = _.take(archive.campaigns, limit); - return ; - } -} - -NewsletterArchiveContainer.defaultProps = { - loading: false, - archive: null, - error: null, - limit: null, -}; - -NewsletterArchiveContainer.propTypes = { - loading: PT.bool, - name: PT.string.isRequired, - getNewsletterArchiveDone: PT.func.isRequired, - archive: PT.shape(), - error: PT.shape(), - limit: PT.string, -}; - -function mapStateToProps(state, ownProps) { - const { newsletterArchive } = state; - if (newsletterArchive[ownProps.name]) { - return { - loading: newsletterArchive[ownProps.name].loading, - error: newsletterArchive[ownProps.name].error, - archive: newsletterArchive[ownProps.name].archive, - }; - } - - return state; -} - -function mapDispatchToProps(dispatch) { - return { - getNewsletterArchiveDone: (name) => { - dispatch(actions.newsletterArchive.fetchDataInit(name)); - dispatch(actions.newsletterArchive.fetchDataDone(name)); - }, - }; -} - -const Container = connect( - mapStateToProps, - mapDispatchToProps, -)(NewsletterArchiveContainer); - -export default Container; diff --git a/src/shared/containers/NewsletterPreferences.jsx b/src/shared/containers/NewsletterPreferences.jsx deleted file mode 100644 index 61895b096c..0000000000 --- a/src/shared/containers/NewsletterPreferences.jsx +++ /dev/null @@ -1,102 +0,0 @@ -import React from 'react'; -import PT from 'prop-types'; -import { connect } from 'react-redux'; -import actions from 'actions/newsletterPreferences'; -import LoadingIndicator from 'components/LoadingIndicator'; -import Email from 'components/Settings/Preferences/Email'; - -class NewsletterPreferencesContainer extends React.Component { - constructor(props) { - super(props); - this.save = this.save.bind(this); - } - - componentDidMount() { - const { - loading, - email, - getNewsletterPreferencesDone, - } = this.props; - if (!loading) { - getNewsletterPreferencesDone(email); - } - } - - save() { - const { saveEmailPreferences } = this.props; - saveEmailPreferences(); - } - - render() { - const { - loading, error, preferences, saveEmailPreferences, email, updated, status, - } = this.props; - if (loading || !preferences) return ; - if (error) { - return Error loading Newsletter Preferences :-( {error.message}; - } - return ( - - ); - } -} - -NewsletterPreferencesContainer.defaultProps = { - loading: false, - error: null, - preferences: null, - updated: null, - status: null, -}; - -NewsletterPreferencesContainer.propTypes = { - loading: PT.bool, - getNewsletterPreferencesDone: PT.func.isRequired, - saveEmailPreferences: PT.func.isRequired, - error: PT.bool, - preferences: PT.shape(), - email: PT.string.isRequired, - updated: PT.shape(), - status: PT.string, -}; - -function mapStateToProps(state) { - const { newsletterPreferences } = state; - if (newsletterPreferences) { - return { - loading: newsletterPreferences.loading, - error: newsletterPreferences.error, - preferences: newsletterPreferences.preferences, - status: newsletterPreferences.status, - updated: newsletterPreferences.updated, - }; - } - - return state; -} - -function mapDispatchToProps(dispatch) { - return { - getNewsletterPreferencesDone: (email) => { - dispatch(actions.newsletterPreferences.fetchDataDone(email)); - }, - saveEmailPreferences: (email, id, checked) => { - dispatch(actions.newsletterPreferences.updateTagInit()); - dispatch(actions.newsletterPreferences.updateTagDone(email, id, checked)); - }, - }; -} - -const Container = connect( - mapStateToProps, - mapDispatchToProps, - null, { withRef: true }, -)(NewsletterPreferencesContainer); - -export default Container; diff --git a/src/shared/containers/NewsletterSignupForMembers.jsx b/src/shared/containers/NewsletterSignupForMembers.jsx deleted file mode 100644 index c73c8925f3..0000000000 --- a/src/shared/containers/NewsletterSignupForMembers.jsx +++ /dev/null @@ -1,278 +0,0 @@ -/** - * Container for NewsletterSignupForMembers component - */ - -/* global window */ - -import React from 'react'; -import PT from 'prop-types'; -import forge from 'node-forge'; -import fetch from 'isomorphic-fetch'; -import NewsletterSignupForMembers, { STATE as SIGNUP_NEWSLETTER } - from 'components/NewsletterSignupForMembers'; -import { connect } from 'react-redux'; -import { config } from 'topcoder-react-utils'; -import _ from 'lodash'; - -/* Holds the base URL of Community App endpoints that proxy HTTP request to - * mailchimp APIs. */ -const PROXY_ENDPOINT = `${config.URL.COMMUNITY_APP}/api/mailchimp`; - -class NewsletterSignupForMembersContainer extends React.Component { - constructor(props) { - super(props); - this.subscribe = this.subscribe.bind(this); - this.checkSubscription = this.checkSubscription.bind(this); - this.showSignupConfirmModal = this.showSignupConfirmModal.bind(this); - this.resetSignupButton = this.resetSignupButton.bind(this); - this.hideSignupButton = this.hideSignupButton.bind(this); - - this.hasSubscribedFromUrl = false; - - // Get interestIds and interest request object for mailchimp api - // to use in checkSubscription and subscribe function - const { groups, tags } = props; - this.groupsIds = null; - this.tagNames = null; - if (groups !== '') { - this.groupsIds = groups.split(/ *, */); - this.groupsIds[this.groupsIds.length - 1] = this.groupsIds[this.groupsIds.length - 1].replace(/^\s+|\s+$/g, ''); - } - if (tags) { - this.tagNames = tags.split(','); - } - this.isSubscribed = false; - - this.state = { - signupState: SIGNUP_NEWSLETTER.DEFAULT, - message: '', - }; - } - - componentDidMount() { - this.checkSubscription(); - } - - componentDidUpdate(prevProps) { - const { token, authenticating } = this.props; - const { signupState } = this.state; - if ( - prevProps.token !== token - || prevProps.authenticating !== authenticating - ) this.checkSubscription(); - let subscribeMe = window.location.href.match(/(.*\?)(.*)/); - subscribeMe = subscribeMe && subscribeMe[2].split('='); - subscribeMe = subscribeMe && subscribeMe[0] === 'subscribeme'; - if (token && subscribeMe && signupState === SIGNUP_NEWSLETTER.DEFAULT - && !this.hasSubscribedFromUrl) { - this.subscribe(); - this.hasSubscribedFromUrl = true; - } - } - - async checkSubscription() { - const { - listId, user, token, authenticating, - } = this.props; - if (!token || authenticating) return; - const md = forge.md.md5.create(); - md.update(user.email); - - this.emailHash = md.digest().toHex(); - - await fetch(`${PROXY_ENDPOINT}/${listId}/members/${this.emailHash}`, { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - }, - }) - .then((result) => { - if (result.status === 400) this.setState({ signupState: SIGNUP_NEWSLETTER.DEFAULT }); - return result.json(); - }) - .then((dataResponse) => { - if (dataResponse.status === 'subscribed') { - this.isSubscribed = true; - if (this.groupsIds) { - const subscribedGroups = _.keys(_.pickBy(dataResponse.interests, v => v)); - if (subscribedGroups.length) { - if (_.intersection(subscribedGroups, this.groupsIds).length) { - this.setState({ signupState: SIGNUP_NEWSLETTER.HIDDEN }); - } - } else { - this.setState({ signupState: SIGNUP_NEWSLETTER.DEFAULT }); - } - } - if (!this.groupsIds && this.tagNames) { - const subscribedTags = _.map(dataResponse.tags, t => t.name); - if (subscribedTags.length) { - if (_.intersection(subscribedTags, this.tagNames).length) { - this.setState({ signupState: SIGNUP_NEWSLETTER.HIDDEN }); - } - } else { - this.setState({ signupState: SIGNUP_NEWSLETTER.DEFAULT }); - } - } - } else { - this.setState({ signupState: SIGNUP_NEWSLETTER.DEFAULT }); - } - }); - } - - async subscribe() { - const { - listId, user, - } = this.props; - const isTagsUpdate = !!this.tagNames; - const fetchUrl = `${PROXY_ENDPOINT}/${listId}/members/${this.emailHash}${isTagsUpdate ? '/tags' : ''}`; - - if (this.groupsIds) { - let data = {}; - if (!this.isSubscribed) { - data = { - email_address: user.email, - status: 'subscribed', - merge_fields: { - FNAME: user.FNAME, - LNAME: user.LNAME, - }, - }; - } - data.interests = {}; - // eslint-disable-next-line array-callback-return - this.groupsIds.map((group) => { - data.interests[group] = true; - }); - - const formData = JSON.stringify(data); - // use proxy for avoid 'Access-Control-Allow-Origin' bug - await fetch(fetchUrl, { - method: 'PUT', - headers: { - 'Content-Type': 'application/json', - }, - body: formData, - }).then(result => result.json()).then((dataResponse) => { - if (dataResponse.status === 'subscribed') { - // regist success - this.setState({ signupState: SIGNUP_NEWSLETTER.SIGNEDUP }); - } else { - // regist fail - this.setState({ - signupState: SIGNUP_NEWSLETTER.ERROR, - message: dataResponse.detail, - }); - } - }); - } - if (!this.groupsIds && this.tagNames) { - const formData = JSON.stringify({ - tags: this.tagNames.map(tName => ({ - name: tName, - status: 'active', - })), - }); - // use proxy for avoid 'Access-Control-Allow-Origin' bug - await fetch(fetchUrl, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: formData, - }).then(result => result.json()).then((dataResponse) => { - if (dataResponse.status === 204) { - // regist success - this.setState({ signupState: SIGNUP_NEWSLETTER.SIGNEDUP }); - } else { - // regist fail - this.setState({ - signupState: SIGNUP_NEWSLETTER.ERROR, - message: dataResponse.detail, - }); - } - }); - } - } - - showSignupConfirmModal() { - this.setState({ signupState: SIGNUP_NEWSLETTER.CONFIRM_SIGNUP }); - } - - resetSignupButton() { - const { signupState } = this.state; - this.setState({ - signupState: signupState === SIGNUP_NEWSLETTER.SIGNEDUP - ? SIGNUP_NEWSLETTER.HIDDEN : SIGNUP_NEWSLETTER.DEFAULT, - }); - } - - hideSignupButton() { - this.setState({ signupState: SIGNUP_NEWSLETTER.HIDDEN }); - } - - render() { - const { signupState, message } = this.state; - return ( - - ); - } -} - -NewsletterSignupForMembersContainer.defaultProps = { - token: '', - label: 'Subscribe for Newsletter', - groups: '', - user: null, - buttonTheme: 'primary-green-md', - title: 'Sign up for the Topcoder Newsletter', - desc: 'Do you want to subscribe to this newsletter?', - tags: null, -}; - -NewsletterSignupForMembersContainer.propTypes = { - authenticating: PT.bool.isRequired, - token: PT.string, - label: PT.string, - groups: PT.string, - listId: PT.string.isRequired, - user: PT.shape(), - buttonTheme: PT.string, - title: PT.string, - desc: PT.string, - tags: PT.string, -}; - -function mapStateToProps(state, ownProps) { - /* We show NewsletterSignup button when a visitor is not authenticated, or when - * he is authenticated and not subscribed to Newsletter. */ - const { profile, tokenV3, authenticating } = state.auth; - - let userData = null; - if (profile && profile.email) { - userData = { - FNAME: profile.firstName, - LNAME: profile.lastName, - email: profile.email, - }; - } - - return { - authenticating, - label: ownProps.label, - theme: ownProps.theme, - token: tokenV3, - user: userData, - }; -} - -export default connect(mapStateToProps)(NewsletterSignupForMembersContainer); diff --git a/src/shared/containers/Settings.jsx b/src/shared/containers/Settings.jsx deleted file mode 100644 index 098dbf9724..0000000000 --- a/src/shared/containers/Settings.jsx +++ /dev/null @@ -1,329 +0,0 @@ -/** - * Connects the Redux store to the Settings components. - */ -import _ from 'lodash'; -import React from 'react'; -import PT from 'prop-types'; -import { connect } from 'react-redux'; - -import { isTokenExpired } from '@topcoder-platform/tc-auth-lib'; -import { goToLogin } from 'utils/tc'; - -import { actions } from 'topcoder-react-lib'; -import settingsActions, { TABS } from 'actions/page/settings'; -import settingsUIActions from 'actions/page/ui'; -import mfaActions from 'actions/mfa'; -import identityActions from 'actions/identity'; - -import Error404 from 'components/Error404'; -import LoadingIndicator from 'components/LoadingIndicator'; -import Settings from 'components/Settings'; - -class SettingsContainer extends React.Component { - componentDidMount() { - this.loadPageData(this.props); - } - - componentWillReceiveProps(nextProps) { - this.loadPageData(nextProps); - } - - loadPageData(props) { - const { - handle, - profileState, - settingsTab: targetSEttingsTab, - tokenV3, - authenticating, - loadTabData, - loadAllUserTraits, - } = props; - - const { - settingsTab, - } = this.props; - - if (authenticating) return; - - // Check auth token, go to login page if invalid - if (!tokenV3 || isTokenExpired(tokenV3)) { - goToLogin('community-app-main'); - return; - } - - const handleChanged = handle !== profileState.profileForHandle; - - // Load all user traits - if (handleChanged) { - loadAllUserTraits(handle, tokenV3); - } - - // Load tab data - if (handleChanged || targetSEttingsTab !== settingsTab) { - loadTabData(props); - } - } - - render() { - const { - authenticating, - loadingError, - profile, - } = this.props; - - if (loadingError) { - return ; - } - - // Only load the page when authenticated and profile is loaded - const loaded = !authenticating && profile; - - return loaded - ? ( - - ) - : ; - } -} - -SettingsContainer.defaultProps = { - settingsTab: TABS.PROFILE, - handle: '', - tokenV3: '', - profile: null, -}; - -SettingsContainer.propTypes = { - loadTabData: PT.func.isRequired, - selectTab: PT.func.isRequired, - uploadPhoto: PT.func.isRequired, - deletePhoto: PT.func.isRequired, - updateProfile: PT.func.isRequired, - updateProfileV5: PT.func.isRequired, - addWebLink: PT.func.isRequired, - deleteWebLink: PT.func.isRequired, - linkExternalAccount: PT.func.isRequired, - unlinkExternalAccount: PT.func.isRequired, - updatePassword: PT.func.isRequired, - settingsTab: PT.string, - authenticating: PT.bool.isRequired, - handle: PT.string, - tokenV3: PT.string, - profile: PT.shape(), - profileState: PT.shape().isRequired, - settingsPageState: PT.shape().isRequired, - lookupData: PT.shape().isRequired, - loadingError: PT.bool.isRequired, - updateEmailConflict: PT.func.isRequired, -}; - -function mapStateToProps(state) { - return { - settingsTab: state.page.settings.settingsTab, - settingsPageState: state.page.settings, - authenticating: state.auth.authenticating, - handle: _.get(state.auth, 'user.handle'), - emailAddress: _.defaults(_.get(state.auth, 'user.email'), _.get(state.auth, 'profile.email')), - tokenV3: state.auth.tokenV3, - profile: state.auth.profile, - user: state.auth.user, - lookupData: state.lookup, - profileState: state.profile, - loadingError: state.profile.loadingError, - settingsUI: state.page.ui.settings, - settings: state.settings, - traitRequestCount: state.settings.traitRequestCount, - userTraits: state.settings.userTraits, - skills: state.profile.skills, - usermfa: state.usermfa, - }; -} - -function mapDispatchToProps(dispatch) { - const profileActions = actions.profile; - const lookupActions = actions.lookup; - - const loadTabData = ({ - handle, - profile, - tokenV3, - settingsTab, - user, - }) => { - dispatch(profileActions.loadProfile(handle)); - if (settingsTab === TABS.PROFILE) { - dispatch(profileActions.getSkillsDone(handle)); - dispatch(lookupActions.getSkillTagsInit()); - dispatch(lookupActions.getSkillTagsDone()); - dispatch(lookupActions.getCountriesInit()); - dispatch(lookupActions.getCountriesDone()); - } else if (settingsTab === TABS.PREFERENCES) { - // Deprecated. Leaving it here as reminder to update topcoder-react-lib as well - // dispatch(profileActions.getEmailPreferencesDone(profile, tokenV3)); - } else if (settingsTab === TABS.ACCOUNT) { - if (profile.userId) { - dispatch(profileActions.getLinkedAccountsDone(profile, tokenV3)); - } else if (user.userId) { - dispatch(profileActions.getLinkedAccountsDone(user, tokenV3)); - } - dispatch(profileActions.getExternalLinksDone(handle)); - if (profile.userId) { - dispatch(profileActions.getCredentialDone(profile, tokenV3)); - } else if (user.userId) { - dispatch(profileActions.getCredentialDone(user, tokenV3)); - } - if (profile.userId) { - dispatch(mfaActions.usermfa.getUser2faDone(profile.userId, tokenV3)); - } else if (user.userId) { - dispatch(mfaActions.usermfa.getUser2faDone(user.userId, tokenV3)); - } - } else if (settingsTab === TABS.TOOLS) { - dispatch(lookupActions.getTypesInit()); - dispatch(lookupActions.getTypesDone()); - } - }; - - return { - loadTabData, - selectTab: tab => dispatch(settingsActions.page.settings.selectTab(tab)), - clearIncorrectPassword: () => dispatch(settingsActions.page.settings.clearIncorrectPassword()), - clearToastrNotification: - (() => dispatch(settingsActions.page.settings.clearToastrNotification())), - addWebLink: (handle, tokenV3, webLink) => { - dispatch(profileActions.addWebLinkInit()); - dispatch(profileActions.addWebLinkDone(handle, tokenV3, webLink)); - }, - getDeviceTypes: () => { - dispatch(lookupActions.getTypesInit()); - dispatch(lookupActions.getTypesDone()); - }, - clearDeviceState: () => { - // reset manufacturers, models, oses - dispatch(lookupActions.getManufacturersInit()); - }, - getManufacturers: (type) => { - dispatch(lookupActions.getManufacturersInit()); - dispatch(lookupActions.getManufacturersDone(type)); - }, - getModels: (page, type, manufacturer) => { - dispatch(lookupActions.getModelsInit(page)); - dispatch(lookupActions.getModelsDone(page, type, manufacturer)); - }, - getMoreModels: (page, type, manufacturer) => { - dispatch(lookupActions.getModelsInit(page)); - dispatch(lookupActions.getModelsDone(page, type, manufacturer)); - }, - getOses: (page, type, manufacturer, model) => { - dispatch(lookupActions.getOsesInit(page)); - dispatch(lookupActions.getOsesDone(page, type, manufacturer, model)); - }, - getMoreOses: (page, type, manufacturer, model) => { - dispatch(lookupActions.getOsesInit(page)); - dispatch(lookupActions.getOsesDone(page, type, manufacturer, model)); - }, - deleteWebLink: (handle, tokenV3, webLink) => { - dispatch(profileActions.deleteWebLinkInit(webLink)); - dispatch(profileActions.deleteWebLinkDone(handle, tokenV3, webLink)); - }, - uploadPhotoInit: () => { - dispatch(profileActions.uploadPhotoInit()); - }, - uploadPhoto: (handle, tokenV3, file) => { - dispatch(profileActions.uploadPhotoInit()); - dispatch(profileActions.uploadPhotoDone(handle, tokenV3, file)); - }, - deletePhoto: (profile, tokenV3) => { - dispatch(profileActions.deletePhotoInit()); - dispatch(profileActions.deletePhotoDone(profile, tokenV3)); - }, - updateProfile: (profile, tokenV3) => { - dispatch(profileActions.updateProfileInit()); - dispatch(profileActions.updateProfileDone(profile, tokenV3)); - }, - updateProfileV5: (profile, handle, tokenV5) => { - dispatch(profileActions.updateProfileInitV5()); - dispatch(profileActions.updateProfileDoneV5(profile, handle, tokenV5)); - }, - linkExternalAccount: (profile, tokenV3, providerType, callbackUrl) => { - dispatch(profileActions.linkExternalAccountInit()); - dispatch(profileActions - .linkExternalAccountDone(profile, tokenV3, providerType, callbackUrl)); - }, - unlinkExternalAccount: (profile, tokenV3, providerType) => { - dispatch(profileActions.unlinkExternalAccountInit({ providerType })); - dispatch(profileActions.unlinkExternalAccountDone(profile, tokenV3, providerType)); - }, - updatePassword: (profile, tokenV3, newPassword, oldPassword) => { - dispatch(profileActions.updatePasswordInit()); - dispatch(profileActions.updatePasswordDone(profile, tokenV3, newPassword, oldPassword)); - }, - toggleProfileSideTab: (tab) => { - dispatch(settingsUIActions.ui.settings.profile.toggleTab(tab)); - }, - toggleToolsSideTab: (tab) => { - dispatch(settingsUIActions.ui.settings.tools.toggleTab(tab)); - }, - toggleAccountSideTab: (tab) => { - dispatch(settingsUIActions.ui.settings.account.toggleTab(tab)); - }, - loadAllUserTraits: (handle, tokenV3) => { - dispatch(actions.settings.getAllUserTraits(handle, tokenV3)); - }, - addUserTrait: (handle, traitId, data, tokenV3) => { - dispatch(actions.settings.modifyUserTraitInit()); - return dispatch(actions.settings.addUserTrait(handle, traitId, data, tokenV3)); - }, - addUserSkill: (handle, skill, tokenV3) => { - dispatch(actions.profile.addSkillInit()); - dispatch(actions.profile.addSkillDone(handle, tokenV3, _.assign(skill, { tagId: skill.id }))); - }, - updateUserTrait: (handle, traitId, data, tokenV3) => { - dispatch(actions.settings.modifyUserTraitInit()); - return dispatch(actions.settings.updateUserTrait(handle, traitId, data, tokenV3)); - }, - deleteUserTrait: (handle, traitId, tokenV3) => { - dispatch(actions.settings.modifyUserTraitInit()); - dispatch(actions.settings.deleteUserTrait(handle, traitId, tokenV3)); - }, - deleteUserSkill: (handle, skill, tokenV3) => { - dispatch(actions.profile.hideSkillInit()); - dispatch( - actions.profile.hideSkillDone(handle, tokenV3, _.assign(skill, { tagId: skill.id })), - ); - }, - updateEmailConflict: (state) => { - dispatch(actions.profile.updateEmailConflict(state)); - }, - getUser2fa: (userId, tokenV3) => { - dispatch(mfaActions.usermfa.getUser2faDone(userId, tokenV3)); - }, - updateUser2fa: (userId, mfaEnabled, tokenV3) => { - dispatch(mfaActions.usermfa.updateUser2faInit()); - dispatch(mfaActions.usermfa.updateUser2faDone(userId, mfaEnabled, tokenV3)); - }, - updateUserDice: (userId, diceEnabled, tokenV3) => { - dispatch(mfaActions.usermfa.updateUserDiceDone(userId, diceEnabled, tokenV3)); - }, - getNewDiceConnection: (userId, tokenV3) => { - dispatch(mfaActions.usermfa.getNewDiceConnectionInit()); - dispatch(mfaActions.usermfa.getNewDiceConnectionDone(userId, tokenV3)); - }, - getDiceConnection: (userId, connectionId, tokenV3) => { - dispatch(mfaActions.usermfa.getDiceConnectionInit()); - dispatch(mfaActions.usermfa.getDiceConnectionDone(userId, connectionId, tokenV3)); - }, - updatePrimaryRole: (role, tokenV3) => { - dispatch(identityActions.identity.updatePrimaryRoleInit()); - dispatch(identityActions.identity.updatePrimaryRoleDone(role, tokenV3)); - }, - }; -} - -const Container = connect( - mapStateToProps, - mapDispatchToProps, -)(SettingsContainer); - -export default Container; diff --git a/src/shared/containers/SubscribeMailChimpTag/index.jsx b/src/shared/containers/SubscribeMailChimpTag/index.jsx deleted file mode 100644 index 6cccf69bd9..0000000000 --- a/src/shared/containers/SubscribeMailChimpTag/index.jsx +++ /dev/null @@ -1,128 +0,0 @@ -/** - * Genetic subscribe for MailChimp tags component - */ -import React from 'react'; -import PT from 'prop-types'; -import { isValidEmail } from 'utils/tc'; -import { Modal } from 'topcoder-react-ui-kit'; -import modalStyle from 'components/NewsletterSignupForMembers/modal.scss'; -import defaulTheme from './style.scss'; - -/* Holds the base URL of Community App endpoints that proxy HTTP request to - * mailchimp APIs. */ -const PROXY_ENDPOINT = '/api/mailchimp'; - -class SubscribeMailChimpTagContainer extends React.Component { - constructor(props) { - super(props); - this.state = { - error: '', - subsribed: false, - disabled: true, - inputVal: '', - }; - this.onSubscribeClick = this.onSubscribeClick.bind(this); - this.onInputChange = this.onInputChange.bind(this); - } - - onSubscribeClick() { - const { inputVal } = this.state; - const { listId, groups } = this.props; - const fetchUrl = `${PROXY_ENDPOINT}/${listId}/members/${inputVal}`; - const data = { - email_address: inputVal, - status: 'subscribed', - interests: groups, - }; - const formData = JSON.stringify(data); - fetch(fetchUrl, { - method: 'PUT', - headers: { - 'Content-Type': 'application/json', - }, - body: formData, - }).then(result => result.json()).then((dataResponse) => { - if (dataResponse.status < 300 || dataResponse.status === 'subscribed') { - // regist success - return this.setState({ - subsribed: true, - error: '', - }); - } - if (dataResponse.status === 404) { - // new email register it for list and add tags - return fetch(`${PROXY_ENDPOINT}/${listId}/members`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - email_address: inputVal, - status: 'subscribed', - interests: groups, - }), - }) - .then(result => result.json()).then(() => { - this.setState({ - subsribed: true, - error: '', - }); - }); - } - return this.setState({ - subsribed: false, - error: dataResponse.detail ? dataResponse.detail : `Error ${dataResponse.status} when trying to subscribe.`, - }); - }) - .catch((e) => { - this.setState({ - subsribed: false, - error: e.message, - }); - }); - } - - onInputChange(event) { - this.setState({ - inputVal: event.target.value, - disabled: !isValidEmail(event.target.value), - }); - } - - render() { - const { - disabled, inputVal, error, subsribed, - } = this.state; - return ( -
    - { - subsribed || error ? ( - this.setState({ - subsribed: false, - error: false, - inputVal: '', - disabled: true, - })} - > -
    -

    {subsribed ? 'Congratulations!' : 'Ops :('}

    -

    {error || 'You are now subscribed.'}

    -
    -
    - ) : null - } - - -
    - ); - } -} - -SubscribeMailChimpTagContainer.propTypes = { - listId: PT.string.isRequired, - groups: PT.shape().isRequired, -}; - -export default SubscribeMailChimpTagContainer; diff --git a/src/shared/containers/SubscribeMailChimpTag/style.scss b/src/shared/containers/SubscribeMailChimpTag/style.scss deleted file mode 100644 index b45ab4e39d..0000000000 --- a/src/shared/containers/SubscribeMailChimpTag/style.scss +++ /dev/null @@ -1,62 +0,0 @@ -@import '~styles/mixins'; - -.wrapper { - display: flex; - - input { - background-color: #fff !important; - border: 1px solid #aaa !important; - border-radius: 6px !important; - margin-right: 10px; - margin-bottom: 0 !important; - color: #2a2a2a; - font-family: Roboto, sans-serif; - font-size: 14px; - line-height: 22px; - } - - input::-webkit-input-placeholder, - input::placeholder { - color: #aaa !important; - font-family: Roboto, sans-serif !important; - font-size: 14px !important; - line-height: 40px !important; - text-transform: none; - } - - input:focus { - box-shadow: none !important; - } - - .button { - background-color: #137d60; - border-radius: 20px; - color: #fff !important; - font-size: 14px; - font-weight: bolder; - text-decoration: none; - text-transform: uppercase; - line-height: 40px; - padding: 0 20px; - border: none; - outline: none; - max-width: 122px; - - &:hover { - box-shadow: 0 1px 5px 0 rgba(0, 0, 0, 0.2); - background-color: #0ab88a; - } - - @include xs-to-sm { - margin-bottom: 20px; - } - - &:disabled { - background-color: #e9e9e9 !important; - border: none !important; - text-decoration: none !important; - color: #fafafb !important; - box-shadow: none !important; - } - } -} diff --git a/src/shared/containers/timeline-wall/modal-confirm-reject/index.jsx b/src/shared/containers/timeline-wall/modal-confirm-reject/index.jsx index d551d59526..91d921ffd8 100644 --- a/src/shared/containers/timeline-wall/modal-confirm-reject/index.jsx +++ b/src/shared/containers/timeline-wall/modal-confirm-reject/index.jsx @@ -3,9 +3,9 @@ import PT from 'prop-types'; import _ from 'lodash'; import { Modal } from 'topcoder-react-ui-kit'; import IconCloseGreen from 'assets/images/icon-close-green.svg'; -import FormField from 'components/Settings/FormField'; -import FormInputTextArea from 'components/Settings/FormInputTextArea'; -import FormInputSelect from 'components/Settings/FormInputSelect'; +import FormField from 'components/Form/FormField'; +import FormInputTextArea from 'components/Form/FormInputTextArea'; +import FormInputSelect from 'components/Form/FormInputSelect'; import { config } from 'topcoder-react-utils'; import style from './styles.scss'; diff --git a/src/shared/containers/timeline-wall/timeline-events/add-event/index.jsx b/src/shared/containers/timeline-wall/timeline-events/add-event/index.jsx index 35ab83d0fb..d74566a111 100644 --- a/src/shared/containers/timeline-wall/timeline-events/add-event/index.jsx +++ b/src/shared/containers/timeline-wall/timeline-events/add-event/index.jsx @@ -5,10 +5,10 @@ import IconPhoto from 'assets/images/timeline-wall/icon-photo.svg'; import IconVideo from 'assets/images/timeline-wall/icon-video.svg'; import IconTooltipDown from 'assets/images/timeline-wall/tooltip-down.svg'; import IconTooltipLeft from 'assets/images/timeline-wall/tooltip-left.svg'; -import FormInputText from 'components/Settings/FormInputText'; -import FormField from 'components/Settings/FormField'; -import FormInputDatePicker from 'components/Settings/FormInputDatePicker'; -import FormInputTextArea from 'components/Settings/FormInputTextArea'; +import FormInputText from 'components/Form/FormInputText'; +import FormField from 'components/Form/FormField'; +import FormInputDatePicker from 'components/Form/FormInputDatePicker'; +import FormInputTextArea from 'components/Form/FormInputTextArea'; import PhotoVideoPicker from 'components/GUIKit/PhotoVideoPicker'; import { config } from 'topcoder-react-utils'; import IconCloseGreen from 'assets/images/icon-close-green.svg'; diff --git a/src/shared/reducers/index.js b/src/shared/reducers/index.js index f5e9782065..34f4da0a55 100644 --- a/src/shared/reducers/index.js +++ b/src/shared/reducers/index.js @@ -25,7 +25,6 @@ import { getAuthTokens } from 'utils/tc'; import contentful from './contentful'; import topcoderHeader from './topcoder_header'; import rss from './rss'; -import newsletterArchive from './newsletterArchive'; import menuNavigation from './contentful/menuNavigation'; import challengesBlock from './contentful/challengesBlock'; import policyPages from './contentful/policyPages'; @@ -37,7 +36,6 @@ import { factory as leaderboardFactory } from './leaderboard'; import { factory as scoreboardFactory } from './tco/scoreboard'; import { factory as termsFactory } from './terms'; import { factory as mfaFactory } from './mfa'; -import newsletterPreferences from './newsletterPreferences'; import mmLeaderboard from './mmLeaderboard'; import tcoLeaderboards from './tco/leaderboards'; import recruitCRM from './recruitCRM'; @@ -172,11 +170,9 @@ export function factory(req) { topcoderHeader, rss, toastr: toastrReducer, - newsletterArchive, menuNavigation, challengesBlock, policyPages, - newsletterPreferences, recruitCRM, mmLeaderboard, gSheet, diff --git a/src/shared/reducers/newsletterArchive.js b/src/shared/reducers/newsletterArchive.js deleted file mode 100644 index df28681713..0000000000 --- a/src/shared/reducers/newsletterArchive.js +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Reducer for state.newsletterArchive - */ - -import actions from 'actions/newsletterArchive'; -import { handleActions } from 'redux-actions'; - -/** - * Handles newsletterArchive.fetchDatInit action. - * @param {Object} state Previous state. - * @param {Object} name The action. - */ -function onInit(state, { payload }) { - return { - ...state, - [payload]: { - archive: [], - loading: true, - }, - }; -} - -/** - * Handles newsletterArchive.fetchDataDone action. - * @param {Object} state Previous state. - * @param {Object} action The action. - */ -function onDone(state, { payload }) { - return { - ...state, - [payload.name]: { - archive: payload.error ? null : payload.archive, - error: payload.error, - loading: false, - }, - }; -} - -/** - * Creates newsletterArchive reducer with the specified initial state. - * @param {Object} state Optional. If not given, the default one is - * generated automatically. - * @return {Function} Reducer. - */ -function create(state = {}) { - return handleActions({ - [actions.newsletterArchive.fetchDataInit]: onInit, - [actions.newsletterArchive.fetchDataDone]: onDone, - }, state); -} - -/* Reducer with the default initial state. */ -export default create(); diff --git a/src/shared/reducers/newsletterPreferences.js b/src/shared/reducers/newsletterPreferences.js deleted file mode 100644 index 6dab15735d..0000000000 --- a/src/shared/reducers/newsletterPreferences.js +++ /dev/null @@ -1,70 +0,0 @@ -/** - * Reducer for state.newsletterPreferences - */ - -import actions from 'actions/newsletterPreferences'; -import { handleActions } from 'redux-actions'; - -/** - * Handles newsletterPreferences.fetchDataInit action. - * @param {Object} state Previous state. - * @param {Object} name The action. - */ -function onInit(state, { payload }) { - return { - ...state, - email: payload, - preferences: {}, - status: null, - loading: true, - }; -} - -/** - * Handles newsletterPreferences.fetchDataDone action. - * @param {Object} state Previous state. - * @param {Object} action The action. - */ -function onDone(state, { payload }) { - return { - ...state, - preferences: payload.error ? null : payload.preferences, - status: payload.error ? null : payload.status, - error: payload.error, - loading: false, - }; -} - -function onUpdateTagInit(state) { - return { - ...state, - updated: null, - }; -} - -function onUpdateTagDone(state, { payload }) { - // eslint-disable-next-line no-param-reassign - state.preferences[payload.id] = payload.checked; - return { - ...state, - updated: payload, - }; -} - -/** - * Creates newsletterPreferences reducer with the specified initial state. - * @param {Object} state Optional. If not given, the default one is - * generated automatically. - * @return {Function} Reducer. - */ -function create(state = {}) { - return handleActions({ - [actions.newsletterPreferences.fetchDataInit]: onInit, - [actions.newsletterPreferences.fetchDataDone]: onDone, - [actions.newsletterPreferences.updateTagInit]: onUpdateTagInit, - [actions.newsletterPreferences.updateTagDone]: onUpdateTagDone, - }, state); -} - -/* Reducer with the default initial state. */ -export default create(); diff --git a/src/shared/routes/Topcoder/Routes.jsx b/src/shared/routes/Topcoder/Routes.jsx index 3c579416a5..7e040cd60d 100644 --- a/src/shared/routes/Topcoder/Routes.jsx +++ b/src/shared/routes/Topcoder/Routes.jsx @@ -29,7 +29,6 @@ import EDUSearch from '../EDUSearch'; import ChallengeListing from './ChallengeListing'; import Dashboard from './Dashboard'; import Notifications from './Notifications'; -import Settings from '../Settings'; import HallOfFame from '../HallOfFame'; import ProfileBadges from '../ProfileBadges'; import Scoreboard from '../tco/scoreboard'; @@ -93,10 +92,6 @@ export default function Topcoder() { /> ) } - } - path="/settings" - /> } diff --git a/src/shared/routes/Topcoder/Settings.jsx b/src/shared/routes/Topcoder/Settings.jsx deleted file mode 100644 index a7ceed5fbd..0000000000 --- a/src/shared/routes/Topcoder/Settings.jsx +++ /dev/null @@ -1,32 +0,0 @@ -/** - * The loader of Settings webpack chunks. - */ -import path from 'path'; -import React from 'react'; -import { StaticRouter } from 'react-router-dom'; - -import LoadingPagePlaceholder from 'components/LoadingPagePlaceholder'; -import { AppChunk, webpack } from 'topcoder-react-utils'; - -export default function SettingsLoader(props) { - return ( - import(/* webpackChunkName: "settings/chunk" */ 'containers/Settings') - .then(({ default: SettingsContainer }) => ( - - )) - } - renderPlaceholder={() => } - renderServer={() => { - const p = webpack.resolveWeak('containers/Settings'); - const SettingsContainer = webpack.requireWeak(path.resolve(__dirname, p)); - return ( - - - - ); - }} - /> - ); -} diff --git a/src/shared/utils/markdown.js b/src/shared/utils/markdown.js index 5e0883bf04..93363ad536 100644 --- a/src/shared/utils/markdown.js +++ b/src/shared/utils/markdown.js @@ -18,13 +18,10 @@ import sup from 'markdown-it-sup'; import 'highlight.js/styles/github.css'; import JoinCommunity from 'containers/tc-communities/JoinCommunity'; -import NewsletterSignup from 'components/NewsletterSignup'; -import NewsletterSignupForMembers from 'containers/NewsletterSignupForMembers'; import VideoModalButton from 'components/VideoModalButton'; import Looker from 'containers/Looker'; import AnchorLink from 'react-anchor-link-smooth-scroll'; import Modal from 'components/Contentful/Modal'; -import NewsletterArchive from 'containers/NewsletterArchive'; import MMLeaderboard from 'containers/MMLeaderboard'; import tco19SecLg from 'components/buttons/outline/tco/tco19-sec-lg.scss'; @@ -97,8 +94,6 @@ const customComponents = { Link: attrs => ({ type: Link, props: attrs }), JoinCommunity: attrs => ({ type: JoinCommunity, props: attrs }), VideoModalButton: attrs => ({ type: VideoModalButton, props: attrs }), - NewsletterSignup: attrs => ({ type: NewsletterSignup, props: attrs }), - NewsletterSignupForMembers: attrs => ({ type: NewsletterSignupForMembers, props: attrs }), Looker: attrs => ({ type: Looker, props: attrs }), AnchorLink: attrs => ({ type: AnchorLink, props: attrs }), TCOButton: attrs => ({ @@ -116,7 +111,6 @@ const customComponents = { }, }), Modal: attrs => ({ type: Modal, props: attrs }), - NewsletterArchive: attrs => ({ type: NewsletterArchive, props: attrs }), ThemedButton: (attrs) => { const t = attrs.theme.split('-'); return {