diff --git a/.github/workflows/django-test.yml b/.github/workflows/django-test.yml
index 0412bc7b..2ddbc21e 100644
--- a/.github/workflows/django-test.yml
+++ b/.github/workflows/django-test.yml
@@ -21,6 +21,7 @@ jobs:
run: python -m pip install --upgrade pip
- name: Install dependencies
run: |
+ sudo apt update
sudo apt install libsasl2-dev python3-dev libldap2-dev libssl-dev
sudo locale-gen sv_FI.UTF-8
sudo update-locale
diff --git a/teknologr/api/serializers.py b/teknologr/api/serializers.py
index 86a5aa29..eb95ac9d 100644
--- a/teknologr/api/serializers.py
+++ b/teknologr/api/serializers.py
@@ -33,7 +33,7 @@ def get_minimal_id_name(self, instance):
return {'id': instance.id, 'name': instance.name}
def get_minimal_member(self, member):
- return {'id': member.id, 'name': member.name if self.is_staff else member.public_full_name}
+ return {'id': member.id, 'name': member.full_name if self.is_staff else member.public_full_name}
# Members
diff --git a/teknologr/api/tests.py b/teknologr/api/tests.py
index 149022d8..5e53cad5 100644
--- a/teknologr/api/tests.py
+++ b/teknologr/api/tests.py
@@ -124,7 +124,7 @@ def post(self):
return self.client.post(self.api_path, self.post_data)
def check_status_code(self, response, status_code):
- self.assertEqual(response.status_code, status_code, response.data)
+ self.assertEqual(response.status_code, status_code, response.data if 'data' in response else None)
'''
diff --git a/teknologr/katalogen/templates/year.html b/teknologr/katalogen/templates/year.html
index b7b1e6d9..5c216316 100644
--- a/teknologr/katalogen/templates/year.html
+++ b/teknologr/katalogen/templates/year.html
@@ -19,7 +19,11 @@
Postinnehavare |
- {{ functionaries|length }} ({{ functionaries_unique_count }}) |
+ {{ functionaries|length }}
+ {% if functionaries_unique_count %}
+ ({{ functionaries_unique_count }})
+ {% endif %}
+ |
Grupper |
@@ -27,7 +31,11 @@
Gruppmedlemmar |
- {{ group_memberships_total }} ({{ group_memberships_unique }}) |
+ {{ group_memberships_total|default:0 }}
+ {% if group_memberships_unique %}
+ ({{ group_memberships_unique }})
+ {% endif %}
+ |
Nya ordinarie medlemmar |
diff --git a/teknologr/katalogen/tests.py b/teknologr/katalogen/tests_utils.py
similarity index 100%
rename from teknologr/katalogen/tests.py
rename to teknologr/katalogen/tests_utils.py
diff --git a/teknologr/katalogen/tests_views.py b/teknologr/katalogen/tests_views.py
new file mode 100644
index 00000000..906e0a60
--- /dev/null
+++ b/teknologr/katalogen/tests_views.py
@@ -0,0 +1,91 @@
+
+from rest_framework import status
+from api.tests import BaseAPITest
+
+class GetPageTests():
+ def test_get_for_anonymous_users(self):
+ response = self.get_all()
+ self.check_status_code(response, status.HTTP_302_FOUND)
+ self.assertTrue(response.url.startswith('/login/'), response.url)
+
+ def test_get_for_user(self):
+ self.login_user()
+ response = self.get_all()
+ self.check_status_code(response, status.HTTP_200_OK)
+
+
+class HomeViewTest(BaseAPITest, GetPageTests):
+ def setUp(self):
+ super().setUp()
+ self.api_path = ''
+
+
+class MembersSearchViewTest(BaseAPITest, GetPageTests):
+ def setUp(self):
+ super().setUp()
+ self.api_path = '/search/?q=test'
+
+class MembersStartsWithViewTest(BaseAPITest, GetPageTests):
+ def setUp(self):
+ super().setUp()
+ self.api_path = '/A/'
+
+class MemberViewTest(BaseAPITest, GetPageTests):
+ def setUp(self):
+ super().setUp()
+ self.api_path = f'/members/{self.m1.id}/'
+
+
+class DecorationOwnershipsViewTest(BaseAPITest, GetPageTests):
+ def setUp(self):
+ super().setUp()
+ self.api_path = f'/decorations/{self.d.id}/'
+
+
+class DecorationsViewTest(BaseAPITest, GetPageTests):
+ def setUp(self):
+ super().setUp()
+ self.api_path = '/decorations/'
+
+class DecorationOwnershipsViewTest(BaseAPITest, GetPageTests):
+ def setUp(self):
+ super().setUp()
+ self.api_path = f'/decorations/{self.d.id}/'
+
+
+class FunctionaryTypesViewTest(BaseAPITest, GetPageTests):
+ def setUp(self):
+ super().setUp()
+ self.api_path = '/functionaries/'
+
+class FunctionariesViewTest(BaseAPITest, GetPageTests):
+ def setUp(self):
+ super().setUp()
+ self.api_path = f'/functionaries/{self.ft.id}/'
+
+
+class GroupTypesViewTest(BaseAPITest, GetPageTests):
+ def setUp(self):
+ super().setUp()
+ self.api_path = '/groups/'
+
+class GroupsViewTest(BaseAPITest, GetPageTests):
+ def setUp(self):
+ super().setUp()
+ self.api_path = f'/groups/{self.gt.id}/'
+
+
+class YearsViewTest(BaseAPITest, GetPageTests):
+ def setUp(self):
+ super().setUp()
+ self.api_path = '/years/'
+
+class YearViewTest(BaseAPITest, GetPageTests):
+ def setUp(self):
+ super().setUp()
+ self.api_path = f'/years/2023/'
+
+class Year0ViewTest(BaseAPITest, GetPageTests):
+ def setUp(self):
+ super().setUp()
+ self.api_path = f'/years/0/'
diff --git a/teknologr/katalogen/views.py b/teknologr/katalogen/views.py
index 27eefdc9..90554f3b 100644
--- a/teknologr/katalogen/views.py
+++ b/teknologr/katalogen/views.py
@@ -238,6 +238,12 @@ def add(obj, key, count_key=None):
@login_required
def year(request, year):
+ if int(year) <= 0:
+ return render(request, 'year.html', {
+ **_get_base_context(request),
+ 'year': year,
+ })
+
'''
This could be enhanced, but curretnly it is done with 10 queries:
1. SELECT Functionary WHERE correct_year => COUNT
diff --git a/teknologr/members/lookups.py b/teknologr/members/lookups.py
index c6263699..27204486 100644
--- a/teknologr/members/lookups.py
+++ b/teknologr/members/lookups.py
@@ -18,8 +18,7 @@ def get_result(self, obj):
def format_match(self, obj):
""" (HTML) formatted item for display in the dropdown """
- preferred_name = obj.get_preferred_name()
- return f'{obj.given_names.replace(preferred_name, f"{preferred_name}", 1)} {obj.surname}'
+ return obj.get_full_name_HTML()
def format_item_display(self, obj):
""" (HTML) formatted item for displaying item in the selected deck area """
diff --git a/teknologr/members/models.py b/teknologr/members/models.py
index b1482a92..b42ceda1 100644
--- a/teknologr/members/models.py
+++ b/teknologr/members/models.py
@@ -4,8 +4,10 @@
from django.db.models import Q, Prefetch, Count
from django_countries.fields import CountryField
from django.shortcuts import get_object_or_404
+from django.utils.html import format_html
from locale import strxfrm, strcoll
from operator import attrgetter
+from datetime import date
from katalogen.utils import *
from members.utils import *
@@ -143,10 +145,12 @@ def get_surname_without_prefixes(self):
surname = self.surname
return surname.lstrip('abcdefghijklmnopqrstuvwxyzåäö ') or surname.split()[-1]
- # Used for the side bar among other things
- @property
- def name(self):
- return self.full_name
+ def get_full_name_HTML(self):
+ '''
+ Return name with the preferred name undercored. This can go wrong if the preferred name is not set correctly to one of the given names.
+ '''
+ preferred_name = self.get_preferred_name()
+ return format_html(f'{self.given_names.replace(preferred_name, f"{preferred_name}", 1)} {self.surname}')
@property
def common_name(self):
@@ -420,7 +424,7 @@ def year(self, year):
queryset=GroupMembership.objects.select_related('member')
),
'grouptype'
- ).filter(begin_date__lte=datetime.date(int(year), 12, 31), end_date__gte=datetime.date(int(year), 1, 1), num_members__gt=0)
+ ).filter(begin_date__lte=date(int(year), 12, 31), end_date__gte=date(int(year), 1, 1), num_members__gt=0)
def year_ordered_and_counts(self, year):
queryset = self.year(year)
@@ -537,7 +541,7 @@ def all_with_related(self):
return self.get_queryset().select_related('functionarytype', 'member')
def year(self, year):
- return self.all_with_related().filter(begin_date__lte=datetime.date(int(year), 12, 31), end_date__gte=datetime.date(int(year), 1, 1))
+ return self.all_with_related().filter(begin_date__lte=date(int(year), 12, 31), end_date__gte=date(int(year), 1, 1))
def year_ordered_and_unique(self, year):
queryset = self.year(year)
@@ -689,7 +693,7 @@ def order_by(cls, membertypes_list, by, reverse=False):
if by == 'begin_date':
key = lambda mt: mt.begin_date
elif by == 'end_date':
- key = lambda mt: mt.end_date or datetime.date(9999, 12, 31)
+ key = lambda mt: mt.end_date or date(9999, 12, 31)
elif by == 'member':
key = lambda mt: strxfrm(mt.member.full_name_for_sorting)
else:
diff --git a/teknologr/members/templates/decoration.html b/teknologr/members/templates/decoration.html
index eff94603..6fdc9a68 100644
--- a/teknologr/members/templates/decoration.html
+++ b/teknologr/members/templates/decoration.html
@@ -37,7 +37,7 @@ Innehavare av betygelsen
- {{ ownership.member.full_name }} |
+ {{ ownership.member.get_full_name_HTML }} |
{{ ownership.acquired }} |
{% endfor %}
diff --git a/teknologr/members/templates/functionary.html b/teknologr/members/templates/functionary.html
index ef01ec36..518a764c 100644
--- a/teknologr/members/templates/functionary.html
+++ b/teknologr/members/templates/functionary.html
@@ -37,7 +37,7 @@ Innehavare av posten
- {{ functionary.member.full_name }} |
+ {{ functionary.member.get_full_name_HTML }} |
{{ functionary.begin_date }} |
{{ functionary.end_date }} |
diff --git a/teknologr/members/templates/group.html b/teknologr/members/templates/group.html
index 5c9dde2a..7fcd0eea 100644
--- a/teknologr/members/templates/group.html
+++ b/teknologr/members/templates/group.html
@@ -71,7 +71,7 @@
- {{ membership.member.full_name }}
+ {{ membership.member.get_full_name_HTML }}
|
{% endfor %}
diff --git a/teknologr/members/templates/member.html b/teknologr/members/templates/member.html
index fefac2ed..f8299c45 100644
--- a/teknologr/members/templates/member.html
+++ b/teknologr/members/templates/member.html
@@ -11,7 +11,7 @@
{% if result %}
diff --git a/teknologr/members/templates/side.html b/teknologr/members/templates/side.html
index f8d57e05..1c1bf7cf 100644
--- a/teknologr/members/templates/side.html
+++ b/teknologr/members/templates/side.html
@@ -44,6 +44,6 @@
{{ obj.name|default:"Namnlös" }}{% if obj.count >= 0 %} ({{ obj.count }}) {% endif %}
{% empty %}
- Skriv i sökfältet för att visa medlemmar
+ Inga objekt hittades
{% endfor %}
diff --git a/teknologr/members/tests.py b/teknologr/members/tests_models.py
similarity index 99%
rename from teknologr/members/tests.py
rename to teknologr/members/tests_models.py
index 67dde22b..a1a843f9 100644
--- a/teknologr/members/tests.py
+++ b/teknologr/members/tests_models.py
@@ -121,9 +121,7 @@ def test_public_full_name_for_sorting(self):
self.assertEqual(self.member3.public_full_name_for_sorting, 'Tester, F-B Biz-Baz')
def test_name(self):
- self.assertEqual(self.member1.name, 'Foo Bar Baz Tester')
- self.assertEqual(self.member2.name, 'Foo Bar Baz Tester')
- self.assertEqual(self.member3.name, 'Foo-Bar Biz-Baz von der Tester')
+ self.assertFalse(hasattr(self.member1, 'name'))
def test_address(self):
self.assertEquals('Otsvängen 22, 02150 Esbo, Finland', self.member1.full_address)
diff --git a/teknologr/members/tests_views.py b/teknologr/members/tests_views.py
new file mode 100644
index 00000000..a481f1f8
--- /dev/null
+++ b/teknologr/members/tests_views.py
@@ -0,0 +1,86 @@
+
+from rest_framework import status
+from api.tests import BaseAPITest
+
+class GetPageTests():
+ def test_get_for_anonymous_users(self):
+ response = self.get_all()
+ self.check_status_code(response, status.HTTP_302_FOUND)
+ self.assertTrue(response.url.startswith('/login/'), response.url)
+
+ def test_get_for_users(self):
+ response = self.get_all()
+ self.check_status_code(response, status.HTTP_302_FOUND)
+ self.assertTrue(response.url.startswith('/login/'), response.url)
+
+ def test_get_for_superusers(self):
+ self.login_superuser()
+ response = self.get_all()
+ self.check_status_code(response, status.HTTP_200_OK)
+
+
+class HomeViewTest(BaseAPITest, GetPageTests):
+ def setUp(self):
+ super().setUp()
+ self.api_path = '/admin/members/'
+
+
+class MemberViewTest(BaseAPITest, GetPageTests):
+ def setUp(self):
+ super().setUp()
+ self.api_path = f'/admin/members/{self.m1.id}/'
+
+
+class DecorationOwnershipsViewTest(BaseAPITest, GetPageTests):
+ def setUp(self):
+ super().setUp()
+ self.api_path = f'/admin/decorations/{self.d.id}/'
+
+
+class DecorationsViewTest(BaseAPITest, GetPageTests):
+ def setUp(self):
+ super().setUp()
+ self.api_path = '/admin/decorations/'
+
+class DecorationOwnershipsViewTest(BaseAPITest, GetPageTests):
+ def setUp(self):
+ super().setUp()
+ self.api_path = f'/admin/decorations/{self.d.id}/'
+
+
+class FunctionaryTypesViewTest(BaseAPITest, GetPageTests):
+ def setUp(self):
+ super().setUp()
+ self.api_path = '/admin/functionarytypes/'
+
+class FunctionariesViewTest(BaseAPITest, GetPageTests):
+ def setUp(self):
+ super().setUp()
+ self.api_path = f'/admin/functionarytypes/{self.ft.id}/'
+
+
+class GroupTypesViewTest(BaseAPITest, GetPageTests):
+ def setUp(self):
+ super().setUp()
+ self.api_path = '/admin/grouptypes/'
+
+class GroupsViewTest(BaseAPITest, GetPageTests):
+ def setUp(self):
+ super().setUp()
+ self.api_path = f'/admin/grouptypes/{self.gt.id}/'
+
+class GroupMembershipsViewTest(BaseAPITest, GetPageTests):
+ def setUp(self):
+ super().setUp()
+ self.api_path = f'/admin/grouptypes/{self.gt.id}/{self.g.id}/'
+
+
+class ApplicantsViewTest(BaseAPITest, GetPageTests):
+ def setUp(self):
+ super().setUp()
+ self.api_path = '/admin/applicants/'
+
+class ApplicantViewTest(BaseAPITest, GetPageTests):
+ def setUp(self):
+ super().setUp()
+ self.api_path = f'/admin/applicants/{self.a.id}/'
diff --git a/teknologr/members/views.py b/teknologr/members/views.py
index a987401f..ce969801 100644
--- a/teknologr/members/views.py
+++ b/teknologr/members/views.py
@@ -23,6 +23,7 @@ def set_side_context(context, category, active_obj=None):
if active_obj and active_obj not in side['objects']:
from itertools import chain
side['objects'] = list(chain([active_obj], side['objects']))
+ side['objects'] = [{'id': m.id, 'name': m.get_full_name_HTML()} for m in side['objects']]
elif category == 'grouptypes':
side['sname'] = 'grupp'
side['form'] = GroupTypeForm(auto_id="gtmodal_%s")
@@ -233,7 +234,7 @@ def decoration_ownership_form(request, decration_ownership_id):
})
-@user_passes_test(lambda u: u.is_staff, login_url='/login')
+@user_passes_test(lambda u: u.is_staff, login_url='/login/')
def applicant(request, applicant_id):
context = {}