Added 'supply' page to create negative register transactions, updated translation
This commit is contained in:
parent
80b407069d
commit
86ea7c0000
10 changed files with 278 additions and 68 deletions
|
@ -49,6 +49,10 @@ class CustomUserAdmin(UserAdmin):
|
|||
{"fields": ("balance", "allow_order_with_negative_balance")},
|
||||
))
|
||||
fieldsets_.insert(2, (
|
||||
"Supply",
|
||||
{"fields": ("allowed_to_supply",)},
|
||||
))
|
||||
fieldsets_.insert(3, (
|
||||
"Profile Picture",
|
||||
{"fields": ("profile_picture_filename",)},
|
||||
))
|
||||
|
|
|
@ -21,6 +21,7 @@ class User(AbstractUser):
|
|||
balance = models.DecimalField(max_digits=8, decimal_places=2, default=0.00)
|
||||
allow_order_with_negative_balance = models.BooleanField(default=False)
|
||||
profile_picture_filename = models.CharField(default="default.svg", max_length=25)
|
||||
allowed_to_supply = models.BooleanField(default=False)
|
||||
|
||||
def delete(self, *args, **kwargs):
|
||||
self.balance = 0
|
||||
|
|
61
application/app/templates/supply.html
Normal file
61
application/app/templates/supply.html
Normal file
|
@ -0,0 +1,61 @@
|
|||
{% extends "baseLayout.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% load l10n %}
|
||||
|
||||
{% block title %}
|
||||
{% translate "Drinks - Supply" %}
|
||||
{% endblock %}
|
||||
|
||||
{% block headAdditional %}
|
||||
<link rel="stylesheet" href="/static/css/supply.css">
|
||||
<link rel="stylesheet" href="/static/css/customNumberInput.css">
|
||||
{% endblock %}
|
||||
|
||||
{% block heading %}
|
||||
{% translate "Supply" %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% if user.is_superuser or user.allowed_to_supply %}
|
||||
|
||||
<form id="supplyForm">
|
||||
{% csrf_token %}
|
||||
|
||||
<div class="row">
|
||||
<div class="column">{% translate "Description" %}:</div>
|
||||
<input type="text" name="supplyDescription" id="supplyDescription" autofocus>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="column">{% translate "Price" %} ({{ currency_suffix }}):</div>
|
||||
<div class="column">
|
||||
<input type="number" name="supplyPrice" id="supplyPrice" max="9999.99" min="1.00" step="0.01">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="statusInfo"></div>
|
||||
|
||||
<div class="horizontalButtonList">
|
||||
<a href="/" class="button">{% translate "cancel" %}</a>
|
||||
<input type="submit" id="supplySubmitBtn" class="button" value='{% translate "submit" %}'>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
<script src="/static/js/supply.js"></script>
|
||||
<script src="/static/js/customNumberInput.js"></script>
|
||||
|
||||
{% else %}
|
||||
|
||||
<div class="centeringFlex">
|
||||
<p>{% translate "You are not allowed to view this site." %}</p>
|
||||
<a href="/">{% translate "back" %}</a>
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
|
||||
<script src="/static/js/autoreload.js"></script>
|
||||
|
||||
{% endblock %}
|
|
@ -32,6 +32,9 @@
|
|||
{% if user.is_superuser or user.is_staff %}
|
||||
<a class="button dropDownChoice" href="/admin/">Admin Panel</a>
|
||||
{% endif %}
|
||||
{% if user.is_superuser or user.allowed_to_supply %}
|
||||
<a class="button dropDownChoice" href="/supply/">{% translate "Supply" %}</a>
|
||||
{% endif %}
|
||||
<a class="button dropDownChoice" href="/accounts/password_change/">{% translate "Change Password" %}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -10,6 +10,7 @@ urlpatterns = [
|
|||
path('history/', views.history),
|
||||
path('deposit/', views.deposit),
|
||||
path('statistics/', views.statistics),
|
||||
path('supply/', views.supply),
|
||||
path('accounts/login/', views.login_page, name="login"),
|
||||
path('accounts/logout/', auth_views.LogoutView.as_view(), name='logout'),
|
||||
path('accounts/password_change/', auth_views.PasswordChangeView.as_view(), name='password_change'),
|
||||
|
@ -18,5 +19,6 @@ urlpatterns = [
|
|||
# API #
|
||||
path('api/order-drink', views.api_order_drink),
|
||||
path('api/deposit', views.api_deposit),
|
||||
path('api/supply', views.api_supply)
|
||||
#path('api/get-statistics', views.api_get_statistics)
|
||||
]
|
|
@ -103,6 +103,10 @@ def statistics(request):
|
|||
}
|
||||
return render(request, "statistics.html", context)
|
||||
|
||||
@login_required
|
||||
def supply(request):
|
||||
return render(request, "supply.html")
|
||||
|
||||
@login_required
|
||||
def redirect_home(request):
|
||||
return HttpResponseRedirect("/")
|
||||
|
@ -132,7 +136,7 @@ def api_order_drink(request):
|
|||
else:
|
||||
return HttpResponse("notAvailable", status=400)
|
||||
|
||||
else: raise Exception("Balance below zero.")
|
||||
else: raise Exception("Unexpected input or missing privileges.")
|
||||
|
||||
except Exception as e:
|
||||
print(f"An exception occured while processing an order: User: {user.username} - Exception: {e}", file=sys.stderr)
|
||||
|
@ -163,5 +167,33 @@ def api_deposit(request):
|
|||
else: raise Exception("Deposit amount too big or small.")
|
||||
|
||||
except Exception as e:
|
||||
print(f"An exception occured while processing an transaction: User: {user.username} - Exception: {e}", file=sys.stderr)
|
||||
print(f"An exception occured while processing a transaction: User: {user.username} - Exception: {e}", file=sys.stderr)
|
||||
return HttpResponse(b"", status=500)
|
||||
|
||||
@login_required
|
||||
def api_supply(request):
|
||||
|
||||
# check request -> supply
|
||||
|
||||
user = request.user
|
||||
|
||||
try:
|
||||
|
||||
price = decimal.Decimal(request.POST["supplyPrice"])
|
||||
description = str(request.POST["supplyDescription"])
|
||||
|
||||
if 0.00 < price < 9999.99 and (user.allowed_to_supply or user.is_superuser):
|
||||
# create transaction
|
||||
RegisterTransaction.objects.create(
|
||||
transaction_sum=-price,
|
||||
comment=f"Supply: {description}",
|
||||
is_user_deposit=False,
|
||||
user=user
|
||||
)
|
||||
#
|
||||
return HttpResponse("success", status=200)
|
||||
else: raise Exception("Unexpected input or missing privileges.")
|
||||
|
||||
except Exception as e:
|
||||
print(f"An exception occured while processing a supply transaction: User: {user.username} - Exception: {e}", file=sys.stderr)
|
||||
return HttpResponse(b"", status=500)
|
||||
|
|
Binary file not shown.
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-06-13 19:01+0200\n"
|
||||
"POT-Creation-Date: 2022-10-15 19:20+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: Julian Müller (W13R)\n"
|
||||
"Language: DE\n"
|
||||
|
@ -17,221 +17,266 @@ msgstr ""
|
|||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: app/templates/admin/base_site.html:7
|
||||
#: application/app/templates/admin/base_site.html:7
|
||||
msgid "Django site admin"
|
||||
msgstr "Django Administrator"
|
||||
|
||||
#: app/templates/admin/base_site.html:15
|
||||
#: application/app/templates/admin/base_site.html:15
|
||||
msgid "Django administration"
|
||||
msgstr "Django Administration"
|
||||
|
||||
#: app/templates/baseLayout.html:41
|
||||
#: application/app/templates/baseLayout.html:41
|
||||
msgid "An error occured. Please log out and log in again."
|
||||
msgstr "Ein Fehler ist aufgetreten. Bitte ab- und wieder anmelden."
|
||||
|
||||
#: app/templates/deposit.html:6
|
||||
#: application/app/templates/deposit.html:6
|
||||
msgid "Drinks - Deposit"
|
||||
msgstr "Getränke - Einzahlen"
|
||||
|
||||
#: app/templates/deposit.html:14 app/templates/userPanel.html:19
|
||||
#: application/app/templates/deposit.html:14
|
||||
#: application/app/templates/userPanel.html:23
|
||||
msgid "Deposit"
|
||||
msgstr "Einzahlen"
|
||||
|
||||
#: app/templates/deposit.html:23
|
||||
#: application/app/templates/deposit.html:23
|
||||
msgid "Amount"
|
||||
msgstr "Summe"
|
||||
|
||||
#: app/templates/deposit.html:31 app/templates/order.html:72
|
||||
#: app/templates/registration/login.html:56
|
||||
#: application/app/templates/deposit.html:31
|
||||
#: application/app/templates/order.html:72
|
||||
#: application/app/templates/registration/login.html:57
|
||||
#: application/app/templates/supply.html:41
|
||||
msgid "cancel"
|
||||
msgstr "Abbrechen"
|
||||
|
||||
#: app/templates/deposit.html:32
|
||||
#: application/app/templates/deposit.html:32
|
||||
msgid "confirm"
|
||||
msgstr "Bestätigen"
|
||||
|
||||
#: app/templates/history.html:6
|
||||
#: application/app/templates/history.html:6
|
||||
msgid "Drinks - History"
|
||||
msgstr "Getränke - Verlauf"
|
||||
|
||||
#: app/templates/history.html:14 app/templates/userPanel.html:25
|
||||
#: application/app/templates/history.html:14
|
||||
#: application/app/templates/userPanel.html:30
|
||||
msgid "History"
|
||||
msgstr "Verlauf"
|
||||
|
||||
#: app/templates/history.html:22
|
||||
#: application/app/templates/history.html:22
|
||||
msgid "last 30 actions"
|
||||
msgstr "letzte 30 Vorgänge"
|
||||
|
||||
#: app/templates/history.html:33 app/templates/statistics.html:41
|
||||
#: app/templates/statistics.html:61 app/templates/statistics.html:81
|
||||
#: app/templates/statistics.html:101 app/templates/statistics.html:121
|
||||
#: app/templates/statistics.html:141
|
||||
#: application/app/templates/history.html:33
|
||||
#: application/app/templates/statistics.html:41
|
||||
#: application/app/templates/statistics.html:61
|
||||
#: application/app/templates/statistics.html:81
|
||||
#: application/app/templates/statistics.html:101
|
||||
#: application/app/templates/statistics.html:121
|
||||
#: application/app/templates/statistics.html:141
|
||||
msgid "No history."
|
||||
msgstr "Kein Verlauf verfügbar."
|
||||
|
||||
#: app/templates/index.html:6
|
||||
#: application/app/templates/index.html:6
|
||||
msgid "Drinks - Home"
|
||||
msgstr "Getränke - Home"
|
||||
|
||||
#: app/templates/index.html:14
|
||||
#: application/app/templates/index.html:14
|
||||
msgid "Available Drinks"
|
||||
msgstr "Verfügbare Getränke"
|
||||
|
||||
#: app/templates/index.html:27 app/templates/index.html:34
|
||||
#: application/app/templates/index.html:27
|
||||
#: application/app/templates/index.html:34
|
||||
msgid "available"
|
||||
msgstr "verfügbar"
|
||||
|
||||
#: app/templates/index.html:43
|
||||
#: application/app/templates/index.html:43
|
||||
msgid "No drinks available."
|
||||
msgstr "Es sind gerade keine Getränke verfügbar."
|
||||
|
||||
#: app/templates/order.html:7
|
||||
#: application/app/templates/order.html:7
|
||||
msgid "Drinks - Order"
|
||||
msgstr "Getränke - Bestellen"
|
||||
|
||||
#: app/templates/order.html:16
|
||||
#: application/app/templates/order.html:16
|
||||
#: packages/django/forms/formsets.py:405 packages/django/forms/formsets.py:412
|
||||
msgid "Order"
|
||||
msgstr "Bestellung"
|
||||
|
||||
#: app/templates/order.html:29
|
||||
#: application/app/templates/order.html:29
|
||||
msgid "Drink"
|
||||
msgstr "Getränk"
|
||||
|
||||
#: app/templates/order.html:34
|
||||
#: application/app/templates/order.html:34
|
||||
msgid "Price per Item"
|
||||
msgstr "Preis pro Getränk"
|
||||
|
||||
#: app/templates/order.html:40
|
||||
#: application/app/templates/order.html:40
|
||||
msgid "Available"
|
||||
msgstr "Verfügbar"
|
||||
|
||||
#: app/templates/order.html:46
|
||||
#: application/app/templates/order.html:46
|
||||
msgid "Count"
|
||||
msgstr "Anzahl"
|
||||
|
||||
#: app/templates/order.html:63
|
||||
#: application/app/templates/order.html:63
|
||||
msgid "Sum"
|
||||
msgstr "Summe"
|
||||
|
||||
#: app/templates/order.html:73
|
||||
#: application/app/templates/order.html:73
|
||||
msgid "order"
|
||||
msgstr "Bestellen"
|
||||
|
||||
#: app/templates/order.html:85
|
||||
#: application/app/templates/order.html:85
|
||||
msgid "Your balance is too low to order a drink."
|
||||
msgstr "Dein Saldo ist zu niedrig um Getränke zu bestellen."
|
||||
|
||||
#: app/templates/order.html:86 app/templates/order.html:95
|
||||
#: application/app/templates/order.html:86
|
||||
#: application/app/templates/order.html:95
|
||||
#: application/app/templates/supply.html:54
|
||||
msgid "back"
|
||||
msgstr "zurück"
|
||||
|
||||
#: app/templates/order.html:94
|
||||
#: application/app/templates/order.html:94
|
||||
msgid "This drink is not available."
|
||||
msgstr "Dieses Getränk ist gerade nicht verfügbar."
|
||||
|
||||
#: app/templates/registration/logged_out.html:7
|
||||
#: application/app/templates/registration/logged_out.html:7
|
||||
msgid "Drinks - Logged Out"
|
||||
msgstr "Getränke - Abgemeldet"
|
||||
|
||||
#: app/templates/registration/logged_out.html:17
|
||||
#: application/app/templates/registration/logged_out.html:17
|
||||
msgid "Logged out! You will be redirected shortly."
|
||||
msgstr "Du wurdest abgemeldet und wirst in Kürze weitergeleitet."
|
||||
|
||||
#: app/templates/registration/logged_out.html:19
|
||||
#: application/app/templates/registration/logged_out.html:19
|
||||
msgid "Click here if automatic redirection does not work."
|
||||
msgstr ""
|
||||
"Bitte klicke hier, wenn die automatische Weiterleitung nicht funktioniert."
|
||||
|
||||
#: app/templates/registration/login.html:7
|
||||
#: application/app/templates/registration/login.html:8
|
||||
msgid "Drinks - Login"
|
||||
msgstr "Getränke - Anmeldung"
|
||||
|
||||
#: app/templates/registration/login.html:26
|
||||
#: application/app/templates/registration/login.html:27
|
||||
msgid "Log in"
|
||||
msgstr "Anmelden"
|
||||
|
||||
#: app/templates/registration/login.html:28
|
||||
#: application/app/templates/registration/login.html:29
|
||||
msgid "Password/PIN"
|
||||
msgstr "Passwort/PIN"
|
||||
|
||||
#: app/templates/registration/login.html:57
|
||||
#: application/app/templates/registration/login.html:58
|
||||
msgid "login"
|
||||
msgstr "Anmelden"
|
||||
|
||||
#: app/templates/registration/login.html:65
|
||||
#: application/app/templates/registration/login.html:66
|
||||
msgid "Choose your account"
|
||||
msgstr "Wähle deinen Account"
|
||||
|
||||
#: app/templates/statistics.html:6
|
||||
#: application/app/templates/statistics.html:6
|
||||
msgid "Drinks - Statistics"
|
||||
msgstr "Getränke - Statistiken"
|
||||
|
||||
#: app/templates/statistics.html:15 app/templates/userPanel.html:26
|
||||
#: application/app/templates/statistics.html:15
|
||||
#: application/app/templates/userPanel.html:31
|
||||
msgid "Statistics"
|
||||
msgstr "Statistiken"
|
||||
|
||||
#: app/templates/statistics.html:26
|
||||
#: application/app/templates/statistics.html:26
|
||||
msgid "Your orders per drink"
|
||||
msgstr "Deine Bestellungen pro Getränk"
|
||||
|
||||
#: app/templates/statistics.html:30 app/templates/statistics.html:50
|
||||
#: application/app/templates/statistics.html:30
|
||||
#: application/app/templates/statistics.html:50
|
||||
msgid "drink"
|
||||
msgstr "Getränk"
|
||||
|
||||
#: app/templates/statistics.html:31 app/templates/statistics.html:51
|
||||
#: app/templates/statistics.html:71 app/templates/statistics.html:91
|
||||
#: app/templates/statistics.html:111 app/templates/statistics.html:131
|
||||
#: application/app/templates/statistics.html:31
|
||||
#: application/app/templates/statistics.html:51
|
||||
#: application/app/templates/statistics.html:71
|
||||
#: application/app/templates/statistics.html:91
|
||||
#: application/app/templates/statistics.html:111
|
||||
#: application/app/templates/statistics.html:131
|
||||
msgid "count"
|
||||
msgstr "Anzahl"
|
||||
|
||||
#: app/templates/statistics.html:46
|
||||
#: application/app/templates/statistics.html:46
|
||||
msgid "All orders per drink"
|
||||
msgstr "Alle Bestellungen pro Getränk"
|
||||
|
||||
#: app/templates/statistics.html:66
|
||||
#: application/app/templates/statistics.html:66
|
||||
msgid "Your orders per month (last 12 months)"
|
||||
msgstr "Deine Bestellungen pro Monat (letzte 12 Monate)"
|
||||
|
||||
#: app/templates/statistics.html:70 app/templates/statistics.html:90
|
||||
#: application/app/templates/statistics.html:70
|
||||
#: application/app/templates/statistics.html:90
|
||||
msgid "month"
|
||||
msgstr "Monat"
|
||||
|
||||
#: app/templates/statistics.html:86
|
||||
#: application/app/templates/statistics.html:86
|
||||
msgid "All orders per month (last 12 months)"
|
||||
msgstr "Alle Bestellungen pro Monat (letzte 12 Monate)"
|
||||
|
||||
#: app/templates/statistics.html:106
|
||||
#: application/app/templates/statistics.html:106
|
||||
msgid "Your orders per weekday"
|
||||
msgstr "Deine Bestellungen pro Wochentag"
|
||||
|
||||
#: app/templates/statistics.html:110 app/templates/statistics.html:130
|
||||
#: application/app/templates/statistics.html:110
|
||||
#: application/app/templates/statistics.html:130
|
||||
msgid "day"
|
||||
msgstr "Tag"
|
||||
|
||||
#: app/templates/statistics.html:126
|
||||
#: application/app/templates/statistics.html:126
|
||||
msgid "All orders per weekday"
|
||||
msgstr "Alle Bestellungen pro Wochentag"
|
||||
|
||||
#: app/templates/userPanel.html:6 app/templates/userPanel.html:8
|
||||
#: application/app/templates/supply.html:7
|
||||
msgid "Drinks - Supply"
|
||||
msgstr "Getränke - Beschaffung"
|
||||
|
||||
#: application/app/templates/supply.html:16
|
||||
#: application/app/templates/userPanel.html:36
|
||||
msgid "Supply"
|
||||
msgstr "Beschaffung"
|
||||
|
||||
#: application/app/templates/supply.html:27
|
||||
msgid "Description"
|
||||
msgstr "Beschreibung"
|
||||
|
||||
#: application/app/templates/supply.html:32
|
||||
msgid "Price"
|
||||
msgstr "Preis"
|
||||
|
||||
#: application/app/templates/supply.html:42
|
||||
msgid "submit"
|
||||
msgstr "Senden"
|
||||
|
||||
#: application/app/templates/supply.html:53
|
||||
msgid "You are not allowed to view this site."
|
||||
msgstr "Dir fehlt die Berechtigung, diese Seite anzuzeigen."
|
||||
|
||||
#: application/app/templates/userPanel.html:9
|
||||
#: application/app/templates/userPanel.html:11
|
||||
msgid "User"
|
||||
msgstr "Benutzer"
|
||||
|
||||
#: app/templates/userPanel.html:12 app/templates/userPanel.html:14
|
||||
#: application/app/templates/userPanel.html:15
|
||||
#: application/app/templates/userPanel.html:17
|
||||
msgid "Balance"
|
||||
msgstr "Saldo"
|
||||
|
||||
#: app/templates/userPanel.html:22
|
||||
msgid "Account"
|
||||
msgstr "Account"
|
||||
|
||||
#: app/templates/userPanel.html:30
|
||||
msgid "Change Password"
|
||||
msgstr "Passwort ändern"
|
||||
|
||||
#: app/templates/userPanel.html:31
|
||||
#: application/app/templates/userPanel.html:24
|
||||
msgid "Logout"
|
||||
msgstr "Abmelden"
|
||||
|
||||
#: app/views.py:47
|
||||
#: application/app/templates/userPanel.html:27
|
||||
msgid "Account"
|
||||
msgstr "Account"
|
||||
|
||||
#: application/app/templates/userPanel.html:38
|
||||
msgid "Change Password"
|
||||
msgstr "Passwort ändern"
|
||||
|
||||
#: application/app/views.py:47
|
||||
msgid "Invalid username or password."
|
||||
msgstr "Benutzername oder Passwort ungültig."
|
||||
|
|
6
static/css/supply.css
Normal file
6
static/css/supply.css
Normal file
|
@ -0,0 +1,6 @@
|
|||
form {
|
||||
width: 24rem;
|
||||
}
|
||||
#supplyPrice {
|
||||
width: 10rem;
|
||||
}
|
56
static/js/supply.js
Normal file
56
static/js/supply.js
Normal file
|
@ -0,0 +1,56 @@
|
|||
document.addEventListener("DOMContentLoaded", () => {
|
||||
|
||||
// elements
|
||||
|
||||
let supply_description = document.getElementById("supplyDescription");
|
||||
let supply_price = document.getElementById("supplyPrice");
|
||||
|
||||
let supply_form = document.getElementById("supplyForm");
|
||||
let status_info = document.getElementById("statusInfo");
|
||||
let supply_submit_button = document.getElementById("supplySubmitBtn");
|
||||
|
||||
// custom submit method
|
||||
|
||||
supply_form.addEventListener("submit", (event) => {
|
||||
|
||||
supply_submit_button.disabled = true;
|
||||
|
||||
event.preventDefault(); // Don't do the default submit action!
|
||||
|
||||
if (isNaN(parseFloat(supply_price.value)) || supply_description.value == "") {
|
||||
status_info.innerText = "Please enter a description and price."
|
||||
supply_submit_button.disabled = false;
|
||||
}
|
||||
|
||||
let xhr = new XMLHttpRequest();
|
||||
let formData = new FormData(supply_form);
|
||||
|
||||
xhr.addEventListener("load", (event) => {
|
||||
|
||||
status_ = event.target.status;
|
||||
response_ = event.target.responseText;
|
||||
|
||||
if (status_ == 200 && response_ == "success") {
|
||||
status_info.innerText = "Success.";
|
||||
window.location.replace("/");
|
||||
}
|
||||
else {
|
||||
status_info.classList.add("errorText");
|
||||
status_info.innerText = "An error occured.";
|
||||
window.setTimeout(() => { window.location.reload() }, 5000);
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
xhr.addEventListener("error", (event) => {
|
||||
status_info.classList.add("errorText");
|
||||
status_info.innerText = "An error occured.";
|
||||
window.setTimeout(() => { window.location.reload() }, 5000);
|
||||
})
|
||||
|
||||
xhr.open("POST", "/api/supply");
|
||||
xhr.send(formData);
|
||||
|
||||
});
|
||||
|
||||
})
|
Loading…
Add table
Add a link
Reference in a new issue