Skip to content

Commit 725555e

Browse files
committed
Merge branch '1.0.0-dev'
2 parents 253646e + ffd4719 commit 725555e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+8852
-615
lines changed

.coveragerc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ omit=
77
*urls.py,
88
*srlegacy/*,
99
manage.py,
10-
*wsgi.py
10+
*wsgi.py,
11+
.env/*
1112
source=
1213
core/

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ coverage.xml
5757
*.log
5858
local_settings.py
5959
# db.sqlite3 # Include database!
60-
0*.py
60+
# 0*.py
6161

6262
# Flask stuff:
6363
instance/

README.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
<h1 align="center">nutrigo</h1>
22
<p align="center">Calculate nutrition for your favourite recipe!</p>
33
<p align="center">
4-
<img alt="Coveralls github branch" src="https://img.shields.io/coveralls/github/MakuZo/nutrigo/master.svg">
5-
<img alt="Travis (.com)" src="https://img.shields.io/travis/com/MakuZo/nutrigo/master.svg">
4+
<img alt="Coveralls github branch" src="https://img.shields.io/coveralls/github/MakuZo/nutrigo/1.0.0-dev">
5+
<img alt="Travis (.com)" src="https://img.shields.io/travis/com/MakuZo/nutrigo/1.0.0-dev.svg">
66
</p>
77
<p align="center">Try live <a href="https://nutrigo.makuzo.usermd.net">here</a></p>
88
<p align="center">
9-
<img align="center" width="70%" height="70%" src="https://i.imgur.com/3YKGyEt.jpg"></img>
9+
<img align="center" width="70%" height="70%" src="https://i.imgur.com/7zhqcxq.jpg"></img>
1010
</p>
1111

1212
## Overview
@@ -18,10 +18,10 @@ Nevertheless it provides good results for well-structured and uncomplicated reci
1818

1919
nutrigo requires [Python](https://www.python.org/) 3.6+ to run.
2020

21-
Install the dependencies, download WordNet and run the server.
21+
Install the dependencies, download corpora and run the server.
2222

2323
```sh
24-
$ pip install -r requirements.txt
24+
$ pip3 install -r requirements.txt
2525
$ python3 -m textblob.download_corpora
2626
$ python3 manage.py runserver
2727
```
@@ -38,7 +38,8 @@ $ docker run --rm -it -p 8000:8000 nutrigo
3838
```
3939

4040
## Supported websites
41-
41+
--Note that parsing third-party websites is only possible by using API Endpoint /api/calculate-from-url
42+
4243
So far the only supported websites are:
4344
Yummly.com, KwestiaSmaku.com
4445

@@ -52,7 +53,7 @@ $ pytest
5253

5354
## Contribution
5455

55-
Feel free to contribute to the project by making pull requests!
56+
Feel free to contribute to the project by creating pull requests!
5657

5758
## Built With
5859

api/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
"""
22
App which contains everything related to the site (i.e. api, views, etc.)
3-
"""
3+
"""

api/serializers.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from rest_framework import serializers
2+
3+
4+
class IngredientsSerializer(serializers.Serializer):
5+
"""Serializer used to validate POST data, but not to return it"""
6+
ingredients = serializers.ListField(child=serializers.CharField(), allow_empty=False)
7+
servings = serializers.IntegerField(required=False, min_value=1)

api/templates/api/about.html

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{% extends 'api/base.html' %}
2+
3+
{% block body %}
4+
<div class="siimple-content siimple-content--medium">
5+
<div class="siimple--px-5 siimple--py-5">
6+
<div class="siimple-h1 siimple--mb-3" align="center">
7+
<a class="siimple--color-white siimple--text-normal" href="{% url 'index-view' %}" style="text-decoration: none;">Nutrigo</a>
8+
</div>
9+
<div class="siimple-paragraph siimple-paragraph--lead siimple--color-white siimple-grid-col--sm-hide"
10+
align="center">
11+
Calculate nutrition for your favourite recipe!
12+
</div>
13+
<div class="about-content siimple-alert siimple-alert--primary">
14+
<p class="siimple-p">Nutrigo is developed by Piotr Kopacki (<a href="https://github.com/MakuZo">MakuZo</a>).
15+
</p>
16+
<p class="siimple-p">Nutrigo tries to guess and match ingredients from your recipe to products from USDA's
17+
food database.</p>
18+
<p class="siimple-p">Note that results may vary depending on the format of your recipe, ingredients that you
19+
use and weights/amounts that you provide.
20+
With that said, our calculations are not meant to be considered as real.
21+
</p>
22+
</div>
23+
</div>
24+
</div>
25+
26+
<div class="siimple-footer siimple--mt-1" align="center">
27+
<a class="siimple--color-white siimple--text-normal siimple--mr-2 footer-element" href="{% url 'index-view' %}"
28+
target="blank">Home</a>
29+
<a class="siimple--color-white siimple--text-normal siimple--mr-2 footer-element"
30+
href="https://github.com/MakuZo/nutrigo" target="blank">Github</a>
31+
<a class="siimple--color-white siimple--text-normal siimple--mr-2 footer-element"
32+
href="{% url 'calculate-from-text' %}">API</a>
33+
</div>
34+
{% endblock %}

api/templates/api/base.html

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,46 @@
66
<meta charset="UTF-8">
77
<meta name="viewport" content="width=device-width, initial-scale=1.0">
88
<meta http-equiv="X-UA-Compatible" content="ie=edge">
9-
<title>Nutrigo - get your diet straight!</title>
10-
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
11-
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
12-
<link rel="stylesheet" href="{% static 'api/style.css' %}">
13-
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
14-
<script src="https://cdnjs.cloudflare.com/ajax/libs/spin.js/2.3.2/spin.min.js"></script>
15-
<script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0/dist/Chart.min.js"></script>
9+
<link href="https://fonts.googleapis.com/css?family=Nothing+You+Could+Do&display=swap" rel="stylesheet">
10+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/siimple@3.3.1/dist/siimple.min.css">
11+
<script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/4.2.1/echarts.min.js"></script>
12+
<title>Nutrigo - calculate recipe nutrition!</title>
13+
<style>
14+
textarea {
15+
-webkit-box-sizing: border-box;
16+
-moz-box-sizing: border-box;
17+
box-sizing: border-box;
18+
width: 100%;
19+
}
20+
21+
body {
22+
background: url({% static 'api/bg-photo.jpg' %}) no-repeat center fixed;
23+
background-size: cover;
24+
}
25+
26+
.siimple-h1 {
27+
font-family: 'Nothing You Could Do', cursive;
28+
font-size: 55px;
29+
text-shadow: 2px 2px #ff0000;
30+
}
31+
32+
.siimple-paragraph {
33+
font-family: 'Nothing You Could Do';
34+
text-shadow: 1px 1px #60036d;
35+
font-size: 25px;
36+
}
37+
38+
.footer-element {
39+
text-shadow: 1px 1px 5px #760101;
40+
font-size: 15px;
41+
text-decoration: none;
42+
}
43+
</style>
1644
</head>
1745

1846
<body>
1947
{% block body %}
2048
{% endblock %}
21-
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
22-
integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
23-
crossorigin="anonymous"></script>
24-
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
25-
integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
26-
crossorigin="anonymous"></script>
2749
</body>
2850

2951
</html>
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
{% extends 'api/base.html' %}
2+
{% block body %}
3+
<div class="siimple-content siimple-content--medium">
4+
<div class="siimple--px-5 siimple--py-5">
5+
<div class="siimple-h1 siimple--mb-3" align="center">
6+
<a class="siimple--color-white siimple--text-normal" href="{% url 'index-view' %}" style="text-decoration: none;">Nutrigo</a>
7+
</div>
8+
<div class="siimple-paragraph siimple-paragraph--lead siimple--color-white siimple-grid-col--sm-hide"
9+
align="center">
10+
Calculate nutrition for your favourite recipe!
11+
</div>
12+
<div class="siimple-field">
13+
<textarea class="siimple-textarea" id="ingredients-value" rows="13" placeholder="1 chicken breast
14+
2 eggs
15+
200 g of all-purpose flour
16+
..."></textarea>
17+
</div>
18+
19+
<div class="siimple-grid">
20+
<div class="siimple-grid-row">
21+
<div class="siimple-grid-col siimple-grid-col--2 siimple-grid-col--sm-6">
22+
<div class="siimple--mt-1 siimple--text-center siimple--color-white ">Servings</div>
23+
</div>
24+
<div class="siimple-grid-col siimple-grid-col--2 siimple-grid-col--sm-6">
25+
<input type="number" class="siimple-input siimple--width-100" id="servings-value" value="1" min="1">
26+
</div>
27+
28+
<div class="siimple-grid-col siimple-grid-col--8 siimple-grid-col--sm-12">
29+
<div class="siimple-btn siimple-btn--primary siimple-btn--fluid" id="calculate-button">
30+
Calculate
31+
</div>
32+
</div>
33+
</div>
34+
</div>
35+
36+
<div class="siimple-footer siimple--mt-1" align="center">
37+
<a class="siimple--color-white siimple--text-normal siimple--mr-2 footer-element"
38+
href="https://github.com/MakuZo/nutrigo" target="blank">Github</a>
39+
<a class="siimple--color-white siimple--text-normal siimple--mr-2 footer-element" href="{% url 'about-view' %}">About</a>
40+
<a class="siimple--color-white siimple--text-normal siimple--mr-2 footer-element" href="{% url 'calculate-from-text' %}">API</a>
41+
</div>
42+
</div>
43+
</div>
44+
45+
<div class="siimple-modal siimple-modal--medium" id="result-modal" style="display:none;">
46+
<div class="siimple-modal-content">
47+
<div class="siimple-modal-header">
48+
<div class="siimple-modal-header-title">Results</div>
49+
<div class="siimple-modal-header-close" id="modal-close"></div>
50+
</div>
51+
<div class="siimple-modal-body">
52+
<div id="nutrition-chart" style="width: 100%; min-height: 300px"></div>
53+
<div id="nutrition-table" class="siimple-table siimple-table--border">
54+
<div class="siimple-table-header">
55+
<div class="siimple-table-row">
56+
<div class="siimple-table-cell">Nutrient</div>
57+
<div class="siimple-table-cell">Summary</div>
58+
<div class="siimple-table-cell">Serving</div>
59+
</div>
60+
</div>
61+
<div class="siimple-table-body" id="nutrition-table-body">
62+
</div>
63+
</div>
64+
</div>
65+
<div class="siimple-modal-footer">
66+
Note that presented values are approximate and shouldn't be considered as real.
67+
</div>
68+
</div>
69+
</div>
70+
71+
<script>
72+
var namesForNutrients = units = {
73+
"ENERGY": "Energy",
74+
"FAT": "Fat",
75+
"PROTEIN": "Protein",
76+
"CARB": "Carbs",
77+
"FAT_SAT": "Sat Fat",
78+
"FAT_POLY": "Polyunsat Fat",
79+
"FAT_MONO": "Monounsat Fat",
80+
"SUGAR": "Sugar",
81+
"CHOLE": "Chole",
82+
"SODIUM": "Sodium",
83+
"POTAS": "Potas",
84+
"FIBER": "Fiber",
85+
}
86+
var chart = null;
87+
function createChart(data) {
88+
chart = echarts.init(document.getElementById("nutrition-chart"))
89+
option = {
90+
title: {
91+
text: `Total energy: ${data.nutrition.ENERGY[0]} kcal`,
92+
x: 'center'
93+
},
94+
tooltip: {
95+
trigger: 'item',
96+
formatter: "{a} <br/>{b} : {c}g ({d}%)"
97+
},
98+
legend: {
99+
bottom: 40,
100+
left: 'center',
101+
data: ['Fat', 'Protein', 'Carbs']
102+
},
103+
series: [
104+
{
105+
name: 'Nutrition',
106+
type: 'pie',
107+
radius: '55%',
108+
center: ['50%', '45%'],
109+
data: [
110+
{ value: data.nutrition.FAT[0], name: 'Fat', itemStyle: { color: '#FDE74C' } },
111+
{ value: data.nutrition.PROTEIN[0], name: 'Protein', itemStyle: { color: '#5BC0EB' } },
112+
{ value: data.nutrition.CARB[0], name: 'Carbs', itemStyle: { color: '#9BC53D' } },
113+
],
114+
itemStyle: {
115+
emphasis: {
116+
shadowBlur: 10,
117+
shadowOffsetX: 0,
118+
shadowColor: 'rgba(0, 0, 0, 0.5)'
119+
}
120+
}
121+
}
122+
]
123+
};
124+
chart.setOption(option, true);
125+
}
126+
function dropChart() {
127+
chart.clear()
128+
}
129+
function postData() {
130+
var xhr = new XMLHttpRequest();
131+
var url = "{% url 'calculate-from-text' %}";
132+
xhr.open("POST", url, true);
133+
xhr.setRequestHeader("Content-Type", "application/json");
134+
xhr.onreadystatechange = function () {
135+
if (xhr.readyState === 4 && xhr.status === 200) {
136+
var json = JSON.parse(xhr.responseText);
137+
// Show modal before creating chart
138+
document.getElementById("result-modal").style.display = "";
139+
createChart(json);
140+
fillNutritionTable(json);
141+
}
142+
};
143+
var ings = document.getElementById("ingredients-value").value.split("\n");
144+
var servings = parseInt(document.getElementById("servings-value").value);
145+
var data = JSON.stringify({ "ingredients": ings, "servings": servings });
146+
xhr.send(data);
147+
}
148+
function fillNutritionTable(data) {
149+
data = Object.entries(data.nutrition);
150+
var table = document.getElementById("nutrition-table-body");
151+
for (var i = 0; i < data.length; i++) {
152+
// Prepare data
153+
var name = namesForNutrients[data[i][0]];
154+
var unit = data[i][1][2];
155+
var summary = `${data[i][1][0]} ${unit}`;
156+
var serving = `${data[i][1][1]} ${unit}`;
157+
// Create a row
158+
var row = document.createElement("div");
159+
row.className = "siimple-table-row"
160+
// Fill in row
161+
var name_div = document.createElement("div");
162+
name_div.className = "siimple-table-cell";
163+
name_div.innerHTML = name;
164+
var summary_div = document.createElement("div");
165+
summary_div.className = "siimple-table-cell";
166+
summary_div.innerHTML = summary;
167+
var serving_div = document.createElement("div");
168+
serving_div.className = "siimple-table-cell";
169+
serving_div.innerHTML = serving;
170+
row.appendChild(name_div);
171+
row.appendChild(summary_div);
172+
row.appendChild(serving_div);
173+
// Add row to table
174+
table.appendChild(row);
175+
}
176+
}
177+
function clearNutritionTable() {
178+
var table = document.getElementById("nutrition-table-body");
179+
table.innerHTML = '';
180+
}
181+
document.getElementById("calculate-button").addEventListener("click", function () {
182+
input = document.getElementById("ingredients-value").value.trim();
183+
if (!input) {
184+
alert("Add some ingredients first");
185+
} else {
186+
postData();
187+
}
188+
});
189+
document.getElementById("modal-close").addEventListener("click", function () {
190+
document.getElementById("result-modal").style.display = "none";
191+
dropChart();
192+
clearNutritionTable();
193+
});
194+
</script>
195+
{% endblock %}

0 commit comments

Comments
 (0)