Merge branch 'feature/books_refactor' into develop

# Conflicts:
#	vue/webpack-stats.json
This commit is contained in:
Kaibu
2021-09-13 19:30:13 +02:00
17 changed files with 742 additions and 138 deletions

View File

@@ -548,7 +548,7 @@ class RecipeBookEntrySerializer(serializers.ModelSerializer):
return RecipeBookSerializer(context={'request': self.context['request']}).to_representation(obj.book)
def get_recipe_content(self, obj):
return RecipeOverviewSerializer(context={'request': self.context['request']}).to_representation(obj.recipe)
return RecipeSerializer(context={'request': self.context['request']}).to_representation(obj.recipe)
def create(self, validated_data):
book = validated_data['book']

View File

@@ -0,0 +1,127 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="200mm"
height="155mm"
viewBox="0 0 200 155"
version="1.1"
id="SVGRoot"
sodipodi:docname="book.svg"
inkscape:version="1.0.2-2 (e86c870879, 2021-01-15)">
<defs
id="defs2608" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.4"
inkscape:cx="250.5725"
inkscape:cy="265.89318"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
inkscape:document-rotation="0"
showgrid="false"
inkscape:window-width="2560"
inkscape:window-height="1377"
inkscape:window-x="1912"
inkscape:window-y="1072"
inkscape:window-maximized="1" />
<metadata
id="metadata2611">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1">
<path
fill="currentColor"
d="m 178.43105,2.5084522 h -0.0553 c -8.32303,0.04154 -50.03147,-4.552088 -75.88885,9.0177618 -1.39985,0.732762 -3.570481,0.732762 -4.970321,0 C 71.655739,-2.0436358 29.947282,2.5499292 21.627712,2.5084522 h -0.0553 c -11.6446421,0 -21.11519213,9.1491068 -21.11519213,20.3962508 V 125.45629 c 0,10.85658 8.78272603,19.7983 19.99531613,20.35823 12.017921,0.60833 42.178527,-1.29269 62.868573,6.34943 1.82153,0.674 3.67762,1.04383 5.61666,1.04383 h 22.121021 c 1.9425,0 3.79859,-0.37329 5.62012,-1.04383 20.6935,-7.64212 50.85065,-5.7411 62.87894,-6.34943 11.20221,-0.55993 19.98493,-9.4982 19.98493,-20.35477 V 22.904703 C 199.54678,11.657559 190.0757,2.5084522 178.43105,2.5084522 Z"
id="path835"
style="fill:none;fill-opacity:1;stroke:#ddbf86;stroke-width:0.91445;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
sodipodi:nodetypes="sccccsssccssccscs" />
<g
id="g1062-7"
transform="matrix(0.29031165,0.23248306,-0.29632355,0.23741836,21.63667,1.1307691)"
style="fill:none;stroke:#ddbf86;stroke-opacity:1">
<g
id="g1005-6"
style="fill:none;stroke:#ddbf86;stroke-opacity:1">
<g
id="g1003-5"
style="fill:none;stroke:#ddbf86;stroke-opacity:1">
<path
d="M 15.875,42.952 H 4.847 L 22.627,60.731 40.409,42.952 H 29.244 C 30.824,22.001 41.734,5.075 55.884,0.96 53.726,0.332 51.49,0 49.2,0 31.919,0 17.694,18.8 15.875,42.952 Z"
id="path1001-2"
style="fill:none;stroke:#ddbf86;stroke-opacity:1" />
</g>
</g>
<g
id="g1007-2"
style="fill:none;stroke:#ddbf86;stroke-opacity:1" />
<g
id="g1009-3"
style="fill:none;stroke:#ddbf86;stroke-opacity:1" />
<g
id="g1011-2"
style="fill:none;stroke:#ddbf86;stroke-opacity:1" />
<g
id="g1013-4"
style="fill:none;stroke:#ddbf86;stroke-opacity:1" />
<g
id="g1015-3"
style="fill:none;stroke:#ddbf86;stroke-opacity:1" />
<g
id="g1017-6"
style="fill:none;stroke:#ddbf86;stroke-opacity:1" />
<g
id="g1019-6"
style="fill:none;stroke:#ddbf86;stroke-opacity:1" />
<g
id="g1021-8"
style="fill:none;stroke:#ddbf86;stroke-opacity:1" />
<g
id="g1023-0"
style="fill:none;stroke:#ddbf86;stroke-opacity:1" />
<g
id="g1025-1"
style="fill:none;stroke:#ddbf86;stroke-opacity:1" />
<g
id="g1027-2"
style="fill:none;stroke:#ddbf86;stroke-opacity:1" />
<g
id="g1029-1"
style="fill:none;stroke:#ddbf86;stroke-opacity:1" />
<g
id="g1031-6"
style="fill:none;stroke:#ddbf86;stroke-opacity:1" />
<g
id="g1033-7"
style="fill:none;stroke:#ddbf86;stroke-opacity:1" />
<g
id="g1035-8"
style="fill:none;stroke:#ddbf86;stroke-opacity:1" />
</g>
<path
d="m 186.65756,15.01934 3.20156,-2.563823 0.10659,8.35461 -10.43065,-0.08705 3.24132,-2.595673 c -6.66696,-4.606829 -14.84983,-6.088982 -20.17712,-3.776323 0.44041,-0.650797 0.99116,-1.249452 1.65598,-1.781838 5.01687,-4.0175396 14.71744,-2.8611469 22.40232,2.450095 z"
id="path1001"
style="fill:none;stroke:#ddbf86;stroke-width:0.371235;stroke-opacity:1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@@ -1,81 +1,34 @@
{% extends "base.html" %}
{% load custom_tags %}
{% load render_bundle from webpack_loader %}
{% load static %}
{% load i18n %}
{% load l10n %}
{% block title %}{% trans 'Recipe Books' %}{% endblock %}
{% block content_fluid %}
{% block content %}
<div class="row">
<div class="col col-md-9">
<h2>{% trans 'Recipe Books' %}</h2>
</div>
<div class="col col-md-3" style="text-align: right">
<a href="{% url 'new_recipe_book' %}" class="btn btn-success"><i
class="fas fa-plus-circle"></i> {% trans 'New Book' %}</a>
</div>
<div id="app" >
<cookbook-view></cookbook-view>
</div>
<br/>
<br/>
{% for b in book_list %}
<div class="row">
<div class="col-12">
<div class="card" style="margin-top: 2px">
<div class="card-body">
<h5 class="card-title">{% if b.book.icon %}{{ b.book.icon }} {% endif %}{{ b.book.name }}</h5>
<h6 class="card-subtitle mb-2 text-muted">{% if b.book.created_by != request.user %}
{% trans 'by' %} {{ b.book.created_by.get_user_name }}
{% endif %}</h6>
{% if b.book.description %}
<p class="card-text">{{ b.book.description }}</p>
{% endif %}
<a data-toggle="collapse" href="#collapse_{{ b.book.pk }}" role="button" aria-expanded="false"
aria-controls="collapse_{{ b.book.pk }}" class="card-link">{% trans 'Toggle Recipes' %}</a>
{% if b.book.created_by == request.user or request.user.is_superuser %}
<a href="{% url 'edit_recipe_book' b.book.pk %}" class="card-link">{% trans 'Edit' %}</a>
<a href="{% url 'delete_recipe_book' b.book.pk %}"
class="card-link">{% trans 'Delete' %}</a>
{% endif %}
</div>
<div class="collapse" id="collapse_{{ b.book.pk }}">
{% if b.recipes %}
<ul class="list-group list-group-flush">
{% for r in b.recipes %}
<li class="list-group-item">
<div class="row">
<div class="col-10">
{% recipe_last r.recipe request.user as last_cooked %}
<a href="{% url 'view_recipe' r.recipe.pk %}">{{ r.recipe.name }}</a>
{% recipe_rating r.recipe request.user as rating %}
{{ rating|safe }}
{% if last_cooked %}
&nbsp;
<span class="badge badge-primary">{% trans 'Last cooked' %} {{ last_cooked|date }}</span>
{% endif %}
</div>
{% if b.book.created_by == request.user or request.user.is_superuser %}
<div class="col-2" style="text-align: right">
<a href="{% url 'delete_recipe_book_entry' r.pk %}"
class="pull-right"><i class="fas fa-trash-alt"></i></a>
</div>
{% endif %}
</div>
</li>
{% endfor %}
</ul>
{% else %}
<div class="card-body">
<p>
{% trans 'There are no recipes in this book yet.' %}
</p>
</div>
{% endif %}
</div>
</div>
</div>
</div>
{% endfor %}
{% endblock %}
{% block script %}
{% if debug %}
<script src="{% url 'js_reverse' %}"></script>
{% else %}
<script src="{% static 'django_js_reverse/reverse.js' %}"></script>
{% endif %}
<script type="application/javascript">
window.IMAGE_PLACEHOLDER = "{% static 'assets/recipe_no_image.svg' %}"
window.IMAGE_BOOK = "{% static 'assets/book.svg' %}"
window.CUSTOM_LOCALE = '{{ request.LANGUAGE_CODE }}'
</script>
{% render_bundle 'cookbook_view' %}
{% endblock %}

View File

@@ -213,20 +213,7 @@ def recipe_view(request, pk, share=None):
@group_required('user')
def books(request):
book_list = []
recipe_books = RecipeBook.objects.filter(Q(created_by=request.user) | Q(shared=request.user),
space=request.space).distinct().all()
for b in recipe_books:
book_list.append(
{
'book': b,
'recipes': RecipeBookEntry.objects.filter(book=b).all()
}
)
return render(request, 'books.html', {'book_list': book_list})
return render(request, 'books.html', {})
@group_required('user')