diff --git a/.gitignore b/.gitignore index 3f1af3a..a7dbb22 100755 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,5 @@ dist/ ### Emacs ### *~ +/.vscode +/temp diff --git a/docs/decisions/0001-record-architecture-decisions.rst b/docs/decisions/0001-record-architecture-decisions.rst new file mode 100644 index 0000000..0ab9ab4 --- /dev/null +++ b/docs/decisions/0001-record-architecture-decisions.rst @@ -0,0 +1,32 @@ +1. Record Architecture Decisions +-------------------------------- + +Status +------ + +Accepted + +Context +------- + +We would like to keep a historical record on the architectural +decisions we make with this app as it evolves over time. + +Decision +-------- + +We will use Architecture Decision Records, as described by +Michael Nygard in `Documenting Architecture Decisions`_ + +.. _Documenting Architecture Decisions: http://thinkrelevance.com/blog/2011/11/15/documenting-architecture-decisions + +Consequences +------------ + +See Michael Nygard's article, linked above. + +References +---------- + +* https://resources.sei.cmu.edu/asset_files/Presentation/2017_017_001_497746.pdf +* https://github.com/npryce/adr-tools/tree/master/doc/adr diff --git a/package-lock.json b/package-lock.json index fc20fbb..0af1e21 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2570,18 +2570,11 @@ "integrity": "sha512-APBpZvdQrC1MJWMzk33V7FR2RhBRtnH2QPLqZzS+qia7PixwgWNlnX7UfHjhx+YWkM53GdsZKs40EBkSwADuMA==" }, "@edx/edx-bootstrap": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@edx/edx-bootstrap/-/edx-bootstrap-2.0.0.tgz", - "integrity": "sha512-2wuEqzLNQDxX46+rr6HHsFAEuXiAGHHCMEavjlgBDStX4mLIYJrey3vi6oOmN/qvlIFQEM17GDihrFPq46wPgQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@edx/edx-bootstrap/-/edx-bootstrap-2.0.1.tgz", + "integrity": "sha512-tq9ScRJBkUYw+0ypTshd+9+9Hnow00FkS6Rvh0RfK4xZ+rh8wNAUIVkG3TMclaW5qxvXSIE7Qo7YO7i7JrqV6A==", "requires": { "bootstrap": "^4.3.1" - }, - "dependencies": { - "bootstrap": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.3.1.tgz", - "integrity": "sha512-rXqOmH1VilAt2DyPzluTi2blhk17bO7ef+zLLPlWvG494pDxcM234pJ8wTc/6R40UWizAIIMgxjvxZg5kmsbag==" - } } }, "@edx/frontend-analytics": { @@ -2639,9 +2632,9 @@ "integrity": "sha512-1djcoIfT2rqqnGDTBPwuQOekgtKyk9lwriKAC2oFJeqvDhmMmqSnWUTEJde4/UiZbV7zhEMJ6GPnF9LH5bsadg==" }, "@edx/paragon": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@edx/paragon/-/paragon-4.1.2.tgz", - "integrity": "sha512-0OQkclsrocwvokqIsXFZWSkcyzeF9FaT2zo9/Wb2DpbePOoy9axnnBvaU2GUCdOdGiJTM885OJT8ywCOvnUVBg==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@edx/paragon/-/paragon-4.1.4.tgz", + "integrity": "sha512-IucQ5a8vp5Qg7A9xP8hvOb1ywTw7n4wSW9CkRDVTs7mJnbD0pPJeskkhF91GlJEtFi8tXLbjRJslNU+9qKgF4A==", "requires": { "airbnb-prop-types": "^2.12.0", "classnames": "^2.2.6", @@ -3983,9 +3976,9 @@ "dev": true }, "node-releases": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.15.tgz", - "integrity": "sha512-cKV097BQaZr8LTSRUa2+oc/aX5L8UkZtPQrMSTgiJEeaW7ymTDCoRaGCoaTqk0lqnalcoSHu4wjSl0Cmj2+bMw==", + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.16.tgz", + "integrity": "sha512-BOMWCW9CaT4sffMa5S9Mj4vYObvVShyo6JoM9WzzQOKVyNUn1+OVMUaQT3fo2tJKCMwHjqaDW/Pf3/JsYmPD2g==", "dev": true, "requires": { "semver": "^5.3.0" @@ -6396,6 +6389,11 @@ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" }, + "bootstrap": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.3.1.tgz", + "integrity": "sha512-rXqOmH1VilAt2DyPzluTi2blhk17bO7ef+zLLPlWvG494pDxcM234pJ8wTc/6R40UWizAIIMgxjvxZg5kmsbag==" + }, "boxen": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", @@ -7878,9 +7876,9 @@ "dev": true }, "node-releases": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.15.tgz", - "integrity": "sha512-cKV097BQaZr8LTSRUa2+oc/aX5L8UkZtPQrMSTgiJEeaW7ymTDCoRaGCoaTqk0lqnalcoSHu4wjSl0Cmj2+bMw==", + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.16.tgz", + "integrity": "sha512-BOMWCW9CaT4sffMa5S9Mj4vYObvVShyo6JoM9WzzQOKVyNUn1+OVMUaQT3fo2tJKCMwHjqaDW/Pf3/JsYmPD2g==", "dev": true, "requires": { "semver": "^5.3.0" @@ -11382,7 +11380,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -11403,12 +11402,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -11423,17 +11424,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -11550,7 +11554,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -11562,6 +11567,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -11576,6 +11582,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -11583,12 +11590,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -11607,6 +11616,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -11687,7 +11697,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -11699,6 +11710,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -11784,7 +11796,8 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -11820,6 +11833,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -11839,6 +11853,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -11882,12 +11897,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, diff --git a/package.json b/package.json index a8d220a..c5b7d6e 100755 --- a/package.json +++ b/package.json @@ -25,13 +25,13 @@ }, "dependencies": { "@cospired/i18n-iso-languages": "^2.0.2", - "@edx/edx-bootstrap": "^2.0.0", + "@edx/edx-bootstrap": "^2.0.1", "@edx/frontend-analytics": "^1.0.0", "@edx/frontend-auth": "^4.0.0", "@edx/frontend-component-footer": "^2.0.3", "@edx/frontend-component-site-header": "^2.1.4", "@edx/frontend-logging": "^1.0.2", - "@edx/paragon": "^4.1.2", + "@edx/paragon": "^4.1.3", "@fortawesome/fontawesome-svg-core": "^1.2.14", "@fortawesome/free-brands-svg-icons": "^5.7.2", "@fortawesome/free-regular-svg-icons": "^5.7.1", diff --git a/src/common/components/PageLoading.jsx b/src/common/components/PageLoading.jsx index 9e5fa89..1b1135d 100644 --- a/src/common/components/PageLoading.jsx +++ b/src/common/components/PageLoading.jsx @@ -1,18 +1,37 @@ -import React from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; -function PageLoading() { - return ( -
-
-
+export default class PageLoading extends Component { + renderSrMessage() { + if (!this.props.srMessage) { + return null; + } + + return ( + + {this.props.srMessage} + + ); + } + + render() { + return ( +
+
+
+ {this.renderSrMessage()} +
+
-
- ); + ); + } } -export default PageLoading; +PageLoading.propTypes = { + srMessage: PropTypes.string.isRequired, +}; diff --git a/src/components/App.jsx b/src/components/App.jsx index 593e70a..e951883 100644 --- a/src/components/App.jsx +++ b/src/components/App.jsx @@ -28,7 +28,7 @@ function PageContent({ intl, }) { if (!ready) { - return ; + return ; } const mainMenu = [ @@ -56,7 +56,7 @@ function PageContent({ }, { type: 'item', - href: `${process.env.BASE_URL}/u/${username}`, + href: `${process.env.LMS_BASE_URL}/u/${username}`, content: intl.formatMessage(messages['siteheader.user.menu.profile']), }, { diff --git a/src/components/App.messages.jsx b/src/components/App.messages.jsx index 995fd1b..ba110a3 100644 --- a/src/components/App.messages.jsx +++ b/src/components/App.messages.jsx @@ -46,6 +46,11 @@ const messages = defineMessages({ defaultMessage: 'Sign Up', description: 'Link to registration', }, + 'app.loading.message': { + id: 'app.loading.message', + defaultMessage: 'Loading', + description: 'Message shown when page content is loading.', + }, }); export default messages; diff --git a/src/i18n/transifex_input.json b/src/i18n/transifex_input.json index 62081a3..7cbdf0e 100644 --- a/src/i18n/transifex_input.json +++ b/src/i18n/transifex_input.json @@ -8,21 +8,37 @@ "siteheader.user.menu.logout": "Logout", "siteheader.user.menu.login": "Login", "siteheader.user.menu.register": "Sign Up", + "app.loading.message": "Loading", + "profile.error.message.text": "An unexpected error occurred. Please click the button below to return to your profile and try again.", + "profile.error.button.text": "Return to Your Profile", "profile.notfound.message": "The page you're looking for is unavailable or there's an error in the URL. Please check the URL and try again.", "profile.age.headline": "Your profile cannot be shared.", "profile.age.details": "To share your profile with other edX learners, you must confirm that you are over the age of 13.", "profile.age.set.date": "Set your date of birth", + "profile.datejoined.member.since": "Member since {year}", "profile.bio.empty": "Add a short bio", "profile.bio.about.me": "About Me", "profile.certificate.organization.label": "From", + "profile.certificate.completion.date.label": "Completed on {date}", "profile.no.certificates": "You don't have any certificates yet.", "profile.certificates.my.certificates": "My Certificates", "profile.certificates.view.certificate": "View Certificate", + "profile.certificates.types.verified": "Verified Certificate", + "profile.certificates.types.professional": "Professional Certificate", + "profile.certificates.types.unknown": "Certificate", "profile.country.label": "Location", "profile.country.empty": "Add location", - "profile.datejoined.member.since": "Member since {year}", "profile.education.empty": "Add education", "profile.education.education": "Education", + "profile.education.levels.p": "Doctorate", + "profile.education.levels.m": "Master's or professional degree", + "profile.education.levels.b": "Bachelor's Degree", + "profile.education.levels.a": "Associate's degree", + "profile.education.levels.hs": "Secondary/high school", + "profile.education.levels.jhs": "Junior secondary/junior high/middle school", + "profile.education.levels.el": "Elementary/primary school", + "profile.education.levels.none": "No formal education", + "profile.education.levels.o": "Other education", "profile.editbutton.edit": "Edit", "profile.formcontrols.who.can.see": "Who can see this:", "profile.formcontrols.button.cancel": "Cancel", @@ -31,14 +47,17 @@ "profile.formcontrols.button.saved": "Saved", "profile.visibility.who.just.me": "Just me", "profile.visibility.who.everyone": "Everyone on edX", + "profile.name.full.name": "Full Name", "profile.name.details": "This is the name that appears in your account and on your certificates.", "profile.name.empty": "Add name", - "profile.name.full.name": "Full Name", - "profile.preferredlanguage.label": "Language", "profile.preferredlanguage.empty": "Add language", + "profile.preferredlanguage.label": "Primary Language Spoken", "profile.profileavatar.upload-button": "Upload Photo", "profile.profileavatar.change-button": "Change", "profile.profileavatar.remove.button": "Remove", + "profile.image.alt.attribute": "profile avatar", "profile.sociallinks.add": "Add {network}", - "profile.sociallinks.social.links": "Social Links" + "profile.sociallinks.social.links": "Social Links", + "profile.viewMyRecords": "View My Records", + "profile.loading": "Profile loading..." } \ No newline at end of file diff --git a/src/profile/components/ProfilePage.jsx b/src/profile/components/ProfilePage.jsx index ebb5307..b8f7ced 100644 --- a/src/profile/components/ProfilePage.jsx +++ b/src/profile/components/ProfilePage.jsx @@ -151,7 +151,7 @@ export class ProfilePage extends React.Component { } = this.props; if (isLoadingProfile) { - return ; + return ; } const commonFormProps = { diff --git a/src/profile/components/ProfilePage.messages.jsx b/src/profile/components/ProfilePage.messages.jsx index a409c2b..9a70556 100644 --- a/src/profile/components/ProfilePage.messages.jsx +++ b/src/profile/components/ProfilePage.messages.jsx @@ -6,6 +6,11 @@ const messages = defineMessages({ defaultMessage: 'View My Records', description: 'A link to go view my academic records', }, + 'profile.loading': { + id: 'profile.loading', + defaultMessage: 'Profile loading...', + description: 'Message displayed when the profile data is loading.', + }, }); export default messages; diff --git a/src/profile/components/__snapshots__/ProfilePage.test.jsx.snap b/src/profile/components/__snapshots__/ProfilePage.test.jsx.snap index 538a99d..093753b 100644 --- a/src/profile/components/__snapshots__/ProfilePage.test.jsx.snap +++ b/src/profile/components/__snapshots__/ProfilePage.test.jsx.snap @@ -19,7 +19,13 @@ exports[` Renders correctly in various states app loading 1`] = `
+ > + + Profile loading... + +
diff --git a/webpack/webpack.dev.config.js b/webpack/webpack.dev.config.js index 4fe7b9d..2eaffcd 100755 --- a/webpack/webpack.dev.config.js +++ b/webpack/webpack.dev.config.js @@ -109,6 +109,7 @@ module.exports = Merge.smart(commonConfig, { BASE_URL: 'localhost:1995', LMS_BASE_URL: 'http://localhost:18000', CREDENTIALS_BASE_URL: 'http://localhost:18150', + ECOMMERCE_BASE_URL: 'http://localhost:18130', LOGIN_URL: 'http://localhost:18000/login', LOGOUT_URL: 'http://localhost:18000/login', CSRF_TOKEN_API_PATH: '/csrf/api/v1/token', diff --git a/webpack/webpack.prod.config.js b/webpack/webpack.prod.config.js index 6569af6..8b18e39 100755 --- a/webpack/webpack.prod.config.js +++ b/webpack/webpack.prod.config.js @@ -134,6 +134,7 @@ module.exports = Merge.smart(commonConfig, { BASE_URL: null, LMS_BASE_URL: null, CREDENTIALS_BASE_URL: null, + ECOMMERCE_BASE_URL: null, LOGIN_URL: null, LOGOUT_URL: null, CSRF_TOKEN_API_PATH: null,