Miscellaneous updates to the boilerplate code. (#161)

Based on changes/things I noticed when putting together the frontend-app-account repository.
This commit is contained in:
David Joy
2019-04-23 15:52:32 -04:00
committed by GitHub
parent 9eeb61cef8
commit 3f411f3795
13 changed files with 161 additions and 54 deletions

2
.gitignore vendored
View File

@@ -12,3 +12,5 @@ dist/
### Emacs ###
*~
/.vscode
/temp

View File

@@ -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

77
package-lock.json generated
View File

@@ -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
}
}
},

View File

@@ -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",

View File

@@ -1,18 +1,37 @@
import React from 'react';
import React, { Component } from 'react';
import PropTypes from 'prop-types';
function PageLoading() {
return (
<div>
<div
className="d-flex justify-content-center align-items-center flex-column"
style={{
height: '50vh',
}}
>
<div className="spinner-border text-primary" role="status" />
export default class PageLoading extends Component {
renderSrMessage() {
if (!this.props.srMessage) {
return null;
}
return (
<span className="sr-only">
{this.props.srMessage}
</span>
);
}
render() {
return (
<div>
<div
className="d-flex justify-content-center align-items-center flex-column"
style={{
height: '50vh',
}}
>
<div className="spinner-border text-primary" role="status">
{this.renderSrMessage()}
</div>
</div>
</div>
</div>
);
);
}
}
export default PageLoading;
PageLoading.propTypes = {
srMessage: PropTypes.string.isRequired,
};

View File

@@ -28,7 +28,7 @@ function PageContent({
intl,
}) {
if (!ready) {
return <PageLoading />;
return <PageLoading srMessage={intl.formatMessage(messages['app.loading.message'])} />;
}
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']),
},
{

View File

@@ -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;

View File

@@ -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..."
}

View File

@@ -151,7 +151,7 @@ export class ProfilePage extends React.Component {
} = this.props;
if (isLoadingProfile) {
return <PageLoading />;
return <PageLoading srMessage={this.props.intl.formatMessage(messages['profile.loading'])} />;
}
const commonFormProps = {

View File

@@ -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;

View File

@@ -19,7 +19,13 @@ exports[`<ProfilePage /> Renders correctly in various states app loading 1`] = `
<div
className="spinner-border text-primary"
role="status"
/>
>
<span
className="sr-only"
>
Profile loading...
</span>
</div>
</div>
</div>
</div>

View File

@@ -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',

View File

@@ -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,