sandwitches 2.1.2__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.2 → sandwitches-2.2.0}/PKG-INFO +1 -1
  2. {sandwitches-2.1.2 → sandwitches-2.2.0}/pyproject.toml +1 -1
  3. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/admin.py +2 -1
  4. sandwitches-2.2.0/src/sandwitches/migrations/0006_historicalrecipe_is_highlighted_and_more.py +22 -0
  5. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/models.py +1 -0
  6. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/settings.py +3 -0
  7. sandwitches-2.2.0/src/sandwitches/templates/components/carousel_scripts.html +59 -0
  8. sandwitches-2.2.0/src/sandwitches/templates/index.html +76 -0
  9. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/views.py +3 -0
  10. sandwitches-2.1.2/src/sandwitches/templates/index.html +0 -42
  11. {sandwitches-2.1.2 → sandwitches-2.2.0}/README.md +0 -0
  12. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/__init__.py +0 -0
  13. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/api.py +0 -0
  14. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/asgi.py +0 -0
  15. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/feeds.py +0 -0
  16. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/forms.py +0 -0
  17. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/locale/nl/LC_MESSAGES/django.mo +0 -0
  18. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/locale/nl/LC_MESSAGES/django.po +0 -0
  19. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/migrations/0001_initial.py +0 -0
  20. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/migrations/0002_historicalrecipe_servings_recipe_servings.py +0 -0
  21. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/migrations/0003_setting.py +0 -0
  22. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/migrations/0004_alter_setting_ai_api_key_and_more.py +0 -0
  23. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/migrations/0005_rating_comment.py +0 -0
  24. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/migrations/__init__.py +0 -0
  25. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/storage.py +0 -0
  26. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/tasks.py +0 -0
  27. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templates/admin/admin_base.html +0 -0
  28. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templates/admin/confirm_delete.html +0 -0
  29. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templates/admin/dashboard.html +0 -0
  30. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templates/admin/rating_list.html +0 -0
  31. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templates/admin/recipe_form.html +0 -0
  32. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templates/admin/recipe_list.html +0 -0
  33. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templates/admin/tag_form.html +0 -0
  34. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templates/admin/tag_list.html +0 -0
  35. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templates/admin/task_detail.html +0 -0
  36. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templates/admin/task_list.html +0 -0
  37. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templates/admin/user_form.html +0 -0
  38. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templates/admin/user_list.html +0 -0
  39. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templates/base.html +0 -0
  40. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templates/base_beer.html +0 -0
  41. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templates/components/favorites_search_form.html +0 -0
  42. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templates/components/footer.html +0 -0
  43. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templates/components/ingredients_scripts.html +0 -0
  44. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templates/components/ingredients_section.html +0 -0
  45. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templates/components/instructions_section.html +0 -0
  46. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templates/components/language_dialog.html +0 -0
  47. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templates/components/navbar.html +0 -0
  48. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templates/components/rating_section.html +0 -0
  49. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templates/components/recipe_header.html +0 -0
  50. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templates/components/search_form.html +0 -0
  51. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templates/components/search_scripts.html +0 -0
  52. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templates/components/side_menu.html +0 -0
  53. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templates/components/user_menu.html +0 -0
  54. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templates/detail.html +0 -0
  55. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templates/favorites.html +0 -0
  56. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templates/login.html +0 -0
  57. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templates/partials/recipe_list.html +0 -0
  58. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templates/recipe_form.html +0 -0
  59. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templates/setup.html +0 -0
  60. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templates/signup.html +0 -0
  61. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templatetags/__init__.py +0 -0
  62. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templatetags/custom_filters.py +0 -0
  63. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/templatetags/markdown_extras.py +0 -0
  64. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/urls.py +0 -0
  65. {sandwitches-2.1.2 → sandwitches-2.2.0}/src/sandwitches/utils.py +0 -0
  66. {sandwitches-2.1.2 → 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.2
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.2"
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):
@@ -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
@@ -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>
@@ -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 %}
@@ -563,6 +563,8 @@ def index(request):
563
563
  uploaders = User.objects.filter(recipes__isnull=False).distinct()
564
564
  tags = Tag.objects.all() # ty:ignore[unresolved-attribute]
565
565
 
566
+ highlighted_recipes = Recipe.objects.filter(is_highlighted=True) # ty:ignore[unresolved-attribute]
567
+
566
568
  return render(
567
569
  request,
568
570
  "index.html",
@@ -573,6 +575,7 @@ def index(request):
573
575
  "tags": tags,
574
576
  "selected_tags": request.GET.getlist("tag"),
575
577
  "user": request.user, # Pass user to template
578
+ "highlighted_recipes": highlighted_recipes,
576
579
  },
577
580
  )
578
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