Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 0 additions & 12 deletions .idea/dataSources.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions eproba/apps/core/templates/core/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,10 @@
right: 0;
background: red;
color: white;
padding: 10px 40px;
padding: 4px 50px;
font-weight: bold;
font-size: 14px;
transform: rotate(45deg) translate(35px, -10px);
font-size: 16px;
transform: rotate(45deg) translate(43px, -10px);
transform-origin: top right;
z-index: 9999;
box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.3);
Expand Down
3 changes: 3 additions & 0 deletions eproba/apps/core/templates/core/navbar.html
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@
</div>
</div>
{% endif %}
<a class="navbar-item" href="{% url 'wiki:index' %}">
Wiki
</a>
<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link">
Więcej
Expand Down
Empty file.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
from apps.users.serializers import UserSerializer
from apps.teams.models import District, Patrol, Team, TeamRequest
from apps.users.api.serializers import UserSerializer
from rest_framework import serializers

from .models import District, Patrol, Team, TeamRequest


class PatrolSerializer(serializers.ModelSerializer):
class Meta:
Expand Down
58 changes: 55 additions & 3 deletions eproba/apps/teams/views/api.py → eproba/apps/teams/api/views.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,63 @@
from apps.teams.api.permissions import IsAllowedToAccessTeamRequest
from apps.teams.api.serializers import TeamRequestSerializer
from apps.teams.models import District, Patrol, Team, TeamRequest
from django.conf import settings
from django.core.mail import send_mail
from rest_framework import mixins, status, viewsets
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

from ..models import TeamRequest
from ..permissions import IsAllowedToAccessTeamRequest
from ..serializers import TeamRequestSerializer
from .permissions import (
IsAllowedToManagePatrolOrReadOnly,
IsAllowedToManageTeamOrReadOnly,
)
from .serializers import (
DistrictSerializer,
PatrolSerializer,
TeamListSerializer,
TeamSerializer,
)


class DistrictViewSet(viewsets.ModelViewSet):
permission_classes = [IsAuthenticated]
queryset = District.objects.all()
serializer_class = DistrictSerializer


class TeamViewSet(viewsets.ModelViewSet):
permission_classes = [IsAuthenticated, IsAllowedToManageTeamOrReadOnly]

def get_queryset(self):
district = self.request.GET.get("district")
is_verified = self.request.GET.get("is_verified")
qs = Team.objects.all()
if district:
qs = qs.filter(district=district)
if is_verified is not None:
qs = qs.filter(is_verified=is_verified.lower() == "true")
return qs

def get_serializer_class(self):
if self.action == "list" and self.request.GET.get("with_patrols") != "true":
return TeamListSerializer
return TeamSerializer


class PatrolViewSet(viewsets.ModelViewSet):
queryset = Patrol.objects.all()
serializer_class = PatrolSerializer
permission_classes = [IsAuthenticated, IsAllowedToManagePatrolOrReadOnly]

def perform_destroy(self, instance):
# Prevent deletion if patrol has active users
if instance.users.filter(is_active=True).exists():
from rest_framework.exceptions import APIException

exc = APIException("Patrol has active users.")
exc.status_code = 409
raise exc
instance.delete()


class TeamRequestViewSet(
Expand Down
11 changes: 9 additions & 2 deletions eproba/apps/teams/forms.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from django import forms

from .models import District, TeamRequest
from .models import District, OrganizationChoice, TeamRequest


class TeamRequestForm(forms.Form):
Expand Down Expand Up @@ -39,12 +39,19 @@ class TeamRequestForm(forms.Form):
)

function_level = forms.ChoiceField(
choices=TeamRequest.FUNCTION_CHOICES,
choices=TeamRequest.FUNCTION_CHOICES[:2],
initial=TeamRequest.FUNCTION_CHOICES[1][0],
widget=forms.Select,
label="Twoja funkcja",
)

organization = forms.ChoiceField(
choices=[("", "Wybierz organizację")] + OrganizationChoice.choices,
widget=forms.Select,
label="Twoja organizacja",
required=True,
)

class Meta:
model = TeamRequest
fields = ["district", "team_name", "team_short_name", "function_level"]
21 changes: 21 additions & 0 deletions eproba/apps/teams/migrations/0006_team_organization.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Generated by Django 5.1.6 on 2025-02-20 23:01

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("teams", "0005_alter_teamrequest_notes"),
]

operations = [
migrations.AddField(
model_name="team",
name="organization",
field=models.IntegerField(
choices=[(0, "Organizacja Harcerzy"), (1, "Organizacja Harcerek")],
default=0,
),
),
]
12 changes: 12 additions & 0 deletions eproba/apps/teams/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@
from django.db import models


class OrganizationChoice(models.IntegerChoices):
"""
Czy drużyna należy do organizacji harcerek czy harcerzy
"""

MALE = 0, "Organizacja Harcerzy"
FEMALE = 1, "Organizacja Harcerek"


class District(models.Model):
"""
Okręg
Expand Down Expand Up @@ -31,6 +40,9 @@ class Team(models.Model):
District, on_delete=models.RESTRICT, related_name="teams"
)
is_verified = models.BooleanField(default=False)
organization = models.IntegerField(
choices=OrganizationChoice.choices, default=OrganizationChoice.choices[0][0]
)

class Meta:
verbose_name = "Drużyna"
Expand Down
9 changes: 9 additions & 0 deletions eproba/apps/teams/templates/teams/team_request.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@ <h1 class="title has-text-weight-bold">Zgłoszenie drużyny</h1>
</div>
</div>

<div class="field">
<label class="label">{{ form.organization.label }}</label>
<div class="control">
<div class="select is-fullwidth">
{{ form.organization }}
</div>
</div>
</div>

<div class="field">
<label class="label">{{ form.team_name.label }}</label>
<div class="control">
Expand Down
22 changes: 21 additions & 1 deletion eproba/apps/teams/views/team_request.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
import threading

from django.contrib import messages
from django.core.mail import EmailMessage
from django.shortcuts import redirect, render
from django.urls import reverse

from ..forms import TeamRequestForm
from ..models import District, Team, TeamRequest


def send_team_request_email(team_request_obj):
email = EmailMessage(
subject=f"Zgłoszenie o dodanie drużyny: {team_request_obj.team.name}",
body="Pojawiło się nowe zgłoszenie o dodanie drużyny. https://eproba.zhr.pl/team/requests/",
from_email=None,
to=["eproba@zhr.pl"],
headers={"Reply-To": team_request_obj.created_by.email},
)
email.send()


def team_request(request):
if not request.user.is_authenticated:
return render(request, "teams/team_request_unauthorized.html")
Expand All @@ -32,6 +46,7 @@ def team_request(request):
name=request.POST.get("team_name"),
short_name=request.POST.get("team_short_name"),
district=District.objects.get(id=request.POST.get("district")),
organization=int(request.POST.get("organization", 0)),
is_verified=False,
)

Expand All @@ -46,12 +61,17 @@ def team_request(request):

request.user.save()

TeamRequest.objects.create(
team_request_obj = TeamRequest.objects.create(
created_by=request.user,
team=team,
function_level=request.POST.get("function_level"),
)

send_email_thread = threading.Thread(
target=send_team_request_email, args={team_request_obj}, daemon=True
)
send_email_thread.start()

return redirect(reverse("teams:team_request_success"))

else:
Expand Down
Empty file.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from apps.users.models import User
from rest_framework import serializers

from .models import User


class UserSerializer(serializers.ModelSerializer):
team = serializers.UUIDField(
Expand Down
54 changes: 54 additions & 0 deletions eproba/apps/users/api/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
from apps.users.models import User
from rest_framework import mixins, viewsets
from rest_framework.generics import get_object_or_404
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

from .permissions import IsAllowedToManageUserOrReadOnly
from .serializers import PublicUserSerializer, UserSerializer


class UserViewSet(
mixins.UpdateModelMixin, mixins.ListModelMixin, viewsets.GenericViewSet
):
permission_classes = [IsAuthenticated, IsAllowedToManageUserOrReadOnly]
serializer_class = PublicUserSerializer

def get_queryset(self):
# Check if a list of IDs is provided in the query string
ids = self.request.query_params.get("ids")
if ids:
# Expect a comma-separated list of IDs (UUIDs)
user_ids = [uid.strip() for uid in ids.split(",") if uid.strip()]
return User.objects.filter(id__in=user_ids)

team_id = self.request.query_params.get("team")
if team_id is not None:
return User.objects.filter(patrol__team_id=team_id)

if self.request.user.patrol is None:
return User.objects.none()

return User.objects.filter(patrol__team_id=self.request.user.patrol.team.id)

def perform_update(self, serializer):
# Example check for promotion restrictions
data = serializer.validated_data.get("user")
if data and data.get("function", 0) > self.request.user.function:
from rest_framework.exceptions import PermissionDenied

raise PermissionDenied("Cannot assign a higher function than your own.")
serializer.save()

def retrieve(self, request, *args, **kwargs):
instance = get_object_or_404(User, pk=kwargs["pk"])
serializer = self.get_serializer(instance)
return Response(serializer.data)


class UserInfo(viewsets.ModelViewSet):
serializer_class = UserSerializer
permission_classes = [IsAuthenticated]

def list(self, request, *args, **kwargs):
return Response(self.get_serializer(request.user).data)
18 changes: 13 additions & 5 deletions eproba/apps/users/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class Meta:
verbose_name_plural = "Użytkownicy"

def __str__(self):
return f"{self.email} ({self.nickname})"
return self.full_name_nickname() or self.email

def get_short_name(self):
return self.full_name() or self.email.split("@")[0]
Expand Down Expand Up @@ -120,6 +120,10 @@ def rank(self):
else ""
)

_gender = (
self.patrol.team.organization if self.patrol is not None else self.gender
)

scout_rank_male = {
1: "biszkopt",
2: "mł.",
Expand All @@ -138,9 +142,9 @@ def rank(self):
6: "HR",
}

if self.gender == 0:
if _gender == 0:
scout_rank = scout_rank_male.get(self.scout_rank, "")
elif self.gender == 1:
elif _gender == 1:
scout_rank = scout_rank_female.get(self.scout_rank, "")
else:
scout_rank = self.get_scout_rank_display()
Expand All @@ -149,6 +153,10 @@ def rank(self):

def full_rank(self):

_gender = (
self.patrol.team.organization if self.patrol is not None else self.gender
)

instructor_rank_male = {1: "przewodnik", 2: "podharcmistrz", 3: "harcmistrz"}

instructor_rank_female = {
Expand All @@ -175,10 +183,10 @@ def full_rank(self):
6: "harcerka Rzeczypospolitej",
}

if self.gender == 0:
if _gender == 0:
instructor_rank = instructor_rank_male.get(self.instructor_rank, "")
scout_rank = scout_rank_male.get(self.scout_rank, "")
elif self.gender == 1:
elif _gender == 1:
instructor_rank = instructor_rank_female.get(self.instructor_rank, "")
scout_rank = scout_rank_female.get(self.scout_rank, "")
else:
Expand Down
2 changes: 1 addition & 1 deletion eproba/apps/users/templates/users/view_profile.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
{% load static %}
{% block extrahead %}
<script defer src="{% static 'js/core/helpers.js' %}"></script>
<script async type="module" src="{% static 'js/users/profile.js' %}"></script>
<script type="module" src="{% static 'js/users/profile.js' %}"></script>
{% endblock %}
{% block title %}Profil - {{ user.nickname }} - Epróba{% endblock %}
{% block content %}
Expand Down
Empty file added eproba/apps/wiki/__init__.py
Empty file.
Loading