sandwitches 2.2.0__py3-none-any.whl → 2.3.1__py3-none-any.whl
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.
- sandwitches/admin.py +23 -2
- sandwitches/api.py +22 -1
- sandwitches/forms.py +49 -0
- sandwitches/management/__init__.py +0 -0
- sandwitches/management/commands/__init__.py +0 -0
- sandwitches/management/commands/reset_daily_orders.py +14 -0
- sandwitches/migrations/0007_historicalrecipe_price_recipe_price_order.py +86 -0
- sandwitches/migrations/0008_historicalrecipe_daily_orders_count_and_more.py +36 -0
- sandwitches/migrations/0009_historicalrecipe_is_approved_recipe_is_approved.py +22 -0
- sandwitches/models.py +63 -1
- sandwitches/settings.py +1 -0
- sandwitches/tasks.py +74 -0
- sandwitches/templates/admin/admin_base.html +4 -0
- sandwitches/templates/admin/dashboard.html +125 -61
- sandwitches/templates/admin/order_list.html +30 -0
- sandwitches/templates/admin/partials/dashboard_charts.html +90 -0
- sandwitches/templates/admin/partials/order_rows.html +28 -0
- sandwitches/templates/admin/rating_list.html +2 -0
- sandwitches/templates/admin/recipe_form.html +26 -0
- sandwitches/templates/admin/recipe_list.html +65 -15
- sandwitches/templates/base.html +12 -0
- sandwitches/templates/components/navbar.html +10 -5
- sandwitches/templates/components/recipe_header.html +17 -0
- sandwitches/templates/components/side_menu.html +4 -0
- sandwitches/templates/partials/recipe_list.html +7 -0
- sandwitches/templates/profile.html +95 -0
- sandwitches/templates/recipe_form.html +15 -1
- sandwitches/urls.py +9 -0
- sandwitches/views.py +178 -21
- {sandwitches-2.2.0.dist-info → sandwitches-2.3.1.dist-info}/METADATA +1 -1
- {sandwitches-2.2.0.dist-info → sandwitches-2.3.1.dist-info}/RECORD +32 -22
- {sandwitches-2.2.0.dist-info → sandwitches-2.3.1.dist-info}/WHEEL +0 -0
|
@@ -127,37 +127,147 @@
|
|
|
127
127
|
|
|
128
128
|
|
|
129
129
|
|
|
130
|
-
|
|
130
|
+
<!-- Charts Section -->
|
|
131
131
|
|
|
132
|
-
<div class="s12 m6">
|
|
133
132
|
|
|
134
|
-
<article class="round border padding">
|
|
135
133
|
|
|
136
|
-
<
|
|
134
|
+
<div class="s12">
|
|
137
135
|
|
|
138
|
-
<canvas id="recipeChart" style="width:100%; max-height:300px;"></canvas>
|
|
139
136
|
|
|
140
|
-
</article>
|
|
141
137
|
|
|
142
|
-
|
|
138
|
+
{% include "admin/partials/dashboard_charts.html" %}
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
</div>
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
{% if pending_recipes %}
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
<div class="s12">
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
<h5 class="bold error-text">{% trans "Pending Approvals" %}</h5>
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
<table class="border striped no-space">
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
<thead>
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
<tr>
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
<th>{% trans "Title" %}</th>
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
<th>{% trans "Uploader" %}</th>
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
<th>{% trans "Created At" %}</th>
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
<th class="right-align">{% trans "Actions" %}</th>
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
</tr>
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
</thead>
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
<tbody>
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
{% for recipe in pending_recipes %}
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
<tr class="pointer" onclick="location.href='{% url 'admin_recipe_edit' recipe.pk %}'">
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
<td>{{ recipe.title }}</td>
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
<td>{{ recipe.uploaded_by.username|default:"-" }}</td>
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
<td>{{ recipe.created_at|date:"SHORT_DATETIME_FORMAT" }}</td>
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
<td class="right-align">
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
<a href="{% url 'admin_recipe_approve' recipe.pk %}" class="button circle transparent" onclick="event.stopPropagation();" title="{% trans 'Approve' %}"><i>check</i></a>
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
<a href="{% url 'admin_recipe_edit' recipe.pk %}" class="button circle transparent" onclick="event.stopPropagation();"><i>edit</i></a>
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
</td>
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
</tr>
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
{% endfor %}
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
</tbody>
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
</table>
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
</div>
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
{% endif %}
|
|
143
259
|
|
|
144
|
-
<div class="s12 m6">
|
|
145
260
|
|
|
146
|
-
<article class="round border padding">
|
|
147
261
|
|
|
148
|
-
<h6 class="bold mb-1">{% trans "Average Rating Over Time (Last 30 Days)" %}</h6>
|
|
149
262
|
|
|
150
|
-
<canvas id="ratingChart" style="width:100%; max-height:300px;"></canvas>
|
|
151
263
|
|
|
152
|
-
</article>
|
|
153
264
|
|
|
154
|
-
</div>
|
|
155
265
|
|
|
266
|
+
<div class="s12">
|
|
156
267
|
|
|
157
268
|
|
|
158
|
-
<div class="s12">
|
|
159
269
|
|
|
160
|
-
|
|
270
|
+
<h5 class="bold">{% trans "Recent Recipes" %}</h5>
|
|
161
271
|
|
|
162
272
|
<table class="border striped no-space">
|
|
163
273
|
|
|
@@ -213,50 +323,4 @@
|
|
|
213
323
|
|
|
214
324
|
{% block admin_scripts %}
|
|
215
325
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
216
|
-
<script>
|
|
217
|
-
document.addEventListener('DOMContentLoaded', function() {
|
|
218
|
-
const primaryColor = getComputedStyle(document.documentElement).getPropertyValue('--primary').trim() || '#5d4037';
|
|
219
|
-
const secondaryColor = getComputedStyle(document.documentElement).getPropertyValue('--secondary').trim() || '#ff7a18';
|
|
220
|
-
|
|
221
|
-
// Recipe Chart
|
|
222
|
-
new Chart(document.getElementById('recipeChart'), {
|
|
223
|
-
type: 'line',
|
|
224
|
-
data: {
|
|
225
|
-
labels: {{ recipe_labels|safe }},
|
|
226
|
-
datasets: [{
|
|
227
|
-
label: '{% trans "Recipes Created" %}',
|
|
228
|
-
data: {{ recipe_counts|safe }},
|
|
229
|
-
borderColor: primaryColor,
|
|
230
|
-
backgroundColor: primaryColor + '33',
|
|
231
|
-
fill: true,
|
|
232
|
-
tension: 0.4
|
|
233
|
-
}]
|
|
234
|
-
},
|
|
235
|
-
options: {
|
|
236
|
-
responsive: true,
|
|
237
|
-
plugins: { legend: { display: false } },
|
|
238
|
-
scales: { y: { beginAtZero: true, ticks: { stepSize: 1 } } }
|
|
239
|
-
}
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
// Rating Chart
|
|
243
|
-
new Chart(document.getElementById('ratingChart'), {
|
|
244
|
-
type: 'bar',
|
|
245
|
-
data: {
|
|
246
|
-
labels: {{ rating_labels|safe }},
|
|
247
|
-
datasets: [{
|
|
248
|
-
label: '{% trans "Avg Rating" %}',
|
|
249
|
-
data: {{ rating_avgs|safe }},
|
|
250
|
-
backgroundColor: secondaryColor,
|
|
251
|
-
borderRadius: 4
|
|
252
|
-
}]
|
|
253
|
-
},
|
|
254
|
-
options: {
|
|
255
|
-
responsive: true,
|
|
256
|
-
plugins: { legend: { display: false } },
|
|
257
|
-
scales: { y: { min: 0, max: 10 } }
|
|
258
|
-
}
|
|
259
|
-
});
|
|
260
|
-
});
|
|
261
|
-
</script>
|
|
262
326
|
{% endblock %}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{% extends "admin/admin_base.html" %}
|
|
2
|
+
{% load i18n %}
|
|
3
|
+
|
|
4
|
+
{% block admin_title %}{% trans "Orders" %}{% endblock %}
|
|
5
|
+
|
|
6
|
+
{% block content %}
|
|
7
|
+
<div class="padding">
|
|
8
|
+
<div class="row align-center">
|
|
9
|
+
<h5 class="max">{% trans "Orders" %}</h5>
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
<div class="space"></div>
|
|
13
|
+
|
|
14
|
+
<table class="border">
|
|
15
|
+
<thead>
|
|
16
|
+
<tr>
|
|
17
|
+
<th>ID</th>
|
|
18
|
+
<th>{% trans "User" %}</th>
|
|
19
|
+
<th>{% trans "Recipe" %}</th>
|
|
20
|
+
<th>{% trans "Price" %}</th>
|
|
21
|
+
<th>{% trans "Status" %}</th>
|
|
22
|
+
<th>{% trans "Date" %}</th>
|
|
23
|
+
</tr>
|
|
24
|
+
</thead>
|
|
25
|
+
<tbody hx-get="{% url 'admin_order_list' %}" hx-trigger="every 5s">
|
|
26
|
+
{% include "admin/partials/order_rows.html" %}
|
|
27
|
+
</tbody>
|
|
28
|
+
</table>
|
|
29
|
+
</div>
|
|
30
|
+
{% endblock %}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
{% load i18n %}
|
|
2
|
+
<div class="grid" hx-get="." hx-trigger="every 30s" hx-swap="outerHTML">
|
|
3
|
+
<div class="s12 m4">
|
|
4
|
+
<article class="round border padding">
|
|
5
|
+
<h6 class="bold mb-1">{% trans "Recipes Over Time" %}</h6>
|
|
6
|
+
<canvas id="recipeChart" style="width:100%; max-height:300px;"></canvas>
|
|
7
|
+
</article>
|
|
8
|
+
</div>
|
|
9
|
+
<div class="s12 m4">
|
|
10
|
+
<article class="round border padding">
|
|
11
|
+
<h6 class="bold mb-1">{% trans "Orders Over Time" %}</h6>
|
|
12
|
+
<canvas id="orderChart" style="width:100%; max-height:300px;"></canvas>
|
|
13
|
+
</article>
|
|
14
|
+
</div>
|
|
15
|
+
<div class="s12 m4">
|
|
16
|
+
<article class="round border padding">
|
|
17
|
+
<h6 class="bold mb-1">{% trans "Avg Rating" %}</h6>
|
|
18
|
+
<canvas id="ratingChart" style="width:100%; max-height:300px;"></canvas>
|
|
19
|
+
</article>
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
<script>
|
|
23
|
+
(function() {
|
|
24
|
+
const primaryColor = getComputedStyle(document.documentElement).getPropertyValue('--primary').trim() || '#5d4037';
|
|
25
|
+
const secondaryColor = getComputedStyle(document.documentElement).getPropertyValue('--secondary').trim() || '#ff7a18';
|
|
26
|
+
const tertiaryColor = getComputedStyle(document.documentElement).getPropertyValue('--tertiary').trim() || '#4caf50';
|
|
27
|
+
|
|
28
|
+
// Recipe Chart
|
|
29
|
+
new Chart(document.getElementById('recipeChart'), {
|
|
30
|
+
type: 'line',
|
|
31
|
+
data: {
|
|
32
|
+
labels: {{ recipe_labels|safe }},
|
|
33
|
+
datasets: [{
|
|
34
|
+
label: '{% trans "Recipes" %}',
|
|
35
|
+
data: {{ recipe_counts|safe }},
|
|
36
|
+
borderColor: primaryColor,
|
|
37
|
+
backgroundColor: primaryColor + '33',
|
|
38
|
+
fill: true,
|
|
39
|
+
tension: 0.4
|
|
40
|
+
}]
|
|
41
|
+
},
|
|
42
|
+
options: {
|
|
43
|
+
responsive: true,
|
|
44
|
+
plugins: { legend: { display: false } },
|
|
45
|
+
scales: { y: { beginAtZero: true, ticks: { stepSize: 1 } } }
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// Order Chart
|
|
50
|
+
new Chart(document.getElementById('orderChart'), {
|
|
51
|
+
type: 'line',
|
|
52
|
+
data: {
|
|
53
|
+
labels: {{ order_labels|safe }},
|
|
54
|
+
datasets: [{
|
|
55
|
+
label: '{% trans "Orders" %}',
|
|
56
|
+
data: {{ order_counts|safe }},
|
|
57
|
+
borderColor: tertiaryColor,
|
|
58
|
+
backgroundColor: tertiaryColor + '33',
|
|
59
|
+
fill: true,
|
|
60
|
+
tension: 0.4
|
|
61
|
+
}]
|
|
62
|
+
},
|
|
63
|
+
options: {
|
|
64
|
+
responsive: true,
|
|
65
|
+
plugins: { legend: { display: false } },
|
|
66
|
+
scales: { y: { beginAtZero: true, ticks: { stepSize: 1 } } }
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// Rating Chart
|
|
71
|
+
new Chart(document.getElementById('ratingChart'), {
|
|
72
|
+
type: 'bar',
|
|
73
|
+
data: {
|
|
74
|
+
labels: {{ rating_labels|safe }},
|
|
75
|
+
datasets: [{
|
|
76
|
+
label: '{% trans "Avg Rating" %}',
|
|
77
|
+
data: {{ rating_avgs|safe }},
|
|
78
|
+
backgroundColor: secondaryColor,
|
|
79
|
+
borderRadius: 4
|
|
80
|
+
}]
|
|
81
|
+
},
|
|
82
|
+
options: {
|
|
83
|
+
responsive: true,
|
|
84
|
+
plugins: { legend: { display: false } },
|
|
85
|
+
scales: { y: { min: 0, max: 10 } }
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
})();
|
|
89
|
+
</script>
|
|
90
|
+
</div>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{% load i18n %}
|
|
2
|
+
{% for order in orders %}
|
|
3
|
+
<tr>
|
|
4
|
+
<td>{{ order.id }}</td>
|
|
5
|
+
<td>
|
|
6
|
+
<div class="row align-center">
|
|
7
|
+
{% if order.user.avatar %}
|
|
8
|
+
<img src="{{ order.user.avatar.url }}" class="circle tiny">
|
|
9
|
+
{% else %}
|
|
10
|
+
<i class="circle tiny">person</i>
|
|
11
|
+
{% endif %}
|
|
12
|
+
<span class="max">{{ order.user.username }}</span>
|
|
13
|
+
</div>
|
|
14
|
+
</td>
|
|
15
|
+
<td>{{ order.recipe.title }}</td>
|
|
16
|
+
<td>{{ order.total_price }} €</td>
|
|
17
|
+
<td>
|
|
18
|
+
<span class="chip {% if order.status == 'PENDING' %}surface-variant{% elif order.status == 'COMPLETED' %}primary{% else %}error{% endif %}">
|
|
19
|
+
{{ order.get_status_display }}
|
|
20
|
+
</span>
|
|
21
|
+
</td>
|
|
22
|
+
<td>{{ order.created_at|date:"d/m/Y H:i" }}</td>
|
|
23
|
+
</tr>
|
|
24
|
+
{% empty %}
|
|
25
|
+
<tr>
|
|
26
|
+
<td colspan="6" class="center-align">{% trans "No orders found." %}</td>
|
|
27
|
+
</tr>
|
|
28
|
+
{% endfor %}
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
<th>{% trans "Recipe" %}</th>
|
|
13
13
|
<th>{% trans "User" %}</th>
|
|
14
14
|
<th class="min center-align">{% trans "Score" %}</th>
|
|
15
|
+
<th>{% trans "Comment" %}</th>
|
|
15
16
|
<th>{% trans "Updated" %}</th>
|
|
16
17
|
<th class="right-align">{% trans "Actions" %}</th>
|
|
17
18
|
</tr>
|
|
@@ -27,6 +28,7 @@
|
|
|
27
28
|
<span>{{ r.score }}</span>
|
|
28
29
|
</div>
|
|
29
30
|
</td>
|
|
31
|
+
<td>{{ r.comment|default:"-"|truncatechars:50 }}</td>
|
|
30
32
|
<td>{{ r.updated_at|date:"SHORT_DATETIME_FORMAT" }}</td>
|
|
31
33
|
<td class="right-align">
|
|
32
34
|
<a href="{% url 'admin_rating_delete' r.pk %}" class="button circle transparent" title="{% trans 'Delete' %}"><i>delete</i></a>
|
|
@@ -60,6 +60,32 @@
|
|
|
60
60
|
<label>{{ form.uploaded_by.label }}</label>
|
|
61
61
|
{% if form.uploaded_by.errors %}<span class="error">{{ form.uploaded_by.errors|striptags }}</span>{% endif %}
|
|
62
62
|
</div>
|
|
63
|
+
|
|
64
|
+
<div class="field label border round mt-1">
|
|
65
|
+
{{ form.price }}
|
|
66
|
+
<label>{{ form.price.label }}</label>
|
|
67
|
+
{% if form.price.errors %}<span class="error">{{ form.price.errors|striptags }}</span>{% endif %}
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
<div class="field label border round mt-1">
|
|
71
|
+
{{ form.max_daily_orders }}
|
|
72
|
+
<label>{{ form.max_daily_orders.label }}</label>
|
|
73
|
+
{% if form.max_daily_orders.errors %}<span class="error">{{ form.max_daily_orders.errors|striptags }}</span>{% endif %}
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
<div class="field middle-align mt-1">
|
|
77
|
+
<label class="checkbox">
|
|
78
|
+
{{ form.is_highlighted }}
|
|
79
|
+
<span>{{ form.is_highlighted.label }}</span>
|
|
80
|
+
</label>
|
|
81
|
+
</div>
|
|
82
|
+
|
|
83
|
+
<div class="field middle-align mt-1">
|
|
84
|
+
<label class="checkbox">
|
|
85
|
+
{{ form.is_approved }}
|
|
86
|
+
<span>{{ form.is_approved.label }}</span>
|
|
87
|
+
</label>
|
|
88
|
+
</div>
|
|
63
89
|
</article>
|
|
64
90
|
|
|
65
91
|
<!-- Description -->
|
|
@@ -12,21 +12,48 @@
|
|
|
12
12
|
</a>
|
|
13
13
|
</div>
|
|
14
14
|
|
|
15
|
-
<table class="border striped no-space">
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
15
|
+
<table class="border striped no-space">
|
|
16
|
+
<thead>
|
|
17
|
+
<tr>
|
|
18
|
+
<th class="min">{% trans "ID" %}</th>
|
|
19
|
+
<th class="min">{% trans "Image" %}</th>
|
|
20
|
+
<th class="max">
|
|
21
|
+
<a href="?sort={% if current_sort == 'title' %}-title{% else %}title{% endif %}" class="row align-center">
|
|
22
|
+
{% trans "Title" %}
|
|
23
|
+
{% if current_sort == 'title' %}<i>arrow_upward</i>{% elif current_sort == '-title' %}<i>arrow_downward</i>{% endif %}
|
|
24
|
+
</a>
|
|
25
|
+
</th>
|
|
26
|
+
<th class="min">
|
|
27
|
+
<a href="?sort={% if current_sort == 'price' %}-price{% else %}price{% endif %}" class="row align-center">
|
|
28
|
+
{% trans "Price" %}
|
|
29
|
+
{% if current_sort == 'price' %}<i>arrow_upward</i>{% elif current_sort == '-price' %}<i>arrow_downward</i>{% endif %}
|
|
30
|
+
</a>
|
|
31
|
+
</th>
|
|
32
|
+
<th class="min">
|
|
33
|
+
<a href="?sort={% if current_sort == 'orders' %}-orders{% else %}orders{% endif %}" class="row align-center">
|
|
34
|
+
{% trans "Orders" %}
|
|
35
|
+
{% if current_sort == 'orders' %}<i>arrow_upward</i>{% elif current_sort == '-orders' %}<i>arrow_downward</i>{% endif %}
|
|
36
|
+
</a>
|
|
37
|
+
</th>
|
|
38
|
+
<th class="min">{% trans "Rating" %}</th>
|
|
39
|
+
<th class="min">{% trans "Approved" %}</th>
|
|
40
|
+
<th class="m l">{% trans "Tags" %}</th>
|
|
41
|
+
<th>
|
|
42
|
+
<a href="?sort={% if current_sort == 'uploader' %}-uploader{% else %}uploader{% endif %}" class="row align-center">
|
|
43
|
+
{% trans "Uploader" %}
|
|
44
|
+
{% if current_sort == 'uploader' %}<i>arrow_upward</i>{% elif current_sort == '-uploader' %}<i>arrow_downward</i>{% endif %}
|
|
45
|
+
</a>
|
|
46
|
+
</th>
|
|
47
|
+
<th>
|
|
48
|
+
<a href="?sort={% if current_sort == 'created_at' %}-created_at{% else %}created_at{% endif %}" class="row align-center">
|
|
49
|
+
{% trans "Created" %}
|
|
50
|
+
{% if current_sort == 'created_at' %}<i>arrow_upward</i>{% elif current_sort == '-created_at' %}<i>arrow_downward</i>{% endif %}
|
|
51
|
+
</a>
|
|
52
|
+
</th>
|
|
53
|
+
<th class="right-align">{% trans "Actions" %}</th>
|
|
54
|
+
</tr>
|
|
55
|
+
</thead>
|
|
56
|
+
<tbody> {% for recipe in recipes %}
|
|
30
57
|
<tr class="pointer" onclick="location.href='{% url 'admin_recipe_edit' recipe.pk %}'">
|
|
31
58
|
<td class="min">{{ recipe.id }}</td>
|
|
32
59
|
<td class="min">
|
|
@@ -39,14 +66,37 @@
|
|
|
39
66
|
{% endif %}
|
|
40
67
|
</td>
|
|
41
68
|
<td class="max">
|
|
69
|
+
{% if recipe.is_highlighted %}
|
|
70
|
+
<i class="tiny amber-text">star</i>
|
|
71
|
+
{% endif %}
|
|
42
72
|
<b>{{ recipe.title }}</b>
|
|
43
73
|
</td>
|
|
74
|
+
<td class="min no-wrap">
|
|
75
|
+
{% if recipe.price %}
|
|
76
|
+
{{ recipe.price }} €
|
|
77
|
+
{% else %}
|
|
78
|
+
-
|
|
79
|
+
{% endif %}
|
|
80
|
+
</td>
|
|
81
|
+
<td class="min no-wrap">
|
|
82
|
+
{{ recipe.daily_orders_count }} / {{ recipe.max_daily_orders|default:"∞" }}
|
|
83
|
+
</td>
|
|
44
84
|
<td class="min center-align">
|
|
45
85
|
<div class="row align-center">
|
|
46
86
|
<i class="primary-text">star</i>
|
|
47
87
|
<span>{{ recipe.avg_rating|default:0|floatformat:1 }}</span>
|
|
48
88
|
</div>
|
|
49
89
|
</td>
|
|
90
|
+
<td class="min center-align">
|
|
91
|
+
{% if recipe.is_approved %}
|
|
92
|
+
<i class="primary-text">check_circle</i>
|
|
93
|
+
{% else %}
|
|
94
|
+
<a href="{% url 'admin_recipe_approve' recipe.pk %}" class="button tiny primary round" onclick="event.stopPropagation();">
|
|
95
|
+
<i>check</i>
|
|
96
|
+
<span>{% trans "Approve" %}</span>
|
|
97
|
+
</a>
|
|
98
|
+
{% endif %}
|
|
99
|
+
</td>
|
|
50
100
|
<td class="m l">
|
|
51
101
|
{% for tag in recipe.tags.all %}
|
|
52
102
|
<span class="chip tiny">{{ tag.name }}</span>
|
sandwitches/templates/base.html
CHANGED
|
@@ -56,6 +56,18 @@
|
|
|
56
56
|
</svg>
|
|
57
57
|
</div>
|
|
58
58
|
{% block navbar %}{% endblock %}
|
|
59
|
+
|
|
60
|
+
{% if messages %}
|
|
61
|
+
<div class="padding no-margin">
|
|
62
|
+
{% for message in messages %}
|
|
63
|
+
<div class="snackbar active {% if message.tags == 'error' %}error{% else %}primary{% endif %}">
|
|
64
|
+
<i>{% if message.tags == 'error' %}error{% else %}info{% endif %}</i>
|
|
65
|
+
<span>{{ message }}</span>
|
|
66
|
+
</div>
|
|
67
|
+
{% endfor %}
|
|
68
|
+
</div>
|
|
69
|
+
{% endif %}
|
|
70
|
+
|
|
59
71
|
<main class="container" role="main">{% block content %}{% endblock %}</main>
|
|
60
72
|
{% block footer %}{% endblock %}
|
|
61
73
|
{% block extra_scripts %}{% endblock %}
|
|
@@ -15,11 +15,16 @@
|
|
|
15
15
|
</button>
|
|
16
16
|
|
|
17
17
|
{% if user.is_authenticated %}
|
|
18
|
-
{%
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
<a href="{% url 'user_profile' %}">
|
|
19
|
+
{% if user.avatar %}
|
|
20
|
+
<img src="{{ user.avatar.url }}" class="circle">
|
|
21
|
+
{% else %}
|
|
22
|
+
<img src="https://www.w3schools.com/howto/img_avatar.png" class="circle">
|
|
23
|
+
{% endif %}
|
|
24
|
+
</a>
|
|
25
|
+
<button class="circle transparent" data-ui="#user-menu">
|
|
26
|
+
<i>more_vert</i>
|
|
27
|
+
</button>
|
|
23
28
|
{% else %}
|
|
24
29
|
<a href="{% url 'login' %}"><button class="chip transparent border white-text">{% trans "Login" %}</button></a>
|
|
25
30
|
<a href="{% url 'signup' %}"><button class="chip primary">{% trans "Sign up" %}</button></a>
|
|
@@ -30,3 +30,20 @@
|
|
|
30
30
|
</div>
|
|
31
31
|
{% endif %}
|
|
32
32
|
</div>
|
|
33
|
+
|
|
34
|
+
<div class="space"></div>
|
|
35
|
+
{% if recipe.price %}
|
|
36
|
+
<div class="row align-center">
|
|
37
|
+
<i class="primary-text">euro_symbol</i>
|
|
38
|
+
<h5 class="bold ml-1">{{ recipe.price }}</h5>
|
|
39
|
+
{% if user.is_authenticated %}
|
|
40
|
+
<form action="{% url 'order_recipe' recipe.pk %}" method="post" class="ml-2">
|
|
41
|
+
{% csrf_token %}
|
|
42
|
+
<button type="submit" class="button primary round">
|
|
43
|
+
<i>shopping_cart</i>
|
|
44
|
+
<span>{% trans "Order Now" %}</span>
|
|
45
|
+
</button>
|
|
46
|
+
</form>
|
|
47
|
+
{% endif %}
|
|
48
|
+
</div>
|
|
49
|
+
{% endif %}
|
|
@@ -15,6 +15,10 @@
|
|
|
15
15
|
<i class="extra padding">favorite</i>
|
|
16
16
|
<span class="large-text">{% trans "Favorites" %}</span>
|
|
17
17
|
</a>
|
|
18
|
+
<a href="{% url 'submit_recipe' %}" class="padding {% if request.resolver_match.url_name == 'submit_recipe' %}active{% endif %}">
|
|
19
|
+
<i class="extra padding">add_circle</i>
|
|
20
|
+
<span class="large-text">{% trans "Submit Recipe" %}</span>
|
|
21
|
+
</a>
|
|
18
22
|
{% endif %}
|
|
19
23
|
<a href="/api/docs" class="padding">
|
|
20
24
|
<i class="extra padding">api</i>
|
|
@@ -26,6 +26,13 @@
|
|
|
26
26
|
<div class="padding">
|
|
27
27
|
<h5 class="truncate pointer" onclick="location.href='{% url 'recipe_detail' recipe.slug %}';">{{ recipe.title }}</h5>
|
|
28
28
|
|
|
29
|
+
{% if recipe.price %}
|
|
30
|
+
<div class="row align-center mb-1">
|
|
31
|
+
<i class="small-text primary-text">euro_symbol</i>
|
|
32
|
+
<span class="bold">{{ recipe.price }}</span>
|
|
33
|
+
</div>
|
|
34
|
+
{% endif %}
|
|
35
|
+
|
|
29
36
|
<div class="row align-center">
|
|
30
37
|
{% if recipe.uploaded_by %}
|
|
31
38
|
<a href="{% url 'index' %}?uploader={{ recipe.uploaded_by.username|urlencode }}" class="row align-center" style="color: inherit; text-decoration: none;">
|