diff --git a/.env b/.env index b8c2875..bddadec 100644 --- a/.env +++ b/.env @@ -26,3 +26,4 @@ COLLECT_YEAR_OF_BIRTH=true APP_ID='' MFE_CONFIG_API_URL='' ENABLE_SKILLS_BUILDER='' +ENABLE_SKILLS_BUILDER_PROFILE='' diff --git a/.env.development b/.env.development index 2f52fd8..d249e3e 100644 --- a/.env.development +++ b/.env.development @@ -27,3 +27,4 @@ COLLECT_YEAR_OF_BIRTH=true APP_ID='' MFE_CONFIG_API_URL='' ENABLE_SKILLS_BUILDER='true' +ENABLE_SKILLS_BUILDER_PROFILE='' diff --git a/.env.test b/.env.test index dc8c561..b79d85c 100644 --- a/.env.test +++ b/.env.test @@ -17,6 +17,9 @@ LOGO_URL=https://edx-cdn.org/v3/default/logo.svg LOGO_TRADEMARK_URL=https://edx-cdn.org/v3/default/logo-trademark.svg LOGO_WHITE_URL=https://edx-cdn.org/v3/default/logo-white.svg FAVICON_URL=https://edx-cdn.org/v3/default/favicon.ico +ENABLE_LEARNER_RECORD_MFE='' +ENABLE_SKILLS_BUILDER_PROFILE='' +LEARNER_RECORD_MFE_BASE_URL='http://localhost:1990' COLLECT_YEAR_OF_BIRTH=true APP_ID='' MFE_CONFIG_API_URL='' diff --git a/src/index.jsx b/src/index.jsx index aedd75f..951014b 100755 --- a/src/index.jsx +++ b/src/index.jsx @@ -67,6 +67,7 @@ initialize({ mergeConfig({ COLLECT_YEAR_OF_BIRTH: process.env.COLLECT_YEAR_OF_BIRTH, ENABLE_SKILLS_BUILDER: process.env.ENABLE_SKILLS_BUILDER, + ENABLE_SKILLS_BUILDER_PROFILE: process.env.ENABLE_SKILLS_BUILDER_PROFILE, }, 'App loadConfig override handler'); }, }, diff --git a/src/profile/ProfilePage.jsx b/src/profile/ProfilePage.jsx index c5c7604..a1f789e 100644 --- a/src/profile/ProfilePage.jsx +++ b/src/profile/ProfilePage.jsx @@ -33,6 +33,7 @@ import DateJoined from './DateJoined'; import UsernameDescription from './UsernameDescription'; import PageLoading from './PageLoading'; import Banner from './Banner'; +import LearningGoal from './forms/LearningGoal'; // Selectors import { profilePageSelector } from './data/selectors'; @@ -171,6 +172,8 @@ class ProfilePage extends React.Component { socialLinks, draftSocialLinksByPlatform, visibilitySocialLinks, + learningGoal, + visibilityLearningGoal, languageProficiencies, visibilityLanguageProficiencies, visibilityCourseCertificates, @@ -265,6 +268,14 @@ class ProfilePage extends React.Component { formId="bio" {...commonFormProps} /> + {getConfig().ENABLE_SKILLS_BUILDER_PROFILE && ( + + )} { + let { learningGoal, editMode, visibilityLearningGoal } = props; + const { intl } = props; + + if (!learningGoal) { + learningGoal = mockData.learningGoal; + } + + if (!editMode || editMode === 'empty') { // editMode defaults to 'empty', not sure why yet + editMode = mockData.editMode; + } + + if (!visibilityLearningGoal) { + visibilityLearningGoal = mockData.visibilityLearningGoal; + } + + return ( + + +

+ {intl.formatMessage(get( + messages, + `profile.learningGoal.options.${learningGoal}`, + messages['profile.learningGoal.options.something_else'], + ))} +

+ + ), + static: ( + <> + +

+ {intl.formatMessage(get( + messages, + `profile.learningGoal.options.${learningGoal}`, + messages['profile.learningGoal.options.something_else'], + ))} +

+ + ), + }} + /> + ); +}; + +LearningGoal.propTypes = { + // From Selector + learningGoal: PropTypes.oneOf(['advance_career', 'start_career', 'learn_something_new', 'something_else']), + visibilityLearningGoal: PropTypes.oneOf(['private', 'all_users']), + editMode: PropTypes.oneOf(['editable', 'static']), + + // i18n + intl: intlShape.isRequired, +}; + +LearningGoal.defaultProps = { + editMode: 'static', + learningGoal: null, + visibilityLearningGoal: 'private', +}; + +export default connect( + editableFormSelector, + {}, +)(injectIntl(LearningGoal)); diff --git a/src/profile/forms/LearningGoal.messages.jsx b/src/profile/forms/LearningGoal.messages.jsx new file mode 100644 index 0000000..181fbb3 --- /dev/null +++ b/src/profile/forms/LearningGoal.messages.jsx @@ -0,0 +1,31 @@ +import { defineMessages } from '@edx/frontend-platform/i18n'; + +const messages = defineMessages({ + 'profile.learningGoal.learningGoal': { + id: 'profile.learningGoal.learningGoal', + defaultMessage: 'Learning Goal', + description: 'A section of a user profile that displays their current learning goal.', + }, + 'profile.learningGoal.options.start_career': { + id: 'profile.learningGoal.options.start_career', + defaultMessage: 'I want to start my career', + description: 'Selected by user if their goal is to start their career.', + }, + 'profile.learningGoal.options.advance_career': { + id: 'profile.learningGoal.options.advance_career', + defaultMessage: 'I want to advance my career', + description: 'Selected by user if their goal is to advance their career.', + }, + 'profile.learningGoal.options.learn_something_new': { + id: 'profile.learningGoal.options.learn_something_new', + defaultMessage: 'I want to learn something new', + description: 'Selected by user if their goal is to learn something new.', + }, + 'profile.learningGoal.options.something_else': { + id: 'profile.learningGoal.options.something_else', + defaultMessage: 'Something else', + description: 'Selected by user if their goal is not described by the other choices.', + }, +}); + +export default messages; diff --git a/src/profile/forms/LearningGoal.test.jsx b/src/profile/forms/LearningGoal.test.jsx new file mode 100644 index 0000000..1143aff --- /dev/null +++ b/src/profile/forms/LearningGoal.test.jsx @@ -0,0 +1,122 @@ +import PropTypes from 'prop-types'; +import React, { useMemo } from 'react'; +import { Provider } from 'react-redux'; +import renderer from 'react-test-renderer'; +import configureMockStore from 'redux-mock-store'; +import thunk from 'redux-thunk'; +import { configure as configureI18n, IntlProvider } from '@edx/frontend-platform/i18n'; +import { getConfig } from '@edx/frontend-platform'; +import { AppContext } from '@edx/frontend-platform/react'; +import messages from '../../i18n'; + +import viewOwnProfileMockStore from '../__mocks__/viewOwnProfile.mockStore'; +import savingEditedBioMockStore from '../__mocks__/savingEditedBio.mockStore'; + +import LearningGoal from './LearningGoal'; + +const mockStore = configureMockStore([thunk]); + +// props to be passed down to LearningGoal component +const requiredLearningGoalProps = { + formId: 'learningGoal', + learningGoal: 'advance_career', + drafts: {}, + visibilityLearningGoal: 'private', + editMode: 'static', + saveState: null, + error: null, + openHandler: jest.fn(), +}; + +configureI18n({ + loggingService: { logError: jest.fn() }, + config: { + ENVIRONMENT: 'production', + LANGUAGE_PREFERENCE_COOKIE_NAME: 'yum', + }, + messages, +}); + +const LearningGoalWrapper = (props) => { + const contextValue = useMemo(() => ({ + authenticatedUser: { userId: null, username: null, administrator: false }, + config: getConfig(), + }), []); + return ( + + + + + + + + ); +}; + +LearningGoalWrapper.defaultProps = { + store: mockStore(viewOwnProfileMockStore), +}; + +LearningGoalWrapper.propTypes = { + store: PropTypes.shape({}), +}; + +const LearningGoalWrapperWithStore = ({ store }) => { + const contextValue = useMemo(() => ({ + authenticatedUser: { userId: null, username: null, administrator: false }, + config: getConfig(), + }), []); + return ( + + + + + + + + ); +}; + +LearningGoalWrapperWithStore.defaultProps = { + store: mockStore(savingEditedBioMockStore), +}; + +LearningGoalWrapperWithStore.propTypes = { + store: PropTypes.shape({}), +}; + +describe('', () => { + describe('renders the current learning goal', () => { + it('renders "I want to advance my career"', () => { + const learningGoalRenderer = renderer.create( + , + ); + + const learningGoalInstance = learningGoalRenderer.root; + + expect(learningGoalInstance.findByProps({ className: 'lead' }).children).toEqual(['I want to advance my career']); + }); + + it('renders "Something else"', () => { + requiredLearningGoalProps.learningGoal = 'something_else'; + + const learningGoalRenderer = renderer.create( + , + ); + + const learningGoalInstance = learningGoalRenderer.root; + + expect(learningGoalInstance.findByProps({ className: 'lead' }).children).toEqual(['Something else']); + }); + }); +});