Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to CRA-v2, and new project structure #4

Merged
merged 19 commits into from
Oct 26, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .env

This file was deleted.

4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
# dependencies
/node_modules

# IDE
/.idea

# testing
/coverage

Expand All @@ -19,3 +22,4 @@
npm-debug.log*
yarn-debug.log*
yarn-error.log*
package-lock.json
123 changes: 87 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,43 +1,94 @@
# Frontend Setup
> Instructions to install dependencies and run frontend development environment.
## Project Files
This is our basic file structure, including `build/`, `public/` and `src/`.
```
├── build
│   └── ...generated static resources: css, js, media
├── public
│   └── ...favicon.ico, index.html, manifest.json
├── src
│ └── ...development files
├── .gitignore
├── package.json (dependencies, scripts, configuration)
└── README.md
```
## Development
For development, `src/` contains the main assets. There are `components/`, `resources/`, redux-based `actions/`, `constants/`, `reducers/` and `services/`.

### Directory
.
├── create-react-app # For installing dependencies, you can delete after install
└── frontend # Actual development environment
├── other files... # Stores App.js, components/, etc..
└── (to be updated)
**Note**: each folder contains a file called `index.js`. This helps to shorten import statements, and the decision to include these is for convenience.

### Install Create-React-App (only for dependencies)
Link: https://github.com/IS3106-T07/create-react-app
```
/ ...
└── src
├── actions
│   ├── ...actions.js
│   └── index.js
├── components
│ ├── css
│   │   └── ...example.module.css
│   ├── App.js
│   ├── PrivateRoute.js
│   └── ...PageComponents.js
├── constants
│   ├── ...constants.js
│   └── index.js
├── reducers
│   ├── ...reducer.js
│   └── index.js
├── resources
│   └── (images)
├── services
│ ├── ...service.js
│ └── index.js
└ ...
```

git clone https://github.com/IS3106-T07/create-react-app
cd create-react-app
npm install
And `helpers/`, `index.html` and `index.js`.
```
...
├── helpers
│   ├── auth-header.js
│   ├── fake-backend.js
│   ├── history.js
│   ├── index.js
│   ├── serviceWorker.js
│   └── store.js
├── index.html
└── index.js
```

### Install Frontend
Link: Current Page
## Using this project
The development server runs on `PORT 8000`. See *scripts* in `package.json` to change.
Configure *apiUrl* at `src/index.js`. Default value: http://localhost:3000.

cd ..
git clone https://github.com/IS3106-T07/frontend
cd frontend
npm install
**Note**: `HTTPS` is required for service workers.

Run in **development**
```
npm install
npm start
HTTPS=true npm start // Linux, macOS (bash)
set HTTPS=true&&npm start // Windows (cmd.exe)
($env:HTTPS = $true) -and (npm start) // Windows (powershell)
```
Run in **production**
```
npm install
npm run build
serve -s build
```
Run **tests**
```
npm build
npm run test
```

### Testing
npm test
## Creating a component
```
// todo Guide
```

### Run
npm start

Running at http://localhost:3003 (and at specified IP network address, e.g. 192.168.1.40:3003)

# FAQ
> Frequently asked questions.

### Q. I'm stuck at registry config, on install. How to proceed?
Set config manually.

npm config set registry="http://registry.npmjs.org"

### Q. Where is the PWA Setup Guide?
See MANUAL.md.
This brings us to the end of project-specific documentation.
48 changes: 37 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,44 @@
"name": "frontend",
"version": "0.1.0",
"private": true,
"devDependencies": {
"react-router-dom": "^4.4.0-alpha.1",
"react-scripts": "1.1.5"
"license": "MIT",
"scripts": {
"start": "PORT=8000 react-scripts start export",
"build": "react-scripts build",
"test": "react-scripts test"
},
"eslintConfig": {
"extends": "react-app"
},
"dependencies": {
"react": "^16.5.1",
"react-dom": "^16.5.1"
"config": "^2.0.1",
"history": "^4.6.3",
"react": "^16.0.0",
"react-dom": "^16.0.0",
"react-redux": "^5.0.5",
"react-router-dom": "^4.1.2",
"redux": "^3.7.2",
"redux-logger": "^3.0.6",
"redux-thunk": "^2.2.0"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
"devDependencies": {
"babel-core": "^6.21.0",
"babel-preset-es2015": "^6.18.0",
"babel-preset-react": "^6.16.0",
"babel-preset-stage-3": "^6.24.1",
"css-loader": "^1.0.0",
"html-webpack-plugin": "^2.26.0",
"path": "^0.12.7",
"react-scripts": "2.0.5",
"style-loader": "^0.23.0",
"url-loader": "^1.1.1",
"webpack-cli": "^3.1.2"
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
],
"homepage": "./"
}
2 changes: 1 addition & 1 deletion public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
<title>Public</title>
</head>
<body>
<noscript>
Expand Down
19 changes: 19 additions & 0 deletions src/actions/alert.actions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { alertConstants } from '../constants';

export const alertActions = {
success,
error,
clear
};

function success(message) {
return { type: alertConstants.SUCCESS, message };
}

function error(message) {
return { type: alertConstants.ERROR, message };
}

function clear() {
return { type: alertConstants.CLEAR };
}
2 changes: 2 additions & 0 deletions src/actions/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './alert.actions';
export * from './user.actions';
94 changes: 94 additions & 0 deletions src/actions/user.actions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { userConstants } from '../constants';
import { userService, history } from '../helpers';
import { alertActions } from './';

export const userActions = {
login,
logout,
register,
getAll,
delete: _delete
};

function login(email, password) {
return dispatch => {
dispatch(request({ email }));
userService.login(email, password)
.then(
user => {
dispatch(success(user));
history.push('/');
},
error => {
dispatch(failure(error.toString()));
console.log(error);
dispatch(alertActions.error(error.toString()));
}
);
};

function request(user) { return { type: userConstants.LOGIN_REQUEST, user } }
function success(user) { return { type: userConstants.LOGIN_SUCCESS, user } }
function failure(error) { return { type: userConstants.LOGIN_FAILURE, error } }
}

function logout() {
userService.logout();
return { type: userConstants.LOGOUT };
}

function register(user) {
return dispatch => {
dispatch(request(user));

userService.register(user)
.then(
user => {
dispatch(success());
history.push('/login');
dispatch(alertActions.success('Registration successful'));
},
error => {
dispatch(failure(error.toString()));
dispatch(alertActions.error(error.toString()));
}
);
};

function request(user) { return { type: userConstants.REGISTER_REQUEST, user } }
function success(user) { return { type: userConstants.REGISTER_SUCCESS, user } }
function failure(error) { return { type: userConstants.REGISTER_FAILURE, error } }
}

function getAll() {
return dispatch => {
dispatch(request());

userService.getAll()
.then(
users => dispatch(success(users)),
error => dispatch(failure(error.toString()))
);
};

function request() { return { type: userConstants.GETALL_REQUEST } }
function success(users) { return { type: userConstants.GETALL_SUCCESS, users } }
function failure(error) { return { type: userConstants.GETALL_FAILURE, error } }
}

// prefixed function name with underscore because delete is a reserved word in javascript
function _delete(id) {
return dispatch => {
dispatch(request(id));

userService.delete(id)
.then(
user => dispatch(success(id)),
error => dispatch(failure(id, error.toString()))
);
};

function request(id) { return { type: userConstants.DELETE_REQUEST, id } }
function success(id) { return { type: userConstants.DELETE_SUCCESS, id } }
function failure(id, error) { return { type: userConstants.DELETE_FAILURE, id, error } }
}
54 changes: 54 additions & 0 deletions src/components/App.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React from 'react';
import { Router, Route } from 'react-router-dom';
import { connect } from 'react-redux';

import { history } from '../helpers';
import { alertActions } from '../actions';
import { PrivateRoute } from './PrivateRoute';
import { HomePage } from './HomePage';
import { LoginPage } from './LoginPage';
import { RegisterPage } from './RegisterPage';

class App extends React.Component {
constructor(props) {
super(props);

const { dispatch } = this.props;
history.listen((location, action) => {
// clear alert on location change
dispatch(alertActions.clear());
});
}

render() {
const { alert } = this.props;
return (
<div className="jumbotron">
<div className="container">
<div className="col-sm-8 col-sm-offset-2">
{alert.message &&
<div className={`alert ${alert.type}`}>{alert.message}</div>
}
<Router history={history}>
<div>
<PrivateRoute exact path="/" component={HomePage} />
<Route path="/login" component={LoginPage} />
<Route path="/register" component={RegisterPage} />
</div>
</Router>
</div>
</div>
</div>
);
}
}

function mapStateToProps(state) {
const { alert } = state;
return {
alert
};
}

const connectedApp = connect(mapStateToProps)(App);
export { connectedApp as App };
Loading