Compare commits
1 Commits
open-relea
...
douglashal
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
66d647f381 |
110
package-lock.json
generated
110
package-lock.json
generated
@@ -2875,6 +2875,21 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"@babel/runtime": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.2.0.tgz",
|
||||
"integrity": "sha512-oouEibCbHMVdZSDlJBO6bZmID/zA/G/Qx3H1d3rSNPTD+L8UNKvCat7aKWSJ74zYbm5zWGh0GQN0hKj8zYFTCg==",
|
||||
"requires": {
|
||||
"regenerator-runtime": "0.12.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"regenerator-runtime": {
|
||||
"version": "0.12.1",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz",
|
||||
"integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@babel/template": {
|
||||
"version": "7.0.0-beta.40",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.40.tgz",
|
||||
@@ -2965,9 +2980,9 @@
|
||||
}
|
||||
},
|
||||
"@edx/frontend-auth": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@edx/frontend-auth/-/frontend-auth-1.2.1.tgz",
|
||||
"integrity": "sha512-NEc+rAJq5HJ9UACPirezpwTp5yhX9G2AQDPfk1hW4ceEF7BFRMIfzb+nJqmTJkEX/37yRVYUfQFLW+z2j1ZRcw==",
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@edx/frontend-auth/-/frontend-auth-1.3.0.tgz",
|
||||
"integrity": "sha512-llAoGBvxwZCnGzUMFSHHMxGIrrYLuWlEmrSQs6rqdqT5RXHUkuwNde5iemohqGe/dLGcGjiNzUjr83iGUlN66Q==",
|
||||
"requires": {
|
||||
"axios": "^0.18.0",
|
||||
"jwt-decode": "^2.2.0",
|
||||
@@ -7968,6 +7983,14 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"dom-helpers": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz",
|
||||
"integrity": "sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==",
|
||||
"requires": {
|
||||
"@babel/runtime": "7.2.0"
|
||||
}
|
||||
},
|
||||
"dom-serializer": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz",
|
||||
@@ -13793,6 +13816,16 @@
|
||||
"integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=",
|
||||
"dev": true
|
||||
},
|
||||
"lodash.isfunction": {
|
||||
"version": "3.0.9",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz",
|
||||
"integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw=="
|
||||
},
|
||||
"lodash.isobject": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz",
|
||||
"integrity": "sha1-PI+41bW/S/kK4G4U8qUwpO2TXh0="
|
||||
},
|
||||
"lodash.isplainobject": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
|
||||
@@ -13856,6 +13889,11 @@
|
||||
"integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=",
|
||||
"dev": true
|
||||
},
|
||||
"lodash.tonumber": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/lodash.tonumber/-/lodash.tonumber-4.0.3.tgz",
|
||||
"integrity": "sha1-C5azGzVnJ5Prf1pj7nkfG56QJdk="
|
||||
},
|
||||
"lodash.uniq": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
|
||||
@@ -20129,6 +20167,27 @@
|
||||
"integrity": "sha512-FlsPxavEyMuR6TjVbSSywovXSEyOg6ZDj5+Z8nbsRl9EkOzAhEIcS+GLoQDC5fz/t9suhUXWmUrOBrgeUvrMxw==",
|
||||
"dev": true
|
||||
},
|
||||
"react-lifecycles-compat": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
|
||||
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
|
||||
},
|
||||
"react-popper": {
|
||||
"version": "0.10.4",
|
||||
"resolved": "https://registry.npmjs.org/react-popper/-/react-popper-0.10.4.tgz",
|
||||
"integrity": "sha1-rypBXqIike3VBGeNev2opu4ylao=",
|
||||
"requires": {
|
||||
"popper.js": "1.14.6",
|
||||
"prop-types": "15.6.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"popper.js": {
|
||||
"version": "1.14.6",
|
||||
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.14.6.tgz",
|
||||
"integrity": "sha512-AGwHGQBKumlk/MDfrSOf0JHhJCImdDMcGNoqKmKkU+68GFazv3CQ6q9r7Ja1sKDZmYWTckY/uLyEznheTDycnA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"react-proptype-conditional-require": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/react-proptype-conditional-require/-/react-proptype-conditional-require-1.0.4.tgz",
|
||||
@@ -20217,6 +20276,51 @@
|
||||
"prop-types": "^15.6.0"
|
||||
}
|
||||
},
|
||||
"react-transition-group": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.5.1.tgz",
|
||||
"integrity": "sha512-8x/CxUL9SjYFmUdzsBPTgtKeCxt7QArjNSte0wwiLtF/Ix/o1nWNJooNy5o9XbHIKS31pz7J5VF2l41TwlvbHQ==",
|
||||
"requires": {
|
||||
"dom-helpers": "3.4.0",
|
||||
"loose-envify": "1.4.0",
|
||||
"prop-types": "15.6.2",
|
||||
"react-lifecycles-compat": "3.0.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"loose-envify": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
|
||||
"requires": {
|
||||
"js-tokens": "3.0.2"
|
||||
}
|
||||
},
|
||||
"prop-types": {
|
||||
"version": "15.6.2",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz",
|
||||
"integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==",
|
||||
"requires": {
|
||||
"loose-envify": "1.4.0",
|
||||
"object-assign": "4.1.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"reactstrap": {
|
||||
"version": "6.5.0",
|
||||
"resolved": "https://registry.npmjs.org/reactstrap/-/reactstrap-6.5.0.tgz",
|
||||
"integrity": "sha512-dWb3fB/wBAiQloteKlf+j9Nl2VLe6BMZgTEt6hpeTt0t9TwtkeU+2v2NBYONZaF4FZATfMiIKozhWpc2HmLW1g==",
|
||||
"requires": {
|
||||
"classnames": "2.2.5",
|
||||
"lodash.isfunction": "3.0.9",
|
||||
"lodash.isobject": "3.0.2",
|
||||
"lodash.tonumber": "4.0.3",
|
||||
"prop-types": "15.6.1",
|
||||
"react-lifecycles-compat": "3.0.4",
|
||||
"react-popper": "0.10.4",
|
||||
"react-transition-group": "2.5.1"
|
||||
}
|
||||
},
|
||||
"read-pkg": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@edx/edx-bootstrap": "^0.4.3",
|
||||
"@edx/frontend-auth": "^1.2.1",
|
||||
"@edx/frontend-auth": "^1.3.0",
|
||||
"@edx/paragon": "^3.7.2",
|
||||
"babel-polyfill": "^6.26.0",
|
||||
"classnames": "^2.2.5",
|
||||
@@ -40,6 +40,7 @@
|
||||
"react-router": "^4.2.0",
|
||||
"react-router-dom": "^4.2.2",
|
||||
"react-router-redux": "^5.0.0-alpha.9",
|
||||
"reactstrap": "^6.5.0",
|
||||
"redux": "^3.7.2",
|
||||
"redux-devtools-extension": "^2.13.2",
|
||||
"redux-logger": "^3.0.6",
|
||||
|
||||
@@ -1,30 +1,94 @@
|
||||
import React from 'react';
|
||||
import { Hyperlink } from '@edx/paragon';
|
||||
import {
|
||||
Collapse,
|
||||
Navbar,
|
||||
NavbarToggler,
|
||||
NavbarBrand,
|
||||
Nav,
|
||||
NavItem,
|
||||
NavLink,
|
||||
UncontrolledDropdown,
|
||||
DropdownToggle,
|
||||
DropdownMenu,
|
||||
DropdownItem,
|
||||
} from 'reactstrap';
|
||||
import { Icon } from '@edx/paragon';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import apiClient from '../../data/apiClient';
|
||||
import { configuration } from '../../config';
|
||||
import EdxLogo from '../../../assets/edx-sm.png';
|
||||
|
||||
export default class Header extends React.Component {
|
||||
class Header extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.toggle = this.toggle.bind(this);
|
||||
this.state = {
|
||||
mobileNavOpen: false,
|
||||
};
|
||||
}
|
||||
|
||||
renderLogo() {
|
||||
return (
|
||||
<img src={EdxLogo} alt="edX logo" height="30" width="60" />
|
||||
);
|
||||
toggle() {
|
||||
this.setState({
|
||||
mobileNavOpen: !this.state.mobileNavOpen,
|
||||
});
|
||||
}
|
||||
|
||||
getUserProfileImageIcon() {
|
||||
const screenReaderText = `Profile image for ${this.props.username}`;
|
||||
|
||||
if (this.props.userProfileImageUrl) {
|
||||
return <img src={this.props.userProfileImageUrl} alt={screenReaderText} />;
|
||||
}
|
||||
return <Icon className={['fa', 'fa-user', 'px-3']} screenReaderText={screenReaderText} />;
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="mb-3">
|
||||
<header className="d-flex justify-content-center align-items-center p-3 border-bottom-blue">
|
||||
<Hyperlink content={this.renderLogo()} destination="https://www.edx.org" />
|
||||
<div />
|
||||
</header>
|
||||
</div>
|
||||
<Navbar light expand="md" className="border-bottom">
|
||||
<NavbarBrand href={configuration.LMS_BASE_URL}>
|
||||
<img src={EdxLogo} alt="edX logo" height="30" width="60" />
|
||||
</NavbarBrand>
|
||||
<NavbarToggler onClick={this.toggle} />
|
||||
<Collapse isOpen={this.state.mobileNavOpen} navbar>
|
||||
<Nav className="ml-auto" navbar>
|
||||
<UncontrolledDropdown nav inNavbar>
|
||||
<DropdownToggle nav caret>
|
||||
{this.getUserProfileImageIcon()}
|
||||
{this.props.username}
|
||||
</DropdownToggle>
|
||||
<DropdownMenu right>
|
||||
<DropdownItem href={`${configuration.LMS_BASE_URL}/dashboard`}>
|
||||
Dashboard
|
||||
</DropdownItem>
|
||||
<DropdownItem href={`${configuration.LMS_BASE_URL}/u/${this.props.username}`}>
|
||||
Profile
|
||||
</DropdownItem>
|
||||
<DropdownItem href={`${configuration.LMS_BASE_URL}/account/settings`}>
|
||||
Account
|
||||
</DropdownItem>
|
||||
<DropdownItem divider />
|
||||
<DropdownItem onClick={() => apiClient.logout()}>
|
||||
Logout
|
||||
</DropdownItem>
|
||||
</DropdownMenu>
|
||||
</UncontrolledDropdown>
|
||||
</Nav>
|
||||
</Collapse>
|
||||
</Navbar>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Header.defaultProps = {
|
||||
username: null,
|
||||
userProfileImageUrl: null,
|
||||
};
|
||||
|
||||
Header.propTypes = {
|
||||
username: PropTypes.string,
|
||||
userProfileImageUrl: PropTypes.string,
|
||||
};
|
||||
|
||||
export default Header;
|
||||
|
||||
11
src/containers/Header/index.jsx
Normal file
11
src/containers/Header/index.jsx
Normal file
@@ -0,0 +1,11 @@
|
||||
import { connect } from 'react-redux';
|
||||
import { fetchUserProfile } from '@edx/frontend-auth';
|
||||
|
||||
import Header from '../../components/Header';
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
username: state.userProfile.username,
|
||||
userProfileImageUrl: state.userProfile.userProfileImageUrl,
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(Header);
|
||||
@@ -4,6 +4,7 @@ import { configuration } from '../config';
|
||||
|
||||
const apiClient = getAuthenticatedAPIClient({
|
||||
appBaseUrl: configuration.BASE_URL,
|
||||
authBaseUrl: configuration.LMS_BASE_URL,
|
||||
loginUrl: configuration.LOGIN_URL,
|
||||
logoutUrl: configuration.LOGOUT_URL,
|
||||
csrfTokenApiPath: process.env.CSRF_TOKEN_API_PATH,
|
||||
|
||||
@@ -1,11 +1,21 @@
|
||||
import { combineReducers } from 'redux';
|
||||
import { userProfile } from '@edx/frontend-auth';
|
||||
|
||||
import cohorts from './cohorts';
|
||||
import grades from './grades';
|
||||
import tracks from './tracks';
|
||||
import assignmentTypes from './assignmentTypes';
|
||||
|
||||
const identityReducer = (state) => {
|
||||
const newState = { ...state };
|
||||
return newState;
|
||||
};
|
||||
|
||||
const rootReducer = combineReducers({
|
||||
// The authentication state is added as initialState when
|
||||
// creating the store in data/store.js.
|
||||
authentication: identityReducer,
|
||||
userProfile,
|
||||
grades,
|
||||
cohorts,
|
||||
tracks,
|
||||
|
||||
@@ -3,12 +3,15 @@ import thunkMiddleware from 'redux-thunk';
|
||||
import { composeWithDevTools } from 'redux-devtools-extension/logOnlyInProduction';
|
||||
import { createLogger } from 'redux-logger';
|
||||
|
||||
import apiClient from './apiClient';
|
||||
import reducers from './reducers';
|
||||
|
||||
const loggerMiddleware = createLogger();
|
||||
const initialState = apiClient.getAuthenticationState();
|
||||
|
||||
const store = createStore(
|
||||
reducers,
|
||||
initialState,
|
||||
composeWithDevTools(applyMiddleware(thunkMiddleware, loggerMiddleware)),
|
||||
);
|
||||
|
||||
|
||||
@@ -3,29 +3,37 @@ import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
|
||||
import { Provider } from 'react-redux';
|
||||
import { fetchUserProfile } from '@edx/frontend-auth';
|
||||
|
||||
import apiClient from './data/apiClient';
|
||||
import Footer from './components/Gradebook/footer';
|
||||
import GradebookPage from './containers/GradebookPage';
|
||||
import Header from './components/Header';
|
||||
import Header from './containers/Header';
|
||||
import store from './data/store';
|
||||
import './App.scss';
|
||||
|
||||
const App = () => (
|
||||
<Provider store={store}>
|
||||
<Router>
|
||||
<div>
|
||||
<Header />
|
||||
<main>
|
||||
<Switch>
|
||||
<Route exact path="/:courseId" component={GradebookPage} />
|
||||
</Switch>
|
||||
</main>
|
||||
<Footer />
|
||||
</div>
|
||||
</Router>
|
||||
</Provider>
|
||||
);
|
||||
class App extends React.Component {
|
||||
componentDidMount() {
|
||||
const username = store.getState().authentication.username;
|
||||
store.dispatch(fetchUserProfile(apiClient, username));
|
||||
}
|
||||
|
||||
render() {
|
||||
return <Provider store={store}>
|
||||
<Router>
|
||||
<div>
|
||||
<Header />
|
||||
<main>
|
||||
<Switch>
|
||||
<Route exact path="/:courseId" component={GradebookPage} />
|
||||
</Switch>
|
||||
</main>
|
||||
<Footer />
|
||||
</div>
|
||||
</Router>
|
||||
</Provider>;
|
||||
}
|
||||
}
|
||||
|
||||
if (apiClient.ensurePublicOrAuthencationAndCookies(window.location.pathname)) {
|
||||
ReactDOM.render(<App />, document.getElementById('root'));
|
||||
|
||||
Reference in New Issue
Block a user