diff --git a/tin/apps/users/forms.py b/tin/apps/users/forms.py index 38c7ed1c..4d249155 100644 --- a/tin/apps/users/forms.py +++ b/tin/apps/users/forms.py @@ -6,3 +6,7 @@ class UserMultipleChoiceField(forms.ModelMultipleChoiceField): def label_from_instance(self, user): # pylint: disable=arguments-differ return f"{user.full_name} ({user.username})" + + +class ThemeForm(forms.Form): + dark_mode = forms.IntegerField() diff --git a/tin/apps/users/migrations/0003_user_dark_mode.py b/tin/apps/users/migrations/0003_user_dark_mode.py new file mode 100644 index 00000000..80174d87 --- /dev/null +++ b/tin/apps/users/migrations/0003_user_dark_mode.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.15 on 2024-09-03 19:43 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0002_remove_user_is_sysadmin'), + ] + + operations = [ + migrations.AddField( + model_name='user', + name='dark_mode', + field=models.IntegerField(default=0), + ), + ] diff --git a/tin/apps/users/models.py b/tin/apps/users/models.py index a5e90d56..3ed14353 100644 --- a/tin/apps/users/models.py +++ b/tin/apps/users/models.py @@ -30,6 +30,7 @@ class User(AbstractBaseUser, PermissionsMixin): is_teacher = models.BooleanField(default=False) is_student = models.BooleanField(default=False) date_joined = models.DateTimeField(default=timezone.now) + dark_mode = models.IntegerField(default=0) USERNAME_FIELD = "username" REQUIRED_FIELDS = ["email"] diff --git a/tin/apps/users/urls.py b/tin/apps/users/urls.py new file mode 100644 index 00000000..5d5e3334 --- /dev/null +++ b/tin/apps/users/urls.py @@ -0,0 +1,11 @@ +from __future__ import annotations + +from django.urls import path + +from . import views + +app_name = "users" + +urlpatterns = [ + path("theme/", views.change_theme, name="theme"), +] diff --git a/tin/apps/users/views.py b/tin/apps/users/views.py new file mode 100644 index 00000000..21568bbf --- /dev/null +++ b/tin/apps/users/views.py @@ -0,0 +1,19 @@ +from __future__ import annotations + +from django import http +from django.contrib.auth.decorators import login_required + +from tin.apps.users.forms import ThemeForm + + +@login_required +def change_theme(request): + if request.method == "POST": + form = ThemeForm(request.POST) + if form.is_valid(): + request.user.dark_mode = form.cleaned_data["dark_mode"] + request.user.save() + return http.JsonResponse({"success": True}) + else: + return http.JsonResponse({"success": False, "errors": form.errors}, status=400) + raise http.Http404 diff --git a/tin/static/css/base.css b/tin/static/css/base.css index b7c2a7f9..636a8e54 100644 --- a/tin/static/css/base.css +++ b/tin/static/css/base.css @@ -7,6 +7,7 @@ color: white; line-height: 40px; background: #4fab4f; + position: relative; } #nav ul { @@ -413,3 +414,19 @@ ul.errors { white-space: pre-wrap; } } + +#theme-toggle { + width: 30px; + height: 30px; +} + +.theme-toggle-button { + background: transparent; + border: none; + cursor: pointer; + padding: 0; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-85%, 12%); +} diff --git a/tin/templates/base.html b/tin/templates/base.html index 7629a206..99e89521 100644 --- a/tin/templates/base.html +++ b/tin/templates/base.html @@ -8,6 +8,10 @@ {% include "meta.html" %} + {% if request.user.dark_mode == 1 %} + + + {% endif %} @@ -44,8 +48,56 @@ $(".continuous-progress").css({height: "15px"}).progressbar({value: false}) }); + {% block head %}{% endblock %} +
@@ -90,6 +142,13 @@ {% endif %}