Organize the repo and export profile module properly (#262)

* Moving files to their new homes.

Subsequent commit will wire everything up again.

* Relink files and split stylesheet.

Requires adding resolve-url-loader to fix sass import relativity.

* Remove browserslist warning.

* Remove the need for ProfileMain

* Fix test issues - needed thunk.
This commit is contained in:
David Joy
2019-09-23 13:50:56 -04:00
committed by GitHub
parent 9b126281f1
commit 8f37cc1a8d
60 changed files with 363 additions and 214 deletions

164
package-lock.json generated
View File

@@ -4248,6 +4248,27 @@
"integrity": "sha512-4diPfzWbLEIElVG4AnqP+00SULlPzNuyJFNnmMrLgyaxG6tZXJ1sn7mjBu4fHrJE+Yp/jgylOweJn2xsLMFggQ==",
"dev": true
},
"adjust-sourcemap-loader": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-2.0.0.tgz",
"integrity": "sha512-4hFsTsn58+YjrU9qKzML2JSSDqKvN8mUGQ0nNIrfPi8hmIONT4L3uUaT6MKdMsZ9AjsU6D2xDkZxCkbQPxChrA==",
"dev": true,
"requires": {
"assert": "1.4.1",
"camelcase": "5.0.0",
"loader-utils": "1.2.3",
"object-path": "0.11.4",
"regex-parser": "2.2.10"
},
"dependencies": {
"camelcase": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz",
"integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==",
"dev": true
}
}
},
"agent-base": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz",
@@ -4495,6 +4516,12 @@
"commander": "^2.11.0"
}
},
"arity-n": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/arity-n/-/arity-n-1.0.4.tgz",
"integrity": "sha1-2edrEXM+CFacCEeuezmyhgswt0U=",
"dev": true
},
"arr-diff": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
@@ -6631,6 +6658,15 @@
"integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=",
"dev": true
},
"compose-function": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/compose-function/-/compose-function-3.0.3.tgz",
"integrity": "sha1-ntZ18TzFRQHTCVCkhv9qe6OrGF8=",
"dev": true,
"requires": {
"arity-n": "^1.0.4"
}
},
"compressible": {
"version": "2.0.15",
"resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.15.tgz",
@@ -7131,6 +7167,18 @@
"integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=",
"dev": true
},
"css": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz",
"integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==",
"dev": true,
"requires": {
"inherits": "^2.0.3",
"source-map": "^0.6.1",
"source-map-resolve": "^0.5.2",
"urix": "^0.1.0"
}
},
"css-color-names": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz",
@@ -7462,6 +7510,16 @@
"integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=",
"dev": true
},
"d": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
"integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
"dev": true,
"requires": {
"es5-ext": "^0.10.50",
"type": "^1.0.1"
}
},
"damerau-levenshtein": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz",
@@ -8344,6 +8402,28 @@
"is-symbol": "^1.0.2"
}
},
"es5-ext": {
"version": "0.10.51",
"resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.51.tgz",
"integrity": "sha512-oRpWzM2WcLHVKpnrcyB7OW8j/s67Ba04JCm0WnNv3RiABSvs7mrQlutB8DBv793gKcp0XENR8Il8WxGTlZ73gQ==",
"dev": true,
"requires": {
"es6-iterator": "~2.0.3",
"es6-symbol": "~3.1.1",
"next-tick": "^1.0.0"
}
},
"es6-iterator": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
"integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=",
"dev": true,
"requires": {
"d": "1",
"es5-ext": "^0.10.35",
"es6-symbol": "^3.1.1"
}
},
"es6-promise": {
"version": "4.2.6",
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.6.tgz",
@@ -8357,6 +8437,16 @@
"es6-promise": "^4.0.3"
}
},
"es6-symbol": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.2.tgz",
"integrity": "sha512-/ZypxQsArlv+KHpGvng52/Iz8by3EQPxhmbuz8yFG89N/caTFBSbcXONDw0aMjy827gQg26XAjP4uXFvnfINmQ==",
"dev": true,
"requires": {
"d": "^1.0.1",
"es5-ext": "^0.10.51"
}
},
"escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
@@ -14901,6 +14991,12 @@
}
}
},
"next-tick": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz",
"integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=",
"dev": true
},
"nice-try": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
@@ -15334,6 +15430,12 @@
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz",
"integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag=="
},
"object-path": {
"version": "0.11.4",
"resolved": "https://registry.npmjs.org/object-path/-/object-path-0.11.4.tgz",
"integrity": "sha1-NwrnUvvzfePqcKhhwju6iRVpGUk=",
"dev": true
},
"object-visit": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
@@ -18373,6 +18475,12 @@
"safe-regex": "^1.1.0"
}
},
"regex-parser": {
"version": "2.2.10",
"resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.2.10.tgz",
"integrity": "sha512-8t6074A68gHfU8Neftl0Le6KTDwfGAj7IyjPIMSfikI2wJUTHDMaIq42bUsfVnj8mhx0R+45rdUXHGpN164avA==",
"dev": true
},
"regexp-tree": {
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.13.tgz",
@@ -18595,6 +18703,32 @@
"integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
"dev": true
},
"resolve-url-loader": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-3.1.0.tgz",
"integrity": "sha512-2QcrA+2QgVqsMJ1Hn5NnJXIGCX1clQ1F6QJTqOeiaDw9ACo1G2k+8/shq3mtqne03HOFyskAClqfxKyFBriXZg==",
"dev": true,
"requires": {
"adjust-sourcemap-loader": "2.0.0",
"camelcase": "5.0.0",
"compose-function": "3.0.3",
"convert-source-map": "1.6.0",
"es6-iterator": "2.0.3",
"loader-utils": "1.2.3",
"postcss": "7.0.14",
"rework": "1.0.1",
"rework-visit": "1.0.0",
"source-map": "0.6.1"
},
"dependencies": {
"camelcase": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz",
"integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==",
"dev": true
}
}
},
"responselike": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz",
@@ -18626,6 +18760,30 @@
"integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=",
"dev": true
},
"rework": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/rework/-/rework-1.0.1.tgz",
"integrity": "sha1-MIBqhBNCtUUQqkEQhQzUhTQUSqc=",
"dev": true,
"requires": {
"convert-source-map": "^0.3.3",
"css": "^2.0.0"
},
"dependencies": {
"convert-source-map": {
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-0.3.5.tgz",
"integrity": "sha1-8dgClQr33SYxof6+BZZVDIarMZA=",
"dev": true
}
}
},
"rework-visit": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/rework-visit/-/rework-visit-1.0.0.tgz",
"integrity": "sha1-mUWygD8hni96ygCtuLyfZA+ELJo=",
"dev": true
},
"rgb-regex": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz",
@@ -21406,6 +21564,12 @@
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
"dev": true
},
"type": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
"integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==",
"dev": true
},
"type-check": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",

View File

@@ -6,6 +6,10 @@
"type": "git",
"url": "git+https://github.com/edx/frontend-app-profile.git"
},
"browserslist": [
"last 2 versions",
"ie 11"
],
"scripts": {
"build": "NODE_ENV=production BABEL_ENV=production webpack --config=webpack/webpack.prod.config.js",
"i18n_extract": "BABEL_ENV=i18n babel src --quiet > /dev/null",
@@ -113,6 +117,7 @@
"react-test-renderer": "16.9.0",
"reactifex": "1.1.1",
"redux-mock-store": "1.5.3",
"resolve-url-loader": "^3.1.0",
"sass-loader": "6.0.7",
"source-map-loader": "0.2.4",
"style-loader": "0.20.3",

View File

@@ -4,20 +4,27 @@ import { App, AppProvider, APP_ERROR, APP_READY, ErrorPage } from '@edx/frontend
import { NewRelicLoggingService } from '@edx/frontend-logging';
import React from 'react';
import ReactDOM from 'react-dom';
import { Route, Switch } from 'react-router-dom';
import Header, { messages as headerMessages } from '@edx/frontend-component-header';
import Footer from '../footer/Footer';
import appMessages from './i18n';
import './index.scss';
import ProfileMain from './profile/components/ProfileMain';
import { ProfilePage, NotFoundPage } from './profile';
import configureStore from './store';
App.subscribe(APP_READY, () => {
ReactDOM.render(
<AppProvider store={configureStore()}>
<Header />
<ProfileMain />
<main>
<Switch>
<Route path="/u/:username" component={ProfilePage} />
<Route path="/notfound" component={NotFoundPage} />
<Route path="*" component={NotFoundPage} />
</Switch>
</main>
<Footer />
</AppProvider>,
document.getElementById('root'),
@@ -29,4 +36,3 @@ App.subscribe(APP_ERROR, (error) => {
});
App.initialize({ messages: [appMessages, headerMessages], loggingService: NewRelicLoggingService });

View File

@@ -1,145 +1,7 @@
@import '~@edx/paragon/scss/edx/theme.scss';
@import '~@edx/paragon/scss/edx/fonts.scss'; // Roboto
$fa-font-path: "~font-awesome/fonts";
@import "~font-awesome/scss/font-awesome";
@import './profile/index.scss';
@import "~@edx/frontend-component-header/src/index";
@import "~@edx/frontend-component-footer/src/lib/scss/site-footer";
.word-break-all {
word-break: break-all !important;
}
// TODO: Update edx-bootstrap theme to incorporate these edits.
.btn, a.btn {
text-decoration: none;
&:hover {
text-decoration: none;
}
}
.btn-link {
text-decoration: underline;
&:hover {
text-decoration: underline;
}
}
.profile-page-bg-banner {
height: 12rem;
background-image: url('./assets/dot-pattern-light.png');
background-repeat: repeat-x;
background-size: auto 85%;
}
.profile-page {
.edit-section-header {
@extend .h6;
display: block;
font-weight: normal;
letter-spacing: 0;
margin: 0;
}
label.edit-section-header {
margin-bottom: $spacer * .5;
}
.profile-avatar-wrap {
@include media-breakpoint-up(md) {
max-width: 12rem;
margin-right: 0;
margin-top: -8rem;
margin-bottom: 2rem;
}
}
.profile-avatar-menu-container {
background: rgba(0,0,0,.65);
position: absolute;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
border-radius: 50%;
@include media-breakpoint-up(md) {
background: linear-gradient(to top, rgba(0,0,0,.65) 4rem, rgba(0,0,0,0) 4rem);
align-items: flex-end;
}
.btn {
text-decoration: none;
@include media-breakpoint-up(md) {
margin-bottom: 1.2rem;
}
}
.dropdown {
@include media-breakpoint-up(md) {
margin-bottom: 1.2rem;
}
.btn {
color: $white;
background: transparent;
border-color: transparent;
margin: 0;
}
}
}
.profile-avatar {
width: 5rem;
height: 5rem;
position: relative;
@include media-breakpoint-up(md) {
width: 12rem;
height: 12rem;
}
.profile-avatar-edit-button {
border: none;
position: absolute;
height: 100%;
left: 0;
width: 100%;
bottom: 0;
display: flex;
justify-content: center;
padding-top: .1rem;
font-weight: 600;
background: rgba(0,0,0,.5);
border-radius:0;
transition: opacity 200ms ease;
@include media-breakpoint-up(md) {
height: 4rem;
}
&:focus, &:hover, &:active, &.active {
opacity: 1;
}
}
}
.certificate {
position: relative;
.certificate-title {
font-family: $font-family-serif;
font-weight: 400;
}
.certificate-type-illustration {
position: absolute;
top: 1rem;
right: 1rem;
bottom: 0;
width: 12rem;
opacity: .06;
background-size: 90%;
background-repeat: no-repeat;
background-position: right top;
}
.card-body {
position: relative;
}
}
}

View File

@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { sendTrackingLogEvent } from '@edx/frontend-analytics';
import { App, AppContext } from '@edx/frontend-base';
import { App, AppContext, fetchUserAccount } from '@edx/frontend-base';
import { injectIntl, intlShape } from '@edx/frontend-i18n';
import { StatusAlert, Hyperlink } from '@edx/paragon';
@@ -16,7 +16,7 @@ import {
openForm,
closeForm,
updateDraft,
} from '../actions';
} from './data/actions';
// Components
import ProfileAvatar from './forms/ProfileAvatar';
@@ -33,14 +33,14 @@ import PageLoading from './PageLoading';
import Banner from './Banner';
// Selectors
import { profilePageSelector } from '../selectors';
import { profilePageSelector } from './data/selectors';
// i18n
import messages from './ProfilePage.messages';
App.requireConfig(['CREDENTIALS_BASE_URL', 'LMS_BASE_URL'], 'ProfilePage');
export class ProfilePage extends React.Component {
class ProfilePage extends React.Component {
constructor(props, context) {
super(props, context);
@@ -58,6 +58,7 @@ export class ProfilePage extends React.Component {
}
componentDidMount() {
this.props.fetchUserAccount(this.context.authenticatedUser.username);
this.props.fetchProfile(this.props.match.params.username);
sendTrackingLogEvent('edx.profile.viewed', {
username: this.props.match.params.username,
@@ -331,6 +332,7 @@ ProfilePage.propTypes = {
photoUploadError: PropTypes.objectOf(PropTypes.string),
// Actions
fetchUserAccount: PropTypes.func.isRequired,
fetchProfile: PropTypes.func.isRequired,
saveProfile: PropTypes.func.isRequired,
saveProfilePhoto: PropTypes.func.isRequired,
@@ -370,6 +372,7 @@ ProfilePage.defaultProps = {
export default connect(
profilePageSelector,
{
fetchUserAccount,
fetchProfile,
saveProfilePhoto,
deleteProfilePhoto,

View File

@@ -7,11 +7,12 @@ import React 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 messages from '../../i18n';
import ConnectedProfilePage from './ProfilePage';
import messages from '../i18n';
import ProfilePage from './ProfilePage';
const mockStore = configureMockStore();
const mockStore = configureMockStore([thunk]);
const storeMocks = {
loadingApp: require('./__mocks__/loadingApp.mockStore.js'),
viewOwnProfile: require('./__mocks__/viewOwnProfile.mockStore.js'),
@@ -19,6 +20,7 @@ const storeMocks = {
savingEditedBio: require('./__mocks__/savingEditedBio.mockStore.js'),
};
const requiredProfilePageProps = {
fetchUserAccount: () => {},
fetchProfile: () => {},
saveProfile: () => {},
saveProfilePhoto: () => {},
@@ -33,6 +35,7 @@ Object.defineProperty(global.document, 'cookie', {
writable: true,
value: `${App.config.LANGUAGE_PREFERENCE_COOKIE_NAME}=en`,
});
App.apiClient = jest.fn();
configureI18n(App.config, messages);
@@ -49,7 +52,7 @@ describe('<ProfilePage />', () => {
>
<IntlProvider locale="en">
<Provider store={mockStore(storeMocks.loadingApp)}>
<ConnectedProfilePage {...requiredProfilePageProps} />
<ProfilePage {...requiredProfilePageProps} />
</Provider>
</IntlProvider>
</AppContext.Provider>
@@ -69,7 +72,7 @@ describe('<ProfilePage />', () => {
>
<IntlProvider locale="en">
<Provider store={mockStore(storeMocks.viewOwnProfile)}>
<ConnectedProfilePage {...requiredProfilePageProps} />
<ProfilePage {...requiredProfilePageProps} />
</Provider>
</IntlProvider>
</AppContext.Provider>
@@ -89,7 +92,7 @@ describe('<ProfilePage />', () => {
>
<IntlProvider locale="en">
<Provider store={mockStore(storeMocks.viewOtherProfile)}>
<ConnectedProfilePage
<ProfilePage
{...requiredProfilePageProps}
match={{ params: { username: 'verified' } }} // Override default match
/>
@@ -112,7 +115,7 @@ describe('<ProfilePage />', () => {
>
<IntlProvider locale="en">
<Provider store={mockStore(storeMocks.savingEditedBio)}>
<ConnectedProfilePage {...requiredProfilePageProps} />
<ProfilePage {...requiredProfilePageProps} />
</Provider>
</IntlProvider>
</AppContext.Provider>
@@ -134,7 +137,7 @@ describe('<ProfilePage />', () => {
>
<IntlProvider locale="en">
<Provider store={mockStore(storeMocks.loadingApp)}>
<ConnectedProfilePage
<ProfilePage
{...requiredProfilePageProps}
match={{ params: { username: 'test-username' } }}
/>

141
src/profile/_index.scss Normal file
View File

@@ -0,0 +1,141 @@
$fa-font-path: "~font-awesome/fonts";
@import "~font-awesome/scss/font-awesome";
.word-break-all {
word-break: break-all !important;
}
// TODO: Update edx-bootstrap theme to incorporate these edits.
.btn, a.btn {
text-decoration: none;
&:hover {
text-decoration: none;
}
}
.btn-link {
text-decoration: underline;
&:hover {
text-decoration: underline;
}
}
.profile-page-bg-banner {
height: 12rem;
background-image: url('./assets/dot-pattern-light.png');
background-repeat: repeat-x;
background-size: auto 85%;
}
.profile-page {
.edit-section-header {
@extend .h6;
display: block;
font-weight: normal;
letter-spacing: 0;
margin: 0;
}
label.edit-section-header {
margin-bottom: $spacer * .5;
}
.profile-avatar-wrap {
@include media-breakpoint-up(md) {
max-width: 12rem;
margin-right: 0;
margin-top: -8rem;
margin-bottom: 2rem;
}
}
.profile-avatar-menu-container {
background: rgba(0,0,0,.65);
position: absolute;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
border-radius: 50%;
@include media-breakpoint-up(md) {
background: linear-gradient(to top, rgba(0,0,0,.65) 4rem, rgba(0,0,0,0) 4rem);
align-items: flex-end;
}
.btn {
text-decoration: none;
@include media-breakpoint-up(md) {
margin-bottom: 1.2rem;
}
}
.dropdown {
@include media-breakpoint-up(md) {
margin-bottom: 1.2rem;
}
.btn {
color: $white;
background: transparent;
border-color: transparent;
margin: 0;
}
}
}
.profile-avatar {
width: 5rem;
height: 5rem;
position: relative;
@include media-breakpoint-up(md) {
width: 12rem;
height: 12rem;
}
.profile-avatar-edit-button {
border: none;
position: absolute;
height: 100%;
left: 0;
width: 100%;
bottom: 0;
display: flex;
justify-content: center;
padding-top: .1rem;
font-weight: 600;
background: rgba(0,0,0,.5);
border-radius:0;
transition: opacity 200ms ease;
@include media-breakpoint-up(md) {
height: 4rem;
}
&:focus, &:hover, &:active, &.active {
opacity: 1;
}
}
}
.certificate {
position: relative;
.certificate-title {
font-family: $font-family-serif;
font-weight: 400;
}
.certificate-type-illustration {
position: absolute;
top: 1rem;
right: 1rem;
bottom: 0;
width: 12rem;
opacity: .06;
background-size: 90%;
background-repeat: no-repeat;
background-position: right top;
}
.card-body {
position: relative;
}
}
}

View File

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View File

@@ -1,37 +0,0 @@
import { AppContext, fetchUserAccount } from '@edx/frontend-base';
import PropTypes from 'prop-types';
import React, { useContext, useEffect } from 'react';
import { connect } from 'react-redux';
import { Route, Switch } from 'react-router-dom';
import NotFoundPage from './NotFoundPage';
import ConnectedProfilePage from './ProfilePage';
function ProfileMain(props) {
const { authenticatedUser } = useContext(AppContext);
useEffect(() => {
props.fetchUserAccount(authenticatedUser.username);
}, [authenticatedUser.username]);
return (
<main>
<Switch>
<Route path="/u/:username" component={ConnectedProfilePage} />
<Route path="/notfound" component={NotFoundPage} />
<Route path="*" component={NotFoundPage} />
</Switch>
</main>
);
}
ProfileMain.propTypes = {
fetchUserAccount: PropTypes.func.isRequired,
};
export default connect(
null,
{
fetchUserAccount,
},
)(ProfileMain);

View File

@@ -13,7 +13,7 @@ import EmptyContent from './elements/EmptyContent';
import SwitchContent from './elements/SwitchContent';
// Selectors
import { editableFormSelector } from '../../selectors';
import { editableFormSelector } from '../data/selectors';
class Bio extends React.Component {
constructor(props) {

View File

@@ -13,11 +13,11 @@ import EditableItemHeader from './elements/EditableItemHeader';
import SwitchContent from './elements/SwitchContent';
// Assets
import professionalCertificateSVG from '../../assets/professional-certificate.svg';
import verifiedCertificateSVG from '../../assets/verified-certificate.svg';
import professionalCertificateSVG from '../assets/professional-certificate.svg';
import verifiedCertificateSVG from '../assets/verified-certificate.svg';
// Selectors
import { certificatesSelector } from '../../selectors';
import { certificatesSelector } from '../data/selectors';
class Certificates extends React.Component {
constructor(props) {

View File

@@ -13,7 +13,7 @@ import EmptyContent from './elements/EmptyContent';
import SwitchContent from './elements/SwitchContent';
// Selectors
import { countrySelector } from '../../selectors';
import { countrySelector } from '../data/selectors';
class Country extends React.Component {
constructor(props) {

View File

@@ -14,10 +14,10 @@ import EmptyContent from './elements/EmptyContent';
import SwitchContent from './elements/SwitchContent';
// Constants
import { EDUCATION_LEVELS } from '../../constants';
import { EDUCATION_LEVELS } from '../data/constants';
// Selectors
import { editableFormSelector } from '../../selectors';
import { editableFormSelector } from '../data/selectors';
class Education extends React.Component {
constructor(props) {

View File

@@ -12,7 +12,7 @@ import EmptyContent from './elements/EmptyContent';
import SwitchContent from './elements/SwitchContent';
// Selectors
import { editableFormSelector } from '../../selectors';
import { editableFormSelector } from '../data/selectors';
class Name extends React.Component {
constructor(props) {

View File

@@ -13,7 +13,7 @@ import EmptyContent from './elements/EmptyContent';
import SwitchContent from './elements/SwitchContent';
// Selectors
import { preferredLanguageSelector } from '../../selectors';
import { preferredLanguageSelector } from '../data/selectors';
class PreferredLanguage extends React.Component {
constructor(props) {

View File

@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import { Button, Dropdown } from '@edx/paragon';
import { FormattedMessage, injectIntl, intlShape } from '@edx/frontend-i18n';
import { ReactComponent as DefaultAvatar } from '../../assets/avatar.svg';
import { ReactComponent as DefaultAvatar } from '../assets/avatar.svg';
import messages from './ProfileAvatar.messages';

View File

@@ -16,7 +16,7 @@ import EmptyContent from './elements/EmptyContent';
import SwitchContent from './elements/SwitchContent';
// Selectors
import { editableFormSelector } from '../../selectors';
import { editableFormSelector } from '../data/selectors';
const platformDisplayInfo = {
facebook: {

View File

@@ -1,9 +1,5 @@
import profileReducer from './reducers';
import profileSaga from './sagas';
import ConnectedProfilePage from './components/ProfilePage';
export {
ConnectedProfilePage,
profileReducer,
profileSaga,
};
export { default as reducer } from './data/reducers';
export { default as saga } from './data/sagas';
export { default as ProfilePage } from './ProfilePage';
export { default as NotFoundPage } from './NotFoundPage';
export { default as messages } from './ProfilePage.messages';

View File

@@ -1,7 +1,7 @@
import { combineReducers } from 'redux';
import { userAccount } from '@edx/frontend-auth';
import { profileReducer } from './profile';
import { reducer as profileReducer } from './profile';
const createRootReducer = () =>
combineReducers({

View File

@@ -1,6 +1,6 @@
import { all } from 'redux-saga/effects';
import { profileSaga } from './profile';
import { saga as profileSaga } from './profile';
export default function* rootSaga() {
yield all([

View File

@@ -55,6 +55,9 @@ module.exports = Merge.smart(commonConfig, {
plugins: () => [PostCssRtlPlugin()],
},
},
{
loader: 'resolve-url-loader',
},
{
loader: 'sass-loader', // compiles Sass to CSS
options: {

View File

@@ -67,11 +67,14 @@ module.exports = Merge.smart(commonConfig, {
options: {
plugins: () => [
PostCssRtlPlugin(),
PostCssAutoprefixerPlugin({ grid: true, browsers: ['>1%'] }),
PostCssAutoprefixerPlugin({ grid: true }),
CssNano(),
],
},
},
{
loader: 'resolve-url-loader',
},
{
loader: 'sass-loader', // compiles Sass to CSS
options: {