sandwitches 2.1.1__tar.gz → 2.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. {sandwitches-2.1.1 → sandwitches-2.2.0}/PKG-INFO +1 -1
  2. {sandwitches-2.1.1 → sandwitches-2.2.0}/pyproject.toml +1 -1
  3. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/admin.py +2 -1
  4. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/forms.py +2 -2
  5. sandwitches-2.2.0/src/sandwitches/migrations/0006_historicalrecipe_is_highlighted_and_more.py +22 -0
  6. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/models.py +1 -0
  7. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/settings.py +3 -0
  8. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/templates/admin/recipe_form.html +1 -1
  9. sandwitches-2.2.0/src/sandwitches/templates/components/carousel_scripts.html +59 -0
  10. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/templates/components/navbar.html +1 -1
  11. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/templates/components/rating_section.html +1 -1
  12. sandwitches-2.2.0/src/sandwitches/templates/index.html +76 -0
  13. sandwitches-2.2.0/src/sandwitches/templates/login.html +57 -0
  14. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/urls.py +3 -0
  15. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/views.py +10 -0
  16. sandwitches-2.1.1/src/sandwitches/templates/index.html +0 -42
  17. {sandwitches-2.1.1 → sandwitches-2.2.0}/README.md +0 -0
  18. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/__init__.py +0 -0
  19. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/api.py +0 -0
  20. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/asgi.py +0 -0
  21. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/feeds.py +0 -0
  22. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/locale/nl/LC_MESSAGES/django.mo +0 -0
  23. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/locale/nl/LC_MESSAGES/django.po +0 -0
  24. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/migrations/0001_initial.py +0 -0
  25. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/migrations/0002_historicalrecipe_servings_recipe_servings.py +0 -0
  26. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/migrations/0003_setting.py +0 -0
  27. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/migrations/0004_alter_setting_ai_api_key_and_more.py +0 -0
  28. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/migrations/0005_rating_comment.py +0 -0
  29. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/migrations/__init__.py +0 -0
  30. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/storage.py +0 -0
  31. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/tasks.py +0 -0
  32. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/templates/admin/admin_base.html +0 -0
  33. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/templates/admin/confirm_delete.html +0 -0
  34. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/templates/admin/dashboard.html +0 -0
  35. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/templates/admin/rating_list.html +0 -0
  36. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/templates/admin/recipe_list.html +0 -0
  37. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/templates/admin/tag_form.html +0 -0
  38. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/templates/admin/tag_list.html +0 -0
  39. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/templates/admin/task_detail.html +0 -0
  40. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/templates/admin/task_list.html +0 -0
  41. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/templates/admin/user_form.html +0 -0
  42. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/templates/admin/user_list.html +0 -0
  43. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/templates/base.html +0 -0
  44. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/templates/base_beer.html +0 -0
  45. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/templates/components/favorites_search_form.html +0 -0
  46. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/templates/components/footer.html +0 -0
  47. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/templates/components/ingredients_scripts.html +0 -0
  48. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/templates/components/ingredients_section.html +0 -0
  49. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/templates/components/instructions_section.html +0 -0
  50. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/templates/components/language_dialog.html +0 -0
  51. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/templates/components/recipe_header.html +0 -0
  52. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/templates/components/search_form.html +0 -0
  53. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/templates/components/search_scripts.html +0 -0
  54. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/templates/components/side_menu.html +0 -0
  55. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/templates/components/user_menu.html +0 -0
  56. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/templates/detail.html +0 -0
  57. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/templates/favorites.html +0 -0
  58. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/templates/partials/recipe_list.html +0 -0
  59. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/templates/recipe_form.html +0 -0
  60. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/templates/setup.html +0 -0
  61. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/templates/signup.html +0 -0
  62. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/templatetags/__init__.py +0 -0
  63. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/templatetags/custom_filters.py +0 -0
  64. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/templatetags/markdown_extras.py +0 -0
  65. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/utils.py +0 -0
  66. {sandwitches-2.1.1 → sandwitches-2.2.0}/src/sandwitches/wsgi.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: sandwitches
3
- Version: 2.1.1
3
+ Version: 2.2.0
4
4
  Summary: Add your description here
5
5
  Author: Martyn van Dijke
6
6
  Author-email: Martyn van Dijke <martijnvdijke600@gmail.com>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "sandwitches"
3
- version = "2.1.1"
3
+ version = "2.2.0"
4
4
  description = "Add your description here"
5
5
  readme = "README.md"
6
6
  authors = [
@@ -42,7 +42,8 @@ class CustomUserAdmin(UserAdmin):
42
42
  @admin.register(Recipe)
43
43
  class RecipeAdmin(ImportExportModelAdmin):
44
44
  resource_classes = [RecipeResource]
45
- list_display = ("title", "uploaded_by", "created_at", "show_url")
45
+ list_display = ("title", "uploaded_by", "created_at", "is_highlighted", "show_url")
46
+ list_editable = ("is_highlighted",)
46
47
  readonly_fields = ("created_at", "updated_at")
47
48
 
48
49
  def save_model(self, request, obj, form, change):
@@ -149,8 +149,8 @@ class RecipeForm(forms.ModelForm):
149
149
  # PIL rotates counter-clockwise by default, our 'rotation' is clockwise
150
150
  img = img.rotate(-rotation, expand=True)
151
151
  img.save(recipe.image.path)
152
- except Exception:
153
- pass
152
+ except Exception as e:
153
+ print(f"Error rotating image: {e}")
154
154
 
155
155
  if commit:
156
156
  recipe.set_tags_from_string(self.cleaned_data.get("tags_string", ""))
@@ -0,0 +1,22 @@
1
+ # Generated by Django 6.0.1 on 2026-01-17 16:48
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+ dependencies = [
8
+ ("sandwitches", "0005_rating_comment"),
9
+ ]
10
+
11
+ operations = [
12
+ migrations.AddField(
13
+ model_name="historicalrecipe",
14
+ name="is_highlighted",
15
+ field=models.BooleanField(default=False),
16
+ ),
17
+ migrations.AddField(
18
+ model_name="recipe",
19
+ name="is_highlighted",
20
+ field=models.BooleanField(default=False),
21
+ ),
22
+ ]
@@ -127,6 +127,7 @@ class Recipe(models.Model):
127
127
  options={"quality": 95},
128
128
  )
129
129
  tags = models.ManyToManyField(Tag, blank=True, related_name="recipes")
130
+ is_highlighted = models.BooleanField(default=False)
130
131
  created_at = models.DateTimeField(auto_now_add=True)
131
132
  updated_at = models.DateTimeField(auto_now=True)
132
133
  history = HistoricalRecords()
@@ -130,6 +130,9 @@ LOGGING = {
130
130
  },
131
131
  }
132
132
 
133
+ LOGIN_REDIRECT_URL = "index"
134
+ LOGOUT_REDIRECT_URL = "index"
135
+
133
136
 
134
137
  # Password validation
135
138
  # https://docs.djangoproject.com/en/5.2/ref/settings/#auth-password-validators
@@ -81,7 +81,7 @@
81
81
 
82
82
  <div class="relative mb-1" style="overflow: hidden; min-height: 200px; display: flex; align-items: center; justify-content: center;">
83
83
  {% if recipe.image %}
84
- <img src="{{ recipe.image_medium.url }}" class="responsive round" id="image-preview" style="max-height: 300px; width: 100%; object-fit: contain; transition: transform 0.3s ease;">
84
+ <img src="{{ recipe.image_medium.url }}?v={% now "U" %}" class="responsive round" id="image-preview" style="max-height: 300px; width: 100%; object-fit: contain; transition: transform 0.3s ease;">
85
85
  {% else %}
86
86
  <div class="medium-height middle-align center-align gray1 round" id="image-placeholder" style="width: 100%;">
87
87
  <i class="extra">image</i>
@@ -0,0 +1,59 @@
1
+ <script>
2
+ (function() {
3
+ const carousel = document.getElementById('highlighted-carousel');
4
+ const scrollAmount = 320; // Approximately card width + margin
5
+ let autoScrollInterval;
6
+
7
+ window.scrollCarousel = function(direction) {
8
+ if (carousel) {
9
+ const currentScroll = carousel.scrollLeft;
10
+ const maxScroll = carousel.scrollWidth - carousel.clientWidth;
11
+
12
+ let newScroll = currentScroll + (direction * scrollAmount);
13
+
14
+ // Loop functionality for manual navigation?
15
+ // Maybe just stop at ends or loop? Let's just scroll.
16
+ carousel.scrollBy({ left: direction * scrollAmount, behavior: 'smooth' });
17
+ }
18
+ }
19
+
20
+ function autoScroll() {
21
+ if (!carousel) return;
22
+
23
+ const currentScroll = carousel.scrollLeft;
24
+ const maxScroll = carousel.scrollWidth - carousel.clientWidth;
25
+
26
+ // Tolerance for float calculation
27
+ if (currentScroll >= maxScroll - 10) {
28
+ // Loop back to start
29
+ carousel.scrollTo({ left: 0, behavior: 'smooth' });
30
+ } else {
31
+ carousel.scrollBy({ left: scrollAmount, behavior: 'smooth' });
32
+ }
33
+ }
34
+
35
+ function startAutoScroll() {
36
+ stopAutoScroll(); // Clear any existing
37
+ autoScrollInterval = setInterval(autoScroll, 5000); // 5 seconds
38
+ }
39
+
40
+ function stopAutoScroll() {
41
+ if (autoScrollInterval) {
42
+ clearInterval(autoScrollInterval);
43
+ }
44
+ }
45
+
46
+ if (carousel) {
47
+ // Start auto-scroll
48
+ startAutoScroll();
49
+
50
+ // Pause on interaction
51
+ carousel.addEventListener('mouseenter', stopAutoScroll);
52
+ carousel.addEventListener('mouseleave', startAutoScroll);
53
+
54
+ // Touch events for mobile
55
+ carousel.addEventListener('touchstart', stopAutoScroll);
56
+ carousel.addEventListener('touchend', startAutoScroll);
57
+ }
58
+ })();
59
+ </script>
@@ -21,7 +21,7 @@
21
21
  <img src="https://www.w3schools.com/howto/img_avatar.png" class="circle" data-ui="#user-menu">
22
22
  {% endif %}
23
23
  {% else %}
24
- <a href="{% url 'admin:login' %}"><button class="chip transparent border white-text">{% trans "Login" %}</button></a>
24
+ <a href="{% url 'login' %}"><button class="chip transparent border white-text">{% trans "Login" %}</button></a>
25
25
  <a href="{% url 'signup' %}"><button class="chip primary">{% trans "Sign up" %}</button></a>
26
26
  {% endif %}
27
27
  </nav>
@@ -44,7 +44,7 @@
44
44
  </form>
45
45
  </article>
46
46
  {% else %}
47
- <p><a href="{% url 'admin:login' %}" class="link">{% trans "Log in" %}</a> {% trans "to rate this recipe." %}</p>
47
+ <p><a href="{% url 'login' %}" class="link">{% trans "Log in" %}</a> {% trans "to rate this recipe." %}</p>
48
48
  {% endif %}
49
49
 
50
50
  {% if all_ratings %}
@@ -0,0 +1,76 @@
1
+ {% extends "base_beer.html" %}
2
+ {% load i18n static %}
3
+
4
+ {% block title %}Sandwitches{% endblock %}
5
+
6
+ {% block extra_head %}
7
+ {{ block.super }}
8
+ <style>
9
+ @media only screen and (min-width: 992px) {
10
+ main.container {
11
+ padding-left: 10%;
12
+ padding-right: 10%;
13
+ }
14
+ }
15
+ </style>
16
+ {% endblock %}
17
+
18
+ {% block content %}
19
+ <div class="large-space"></div>
20
+
21
+ <article class="round secondary s12 m12 l12">
22
+ <div class="row align-center">
23
+ <div class="max">
24
+ <h4 class="upper">{% trans 'Sandwitches' %}</h4>
25
+ <p class="large-text">{% trans 'Sandwiches so good, they haunt you!' %}</p>
26
+ </div>
27
+ </div>
28
+ </article>
29
+
30
+ <div class="space"></div>
31
+
32
+ {% include "components/search_form.html" %}
33
+
34
+ {% if highlighted_recipes %}
35
+ <div class="large-space"></div>
36
+ <h4 class="upper center-align">{% trans 'Highlights' %}</h4>
37
+ <div class="small-space"></div>
38
+ <div class="relative">
39
+ <div class="row scroll snap no-scrollbar" id="highlighted-carousel" style="gap: 20px; flex-wrap: nowrap;">
40
+ {% for recipe in highlighted_recipes %}
41
+ <a href="{{ recipe.get_absolute_url }}">
42
+ <article class="round no-padding elevate" style="min-width: 300px; width: 300px; flex-shrink: 0; scroll-snap-align: start;">
43
+ {% if recipe.image %}
44
+ <img src="{{ recipe.image_medium.url }}" class="responsive top-round" alt="{{ recipe.title }}" style="height: 200px; object-fit: cover;">
45
+ {% else %}
46
+ <div class="primary medium-height top-round middle-align center-align" style="height:200px;">
47
+ <i class="extra">lunch_dining</i>
48
+ </div>
49
+ {% endif %}
50
+ <div class="padding">
51
+ <h5>{{ recipe.title }}</h5>
52
+ </div>
53
+ </article>
54
+ </a>
55
+ {% endfor %}
56
+ </div>
57
+
58
+ <button class="circle surface absolute left middle-align elevate" onclick="scrollCarousel(-1)" style="top: 50%; transform: translateY(-50%); left: -20px; z-index: 10;">
59
+ <i>chevron_left</i>
60
+ </button>
61
+ <button class="circle surface absolute right middle-align elevate" onclick="scrollCarousel(1)" style="top: 50%; transform: translateY(-50%); right: -20px; z-index: 10;">
62
+ <i>chevron_right</i>
63
+ </button>
64
+ </div>
65
+ {% endif %}
66
+
67
+ <div class="large-space"></div>
68
+
69
+ {% include "partials/recipe_list.html" %}
70
+
71
+ {% endblock %}
72
+
73
+ {% block page_scripts %}
74
+ {% include "components/search_scripts.html" %}
75
+ {% include "components/carousel_scripts.html" %}
76
+ {% endblock %}
@@ -0,0 +1,57 @@
1
+ {% extends "base_beer.html" %}
2
+ {% load static i18n %}
3
+ {% block title %}{% trans "Login" %}{% endblock %}
4
+
5
+ {% block content %}
6
+ <div class="large-space"></div>
7
+
8
+ <div class="grid">
9
+ <div class="s12 m10 l8 xl6 middle-align center-align" style="margin: 0 auto;">
10
+ <article class="round elevate">
11
+ <div class="padding">
12
+ <h4 class="center-align primary-text">{% trans "Login to your account" %}</h4>
13
+ <p class="center-align">{% trans "Welcome back!" %}</p>
14
+ </div>
15
+
16
+ <form method="post" novalidate>
17
+ {% csrf_token %}
18
+
19
+ {% if form.non_field_errors %}
20
+ <div class="padding error surface round mb">
21
+ {% for error in form.non_field_errors %}
22
+ <div class="row align-center">
23
+ <i class="error-text">warning</i>
24
+ <span class="error-text">{{ error }}</span>
25
+ </div>
26
+ {% endfor %}
27
+ </div>
28
+ {% endif %}
29
+
30
+ <div class="field label border round {% if form.username.errors %}error{% endif %}">
31
+ <input type="text" name="{{ form.username.name }}" id="{{ form.username.id_for_label }}" value="{{ form.username.value|default:'' }}">
32
+ <label>{% trans "Username" %}</label>
33
+ {% if form.username.errors %}
34
+ <span class="helper error-text">{{ form.username.errors.0 }}</span>
35
+ {% endif %}
36
+ </div>
37
+
38
+ <div class="field label border round {% if form.password.errors %}error{% endif %}">
39
+ <input type="password" name="{{ form.password.name }}" id="{{ form.password.id_for_label }}">
40
+ <label>{% trans "Password" %}</label>
41
+ {% if form.password.errors %}
42
+ <span class="helper error-text">{{ form.password.errors.0 }}</span>
43
+ {% endif %}
44
+ </div>
45
+
46
+ <div class="large-space"></div>
47
+
48
+ <nav class="right-align">
49
+ <a class="button transparent border round" href="{% url 'index' %}">{% trans "Cancel" %}</a>
50
+ <button type="submit" class="button primary round">{% trans "Login" %}</button>
51
+ </nav>
52
+
53
+ </form>
54
+ </article>
55
+ </div>
56
+ </div>
57
+ {% endblock %}
@@ -21,6 +21,7 @@ from . import views
21
21
  from .api import api
22
22
  from django.conf.urls.i18n import i18n_patterns
23
23
  from .feeds import LatestRecipesFeed # Import the feed class
24
+ from django.contrib.auth.views import LogoutView # Import LogoutView
24
25
 
25
26
 
26
27
  import os
@@ -30,6 +31,8 @@ import sys
30
31
  urlpatterns = [
31
32
  path("i18n/", include("django.conf.urls.i18n")),
32
33
  path("signup/", views.signup, name="signup"),
34
+ path("login/", views.CustomLoginView.as_view(), name="login"),
35
+ path("logout/", LogoutView.as_view(next_page="index"), name="logout"),
33
36
  path("admin/", admin.site.urls),
34
37
  path("api/", api.urls),
35
38
  path("media/<path:file_path>", views.media, name="media"),
@@ -23,12 +23,19 @@ import mimetypes
23
23
  from PIL import Image
24
24
  from django.db.models import Q, Avg
25
25
  from django_tasks.backends.database.models import DBTaskResult
26
+ from django.contrib.auth.views import LoginView
27
+
26
28
 
27
29
  from sandwitches import __version__ as sandwitches_version
28
30
 
29
31
  User = get_user_model()
30
32
 
31
33
 
34
+ class CustomLoginView(LoginView):
35
+ template_name = "login.html"
36
+ redirect_authenticated_user = True
37
+
38
+
32
39
  @staff_member_required
33
40
  def admin_dashboard(request):
34
41
  recipe_count = Recipe.objects.count() # ty:ignore[unresolved-attribute]
@@ -556,6 +563,8 @@ def index(request):
556
563
  uploaders = User.objects.filter(recipes__isnull=False).distinct()
557
564
  tags = Tag.objects.all() # ty:ignore[unresolved-attribute]
558
565
 
566
+ highlighted_recipes = Recipe.objects.filter(is_highlighted=True) # ty:ignore[unresolved-attribute]
567
+
559
568
  return render(
560
569
  request,
561
570
  "index.html",
@@ -566,6 +575,7 @@ def index(request):
566
575
  "tags": tags,
567
576
  "selected_tags": request.GET.getlist("tag"),
568
577
  "user": request.user, # Pass user to template
578
+ "highlighted_recipes": highlighted_recipes,
569
579
  },
570
580
  )
571
581
 
@@ -1,42 +0,0 @@
1
- {% extends "base_beer.html" %}
2
- {% load i18n static %}
3
-
4
- {% block title %}Sandwitches{% endblock %}
5
-
6
- {% block extra_head %}
7
- {{ block.super }}
8
- <style>
9
- @media only screen and (min-width: 992px) {
10
- main.container {
11
- padding-left: 10%;
12
- padding-right: 10%;
13
- }
14
- }
15
- </style>
16
- {% endblock %}
17
-
18
- {% block content %}
19
- <div class="large-space"></div>
20
-
21
- <article class="round secondary s12 m12 l12">
22
- <div class="row align-center">
23
- <div class="max">
24
- <h4 class="upper">{% trans 'Sandwitches' %}</h4>
25
- <p class="large-text">{% trans 'Sandwiches so good, they haunt you!' %}</p>
26
- </div>
27
- </div>
28
- </article>
29
-
30
- <div class="space"></div>
31
-
32
- {% include "components/search_form.html" %}
33
-
34
- <div class="large-space"></div>
35
-
36
- {% include "partials/recipe_list.html" %}
37
-
38
- {% endblock %}
39
-
40
- {% block page_scripts %}
41
- {% include "components/search_scripts.html" %}
42
- {% endblock %}
File without changes