diff --git a/core/static/core/style.scss b/core/static/core/style.scss
index 50892df3..6973aa75 100644
--- a/core/static/core/style.scss
+++ b/core/static/core/style.scss
@@ -42,6 +42,29 @@ body {
}
}
+[tooltip] {
+ position: relative;
+}
+
+[tooltip]:before {
+ opacity: 0;
+ z-index: 1;
+ content: attr(tooltip);
+ background: $white-color;
+ color: $black-color;
+ border: 1px solid $black-color;
+ border-radius: 5px;
+ padding: 5px;
+ top: 1em;
+ position: absolute;
+ white-space: nowrap;
+ transition: opacity 500ms ease-out;
+}
+
+[tooltip]:hover:before {
+ opacity: 1;
+}
+
.ib {
display: inline-block;
padding: 1px;
@@ -308,6 +331,7 @@ body {
font-size: 120%;
background-color: unset;
position: relative;
+
&:after {
content: '';
position: absolute;
@@ -318,14 +342,17 @@ body {
border-radius: 2px;
transition: all 0.2s ease-in-out;
}
+
&:hover:after {
border-bottom-color: darken($primary-neutral-light-color, 20%);
}
+
&.active:after {
border-bottom-color: $primary-dark-color;
}
}
}
+
section {
padding: 20px;
}
diff --git a/counter/templates/counter/fragments/create_student_card.jinja b/counter/templates/counter/fragments/create_student_card.jinja
index f8e59d24..d972ff33 100644
--- a/counter/templates/counter/fragments/create_student_card.jinja
+++ b/counter/templates/counter/fragments/create_student_card.jinja
@@ -13,10 +13,13 @@
{% trans %}No student card registered.{% endtrans %}
{% else %}
- {% trans %}Registered{% endtrans %} -
-
- {% trans %}Delete{% endtrans %}
-
+ {% trans %}Card registered{% endtrans %}
+ -
+
{% endif %}
diff --git a/counter/templates/counter/fragments/delete_student_card.jinja b/counter/templates/counter/fragments/delete_student_card.jinja
new file mode 100644
index 00000000..94be1c47
--- /dev/null
+++ b/counter/templates/counter/fragments/delete_student_card.jinja
@@ -0,0 +1,15 @@
+
\ No newline at end of file
diff --git a/counter/tests/test_customer.py b/counter/tests/test_customer.py
index b861a97e..3e745ecc 100644
--- a/counter/tests/test_customer.py
+++ b/counter/tests/test_customer.py
@@ -198,8 +198,7 @@ class TestStudentCard(TestCase):
StudentCard, customer=cls.customer.customer, uid="8A89B82018B0A0"
)
- def setUp(self):
- # Auto login on counter
+ def login_in_counter(self):
self.client.post(
reverse("counter:login", args=[self.counter.id]),
{"username": self.barmen.username, "password": "plop"},
@@ -222,6 +221,7 @@ class TestStudentCard(TestCase):
]
def test_search_user_with_student_card(self):
+ self.login_in_counter()
response = self.client.post(
reverse("counter:details", args=[self.counter.id]),
{"code": self.valid_card.uid},
@@ -233,6 +233,7 @@ class TestStudentCard(TestCase):
)
def test_add_student_card_from_counter(self):
+ self.login_in_counter()
for uid in ["8B90734A802A8F", "ABCAAAFAAFAAAB", "15248196326518"]:
customer = subscriber_user.make().customer
response = self.client.post(
@@ -251,6 +252,7 @@ class TestStudentCard(TestCase):
assert customer.student_card.uid == uid
def test_add_student_card_from_counter_fail(self):
+ self.login_in_counter()
customer = subscriber_user.make().customer
for uid, error_msg in self.invalid_uids():
response = self.client.post(
@@ -269,25 +271,15 @@ class TestStudentCard(TestCase):
assert not hasattr(customer, "student_card")
def test_add_student_card_from_counter_unauthorized(self):
- barman = subscriber_user.make()
- self.counter.sellers.add(barman)
- customer = self.customer.customer
- # There is someone logged to a counter
- # with the client of this TestCase instance,
- # so we create a new client, in order to check
- # that using a client not logged to a counter
- # where another client is logged still isn't authorized.
- client = Client()
-
def send_valid_request(counter_id):
- return client.post(
+ return self.client.post(
reverse(
- "counter:add_student_card", kwargs={"customer_id": customer.pk}
+ "counter:add_student_card", kwargs={"customer_id": self.customer.pk}
),
{"uid": "8B90734A802A8F"},
HTTP_REFERER=reverse(
"counter:click",
- kwargs={"counter_id": counter_id, "user_id": customer.pk},
+ kwargs={"counter_id": counter_id, "user_id": self.customer.pk},
),
)
@@ -295,7 +287,7 @@ class TestStudentCard(TestCase):
assert send_valid_request(self.counter.id).status_code == 403
# Send to a non bar counter
- client.force_login(self.club_admin)
+ self.client.force_login(self.club_admin)
assert send_valid_request(self.club_counter.id).status_code == 403
def test_delete_student_card_with_owner(self):
@@ -322,6 +314,24 @@ class TestStudentCard(TestCase):
self.customer.customer.refresh_from_db()
assert not hasattr(self.customer.customer, "student_card")
+ def test_delete_student_card_from_counter(self):
+ self.login_in_counter()
+ self.client.post(
+ reverse(
+ "counter:delete_student_card",
+ kwargs={"customer_id": self.customer.customer.pk},
+ ),
+ http_referer=reverse(
+ "counter:click",
+ kwargs={
+ "counter_id": self.counter.id,
+ "user_id": self.customer.customer.pk,
+ },
+ ),
+ )
+ self.customer.customer.refresh_from_db()
+ assert not hasattr(self.customer.customer, "student_card")
+
def test_delete_student_card_fail(self):
"""Test that non-admin users cannot delete student cards"""
self.client.force_login(self.subscriber)
@@ -336,7 +346,7 @@ class TestStudentCard(TestCase):
assert not hasattr(self.subscriber.customer, "student_card")
def test_add_student_card_from_user_preferences(self):
- users = [self.subscriber, self.board_admin, self.root]
+ users = [self.customer, self.board_admin, self.root]
uids = ["8B90734A802A8F", "ABCAAAFAAFAAAB", "15248196326518"]
for user, uid in itertools.product(users, uids):
self.customer.customer.student_card.delete()
@@ -353,7 +363,7 @@ class TestStudentCard(TestCase):
self.customer.customer.refresh_from_db()
assert self.customer.customer.student_card.uid == uid
- self.assertContains(response, text="Enregistré")
+ self.assertContains(response, text="Carte enregistrée")
def test_add_student_card_from_user_preferences_fail(self):
customer = subscriber_user.make()
diff --git a/counter/views/student_card.py b/counter/views/student_card.py
index 070e260d..35226e95 100644
--- a/counter/views/student_card.py
+++ b/counter/views/student_card.py
@@ -22,22 +22,32 @@ from django.utils.translation import gettext as _
from django.views.generic.edit import DeleteView, FormView
from core.utils import FormFragmentTemplateData
-from core.views import CanEditMixin
+from core.views import can_edit
from counter.forms import StudentCardForm
from counter.models import Customer, StudentCard
from counter.utils import is_logged_in_counter
-class StudentCardDeleteView(DeleteView, CanEditMixin):
- """View used to delete a card from a user."""
+class StudentCardDeleteView(DeleteView):
+ """View used to delete a card from a user. This is a fragment view !"""
model = StudentCard
- template_name = "core/delete_confirm.jinja"
+ template_name = "counter/fragments/delete_student_card.jinja"
- def dispatch(self, request, *args, **kwargs):
+ def dispatch(self, request: HttpRequest, *args, **kwargs):
self.customer = get_object_or_404(Customer, pk=kwargs["customer_id"])
+ if not is_logged_in_counter(request) and not can_edit(
+ self.get_object(), request.user
+ ):
+ raise PermissionDenied()
return super().dispatch(request, *args, **kwargs)
+ def get_context_data(self, **kwargs):
+ context = super().get_context_data(**kwargs)
+ context["action"] = self.request.path
+ context["action_cancel"] = self.get_success_url()
+ return context
+
def get_object(self, queryset=None):
if not hasattr(self.customer, "student_card"):
raise Http404(
@@ -47,7 +57,9 @@ class StudentCardDeleteView(DeleteView, CanEditMixin):
return self.customer.student_card
def get_success_url(self, **kwargs):
- return reverse("core:user_prefs", kwargs={"user_id": self.customer.user_id})
+ return reverse(
+ "counter:add_student_card", kwargs={"customer_id": self.customer.pk}
+ )
class StudentCardFormView(FormView):
diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po
index 1a2786bc..482befd3 100644
--- a/locale/fr/LC_MESSAGES/django.po
+++ b/locale/fr/LC_MESSAGES/django.po
@@ -369,7 +369,7 @@ msgstr "Compte en banque : "
#: core/templates/core/user_clubs.jinja:34
#: core/templates/core/user_clubs.jinja:63
#: core/templates/core/user_edit.jinja:62
-#: counter/templates/counter/fragments/create_student_card.jinja:18
+#: counter/templates/counter/fragments/create_student_card.jinja:22
#: counter/templates/counter/last_ops.jinja:35
#: counter/templates/counter/last_ops.jinja:65
#: election/templates/election/election_detail.jinja:191
@@ -2574,18 +2574,21 @@ msgstr "Confirmation de suppression"
#: core/templates/core/delete_confirm.jinja:16
#: core/templates/core/file_delete_confirm.jinja:29
+#: counter/templates/counter/fragments/delete_student_card.jinja:4
#, python-format
msgid "Are you sure you want to delete \"%(obj)s\"?"
msgstr "Êtes-vous sûr de vouloir supprimer \"%(obj)s\" ?"
#: core/templates/core/delete_confirm.jinja:17
#: core/templates/core/file_delete_confirm.jinja:36
+#: counter/templates/counter/fragments/delete_student_card.jinja:5
msgid "Confirm"
msgstr "Confirmation"
#: core/templates/core/delete_confirm.jinja:20
#: core/templates/core/file_delete_confirm.jinja:46
#: counter/templates/counter/counter_click.jinja:104
+#: counter/templates/counter/fragments/delete_student_card.jinja:12
#: sas/templates/sas/ask_picture_removal.jinja:20
msgid "Cancel"
msgstr "Annuler"
@@ -4044,8 +4047,13 @@ msgid "No student card registered."
msgstr "Aucune carte étudiante enregistrée."
#: counter/templates/counter/fragments/create_student_card.jinja:16
-msgid "Registered"
-msgstr "Enregistré"
+msgid "Card registered"
+msgstr "Carte enregistrée"
+
+#: counter/templates/counter/fragments/create_student_card.jinja:17
+#, python-format
+msgid "uid: %(uid)s "
+msgstr "uid: %(uid)s"
#: counter/templates/counter/invoices_call.jinja:8
#, python-format
@@ -4317,7 +4325,7 @@ msgstr "Administration des comptoirs"
msgid "Product types"
msgstr "Types de produit"
-#: counter/views/student_card.py:44
+#: counter/views/student_card.py:54
#, python-format
msgid "%(name)s has no registered student card"
msgstr "%(name)s n'a pas de carte étudiante enregistrée"