Skip to content

Commit 0a24f6e

Browse files
author
Josh Reynolds
committed
Adding spa and api refactoring example
1 parent 7d5a2c0 commit 0a24f6e

File tree

9 files changed

+145
-7
lines changed

9 files changed

+145
-7
lines changed

api/Makefile

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
PYBIN=venv/bin
1+
PYBIN=.venv/bin
22

3-
venv: venv/bin/activate
3+
venv: .venv/bin/activate
44

5-
venv/bin/activate: requirements.txt
6-
test -d venv || python3 -m venv venv
5+
.venv/bin/activate: requirements.txt
6+
test -d venv || python3 -m venv .venv
77
. $(PYBIN)/activate; pip install -Ur requirements.txt
8-
touch venv/bin/activate
8+
touch .venv/bin/activate
99

1010
test: venv
1111
. $(PYBIN)/activate; python -m unittest discover todo/unittests

api/backend/settings.py

+1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
'corsheaders', # add this
4343
'rest_framework', # add this
4444
'todo',
45+
'stats',
4546
]
4647

4748

api/todo/stats.py

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import math
2+
import json
3+
4+
5+
class DataStats:
6+
# original code sourced from https://github.com/lgiordani/datastats
7+
8+
def stats(self, data, iage, isalary):
9+
# iage and isalary are the starting age and salary used to
10+
# compute the average yearly increase of salary.
11+
12+
# Compute average yearly increase
13+
average_age_increase = math.floor(
14+
sum([e['age'] for e in data])/len(data)) - iage
15+
average_salary_increase = math.floor(
16+
sum([int(e['salary'][1:]) for e in data])/len(data)) - isalary
17+
18+
yearly_avg_increase = math.floor(
19+
average_salary_increase/average_age_increase)
20+
21+
# Compute max salary
22+
salaries = [int(e['salary'][1:]) for e in data]
23+
threshold = '$' + str(max(salaries))
24+
25+
max_salary = [e for e in data if e['salary'] == threshold]
26+
27+
# Compute min salary
28+
salaries = [int(d['salary'][1:]) for d in data]
29+
min_salary = [e for e in data if e['salary'] ==
30+
'${}'.format(str(min(salaries)))]
31+
32+
return json.dumps({
33+
'avg_age': math.floor(sum([e['age'] for e in data])/len(data)),
34+
'avg_salary': math.floor(sum(
35+
[int(e['salary'][1:]) for e in data])/len(data)),
36+
'avg_yearly_increase': yearly_avg_increase,
37+
'max_salary': max_salary,
38+
'min_salary': min_salary
39+
})

api/todo/unittests/test_stats.py

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import json
2+
from unittest import TestCase
3+
from todo.stats import DataStats
4+
5+
6+
test_data = [
7+
{
8+
"id": 1,
9+
"name": "Laith",
10+
"surname": "Simmons",
11+
"age": 68,
12+
"salary": "$27888"
13+
},
14+
{
15+
"id": 2,
16+
"name": "Mikayla",
17+
"surname": "Henry",
18+
"age": 49,
19+
"salary": "$67137"
20+
},
21+
{
22+
"id": 3,
23+
"name": "Garth",
24+
"surname": "Fields",
25+
"age": 70,
26+
"salary": "$70472"
27+
}
28+
]
29+
30+
31+
class TestDataData(TestCase):
32+
33+
def test_json(self):
34+
35+
ds = DataStats()
36+
37+
expected_output = json.dumps(
38+
{
39+
'avg_age': 62,
40+
'avg_salary': 55165,
41+
'avg_yearly_increase': 837,
42+
'max_salary': [{
43+
"id": 3,
44+
"name": "Garth",
45+
"surname": "Fields",
46+
"age": 70,
47+
"salary": "$70472"
48+
}],
49+
'min_salary': [{
50+
"id": 1,
51+
"name": "Laith",
52+
"surname": "Simmons",
53+
"age": 68,
54+
"salary": "$27888"
55+
}]
56+
}
57+
)
58+
59+
self.assertEqual(expected_output, ds.stats(test_data, 20, 20000))

spa/.dockerignore

+3
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
node_modules
22
build
3+
docker-compose.yml
4+
Dockerfile
5+
infrastructure

spa/docker-compose.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ services:
66
ports:
77
- 3000:80
88
environment:
9-
- REACT_APP_API=web
9+
- REACT_APP_API=localhost:8000
1010

1111

1212
networks:

spa/infrastructure/spa.yml

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
apiVersion: apps/v1
2+
kind: Deployment
3+
metadata:
4+
name: spa
5+
spec:
6+
replicas: 1
7+
selector:
8+
matchLabels:
9+
app: spa
10+
template:
11+
metadata:
12+
labels:
13+
app: spa
14+
spec:
15+
containers:
16+
- name: spa
17+
image: class/spa:latest
18+
imagePullPolicy: Never
19+
ports:
20+
- containerPort: 80
21+
22+
---
23+
apiVersion: v1
24+
kind: Service
25+
metadata:
26+
name: spa
27+
spec:
28+
selector:
29+
app: spa
30+
ports:
31+
- port: 80
32+
targetPort: 80
33+
type: NodePort

spa/package.json

+3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
"scripts": {
1818
"start": "react-scripts start",
1919
"build": "npx react-scripts build",
20+
"build-docker-prod": "docker build . -t class/spa",
21+
"deploy": "kubectl delete pod -l app=spa; kubectl apply -f infrastructure/spa.yml",
22+
"bind-spa-locally": "kubectl port-forward service/spa 3000:80",
2023
"cy.run": "npx cypress run",
2124
"cy.open": "npx cypress open",
2225
"docker-compose": "docker-compose up --build",

spa/src/App.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import Modal from "./components/Modal";
55
import axios from "axios";
66

77
const config = {
8-
apiServer: process.env.REACT_APP_API
8+
apiServer: process.env.REACT_APP_API ? process.env.REACT_APP_API : 'http://localhost:8000'
99
}
1010

1111
class App extends Component {

0 commit comments

Comments
 (0)