update to current npm versions (React 18, BS5, etc.)
This commit is contained in:
parent
5555adff24
commit
be04f7d339
21
react-app/.gitignore
vendored
21
react-app/.gitignore
vendored
@ -1,21 +1,2 @@
|
||||
# See https://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.gitignore
|
||||
|
35898
react-app/package-lock.json
generated
35898
react-app/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -3,22 +3,23 @@
|
||||
"version": "0.2.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"bootstrap": "^4.6.1",
|
||||
"bootstrap": "^5.1.3",
|
||||
"formik": "^2.2.9",
|
||||
"prop-types": "^15.7.2",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-player": "^2.9.0",
|
||||
"react-redux": "^7.2.6",
|
||||
"react-router-dom": "^5.2.1",
|
||||
"reactstrap": "^8.10.1",
|
||||
"prop-types": "^15.8.1",
|
||||
"react": "^18.0.0",
|
||||
"react-dom": "^18.0.0",
|
||||
"react-player": "^2.10.0",
|
||||
"react-redux": "^8.0.0",
|
||||
"react-router": "^6.3.0",
|
||||
"react-router-dom": "^6.3.0",
|
||||
"reactstrap": "^9.0.2",
|
||||
"redux": "^4.1.2",
|
||||
"redux-thunk": "^2.4.0",
|
||||
"superagent": "^6.1.0",
|
||||
"superagent": "^7.1.2",
|
||||
"toastr": "^2.1.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"react-scripts": "4.0.3"
|
||||
"react-scripts": "^5.0.1"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
|
@ -1,7 +1,11 @@
|
||||
|
||||
https://reacttraining.com/react-router/web/guides/redux-integration
|
||||
|
||||
Updated Spring 2020 to React 16.13.1 and react-redux 7.2.0
|
||||
|
||||
Updated Spring 2021 to React 17.0.2 and latest version of all other packages.
|
||||
- added support for video player
|
||||
|
||||
Updated Spring 2022 to React 18.0.0 and latest version of all other packages.
|
||||
- updated bootstrap to BS5 and react-router v6
|
||||
|
||||
https://reacttraining.com/react-router/web/guides/redux-integration
|
||||
|
||||
|
5
react-app/src/components/Logout.js
vendored
5
react-app/src/components/Logout.js
vendored
@ -1,14 +1,15 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { Redirect } from 'react-router-dom';
|
||||
import { Navigate } from 'react-router-dom';
|
||||
import store from '../store';
|
||||
|
||||
const Logout = () => {
|
||||
// normally, we would inform the server just in case.
|
||||
// (also, this wouldn't work if the cookie were httponly which it ought to be
|
||||
document.cookie = "auth_token=";
|
||||
useEffect(() => {
|
||||
store.dispatch({ type: "LOGOUT" });
|
||||
}, []);
|
||||
return (<Redirect to="/" />);
|
||||
return (<Navigate to="/" />);
|
||||
};
|
||||
|
||||
export default Logout;
|
||||
|
10
react-app/src/components/TopNavBar.js
vendored
10
react-app/src/components/TopNavBar.js
vendored
@ -38,10 +38,10 @@ const DropDowns = (props) => {
|
||||
<DropdownToggle nav caret>
|
||||
{dropdown.label}
|
||||
</DropdownToggle>
|
||||
<DropdownMenu right>
|
||||
<DropdownMenu end>
|
||||
{dropdown.entries.map((item) =>
|
||||
<DropdownItem key={item.path}>
|
||||
<NavLink to={item.path} key={item.path} activeClassName="active" tag={RRNavLink}>
|
||||
<NavLink to={item.path} key={item.path} tag={RRNavLink}>
|
||||
{item.label}
|
||||
</NavLink>
|
||||
</DropdownItem>
|
||||
@ -70,7 +70,7 @@ const NavBar = (props) => {
|
||||
<Nav className="mr-auto" navbar>
|
||||
{menus.topbar.map((item) =>
|
||||
<NavItem key={item.path}>
|
||||
<NavLink to={item.path} activeClassName="active" tag={RRNavLink}>
|
||||
<NavLink to={item.path} tag={RRNavLink}>
|
||||
{item.label}
|
||||
</NavLink>
|
||||
</NavItem>
|
||||
@ -86,11 +86,11 @@ const NavBar = (props) => {
|
||||
|
||||
{isLoaded(user) ?
|
||||
<NavItem>
|
||||
<NavLink activeClassName="active" tag={RRNavLink} to={props.logoutUrl}>Logout ({user.sub})</NavLink>
|
||||
<NavLink tag={RRNavLink} to={props.logoutUrl}>Logout ({user.sub})</NavLink>
|
||||
</NavItem>
|
||||
:
|
||||
<NavItem>
|
||||
<NavLink activeClassName="active" tag={RRNavLink} to={props.loginUrl}>Login</NavLink>
|
||||
<NavLink tag={RRNavLink} to={props.loginUrl}>Login</NavLink>
|
||||
</NavItem>
|
||||
}
|
||||
</Nav>
|
||||
|
5
react-app/src/config/index.js
vendored
5
react-app/src/config/index.js
vendored
@ -34,4 +34,7 @@ const apiPrefix = `${publicUrl}/api`
|
||||
console.log(`Read configuration. Public_URL: ${publicUrl}`)
|
||||
// console.log(`apiPrefix: ${apiPrefix}`)
|
||||
|
||||
export default { menus, apiPrefix, publicUrl }
|
||||
export default { menus,
|
||||
branding: "CS3214 Demo App 2022",
|
||||
apiPrefix, publicUrl
|
||||
}
|
||||
|
26
react-app/src/containers/AppContainer.js
vendored
26
react-app/src/containers/AppContainer.js
vendored
@ -9,9 +9,9 @@ import HomePage from '../pages/HomePage';
|
||||
import PrivatePage from '../pages/PrivatePage';
|
||||
import PlayerPage from '../pages/PlayerPage';
|
||||
|
||||
import { Switch, Route, withRouter } from 'react-router-dom';
|
||||
import { Routes, Route } from 'react-router-dom';
|
||||
|
||||
import config from '../config/';
|
||||
import config from '../config';
|
||||
|
||||
/** AppContainer renders the navigation bar on top and its
|
||||
* children in the main part of the page. Its children will
|
||||
@ -19,22 +19,22 @@ import config from '../config/';
|
||||
*/
|
||||
const AppContainer = (props) => (
|
||||
<div>
|
||||
<TopNavBar branding="CS3214 Demo App 2021"
|
||||
<TopNavBar branding={config.branding}
|
||||
menus={config.menus}
|
||||
user={props.user}
|
||||
loginUrl={`/login`}
|
||||
logoutUrl={`/logout`}
|
||||
/>
|
||||
<div className="container-fluid marketing">
|
||||
<Switch>
|
||||
<Route exact path={`/`} component={HomePage} />
|
||||
<Route path={`/logout`} component={Logout} />
|
||||
<Route path={`/login`} component={LoginPage} />
|
||||
<Route path={`/public`} component={PublicPage} />
|
||||
<Route path={`/protected`} component={PrivatePage} />
|
||||
<Route path={`/player`} component={PlayerPage} />
|
||||
<Route component={NotFoundPage} />
|
||||
</Switch>
|
||||
<Routes>
|
||||
<Route exact path={`/`} element={<HomePage />} />
|
||||
<Route path={`/logout`} element={<Logout />} />
|
||||
<Route path={`/login`} element={<LoginPage />} />
|
||||
<Route path={`/public`} element={<PublicPage />} />
|
||||
<Route path={`/protected`} element={<PrivatePage />} />
|
||||
<Route path={`/player`} element={<PlayerPage />} />
|
||||
<Route element={<NotFoundPage />} />
|
||||
</Routes>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@ -51,4 +51,4 @@ function mapDispatchToProps(dispatch) {
|
||||
};
|
||||
}
|
||||
|
||||
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(AppContainer));
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(AppContainer);
|
||||
|
@ -4,33 +4,27 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { Redirect, withRouter } from 'react-router';
|
||||
import { connect } from 'react-redux';
|
||||
import { Navigate, useLocation } from 'react-router';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { isLoaded } from '../util/loadingObject';
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
user: state.auth
|
||||
};
|
||||
}
|
||||
|
||||
export default function RequireAuthentication(Component) {
|
||||
const wrapper = props => {
|
||||
if (isLoaded(props.user)) {
|
||||
const location = useLocation();
|
||||
const user = useSelector(state => state.auth);
|
||||
if (isLoaded(user)) {
|
||||
return <Component {...props} />;
|
||||
} else {
|
||||
return (
|
||||
<Redirect
|
||||
to={{
|
||||
pathname: `/login`,
|
||||
state: {
|
||||
from: props.history.location
|
||||
}
|
||||
<Navigate
|
||||
to={`/login`}
|
||||
state = {{
|
||||
from: location
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
return withRouter(connect(mapStateToProps)(wrapper));
|
||||
return wrapper;
|
||||
}
|
||||
|
4
react-app/src/index.js
vendored
4
react-app/src/index.js
vendored
@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import { Provider } from 'react-redux';
|
||||
import { BrowserRouter as Router } from 'react-router-dom';
|
||||
|
||||
@ -22,6 +23,7 @@ toastr.options.positionClass = 'toast-bottom-right';
|
||||
store.dispatch(checklogin());
|
||||
|
||||
const mountPoint = document.getElementById('root');
|
||||
const root = createRoot(mountPoint);
|
||||
const rootNode = (
|
||||
<Provider store={store}>
|
||||
<Router basename={config.publicUrl}>
|
||||
@ -29,6 +31,6 @@ const rootNode = (
|
||||
</Router>
|
||||
</Provider>
|
||||
);
|
||||
ReactDOM.render(rootNode, mountPoint);
|
||||
root.render(rootNode);
|
||||
|
||||
window.jQuery = jQuery; // for toastr
|
||||
|
9
react-app/src/pages/LoginPage.js
vendored
9
react-app/src/pages/LoginPage.js
vendored
@ -5,9 +5,10 @@ import { Card, CardHeader, CardBody, Container, Row, Col } from 'reactstrap';
|
||||
import { login } from '../actions/auth.js';
|
||||
import { isLoading, isLoaded } from '../util/loadingObject'
|
||||
import LoginForm from '../components/forms/LoginForm';
|
||||
import { Redirect } from 'react-router-dom';
|
||||
import { Navigate, useLocation } from 'react-router-dom';
|
||||
|
||||
const LoginPage = (props) => {
|
||||
const LoginPage = () => {
|
||||
const location = useLocation();
|
||||
const dispatch = useDispatch();
|
||||
function doLogin({username, password}) {
|
||||
dispatch(login(username, password));
|
||||
@ -15,9 +16,9 @@ const LoginPage = (props) => {
|
||||
|
||||
const user = useSelector(state => state.auth);
|
||||
const isAuthenticated = isLoaded(user);
|
||||
const { from } = props.location.state || { from: { pathname: "/" } };
|
||||
const { from } = location.state || { from: { pathname: "/" } };
|
||||
if (isAuthenticated) {
|
||||
return (<Redirect to={from} />);
|
||||
return (<Navigate to={from} />);
|
||||
}
|
||||
|
||||
return (
|
||||
|
8
react-app/src/pages/PlayerPage.js
vendored
8
react-app/src/pages/PlayerPage.js
vendored
@ -14,8 +14,8 @@ const PlayerPage = () => {
|
||||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
let videos = useSelector((state) => state.video);
|
||||
let [state, setState] = useState({
|
||||
const videos = useSelector((state) => state.video);
|
||||
const [state, setState] = useState({
|
||||
url: ""
|
||||
});
|
||||
const handleChange = (event) => {
|
||||
@ -61,7 +61,10 @@ const PlayerPage = () => {
|
||||
</ButtonToolbar>
|
||||
</Col>
|
||||
<Col>
|
||||
<FormGroup>
|
||||
<Label for="ddmenu">
|
||||
or select one from the list of
|
||||
</Label>
|
||||
{!isLoaded(videos) ? (
|
||||
<Spinner size="lg" color="primary" />
|
||||
) : (
|
||||
@ -79,6 +82,7 @@ const PlayerPage = () => {
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
)}
|
||||
</FormGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
|
11
react-app/src/pages/PrivatePage.js
vendored
11
react-app/src/pages/PrivatePage.js
vendored
@ -9,16 +9,19 @@ const PrivatePage = () => {
|
||||
return (<Container>
|
||||
<h1>Welcome to a private page</h1>
|
||||
<Row className="mt-3">
|
||||
You have successfully authenticated as user <span>{user.sub}</span>.
|
||||
<p>
|
||||
You have successfully authenticated as user <tt>{user.sub}</tt>.
|
||||
</p>
|
||||
</Row>
|
||||
<Row className="mt-3">
|
||||
Your token was issued at {new Date(user.iat*1000).toString()},
|
||||
it expires {new Date(user.exp*1000).toString()}
|
||||
<p>Your token was issued at {new Date(user.iat*1000).toString()},
|
||||
it expires {new Date(user.exp*1000).toString()}</p>
|
||||
</Row>
|
||||
<Row className="mt-3">
|
||||
This page is "private" only inasmuch as the front-end does not
|
||||
<p> This page is "private" only inasmuch as the front-end does not
|
||||
display it to unauthenticated users. In a fully-fledged app,
|
||||
this page would now perform API requests that require authentication.
|
||||
</p>
|
||||
</Row>
|
||||
</Container>);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user