From a168ae4665f75957210325d3de98e23e74ae4c21 Mon Sep 17 00:00:00 2001
From: GDay <1939656+GDay@users.noreply.github.com>
Date: Fri, 29 Mar 2024 02:29:48 +0100
Subject: [PATCH 1/2] Allow manually adding hardware to user
---
.../templates/_toggle_button_hardware.html | 9 +++
back/admin/people/templates/add_hardware.html | 38 +++++++++++++
.../people/templates/colleague_update.html | 5 ++
back/admin/people/tests.py | 55 +++++++++++++++++++
back/admin/people/urls.py | 10 ++++
back/admin/people/views.py | 33 +++++++++++
6 files changed, 150 insertions(+)
create mode 100644 back/admin/people/templates/_toggle_button_hardware.html
create mode 100644 back/admin/people/templates/add_hardware.html
diff --git a/back/admin/people/templates/_toggle_button_hardware.html b/back/admin/people/templates/_toggle_button_hardware.html
new file mode 100644
index 000000000..4b3725b07
--- /dev/null
+++ b/back/admin/people/templates/_toggle_button_hardware.html
@@ -0,0 +1,9 @@
+{% load i18n %}
+
+
+ {% if template in object.hardware.all %}
+ {% translate "Added" %}
+ {% else %}
+ {% translate "Add" %}
+ {% endif %}
+
diff --git a/back/admin/people/templates/add_hardware.html b/back/admin/people/templates/add_hardware.html
new file mode 100644
index 000000000..5094a34cd
--- /dev/null
+++ b/back/admin/people/templates/add_hardware.html
@@ -0,0 +1,38 @@
+{% extends 'admin_base.html' %}
+{% load i18n %}
+
+{% block content %}
+
+
+
+
{% translate "Changing hardware here will not send any messages to colleagues to send out or collect hardware. Use the sequences for that instead!"%}
+
+
+
+
+
+
+
+ {% translate "Name" %} |
+ {% translate "Tags" %} |
+ |
+
+
+
+ {% for template in object_list %}
+
+ {{ template.name }} |
+ {% for tag in template.tags %}{{ tag }}{% endfor %} |
+
+ {% include "_toggle_button_hardware.html" %}
+ |
+
+ {% endfor %}
+
+
+ {% include "_paginator.html" %}
+
+
+
+{% endblock %}
diff --git a/back/admin/people/templates/colleague_update.html b/back/admin/people/templates/colleague_update.html
index 34ac4828e..ce666372d 100644
--- a/back/admin/people/templates/colleague_update.html
+++ b/back/admin/people/templates/colleague_update.html
@@ -78,6 +78,11 @@ {% translate "Hardware" %}
{% endfor %}
+
diff --git a/back/admin/people/tests.py b/back/admin/people/tests.py
index 34dd1d164..31258bdfd 100644
--- a/back/admin/people/tests.py
+++ b/back/admin/people/tests.py
@@ -2726,6 +2726,61 @@ def test_employee_toggle_resources(
assert not employee1.resources.filter(id=resource1.id).exists()
+@pytest.mark.django_db
+def test_employee_hardware(
+ client, django_user_model, employee_factory, hardware_factory
+):
+ client.force_login(
+ django_user_model.objects.create(role=get_user_model().Role.ADMIN)
+ )
+
+ employee1 = employee_factory()
+ hardware1 = hardware_factory()
+ hardware2 = hardware_factory(template=False)
+
+ url = reverse("people:add_hardware", args=[employee1.id])
+ response = client.get(url, follow=True)
+
+ assert hardware1.name in response.content.decode()
+ # Only show templates
+ assert hardware2.name not in response.content.decode()
+ assert "Added" not in response.content.decode()
+
+ # Add resource to user
+ employee1.hardware.add(hardware1)
+
+ response = client.get(url, follow=True)
+
+ # Has been added, so change button name
+ assert hardware2.name not in response.content.decode()
+ assert "Added" in response.content.decode()
+
+
+@pytest.mark.django_db
+def test_employee_toggle_hardware(
+ client, django_user_model, employee_factory, hardware_factory
+):
+ client.force_login(
+ django_user_model.objects.create(role=get_user_model().Role.ADMIN)
+ )
+
+ hardware1 = hardware_factory()
+ employee1 = employee_factory()
+
+ url = reverse("people:toggle_hardware", args=[employee1.id, hardware1.id])
+ response = client.post(url, follow=True)
+
+ assert "Added" in response.content.decode()
+ assert employee1.hardware.filter(id=hardware1.id).exists()
+
+ # Now remove the item
+ response = client.post(url, follow=True)
+
+ assert "Add" in response.content.decode()
+ assert not employee1.resources.filter(id=hardware1.id).exists()
+
+
+
@pytest.mark.django_db
def test_visibility_import_employees_button(
client,
diff --git a/back/admin/people/urls.py b/back/admin/people/urls.py
index db95391b2..830aba164 100644
--- a/back/admin/people/urls.py
+++ b/back/admin/people/urls.py
@@ -168,6 +168,16 @@
views.ColleagueResourceView.as_view(),
name="add_resource",
),
+ path(
+ "colleagues//hardware/",
+ views.ColleagueHardwareView.as_view(),
+ name="add_hardware",
+ ),
+ path(
+ "colleagues//hardware//",
+ views.ColleagueToggleHardwareView.as_view(),
+ name="toggle_hardware",
+ ),
path(
"colleagues//resource//",
views.ColleagueToggleResourceView.as_view(),
diff --git a/back/admin/people/views.py b/back/admin/people/views.py
index a5811bad5..5f9b362da 100644
--- a/back/admin/people/views.py
+++ b/back/admin/people/views.py
@@ -34,6 +34,7 @@
LoginRequiredMixin,
ManagerPermMixin,
)
+from admin.hardware.models import Hardware
from users.models import ToDoUser
from .forms import (
@@ -117,6 +118,38 @@ def get_context_data(self, **kwargs):
return context
+class ColleagueHardwareView(LoginRequiredMixin, ManagerPermMixin, DetailView):
+ template_name = "add_hardware.html"
+ model = get_user_model()
+
+ def get_context_data(self, **kwargs):
+ context = super().get_context_data(**kwargs)
+ user = context["object"]
+ context["title"] = _("Add new hardware for %(name)s") % {
+ "name": user.full_name
+ }
+ context["subtitle"] = _("Employee")
+ context["object_list"] = Hardware.templates.all()
+ return context
+
+
+class ColleagueToggleHardwareView(LoginRequiredMixin, ManagerPermMixin, View):
+ template_name = "_toggle_button_hardware.html"
+
+ def post(self, request, pk, template_id, *args, **kwargs):
+ context = {}
+ user = get_object_or_404(get_user_model(), id=pk)
+ hardware = get_object_or_404(Hardware, id=template_id, template=True)
+ if user.hardware.filter(id=hardware.id).exists():
+ user.hardware.remove(hardware)
+ else:
+ user.hardware.add(hardware)
+ context["id"] = id
+ context["template"] = hardware
+ context["object"] = user
+ return render(request, self.template_name, context)
+
+
class ColleagueResourceView(LoginRequiredMixin, ManagerPermMixin, DetailView):
template_name = "add_resources.html"
model = get_user_model()
From ed9f224c496dc4e728fd306177fa703b22c6e4f2 Mon Sep 17 00:00:00 2001
From: GDay <1939656+GDay@users.noreply.github.com>
Date: Fri, 29 Mar 2024 02:38:48 +0100
Subject: [PATCH 2/2] ruff fixes
---
back/admin/people/tests.py | 1 -
back/admin/people/views.py | 6 ++----
2 files changed, 2 insertions(+), 5 deletions(-)
diff --git a/back/admin/people/tests.py b/back/admin/people/tests.py
index 31258bdfd..b913e590b 100644
--- a/back/admin/people/tests.py
+++ b/back/admin/people/tests.py
@@ -2780,7 +2780,6 @@ def test_employee_toggle_hardware(
assert not employee1.resources.filter(id=hardware1.id).exists()
-
@pytest.mark.django_db
def test_visibility_import_employees_button(
client,
diff --git a/back/admin/people/views.py b/back/admin/people/views.py
index 5f9b362da..90ad8feef 100644
--- a/back/admin/people/views.py
+++ b/back/admin/people/views.py
@@ -14,6 +14,7 @@
from rest_framework.authentication import SessionAuthentication
from admin.admin_tasks.models import AdminTask
+from admin.hardware.models import Hardware
from admin.integrations.exceptions import (
DataIsNotJSONError,
FailedPaginatedResponseError,
@@ -34,7 +35,6 @@
LoginRequiredMixin,
ManagerPermMixin,
)
-from admin.hardware.models import Hardware
from users.models import ToDoUser
from .forms import (
@@ -125,9 +125,7 @@ class ColleagueHardwareView(LoginRequiredMixin, ManagerPermMixin, DetailView):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
user = context["object"]
- context["title"] = _("Add new hardware for %(name)s") % {
- "name": user.full_name
- }
+ context["title"] = _("Add new hardware for %(name)s") % {"name": user.full_name}
context["subtitle"] = _("Employee")
context["object_list"] = Hardware.templates.all()
return context