Compare commits

...

3 Commits

19 changed files with 12088 additions and 6415 deletions

27
.eslintrc.yml Normal file
View File

@@ -0,0 +1,27 @@
env:
browser: true
es2021: true
jest/globals: true
extends:
- "plugin:react/recommended"
- standard
- plugin:jest/recommended
- plugin:jest/style
- prettier
- prettier/standard
parserOptions:
ecmaFeatures:
jsx: true
ecmaVersion: 12
sourceType: module
plugins:
- react
- jest
rules:
no-tabs: 0
indent:
- 2
- tab
settings:
react:
version: detect

16
.prettierignore Normal file
View File

@@ -0,0 +1,16 @@
build
coverage
dist
# ignore top level directory
.babelrc
.eslintrc.yml
.prettierignore
.gitignore
.gitattributes
.prettierrc.json
do.sh
Jenkinsfile
package.json
package-lock.json
webpack.config.js

3
.prettierrc.json Normal file
View File

@@ -0,0 +1,3 @@
{
"useTabs": true
}

0
Jenkinsfile vendored Normal file
View File

16
do.sh
View File

@@ -9,6 +9,22 @@ run() {
npx webpack serve
}
fmt() {
npx prettier --write .
}
_lint() {
npx eslint src --ext .js,.jsx
}
_jest() {
npx jest --coverage
}
test() {
echo "I am ${FUNCNAME[0]}ing"
_lint && _jest
}
"$@" # <- execute the task

18149
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,31 +1,43 @@
{
"name": "gog_frontend",
"version": "0.1.0",
"description": "Frontend for Gogmagog",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": {
"name": "Deepak Mallubhotla"
},
"private": "true",
"license": "ISC",
"devDependencies": {
"@babel/cli": "^7.12.10",
"@babel/core": "^7.12.10",
"@babel/preset-env": "^7.12.11",
"@babel/preset-react": "^7.12.10",
"babel-loader": "^8.2.2",
"css-loader": "^5.0.1",
"style-loader": "^2.0.0",
"webpack": "^5.11.1",
"webpack-cli": "^4.3.1",
"webpack-dev-server": "^3.11.1"
},
"dependencies": {
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-hot-loader": "^4.13.0"
}
"name": "gog_frontend",
"version": "0.1.0",
"description": "Frontend for Gogmagog",
"main": "index.js",
"scripts": {
"test": "./do.sh test"
},
"author": {
"name": "Deepak Mallubhotla"
},
"private": "true",
"license": "ISC",
"devDependencies": {
"@babel/cli": "^7.12.10",
"@babel/core": "^7.12.10",
"@babel/preset-env": "^7.12.11",
"@babel/preset-react": "^7.12.10",
"babel-loader": "^8.2.2",
"css-loader": "^5.0.1",
"eslint": "^7.17.0",
"eslint-config-prettier": "^7.1.0",
"eslint-config-standard": "^16.0.2",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-jest": "^24.1.3",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-react": "^7.22.0",
"jest": "^26.6.3",
"prettier": "2.2.1",
"react-test-renderer": "^17.0.1",
"style-loader": "^2.0.0",
"webpack": "^5.11.1",
"webpack-cli": "^4.3.1",
"webpack-dev-server": "^3.11.1"
},
"dependencies": {
"prop-types": "^15.7.2",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-hot-loader": "^4.13.0"
}
}

View File

@@ -1,19 +1,18 @@
<!-- sourced from https://raw.githubusercontent.com/reactjs/reactjs.org/master/static/html/single-file-example.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<title>Gog React Test</title>
</head>
<body>
<div id="root"></div>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<noscript> You need to enable JavaScript to run this app. </noscript>
<script src="../dist/bundle.js"></script>
</body>
</html>

View File

@@ -1,14 +1,14 @@
.App{
font: 14px "Century Gothic", Futura, sans-serif;
margin: 1rem;
.App {
font: 14px "Century Gothic", Futura, sans-serif;
margin: 1rem;
}
.mainContent{
width: 80%;
margin: auto;
.mainContent {
width: 80%;
margin: auto;
}
body {
background-color: rgb(240, 240, 240);
color: rgb(50, 50, 50);
background-color: rgb(240, 240, 240);
color: rgb(50, 50, 50);
}

View File

@@ -1,14 +1,10 @@
import React from "react";
import {hot} from "react-hot-loader";
import { hot } from "react-hot-loader";
import "./App.css";
import AllPlansComponent from "./components/AllPlansComponent.jsx";
class App extends React.Component {
render() {
const plan = {
plan_id: 1,
plan_date: "snth",
};
return (
<div className="App">
<h1> Hello, World! </h1>

View File

@@ -1,28 +1,30 @@
.actionID, .actionDescription, .actionChunks {
.actionID,
.actionDescription,
.actionChunks {
margin-left: 1rem;
margin-right: 1rem;
}
.actionCompleted {
flex: 1
flex: 1;
}
.actionChunks {
flex: 4
flex: 4;
}
.actionID {
flex: 4
flex: 4;
}
.actionDescription {
flex: 8
flex: 8;
}
.actionWrapper {
align-items: flex-end;
display: flex;
margin-top: .5rem;
margin-bottom: .5rem;
margin-top: 0.5rem;
margin-bottom: 0.5rem;
padding-top: 1rem;
}

View File

@@ -1,15 +1,18 @@
import React from "react";
import { action } from "../types";
import "./Action.css";
class Action extends React.Component {
render() {
const action = this.props.action;
var completed = "completed_on" in action;
const completed = "completed_on" in action;
console.log([action.completed_on, completed]);
return (
<div className="actionWrapper">
<div className="actionCompleted">{completed ? "X" : " "}</div>
<div className="actionID">ID: {action.action_id} | {action.plan_id}</div>
<div className="actionID">
ID: {action.action_id} | {action.plan_id}
</div>
<div className="actionDescription">{action.action_description}</div>
<div className="actionChunks">
{action.completed_chunks}/{action.estimated_chunks}
@@ -19,4 +22,8 @@ class Action extends React.Component {
}
}
Action.propTypes = {
action: action,
};
export default Action;

View File

@@ -0,0 +1,3 @@
test("trying it out", () => {
expect(true).toEqual(true);
});

View File

@@ -1,13 +1,14 @@
import React from "react";
import Action from "./Action.jsx";
import PropTypes from "prop-types";
import { action } from "../types";
class ActionsContainer extends React.Component {
render() {
return (
<div className="ActionsListWrapper">
<ul className="ActionsList">
{this.props.actions.map(action => {
{this.props.actions.map((action) => {
return (
<li className="Action" key={action.action_id}>
<Action action={action} />
@@ -20,4 +21,8 @@ class ActionsContainer extends React.Component {
}
}
ActionsContainer.propTypes = {
actions: PropTypes.arrayOf(action),
};
export default ActionsContainer;

View File

@@ -5,23 +5,23 @@ class AllPlansComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
plans: []
plans: [],
};
}
getPlans() {
getPlans() {
fetch("http://localhost:3000/api/plans", {
headers: {
Accept: "application/json"
}
Accept: "application/json",
},
})
.then(response => response.json())
.then(data => {
.then((response) => response.json())
.then((data) => {
this.setState({
plans: data
plans: data,
});
})
.catch(error => console.error(error));
.catch((error) => console.error(error));
}
componentDidMount() {
@@ -31,7 +31,7 @@ class AllPlansComponent extends React.Component {
render() {
return (
<div className="AllPlans">
<PlanList plans={this.state.plans}/>
<PlanList plans={this.state.plans} />
</div>
);
}

View File

@@ -1,30 +1,34 @@
import React from "react";
import ActionsContainer from "./ActionsContainer.jsx";
import { plan } from "../types";
class Plan extends React.Component {
constructor(props) {
super(props);
this.state = {
actions: []
actions: [],
};
}
getActions() {
fetch("http://localhost:3000/api/actions?" + new URLSearchParams({
plan_id: this.props.plan.plan_id
}), {
headers: {
Accept: "application/json"
getActions() {
fetch(
"http://localhost:3000/api/actions?" +
new URLSearchParams({
plan_id: this.props.plan.plan_id,
}),
{
headers: {
Accept: "application/json",
},
}
})
.then(response => response.json())
.then(data => {
)
.then((response) => response.json())
.then((data) => {
this.setState({
actions: data
actions: data,
});
})
.catch(error => console.error(error));
.catch((error) => console.error(error));
}
componentDidMount() {
@@ -34,11 +38,17 @@ class Plan extends React.Component {
render() {
return (
<div className="PlanActionsWrapper">
<div><h3>Plan for {this.props.plan.plan_date}</h3></div>
<div>
<h3>Plan for {this.props.plan.plan_date}</h3>
</div>
<ActionsContainer actions={this.state.actions.slice()} />
</div>
);
}
}
Plan.propTypes = {
plan: plan,
};
export default Plan;

View File

@@ -1,13 +1,14 @@
import React from "react";
import Plan from "./Plan.jsx";
import { plan } from "../types";
import PropTypes from "prop-types";
class PlanList extends React.Component {
render() {
return (
<div className="PlanListWrapper">
<ul className="PlanList">
{this.props.plans.map(plan => {
{this.props.plans.map((plan) => {
return (
<li className="Plan" key={plan.plan_id}>
<Plan plan={plan} />
@@ -20,4 +21,8 @@ class PlanList extends React.Component {
}
}
PlanList.propTypes = {
plans: PropTypes.arrayOf(plan),
};
export default PlanList;

15
src/types/index.js Normal file
View File

@@ -0,0 +1,15 @@
import PropTypes from "prop-types";
export const action = PropTypes.shape({
completed_on: PropTypes.string,
action_id: PropTypes.number.isRequired,
action_description: PropTypes.string.isRequired,
plan_id: PropTypes.number.isRequired,
completed_chunks: PropTypes.number,
estimated_chunks: PropTypes.number,
});
export const plan = PropTypes.shape({
plan_date: PropTypes.string,
plan_id: PropTypes.number.isRequired,
});

View File

@@ -2,39 +2,39 @@ const path = require("path");
const webpack = require("webpack");
module.exports = {
entry: "./src/index.jsx",
mode: "development",
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /(node_modules|bower_components)/,
loader: "babel-loader",
options: { presets: ["@babel/env"] }
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
}
]
},
resolve: { extensions: ["*", ".js", ".jsx"] },
output: {
path: path.resolve(__dirname, "dist/"),
publicPath: "/dist/",
filename: "bundle.js"
},
devServer: {
contentBase: path.join(__dirname, "public/"),
port: 3000,
publicPath: "http://localhost:3000/dist/",
hotOnly: true,
proxy: {
'/api': {
target: 'http://localhost:8080',
pathRewrite: {'^/api' : ''}
}
}
},
plugins: [new webpack.HotModuleReplacementPlugin()]
entry: "./src/index.jsx",
mode: "development",
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /(node_modules|bower_components)/,
loader: "babel-loader",
options: { presets: ["@babel/env"] },
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
],
},
resolve: { extensions: ["*", ".js", ".jsx"] },
output: {
path: path.resolve(__dirname, "dist/"),
publicPath: "/dist/",
filename: "bundle.js",
},
devServer: {
contentBase: path.join(__dirname, "public/"),
port: 3000,
publicPath: "http://localhost:3000/dist/",
hotOnly: true,
proxy: {
"/api": {
target: "http://localhost:8080",
pathRewrite: { "^/api": "" },
},
},
},
plugins: [new webpack.HotModuleReplacementPlugin()],
};