diff --git a/src/humulus/designs/recipes.json b/src/humulus/designs/recipes.json
index 7ea1b59..28aca01 100644
--- a/src/humulus/designs/recipes.json
+++ b/src/humulus/designs/recipes.json
@@ -10,6 +10,9 @@
},
"by-volume": {
"map": "function (doc) {\n if (doc.$type == \"recipe\" && doc.volume && doc.name) {\n emit(doc.volume, doc.name)\n }\n}"
+ },
+ "by-type": {
+ "map": "function (doc) {\n if (doc.$type == \"recipe\" && doc.type && doc.name) {\n emit(doc.type, doc.name)\n }\n}"
}
},
"lists": {},
diff --git a/src/humulus/recipes.py b/src/humulus/recipes.py
index 4c1bf65..d147532 100644
--- a/src/humulus/recipes.py
+++ b/src/humulus/recipes.py
@@ -17,7 +17,8 @@
import json
from decimal import Decimal
-from flask import (Blueprint, flash, redirect, render_template, jsonify,
+import requests
+from flask import (abort, Blueprint, flash, redirect, render_template, jsonify,
request, url_for)
from flask_wtf import FlaskForm
from flask_wtf.file import FileField, FileRequired
@@ -148,6 +149,11 @@ class YeastForm(Form):
class RecipeForm(FlaskForm):
"""Form for recipes."""
name = StringField('Name', validators=[DataRequired()])
+ type = SelectField('Type', default='',
+ choices=[(c, c) for c in ['All-Grain',
+ 'Partial Extract',
+ 'Extract']],
+ validators=[Optional()])
efficiency = DecimalField('Batch Efficiency (%)',
validators=[DataRequired()])
volume = DecimalField('Batch Volume (gal)', validators=[DataRequired()])
@@ -176,6 +182,7 @@ class RecipeForm(FlaskForm):
'volume': str(self.volume.data),
'notes': self.notes.data,
'$type': 'recipe',
+ 'type': self.type.data
}
recipe['fermentables'] = [f.doc for f in self.fermentables]
@@ -191,6 +198,7 @@ class RecipeForm(FlaskForm):
def copyfrom(self, data):
"""Copies from a dictionary (data) into the current object"""
self.name.data = data['name']
+ self.type.data = data['type']
self.efficiency.data = Decimal(data['efficiency'])
self.volume.data = Decimal(data['volume'])
self.notes.data = data['notes']
@@ -255,16 +263,16 @@ def index():
['true', 'yes']
)
sort_by = request.args.get('sort_by', default='name', type=str)
- if sort_by == 'date':
- view = get_view('_design/recipes', 'by-date')
- elif sort_by == 'volume':
- view = get_view('_design/recipes', 'by-volume')
- else:
- view = get_view('_design/recipes', 'by-name')
+
+ view = get_view('_design/recipes', 'by-{}'.format(sort_by))
+ try:
+ rows = view(include_docs=True, descending=descending)['rows']
+ except requests.exceptions.HTTPError:
+ abort(400)
return render_template(
'recipes/index.html',
- rows=view(include_docs=True, descending=descending)['rows'],
+ rows=rows,
descending=descending,
sort_by=sort_by
)
diff --git a/src/humulus/templates/recipes/_macros.html b/src/humulus/templates/recipes/_macros.html
index ae48f16..6ac50ac 100644
--- a/src/humulus/templates/recipes/_macros.html
+++ b/src/humulus/templates/recipes/_macros.html
@@ -26,8 +26,9 @@
-#}
{{ render_field_with_errors(form.name) }}
-
{{ render_field_with_errors(form.efficiency, 'ingredient-field') }}
-
{{ render_field_with_errors(form.volume, 'ingredient-field') }}
+
{{ render_field_with_errors(form.type) }}
+
{{ render_field_with_errors(form.efficiency, 'ingredient-field') }}
+
{{ render_field_with_errors(form.volume, 'ingredient-field') }}
{#-
Fermentable Ingredients
diff --git a/src/humulus/templates/recipes/index.html b/src/humulus/templates/recipes/index.html
index 495e0b9..23647f8 100644
--- a/src/humulus/templates/recipes/index.html
+++ b/src/humulus/templates/recipes/index.html
@@ -49,6 +49,15 @@
Batch Size
{% endif %}
+
+ {% if sort_by == 'type' and descending %}
+ Type ↓
+ {% elif sort_by == 'type' %}
+ Type ↑
+ {% else %}
+ Type
+ {% endif %}
+ |
{% if sort_by == 'date' and descending %}
Created On ↓
@@ -64,6 +73,7 @@
|
| {{ row.doc.name }} |
{{ row.doc.volume }} gal. |
+ {{ row.doc.type }} |
{{ moment(row.doc.created) }} |
{% endfor %}
diff --git a/src/humulus/templates/recipes/info.html b/src/humulus/templates/recipes/info.html
index 13252ba..0a8695c 100644
--- a/src/humulus/templates/recipes/info.html
+++ b/src/humulus/templates/recipes/info.html
@@ -28,6 +28,8 @@
+ - Recipe Type
+ - {{ recipe.type }}
- Batch Efficiency
- {{ recipe.efficiency|int }}%
- Batch Volume
diff --git a/tests/conftest.py b/tests/conftest.py
index 917f4fd..d997ccb 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -44,6 +44,7 @@ def app():
put_doc({
'_id': 'awesome-lager',
'$type': 'recipe',
+ 'type': 'All-Grain',
'efficiency': '65',
'name': 'Awesome Lager',
'notes': 'Test',
@@ -56,6 +57,7 @@ def app():
'$type': 'recipe',
'efficiency': '75',
'name': 'Partial Beer',
+ 'type': 'Extract',
'notes': 'Contains only required fields for yeast.',
'volume': '3.5',
'fermentables': [],
@@ -70,6 +72,7 @@ def app():
'_id': 'full-recipe',
'$type': 'recipe',
'efficiency': '78',
+ 'type': 'All-Grain',
'name': 'Awesome Beer',
'notes': 'This is a test beer that contains most possible fields.',
'volume': '2.5',
@@ -160,6 +163,7 @@ def sample_recipes():
return {
'lager': {
'efficiency': '72',
+ 'type': 'All-Grain',
'fermentables': [
{
'amount': '9.5',
@@ -217,6 +221,7 @@ def sample_recipes():
},
'sweetstout': {
'efficiency': '72',
+ 'type': 'All-Grain',
'fermentables': [
{
'amount': '2.75',
diff --git a/tests/test_recipes.py b/tests/test_recipes.py
index d8ca6a4..43f2c2f 100644
--- a/tests/test_recipes.py
+++ b/tests/test_recipes.py
@@ -22,6 +22,10 @@ from humulus.recipes import FermentableForm, HopForm, RecipeForm, YeastForm
def test_index(client):
"""Test success in retrieving index."""
+ # Test for bad request
+ response = client.get('/recipes/?sort_by=foobar')
+ assert response.status_code == 400
+
# Verify defaults
response = client.get('/recipes/')
assert response.status_code == 200
@@ -93,6 +97,27 @@ def test_index(client):
response.data
)
+ # Test sort by type ascending
+ response = client.get('/recipes/?descending=false&sort_by=type')
+ assert (
+ b'"/recipes/?descending=false&sort_by=name">Name' in
+ response.data
+ )
+ assert (
+ b'"/recipes/?descending=true&sort_by=type">Type ↑' in
+ response.data
+ )
+
+ # Test sort by type descending
+ response = client.get('/recipes/?descending=true&sort_by=type')
+ assert (
+ b'"/recipes/?descending=false&sort_by=name">Name' in
+ response.data
+ )
+ assert (
+ b'"/recipes/?descending=false&sort_by=type">Type ↓' in
+ response.data
+ )
def test_create(client, app, auth):
"""Test success in creating a recipe document."""
@@ -253,10 +278,12 @@ def test_recipe_form_doc(app):
recipe.efficiency.data = Decimal('65')
recipe.volume.data = Decimal('5.5')
recipe.notes.data = 'This is a test'
+ recipe.type.data = 'All-Grain'
assert recipe.doc == {
'name': 'Test',
'efficiency': '65',
+ 'type': 'All-Grain',
'volume': '5.5',
'notes': 'This is a test',
'fermentables': [],
@@ -290,6 +317,7 @@ def test_recipe_form_doc(app):
assert recipe.doc == {
'name': 'Test',
'efficiency': '65',
+ 'type': 'All-Grain',
'volume': '5.5',
'notes': 'This is a test',
'$type': 'recipe',