initial commit

This commit is contained in:
Jake McDermott
2018-09-25 10:39:21 -04:00
commit 43f3b484f9
13 changed files with 8768 additions and 0 deletions

7
.babelrc Normal file
View File

@@ -0,0 +1,7 @@
{
"presets": [
"env",
"react",
"stage-2"
]
}

9
README.md Normal file
View File

@@ -0,0 +1,9 @@
# AWX-PF
## Usage
* `git clone git@github.com:jakemcdermott/awx-pf.git`
* cd awx-pf
* npm install
* npm start
* visit `https://127.0.0.1:3000/`

10
dist/index.html vendored Normal file
View File

@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<head>
<title>AWX</title>
</head>
<body>
<div id="app"></div>
<script src="/bundle.js"></script>
</body>
</html>

8445
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

34
package.json Normal file
View File

@@ -0,0 +1,34 @@
{
"name": "awx-react",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "webpack-dev-server --config ./webpack.config.js --mode development",
"test": "echo \"No test specified\" && exit 0"
},
"keywords": [],
"author": "",
"license": "Apache",
"devDependencies": {
"babel-core": "^6.26.3",
"babel-loader": "^7.1.5",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-2": "^6.24.1",
"react-hot-loader": "^4.3.3",
"webpack": "^4.15.1",
"webpack-cli": "^3.0.8",
"webpack-dev-server": "^3.1.4"
},
"dependencies": {
"axios": "^0.18.0",
"babel-preset-env": "^1.7.0",
"react": "^16.4.1",
"react-dom": "^16.4.1",
"react-redux": "^5.0.7",
"react-router-dom": "^4.3.1",
"redux": "^4.0.0",
"@patternfly/patternfly-next": "^1.0.41",
"@patternfly/react-core": "1.11.0"
}
}

43
src/App.jsx Normal file
View File

@@ -0,0 +1,43 @@
import React from 'react';
import { render } from 'react-dom';
import {
HashRouter as Router,
Route,
Link,
Redirect
} from 'react-router-dom';
import api from './api';
import About from './components/About';
import Dashboard from './components/Dashboard';
import Login from './components/Login';
import Organizations from './components/Organizations';
const AuthenticatedRoute = ({ component: Component, ...rest }) => (
<Route {...rest} render={props => (
api.isAuthenticated() ? (
<Component {...props}/>
) : (
<Redirect to={{
pathname: '/login',
state: { from: props.location }
}}/>
)
)}/>
)
const App = () => (
<Router>
<div>
<Route path="/login" component={Login} />
<AuthenticatedRoute exact path="/" component={Dashboard} />
<AuthenticatedRoute exact path="/about" component={About} />
<AuthenticatedRoute exact path="/organizations" component={Organizations} />
</div>
</Router>
);
const el = document.getElementById('app');
render(<App />, el);

54
src/api.js Normal file
View File

@@ -0,0 +1,54 @@
import axios from 'axios';
const API_ROOT = '/api/';
const API_LOGIN = `${API_ROOT}login/`;
const API_V2 = `${API_ROOT}v2/`;
const API_CONFIG = `${API_V2}config/`;
const API_PROJECTS = `${API_V2}projects/`;
const API_ORGANIZATIONS = `${API_V2}organizations/`;
const CSRF_COOKIE_NAME = 'csrftoken';
const CSRF_HEADER_NAME = 'X-CSRFToken';
const http = axios.create({
xsrfCookieName: CSRF_COOKIE_NAME,
xsrfHeaderName: CSRF_HEADER_NAME,
});
let authenticated = false; // temporary
class APIClient {
isAuthenticated() {
return authenticated;
}
login(username, password, redirect = API_CONFIG) {
const un = encodeURIComponent(username);
const pw = encodeURIComponent(password);
const next = encodeURIComponent(redirect);
const data = `username=${un}&password=${pw}&next=${next}`;
const headers = { 'Content-Type': 'application/x-www-form-urlencoded' };
return http.get(API_LOGIN, { headers })
.then(() => http.post(API_LOGIN, data, { headers }))
.then(res => {
authenticated = true; // temporary
return res;
})
}
logout() {
return http.delete(API_LOGIN);
}
getProjects() {
return http.get(API_PROJECTS);
}
getOrganizations() {
return http.get(API_ORGANIZATIONS);
}
};
export default new APIClient();

9
src/components/About.jsx Normal file
View File

@@ -0,0 +1,9 @@
import React from 'react';
const About = () => (
<div>
<h2>About</h2>
</div>
);
export default About;

View File

@@ -0,0 +1,9 @@
import React from 'react';
const Dashboard = () => (
<div>
<h2>Dashboard</h2>
</div>
);
export default Dashboard;

75
src/components/Login.jsx Normal file
View File

@@ -0,0 +1,75 @@
import React, { Component } from 'react';
import { Redirect } from 'react-router-dom';
import { Button } from '@patternfly/react-core';
import api from '../api';
class Login extends Component {
state = {
username: '',
password: '',
redirect: false,
};
handleChange = event => this.setState({ [event.target.name]: event.target.value });
handleSubmit = event => {
const { username, password } = this.state;
event.preventDefault();
api.login(username, password)
.then(() => this.setState({ redirect: true }))
.then(() => api.getProjects())
.then(res => console.log(res));
};
render() {
const { username, password, redirect } = this.state;
if (redirect) {
return (<Redirect to={'/'} />);
}
return (
<div className='column'>
<form onSubmit={this.handleSubmit}>
<div className='field'>
<label className='label'>Username</label>
<div className='control'>
<input
className='input'
type='text'
name='username'
onChange={this.handleChange}
value={username}
required
/>
</div>
</div>
<div className='field'>
<label className='label'>Password</label>
<div className='control'>
<input
className='input'
type='password'
name='password'
onChange={this.handleChange}
value={password}
required
/>
</div>
</div>
<div className='control'>
<Button type='submit'>
Login
</Button>
</div>
</form>
</div>
);
}
}
export default Login;

View File

@@ -0,0 +1,9 @@
import React from 'react';
const Organizations = () => (
<div>
<h2>Organizations</h2>
</div>
);
export default Organizations;

1
src/index.js Normal file
View File

@@ -0,0 +1 @@
import App from './App';

63
webpack.config.js Normal file
View File

@@ -0,0 +1,63 @@
const webpack = require('webpack');
const TARGET = 'https://localhost:443';
const TARGET_PORT = 443;
module.exports = {
entry: './src/index.js',
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: ['babel-loader']
}
]
},
resolve: {
extensions: ['*', '.js', '.jsx']
},
output: {
path: __dirname + '/dist',
publicPath: '/',
filename: 'bundle.js'
},
plugins: [
new webpack.HotModuleReplacementPlugin()
],
devServer: {
contentBase: './dist',
hot: true,
inline: true,
stats: 'minimal',
host: '127.0.0.1',
https: true,
port: 3000,
clientLogLevel: 'none',
proxy: [
{
context: '/api/login/',
target: TARGET,
secure: false,
ws: false,
headers: {
Host: `localhost:${TARGET_PORT}`,
Origin: TARGET,
Referer: `${TARGET}/`
}
},
{
context: '/api',
target: TARGET,
secure: false,
ws: false,
bypass: req => (req.originalUrl.includes('hot-update.json') || req.originalUrl.includes('login')),
},
{
context: '/websocket',
target: TARGET,
secure: false,
ws: true
}]
}
};