diff --git a/backend/api/fixtures/courses.yaml b/backend/api/fixtures/courses.yaml index 4a8677c9..eba5159f 100644 --- a/backend/api/fixtures/courses.yaml +++ b/backend/api/fixtures/courses.yaml @@ -1,21 +1,87 @@ - model: api.course pk: 1 fields: - name: Math + name: "Parallel and Distributed Software Systems" academic_startyear: 2023 - description: Math course + description: "Deze cursus brengt de studenten de verschillende aspecten aan van het ontwerp en +implementatie van gedistribueerde software. De cursus geeft de studenten een state-of-the-art +overzicht van parallelle en cloud-gebaseerde systemen, het ontwerp van parallelle software, +software engineering specifiek voor deze applicaties en het beheren van hoog-performante en +cloud-gebaseerde systemen. De nadruk ligt op de algoritmische aspecten, software aspecten +en op de verschillende programmeermodellen. Hardware en architectuur aspecten worden +slechts aangehaald in de mate noodzakelijk voor het begrijpen van de impact van software +performantie." parent_course: null + faculty: "Ingenieurswetenschappen_Architectuur" - model: api.course pk: 2 fields: - name: Sel2 + name: "Wiskundige modellering in de ingenieurswetenschappen" academic_startyear: 2023 - description: Software course - parent_course: 3 + description: "De basiswiskunde en de eruit voortspruitende wiskundige modellen spelen een prominente rol +in de ingenieurswetenschappen. Wiskunde maakt immers de kwantitatieve aanpak mogelijk die +eigen is aan de ingenieurspraktijk, en wiskundig modelleren ligt aan de basis van de meeste +courante technologische innovaties." + parent_course: null + faculty: "Wetenschappen" - model: api.course pk: 3 fields: - name: Sel1 - academic_startyear: 2022 - description: Software course + name: "Software Engineering Lab 2" + academic_startyear: 2023 + description: "Het ontwerpen en ontwikkelen van een groot software-project in teamverband waarbij +vaardigheden en kennis uit verschillende opleidingsonderdelen moeten worden toegepast. De +uitvoering van het project gebeurt in een context die de bedrijfsrealiteit zoveel mogelijk +nabootst: de projectgroepen moeten zelfstandig beslissingen nemen over werkverdeling, +tijdsbesteding, keuze van architectuur en programmeeromgeving, enz." + parent_course: null + faculty: "Wetenschappen" +- model: api.course + pk: 4 + fields: + name: "Informatiebeveiliging" + academic_startyear: 2023 + description: "Kennis bijbrengen van basisbegrippen over informatiebeveiliging (wiskundige basis, +toepassingen en legale aspecten)" + parent_course: null + faculty: "Ingenieurswetenschappen_Architectuur" +- model: api.course + pk: 5 + fields: + name: "Computationele biologie" + academic_startyear: 2023 + description: "Waar komt SARS vandaan? Hebben wij genen geërfd van de Neanderthalers? Hoe gebruiken +planten hun interne klok? Hoeveel genetisch materiaal wordt er uitgewisseld tussen bacteriële +soorten? De genomische revolutie in de biologie maakt het mogelijk om een antwoord te +vinden op elk van deze vragen. Maar deze revolutie zou onmogelijk geweest zijn zonder de +ondersteuning van krachtige computationele en statistische methodes die toelaten om gebruik +te maken van deze genomische informatie. Oplossen van openstaande en toekomstige +problemen die opduiken in dit intrigerend onderzoeksdomein vereist de opleiding van een +volgende generatie onderzoekers, die zich vloeiend kunnen uitdrukken in de taal van de +wiskunde, informatica en biologie." + parent_course: null + faculty: "Wetenschappen" +- model: api.course + pk: 6 + fields: + name: "Inleiding tot de elektrotechniek" + academic_startyear: 2023 + description: "Practica horend bij het opleidingsonderdeel" + parent_course: null + faculty: "Wetenschappen" +- model: api.course + pk: 7 + fields: + name: "Mobile and Broadband Access Networks" + academic_startyear: 2023 + description: "Practica horend bij het opleidingsonderdeel" + parent_course: null + faculty: "Ingenieurswetenschappen_Architectuur" +- model: api.course + pk: 8 + fields: + name: "Design of Multimedia Applications" + academic_startyear: 2023 + description: "Software projects" parent_course: null + faculty: "Ingenieurswetenschappen_Architectuur" \ No newline at end of file diff --git a/backend/api/migrations/0008_course_faculty.py b/backend/api/migrations/0008_course_faculty.py new file mode 100644 index 00000000..e7641849 --- /dev/null +++ b/backend/api/migrations/0008_course_faculty.py @@ -0,0 +1,20 @@ +# Generated by Django 5.0.3 on 2024-04-03 10:01 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0007_merge_20240313_0639'), + ('authentication', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='course', + name='faculty', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='authentication.faculty'), + ), + ] diff --git a/backend/api/migrations/0009_merge_0008_add_extra_checks_0008_course_faculty.py b/backend/api/migrations/0009_merge_0008_add_extra_checks_0008_course_faculty.py new file mode 100644 index 00000000..409ccce3 --- /dev/null +++ b/backend/api/migrations/0009_merge_0008_add_extra_checks_0008_course_faculty.py @@ -0,0 +1,14 @@ +# Generated by Django 5.0.3 on 2024-04-04 14:51 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0008_add_extra_checks'), + ('api', '0008_course_faculty'), + ] + + operations = [ + ] diff --git a/backend/api/models/course.py b/backend/api/models/course.py index b4fdb972..3612827c 100644 --- a/backend/api/models/course.py +++ b/backend/api/models/course.py @@ -2,6 +2,8 @@ from typing import Self from django.db import models +from authentication.models import Faculty + class Course(models.Model): """This model represents a single course. @@ -14,8 +16,16 @@ class Course(models.Model): # Begin year of the academic year academic_startyear = models.IntegerField(blank=False, null=False) + # The description of the course description = models.TextField(blank=True, null=True) + # The faculty this course belongs to + faculty = models.ForeignKey( + Faculty, + null=True, + on_delete=models.SET_NULL + ) + # OneToOneField is used to represent a one-to-one relationship # with the course of the previous academic year parent_course = models.OneToOneField( diff --git a/backend/api/permissions/student_permissions.py b/backend/api/permissions/student_permissions.py index ab1afd57..7dc1b9c9 100644 --- a/backend/api/permissions/student_permissions.py +++ b/backend/api/permissions/student_permissions.py @@ -1,4 +1,6 @@ from rest_framework.permissions import IsAuthenticated, SAFE_METHODS + +from api.models.student import Student from api.permissions.role_permissions import is_teacher from authentication.models import User @@ -7,9 +9,10 @@ class StudentPermission(IsAuthenticated): def has_permission(self, request, view): """Check if user has permission to view a general student endpoint.""" - return view.action == 'retrieve' + return True - def has_object_permission(self, request, view, obj): + def has_object_permission(self, request, view, student: Student) -> bool: """Check if user has permission to view a detailed group endpoint""" user: User = request.user - return request.method in SAFE_METHODS and (user.id == request.user.id or is_teacher(user)) + + return request.method in SAFE_METHODS and (user.id == student.id or is_teacher(user)) diff --git a/backend/api/serializers/course_serializer.py b/backend/api/serializers/course_serializer.py index 4d7cf067..38b4c281 100644 --- a/backend/api/serializers/course_serializer.py +++ b/backend/api/serializers/course_serializer.py @@ -3,6 +3,7 @@ from rest_framework.exceptions import ValidationError from api.serializers.student_serializer import StudentIDSerializer from api.serializers.teacher_serializer import TeacherIDSerializer +from api.serializers.faculty_serializer import FacultySerializer from api.models.course import Course @@ -31,6 +32,10 @@ class CourseSerializer(serializers.ModelSerializer): many=False, read_only=True, view_name="course-detail" ) + faculty = FacultySerializer( + read_only=True + ) + class Meta: model = Course fields = "__all__" diff --git a/backend/api/serializers/faculty_serializer.py b/backend/api/serializers/faculty_serializer.py index 57bb9bbf..eed3fde7 100644 --- a/backend/api/serializers/faculty_serializer.py +++ b/backend/api/serializers/faculty_serializer.py @@ -1,8 +1,14 @@ +from django.utils.translation import gettext_lazy as _ from rest_framework import serializers from authentication.models import Faculty -class facultySerializer(serializers.ModelSerializer): +class FacultySerializer(serializers.ModelSerializer): + name = serializers.SerializerMethodField() + + def get_name(self, data) -> str: + return _(data.name) + class Meta: model = Faculty fields = "__all__" diff --git a/backend/api/tests/test_admin.py b/backend/api/tests/test_admin.py index 5de600b2..be96e132 100644 --- a/backend/api/tests/test_admin.py +++ b/backend/api/tests/test_admin.py @@ -8,7 +8,7 @@ def create_faculty(name): """ Create a Faculty with the given arguments.""" - return Faculty.objects.create(name=name) + return Faculty.objects.create(id=name, name=name) def create_admin(id, first_name, last_name, email, faculty=None): diff --git a/backend/api/tests/test_assistant.py b/backend/api/tests/test_assistant.py index b59ab048..dd52a797 100644 --- a/backend/api/tests/test_assistant.py +++ b/backend/api/tests/test_assistant.py @@ -22,7 +22,7 @@ def create_course(name, academic_startyear, description=None, parent_course=None def create_faculty(name): """Create a Faculty with the given arguments.""" - return Faculty.objects.create(name=name) + return Faculty.objects.create(id=name, name=name) def create_assistant(id, first_name, last_name, email, faculty=None, courses=None): diff --git a/backend/api/tests/test_student.py b/backend/api/tests/test_student.py index 1fced767..68bcbee9 100644 --- a/backend/api/tests/test_student.py +++ b/backend/api/tests/test_student.py @@ -21,7 +21,7 @@ def create_course(name, academic_startyear, description=None, parent_course=None def create_faculty(name): """Create a Faculty with the given arguments.""" - return Faculty.objects.create(name=name) + return Faculty.objects.create(id=name, name=name) def create_student(id, first_name, last_name, email, faculty=None, courses=None): diff --git a/backend/api/tests/test_teacher.py b/backend/api/tests/test_teacher.py index ec58ec95..ee41e6a9 100644 --- a/backend/api/tests/test_teacher.py +++ b/backend/api/tests/test_teacher.py @@ -21,7 +21,7 @@ def create_course(name, academic_startyear, description=None, parent_course=None def create_faculty(name): """Create a Faculty with the given arguments.""" - return Faculty.objects.create(name=name) + return Faculty.objects.create(id=name, name=name) def create_teacher(id, first_name, last_name, email, faculty=None, courses=None): diff --git a/backend/api/views/course_view.py b/backend/api/views/course_view.py index bc61a913..38537f39 100644 --- a/backend/api/views/course_view.py +++ b/backend/api/views/course_view.py @@ -18,6 +18,7 @@ CourseSerializer, StudentJoinSerializer, StudentLeaveSerializer, CourseCloneSerializer, TeacherJoinSerializer, TeacherLeaveSerializer ) +from api.views.pagination.basic_pagination import BasicPagination from api.serializers.teacher_serializer import TeacherSerializer from api.serializers.assistant_serializer import AssistantSerializer, AssistantIDSerializer from api.serializers.student_serializer import StudentSerializer @@ -46,6 +47,35 @@ def create(self, request: Request, *_): status=status.HTTP_201_CREATED ) + @action(detail=False) + def search(self, request: Request) -> Response: + self.pagination_class = BasicPagination + + # Extract filter params + search = request.query_params.get("search", "") + years = request.query_params.getlist("years[]") + faculties = request.query_params.getlist("faculties[]") + + # Filter the queryset based on the search term + queryset = self.get_queryset().filter( + name__icontains=search + ) + + # Filter the queryset based on selected years + if years: + queryset = queryset.filter(academic_startyear__in=years) + + # Filter the queryset based on selected faculties + if faculties: + queryset = queryset.filter(faculty__in=faculties) + + # Serialize the resulting queryset + serializer = self.serializer_class(self.paginate_queryset(queryset), many=True, context={ + "request": request + }) + + return self.get_paginated_response(serializer.data) + @action(detail=True, permission_classes=[IsAdminUser | CourseAssistantPermission]) def assistants(self, request: Request, **_): """Returns a list of assistants for the given course""" diff --git a/backend/api/views/faculty_view.py b/backend/api/views/faculty_view.py index fc8c71ca..eb5423ac 100644 --- a/backend/api/views/faculty_view.py +++ b/backend/api/views/faculty_view.py @@ -2,10 +2,10 @@ from rest_framework.permissions import IsAdminUser from authentication.models import Faculty from api.permissions.faculty_permissions import FacultyPermission -from ..serializers.faculty_serializer import facultySerializer +from ..serializers.faculty_serializer import FacultySerializer class FacultyViewSet(viewsets.ModelViewSet): queryset = Faculty.objects.all() - serializer_class = facultySerializer + serializer_class = FacultySerializer permission_classes = [IsAdminUser | FacultyPermission] diff --git a/backend/api/views/pagination/__init__.py b/backend/api/views/pagination/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/backend/api/views/pagination/basic_pagination.py b/backend/api/views/pagination/basic_pagination.py new file mode 100644 index 00000000..101e55bf --- /dev/null +++ b/backend/api/views/pagination/basic_pagination.py @@ -0,0 +1,8 @@ +from rest_framework.pagination import PageNumberPagination + + +class BasicPagination(PageNumberPagination): + page_size = 20 + max_page_size = 50 + page_size_query_param = 'page_size' + page_query_param = 'page' diff --git a/backend/authentication/fixtures/faculties.yaml b/backend/authentication/fixtures/faculties.yaml index e13fd9e5..66b69d4c 100644 --- a/backend/authentication/fixtures/faculties.yaml +++ b/backend/authentication/fixtures/faculties.yaml @@ -1,33 +1,44 @@ - model: authentication.faculty pk: Bio-ingenieurswetenschappen - fields: {} + fields: + name: "faculties.bioscience_engineering" - model: authentication.faculty pk: Diergeneeskunde - fields: {} + fields: + name: "faculties.veterinary_medicine" - model: authentication.faculty pk: Economie_Bedrijfskunde - fields: {} + fields: + name: "faculties.economics_business_administration" - model: authentication.faculty pk: Farmaceutische_Wetenschappen - fields: {} + fields: + name: "faculties.pharmaceutical_sciences" - model: authentication.faculty pk: Geneeskunde_Gezondheidswetenschappen - fields: {} + fields: + name: "faculties.medicine_health_sciences" - model: authentication.faculty pk: Ingenieurswetenschappen_Architectuur - fields: {} + fields: + name: "faculties.engineering_architecture" - model: authentication.faculty pk: Letteren_Wijsbegeerte - fields: {} + fields: + name: "faculties.arts_philosophy" - model: authentication.faculty pk: Politieke_Sociale_Wetenschappen - fields: {} + fields: + name: "faculties.political_social_sciences" - model: authentication.faculty pk: Psychologie_PedagogischeWetenschappen - fields: {} + fields: + name: "faculties.psychology_educational_sciences" - model: authentication.faculty pk: Recht_Criminologie - fields: {} + fields: + name: "faculties.law_criminology" - model: authentication.faculty pk: Wetenschappen - fields: {} + fields: + name: "faculties.sciences" diff --git a/backend/authentication/locale/en/LC_MESSAGES/django.po b/backend/authentication/locale/en/LC_MESSAGES/django.po new file mode 100644 index 00000000..9ee53ff5 --- /dev/null +++ b/backend/authentication/locale/en/LC_MESSAGES/django.po @@ -0,0 +1,32 @@ +msgid "faculties.bioscience_engineering" +msgstr "Bioscience Engineering" + +msgid "faculties.veterinary_medicine" +msgstr "Veterinary Medicine" + +msgid "faculties.economics_business_administration" +msgstr "Economics and Business Administration" + +msgid "faculties.pharmaceutical_sciences" +msgstr "Pharmaceutical Sciences" + +msgid "faculties.medicine_health_sciences" +msgstr "Medicine and Health Sciences" + +msgid "faculties.engineering_architecture" +msgstr "Engineering and Architecture" + +msgid "faculties.arts_philosophy" +msgstr "Arts and Philosophy" + +msgid "faculties.political_social_sciences" +msgstr "Political and Social Sciences" + +msgid "faculties.psychology_educational_sciences" +msgstr "Psychology and Educational Sciences" + +msgid "faculties.law_criminology" +msgstr "Law and Criminology" + +msgid "faculties.sciences" +msgstr "Sciences" \ No newline at end of file diff --git a/backend/authentication/locale/nl/LC_MESSAGES/django.po b/backend/authentication/locale/nl/LC_MESSAGES/django.po new file mode 100644 index 00000000..b3ec5337 --- /dev/null +++ b/backend/authentication/locale/nl/LC_MESSAGES/django.po @@ -0,0 +1,32 @@ +msgid "faculties.bioscience_engineering" +msgstr "Bio-ingenieurswetenschappen" + +msgid "faculties.veterinary_medicine" +msgstr "Diergeneeskunde" + +msgid "faculties.economics_business_administration" +msgstr "Economie en Bedrijfskunde" + +msgid "faculties.pharmaceutical_sciences" +msgstr "Farmaceutische Wetenschappen" + +msgid "faculties.medicine_health_sciences" +msgstr "Geneeskunde en Gezondheidswetenschappen" + +msgid "faculties.engineering_architecture" +msgstr "Ingenieurswetenschappen en Architectuur" + +msgid "faculties.arts_philosophy" +msgstr "Letteren en Wijsbegeerte" + +msgid "faculties.political_social_sciences" +msgstr "Politieke en Sociale Wetenschappen" + +msgid "faculties.psychology_educational_sciences" +msgstr "Psychologie en Pedagogische Wetenschappen" + +msgid "faculties.law_criminology" +msgstr "Recht en Criminologie" + +msgid "faculties.science" +msgstr "Wetenschappen" \ No newline at end of file diff --git a/backend/authentication/migrations/0002_rename_name_faculty_id_faculty_description.py b/backend/authentication/migrations/0002_rename_name_faculty_id_faculty_description.py new file mode 100644 index 00000000..3e22f1ad --- /dev/null +++ b/backend/authentication/migrations/0002_rename_name_faculty_id_faculty_description.py @@ -0,0 +1,23 @@ +# Generated by Django 5.0.3 on 2024-04-03 10:31 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0001_initial'), + ] + + operations = [ + migrations.RenameField( + model_name='faculty', + old_name='name', + new_name='id', + ), + migrations.AddField( + model_name='faculty', + name='description', + field=models.CharField(default='faculty', max_length=50), + ), + ] diff --git a/backend/authentication/migrations/0003_rename_description_faculty_name.py b/backend/authentication/migrations/0003_rename_description_faculty_name.py new file mode 100644 index 00000000..1ec0cc3e --- /dev/null +++ b/backend/authentication/migrations/0003_rename_description_faculty_name.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0.3 on 2024-04-03 10:32 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0002_rename_name_faculty_id_faculty_description'), + ] + + operations = [ + migrations.RenameField( + model_name='faculty', + old_name='description', + new_name='name', + ), + ] diff --git a/backend/authentication/models.py b/backend/authentication/models.py index 71eadc53..e7f3e7dd 100644 --- a/backend/authentication/models.py +++ b/backend/authentication/models.py @@ -72,4 +72,10 @@ class Faculty(models.Model): """This model represents a faculty.""" """Model fields""" - name = CharField(max_length=50, primary_key=True) + id = CharField(max_length=50, primary_key=True) + + name = CharField( + max_length=50, + default="faculty", + null=False + ) diff --git a/backend/authentication/views.py b/backend/authentication/views.py index 9836e3e5..617cd58e 100644 --- a/backend/authentication/views.py +++ b/backend/authentication/views.py @@ -18,8 +18,13 @@ class CASViewSet(ViewSet): permission_classes = [IsAuthenticated] @action(detail=False, methods=['GET'], permission_classes=[AllowAny]) - def login(self, _: Request) -> Response: + def login(self, request: Request) -> Response: """Attempt to log in. Redirect to our single CAS endpoint.""" + should_echo = request.query_params.get('echo', False) + + if should_echo == "1" and settings.DEBUG: + client._service_url = settings.CAS_DEBUG_RESPONSE + return redirect(client.get_login_url()) @action(detail=False, methods=['POST']) diff --git a/backend/ypovoli/settings.py b/backend/ypovoli/settings.py index ce904f80..27d287c9 100644 --- a/backend/ypovoli/settings.py +++ b/backend/ypovoli/settings.py @@ -91,6 +91,7 @@ PORT = environ.get("DJANGO_CAS_PORT", "8080") CAS_ENDPOINT = "https://login.ugent.be" CAS_RESPONSE = f"https://{DOMAIN_NAME}:{PORT}/auth/verify" +CAS_DEBUG_RESPONSE = f"https://{DOMAIN_NAME}:{PORT}/api/auth/cas/echo" API_ENDPOINT = f"https://{DOMAIN_NAME}/api" # Database diff --git a/frontend/.prettierrc b/frontend/.prettierrc index f9ca8c32..1d946086 100644 --- a/frontend/.prettierrc +++ b/frontend/.prettierrc @@ -1,12 +1,8 @@ { "tabWidth": 4, - "printWidth": 140, - "max_line_length": 140, + "printWidth": 120, + "max_line_length": 120, "semi": true, "singleQuote": true, - "arrowParens": "always", - "wrapParens": "avoid", - "endOfLine": "auto", - "jsxBracketSameLine": true, - "bracketSameLine": true + "endOfLine": "auto" } \ No newline at end of file diff --git a/frontend/src/assets/img/faculties/Bio-ingenieurswetenschappen.png b/frontend/src/assets/img/faculties/Bio-ingenieurswetenschappen.png new file mode 100644 index 00000000..253b49c2 Binary files /dev/null and b/frontend/src/assets/img/faculties/Bio-ingenieurswetenschappen.png differ diff --git a/frontend/src/assets/img/faculties/Diergeneeskunde.png b/frontend/src/assets/img/faculties/Diergeneeskunde.png new file mode 100644 index 00000000..0c934b27 Binary files /dev/null and b/frontend/src/assets/img/faculties/Diergeneeskunde.png differ diff --git a/frontend/src/assets/img/faculties/Economie_Bedrijfskunde.png b/frontend/src/assets/img/faculties/Economie_Bedrijfskunde.png new file mode 100644 index 00000000..fce93c41 Binary files /dev/null and b/frontend/src/assets/img/faculties/Economie_Bedrijfskunde.png differ diff --git a/frontend/src/assets/img/faculties/Farmaceutische_Wetenschappen.png b/frontend/src/assets/img/faculties/Farmaceutische_Wetenschappen.png new file mode 100644 index 00000000..0caed9bb Binary files /dev/null and b/frontend/src/assets/img/faculties/Farmaceutische_Wetenschappen.png differ diff --git a/frontend/src/assets/img/faculties/Geneeskunde_Gezondheidswetenschappen.png b/frontend/src/assets/img/faculties/Geneeskunde_Gezondheidswetenschappen.png new file mode 100644 index 00000000..59cc06d3 Binary files /dev/null and b/frontend/src/assets/img/faculties/Geneeskunde_Gezondheidswetenschappen.png differ diff --git a/frontend/src/assets/img/faculties/Ingenieurswetenschappen_Architectuur.png b/frontend/src/assets/img/faculties/Ingenieurswetenschappen_Architectuur.png new file mode 100644 index 00000000..9a970f9f Binary files /dev/null and b/frontend/src/assets/img/faculties/Ingenieurswetenschappen_Architectuur.png differ diff --git a/frontend/src/assets/img/faculties/Letteren_Wijsbegeerte.png b/frontend/src/assets/img/faculties/Letteren_Wijsbegeerte.png new file mode 100644 index 00000000..0e47d40d Binary files /dev/null and b/frontend/src/assets/img/faculties/Letteren_Wijsbegeerte.png differ diff --git a/frontend/src/assets/img/faculties/Politieke_Sociale_Wetenschappen.png b/frontend/src/assets/img/faculties/Politieke_Sociale_Wetenschappen.png new file mode 100644 index 00000000..adad8eb8 Binary files /dev/null and b/frontend/src/assets/img/faculties/Politieke_Sociale_Wetenschappen.png differ diff --git a/frontend/src/assets/img/faculties/Recht_Criminologie.png b/frontend/src/assets/img/faculties/Recht_Criminologie.png new file mode 100644 index 00000000..197b479a Binary files /dev/null and b/frontend/src/assets/img/faculties/Recht_Criminologie.png differ diff --git a/frontend/src/assets/img/faculties/Wetenschappen.png b/frontend/src/assets/img/faculties/Wetenschappen.png new file mode 100644 index 00000000..10e77295 Binary files /dev/null and b/frontend/src/assets/img/faculties/Wetenschappen.png differ diff --git a/frontend/src/assets/lang/nl.json b/frontend/src/assets/lang/nl.json index f470c32c..31ec1044 100644 --- a/frontend/src/assets/lang/nl.json +++ b/frontend/src/assets/lang/nl.json @@ -21,8 +21,8 @@ "dashboard": { "courses": "Mijn vakken", "projects": "Lopende projecten", - "no_projects": "Geen projecten beschikbaar voor dit academiejaar.", - "no_courses": "Geen vakken beschikbaar voor dit academiejaar." + "no_projects": "Geen projecten gevonden.", + "no_courses": "Geen vakken gevonden." }, "login": { "title": "Inloggen", @@ -46,7 +46,15 @@ "create": "Creëer vak", "name": "Vaknaam", "description": "Beschrijving", - "year": "Academiejaar" + "year": "Academiejaar", + "search": { + "search": "Zoeken", + "faculty": "Faculteit", + "year": "Academiejaar", + "placeholder": "Zoek een vak op naam", + "title": "Zoek een vak", + "results": "{0} vakken gevonden voor ingestelde filters" + } } }, "composables": { @@ -83,7 +91,23 @@ }, "toasts": { "messages": { - "unknown": "Er is een onbekende fout opgetreden." + "success": "Succes", + "error": "Fout", + "unknown": "Er is een onbekende fout opgetreden.", + "courses": { + "enrollment": { + "success": "Je bent succesvol ingeschreven voor het vak '{0}'.", + "error": "Er is een fout opgetreden tijdens het inschrijven voor het vak '{0}'." + }, + "leave": { + "success": "Je bent succesvol uitgeschreven voor het vak '{0}'.", + "error": "Er is een fout opgetreden tijdens het uitschrijven voor het vak '{0}'." + } + }, + "login": { + "success": "Je bent succesvol ingelogd.", + "error": "Er is een fout opgetreden tijdens het inloggen." + } } }, "primevue": { diff --git a/frontend/src/assets/scss/theme/_variables.scss b/frontend/src/assets/scss/theme/_variables.scss index 72fa60b3..70a12627 100644 --- a/frontend/src/assets/scss/theme/_variables.scss +++ b/frontend/src/assets/scss/theme/_variables.scss @@ -73,7 +73,7 @@ $inputTextFontSize:1rem !default; $inputBg:$shade000 !default; $inputTextColor:$shade700 !default; $inputIconColor:$shade600 !default; -$inputBorder:1px solid $primaryColor !default; +$inputBorder:1px solid $shade400 !default; $inputHoverBorderColor:$primaryColor !default; $inputFocusBorderColor:$primaryColor !default; $inputErrorBorderColor:$errorColor !default; @@ -231,12 +231,12 @@ $checkboxWidth:22px !default; $checkboxHeight:22px !default; $checkboxBorder:2px solid $shade400 !default; $checkboxIconFontSize:14px !default; -$checkboxActiveBorderColor:$primaryColor !default; -$checkboxActiveBg:$primaryColor !default; -$checkboxIconActiveColor:$primaryTextColor !default; -$checkboxActiveHoverBg:$primaryDarkerColor !default; -$checkboxIconActiveHoverColor:$primaryTextColor !default; -$checkboxActiveHoverBorderColor:$primaryDarkerColor !default; +$checkboxActiveBorderColor:$secondaryColor !default; +$checkboxActiveBg:$secondaryColor !default; +$checkboxIconActiveColor:$secondaryTextColor !default; +$checkboxActiveHoverBg:$secondaryDarkColor !default; +$checkboxIconActiveHoverColor:$secondaryTextColor !default; +$checkboxActiveHoverBorderColor:$secondaryDarkColor !default; //radiobutton $radiobuttonWidth:22px !default; @@ -356,15 +356,15 @@ $inputSwitchHandleOnBg:$shade000 !default; //panel $panelHeaderBorderColor:$shade300 !default; $panelHeaderBorder:1px solid $shade300 !default; -$panelHeaderBg:$shade100 !default; -$panelHeaderTextColor:$shade800 !default; +$panelHeaderBg:$primaryLightColor !default; +$panelHeaderTextColor:$primaryColor !default; $panelHeaderFontWeight:700 !default; $panelHeaderPadding:1.25rem !default; $panelToggleableHeaderPadding:.75rem 1.25rem !default; -$panelHeaderHoverBg:$shade200 !default; +$panelHeaderHoverBg:$primaryLightColor !default; $panelHeaderHoverBorderColor:$shade300 !default; -$panelHeaderTextHoverColor:$shade800 !default; +$panelHeaderTextHoverColor:$primaryColor !default; $panelContentBorderColor: $shade300 !default; $panelContentBorder:1px solid $shade300 !default; @@ -382,21 +382,21 @@ $panelFooterPadding:0.75rem 1.25rem !default; $accordionSpacing:4px !default; $accordionHeaderBorder:$panelHeaderBorder !default; $accordionHeaderBg:$panelHeaderBg !default; -$accordionHeaderTextColor:$shade600 !default; +$accordionHeaderTextColor:$panelHeaderTextColor !default; $accordionHeaderFontWeight:$panelHeaderFontWeight !default; $accordionHeaderPadding:$panelHeaderPadding !default; -$accordionHeaderHoverBg:$shade200 !default; +$accordionHeaderHoverBg:$panelHeaderBg !default; $accordionHeaderHoverBorderColor:$shade300 !default; -$accordionHeaderTextHoverColor:$shade800 !default; +$accordionHeaderTextHoverColor:$panelHeaderTextColor !default; $accordionHeaderActiveBg:$panelHeaderBg !default; $accordionHeaderActiveBorderColor:$shade300 !default; -$accordionHeaderTextActiveColor:$shade800 !default; +$accordionHeaderTextActiveColor:$panelHeaderTextColor !default; -$accordionHeaderActiveHoverBg:$shade200 !default; +$accordionHeaderActiveHoverBg:$panelHeaderBg !default; $accordionHeaderActiveHoverBorderColor:$shade300 !default; -$accordionHeaderTextActiveHoverColor:$shade800 !default; +$accordionHeaderTextActiveHoverColor:$panelHeaderTextColor !default; $accordionContentBorder:$panelContentBorder !default; $accordionContentBg:$panelContentBg !default; @@ -875,10 +875,10 @@ $imagePreviewActionIconBorderRadius:50% !default; --secondary-color:#{$secondaryColor}; --secondary-color-text:#{$secondaryTextColor}; --surface-0: #ffffff; - --surface-50: #{$primaryLightColor}50; - --surface-100: #{$primaryLightColor}; - --surface-200: #e5e7eb; - --surface-300: #d1d5db; + --surface-50: #{$primaryLightColor}55; + --surface-100: #{$primaryLightColor}70; + --surface-200: #{$primaryLightColor}85; + --surface-300: #{$primaryLightColor}; --surface-400: #{$primaryColor}25; --surface-500: #{$primaryColor}40; --surface-600: #{$primaryColor}55; diff --git a/frontend/src/components/LanguageSelector.vue b/frontend/src/components/LanguageSelector.vue index 4bb89a5f..e4deaf19 100644 --- a/frontend/src/components/LanguageSelector.vue +++ b/frontend/src/components/LanguageSelector.vue @@ -50,7 +50,8 @@ onMounted(() => { class="w-auto" :options="availableLocales" @change="updateLocale($event.value)" - variant="outlined"> + variant="outlined" + >