diff --git a/CHANGELOG.rst b/CHANGELOG.rst index dc5a3275ceea0f049f2e61782efcb796e2deff18..aa0cdbc0d149f9e597899d04054e1007fd04770e 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -9,6 +9,57 @@ and this project adheres to `Semantic Versioning`_. Unreleased ---------- +Added +~~~~~ + +* Allow to disable exception mails to admins +* Add possibility to create iCal feeds in all apps and dynamically create user-specific urls. + +Fixed +~~~~~ + +* The menu button used to be displayed twice on smaller screens. +* The icons were loaded from external servers instead from local server. +* Weekdays were not translated if system locales were missing + * Added locales-all to base image and note to docs +* The icons in the account menu were still the old ones. +* Due to a merge error, the once removed account menu in the sidenav appeared again. +* Scheduled notifications were shown on dashboard before time. +* Remove broken notifications menu item in favor of item next to account menu. +* Serve OAuth discovery information under root of domain + +Changed +~~~~~~~ + +* [Dev] ActionForm now checks permissions on objects before executing +* [Dev] ActionForm now returns a proper return value from the executed action + +2.8.1`_ - 2022-03-13 +-------------------- + +Changed +~~~~~~~ + +* Official apps can now override any setting + +`2.8`_ - 2022-03-11 +------------------- + +Added +~~~~~ + +* Add iconify icons +* Use identicons where avatars are missing. +* Display personal photos instead of avatars based on a site preference. +* Add an account menu in the top navbar. +* Create a reusable snippet for avatar content. +* Allow to configure if additional field is required +* Allow to configure description of additional fields +* Allow configuring regex for allowed usernames +* [Dev] Support scheduled notifications. +* Implement StaticContentWidget +* Allow to enable password change independently of password reset + Changed ~~~~~~~ @@ -17,7 +68,12 @@ Changed Fixed ~~~~~ -* Serve OAuth discovery information under root of domain +* The ``reset password`` button on the login site used to overflow the card on smaller devices. + +Deprecated +~~~~~~~~~~ + +* Legacy material icon font will be removed in AlekSIS-Core 3.0 `2.7.4`_ - 2022-02-09 --------------------- @@ -763,3 +819,5 @@ Fixed .. _2.7.2: https://edugit.org/AlekSIS/Official/AlekSIS/-/tags/2.7.2 .. _2.7.3: https://edugit.org/AlekSIS/Official/AlekSIS/-/tags/2.7.3 .. _2.7.4: https://edugit.org/AlekSIS/Official/AlekSIS/-/tags/2.7.4 +.. _2.8: https://edugit.org/AlekSIS/Official/AlekSIS/-/tags/2.8 +.. _2.8.1: https://edugit.org/AlekSIS/Official/AlekSIS/-/tags/2.8.1 diff --git a/Dockerfile b/Dockerfile index acb08f98ffe79dccc32f048590bb123c2763302f..4864ac54613a8823fbc118fe73291e127b7939e1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -36,6 +36,7 @@ RUN apt-get -y update && \ less \ libpq-dev \ libssl-dev \ + locales-all \ postgresql-client-14 \ pspg \ python3-dev \ diff --git a/README.rst b/README.rst index a6732de3b038f5d1d4f5b59d2c05f3c77840c2b9..290669c5779841ac7713f7f8004cc3141de0b1f9 100644 --- a/README.rst +++ b/README.rst @@ -64,7 +64,7 @@ Licence Copyright © 2017, 2018, 2019, 2020, 2021, 2022 Jonathan Weth <dev@jonathanweth.de> Copyright © 2017, 2018, 2019, 2020 Frank Poetzsch-Heffter <p-h@katharineum.de> Copyright © 2018, 2019, 2020, 2021, 2022 Hangzhi Yu <yuha@katharineum.de> - Copyright © 2018, 2019, 2020, 2021 Julian Leucker <leuckeju@katharineum.de> + Copyright © 2018, 2019, 2020, 2021, 2022 Julian Leucker <leuckeju@katharineum.de> Copyright © 2019, 2020, 2021, 2022 Dominik George <dominik.george@teckids.org> Copyright © 2019, 2020, 2021, 2022 Tom Teichler <tom.teichler@teckids.org> Copyright © 2019 mirabilos <thorsten.glaser@teckids.org> diff --git a/aleksis/core/apps.py b/aleksis/core/apps.py index 77e4b2a6327d9b88254b160375b1ce85be73ed68..08c965a02a7d6d0c4c53fb1bbcc5919ad35f7b7e 100644 --- a/aleksis/core/apps.py +++ b/aleksis/core/apps.py @@ -39,7 +39,7 @@ class CoreConfig(AppConfig): ([2017, 2018, 2019, 2020, 2021, 2022], "Jonathan Weth", "wethjo@katharineum.de"), ([2017, 2018, 2019, 2020], "Frank Poetzsch-Heffter", "p-h@katharineum.de"), ([2018, 2019, 2020, 2021, 2022], "Hangzhi Yu", "yuha@katharineum.de"), - ([2018, 2019, 2020, 2021], "Julian Leucker", "leuckeju@katharineum.de"), + ([2018, 2019, 2020, 2021, 2022], "Julian Leucker", "leuckeju@katharineum.de"), ([2019, 2020, 2021, 2022], "Dominik George", "dominik.george@teckids.org"), ([2019, 2020, 2021, 2022], "Tom Teichler", "tom.teichler@teckids.org"), ([2019], "mirabilos", "thorsten.glaser@teckids.org"), diff --git a/aleksis/core/feeds.py b/aleksis/core/feeds.py new file mode 100644 index 0000000000000000000000000000000000000000..fdfd6bc1f1123683f15e8b4baeada483892fa8f5 --- /dev/null +++ b/aleksis/core/feeds.py @@ -0,0 +1,80 @@ +from django.conf import settings +from django.utils.formats import date_format +from django.utils.functional import classproperty +from django.utils.translation import gettext_lazy as _ + +from django_ical.utils import build_rrule_from_text +from django_ical.views import ICalFeed + +from aleksis.core import models +from aleksis.core.util.core_helpers import get_site_preferences, queryset_rules_filter + + +class PersonalICalFeedBase(ICalFeed): + """Base class for personal iCal feeds.""" + + @property + def product_id(self): + lang = self.request.LANGUAGE_CODE + title = get_site_preferences()["general__title"] + return f"-//AlekSIS//{title}//{lang}" + + link = settings.BASE_URL + timezone = settings.TIME_ZONE + person = None + request = None + + def get_object(self, request, *args, **kwargs): + if kwargs.get("person"): + self.person = kwargs.pop("person") + self.request = request + return super().get_object(request, *args, **kwargs) + + @classproperty + def subclasses_list(cls): + return cls.__subclasses__() + + @classproperty + def subclasses_dict(cls): + return {subclass.__name__: subclass for subclass in cls.subclasses_list} + + @classproperty + def subclass_choices(cls): + return [ + (subclass.__name__, f"{subclass.title} – {subclass.description}") + for subclass in cls.subclasses_list + ] + + +class BirthdayFeed(PersonalICalFeedBase): + """Birthday calendar feed.""" + + title = _("Birthday Calendar") + description = _("A Calendar of Birthdays") + file_name = "birthdays.ics" + + def items(self): + from aleksis.core.models import Person + + return queryset_rules_filter( + obj=self.person.user, + perm="core.view_personal_details_rule", + queryset=Person.objects.filter(date_of_birth__isnull=False), + ) + + def item_title(self, item: "models.Person"): + return _("%(name)s's birthday") % { + "name": item.addressing_name, + } + + def item_description(self, item: "models.Person"): + return _("%(name)s was born on %(birthday)s") % { + "name": item.addressing_name, + "birthday": date_format(item.date_of_birth), + } + + def item_start_datetime(self, item): + return item.date_of_birth + + def item_rrule(self, item): + return build_rrule_from_text("FREQ=YEARLY") diff --git a/aleksis/core/forms.py b/aleksis/core/forms.py index ef4184812f73d22bb1dcfa1ff84f74f722c3c774..3fb938822b093e250299a3fac04f0e0358e6f47a 100644 --- a/aleksis/core/forms.py +++ b/aleksis/core/forms.py @@ -39,7 +39,7 @@ from .registries import ( site_preferences_registry, ) from .util.auth_helpers import AppScopes -from .util.core_helpers import get_site_preferences +from .util.core_helpers import get_site_preferences, queryset_rules_filter class PersonForm(ExtensibleForm): @@ -722,17 +722,37 @@ class ActionForm(forms.Form): self.fields["selected_objects"].queryset = self.queryset self.fields["action"].choices = self._get_action_choices() - def execute(self) -> bool: + def clean_action(self): + action = self._get_actions_dict().get(self.cleaned_data["action"], None) + if not action: + raise ValidationError(_("The selected action does not exist.")) + return action + + def clean_selected_objects(self): + action = self.cleaned_data["action"] + if hasattr(action, "permission"): + selected_objects = queryset_rules_filter( + self.request, self.cleaned_data["selected_objects"], action.permission + ) + if selected_objects.count() < self.cleaned_data["selected_objects"].count(): + raise ValidationError( + _("You do not have permission to run {} on all selected objects.").format( + getattr(value, "short_description", value.__name__) + ) + ) + return self.cleaned_data["selected_objects"] + + def execute(self) -> Any: """Execute the selected action on all selected objects. - :return: If the form is not valid, it will return ``False``. + :return: the return value of the action """ if self.is_valid(): data = self.cleaned_data["selected_objects"] - action = self._get_actions_dict()[self.cleaned_data["action"]] - action(None, self.request, data) - return True - return False + action = self.cleaned_data["action"] + return action(None, self.request, data) + + raise TypeError("execute() must be called on a pre-validated form.") class ListActionForm(ActionForm): diff --git a/aleksis/core/locale/ar/LC_MESSAGES/django.po b/aleksis/core/locale/ar/LC_MESSAGES/django.po index a382635f245835c9c747b72cb4b661bd39eb7e04..ee356cc39b7d01a0aad1fd7fa3e0343f42da7a6c 100644 --- a/aleksis/core/locale/ar/LC_MESSAGES/django.po +++ b/aleksis/core/locale/ar/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: AlekSIS (School Information System) 0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-02-08 23:16+0000\n" +"POT-Creation-Date: 2022-03-23 11:19+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -38,10 +38,10 @@ msgstr "" msgid "Home and mobile phone" msgstr "" -#: aleksis/core/apps.py:171 aleksis/core/forms.py:220 aleksis/core/menus.py:265 -#: aleksis/core/models.py:462 aleksis/core/templates/core/group/list.html:8 +#: aleksis/core/apps.py:171 aleksis/core/forms.py:220 aleksis/core/menus.py:185 +#: aleksis/core/models.py:487 aleksis/core/templates/core/group/list.html:8 #: aleksis/core/templates/core/group/list.html:9 -#: aleksis/core/templates/core/person/full.html:250 +#: aleksis/core/templates/core/person/full.html:246 msgid "Groups" msgstr "" @@ -66,8 +66,8 @@ msgstr "" msgid "The DashboardWidget was reported broken automatically." msgstr "" -#: aleksis/core/filters.py:42 aleksis/core/templates/core/base.html:105 -#: aleksis/core/templates/core/base.html:106 +#: aleksis/core/filters.py:42 aleksis/core/templates/core/base.html:139 +#: aleksis/core/templates/core/base.html:140 #: aleksis/core/templates/core/group/list.html:20 #: aleksis/core/templates/core/person/list.html:24 #: aleksis/core/templates/search/search.html:7 @@ -91,11 +91,11 @@ msgstr "" msgid "Content type" msgstr "" -#: aleksis/core/filters.py:113 aleksis/core/models.py:688 +#: aleksis/core/filters.py:113 aleksis/core/models.py:713 msgid "User" msgstr "" -#: aleksis/core/filters.py:135 aleksis/core/models.py:461 +#: aleksis/core/filters.py:135 aleksis/core/models.py:486 msgid "Group" msgstr "" @@ -131,7 +131,7 @@ msgstr "" msgid "This username is already in use." msgstr "" -#: aleksis/core/forms.py:153 aleksis/core/models.py:130 +#: aleksis/core/forms.py:153 aleksis/core/models.py:134 msgid "School term" msgstr "" @@ -140,7 +140,7 @@ msgid "Common data" msgstr "" #: aleksis/core/forms.py:155 aleksis/core/forms.py:207 -#: aleksis/core/menus.py:254 aleksis/core/models.py:153 +#: aleksis/core/menus.py:174 aleksis/core/models.py:157 #: aleksis/core/templates/core/person/list.html:8 #: aleksis/core/templates/core/person/list.html:9 msgid "Persons" @@ -150,18 +150,18 @@ msgstr "" msgid "Additional data" msgstr "" -#: aleksis/core/forms.py:157 aleksis/core/models.py:206 -#: aleksis/core/models.py:514 +#: aleksis/core/forms.py:157 aleksis/core/models.py:210 +#: aleksis/core/models.py:539 msgid "Photo" msgstr "" #: aleksis/core/forms.py:199 aleksis/core/forms.py:202 -#: aleksis/core/models.py:73 +#: aleksis/core/models.py:77 msgid "Date" msgstr "" #: aleksis/core/forms.py:200 aleksis/core/forms.py:203 -#: aleksis/core/models.py:81 +#: aleksis/core/models.py:85 msgid "Time" msgstr "" @@ -197,11 +197,11 @@ msgstr "" msgid "Please enter your invitation code." msgstr "" -#: aleksis/core/forms.py:418 aleksis/core/models.py:181 +#: aleksis/core/forms.py:418 aleksis/core/models.py:185 msgid "First name" msgstr "" -#: aleksis/core/forms.py:419 aleksis/core/models.py:182 +#: aleksis/core/forms.py:419 aleksis/core/models.py:186 msgid "Last name" msgstr "" @@ -249,7 +249,15 @@ msgstr "" msgid "Password (again)" msgstr "" -#: aleksis/core/forms.py:775 +#: aleksis/core/forms.py:728 +msgid "The selected action does not exist." +msgstr "" + +#: aleksis/core/forms.py:739 +msgid "You do not have permission to run {} on all selected objects." +msgstr "" + +#: aleksis/core/forms.py:795 msgid "No valid selection." msgstr "" @@ -292,678 +300,698 @@ msgstr "" msgid "Dashboard" msgstr "" -#: aleksis/core/menus.py:41 aleksis/core/models.py:734 -#: aleksis/core/preferences.py:29 +#: aleksis/core/menus.py:41 aleksis/core/models.py:765 +#: aleksis/core/preferences.py:29 aleksis/core/templates/core/base.html:81 #: aleksis/core/templates/core/notifications.html:4 #: aleksis/core/templates/core/notifications.html:5 msgid "Notifications" msgstr "" #: aleksis/core/menus.py:53 -msgid "Account" -msgstr "" - -#: aleksis/core/menus.py:60 -msgid "Stop impersonation" -msgstr "" - -#: aleksis/core/menus.py:69 aleksis/core/templates/core/base.html:80 -msgid "Logout" -msgstr "" - -#: aleksis/core/menus.py:75 -msgid "2FA" -msgstr "" - -#: aleksis/core/menus.py:83 -#: aleksis/core/templates/account/password_change.html:5 -#: aleksis/core/templates/account/password_change.html:6 -#: aleksis/core/templates/account/password_change.html:19 -#: aleksis/core/templates/account/password_reset_from_key.html:5 -#: aleksis/core/templates/account/password_reset_from_key.html:42 -#: aleksis/core/templates/account/password_reset_from_key.html:46 -#: aleksis/core/templates/account/password_reset_from_key_done.html:5 -#: aleksis/core/templates/account/password_reset_from_key_done.html:6 -msgid "Change password" -msgstr "" - -#: aleksis/core/menus.py:95 -msgid "Me" -msgstr "" - -#: aleksis/core/menus.py:104 -#: aleksis/core/templates/dynamic_preferences/form.html:5 -msgid "Preferences" -msgstr "" - -#: aleksis/core/menus.py:113 -msgid "Third-party accounts" -msgstr "" - -#: aleksis/core/menus.py:122 -#: aleksis/core/templates/oauth2_provider/authorized-tokens.html:5 -#: aleksis/core/templates/oauth2_provider/authorized-tokens.html:6 -msgid "Authorized applications" -msgstr "" - -#: aleksis/core/menus.py:133 msgid "Admin" msgstr "" -#: aleksis/core/menus.py:141 aleksis/core/models.py:834 +#: aleksis/core/menus.py:61 aleksis/core/models.py:865 #: aleksis/core/templates/core/announcement/list.html:7 #: aleksis/core/templates/core/announcement/list.html:8 msgid "Announcements" msgstr "" -#: aleksis/core/menus.py:152 aleksis/core/models.py:131 +#: aleksis/core/menus.py:72 aleksis/core/models.py:135 #: aleksis/core/templates/core/school_term/list.html:8 #: aleksis/core/templates/core/school_term/list.html:9 msgid "School terms" msgstr "" -#: aleksis/core/menus.py:163 +#: aleksis/core/menus.py:83 #: aleksis/core/templates/core/dashboard_widget/list.html:8 #: aleksis/core/templates/core/dashboard_widget/list.html:9 msgid "Dashboard widgets" msgstr "" -#: aleksis/core/menus.py:174 +#: aleksis/core/menus.py:94 #: aleksis/core/templates/core/management/data_management.html:6 #: aleksis/core/templates/core/management/data_management.html:7 msgid "Data management" msgstr "" -#: aleksis/core/menus.py:185 +#: aleksis/core/menus.py:105 #: aleksis/core/templates/core/pages/system_status.html:5 #: aleksis/core/templates/core/pages/system_status.html:7 msgid "System status" msgstr "" -#: aleksis/core/menus.py:196 +#: aleksis/core/menus.py:116 msgid "Configuration" msgstr "" -#: aleksis/core/menus.py:207 aleksis/core/templates/core/data_check/list.html:9 +#: aleksis/core/menus.py:127 aleksis/core/templates/core/data_check/list.html:9 #: aleksis/core/templates/core/data_check/list.html:10 msgid "Data checks" msgstr "" -#: aleksis/core/menus.py:213 aleksis/core/templates/core/perms/list.html:13 +#: aleksis/core/menus.py:133 aleksis/core/templates/core/perms/list.html:13 #: aleksis/core/templates/core/perms/list.html:14 msgid "Manage permissions" msgstr "" -#: aleksis/core/menus.py:224 +#: aleksis/core/menus.py:144 msgid "Backend Admin" msgstr "" -#: aleksis/core/menus.py:232 +#: aleksis/core/menus.py:152 #: aleksis/core/templates/oauth2_provider/application/list.html:5 #: aleksis/core/templates/oauth2_provider/application/list.html:6 msgid "OAuth2 Applications" msgstr "" -#: aleksis/core/menus.py:245 +#: aleksis/core/menus.py:165 msgid "People" msgstr "" -#: aleksis/core/menus.py:276 aleksis/core/models.py:1055 +#: aleksis/core/menus.py:196 aleksis/core/models.py:1099 #: aleksis/core/templates/core/group_type/list.html:8 #: aleksis/core/templates/core/group_type/list.html:9 msgid "Group types" msgstr "" -#: aleksis/core/menus.py:287 +#: aleksis/core/menus.py:207 msgid "Groups and child groups" msgstr "" -#: aleksis/core/menus.py:298 aleksis/core/models.py:510 +#: aleksis/core/menus.py:218 aleksis/core/models.py:535 #: aleksis/core/templates/core/additional_field/list.html:8 #: aleksis/core/templates/core/additional_field/list.html:9 msgid "Additional fields" msgstr "" -#: aleksis/core/menus.py:309 +#: aleksis/core/menus.py:229 msgid "Invite person" msgstr "" -#: aleksis/core/menus.py:322 +#: aleksis/core/menus.py:242 #: aleksis/core/templates/core/group/child_groups.html:7 #: aleksis/core/templates/core/group/child_groups.html:9 msgid "Assign child groups to groups" msgstr "" +#: aleksis/core/menus.py:254 +msgid "Stop impersonation" +msgstr "" + +#: aleksis/core/menus.py:263 +msgid "Account" +msgstr "" + +#: aleksis/core/menus.py:272 +#: aleksis/core/templates/dynamic_preferences/form.html:5 +msgid "Preferences" +msgstr "" + +#: aleksis/core/menus.py:281 +msgid "2FA" +msgstr "" + +#: aleksis/core/menus.py:289 +#: aleksis/core/templates/account/password_change.html:5 +#: aleksis/core/templates/account/password_change.html:6 +#: aleksis/core/templates/account/password_change.html:19 +#: aleksis/core/templates/account/password_reset_from_key.html:5 +#: aleksis/core/templates/account/password_reset_from_key.html:42 +#: aleksis/core/templates/account/password_reset_from_key.html:46 +#: aleksis/core/templates/account/password_reset_from_key_done.html:5 +#: aleksis/core/templates/account/password_reset_from_key_done.html:6 +msgid "Change password" +msgstr "" + +#: aleksis/core/menus.py:301 +msgid "Third-party accounts" +msgstr "" + +#: aleksis/core/menus.py:310 +#: aleksis/core/templates/oauth2_provider/authorized-tokens.html:5 +#: aleksis/core/templates/oauth2_provider/authorized-tokens.html:6 +msgid "Authorized applications" +msgstr "" + +#: aleksis/core/menus.py:320 +msgid "Logout" +msgstr "" + #: aleksis/core/mixins.py:511 msgid "Linked school term" msgstr "" -#: aleksis/core/models.py:71 +#: aleksis/core/models.py:75 msgid "Boolean (Yes/No)" msgstr "" -#: aleksis/core/models.py:72 +#: aleksis/core/models.py:76 msgid "Text (one line)" msgstr "" -#: aleksis/core/models.py:74 +#: aleksis/core/models.py:78 msgid "Date and time" msgstr "" -#: aleksis/core/models.py:75 +#: aleksis/core/models.py:79 msgid "Decimal number" msgstr "" -#: aleksis/core/models.py:76 aleksis/core/models.py:199 +#: aleksis/core/models.py:80 aleksis/core/models.py:203 msgid "E-mail address" msgstr "" -#: aleksis/core/models.py:77 +#: aleksis/core/models.py:81 msgid "Integer" msgstr "" -#: aleksis/core/models.py:78 +#: aleksis/core/models.py:82 msgid "IP address" msgstr "" -#: aleksis/core/models.py:79 +#: aleksis/core/models.py:83 msgid "Boolean or empty (Yes/No/Neither)" msgstr "" -#: aleksis/core/models.py:80 +#: aleksis/core/models.py:84 msgid "Text (multi-line)" msgstr "" -#: aleksis/core/models.py:82 +#: aleksis/core/models.py:86 msgid "URL / Link" msgstr "" -#: aleksis/core/models.py:94 aleksis/core/models.py:1024 +#: aleksis/core/models.py:98 aleksis/core/models.py:1068 msgid "Name" msgstr "" -#: aleksis/core/models.py:96 +#: aleksis/core/models.py:100 msgid "Start date" msgstr "" -#: aleksis/core/models.py:97 +#: aleksis/core/models.py:101 msgid "End date" msgstr "" -#: aleksis/core/models.py:116 +#: aleksis/core/models.py:120 msgid "The start date must be earlier than the end date." msgstr "" -#: aleksis/core/models.py:123 +#: aleksis/core/models.py:127 msgid "There is already a school term for this time or a part of this time." msgstr "" -#: aleksis/core/models.py:152 aleksis/core/models.py:973 +#: aleksis/core/models.py:156 aleksis/core/models.py:1017 msgid "Person" msgstr "" -#: aleksis/core/models.py:155 +#: aleksis/core/models.py:159 msgid "Can view address" msgstr "" -#: aleksis/core/models.py:156 +#: aleksis/core/models.py:160 msgid "Can view contact details" msgstr "" -#: aleksis/core/models.py:157 +#: aleksis/core/models.py:161 msgid "Can view photo" msgstr "" -#: aleksis/core/models.py:158 +#: aleksis/core/models.py:162 msgid "Can view avatar image" msgstr "" -#: aleksis/core/models.py:159 +#: aleksis/core/models.py:163 msgid "Can view persons groups" msgstr "" -#: aleksis/core/models.py:160 +#: aleksis/core/models.py:164 msgid "Can view personal details" msgstr "" -#: aleksis/core/models.py:170 +#: aleksis/core/models.py:174 msgid "female" msgstr "" -#: aleksis/core/models.py:170 +#: aleksis/core/models.py:174 msgid "male" msgstr "" -#: aleksis/core/models.py:178 aleksis/core/models.py:1227 +#: aleksis/core/models.py:182 aleksis/core/models.py:1271 msgid "Linked user" msgstr "" -#: aleksis/core/models.py:184 +#: aleksis/core/models.py:188 msgid "Additional name(s)" msgstr "" -#: aleksis/core/models.py:188 aleksis/core/models.py:479 +#: aleksis/core/models.py:192 aleksis/core/models.py:504 msgid "Short name" msgstr "" -#: aleksis/core/models.py:191 +#: aleksis/core/models.py:195 msgid "Street" msgstr "" -#: aleksis/core/models.py:192 +#: aleksis/core/models.py:196 msgid "Street number" msgstr "" -#: aleksis/core/models.py:193 +#: aleksis/core/models.py:197 msgid "Postal code" msgstr "" -#: aleksis/core/models.py:194 +#: aleksis/core/models.py:198 msgid "Place" msgstr "" -#: aleksis/core/models.py:196 aleksis/core/templates/core/person/full.html:172 +#: aleksis/core/models.py:200 aleksis/core/templates/core/person/full.html:160 msgid "Home phone" msgstr "" -#: aleksis/core/models.py:197 aleksis/core/templates/core/person/full.html:182 +#: aleksis/core/models.py:201 aleksis/core/templates/core/person/full.html:170 msgid "Mobile phone" msgstr "" -#: aleksis/core/models.py:201 +#: aleksis/core/models.py:205 msgid "Date of birth" msgstr "" -#: aleksis/core/models.py:202 +#: aleksis/core/models.py:206 msgid "Place of birth" msgstr "" -#: aleksis/core/models.py:203 +#: aleksis/core/models.py:207 msgid "Sex" msgstr "" -#: aleksis/core/models.py:210 aleksis/core/models.py:518 +#: aleksis/core/models.py:214 aleksis/core/models.py:543 msgid "This is an official photo, used for official documents and for internal use cases." msgstr "" -#: aleksis/core/models.py:215 aleksis/core/models.py:522 +#: aleksis/core/models.py:219 aleksis/core/models.py:547 msgid "Display picture / Avatar" msgstr "" -#: aleksis/core/models.py:218 aleksis/core/models.py:525 +#: aleksis/core/models.py:222 aleksis/core/models.py:550 msgid "This is a picture or an avatar for public display." msgstr "" -#: aleksis/core/models.py:223 aleksis/core/templates/core/person/full.html:239 +#: aleksis/core/models.py:227 aleksis/core/templates/core/person/full.html:235 msgid "Guardians / Parents" msgstr "" -#: aleksis/core/models.py:230 +#: aleksis/core/models.py:234 msgid "Primary group" msgstr "" -#: aleksis/core/models.py:233 aleksis/core/models.py:692 -#: aleksis/core/models.py:716 aleksis/core/models.py:801 -#: aleksis/core/models.py:1048 +#: aleksis/core/models.py:237 aleksis/core/models.py:717 +#: aleksis/core/models.py:741 aleksis/core/models.py:832 +#: aleksis/core/models.py:1092 msgid "Description" msgstr "" -#: aleksis/core/models.py:434 +#: aleksis/core/models.py:457 msgid "Title of field" msgstr "" -#: aleksis/core/models.py:436 +#: aleksis/core/models.py:459 msgid "Type of field" msgstr "" -#: aleksis/core/models.py:443 +#: aleksis/core/models.py:461 +msgid "Required" +msgstr "" + +#: aleksis/core/models.py:462 +msgid "Help text / description" +msgstr "" + +#: aleksis/core/models.py:468 msgid "Addtitional field for groups" msgstr "" -#: aleksis/core/models.py:444 +#: aleksis/core/models.py:469 msgid "Addtitional fields for groups" msgstr "" -#: aleksis/core/models.py:464 +#: aleksis/core/models.py:489 msgid "Can assign child groups to groups" msgstr "" -#: aleksis/core/models.py:465 +#: aleksis/core/models.py:490 msgid "Can view statistics about group." msgstr "" -#: aleksis/core/models.py:477 +#: aleksis/core/models.py:502 msgid "Long name" msgstr "" -#: aleksis/core/models.py:487 aleksis/core/templates/core/group/full.html:85 +#: aleksis/core/models.py:512 aleksis/core/templates/core/group/full.html:85 msgid "Members" msgstr "" -#: aleksis/core/models.py:490 aleksis/core/templates/core/group/full.html:82 +#: aleksis/core/models.py:515 aleksis/core/templates/core/group/full.html:82 msgid "Owners" msgstr "" -#: aleksis/core/models.py:497 aleksis/core/templates/core/group/full.html:55 +#: aleksis/core/models.py:522 aleksis/core/templates/core/group/full.html:55 msgid "Parent groups" msgstr "" -#: aleksis/core/models.py:505 +#: aleksis/core/models.py:530 msgid "Type of group" msgstr "" -#: aleksis/core/models.py:691 aleksis/core/models.py:715 -#: aleksis/core/models.py:800 +#: aleksis/core/models.py:716 aleksis/core/models.py:740 +#: aleksis/core/models.py:831 #: aleksis/core/templates/core/announcement/list.html:18 msgid "Title" msgstr "" -#: aleksis/core/models.py:694 +#: aleksis/core/models.py:719 msgid "Application" msgstr "" -#: aleksis/core/models.py:700 +#: aleksis/core/models.py:725 msgid "Activity" msgstr "" -#: aleksis/core/models.py:701 +#: aleksis/core/models.py:726 msgid "Activities" msgstr "" -#: aleksis/core/models.py:707 +#: aleksis/core/models.py:732 msgid "Sender" msgstr "" -#: aleksis/core/models.py:712 +#: aleksis/core/models.py:737 msgid "Recipient" msgstr "" -#: aleksis/core/models.py:717 aleksis/core/models.py:1025 +#: aleksis/core/models.py:742 aleksis/core/models.py:1069 msgid "Link" msgstr "" -#: aleksis/core/models.py:719 +#: aleksis/core/models.py:744 +msgid "Send notification at" +msgstr "" + +#: aleksis/core/models.py:746 msgid "Read" msgstr "" -#: aleksis/core/models.py:720 +#: aleksis/core/models.py:747 msgid "Sent" msgstr "" -#: aleksis/core/models.py:733 +#: aleksis/core/models.py:764 msgid "Notification" msgstr "" -#: aleksis/core/models.py:802 +#: aleksis/core/models.py:833 msgid "Link to detailed view" msgstr "" -#: aleksis/core/models.py:805 +#: aleksis/core/models.py:836 msgid "Date and time from when to show" msgstr "" -#: aleksis/core/models.py:808 +#: aleksis/core/models.py:839 msgid "Date and time until when to show" msgstr "" -#: aleksis/core/models.py:833 +#: aleksis/core/models.py:864 msgid "Announcement" msgstr "" -#: aleksis/core/models.py:871 +#: aleksis/core/models.py:902 msgid "Announcement recipient" msgstr "" -#: aleksis/core/models.py:872 +#: aleksis/core/models.py:903 msgid "Announcement recipients" msgstr "" -#: aleksis/core/models.py:894 +#: aleksis/core/models.py:925 msgid "Widget Title" msgstr "" -#: aleksis/core/models.py:895 +#: aleksis/core/models.py:926 msgid "Activate Widget" msgstr "" -#: aleksis/core/models.py:896 +#: aleksis/core/models.py:927 msgid "Widget is broken" msgstr "" -#: aleksis/core/models.py:899 +#: aleksis/core/models.py:930 msgid "Size on mobile devices" msgstr "" -#: aleksis/core/models.py:900 +#: aleksis/core/models.py:931 msgid "<= 600 px, 12 columns" msgstr "" -#: aleksis/core/models.py:905 +#: aleksis/core/models.py:936 msgid "Size on tablet devices" msgstr "" -#: aleksis/core/models.py:906 +#: aleksis/core/models.py:937 msgid "> 600 px, 12 columns" msgstr "" -#: aleksis/core/models.py:911 +#: aleksis/core/models.py:942 msgid "Size on desktop devices" msgstr "" -#: aleksis/core/models.py:912 +#: aleksis/core/models.py:943 msgid "> 992 px, 12 columns" msgstr "" -#: aleksis/core/models.py:917 +#: aleksis/core/models.py:948 msgid "Size on large desktop devices" msgstr "" -#: aleksis/core/models.py:918 +#: aleksis/core/models.py:949 msgid "> 1200 px>, 12 columns" msgstr "" -#: aleksis/core/models.py:949 +#: aleksis/core/models.py:980 msgid "Can edit default dashboard" msgstr "" -#: aleksis/core/models.py:950 +#: aleksis/core/models.py:981 msgid "Dashboard Widget" msgstr "" -#: aleksis/core/models.py:951 +#: aleksis/core/models.py:982 msgid "Dashboard Widgets" msgstr "" -#: aleksis/core/models.py:957 +#: aleksis/core/models.py:988 msgid "URL" msgstr "" -#: aleksis/core/models.py:958 +#: aleksis/core/models.py:989 msgid "Icon URL" msgstr "" -#: aleksis/core/models.py:964 +#: aleksis/core/models.py:995 msgid "External link widget" msgstr "" -#: aleksis/core/models.py:965 +#: aleksis/core/models.py:996 msgid "External link widgets" msgstr "" -#: aleksis/core/models.py:970 +#: aleksis/core/models.py:1002 +msgid "Content" +msgstr "" + +#: aleksis/core/models.py:1008 +msgid "Static content widget" +msgstr "" + +#: aleksis/core/models.py:1009 +msgid "Static content widgets" +msgstr "" + +#: aleksis/core/models.py:1014 msgid "Dashboard widget" msgstr "" -#: aleksis/core/models.py:975 +#: aleksis/core/models.py:1019 msgid "Order" msgstr "" -#: aleksis/core/models.py:976 +#: aleksis/core/models.py:1020 msgid "Part of the default dashboard" msgstr "" -#: aleksis/core/models.py:991 +#: aleksis/core/models.py:1035 msgid "Dashboard widget order" msgstr "" -#: aleksis/core/models.py:992 +#: aleksis/core/models.py:1036 msgid "Dashboard widget orders" msgstr "" -#: aleksis/core/models.py:998 +#: aleksis/core/models.py:1042 msgid "Menu ID" msgstr "" -#: aleksis/core/models.py:1011 +#: aleksis/core/models.py:1055 msgid "Custom menu" msgstr "" -#: aleksis/core/models.py:1012 +#: aleksis/core/models.py:1056 msgid "Custom menus" msgstr "" -#: aleksis/core/models.py:1022 +#: aleksis/core/models.py:1066 msgid "Menu" msgstr "" -#: aleksis/core/models.py:1026 aleksis/core/models.py:1274 +#: aleksis/core/models.py:1070 aleksis/core/models.py:1318 #: aleksis/core/templates/oauth2_provider/application/detail.html:26 msgid "Icon" msgstr "" -#: aleksis/core/models.py:1032 +#: aleksis/core/models.py:1076 msgid "Custom menu item" msgstr "" -#: aleksis/core/models.py:1033 +#: aleksis/core/models.py:1077 msgid "Custom menu items" msgstr "" -#: aleksis/core/models.py:1047 +#: aleksis/core/models.py:1091 msgid "Title of type" msgstr "" -#: aleksis/core/models.py:1054 aleksis/core/templates/core/group/full.html:47 +#: aleksis/core/models.py:1098 aleksis/core/templates/core/group/full.html:47 msgid "Group type" msgstr "" -#: aleksis/core/models.py:1068 +#: aleksis/core/models.py:1112 msgid "Can view system status" msgstr "" -#: aleksis/core/models.py:1069 +#: aleksis/core/models.py:1113 msgid "Can manage data" msgstr "" -#: aleksis/core/models.py:1070 +#: aleksis/core/models.py:1114 msgid "Can impersonate" msgstr "" -#: aleksis/core/models.py:1071 +#: aleksis/core/models.py:1115 msgid "Can use search" msgstr "" -#: aleksis/core/models.py:1072 +#: aleksis/core/models.py:1116 msgid "Can change site preferences" msgstr "" -#: aleksis/core/models.py:1073 +#: aleksis/core/models.py:1117 msgid "Can change person preferences" msgstr "" -#: aleksis/core/models.py:1074 +#: aleksis/core/models.py:1118 msgid "Can change group preferences" msgstr "" -#: aleksis/core/models.py:1075 +#: aleksis/core/models.py:1119 msgid "Can test PDF generation" msgstr "" -#: aleksis/core/models.py:1076 +#: aleksis/core/models.py:1120 msgid "Can invite persons" msgstr "" -#: aleksis/core/models.py:1112 +#: aleksis/core/models.py:1156 msgid "Related data check task" msgstr "" -#: aleksis/core/models.py:1120 +#: aleksis/core/models.py:1164 msgid "Issue solved" msgstr "" -#: aleksis/core/models.py:1121 +#: aleksis/core/models.py:1165 msgid "Notification sent" msgstr "" -#: aleksis/core/models.py:1134 +#: aleksis/core/models.py:1178 msgid "Data check result" msgstr "" -#: aleksis/core/models.py:1135 +#: aleksis/core/models.py:1179 msgid "Data check results" msgstr "" -#: aleksis/core/models.py:1137 +#: aleksis/core/models.py:1181 msgid "Can run data checks" msgstr "" -#: aleksis/core/models.py:1138 +#: aleksis/core/models.py:1182 msgid "Can solve data check problems" msgstr "" -#: aleksis/core/models.py:1145 +#: aleksis/core/models.py:1189 msgid "E-Mail address" msgstr "" -#: aleksis/core/models.py:1177 +#: aleksis/core/models.py:1221 msgid "Owner" msgstr "" -#: aleksis/core/models.py:1181 +#: aleksis/core/models.py:1225 msgid "File expires at" msgstr "" -#: aleksis/core/models.py:1183 +#: aleksis/core/models.py:1227 msgid "Generated HTML file" msgstr "" -#: aleksis/core/models.py:1185 +#: aleksis/core/models.py:1229 msgid "Generated PDF file" msgstr "" -#: aleksis/core/models.py:1192 +#: aleksis/core/models.py:1236 msgid "PDF file" msgstr "" -#: aleksis/core/models.py:1193 +#: aleksis/core/models.py:1237 msgid "PDF files" msgstr "" -#: aleksis/core/models.py:1198 +#: aleksis/core/models.py:1242 msgid "Task result" msgstr "" -#: aleksis/core/models.py:1201 +#: aleksis/core/models.py:1245 msgid "Task user" msgstr "" -#: aleksis/core/models.py:1213 +#: aleksis/core/models.py:1257 msgid "Task user assignment" msgstr "" -#: aleksis/core/models.py:1214 +#: aleksis/core/models.py:1258 msgid "Task user assignments" msgstr "" -#: aleksis/core/models.py:1230 +#: aleksis/core/models.py:1274 msgid "Additional attributes" msgstr "" -#: aleksis/core/models.py:1268 +#: aleksis/core/models.py:1312 msgid "Allowed scopes that clients can request" msgstr "" -#: aleksis/core/models.py:1278 +#: aleksis/core/models.py:1322 msgid "This image will be shown as icon in the authorization flow. It should be squared." msgstr "" @@ -1084,86 +1112,98 @@ msgid "Allow users to change their passwords" msgstr "" #: aleksis/core/preferences.py:279 -msgid "Enable signup" +msgid "Allow users to reset their passwords" msgstr "" #: aleksis/core/preferences.py:287 -msgid "Enable invitations" +msgid "Enable signup" msgstr "" #: aleksis/core/preferences.py:295 -msgid "Length of invite code. (Default 3: abcde-acbde-abcde)" +msgid "Regular expression for allowed usernames" msgstr "" #: aleksis/core/preferences.py:303 +msgid "Enable invitations" +msgstr "" + +#: aleksis/core/preferences.py:311 +msgid "Length of invite code. (Default 3: abcde-acbde-abcde)" +msgstr "" + +#: aleksis/core/preferences.py:319 msgid "Size of packets. (Default 5: abcde)" msgstr "" -#: aleksis/core/preferences.py:314 +#: aleksis/core/preferences.py:330 msgid "Allowed Grant Flows for OAuth applications" msgstr "" -#: aleksis/core/preferences.py:328 +#: aleksis/core/preferences.py:344 msgid "Available languages" msgstr "" -#: aleksis/core/preferences.py:341 +#: aleksis/core/preferences.py:357 msgid "Send emails if data checks detect problems" msgstr "" -#: aleksis/core/preferences.py:352 +#: aleksis/core/preferences.py:368 msgid "Email recipients for data checks problem emails" msgstr "" -#: aleksis/core/preferences.py:363 +#: aleksis/core/preferences.py:379 msgid "Email recipient groups for data checks problem emails" msgstr "" -#: aleksis/core/preferences.py:372 +#: aleksis/core/preferences.py:388 msgid "Show dashboard to users without login" msgstr "" -#: aleksis/core/preferences.py:381 +#: aleksis/core/preferences.py:397 msgid "Allow users to edit their dashboard" msgstr "" -#: aleksis/core/preferences.py:392 +#: aleksis/core/preferences.py:408 msgid "Fields on person model which are editable by themselves." msgstr "" -#: aleksis/core/preferences.py:407 +#: aleksis/core/preferences.py:423 msgid "Editable fields on person model which should trigger a notification on change" msgstr "" -#: aleksis/core/preferences.py:421 +#: aleksis/core/preferences.py:437 msgid "Contact for notification if a person changes their data" msgstr "" -#: aleksis/core/preferences.py:432 +#: aleksis/core/preferences.py:448 +msgid "Prefer personal photos over avatars" +msgstr "" + +#: aleksis/core/preferences.py:458 msgid "PDF file expiration duration" msgstr "" -#: aleksis/core/preferences.py:433 +#: aleksis/core/preferences.py:459 msgid "in minutes" msgstr "" -#: aleksis/core/preferences.py:443 +#: aleksis/core/preferences.py:469 msgid "Automatically update the dashboard and its widgets" msgstr "" -#: aleksis/core/preferences.py:453 +#: aleksis/core/preferences.py:479 msgid "Automatically update the dashboard and its widgets sitewide" msgstr "" -#: aleksis/core/preferences.py:463 +#: aleksis/core/preferences.py:489 msgid "Country for phone number parsing" msgstr "" -#: aleksis/core/settings.py:529 +#: aleksis/core/settings.py:540 msgid "English" msgstr "" -#: aleksis/core/settings.py:530 +#: aleksis/core/settings.py:541 msgid "German" msgstr "" @@ -1171,7 +1211,7 @@ msgstr "" #: aleksis/core/templates/core/announcement/list.html:36 #: aleksis/core/templates/core/group/full.html:24 #: aleksis/core/templates/core/person/full.html:26 -#: aleksis/core/templates/core/person/full.html:98 +#: aleksis/core/templates/core/person/full.html:86 #: aleksis/core/templates/oauth2_provider/application/detail.html:17 msgid "Edit" msgstr "" @@ -1189,7 +1229,7 @@ msgstr "" #: aleksis/core/templates/core/group/full.html:31 #: aleksis/core/templates/core/pages/delete.html:22 #: aleksis/core/templates/core/person/full.html:33 -#: aleksis/core/templates/core/person/full.html:105 +#: aleksis/core/templates/core/person/full.html:93 #: aleksis/core/templates/oauth2_provider/application/detail.html:21 msgid "Delete" msgstr "" @@ -1236,6 +1276,10 @@ msgid "" " " msgstr "" +#: aleksis/core/templates/500.html:21 +msgid "Retry" +msgstr "" + #: aleksis/core/templates/503.html:10 msgid "" "The maintenance mode is currently enabled. Please try again\n" @@ -1494,19 +1538,15 @@ msgstr "" msgid "There are no announcements." msgstr "" -#: aleksis/core/templates/core/base.html:78 -msgid "Logged in as" -msgstr "" - -#: aleksis/core/templates/core/base.html:179 +#: aleksis/core/templates/core/base.html:213 msgid "About AlekSIS® — The Free School Information System" msgstr "" -#: aleksis/core/templates/core/base.html:187 +#: aleksis/core/templates/core/base.html:221 msgid "Imprint" msgstr "" -#: aleksis/core/templates/core/base.html:195 +#: aleksis/core/templates/core/base.html:229 msgid "Privacy Policy" msgstr "" @@ -1727,7 +1767,7 @@ msgstr "" #: aleksis/core/templates/core/group/full.html:38 #: aleksis/core/templates/core/person/full.html:40 -#: aleksis/core/templates/core/person/full.html:112 +#: aleksis/core/templates/core/person/full.html:100 msgid "Change preferences" msgstr "" @@ -1917,83 +1957,83 @@ msgstr "" msgid "System checks" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:21 +#: aleksis/core/templates/core/pages/system_status.html:22 msgid "Maintenance mode enabled" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:23 +#: aleksis/core/templates/core/pages/system_status.html:24 msgid "" "\n" " Only admin and visitors from internal IPs can access thesite.\n" " " msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:34 +#: aleksis/core/templates/core/pages/system_status.html:36 msgid "Maintenance mode disabled" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:35 +#: aleksis/core/templates/core/pages/system_status.html:37 msgid "Everyone can access the site." msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:45 +#: aleksis/core/templates/core/pages/system_status.html:47 msgid "Debug mode enabled" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:47 +#: aleksis/core/templates/core/pages/system_status.html:49 msgid "" "\n" " The web server throws back debug information on errors. Do not use in production!\n" " " msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:54 +#: aleksis/core/templates/core/pages/system_status.html:56 msgid "Debug mode disabled" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:56 +#: aleksis/core/templates/core/pages/system_status.html:58 msgid "" "\n" " Debug mode is disabled. Default error pages are displayed on errors.\n" " " msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:69 +#: aleksis/core/templates/core/pages/system_status.html:71 msgid "System health checks" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:75 +#: aleksis/core/templates/core/pages/system_status.html:77 msgid "Service" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:76 -#: aleksis/core/templates/core/pages/system_status.html:115 +#: aleksis/core/templates/core/pages/system_status.html:78 +#: aleksis/core/templates/core/pages/system_status.html:119 msgid "Status" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:77 +#: aleksis/core/templates/core/pages/system_status.html:79 msgid "Time taken" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:96 +#: aleksis/core/templates/core/pages/system_status.html:100 msgid "seconds" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:107 +#: aleksis/core/templates/core/pages/system_status.html:111 msgid "Celery task results" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:112 +#: aleksis/core/templates/core/pages/system_status.html:116 #: aleksis/core/templates/templated_email/celery_failure.email:9 #: aleksis/core/templates/templated_email/celery_failure.email:28 msgid "Task" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:113 +#: aleksis/core/templates/core/pages/system_status.html:117 msgid "ID" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:114 +#: aleksis/core/templates/core/pages/system_status.html:118 msgid "Date done" msgstr "" @@ -2034,6 +2074,18 @@ msgid "" " " msgstr "" +#: aleksis/core/templates/core/partials/avatar_content.html:14 +#: aleksis/core/templates/core/partials/avatar_content.html:15 +#: aleksis/core/templates/core/person/full.html:213 +#: aleksis/core/templates/core/person/full.html:214 +msgid "Avatar" +msgstr "" + +#: aleksis/core/templates/core/partials/avatar_content.html:19 +#: aleksis/core/templates/core/partials/avatar_content.html:20 +msgid "Identicon" +msgstr "" + #: aleksis/core/templates/core/partials/crud_events.html:15 msgid "Changed by" msgstr "" @@ -2124,24 +2176,24 @@ msgid "Edit person" msgstr "" #: aleksis/core/templates/core/person/full.html:47 -#: aleksis/core/templates/core/person/full.html:119 +#: aleksis/core/templates/core/person/full.html:107 msgid "Impersonate" msgstr "" #: aleksis/core/templates/core/person/full.html:54 -#: aleksis/core/templates/core/person/full.html:126 +#: aleksis/core/templates/core/person/full.html:114 msgid "Invite user" msgstr "" -#: aleksis/core/templates/core/person/full.html:133 +#: aleksis/core/templates/core/person/full.html:121 msgid "Contact details" msgstr "" -#: aleksis/core/templates/core/person/full.html:224 +#: aleksis/core/templates/core/person/full.html:220 msgid "This person didn't upload a personal photo." msgstr "" -#: aleksis/core/templates/core/person/full.html:232 +#: aleksis/core/templates/core/person/full.html:228 msgid "Children" msgstr "" @@ -2346,13 +2398,11 @@ msgstr "" msgid "Network error" msgstr "" -#: aleksis/core/templates/offline.html:8 -msgid "" -"No internet\n" -" connection." +#: aleksis/core/templates/offline.html:10 +msgid "No internet connection." msgstr "" -#: aleksis/core/templates/offline.html:12 +#: aleksis/core/templates/offline.html:14 msgid "" "\n" " There was an error accessing this page. You probably don't have an internet connection. Check to see if your WiFi\n" @@ -2596,7 +2646,7 @@ msgstr "" #: aleksis/core/templates/two_factor/_base_focus.html:6 #: aleksis/core/templates/two_factor/core/otp_required.html:22 #: aleksis/core/templates/two_factor/core/setup.html:5 -#: aleksis/core/templates/two_factor/profile/profile.html:87 +#: aleksis/core/templates/two_factor/profile/profile.html:88 msgid "Enable Two-Factor Authentication" msgstr "" @@ -2700,15 +2750,15 @@ msgstr "" msgid "Or, alternatively, use one of your backup phones:" msgstr "" -#: aleksis/core/templates/two_factor/core/login.html:121 +#: aleksis/core/templates/two_factor/core/login.html:122 msgid "As a last resort, you can use a backup token:" msgstr "" -#: aleksis/core/templates/two_factor/core/login.html:124 +#: aleksis/core/templates/two_factor/core/login.html:125 msgid "Use Backup Token" msgstr "" -#: aleksis/core/templates/two_factor/core/login.html:135 +#: aleksis/core/templates/two_factor/core/login.html:136 msgid "Use alternative login options" msgstr "" @@ -2949,11 +2999,11 @@ msgid "" " " msgstr "" -#: aleksis/core/util/notifications.py:63 +#: aleksis/core/util/notifications.py:64 msgid "E-Mail" msgstr "" -#: aleksis/core/util/notifications.py:64 +#: aleksis/core/util/notifications.py:65 msgid "SMS" msgstr "" @@ -2977,156 +3027,156 @@ msgstr "" msgid "Download PDF" msgstr "" -#: aleksis/core/views.py:285 +#: aleksis/core/views.py:289 msgid "The school term has been created." msgstr "" -#: aleksis/core/views.py:297 +#: aleksis/core/views.py:301 msgid "The school term has been saved." msgstr "" -#: aleksis/core/views.py:417 +#: aleksis/core/views.py:421 msgid "The child groups were successfully saved." msgstr "" -#: aleksis/core/views.py:436 aleksis/core/views.py:446 +#: aleksis/core/views.py:440 aleksis/core/views.py:450 msgid "The person has been saved." msgstr "" -#: aleksis/core/views.py:496 +#: aleksis/core/views.py:500 msgid "The group has been saved." msgstr "" -#: aleksis/core/views.py:593 +#: aleksis/core/views.py:597 msgid "The announcement has been saved." msgstr "" -#: aleksis/core/views.py:609 +#: aleksis/core/views.py:613 msgid "The announcement has been deleted." msgstr "" -#: aleksis/core/views.py:677 +#: aleksis/core/views.py:681 msgid "The requested preference registry does not exist" msgstr "" -#: aleksis/core/views.py:696 +#: aleksis/core/views.py:700 msgid "The preferences have been saved successfully." msgstr "" -#: aleksis/core/views.py:720 +#: aleksis/core/views.py:724 msgid "The person has been deleted." msgstr "" -#: aleksis/core/views.py:734 +#: aleksis/core/views.py:738 msgid "The group has been deleted." msgstr "" -#: aleksis/core/views.py:766 +#: aleksis/core/views.py:770 msgid "The additional_field has been saved." msgstr "" -#: aleksis/core/views.py:800 +#: aleksis/core/views.py:804 msgid "The additional field has been deleted." msgstr "" -#: aleksis/core/views.py:825 +#: aleksis/core/views.py:829 msgid "The group type has been saved." msgstr "" -#: aleksis/core/views.py:855 +#: aleksis/core/views.py:859 msgid "The group type has been deleted." msgstr "" -#: aleksis/core/views.py:888 +#: aleksis/core/views.py:892 msgid "Progress: Run data checks" msgstr "" -#: aleksis/core/views.py:889 +#: aleksis/core/views.py:893 msgid "Run data checks …" msgstr "" -#: aleksis/core/views.py:890 +#: aleksis/core/views.py:894 msgid "The data checks were run successfully." msgstr "" -#: aleksis/core/views.py:891 +#: aleksis/core/views.py:895 msgid "There was a problem while running data checks." msgstr "" -#: aleksis/core/views.py:907 +#: aleksis/core/views.py:911 #, python-brace-format msgid "The solve option '{solve_option_obj.verbose_name}' " msgstr "" -#: aleksis/core/views.py:917 +#: aleksis/core/views.py:921 msgid "The requested solve option does not exist" msgstr "" -#: aleksis/core/views.py:949 +#: aleksis/core/views.py:953 msgid "The dashboard widget has been saved." msgstr "" -#: aleksis/core/views.py:979 +#: aleksis/core/views.py:983 msgid "The dashboard widget has been created." msgstr "" -#: aleksis/core/views.py:989 +#: aleksis/core/views.py:993 msgid "The dashboard widget has been deleted." msgstr "" -#: aleksis/core/views.py:1060 +#: aleksis/core/views.py:1064 msgid "Your dashboard configuration has been saved successfully." msgstr "" -#: aleksis/core/views.py:1062 +#: aleksis/core/views.py:1066 msgid "The configuration of the default dashboard has been saved successfully." msgstr "" -#: aleksis/core/views.py:1138 +#: aleksis/core/views.py:1142 #, python-brace-format msgid "The invitation was successfully created. The invitation code is {code}" msgstr "" -#: aleksis/core/views.py:1229 +#: aleksis/core/views.py:1233 msgid "We have successfully assigned the permissions." msgstr "" -#: aleksis/core/views.py:1239 +#: aleksis/core/views.py:1243 msgid "The global user permission has been deleted." msgstr "" -#: aleksis/core/views.py:1249 +#: aleksis/core/views.py:1253 msgid "The global group permission has been deleted." msgstr "" -#: aleksis/core/views.py:1259 +#: aleksis/core/views.py:1263 msgid "The object user permission has been deleted." msgstr "" -#: aleksis/core/views.py:1269 +#: aleksis/core/views.py:1273 msgid "The object group permission has been deleted." msgstr "" -#: aleksis/core/views.py:1337 +#: aleksis/core/views.py:1341 msgid "The requested PDF file does not exist" msgstr "" -#: aleksis/core/views.py:1346 aleksis/core/views.py:1350 +#: aleksis/core/views.py:1350 aleksis/core/views.py:1354 msgid "The requested task does not exist or is not accessible" msgstr "" -#: aleksis/core/views.py:1388 +#: aleksis/core/views.py:1406 msgid "The third-party account could not be disconnected because it is the only login method available." msgstr "" -#: aleksis/core/views.py:1395 +#: aleksis/core/views.py:1413 msgid "The third-party account has been successfully disconnected." msgstr "" -#: aleksis/core/views.py:1466 +#: aleksis/core/views.py:1484 msgid "Person was invited successfully and an email with further instructions has been send to them." msgstr "" -#: aleksis/core/views.py:1477 +#: aleksis/core/views.py:1495 msgid "Person was already invited." msgstr "" diff --git a/aleksis/core/locale/ar/LC_MESSAGES/djangojs.po b/aleksis/core/locale/ar/LC_MESSAGES/djangojs.po index 8a53fc2fc168227f37f344c17ae359b5d5764596..31b839fb203db1208029422282b10d1fa3e95123 100644 --- a/aleksis/core/locale/ar/LC_MESSAGES/djangojs.po +++ b/aleksis/core/locale/ar/LC_MESSAGES/djangojs.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-02-08 23:16+0000\n" +"POT-Creation-Date: 2022-03-23 11:20+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -30,6 +30,6 @@ msgstr "" msgid "OK" msgstr "" -#: aleksis/core/static/js/main.js:191 +#: aleksis/core/static/js/main.js:195 msgid "This page may contain outdated information since there is no internet connection." msgstr "" diff --git a/aleksis/core/locale/de_DE/LC_MESSAGES/django.po b/aleksis/core/locale/de_DE/LC_MESSAGES/django.po index 56ff3ab652cb345ae714d6b1eb8b54e7ae5f27a2..e39ddc518a4ec11696d1f0cb411139a7615e90c1 100644 --- a/aleksis/core/locale/de_DE/LC_MESSAGES/django.po +++ b/aleksis/core/locale/de_DE/LC_MESSAGES/django.po @@ -7,9 +7,9 @@ msgid "" msgstr "" "Project-Id-Version: AlekSIS (School Information System) 0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-02-08 23:16+0000\n" -"PO-Revision-Date: 2022-02-08 23:24+0000\n" -"Last-Translator: Tom Teichler <tom.teichler@teckids.org>\n" +"POT-Creation-Date: 2022-03-23 11:19+0100\n" +"PO-Revision-Date: 2022-03-23 11:06+0000\n" +"Last-Translator: Jonathan Weth <teckids@jonathanweth.de>\n" "Language-Team: German <https://translate.edugit.org/projects/aleksis/" "aleksis-core/de/>\n" "Language: de_DE\n" @@ -39,10 +39,10 @@ msgstr "E-Mail-Adresse" msgid "Home and mobile phone" msgstr "Festnetz- und Mobilfunknummer" -#: aleksis/core/apps.py:171 aleksis/core/forms.py:220 aleksis/core/menus.py:265 -#: aleksis/core/models.py:462 aleksis/core/templates/core/group/list.html:8 +#: aleksis/core/apps.py:171 aleksis/core/forms.py:220 aleksis/core/menus.py:185 +#: aleksis/core/models.py:487 aleksis/core/templates/core/group/list.html:8 #: aleksis/core/templates/core/group/list.html:9 -#: aleksis/core/templates/core/person/full.html:250 +#: aleksis/core/templates/core/person/full.html:246 msgid "Groups" msgstr "Gruppen" @@ -67,8 +67,8 @@ msgstr "Sicherstellen, dass es keine kaputten Dashboard-Widgets gibt." msgid "The DashboardWidget was reported broken automatically." msgstr "Das Dashboard-Widget wurde automatisch als kaputt gemeldet." -#: aleksis/core/filters.py:42 aleksis/core/templates/core/base.html:105 -#: aleksis/core/templates/core/base.html:106 +#: aleksis/core/filters.py:42 aleksis/core/templates/core/base.html:139 +#: aleksis/core/templates/core/base.html:140 #: aleksis/core/templates/core/group/list.html:20 #: aleksis/core/templates/core/person/list.html:24 #: aleksis/core/templates/search/search.html:7 @@ -92,11 +92,11 @@ msgstr "Berechtigung" msgid "Content type" msgstr "Inhaltstyp" -#: aleksis/core/filters.py:113 aleksis/core/models.py:688 +#: aleksis/core/filters.py:113 aleksis/core/models.py:713 msgid "User" msgstr "Benutzer" -#: aleksis/core/filters.py:135 aleksis/core/models.py:461 +#: aleksis/core/filters.py:135 aleksis/core/models.py:486 msgid "Group" msgstr "Gruppe" @@ -132,7 +132,7 @@ msgstr "Sie können keine neuen Benutzer erstellen, wenn Sie gleichzeitig einen msgid "This username is already in use." msgstr "Dieser Benutzername wird bereits genutzt." -#: aleksis/core/forms.py:153 aleksis/core/models.py:130 +#: aleksis/core/forms.py:153 aleksis/core/models.py:134 msgid "School term" msgstr "Schuljahr" @@ -141,7 +141,7 @@ msgid "Common data" msgstr "Allgemeine Daten" #: aleksis/core/forms.py:155 aleksis/core/forms.py:207 -#: aleksis/core/menus.py:254 aleksis/core/models.py:153 +#: aleksis/core/menus.py:174 aleksis/core/models.py:157 #: aleksis/core/templates/core/person/list.html:8 #: aleksis/core/templates/core/person/list.html:9 msgid "Persons" @@ -151,18 +151,18 @@ msgstr "Personen" msgid "Additional data" msgstr "Zusätzliche Datne" -#: aleksis/core/forms.py:157 aleksis/core/models.py:206 -#: aleksis/core/models.py:514 +#: aleksis/core/forms.py:157 aleksis/core/models.py:210 +#: aleksis/core/models.py:539 msgid "Photo" msgstr "Foto" #: aleksis/core/forms.py:199 aleksis/core/forms.py:202 -#: aleksis/core/models.py:73 +#: aleksis/core/models.py:77 msgid "Date" msgstr "Datum" #: aleksis/core/forms.py:200 aleksis/core/forms.py:203 -#: aleksis/core/models.py:81 +#: aleksis/core/models.py:85 msgid "Time" msgstr "Zeit" @@ -198,11 +198,11 @@ msgstr "Einladungscode" msgid "Please enter your invitation code." msgstr "Bitte geben Sie Ihren Einladungscode ein." -#: aleksis/core/forms.py:418 aleksis/core/models.py:181 +#: aleksis/core/forms.py:418 aleksis/core/models.py:185 msgid "First name" msgstr "Vorname" -#: aleksis/core/forms.py:419 aleksis/core/models.py:182 +#: aleksis/core/forms.py:419 aleksis/core/models.py:186 msgid "Last name" msgstr "Nachname" @@ -250,7 +250,17 @@ msgstr "Passwort" msgid "Password (again)" msgstr "Passwort wiederholen" -#: aleksis/core/forms.py:775 +#: aleksis/core/forms.py:728 +msgid "The selected action does not exist." +msgstr "Die ausgewählte Aktion existiert nicht." + +#: aleksis/core/forms.py:739 +msgid "You do not have permission to run {} on all selected objects." +msgstr "" +"Sie haben nicht die Berechtigung, {} auf alle ausgewählten Objekte " +"auszuführen." + +#: aleksis/core/forms.py:795 msgid "No valid selection." msgstr "Keine gültige Auswahl." @@ -293,678 +303,698 @@ msgstr "Einladung akzeptieren" msgid "Dashboard" msgstr "Dashboard" -#: aleksis/core/menus.py:41 aleksis/core/models.py:734 -#: aleksis/core/preferences.py:29 +#: aleksis/core/menus.py:41 aleksis/core/models.py:765 +#: aleksis/core/preferences.py:29 aleksis/core/templates/core/base.html:81 #: aleksis/core/templates/core/notifications.html:4 #: aleksis/core/templates/core/notifications.html:5 msgid "Notifications" msgstr "Benachrichtigungen" #: aleksis/core/menus.py:53 -msgid "Account" -msgstr "Konto" - -#: aleksis/core/menus.py:60 -msgid "Stop impersonation" -msgstr "Verkleidung beenden" - -#: aleksis/core/menus.py:69 aleksis/core/templates/core/base.html:80 -msgid "Logout" -msgstr "Abmelden" - -#: aleksis/core/menus.py:75 -msgid "2FA" -msgstr "2FA" - -#: aleksis/core/menus.py:83 -#: aleksis/core/templates/account/password_change.html:5 -#: aleksis/core/templates/account/password_change.html:6 -#: aleksis/core/templates/account/password_change.html:19 -#: aleksis/core/templates/account/password_reset_from_key.html:5 -#: aleksis/core/templates/account/password_reset_from_key.html:42 -#: aleksis/core/templates/account/password_reset_from_key.html:46 -#: aleksis/core/templates/account/password_reset_from_key_done.html:5 -#: aleksis/core/templates/account/password_reset_from_key_done.html:6 -msgid "Change password" -msgstr "Passwort ändern" - -#: aleksis/core/menus.py:95 -msgid "Me" -msgstr "Ich" - -#: aleksis/core/menus.py:104 -#: aleksis/core/templates/dynamic_preferences/form.html:5 -msgid "Preferences" -msgstr "Einstellungen" - -#: aleksis/core/menus.py:113 -msgid "Third-party accounts" -msgstr "Drittanbieter-Konten" - -#: aleksis/core/menus.py:122 -#: aleksis/core/templates/oauth2_provider/authorized-tokens.html:5 -#: aleksis/core/templates/oauth2_provider/authorized-tokens.html:6 -msgid "Authorized applications" -msgstr "Autorisierte Anwendungen" - -#: aleksis/core/menus.py:133 msgid "Admin" msgstr "Admin" -#: aleksis/core/menus.py:141 aleksis/core/models.py:834 +#: aleksis/core/menus.py:61 aleksis/core/models.py:865 #: aleksis/core/templates/core/announcement/list.html:7 #: aleksis/core/templates/core/announcement/list.html:8 msgid "Announcements" msgstr "Ankündigungen" -#: aleksis/core/menus.py:152 aleksis/core/models.py:131 +#: aleksis/core/menus.py:72 aleksis/core/models.py:135 #: aleksis/core/templates/core/school_term/list.html:8 #: aleksis/core/templates/core/school_term/list.html:9 msgid "School terms" msgstr "Schuljahre" -#: aleksis/core/menus.py:163 +#: aleksis/core/menus.py:83 #: aleksis/core/templates/core/dashboard_widget/list.html:8 #: aleksis/core/templates/core/dashboard_widget/list.html:9 msgid "Dashboard widgets" msgstr "Dashboard-Widgets" -#: aleksis/core/menus.py:174 +#: aleksis/core/menus.py:94 #: aleksis/core/templates/core/management/data_management.html:6 #: aleksis/core/templates/core/management/data_management.html:7 msgid "Data management" msgstr "Datenverwaltung" -#: aleksis/core/menus.py:185 +#: aleksis/core/menus.py:105 #: aleksis/core/templates/core/pages/system_status.html:5 #: aleksis/core/templates/core/pages/system_status.html:7 msgid "System status" msgstr "Systemstatus" -#: aleksis/core/menus.py:196 +#: aleksis/core/menus.py:116 msgid "Configuration" msgstr "Konfiguration" -#: aleksis/core/menus.py:207 aleksis/core/templates/core/data_check/list.html:9 +#: aleksis/core/menus.py:127 aleksis/core/templates/core/data_check/list.html:9 #: aleksis/core/templates/core/data_check/list.html:10 msgid "Data checks" msgstr "Datenprüfungen" -#: aleksis/core/menus.py:213 aleksis/core/templates/core/perms/list.html:13 +#: aleksis/core/menus.py:133 aleksis/core/templates/core/perms/list.html:13 #: aleksis/core/templates/core/perms/list.html:14 msgid "Manage permissions" msgstr "Berechtigungen verwalten" -#: aleksis/core/menus.py:224 +#: aleksis/core/menus.py:144 msgid "Backend Admin" msgstr "Backend-Administration" -#: aleksis/core/menus.py:232 +#: aleksis/core/menus.py:152 #: aleksis/core/templates/oauth2_provider/application/list.html:5 #: aleksis/core/templates/oauth2_provider/application/list.html:6 msgid "OAuth2 Applications" msgstr "OAuth2-Anwendungen" -#: aleksis/core/menus.py:245 +#: aleksis/core/menus.py:165 msgid "People" msgstr "Leute" -#: aleksis/core/menus.py:276 aleksis/core/models.py:1055 +#: aleksis/core/menus.py:196 aleksis/core/models.py:1099 #: aleksis/core/templates/core/group_type/list.html:8 #: aleksis/core/templates/core/group_type/list.html:9 msgid "Group types" msgstr "Gruppentypen" -#: aleksis/core/menus.py:287 +#: aleksis/core/menus.py:207 msgid "Groups and child groups" msgstr "Gruppen und Kindgruppen" -#: aleksis/core/menus.py:298 aleksis/core/models.py:510 +#: aleksis/core/menus.py:218 aleksis/core/models.py:535 #: aleksis/core/templates/core/additional_field/list.html:8 #: aleksis/core/templates/core/additional_field/list.html:9 msgid "Additional fields" msgstr "Zusätzliche Felder" -#: aleksis/core/menus.py:309 +#: aleksis/core/menus.py:229 msgid "Invite person" msgstr "Person einladen" -#: aleksis/core/menus.py:322 +#: aleksis/core/menus.py:242 #: aleksis/core/templates/core/group/child_groups.html:7 #: aleksis/core/templates/core/group/child_groups.html:9 msgid "Assign child groups to groups" msgstr "Kindgruppen zu Gruppen zuordnen" +#: aleksis/core/menus.py:254 +msgid "Stop impersonation" +msgstr "Verkleidung beenden" + +#: aleksis/core/menus.py:263 +msgid "Account" +msgstr "Konto" + +#: aleksis/core/menus.py:272 +#: aleksis/core/templates/dynamic_preferences/form.html:5 +msgid "Preferences" +msgstr "Einstellungen" + +#: aleksis/core/menus.py:281 +msgid "2FA" +msgstr "2FA" + +#: aleksis/core/menus.py:289 +#: aleksis/core/templates/account/password_change.html:5 +#: aleksis/core/templates/account/password_change.html:6 +#: aleksis/core/templates/account/password_change.html:19 +#: aleksis/core/templates/account/password_reset_from_key.html:5 +#: aleksis/core/templates/account/password_reset_from_key.html:42 +#: aleksis/core/templates/account/password_reset_from_key.html:46 +#: aleksis/core/templates/account/password_reset_from_key_done.html:5 +#: aleksis/core/templates/account/password_reset_from_key_done.html:6 +msgid "Change password" +msgstr "Passwort ändern" + +#: aleksis/core/menus.py:301 +msgid "Third-party accounts" +msgstr "Drittanbieter-Konten" + +#: aleksis/core/menus.py:310 +#: aleksis/core/templates/oauth2_provider/authorized-tokens.html:5 +#: aleksis/core/templates/oauth2_provider/authorized-tokens.html:6 +msgid "Authorized applications" +msgstr "Autorisierte Anwendungen" + +#: aleksis/core/menus.py:320 +msgid "Logout" +msgstr "Abmelden" + #: aleksis/core/mixins.py:511 msgid "Linked school term" msgstr "Zugeordnetes Schuljahr" -#: aleksis/core/models.py:71 +#: aleksis/core/models.py:75 msgid "Boolean (Yes/No)" msgstr "Boolean (Ja/Nein)" -#: aleksis/core/models.py:72 +#: aleksis/core/models.py:76 msgid "Text (one line)" msgstr "Text (eine Zeile)" -#: aleksis/core/models.py:74 +#: aleksis/core/models.py:78 msgid "Date and time" msgstr "Datum und Uhrzeit" -#: aleksis/core/models.py:75 +#: aleksis/core/models.py:79 msgid "Decimal number" msgstr "Dezimalzahl" -#: aleksis/core/models.py:76 aleksis/core/models.py:199 +#: aleksis/core/models.py:80 aleksis/core/models.py:203 msgid "E-mail address" msgstr "E-Mail-Adresse" -#: aleksis/core/models.py:77 +#: aleksis/core/models.py:81 msgid "Integer" msgstr "Ganze Zahl" -#: aleksis/core/models.py:78 +#: aleksis/core/models.py:82 msgid "IP address" msgstr "IP-Adresse" -#: aleksis/core/models.py:79 +#: aleksis/core/models.py:83 msgid "Boolean or empty (Yes/No/Neither)" msgstr "Boolean oder leer (Ja/Nein/weder)" -#: aleksis/core/models.py:80 +#: aleksis/core/models.py:84 msgid "Text (multi-line)" msgstr "Text (mehrzeilig)" -#: aleksis/core/models.py:82 +#: aleksis/core/models.py:86 msgid "URL / Link" msgstr "URL / Link" -#: aleksis/core/models.py:94 aleksis/core/models.py:1024 +#: aleksis/core/models.py:98 aleksis/core/models.py:1068 msgid "Name" msgstr "Name" -#: aleksis/core/models.py:96 +#: aleksis/core/models.py:100 msgid "Start date" msgstr "Startdatum" -#: aleksis/core/models.py:97 +#: aleksis/core/models.py:101 msgid "End date" msgstr "Enddatum" -#: aleksis/core/models.py:116 +#: aleksis/core/models.py:120 msgid "The start date must be earlier than the end date." msgstr "Das Startdatum muss vor dem Enddatum liegen." -#: aleksis/core/models.py:123 +#: aleksis/core/models.py:127 msgid "There is already a school term for this time or a part of this time." msgstr "Es gibt bereits ein Schuljahr für diesen Zeitraum oder einen Teilzeitraum." -#: aleksis/core/models.py:152 aleksis/core/models.py:973 +#: aleksis/core/models.py:156 aleksis/core/models.py:1017 msgid "Person" msgstr "Person" -#: aleksis/core/models.py:155 +#: aleksis/core/models.py:159 msgid "Can view address" msgstr "Kann Adresse sehen" -#: aleksis/core/models.py:156 +#: aleksis/core/models.py:160 msgid "Can view contact details" msgstr "Kann Kontaktdetails sehen" -#: aleksis/core/models.py:157 +#: aleksis/core/models.py:161 msgid "Can view photo" msgstr "Kann Foto sehen" -#: aleksis/core/models.py:158 +#: aleksis/core/models.py:162 msgid "Can view avatar image" msgstr "Kann Avatar-Bild sehen" -#: aleksis/core/models.py:159 +#: aleksis/core/models.py:163 msgid "Can view persons groups" msgstr "Kann Gruppen einer Person sehen" -#: aleksis/core/models.py:160 +#: aleksis/core/models.py:164 msgid "Can view personal details" msgstr "Kann persönliche Daten sehen" -#: aleksis/core/models.py:170 +#: aleksis/core/models.py:174 msgid "female" msgstr "weiblich" -#: aleksis/core/models.py:170 +#: aleksis/core/models.py:174 msgid "male" msgstr "männlich" -#: aleksis/core/models.py:178 aleksis/core/models.py:1227 +#: aleksis/core/models.py:182 aleksis/core/models.py:1271 msgid "Linked user" msgstr "Verknüpfter Benutzer" -#: aleksis/core/models.py:184 +#: aleksis/core/models.py:188 msgid "Additional name(s)" msgstr "Zusätzliche Namen" -#: aleksis/core/models.py:188 aleksis/core/models.py:479 +#: aleksis/core/models.py:192 aleksis/core/models.py:504 msgid "Short name" msgstr "Kurzname" -#: aleksis/core/models.py:191 +#: aleksis/core/models.py:195 msgid "Street" msgstr "Straße" -#: aleksis/core/models.py:192 +#: aleksis/core/models.py:196 msgid "Street number" msgstr "Hausnummer" -#: aleksis/core/models.py:193 +#: aleksis/core/models.py:197 msgid "Postal code" msgstr "Postleitzahl" -#: aleksis/core/models.py:194 +#: aleksis/core/models.py:198 msgid "Place" msgstr "Ort" -#: aleksis/core/models.py:196 aleksis/core/templates/core/person/full.html:172 +#: aleksis/core/models.py:200 aleksis/core/templates/core/person/full.html:160 msgid "Home phone" msgstr "Festnetz" -#: aleksis/core/models.py:197 aleksis/core/templates/core/person/full.html:182 +#: aleksis/core/models.py:201 aleksis/core/templates/core/person/full.html:170 msgid "Mobile phone" msgstr "Handy" -#: aleksis/core/models.py:201 +#: aleksis/core/models.py:205 msgid "Date of birth" msgstr "Geburtsdatum" -#: aleksis/core/models.py:202 +#: aleksis/core/models.py:206 msgid "Place of birth" msgstr "Geburtsort" -#: aleksis/core/models.py:203 +#: aleksis/core/models.py:207 msgid "Sex" msgstr "Geschlecht" -#: aleksis/core/models.py:210 aleksis/core/models.py:518 +#: aleksis/core/models.py:214 aleksis/core/models.py:543 msgid "This is an official photo, used for official documents and for internal use cases." msgstr "Dies ist ein offizielles Foto, genutzt für offizielle Dokumente und interne Zwecke." -#: aleksis/core/models.py:215 aleksis/core/models.py:522 +#: aleksis/core/models.py:219 aleksis/core/models.py:547 msgid "Display picture / Avatar" msgstr "Bild/Avatar anzeigen" -#: aleksis/core/models.py:218 aleksis/core/models.py:525 +#: aleksis/core/models.py:222 aleksis/core/models.py:550 msgid "This is a picture or an avatar for public display." msgstr "Dies ist ein Bild oder ein Avatar für die öffentliche Darstellung." -#: aleksis/core/models.py:223 aleksis/core/templates/core/person/full.html:239 +#: aleksis/core/models.py:227 aleksis/core/templates/core/person/full.html:235 msgid "Guardians / Parents" msgstr "Erziehungsberechtigte / Eltern" -#: aleksis/core/models.py:230 +#: aleksis/core/models.py:234 msgid "Primary group" msgstr "Primärgruppe" -#: aleksis/core/models.py:233 aleksis/core/models.py:692 -#: aleksis/core/models.py:716 aleksis/core/models.py:801 -#: aleksis/core/models.py:1048 +#: aleksis/core/models.py:237 aleksis/core/models.py:717 +#: aleksis/core/models.py:741 aleksis/core/models.py:832 +#: aleksis/core/models.py:1092 msgid "Description" msgstr "Beschreibung" -#: aleksis/core/models.py:434 +#: aleksis/core/models.py:457 msgid "Title of field" msgstr "Feldtitel" -#: aleksis/core/models.py:436 +#: aleksis/core/models.py:459 msgid "Type of field" msgstr "Feldtyp" -#: aleksis/core/models.py:443 +#: aleksis/core/models.py:461 +msgid "Required" +msgstr "Pflichtfeld" + +#: aleksis/core/models.py:462 +msgid "Help text / description" +msgstr "Hilfetext/Beschreibung" + +#: aleksis/core/models.py:468 msgid "Addtitional field for groups" msgstr "Zusätzliche Felder für Gruppen" -#: aleksis/core/models.py:444 +#: aleksis/core/models.py:469 msgid "Addtitional fields for groups" msgstr "Zusätzliche Felder für Gruppen" -#: aleksis/core/models.py:464 +#: aleksis/core/models.py:489 msgid "Can assign child groups to groups" msgstr "Kann Kindgruppen zu Gruppen zuordnen" -#: aleksis/core/models.py:465 +#: aleksis/core/models.py:490 msgid "Can view statistics about group." msgstr "Kann Statistiken über Gruppen sehen." -#: aleksis/core/models.py:477 +#: aleksis/core/models.py:502 msgid "Long name" msgstr "Langname" -#: aleksis/core/models.py:487 aleksis/core/templates/core/group/full.html:85 +#: aleksis/core/models.py:512 aleksis/core/templates/core/group/full.html:85 msgid "Members" msgstr "Mitglieder" -#: aleksis/core/models.py:490 aleksis/core/templates/core/group/full.html:82 +#: aleksis/core/models.py:515 aleksis/core/templates/core/group/full.html:82 msgid "Owners" msgstr "Leiter/-innen" -#: aleksis/core/models.py:497 aleksis/core/templates/core/group/full.html:55 +#: aleksis/core/models.py:522 aleksis/core/templates/core/group/full.html:55 msgid "Parent groups" msgstr "Übergeordnete Gruppen" -#: aleksis/core/models.py:505 +#: aleksis/core/models.py:530 msgid "Type of group" msgstr "Gruppentyp" -#: aleksis/core/models.py:691 aleksis/core/models.py:715 -#: aleksis/core/models.py:800 +#: aleksis/core/models.py:716 aleksis/core/models.py:740 +#: aleksis/core/models.py:831 #: aleksis/core/templates/core/announcement/list.html:18 msgid "Title" msgstr "Titel" -#: aleksis/core/models.py:694 +#: aleksis/core/models.py:719 msgid "Application" msgstr "Anwendung" -#: aleksis/core/models.py:700 +#: aleksis/core/models.py:725 msgid "Activity" msgstr "Aktivität" -#: aleksis/core/models.py:701 +#: aleksis/core/models.py:726 msgid "Activities" msgstr "Aktivitäten" -#: aleksis/core/models.py:707 +#: aleksis/core/models.py:732 msgid "Sender" msgstr "Absender" -#: aleksis/core/models.py:712 +#: aleksis/core/models.py:737 msgid "Recipient" msgstr "Empfänger" -#: aleksis/core/models.py:717 aleksis/core/models.py:1025 +#: aleksis/core/models.py:742 aleksis/core/models.py:1069 msgid "Link" msgstr "Link" -#: aleksis/core/models.py:719 +#: aleksis/core/models.py:744 +msgid "Send notification at" +msgstr "Benachrichtigung schicken am" + +#: aleksis/core/models.py:746 msgid "Read" msgstr "Gelesen" -#: aleksis/core/models.py:720 +#: aleksis/core/models.py:747 msgid "Sent" msgstr "Versandt" -#: aleksis/core/models.py:733 +#: aleksis/core/models.py:764 msgid "Notification" msgstr "Benachrichtigung" -#: aleksis/core/models.py:802 +#: aleksis/core/models.py:833 msgid "Link to detailed view" msgstr "Link zur detaillierten Ansicht" -#: aleksis/core/models.py:805 +#: aleksis/core/models.py:836 msgid "Date and time from when to show" msgstr "Datum und Uhrzeit des Anzeigestarts" -#: aleksis/core/models.py:808 +#: aleksis/core/models.py:839 msgid "Date and time until when to show" msgstr "Anzeigezeitraum" -#: aleksis/core/models.py:833 +#: aleksis/core/models.py:864 msgid "Announcement" msgstr "Ankündigung" -#: aleksis/core/models.py:871 +#: aleksis/core/models.py:902 msgid "Announcement recipient" msgstr "Empfänger der Ankündigung" -#: aleksis/core/models.py:872 +#: aleksis/core/models.py:903 msgid "Announcement recipients" msgstr "Empfänger der Ankündigung" -#: aleksis/core/models.py:894 +#: aleksis/core/models.py:925 msgid "Widget Title" msgstr "Widget-Titel" -#: aleksis/core/models.py:895 +#: aleksis/core/models.py:926 msgid "Activate Widget" msgstr "Widget aktivieren" -#: aleksis/core/models.py:896 +#: aleksis/core/models.py:927 msgid "Widget is broken" msgstr "Widget ist kaputt" -#: aleksis/core/models.py:899 +#: aleksis/core/models.py:930 msgid "Size on mobile devices" msgstr "Größe auf Mobilgeräten" -#: aleksis/core/models.py:900 +#: aleksis/core/models.py:931 msgid "<= 600 px, 12 columns" msgstr "<= 600 px, 12 Spalten" -#: aleksis/core/models.py:905 +#: aleksis/core/models.py:936 msgid "Size on tablet devices" msgstr "Größe auf Tablets" -#: aleksis/core/models.py:906 +#: aleksis/core/models.py:937 msgid "> 600 px, 12 columns" msgstr "> 600px, 12 Spalten" -#: aleksis/core/models.py:911 +#: aleksis/core/models.py:942 msgid "Size on desktop devices" msgstr "Größe auf Desktopgeräten" -#: aleksis/core/models.py:912 +#: aleksis/core/models.py:943 msgid "> 992 px, 12 columns" msgstr "> 992 px, 12 Spalten" -#: aleksis/core/models.py:917 +#: aleksis/core/models.py:948 msgid "Size on large desktop devices" msgstr "Größe auf großen Desktopgeräten" -#: aleksis/core/models.py:918 +#: aleksis/core/models.py:949 msgid "> 1200 px>, 12 columns" msgstr "> 1200 px, 12 Spalten" -#: aleksis/core/models.py:949 +#: aleksis/core/models.py:980 msgid "Can edit default dashboard" msgstr "Kann Standarddashboard bearbeiten" -#: aleksis/core/models.py:950 +#: aleksis/core/models.py:981 msgid "Dashboard Widget" msgstr "Dashboard-Widget" -#: aleksis/core/models.py:951 +#: aleksis/core/models.py:982 msgid "Dashboard Widgets" msgstr "Dashboard-Widgets" -#: aleksis/core/models.py:957 +#: aleksis/core/models.py:988 msgid "URL" msgstr "URL" -#: aleksis/core/models.py:958 +#: aleksis/core/models.py:989 msgid "Icon URL" msgstr "Symbol-URL" -#: aleksis/core/models.py:964 +#: aleksis/core/models.py:995 msgid "External link widget" msgstr "Externer-Link-Widget" -#: aleksis/core/models.py:965 +#: aleksis/core/models.py:996 msgid "External link widgets" msgstr "Externer-Link-Widgets" -#: aleksis/core/models.py:970 +#: aleksis/core/models.py:1002 +msgid "Content" +msgstr "Inhalt" + +#: aleksis/core/models.py:1008 +msgid "Static content widget" +msgstr "Statischer-Inhalt-Widget" + +#: aleksis/core/models.py:1009 +msgid "Static content widgets" +msgstr "Statischer-Inhalt-Widgets" + +#: aleksis/core/models.py:1014 msgid "Dashboard widget" msgstr "Dashboard-Widget" -#: aleksis/core/models.py:975 +#: aleksis/core/models.py:1019 msgid "Order" msgstr "Reihenfolge" -#: aleksis/core/models.py:976 +#: aleksis/core/models.py:1020 msgid "Part of the default dashboard" msgstr "Teil des Standarddashboards" -#: aleksis/core/models.py:991 +#: aleksis/core/models.py:1035 msgid "Dashboard widget order" msgstr "Reihenfolge der Dashboard-Widgets" -#: aleksis/core/models.py:992 +#: aleksis/core/models.py:1036 msgid "Dashboard widget orders" msgstr "Reihenfolgen der Dashboard-Widgets" -#: aleksis/core/models.py:998 +#: aleksis/core/models.py:1042 msgid "Menu ID" msgstr "Menü-ID" -#: aleksis/core/models.py:1011 +#: aleksis/core/models.py:1055 msgid "Custom menu" msgstr "Benutzerdefiniertes Menü" -#: aleksis/core/models.py:1012 +#: aleksis/core/models.py:1056 msgid "Custom menus" msgstr "Benutzerdefinierte Menüs" -#: aleksis/core/models.py:1022 +#: aleksis/core/models.py:1066 msgid "Menu" msgstr "Menü" -#: aleksis/core/models.py:1026 aleksis/core/models.py:1274 +#: aleksis/core/models.py:1070 aleksis/core/models.py:1318 #: aleksis/core/templates/oauth2_provider/application/detail.html:26 msgid "Icon" msgstr "Symbol" -#: aleksis/core/models.py:1032 +#: aleksis/core/models.py:1076 msgid "Custom menu item" msgstr "Benutzerdefiniertes Menüelement" -#: aleksis/core/models.py:1033 +#: aleksis/core/models.py:1077 msgid "Custom menu items" msgstr "Benutzerdefinierte Menüelemente" -#: aleksis/core/models.py:1047 +#: aleksis/core/models.py:1091 msgid "Title of type" msgstr "Titel des Typs" -#: aleksis/core/models.py:1054 aleksis/core/templates/core/group/full.html:47 +#: aleksis/core/models.py:1098 aleksis/core/templates/core/group/full.html:47 msgid "Group type" msgstr "Gruppentyp" -#: aleksis/core/models.py:1068 +#: aleksis/core/models.py:1112 msgid "Can view system status" msgstr "Kann Systemstatus sehen" -#: aleksis/core/models.py:1069 +#: aleksis/core/models.py:1113 msgid "Can manage data" msgstr "Kann Daten verwalten" -#: aleksis/core/models.py:1070 +#: aleksis/core/models.py:1114 msgid "Can impersonate" msgstr "Kann sich verkleiden" -#: aleksis/core/models.py:1071 +#: aleksis/core/models.py:1115 msgid "Can use search" msgstr "Kann Suche benutzen" -#: aleksis/core/models.py:1072 +#: aleksis/core/models.py:1116 msgid "Can change site preferences" msgstr "Kann Konfiguration ändern" -#: aleksis/core/models.py:1073 +#: aleksis/core/models.py:1117 msgid "Can change person preferences" msgstr "Kann Einstellungen einer Person verändern" -#: aleksis/core/models.py:1074 +#: aleksis/core/models.py:1118 msgid "Can change group preferences" msgstr "Kann Einstellungen einer Gruppe verändern" -#: aleksis/core/models.py:1075 +#: aleksis/core/models.py:1119 msgid "Can test PDF generation" msgstr "Kann die PDF-Generierung testen" -#: aleksis/core/models.py:1076 +#: aleksis/core/models.py:1120 msgid "Can invite persons" msgstr "Kann Personen einladen" -#: aleksis/core/models.py:1112 +#: aleksis/core/models.py:1156 msgid "Related data check task" msgstr "Zugehörige Datenprüfungsaufgabe" -#: aleksis/core/models.py:1120 +#: aleksis/core/models.py:1164 msgid "Issue solved" msgstr "Problem gelöst" -#: aleksis/core/models.py:1121 +#: aleksis/core/models.py:1165 msgid "Notification sent" msgstr "Benachrichtigung gesendet" -#: aleksis/core/models.py:1134 +#: aleksis/core/models.py:1178 msgid "Data check result" msgstr "Datenprüfungsergebnis" -#: aleksis/core/models.py:1135 +#: aleksis/core/models.py:1179 msgid "Data check results" msgstr "Datenprüfungsergebnisse" -#: aleksis/core/models.py:1137 +#: aleksis/core/models.py:1181 msgid "Can run data checks" msgstr "Kann Datenprüfungen ausführen" -#: aleksis/core/models.py:1138 +#: aleksis/core/models.py:1182 msgid "Can solve data check problems" msgstr "Kann Datenprüfungsprobleme lösen" -#: aleksis/core/models.py:1145 +#: aleksis/core/models.py:1189 msgid "E-Mail address" msgstr "E-Mail-Adresse" -#: aleksis/core/models.py:1177 +#: aleksis/core/models.py:1221 msgid "Owner" msgstr "Leiter" -#: aleksis/core/models.py:1181 +#: aleksis/core/models.py:1225 msgid "File expires at" msgstr "Datei abgelaufen am" -#: aleksis/core/models.py:1183 +#: aleksis/core/models.py:1227 msgid "Generated HTML file" msgstr "Generierte HTML-Datei" -#: aleksis/core/models.py:1185 +#: aleksis/core/models.py:1229 msgid "Generated PDF file" msgstr "Generierte PDF-Datei" -#: aleksis/core/models.py:1192 +#: aleksis/core/models.py:1236 msgid "PDF file" msgstr "PDF-Datei" -#: aleksis/core/models.py:1193 +#: aleksis/core/models.py:1237 msgid "PDF files" msgstr "PDF-Dateien" -#: aleksis/core/models.py:1198 +#: aleksis/core/models.py:1242 msgid "Task result" msgstr "Task-Ergebnis" -#: aleksis/core/models.py:1201 +#: aleksis/core/models.py:1245 msgid "Task user" msgstr "Task-Benutzer" -#: aleksis/core/models.py:1213 +#: aleksis/core/models.py:1257 msgid "Task user assignment" msgstr "Task-Benutzer-Zuordnung" -#: aleksis/core/models.py:1214 +#: aleksis/core/models.py:1258 msgid "Task user assignments" msgstr "Task-Benutzer-Zuordnungen" -#: aleksis/core/models.py:1230 +#: aleksis/core/models.py:1274 msgid "Additional attributes" msgstr "Zusätzliche Attribute" -#: aleksis/core/models.py:1268 +#: aleksis/core/models.py:1312 msgid "Allowed scopes that clients can request" msgstr "Erlaubte Scopes, die ein Client anfordern kann" -#: aleksis/core/models.py:1278 +#: aleksis/core/models.py:1322 msgid "This image will be shown as icon in the authorization flow. It should be squared." msgstr "Dieses Bild wird im Autorisierungs-Vorgang als Symbol angezeigt werden. Es sollte rechteckig sein." @@ -1085,86 +1115,98 @@ msgid "Allow users to change their passwords" msgstr "Erlaube Benutzern, ihr Passwort zu ändern" #: aleksis/core/preferences.py:279 +msgid "Allow users to reset their passwords" +msgstr "Erlaube Benutzern, ihr Passwort zurückzusetzen" + +#: aleksis/core/preferences.py:287 msgid "Enable signup" msgstr "Registrierung aktivieren" -#: aleksis/core/preferences.py:287 +#: aleksis/core/preferences.py:295 +msgid "Regular expression for allowed usernames" +msgstr "Regulärer Ausdruck für erlaubte Benutzernamen" + +#: aleksis/core/preferences.py:303 msgid "Enable invitations" msgstr "Einladungen aktivieren" -#: aleksis/core/preferences.py:295 +#: aleksis/core/preferences.py:311 msgid "Length of invite code. (Default 3: abcde-acbde-abcde)" msgstr "Länge des Einladungscodes. (Standard: 3: abcde-acbde-abcde)" -#: aleksis/core/preferences.py:303 +#: aleksis/core/preferences.py:319 msgid "Size of packets. (Default 5: abcde)" msgstr "Größe der Pakete. (Standard 5: abcde)" -#: aleksis/core/preferences.py:314 +#: aleksis/core/preferences.py:330 msgid "Allowed Grant Flows for OAuth applications" msgstr "Erlaubte Grant Flows für OAuth-Anwendungen" -#: aleksis/core/preferences.py:328 +#: aleksis/core/preferences.py:344 msgid "Available languages" msgstr "Verfügbare Sprachen" -#: aleksis/core/preferences.py:341 +#: aleksis/core/preferences.py:357 msgid "Send emails if data checks detect problems" msgstr "E-Mails versenden, wenn Datenprüfungen Probleme finden" -#: aleksis/core/preferences.py:352 +#: aleksis/core/preferences.py:368 msgid "Email recipients for data checks problem emails" msgstr "E-Mailempfänger für Datenprüfungsproblem-E-Mails" -#: aleksis/core/preferences.py:363 +#: aleksis/core/preferences.py:379 msgid "Email recipient groups for data checks problem emails" msgstr "E-Mail-Empfängergruppen für Datenprüfungsproblem-E-Mails" -#: aleksis/core/preferences.py:372 +#: aleksis/core/preferences.py:388 msgid "Show dashboard to users without login" msgstr "Zeige Dashboard für Benutzer ohne Login" -#: aleksis/core/preferences.py:381 +#: aleksis/core/preferences.py:397 msgid "Allow users to edit their dashboard" msgstr "Erlaube Benutzern, ihr Dashboard zu bearbeiten" -#: aleksis/core/preferences.py:392 +#: aleksis/core/preferences.py:408 msgid "Fields on person model which are editable by themselves." msgstr "Felder des Personen-Models welche von ihnen selbst editierbar sind." -#: aleksis/core/preferences.py:407 +#: aleksis/core/preferences.py:423 msgid "Editable fields on person model which should trigger a notification on change" msgstr "Editierbare Felder des Personen-Models welche eine Benachrichtigung für Änderungen auslösen soll" -#: aleksis/core/preferences.py:421 +#: aleksis/core/preferences.py:437 msgid "Contact for notification if a person changes their data" msgstr "Kontakt für Benachrichtigung, wenn eine Person ihre Daten ändert" -#: aleksis/core/preferences.py:432 +#: aleksis/core/preferences.py:448 +msgid "Prefer personal photos over avatars" +msgstr "Persönliche Fotos Avataren vorziehen" + +#: aleksis/core/preferences.py:458 msgid "PDF file expiration duration" msgstr "PDF-Datei-Ablaufdauer" -#: aleksis/core/preferences.py:433 +#: aleksis/core/preferences.py:459 msgid "in minutes" msgstr "in Minuten" -#: aleksis/core/preferences.py:443 +#: aleksis/core/preferences.py:469 msgid "Automatically update the dashboard and its widgets" msgstr "Automatisch das Dashboard und seine Widgets aktualisieren" -#: aleksis/core/preferences.py:453 +#: aleksis/core/preferences.py:479 msgid "Automatically update the dashboard and its widgets sitewide" msgstr "Automatisch das Dashboard und seine Widgets aktualisieren (auf der ganzen Seite)" -#: aleksis/core/preferences.py:463 +#: aleksis/core/preferences.py:489 msgid "Country for phone number parsing" msgstr "Land für das Einlesen von Telefonnummern" -#: aleksis/core/settings.py:529 +#: aleksis/core/settings.py:540 msgid "English" msgstr "Englisch" -#: aleksis/core/settings.py:530 +#: aleksis/core/settings.py:541 msgid "German" msgstr "Deutsch" @@ -1172,7 +1214,7 @@ msgstr "Deutsch" #: aleksis/core/templates/core/announcement/list.html:36 #: aleksis/core/templates/core/group/full.html:24 #: aleksis/core/templates/core/person/full.html:26 -#: aleksis/core/templates/core/person/full.html:98 +#: aleksis/core/templates/core/person/full.html:86 #: aleksis/core/templates/oauth2_provider/application/detail.html:17 msgid "Edit" msgstr "Bearbeiten" @@ -1190,7 +1232,7 @@ msgstr "Aktionen" #: aleksis/core/templates/core/group/full.html:31 #: aleksis/core/templates/core/pages/delete.html:22 #: aleksis/core/templates/core/person/full.html:33 -#: aleksis/core/templates/core/person/full.html:105 +#: aleksis/core/templates/core/person/full.html:93 #: aleksis/core/templates/oauth2_provider/application/detail.html:21 msgid "Delete" msgstr "Löschen" @@ -1253,6 +1295,10 @@ msgstr "" " Sie können diese auch direkt kontaktieren:\n" " " +#: aleksis/core/templates/500.html:21 +msgid "Retry" +msgstr "Wiederholen" + #: aleksis/core/templates/503.html:10 msgid "" "The maintenance mode is currently enabled. Please try again\n" @@ -1553,19 +1599,15 @@ msgstr "Empfänger" msgid "There are no announcements." msgstr "Es gibt aktuell keine Ankündigungen." -#: aleksis/core/templates/core/base.html:78 -msgid "Logged in as" -msgstr "Angemeldet als" - -#: aleksis/core/templates/core/base.html:179 +#: aleksis/core/templates/core/base.html:213 msgid "About AlekSIS® — The Free School Information System" msgstr "Über AlekSIS® — The Free School Information System" -#: aleksis/core/templates/core/base.html:187 +#: aleksis/core/templates/core/base.html:221 msgid "Imprint" msgstr "Impressum" -#: aleksis/core/templates/core/base.html:195 +#: aleksis/core/templates/core/base.html:229 msgid "Privacy Policy" msgstr "Datenschutzerklärung" @@ -1817,7 +1859,7 @@ msgstr "Gruppe editieren" #: aleksis/core/templates/core/group/full.html:38 #: aleksis/core/templates/core/person/full.html:40 -#: aleksis/core/templates/core/person/full.html:112 +#: aleksis/core/templates/core/person/full.html:100 msgid "Change preferences" msgstr "Einstellungen ändern" @@ -2033,11 +2075,11 @@ msgstr "Zurück" msgid "System checks" msgstr "Systemprüfungen" -#: aleksis/core/templates/core/pages/system_status.html:21 +#: aleksis/core/templates/core/pages/system_status.html:22 msgid "Maintenance mode enabled" msgstr "Wartungsmodus aktiviert" -#: aleksis/core/templates/core/pages/system_status.html:23 +#: aleksis/core/templates/core/pages/system_status.html:24 msgid "" "\n" " Only admin and visitors from internal IPs can access thesite.\n" @@ -2047,19 +2089,19 @@ msgstr "" " Nur Administratoren und Besucher von internen IP-Adressen können die Seite aufrufen.\n" " " -#: aleksis/core/templates/core/pages/system_status.html:34 +#: aleksis/core/templates/core/pages/system_status.html:36 msgid "Maintenance mode disabled" msgstr "Wartungsmodus deaktiviert" -#: aleksis/core/templates/core/pages/system_status.html:35 +#: aleksis/core/templates/core/pages/system_status.html:37 msgid "Everyone can access the site." msgstr "Jeder kann die Seite aufrufen." -#: aleksis/core/templates/core/pages/system_status.html:45 +#: aleksis/core/templates/core/pages/system_status.html:47 msgid "Debug mode enabled" msgstr "Debug-Modus aktiviert" -#: aleksis/core/templates/core/pages/system_status.html:47 +#: aleksis/core/templates/core/pages/system_status.html:49 msgid "" "\n" " The web server throws back debug information on errors. Do not use in production!\n" @@ -2069,11 +2111,11 @@ msgstr "" " Der Server gibt Debug-Informationen bei Fehlern zurück. Nicht im Produktivbetrieb nutzen!\n" " " -#: aleksis/core/templates/core/pages/system_status.html:54 +#: aleksis/core/templates/core/pages/system_status.html:56 msgid "Debug mode disabled" msgstr "Debug-Modus deaktivert" -#: aleksis/core/templates/core/pages/system_status.html:56 +#: aleksis/core/templates/core/pages/system_status.html:58 msgid "" "\n" " Debug mode is disabled. Default error pages are displayed on errors.\n" @@ -2083,42 +2125,42 @@ msgstr "" " Debug-Modus ist deaktiviert. Standard-Fehlerseiten werden bei Fehlern angezeigt.\n" " " -#: aleksis/core/templates/core/pages/system_status.html:69 +#: aleksis/core/templates/core/pages/system_status.html:71 msgid "System health checks" msgstr "Systemprüfungen" -#: aleksis/core/templates/core/pages/system_status.html:75 +#: aleksis/core/templates/core/pages/system_status.html:77 msgid "Service" msgstr "Dienst" -#: aleksis/core/templates/core/pages/system_status.html:76 -#: aleksis/core/templates/core/pages/system_status.html:115 +#: aleksis/core/templates/core/pages/system_status.html:78 +#: aleksis/core/templates/core/pages/system_status.html:119 msgid "Status" msgstr "Status" -#: aleksis/core/templates/core/pages/system_status.html:77 +#: aleksis/core/templates/core/pages/system_status.html:79 msgid "Time taken" msgstr "Dauer" -#: aleksis/core/templates/core/pages/system_status.html:96 +#: aleksis/core/templates/core/pages/system_status.html:100 msgid "seconds" msgstr "Sekunden" -#: aleksis/core/templates/core/pages/system_status.html:107 +#: aleksis/core/templates/core/pages/system_status.html:111 msgid "Celery task results" msgstr "Celery Task-Ergebnisse" -#: aleksis/core/templates/core/pages/system_status.html:112 +#: aleksis/core/templates/core/pages/system_status.html:116 #: aleksis/core/templates/templated_email/celery_failure.email:9 #: aleksis/core/templates/templated_email/celery_failure.email:28 msgid "Task" msgstr "Task" -#: aleksis/core/templates/core/pages/system_status.html:113 +#: aleksis/core/templates/core/pages/system_status.html:117 msgid "ID" msgstr "ID" -#: aleksis/core/templates/core/pages/system_status.html:114 +#: aleksis/core/templates/core/pages/system_status.html:118 msgid "Date done" msgstr "Erledigungszeitpunkt" @@ -2171,6 +2213,18 @@ msgstr "" " Gültig von %(from)s – %(until)s\n" " " +#: aleksis/core/templates/core/partials/avatar_content.html:14 +#: aleksis/core/templates/core/partials/avatar_content.html:15 +#: aleksis/core/templates/core/person/full.html:213 +#: aleksis/core/templates/core/person/full.html:214 +msgid "Avatar" +msgstr "Avatar" + +#: aleksis/core/templates/core/partials/avatar_content.html:19 +#: aleksis/core/templates/core/partials/avatar_content.html:20 +msgid "Identicon" +msgstr "Identicon" + #: aleksis/core/templates/core/partials/crud_events.html:15 msgid "Changed by" msgstr "Verändert von" @@ -2270,24 +2324,24 @@ msgid "Edit person" msgstr "Person editieren" #: aleksis/core/templates/core/person/full.html:47 -#: aleksis/core/templates/core/person/full.html:119 +#: aleksis/core/templates/core/person/full.html:107 msgid "Impersonate" msgstr "Verkleiden" #: aleksis/core/templates/core/person/full.html:54 -#: aleksis/core/templates/core/person/full.html:126 +#: aleksis/core/templates/core/person/full.html:114 msgid "Invite user" msgstr "Benutzer einladen" -#: aleksis/core/templates/core/person/full.html:133 +#: aleksis/core/templates/core/person/full.html:121 msgid "Contact details" msgstr "Kontaktdetails" -#: aleksis/core/templates/core/person/full.html:224 +#: aleksis/core/templates/core/person/full.html:220 msgid "This person didn't upload a personal photo." msgstr "Diese Person hat kein persönliches Foto hochgeladen." -#: aleksis/core/templates/core/person/full.html:232 +#: aleksis/core/templates/core/person/full.html:228 msgid "Children" msgstr "Kinder" @@ -2337,9 +2391,7 @@ msgstr "Die Einladungsfunktion ist deaktiviert." #: aleksis/core/templates/invitations/disabled.html:15 msgid "To enable it, switch on the corresponding checkbox in the authentication section of the " -msgstr "" -"Um sie zu aktivieren, nutzen Sie die Checkbox im Abschnitt \"Authentifikation" -"\" der " +msgstr "Um sie zu aktivieren, nutzen Sie die Checkbox im Abschnitt \"Authentifikation\" der " #: aleksis/core/templates/invitations/disabled.html:16 msgid "site preferences page" @@ -2498,15 +2550,11 @@ msgstr "Keine autorisierten Anwendungen." msgid "Network error" msgstr "Netzwerkfehler" -#: aleksis/core/templates/offline.html:8 -msgid "" -"No internet\n" -" connection." -msgstr "" -"Keine\n" -" Internetverbindung." +#: aleksis/core/templates/offline.html:10 +msgid "No internet connection." +msgstr "Keine Internetverbindung." -#: aleksis/core/templates/offline.html:12 +#: aleksis/core/templates/offline.html:14 msgid "" "\n" " There was an error accessing this page. You probably don't have an internet connection. Check to see if your WiFi\n" @@ -2788,7 +2836,7 @@ msgstr "" #: aleksis/core/templates/two_factor/_base_focus.html:6 #: aleksis/core/templates/two_factor/core/otp_required.html:22 #: aleksis/core/templates/two_factor/core/setup.html:5 -#: aleksis/core/templates/two_factor/profile/profile.html:87 +#: aleksis/core/templates/two_factor/profile/profile.html:88 msgid "Enable Two-Factor Authentication" msgstr "Zwei-Faktor-Authentifizierung aktivieren" @@ -2920,15 +2968,15 @@ msgstr "Gerät aktuell nicht verfügbar?" msgid "Or, alternatively, use one of your backup phones:" msgstr "Oder, alternativ, nutzen Sie eins Ihrer Backup-Telefone:" -#: aleksis/core/templates/two_factor/core/login.html:121 +#: aleksis/core/templates/two_factor/core/login.html:122 msgid "As a last resort, you can use a backup token:" msgstr "Als letzte Möglichkeit können Sie einen Backup-Token nutzen:" -#: aleksis/core/templates/two_factor/core/login.html:124 +#: aleksis/core/templates/two_factor/core/login.html:125 msgid "Use Backup Token" msgstr "Backup-Token nutzen" -#: aleksis/core/templates/two_factor/core/login.html:135 +#: aleksis/core/templates/two_factor/core/login.html:136 msgid "Use alternative login options" msgstr "Alternative Anmeldemöglichkeiten nutzen" @@ -3241,11 +3289,11 @@ msgstr "" " Accountsicherheit.\n" " " -#: aleksis/core/util/notifications.py:63 +#: aleksis/core/util/notifications.py:64 msgid "E-Mail" msgstr "E-Mail" -#: aleksis/core/util/notifications.py:64 +#: aleksis/core/util/notifications.py:65 msgid "SMS" msgstr "SMS" @@ -3269,162 +3317,166 @@ msgstr "Es ist ein Fehler beim Generieren der PDF-Datei aufgetreten." msgid "Download PDF" msgstr "PDF herunterladen" -#: aleksis/core/views.py:285 +#: aleksis/core/views.py:289 msgid "The school term has been created." msgstr "Das Schuljahr wurde erstellt." -#: aleksis/core/views.py:297 +#: aleksis/core/views.py:301 msgid "The school term has been saved." msgstr "Das Schuljahr wurde gespeichert." -#: aleksis/core/views.py:417 +#: aleksis/core/views.py:421 msgid "The child groups were successfully saved." msgstr "Die Untergruppen wurden gespeichert." -#: aleksis/core/views.py:436 aleksis/core/views.py:446 +#: aleksis/core/views.py:440 aleksis/core/views.py:450 msgid "The person has been saved." msgstr "Die Person wurde gespeichert." -#: aleksis/core/views.py:496 +#: aleksis/core/views.py:500 msgid "The group has been saved." msgstr "Die Gruppe wurde gespeichert." -#: aleksis/core/views.py:593 +#: aleksis/core/views.py:597 msgid "The announcement has been saved." msgstr "Die Ankündigung wurde gespeichert." -#: aleksis/core/views.py:609 +#: aleksis/core/views.py:613 msgid "The announcement has been deleted." msgstr "Ankündigung wurde gelöscht." -#: aleksis/core/views.py:677 +#: aleksis/core/views.py:681 msgid "The requested preference registry does not exist" msgstr "Das angeforderte Einstellungsregister existiert nicht" -#: aleksis/core/views.py:696 +#: aleksis/core/views.py:700 msgid "The preferences have been saved successfully." msgstr "Die Einstellungen wurde gespeichert." -#: aleksis/core/views.py:720 +#: aleksis/core/views.py:724 msgid "The person has been deleted." msgstr "Die Person wurde gelöscht." -#: aleksis/core/views.py:734 +#: aleksis/core/views.py:738 msgid "The group has been deleted." msgstr "Die Gruppe wurde gelöscht." -#: aleksis/core/views.py:766 +#: aleksis/core/views.py:770 msgid "The additional_field has been saved." msgstr "Das zusätzliche Feld wurde gespeichert." -#: aleksis/core/views.py:800 +#: aleksis/core/views.py:804 msgid "The additional field has been deleted." msgstr "Das zusätzliche Feld wurde gelöscht." -#: aleksis/core/views.py:825 +#: aleksis/core/views.py:829 msgid "The group type has been saved." msgstr "Der Gruppentyp wurde gespeichert." -#: aleksis/core/views.py:855 +#: aleksis/core/views.py:859 msgid "The group type has been deleted." msgstr "Der Gruppentyp wurde gelöscht." -#: aleksis/core/views.py:888 +#: aleksis/core/views.py:892 msgid "Progress: Run data checks" msgstr "Fortschritt: Datenprüfungen ausführen" -#: aleksis/core/views.py:889 +#: aleksis/core/views.py:893 msgid "Run data checks …" msgstr "Datenprüfungen laufen …" -#: aleksis/core/views.py:890 +#: aleksis/core/views.py:894 msgid "The data checks were run successfully." msgstr "Die Datenprüfungen wurden erfolgreich ausgeführt." -#: aleksis/core/views.py:891 +#: aleksis/core/views.py:895 msgid "There was a problem while running data checks." msgstr "Es gab ein Problem beim Ausführen der Datenprüfungen." -#: aleksis/core/views.py:907 +#: aleksis/core/views.py:911 #, python-brace-format msgid "The solve option '{solve_option_obj.verbose_name}' " msgstr "Die Lösungsoption \"{solve_option_obj.verbose_name}\" " -#: aleksis/core/views.py:917 +#: aleksis/core/views.py:921 msgid "The requested solve option does not exist" msgstr "Die angeforderte Lösungsoption existiert nicht" -#: aleksis/core/views.py:949 +#: aleksis/core/views.py:953 msgid "The dashboard widget has been saved." msgstr "Das Dashboard-Widget wurde gespeichert." -#: aleksis/core/views.py:979 +#: aleksis/core/views.py:983 msgid "The dashboard widget has been created." msgstr "Das Dashboard-Widget wurde erstellt." -#: aleksis/core/views.py:989 +#: aleksis/core/views.py:993 msgid "The dashboard widget has been deleted." msgstr "Das Dashboard-Widget wurde gelöscht." -#: aleksis/core/views.py:1060 +#: aleksis/core/views.py:1064 msgid "Your dashboard configuration has been saved successfully." msgstr "Ihre Dashboardkonfiguration wurde erfolgreich gespeichert." -#: aleksis/core/views.py:1062 +#: aleksis/core/views.py:1066 msgid "The configuration of the default dashboard has been saved successfully." msgstr "Die Konfiguration des Standard-Dashboardes wurde erfolgreich gespeichert." -#: aleksis/core/views.py:1138 +#: aleksis/core/views.py:1142 #, python-brace-format msgid "The invitation was successfully created. The invitation code is {code}" msgstr "Die Einladung wurde erfolgreich erstellt. Der Einladungscode ist {code}" -#: aleksis/core/views.py:1229 +#: aleksis/core/views.py:1233 msgid "We have successfully assigned the permissions." msgstr "Wir haben die Berechtigungen erfolgreich zugewiesen." -#: aleksis/core/views.py:1239 +#: aleksis/core/views.py:1243 msgid "The global user permission has been deleted." msgstr "Die globale Benutzerberechtigung wurde gelöscht." -#: aleksis/core/views.py:1249 +#: aleksis/core/views.py:1253 msgid "The global group permission has been deleted." msgstr "Die globale Gruppenberechtigung wurde gelöscht." -#: aleksis/core/views.py:1259 +#: aleksis/core/views.py:1263 msgid "The object user permission has been deleted." msgstr "Die Objekt-Benutzerberechtigung wurde gelöscht." -#: aleksis/core/views.py:1269 +#: aleksis/core/views.py:1273 msgid "The object group permission has been deleted." msgstr "Die Objekt-Gruppenberechtigung wurde gelöscht." -#: aleksis/core/views.py:1337 +#: aleksis/core/views.py:1341 msgid "The requested PDF file does not exist" msgstr "Die angeforderte PDF-Datei existiert nicht" -#: aleksis/core/views.py:1346 aleksis/core/views.py:1350 +#: aleksis/core/views.py:1350 aleksis/core/views.py:1354 msgid "The requested task does not exist or is not accessible" msgstr "Der angeforderte Task existiert nicht oder ist nicht abrufbar" -#: aleksis/core/views.py:1388 +#: aleksis/core/views.py:1406 msgid "The third-party account could not be disconnected because it is the only login method available." msgstr "Das Drittanbieter-Konto konnte nicht deaktiviert werden, weil es die einzige verfügbare Anmeldeoption ist." -#: aleksis/core/views.py:1395 +#: aleksis/core/views.py:1413 msgid "The third-party account has been successfully disconnected." msgstr "Das Drittanbieter-Konto wurde erfolgreich getrennt." -#: aleksis/core/views.py:1466 +#: aleksis/core/views.py:1484 msgid "Person was invited successfully and an email with further instructions has been send to them." -msgstr "" -"Die Person wurde erfolgreich eingeladen und eine E-Mail mit weiteren " -"Anweisungen wurde an sie verschickt." +msgstr "Die Person wurde erfolgreich eingeladen und eine E-Mail mit weiteren Anweisungen wurde an sie verschickt." -#: aleksis/core/views.py:1477 +#: aleksis/core/views.py:1495 msgid "Person was already invited." msgstr "Person wurde bereits eingeladen." +#~ msgid "Me" +#~ msgstr "Ich" + +#~ msgid "Logged in as" +#~ msgstr "Angemeldet als" + #~ msgid "Person was invited successfully." #~ msgstr "Person wurde erfolgreich eingeladen." diff --git a/aleksis/core/locale/de_DE/LC_MESSAGES/djangojs.po b/aleksis/core/locale/de_DE/LC_MESSAGES/djangojs.po index 376788f8a7ea941b89dff0620fdbc78a40c106a5..c0b719bf0961c3f0c22071603f7df5b175571354 100644 --- a/aleksis/core/locale/de_DE/LC_MESSAGES/djangojs.po +++ b/aleksis/core/locale/de_DE/LC_MESSAGES/djangojs.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-02-08 23:16+0000\n" +"POT-Creation-Date: 2022-03-23 11:20+0100\n" "PO-Revision-Date: 2021-10-28 14:37+0000\n" "Last-Translator: Jonathan Weth <teckids@jonathanweth.de>\n" "Language-Team: German <https://translate.edugit.org/projects/aleksis/aleksis-core-js/de/>\n" @@ -30,6 +30,6 @@ msgstr "Abbrechen" msgid "OK" msgstr "OK" -#: aleksis/core/static/js/main.js:191 +#: aleksis/core/static/js/main.js:195 msgid "This page may contain outdated information since there is no internet connection." msgstr "Diese Seite enthält vielleicht veraltete Informationen, da es keine Internetverbindung gibt." diff --git a/aleksis/core/locale/fr/LC_MESSAGES/django.po b/aleksis/core/locale/fr/LC_MESSAGES/django.po index ac9b5f99c721e75f4dd0e5bf94368eaee2c7867f..231a5f739692d128aa759a0b397450df36c54169 100644 --- a/aleksis/core/locale/fr/LC_MESSAGES/django.po +++ b/aleksis/core/locale/fr/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: AlekSIS (School Information System) 0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-02-08 23:16+0000\n" +"POT-Creation-Date: 2022-03-23 11:19+0100\n" "PO-Revision-Date: 2021-06-16 12:00+0000\n" "Last-Translator: Jonathan Weth <teckids@jonathanweth.de>\n" "Language-Team: French <https://translate.edugit.org/projects/aleksis/aleksis/fr/>\n" @@ -40,10 +40,10 @@ msgstr "Détails de contact" msgid "Home and mobile phone" msgstr "" -#: aleksis/core/apps.py:171 aleksis/core/forms.py:220 aleksis/core/menus.py:265 -#: aleksis/core/models.py:462 aleksis/core/templates/core/group/list.html:8 +#: aleksis/core/apps.py:171 aleksis/core/forms.py:220 aleksis/core/menus.py:185 +#: aleksis/core/models.py:487 aleksis/core/templates/core/group/list.html:8 #: aleksis/core/templates/core/group/list.html:9 -#: aleksis/core/templates/core/person/full.html:250 +#: aleksis/core/templates/core/person/full.html:246 #, fuzzy #| msgid "Group" msgid "Groups" @@ -70,8 +70,8 @@ msgstr "" msgid "The DashboardWidget was reported broken automatically." msgstr "" -#: aleksis/core/filters.py:42 aleksis/core/templates/core/base.html:105 -#: aleksis/core/templates/core/base.html:106 +#: aleksis/core/filters.py:42 aleksis/core/templates/core/base.html:139 +#: aleksis/core/templates/core/base.html:140 #: aleksis/core/templates/core/group/list.html:20 #: aleksis/core/templates/core/person/list.html:24 #: aleksis/core/templates/search/search.html:7 @@ -97,11 +97,11 @@ msgstr "" msgid "Content type" msgstr "" -#: aleksis/core/filters.py:113 aleksis/core/models.py:688 +#: aleksis/core/filters.py:113 aleksis/core/models.py:713 msgid "User" msgstr "" -#: aleksis/core/filters.py:135 aleksis/core/models.py:461 +#: aleksis/core/filters.py:135 aleksis/core/models.py:486 msgid "Group" msgstr "groupe" @@ -141,7 +141,7 @@ msgstr "" msgid "This username is already in use." msgstr "Cet nom est deja en utilisation." -#: aleksis/core/forms.py:153 aleksis/core/models.py:130 +#: aleksis/core/forms.py:153 aleksis/core/models.py:134 msgid "School term" msgstr "" @@ -152,7 +152,7 @@ msgid "Common data" msgstr "Détails de contact" #: aleksis/core/forms.py:155 aleksis/core/forms.py:207 -#: aleksis/core/menus.py:254 aleksis/core/models.py:153 +#: aleksis/core/menus.py:174 aleksis/core/models.py:157 #: aleksis/core/templates/core/person/list.html:8 #: aleksis/core/templates/core/person/list.html:9 #, fuzzy @@ -166,18 +166,18 @@ msgstr "Personne" msgid "Additional data" msgstr "Détails de contact" -#: aleksis/core/forms.py:157 aleksis/core/models.py:206 -#: aleksis/core/models.py:514 +#: aleksis/core/forms.py:157 aleksis/core/models.py:210 +#: aleksis/core/models.py:539 msgid "Photo" msgstr "" #: aleksis/core/forms.py:199 aleksis/core/forms.py:202 -#: aleksis/core/models.py:73 +#: aleksis/core/models.py:77 msgid "Date" msgstr "Date" #: aleksis/core/forms.py:200 aleksis/core/forms.py:203 -#: aleksis/core/models.py:81 +#: aleksis/core/models.py:85 msgid "Time" msgstr "" @@ -213,11 +213,11 @@ msgstr "" msgid "Please enter your invitation code." msgstr "" -#: aleksis/core/forms.py:418 aleksis/core/models.py:181 +#: aleksis/core/forms.py:418 aleksis/core/models.py:185 msgid "First name" msgstr "Prénom" -#: aleksis/core/forms.py:419 aleksis/core/models.py:182 +#: aleksis/core/forms.py:419 aleksis/core/models.py:186 msgid "Last name" msgstr "Nom de famille" @@ -267,7 +267,15 @@ msgstr "" msgid "Password (again)" msgstr "" -#: aleksis/core/forms.py:775 +#: aleksis/core/forms.py:728 +msgid "The selected action does not exist." +msgstr "" + +#: aleksis/core/forms.py:739 +msgid "You do not have permission to run {} on all selected objects." +msgstr "" + +#: aleksis/core/forms.py:795 msgid "No valid selection." msgstr "" @@ -310,123 +318,76 @@ msgstr "" msgid "Dashboard" msgstr "" -#: aleksis/core/menus.py:41 aleksis/core/models.py:734 -#: aleksis/core/preferences.py:29 +#: aleksis/core/menus.py:41 aleksis/core/models.py:765 +#: aleksis/core/preferences.py:29 aleksis/core/templates/core/base.html:81 #: aleksis/core/templates/core/notifications.html:4 #: aleksis/core/templates/core/notifications.html:5 msgid "Notifications" msgstr "" #: aleksis/core/menus.py:53 -msgid "Account" -msgstr "" - -#: aleksis/core/menus.py:60 -msgid "Stop impersonation" -msgstr "" - -#: aleksis/core/menus.py:69 aleksis/core/templates/core/base.html:80 -msgid "Logout" -msgstr "" - -#: aleksis/core/menus.py:75 -msgid "2FA" -msgstr "" - -#: aleksis/core/menus.py:83 -#: aleksis/core/templates/account/password_change.html:5 -#: aleksis/core/templates/account/password_change.html:6 -#: aleksis/core/templates/account/password_change.html:19 -#: aleksis/core/templates/account/password_reset_from_key.html:5 -#: aleksis/core/templates/account/password_reset_from_key.html:42 -#: aleksis/core/templates/account/password_reset_from_key.html:46 -#: aleksis/core/templates/account/password_reset_from_key_done.html:5 -#: aleksis/core/templates/account/password_reset_from_key_done.html:6 -msgid "Change password" -msgstr "" - -#: aleksis/core/menus.py:95 -msgid "Me" -msgstr "" - -#: aleksis/core/menus.py:104 -#: aleksis/core/templates/dynamic_preferences/form.html:5 -msgid "Preferences" -msgstr "" - -#: aleksis/core/menus.py:113 -msgid "Third-party accounts" -msgstr "" - -#: aleksis/core/menus.py:122 -#: aleksis/core/templates/oauth2_provider/authorized-tokens.html:5 -#: aleksis/core/templates/oauth2_provider/authorized-tokens.html:6 -msgid "Authorized applications" -msgstr "" - -#: aleksis/core/menus.py:133 msgid "Admin" msgstr "" -#: aleksis/core/menus.py:141 aleksis/core/models.py:834 +#: aleksis/core/menus.py:61 aleksis/core/models.py:865 #: aleksis/core/templates/core/announcement/list.html:7 #: aleksis/core/templates/core/announcement/list.html:8 msgid "Announcements" msgstr "" -#: aleksis/core/menus.py:152 aleksis/core/models.py:131 +#: aleksis/core/menus.py:72 aleksis/core/models.py:135 #: aleksis/core/templates/core/school_term/list.html:8 #: aleksis/core/templates/core/school_term/list.html:9 msgid "School terms" msgstr "" -#: aleksis/core/menus.py:163 +#: aleksis/core/menus.py:83 #: aleksis/core/templates/core/dashboard_widget/list.html:8 #: aleksis/core/templates/core/dashboard_widget/list.html:9 msgid "Dashboard widgets" msgstr "" -#: aleksis/core/menus.py:174 +#: aleksis/core/menus.py:94 #: aleksis/core/templates/core/management/data_management.html:6 #: aleksis/core/templates/core/management/data_management.html:7 msgid "Data management" msgstr "" -#: aleksis/core/menus.py:185 +#: aleksis/core/menus.py:105 #: aleksis/core/templates/core/pages/system_status.html:5 #: aleksis/core/templates/core/pages/system_status.html:7 msgid "System status" msgstr "" -#: aleksis/core/menus.py:196 +#: aleksis/core/menus.py:116 msgid "Configuration" msgstr "" -#: aleksis/core/menus.py:207 aleksis/core/templates/core/data_check/list.html:9 +#: aleksis/core/menus.py:127 aleksis/core/templates/core/data_check/list.html:9 #: aleksis/core/templates/core/data_check/list.html:10 msgid "Data checks" msgstr "" -#: aleksis/core/menus.py:213 aleksis/core/templates/core/perms/list.html:13 +#: aleksis/core/menus.py:133 aleksis/core/templates/core/perms/list.html:13 #: aleksis/core/templates/core/perms/list.html:14 msgid "Manage permissions" msgstr "" -#: aleksis/core/menus.py:224 +#: aleksis/core/menus.py:144 msgid "Backend Admin" msgstr "" -#: aleksis/core/menus.py:232 +#: aleksis/core/menus.py:152 #: aleksis/core/templates/oauth2_provider/application/list.html:5 #: aleksis/core/templates/oauth2_provider/application/list.html:6 msgid "OAuth2 Applications" msgstr "" -#: aleksis/core/menus.py:245 +#: aleksis/core/menus.py:165 msgid "People" msgstr "" -#: aleksis/core/menus.py:276 aleksis/core/models.py:1055 +#: aleksis/core/menus.py:196 aleksis/core/models.py:1099 #: aleksis/core/templates/core/group_type/list.html:8 #: aleksis/core/templates/core/group_type/list.html:9 #, fuzzy @@ -434,594 +395,663 @@ msgstr "" msgid "Group types" msgstr "Groupe" -#: aleksis/core/menus.py:287 +#: aleksis/core/menus.py:207 msgid "Groups and child groups" msgstr "" -#: aleksis/core/menus.py:298 aleksis/core/models.py:510 +#: aleksis/core/menus.py:218 aleksis/core/models.py:535 #: aleksis/core/templates/core/additional_field/list.html:8 #: aleksis/core/templates/core/additional_field/list.html:9 msgid "Additional fields" msgstr "" -#: aleksis/core/menus.py:309 +#: aleksis/core/menus.py:229 #, fuzzy #| msgid "Contact details" msgid "Invite person" msgstr "Détails de contact" -#: aleksis/core/menus.py:322 +#: aleksis/core/menus.py:242 #: aleksis/core/templates/core/group/child_groups.html:7 #: aleksis/core/templates/core/group/child_groups.html:9 msgid "Assign child groups to groups" msgstr "" +#: aleksis/core/menus.py:254 +msgid "Stop impersonation" +msgstr "" + +#: aleksis/core/menus.py:263 +msgid "Account" +msgstr "" + +#: aleksis/core/menus.py:272 +#: aleksis/core/templates/dynamic_preferences/form.html:5 +msgid "Preferences" +msgstr "" + +#: aleksis/core/menus.py:281 +msgid "2FA" +msgstr "" + +#: aleksis/core/menus.py:289 +#: aleksis/core/templates/account/password_change.html:5 +#: aleksis/core/templates/account/password_change.html:6 +#: aleksis/core/templates/account/password_change.html:19 +#: aleksis/core/templates/account/password_reset_from_key.html:5 +#: aleksis/core/templates/account/password_reset_from_key.html:42 +#: aleksis/core/templates/account/password_reset_from_key.html:46 +#: aleksis/core/templates/account/password_reset_from_key_done.html:5 +#: aleksis/core/templates/account/password_reset_from_key_done.html:6 +msgid "Change password" +msgstr "" + +#: aleksis/core/menus.py:301 +msgid "Third-party accounts" +msgstr "" + +#: aleksis/core/menus.py:310 +#: aleksis/core/templates/oauth2_provider/authorized-tokens.html:5 +#: aleksis/core/templates/oauth2_provider/authorized-tokens.html:6 +msgid "Authorized applications" +msgstr "" + +#: aleksis/core/menus.py:320 +msgid "Logout" +msgstr "" + #: aleksis/core/mixins.py:511 msgid "Linked school term" msgstr "" -#: aleksis/core/models.py:71 +#: aleksis/core/models.py:75 msgid "Boolean (Yes/No)" msgstr "" -#: aleksis/core/models.py:72 +#: aleksis/core/models.py:76 msgid "Text (one line)" msgstr "" -#: aleksis/core/models.py:74 +#: aleksis/core/models.py:78 msgid "Date and time" msgstr "" -#: aleksis/core/models.py:75 +#: aleksis/core/models.py:79 msgid "Decimal number" msgstr "" -#: aleksis/core/models.py:76 aleksis/core/models.py:199 +#: aleksis/core/models.py:80 aleksis/core/models.py:203 msgid "E-mail address" msgstr "" -#: aleksis/core/models.py:77 +#: aleksis/core/models.py:81 msgid "Integer" msgstr "" -#: aleksis/core/models.py:78 +#: aleksis/core/models.py:82 msgid "IP address" msgstr "" -#: aleksis/core/models.py:79 +#: aleksis/core/models.py:83 msgid "Boolean or empty (Yes/No/Neither)" msgstr "" -#: aleksis/core/models.py:80 +#: aleksis/core/models.py:84 msgid "Text (multi-line)" msgstr "" -#: aleksis/core/models.py:82 +#: aleksis/core/models.py:86 msgid "URL / Link" msgstr "" -#: aleksis/core/models.py:94 aleksis/core/models.py:1024 +#: aleksis/core/models.py:98 aleksis/core/models.py:1068 msgid "Name" msgstr "" -#: aleksis/core/models.py:96 +#: aleksis/core/models.py:100 #, fuzzy #| msgid "Contact details" msgid "Start date" msgstr "Détails de contact" -#: aleksis/core/models.py:97 +#: aleksis/core/models.py:101 msgid "End date" msgstr "" -#: aleksis/core/models.py:116 +#: aleksis/core/models.py:120 msgid "The start date must be earlier than the end date." msgstr "" -#: aleksis/core/models.py:123 +#: aleksis/core/models.py:127 msgid "There is already a school term for this time or a part of this time." msgstr "" -#: aleksis/core/models.py:152 aleksis/core/models.py:973 +#: aleksis/core/models.py:156 aleksis/core/models.py:1017 msgid "Person" msgstr "Personne" -#: aleksis/core/models.py:155 +#: aleksis/core/models.py:159 #, fuzzy #| msgid "Contact details" msgid "Can view address" msgstr "Détails de contact" -#: aleksis/core/models.py:156 +#: aleksis/core/models.py:160 #, fuzzy #| msgid "Contact details" msgid "Can view contact details" msgstr "Détails de contact" -#: aleksis/core/models.py:157 +#: aleksis/core/models.py:161 #, fuzzy #| msgid "Contact details" msgid "Can view photo" msgstr "Détails de contact" -#: aleksis/core/models.py:158 +#: aleksis/core/models.py:162 #, fuzzy #| msgid "Contact details" msgid "Can view avatar image" msgstr "Détails de contact" -#: aleksis/core/models.py:159 +#: aleksis/core/models.py:163 #, fuzzy #| msgid "Contact details" msgid "Can view persons groups" msgstr "Détails de contact" -#: aleksis/core/models.py:160 +#: aleksis/core/models.py:164 #, fuzzy #| msgid "Contact details" msgid "Can view personal details" msgstr "Détails de contact" -#: aleksis/core/models.py:170 +#: aleksis/core/models.py:174 msgid "female" msgstr "" -#: aleksis/core/models.py:170 +#: aleksis/core/models.py:174 msgid "male" msgstr "" -#: aleksis/core/models.py:178 aleksis/core/models.py:1227 +#: aleksis/core/models.py:182 aleksis/core/models.py:1271 msgid "Linked user" msgstr "" -#: aleksis/core/models.py:184 +#: aleksis/core/models.py:188 msgid "Additional name(s)" msgstr "" -#: aleksis/core/models.py:188 aleksis/core/models.py:479 +#: aleksis/core/models.py:192 aleksis/core/models.py:504 #, fuzzy #| msgid "First name" msgid "Short name" msgstr "Prénom" -#: aleksis/core/models.py:191 +#: aleksis/core/models.py:195 msgid "Street" msgstr "" -#: aleksis/core/models.py:192 +#: aleksis/core/models.py:196 msgid "Street number" msgstr "" -#: aleksis/core/models.py:193 +#: aleksis/core/models.py:197 msgid "Postal code" msgstr "" -#: aleksis/core/models.py:194 +#: aleksis/core/models.py:198 msgid "Place" msgstr "" -#: aleksis/core/models.py:196 aleksis/core/templates/core/person/full.html:172 +#: aleksis/core/models.py:200 aleksis/core/templates/core/person/full.html:160 msgid "Home phone" msgstr "" -#: aleksis/core/models.py:197 aleksis/core/templates/core/person/full.html:182 +#: aleksis/core/models.py:201 aleksis/core/templates/core/person/full.html:170 msgid "Mobile phone" msgstr "" -#: aleksis/core/models.py:201 +#: aleksis/core/models.py:205 msgid "Date of birth" msgstr "Date d'anniversaire" -#: aleksis/core/models.py:202 +#: aleksis/core/models.py:206 #, fuzzy #| msgid "Date of birth" msgid "Place of birth" msgstr "Date d'anniversaire" -#: aleksis/core/models.py:203 +#: aleksis/core/models.py:207 msgid "Sex" msgstr "Sexe" -#: aleksis/core/models.py:210 aleksis/core/models.py:518 +#: aleksis/core/models.py:214 aleksis/core/models.py:543 msgid "This is an official photo, used for official documents and for internal use cases." msgstr "" -#: aleksis/core/models.py:215 aleksis/core/models.py:522 +#: aleksis/core/models.py:219 aleksis/core/models.py:547 msgid "Display picture / Avatar" msgstr "" -#: aleksis/core/models.py:218 aleksis/core/models.py:525 +#: aleksis/core/models.py:222 aleksis/core/models.py:550 msgid "This is a picture or an avatar for public display." msgstr "" -#: aleksis/core/models.py:223 aleksis/core/templates/core/person/full.html:239 +#: aleksis/core/models.py:227 aleksis/core/templates/core/person/full.html:235 msgid "Guardians / Parents" msgstr "" -#: aleksis/core/models.py:230 +#: aleksis/core/models.py:234 msgid "Primary group" msgstr "" -#: aleksis/core/models.py:233 aleksis/core/models.py:692 -#: aleksis/core/models.py:716 aleksis/core/models.py:801 -#: aleksis/core/models.py:1048 +#: aleksis/core/models.py:237 aleksis/core/models.py:717 +#: aleksis/core/models.py:741 aleksis/core/models.py:832 +#: aleksis/core/models.py:1092 msgid "Description" msgstr "Description" -#: aleksis/core/models.py:434 +#: aleksis/core/models.py:457 msgid "Title of field" msgstr "" -#: aleksis/core/models.py:436 +#: aleksis/core/models.py:459 msgid "Type of field" msgstr "" -#: aleksis/core/models.py:443 +#: aleksis/core/models.py:461 +msgid "Required" +msgstr "" + +#: aleksis/core/models.py:462 +#, fuzzy +#| msgid "Description" +msgid "Help text / description" +msgstr "Description" + +#: aleksis/core/models.py:468 msgid "Addtitional field for groups" msgstr "" -#: aleksis/core/models.py:444 +#: aleksis/core/models.py:469 msgid "Addtitional fields for groups" msgstr "" -#: aleksis/core/models.py:464 +#: aleksis/core/models.py:489 msgid "Can assign child groups to groups" msgstr "" -#: aleksis/core/models.py:465 +#: aleksis/core/models.py:490 #, fuzzy #| msgid "Contact details" msgid "Can view statistics about group." msgstr "Détails de contact" -#: aleksis/core/models.py:477 +#: aleksis/core/models.py:502 #, fuzzy #| msgid "Last name" msgid "Long name" msgstr "Nom de famille" -#: aleksis/core/models.py:487 aleksis/core/templates/core/group/full.html:85 +#: aleksis/core/models.py:512 aleksis/core/templates/core/group/full.html:85 msgid "Members" msgstr "" -#: aleksis/core/models.py:490 aleksis/core/templates/core/group/full.html:82 +#: aleksis/core/models.py:515 aleksis/core/templates/core/group/full.html:82 msgid "Owners" msgstr "Propriétaires" -#: aleksis/core/models.py:497 aleksis/core/templates/core/group/full.html:55 +#: aleksis/core/models.py:522 aleksis/core/templates/core/group/full.html:55 msgid "Parent groups" msgstr "" -#: aleksis/core/models.py:505 +#: aleksis/core/models.py:530 msgid "Type of group" msgstr "" -#: aleksis/core/models.py:691 aleksis/core/models.py:715 -#: aleksis/core/models.py:800 +#: aleksis/core/models.py:716 aleksis/core/models.py:740 +#: aleksis/core/models.py:831 #: aleksis/core/templates/core/announcement/list.html:18 msgid "Title" msgstr "" -#: aleksis/core/models.py:694 +#: aleksis/core/models.py:719 msgid "Application" msgstr "" -#: aleksis/core/models.py:700 +#: aleksis/core/models.py:725 msgid "Activity" msgstr "" -#: aleksis/core/models.py:701 +#: aleksis/core/models.py:726 msgid "Activities" msgstr "" -#: aleksis/core/models.py:707 +#: aleksis/core/models.py:732 msgid "Sender" msgstr "" -#: aleksis/core/models.py:712 +#: aleksis/core/models.py:737 msgid "Recipient" msgstr "" -#: aleksis/core/models.py:717 aleksis/core/models.py:1025 +#: aleksis/core/models.py:742 aleksis/core/models.py:1069 msgid "Link" msgstr "" -#: aleksis/core/models.py:719 +#: aleksis/core/models.py:744 +msgid "Send notification at" +msgstr "" + +#: aleksis/core/models.py:746 msgid "Read" msgstr "" -#: aleksis/core/models.py:720 +#: aleksis/core/models.py:747 msgid "Sent" msgstr "" -#: aleksis/core/models.py:733 +#: aleksis/core/models.py:764 msgid "Notification" msgstr "" -#: aleksis/core/models.py:802 +#: aleksis/core/models.py:833 msgid "Link to detailed view" msgstr "" -#: aleksis/core/models.py:805 +#: aleksis/core/models.py:836 msgid "Date and time from when to show" msgstr "" -#: aleksis/core/models.py:808 +#: aleksis/core/models.py:839 msgid "Date and time until when to show" msgstr "" -#: aleksis/core/models.py:833 +#: aleksis/core/models.py:864 msgid "Announcement" msgstr "" -#: aleksis/core/models.py:871 +#: aleksis/core/models.py:902 msgid "Announcement recipient" msgstr "" -#: aleksis/core/models.py:872 +#: aleksis/core/models.py:903 msgid "Announcement recipients" msgstr "" -#: aleksis/core/models.py:894 +#: aleksis/core/models.py:925 msgid "Widget Title" msgstr "" -#: aleksis/core/models.py:895 +#: aleksis/core/models.py:926 msgid "Activate Widget" msgstr "" -#: aleksis/core/models.py:896 +#: aleksis/core/models.py:927 msgid "Widget is broken" msgstr "" -#: aleksis/core/models.py:899 +#: aleksis/core/models.py:930 msgid "Size on mobile devices" msgstr "" -#: aleksis/core/models.py:900 +#: aleksis/core/models.py:931 msgid "<= 600 px, 12 columns" msgstr "" -#: aleksis/core/models.py:905 +#: aleksis/core/models.py:936 msgid "Size on tablet devices" msgstr "" -#: aleksis/core/models.py:906 +#: aleksis/core/models.py:937 msgid "> 600 px, 12 columns" msgstr "" -#: aleksis/core/models.py:911 +#: aleksis/core/models.py:942 msgid "Size on desktop devices" msgstr "" -#: aleksis/core/models.py:912 +#: aleksis/core/models.py:943 msgid "> 992 px, 12 columns" msgstr "" -#: aleksis/core/models.py:917 +#: aleksis/core/models.py:948 msgid "Size on large desktop devices" msgstr "" -#: aleksis/core/models.py:918 +#: aleksis/core/models.py:949 msgid "> 1200 px>, 12 columns" msgstr "" -#: aleksis/core/models.py:949 +#: aleksis/core/models.py:980 msgid "Can edit default dashboard" msgstr "" -#: aleksis/core/models.py:950 +#: aleksis/core/models.py:981 msgid "Dashboard Widget" msgstr "" -#: aleksis/core/models.py:951 +#: aleksis/core/models.py:982 msgid "Dashboard Widgets" msgstr "" -#: aleksis/core/models.py:957 +#: aleksis/core/models.py:988 msgid "URL" msgstr "" -#: aleksis/core/models.py:958 +#: aleksis/core/models.py:989 msgid "Icon URL" msgstr "" -#: aleksis/core/models.py:964 +#: aleksis/core/models.py:995 msgid "External link widget" msgstr "" -#: aleksis/core/models.py:965 +#: aleksis/core/models.py:996 msgid "External link widgets" msgstr "" -#: aleksis/core/models.py:970 +#: aleksis/core/models.py:1002 +msgid "Content" +msgstr "" + +#: aleksis/core/models.py:1008 +msgid "Static content widget" +msgstr "" + +#: aleksis/core/models.py:1009 +msgid "Static content widgets" +msgstr "" + +#: aleksis/core/models.py:1014 msgid "Dashboard widget" msgstr "" -#: aleksis/core/models.py:975 +#: aleksis/core/models.py:1019 msgid "Order" msgstr "" -#: aleksis/core/models.py:976 +#: aleksis/core/models.py:1020 msgid "Part of the default dashboard" msgstr "" -#: aleksis/core/models.py:991 +#: aleksis/core/models.py:1035 msgid "Dashboard widget order" msgstr "" -#: aleksis/core/models.py:992 +#: aleksis/core/models.py:1036 msgid "Dashboard widget orders" msgstr "" -#: aleksis/core/models.py:998 +#: aleksis/core/models.py:1042 msgid "Menu ID" msgstr "" -#: aleksis/core/models.py:1011 +#: aleksis/core/models.py:1055 msgid "Custom menu" msgstr "" -#: aleksis/core/models.py:1012 +#: aleksis/core/models.py:1056 msgid "Custom menus" msgstr "" -#: aleksis/core/models.py:1022 +#: aleksis/core/models.py:1066 msgid "Menu" msgstr "" -#: aleksis/core/models.py:1026 aleksis/core/models.py:1274 +#: aleksis/core/models.py:1070 aleksis/core/models.py:1318 #: aleksis/core/templates/oauth2_provider/application/detail.html:26 msgid "Icon" msgstr "" -#: aleksis/core/models.py:1032 +#: aleksis/core/models.py:1076 msgid "Custom menu item" msgstr "" -#: aleksis/core/models.py:1033 +#: aleksis/core/models.py:1077 msgid "Custom menu items" msgstr "" -#: aleksis/core/models.py:1047 +#: aleksis/core/models.py:1091 msgid "Title of type" msgstr "" -#: aleksis/core/models.py:1054 aleksis/core/templates/core/group/full.html:47 +#: aleksis/core/models.py:1098 aleksis/core/templates/core/group/full.html:47 #, fuzzy #| msgid "Group" msgid "Group type" msgstr "Groupe" -#: aleksis/core/models.py:1068 +#: aleksis/core/models.py:1112 #, fuzzy #| msgid "Contact details" msgid "Can view system status" msgstr "Détails de contact" -#: aleksis/core/models.py:1069 +#: aleksis/core/models.py:1113 msgid "Can manage data" msgstr "" -#: aleksis/core/models.py:1070 +#: aleksis/core/models.py:1114 #, fuzzy #| msgid "Contact details" msgid "Can impersonate" msgstr "Détails de contact" -#: aleksis/core/models.py:1071 +#: aleksis/core/models.py:1115 msgid "Can use search" msgstr "" -#: aleksis/core/models.py:1072 +#: aleksis/core/models.py:1116 msgid "Can change site preferences" msgstr "" -#: aleksis/core/models.py:1073 +#: aleksis/core/models.py:1117 msgid "Can change person preferences" msgstr "" -#: aleksis/core/models.py:1074 +#: aleksis/core/models.py:1118 msgid "Can change group preferences" msgstr "" -#: aleksis/core/models.py:1075 +#: aleksis/core/models.py:1119 msgid "Can test PDF generation" msgstr "" -#: aleksis/core/models.py:1076 +#: aleksis/core/models.py:1120 #, fuzzy #| msgid "Contact details" msgid "Can invite persons" msgstr "Détails de contact" -#: aleksis/core/models.py:1112 +#: aleksis/core/models.py:1156 msgid "Related data check task" msgstr "" -#: aleksis/core/models.py:1120 +#: aleksis/core/models.py:1164 msgid "Issue solved" msgstr "" -#: aleksis/core/models.py:1121 +#: aleksis/core/models.py:1165 msgid "Notification sent" msgstr "" -#: aleksis/core/models.py:1134 +#: aleksis/core/models.py:1178 msgid "Data check result" msgstr "" -#: aleksis/core/models.py:1135 +#: aleksis/core/models.py:1179 msgid "Data check results" msgstr "" -#: aleksis/core/models.py:1137 +#: aleksis/core/models.py:1181 msgid "Can run data checks" msgstr "" -#: aleksis/core/models.py:1138 +#: aleksis/core/models.py:1182 msgid "Can solve data check problems" msgstr "" -#: aleksis/core/models.py:1145 +#: aleksis/core/models.py:1189 #, fuzzy #| msgid "Contact details" msgid "E-Mail address" msgstr "Détails de contact" -#: aleksis/core/models.py:1177 +#: aleksis/core/models.py:1221 #, fuzzy #| msgid "Owners" msgid "Owner" msgstr "Propriétaires" -#: aleksis/core/models.py:1181 +#: aleksis/core/models.py:1225 msgid "File expires at" msgstr "" -#: aleksis/core/models.py:1183 +#: aleksis/core/models.py:1227 msgid "Generated HTML file" msgstr "" -#: aleksis/core/models.py:1185 +#: aleksis/core/models.py:1229 msgid "Generated PDF file" msgstr "" -#: aleksis/core/models.py:1192 +#: aleksis/core/models.py:1236 msgid "PDF file" msgstr "" -#: aleksis/core/models.py:1193 +#: aleksis/core/models.py:1237 msgid "PDF files" msgstr "" -#: aleksis/core/models.py:1198 +#: aleksis/core/models.py:1242 msgid "Task result" msgstr "" -#: aleksis/core/models.py:1201 +#: aleksis/core/models.py:1245 msgid "Task user" msgstr "" -#: aleksis/core/models.py:1213 +#: aleksis/core/models.py:1257 msgid "Task user assignment" msgstr "" -#: aleksis/core/models.py:1214 +#: aleksis/core/models.py:1258 msgid "Task user assignments" msgstr "" -#: aleksis/core/models.py:1230 +#: aleksis/core/models.py:1274 #, fuzzy #| msgid "Contact details" msgid "Additional attributes" msgstr "Détails de contact" -#: aleksis/core/models.py:1268 +#: aleksis/core/models.py:1312 msgid "Allowed scopes that clients can request" msgstr "" -#: aleksis/core/models.py:1278 +#: aleksis/core/models.py:1322 msgid "This image will be shown as icon in the authorization flow. It should be squared." msgstr "" @@ -1148,88 +1178,100 @@ msgid "Allow users to change their passwords" msgstr "" #: aleksis/core/preferences.py:279 -msgid "Enable signup" +msgid "Allow users to reset their passwords" msgstr "" #: aleksis/core/preferences.py:287 -msgid "Enable invitations" +msgid "Enable signup" msgstr "" #: aleksis/core/preferences.py:295 -msgid "Length of invite code. (Default 3: abcde-acbde-abcde)" +msgid "Regular expression for allowed usernames" msgstr "" #: aleksis/core/preferences.py:303 +msgid "Enable invitations" +msgstr "" + +#: aleksis/core/preferences.py:311 +msgid "Length of invite code. (Default 3: abcde-acbde-abcde)" +msgstr "" + +#: aleksis/core/preferences.py:319 msgid "Size of packets. (Default 5: abcde)" msgstr "" -#: aleksis/core/preferences.py:314 +#: aleksis/core/preferences.py:330 #, fuzzy #| msgid "Contact details" msgid "Allowed Grant Flows for OAuth applications" msgstr "Détails de contact" -#: aleksis/core/preferences.py:328 +#: aleksis/core/preferences.py:344 msgid "Available languages" msgstr "" -#: aleksis/core/preferences.py:341 +#: aleksis/core/preferences.py:357 msgid "Send emails if data checks detect problems" msgstr "" -#: aleksis/core/preferences.py:352 +#: aleksis/core/preferences.py:368 msgid "Email recipients for data checks problem emails" msgstr "" -#: aleksis/core/preferences.py:363 +#: aleksis/core/preferences.py:379 msgid "Email recipient groups for data checks problem emails" msgstr "" -#: aleksis/core/preferences.py:372 +#: aleksis/core/preferences.py:388 msgid "Show dashboard to users without login" msgstr "" -#: aleksis/core/preferences.py:381 +#: aleksis/core/preferences.py:397 msgid "Allow users to edit their dashboard" msgstr "" -#: aleksis/core/preferences.py:392 +#: aleksis/core/preferences.py:408 msgid "Fields on person model which are editable by themselves." msgstr "" -#: aleksis/core/preferences.py:407 +#: aleksis/core/preferences.py:423 msgid "Editable fields on person model which should trigger a notification on change" msgstr "" -#: aleksis/core/preferences.py:421 +#: aleksis/core/preferences.py:437 msgid "Contact for notification if a person changes their data" msgstr "" -#: aleksis/core/preferences.py:432 +#: aleksis/core/preferences.py:448 +msgid "Prefer personal photos over avatars" +msgstr "" + +#: aleksis/core/preferences.py:458 msgid "PDF file expiration duration" msgstr "" -#: aleksis/core/preferences.py:433 +#: aleksis/core/preferences.py:459 msgid "in minutes" msgstr "" -#: aleksis/core/preferences.py:443 +#: aleksis/core/preferences.py:469 msgid "Automatically update the dashboard and its widgets" msgstr "" -#: aleksis/core/preferences.py:453 +#: aleksis/core/preferences.py:479 msgid "Automatically update the dashboard and its widgets sitewide" msgstr "" -#: aleksis/core/preferences.py:463 +#: aleksis/core/preferences.py:489 msgid "Country for phone number parsing" msgstr "" -#: aleksis/core/settings.py:529 +#: aleksis/core/settings.py:540 msgid "English" msgstr "" -#: aleksis/core/settings.py:530 +#: aleksis/core/settings.py:541 msgid "German" msgstr "" @@ -1237,7 +1279,7 @@ msgstr "" #: aleksis/core/templates/core/announcement/list.html:36 #: aleksis/core/templates/core/group/full.html:24 #: aleksis/core/templates/core/person/full.html:26 -#: aleksis/core/templates/core/person/full.html:98 +#: aleksis/core/templates/core/person/full.html:86 #: aleksis/core/templates/oauth2_provider/application/detail.html:17 msgid "Edit" msgstr "" @@ -1255,7 +1297,7 @@ msgstr "" #: aleksis/core/templates/core/group/full.html:31 #: aleksis/core/templates/core/pages/delete.html:22 #: aleksis/core/templates/core/person/full.html:33 -#: aleksis/core/templates/core/person/full.html:105 +#: aleksis/core/templates/core/person/full.html:93 #: aleksis/core/templates/oauth2_provider/application/detail.html:21 msgid "Delete" msgstr "" @@ -1302,6 +1344,10 @@ msgid "" " " msgstr "" +#: aleksis/core/templates/500.html:21 +msgid "Retry" +msgstr "" + #: aleksis/core/templates/503.html:10 msgid "" "The maintenance mode is currently enabled. Please try again\n" @@ -1560,19 +1606,15 @@ msgstr "" msgid "There are no announcements." msgstr "" -#: aleksis/core/templates/core/base.html:78 -msgid "Logged in as" -msgstr "" - -#: aleksis/core/templates/core/base.html:179 +#: aleksis/core/templates/core/base.html:213 msgid "About AlekSIS® — The Free School Information System" msgstr "" -#: aleksis/core/templates/core/base.html:187 +#: aleksis/core/templates/core/base.html:221 msgid "Imprint" msgstr "" -#: aleksis/core/templates/core/base.html:195 +#: aleksis/core/templates/core/base.html:229 msgid "Privacy Policy" msgstr "" @@ -1799,7 +1841,7 @@ msgstr "" #: aleksis/core/templates/core/group/full.html:38 #: aleksis/core/templates/core/person/full.html:40 -#: aleksis/core/templates/core/person/full.html:112 +#: aleksis/core/templates/core/person/full.html:100 msgid "Change preferences" msgstr "" @@ -1993,83 +2035,83 @@ msgstr "" msgid "System checks" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:21 +#: aleksis/core/templates/core/pages/system_status.html:22 msgid "Maintenance mode enabled" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:23 +#: aleksis/core/templates/core/pages/system_status.html:24 msgid "" "\n" " Only admin and visitors from internal IPs can access thesite.\n" " " msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:34 +#: aleksis/core/templates/core/pages/system_status.html:36 msgid "Maintenance mode disabled" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:35 +#: aleksis/core/templates/core/pages/system_status.html:37 msgid "Everyone can access the site." msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:45 +#: aleksis/core/templates/core/pages/system_status.html:47 msgid "Debug mode enabled" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:47 +#: aleksis/core/templates/core/pages/system_status.html:49 msgid "" "\n" " The web server throws back debug information on errors. Do not use in production!\n" " " msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:54 +#: aleksis/core/templates/core/pages/system_status.html:56 msgid "Debug mode disabled" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:56 +#: aleksis/core/templates/core/pages/system_status.html:58 msgid "" "\n" " Debug mode is disabled. Default error pages are displayed on errors.\n" " " msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:69 +#: aleksis/core/templates/core/pages/system_status.html:71 msgid "System health checks" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:75 +#: aleksis/core/templates/core/pages/system_status.html:77 msgid "Service" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:76 -#: aleksis/core/templates/core/pages/system_status.html:115 +#: aleksis/core/templates/core/pages/system_status.html:78 +#: aleksis/core/templates/core/pages/system_status.html:119 msgid "Status" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:77 +#: aleksis/core/templates/core/pages/system_status.html:79 msgid "Time taken" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:96 +#: aleksis/core/templates/core/pages/system_status.html:100 msgid "seconds" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:107 +#: aleksis/core/templates/core/pages/system_status.html:111 msgid "Celery task results" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:112 +#: aleksis/core/templates/core/pages/system_status.html:116 #: aleksis/core/templates/templated_email/celery_failure.email:9 #: aleksis/core/templates/templated_email/celery_failure.email:28 msgid "Task" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:113 +#: aleksis/core/templates/core/pages/system_status.html:117 msgid "ID" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:114 +#: aleksis/core/templates/core/pages/system_status.html:118 #, fuzzy #| msgid "Date" msgid "Date done" @@ -2112,6 +2154,18 @@ msgid "" " " msgstr "" +#: aleksis/core/templates/core/partials/avatar_content.html:14 +#: aleksis/core/templates/core/partials/avatar_content.html:15 +#: aleksis/core/templates/core/person/full.html:213 +#: aleksis/core/templates/core/person/full.html:214 +msgid "Avatar" +msgstr "" + +#: aleksis/core/templates/core/partials/avatar_content.html:19 +#: aleksis/core/templates/core/partials/avatar_content.html:20 +msgid "Identicon" +msgstr "" + #: aleksis/core/templates/core/partials/crud_events.html:15 msgid "Changed by" msgstr "" @@ -2206,26 +2260,26 @@ msgid "Edit person" msgstr "" #: aleksis/core/templates/core/person/full.html:47 -#: aleksis/core/templates/core/person/full.html:119 +#: aleksis/core/templates/core/person/full.html:107 #, fuzzy #| msgid "Contact details" msgid "Impersonate" msgstr "Détails de contact" #: aleksis/core/templates/core/person/full.html:54 -#: aleksis/core/templates/core/person/full.html:126 +#: aleksis/core/templates/core/person/full.html:114 msgid "Invite user" msgstr "" -#: aleksis/core/templates/core/person/full.html:133 +#: aleksis/core/templates/core/person/full.html:121 msgid "Contact details" msgstr "Détails de contact" -#: aleksis/core/templates/core/person/full.html:224 +#: aleksis/core/templates/core/person/full.html:220 msgid "This person didn't upload a personal photo." msgstr "" -#: aleksis/core/templates/core/person/full.html:232 +#: aleksis/core/templates/core/person/full.html:228 msgid "Children" msgstr "" @@ -2441,13 +2495,11 @@ msgstr "Détails de contact" msgid "Network error" msgstr "" -#: aleksis/core/templates/offline.html:8 -msgid "" -"No internet\n" -" connection." +#: aleksis/core/templates/offline.html:10 +msgid "No internet connection." msgstr "" -#: aleksis/core/templates/offline.html:12 +#: aleksis/core/templates/offline.html:14 msgid "" "\n" " There was an error accessing this page. You probably don't have an internet connection. Check to see if your WiFi\n" @@ -2697,7 +2749,7 @@ msgstr "" #: aleksis/core/templates/two_factor/_base_focus.html:6 #: aleksis/core/templates/two_factor/core/otp_required.html:22 #: aleksis/core/templates/two_factor/core/setup.html:5 -#: aleksis/core/templates/two_factor/profile/profile.html:87 +#: aleksis/core/templates/two_factor/profile/profile.html:88 msgid "Enable Two-Factor Authentication" msgstr "" @@ -2802,15 +2854,15 @@ msgstr "" msgid "Or, alternatively, use one of your backup phones:" msgstr "" -#: aleksis/core/templates/two_factor/core/login.html:121 +#: aleksis/core/templates/two_factor/core/login.html:122 msgid "As a last resort, you can use a backup token:" msgstr "" -#: aleksis/core/templates/two_factor/core/login.html:124 +#: aleksis/core/templates/two_factor/core/login.html:125 msgid "Use Backup Token" msgstr "" -#: aleksis/core/templates/two_factor/core/login.html:135 +#: aleksis/core/templates/two_factor/core/login.html:136 msgid "Use alternative login options" msgstr "" @@ -3047,11 +3099,11 @@ msgid "" " " msgstr "" -#: aleksis/core/util/notifications.py:63 +#: aleksis/core/util/notifications.py:64 msgid "E-Mail" msgstr "" -#: aleksis/core/util/notifications.py:64 +#: aleksis/core/util/notifications.py:65 msgid "SMS" msgstr "" @@ -3075,157 +3127,157 @@ msgstr "" msgid "Download PDF" msgstr "" -#: aleksis/core/views.py:285 +#: aleksis/core/views.py:289 msgid "The school term has been created." msgstr "" -#: aleksis/core/views.py:297 +#: aleksis/core/views.py:301 msgid "The school term has been saved." msgstr "" -#: aleksis/core/views.py:417 +#: aleksis/core/views.py:421 msgid "The child groups were successfully saved." msgstr "" -#: aleksis/core/views.py:436 aleksis/core/views.py:446 +#: aleksis/core/views.py:440 aleksis/core/views.py:450 msgid "The person has been saved." msgstr "" -#: aleksis/core/views.py:496 +#: aleksis/core/views.py:500 msgid "The group has been saved." msgstr "" -#: aleksis/core/views.py:593 +#: aleksis/core/views.py:597 msgid "The announcement has been saved." msgstr "" -#: aleksis/core/views.py:609 +#: aleksis/core/views.py:613 msgid "The announcement has been deleted." msgstr "" -#: aleksis/core/views.py:677 +#: aleksis/core/views.py:681 msgid "The requested preference registry does not exist" msgstr "" -#: aleksis/core/views.py:696 +#: aleksis/core/views.py:700 msgid "The preferences have been saved successfully." msgstr "" -#: aleksis/core/views.py:720 +#: aleksis/core/views.py:724 msgid "The person has been deleted." msgstr "" -#: aleksis/core/views.py:734 +#: aleksis/core/views.py:738 msgid "The group has been deleted." msgstr "" -#: aleksis/core/views.py:766 +#: aleksis/core/views.py:770 msgid "The additional_field has been saved." msgstr "" -#: aleksis/core/views.py:800 +#: aleksis/core/views.py:804 msgid "The additional field has been deleted." msgstr "" -#: aleksis/core/views.py:825 +#: aleksis/core/views.py:829 msgid "The group type has been saved." msgstr "" -#: aleksis/core/views.py:855 +#: aleksis/core/views.py:859 msgid "The group type has been deleted." msgstr "" -#: aleksis/core/views.py:888 +#: aleksis/core/views.py:892 msgid "Progress: Run data checks" msgstr "" -#: aleksis/core/views.py:889 +#: aleksis/core/views.py:893 msgid "Run data checks …" msgstr "" -#: aleksis/core/views.py:890 +#: aleksis/core/views.py:894 msgid "The data checks were run successfully." msgstr "" -#: aleksis/core/views.py:891 +#: aleksis/core/views.py:895 msgid "There was a problem while running data checks." msgstr "" -#: aleksis/core/views.py:907 +#: aleksis/core/views.py:911 #, python-brace-format msgid "The solve option '{solve_option_obj.verbose_name}' " msgstr "" -#: aleksis/core/views.py:917 +#: aleksis/core/views.py:921 msgid "The requested solve option does not exist" msgstr "" -#: aleksis/core/views.py:949 +#: aleksis/core/views.py:953 msgid "The dashboard widget has been saved." msgstr "" -#: aleksis/core/views.py:979 +#: aleksis/core/views.py:983 msgid "The dashboard widget has been created." msgstr "" -#: aleksis/core/views.py:989 +#: aleksis/core/views.py:993 msgid "The dashboard widget has been deleted." msgstr "" -#: aleksis/core/views.py:1060 +#: aleksis/core/views.py:1064 msgid "Your dashboard configuration has been saved successfully." msgstr "" -#: aleksis/core/views.py:1062 +#: aleksis/core/views.py:1066 msgid "The configuration of the default dashboard has been saved successfully." msgstr "" -#: aleksis/core/views.py:1138 +#: aleksis/core/views.py:1142 #, python-brace-format msgid "The invitation was successfully created. The invitation code is {code}" msgstr "" -#: aleksis/core/views.py:1229 +#: aleksis/core/views.py:1233 msgid "We have successfully assigned the permissions." msgstr "" -#: aleksis/core/views.py:1239 +#: aleksis/core/views.py:1243 msgid "The global user permission has been deleted." msgstr "" -#: aleksis/core/views.py:1249 +#: aleksis/core/views.py:1253 msgid "The global group permission has been deleted." msgstr "" -#: aleksis/core/views.py:1259 +#: aleksis/core/views.py:1263 msgid "The object user permission has been deleted." msgstr "" -#: aleksis/core/views.py:1269 +#: aleksis/core/views.py:1273 msgid "The object group permission has been deleted." msgstr "" -#: aleksis/core/views.py:1337 +#: aleksis/core/views.py:1341 msgid "The requested PDF file does not exist" msgstr "" -#: aleksis/core/views.py:1346 aleksis/core/views.py:1350 +#: aleksis/core/views.py:1350 aleksis/core/views.py:1354 msgid "The requested task does not exist or is not accessible" msgstr "" -#: aleksis/core/views.py:1388 +#: aleksis/core/views.py:1406 msgid "The third-party account could not be disconnected because it is the only login method available." msgstr "" -#: aleksis/core/views.py:1395 +#: aleksis/core/views.py:1413 msgid "The third-party account has been successfully disconnected." msgstr "" -#: aleksis/core/views.py:1466 +#: aleksis/core/views.py:1484 msgid "Person was invited successfully and an email with further instructions has been send to them." msgstr "" -#: aleksis/core/views.py:1477 +#: aleksis/core/views.py:1495 #, fuzzy #| msgid "This username is already in use." msgid "Person was already invited." diff --git a/aleksis/core/locale/fr/LC_MESSAGES/djangojs.po b/aleksis/core/locale/fr/LC_MESSAGES/djangojs.po index 9f07be2903046e41680c481bea659aa95b695df7..0f31d087d69a8fca9b3573dfa6d977c8459eaf99 100644 --- a/aleksis/core/locale/fr/LC_MESSAGES/djangojs.po +++ b/aleksis/core/locale/fr/LC_MESSAGES/djangojs.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-02-08 23:16+0000\n" +"POT-Creation-Date: 2022-03-23 11:20+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -30,6 +30,6 @@ msgstr "" msgid "OK" msgstr "" -#: aleksis/core/static/js/main.js:191 +#: aleksis/core/static/js/main.js:195 msgid "This page may contain outdated information since there is no internet connection." msgstr "" diff --git a/aleksis/core/locale/la/LC_MESSAGES/django.po b/aleksis/core/locale/la/LC_MESSAGES/django.po index 4b2afb73bbbc2fd8a426789859152fa2d1895395..fd7a3aa487f88448c539f5347f5700188a72d270 100644 --- a/aleksis/core/locale/la/LC_MESSAGES/django.po +++ b/aleksis/core/locale/la/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-02-08 23:16+0000\n" +"POT-Creation-Date: 2022-03-23 11:19+0100\n" "PO-Revision-Date: 2020-12-19 12:57+0000\n" "Last-Translator: Julian <leuckerj@gmail.com>\n" "Language-Team: Latin <https://translate.edugit.org/projects/aleksis/aleksis/la/>\n" @@ -44,10 +44,10 @@ msgstr "Inscriptio electronica" msgid "Home and mobile phone" msgstr "Numerus telephoni mobilis" -#: aleksis/core/apps.py:171 aleksis/core/forms.py:220 aleksis/core/menus.py:265 -#: aleksis/core/models.py:462 aleksis/core/templates/core/group/list.html:8 +#: aleksis/core/apps.py:171 aleksis/core/forms.py:220 aleksis/core/menus.py:185 +#: aleksis/core/models.py:487 aleksis/core/templates/core/group/list.html:8 #: aleksis/core/templates/core/group/list.html:9 -#: aleksis/core/templates/core/person/full.html:250 +#: aleksis/core/templates/core/person/full.html:246 msgid "Groups" msgstr "Greges" @@ -74,8 +74,8 @@ msgstr "" msgid "The DashboardWidget was reported broken automatically." msgstr "" -#: aleksis/core/filters.py:42 aleksis/core/templates/core/base.html:105 -#: aleksis/core/templates/core/base.html:106 +#: aleksis/core/filters.py:42 aleksis/core/templates/core/base.html:139 +#: aleksis/core/templates/core/base.html:140 #: aleksis/core/templates/core/group/list.html:20 #: aleksis/core/templates/core/person/list.html:24 #: aleksis/core/templates/search/search.html:7 @@ -101,11 +101,11 @@ msgstr "" msgid "Content type" msgstr "" -#: aleksis/core/filters.py:113 aleksis/core/models.py:688 +#: aleksis/core/filters.py:113 aleksis/core/models.py:713 msgid "User" msgstr "" -#: aleksis/core/filters.py:135 aleksis/core/models.py:461 +#: aleksis/core/filters.py:135 aleksis/core/models.py:486 msgid "Group" msgstr "Grex" @@ -145,7 +145,7 @@ msgstr "" msgid "This username is already in use." msgstr "" -#: aleksis/core/forms.py:153 aleksis/core/models.py:130 +#: aleksis/core/forms.py:153 aleksis/core/models.py:134 msgid "School term" msgstr "Anus scolae" @@ -156,7 +156,7 @@ msgid "Common data" msgstr "Adminstratio datarum" #: aleksis/core/forms.py:155 aleksis/core/forms.py:207 -#: aleksis/core/menus.py:254 aleksis/core/models.py:153 +#: aleksis/core/menus.py:174 aleksis/core/models.py:157 #: aleksis/core/templates/core/person/list.html:8 #: aleksis/core/templates/core/person/list.html:9 msgid "Persons" @@ -168,18 +168,18 @@ msgstr "personae" msgid "Additional data" msgstr "addita nomines" -#: aleksis/core/forms.py:157 aleksis/core/models.py:206 -#: aleksis/core/models.py:514 +#: aleksis/core/forms.py:157 aleksis/core/models.py:210 +#: aleksis/core/models.py:539 msgid "Photo" msgstr "Photographia" #: aleksis/core/forms.py:199 aleksis/core/forms.py:202 -#: aleksis/core/models.py:73 +#: aleksis/core/models.py:77 msgid "Date" msgstr "dies" #: aleksis/core/forms.py:200 aleksis/core/forms.py:203 -#: aleksis/core/models.py:81 +#: aleksis/core/models.py:85 msgid "Time" msgstr "tempus" @@ -215,11 +215,11 @@ msgstr "" msgid "Please enter your invitation code." msgstr "" -#: aleksis/core/forms.py:418 aleksis/core/models.py:181 +#: aleksis/core/forms.py:418 aleksis/core/models.py:185 msgid "First name" msgstr "Primus nomen" -#: aleksis/core/forms.py:419 aleksis/core/models.py:182 +#: aleksis/core/forms.py:419 aleksis/core/models.py:186 msgid "Last name" msgstr "Secondus nomen" @@ -275,7 +275,15 @@ msgstr "" msgid "Password (again)" msgstr "" -#: aleksis/core/forms.py:775 +#: aleksis/core/forms.py:728 +msgid "The selected action does not exist." +msgstr "" + +#: aleksis/core/forms.py:739 +msgid "You do not have permission to run {} on all selected objects." +msgstr "" + +#: aleksis/core/forms.py:795 msgid "No valid selection." msgstr "" @@ -322,81 +330,30 @@ msgstr "Muta informationes scolae" msgid "Dashboard" msgstr "Forum" -#: aleksis/core/menus.py:41 aleksis/core/models.py:734 -#: aleksis/core/preferences.py:29 +#: aleksis/core/menus.py:41 aleksis/core/models.py:765 +#: aleksis/core/preferences.py:29 aleksis/core/templates/core/base.html:81 #: aleksis/core/templates/core/notifications.html:4 #: aleksis/core/templates/core/notifications.html:5 msgid "Notifications" msgstr "Nuntii" #: aleksis/core/menus.py:53 -msgid "Account" -msgstr "" - -#: aleksis/core/menus.py:60 -msgid "Stop impersonation" -msgstr "Simulandum aliquem finire" - -#: aleksis/core/menus.py:69 aleksis/core/templates/core/base.html:80 -msgid "Logout" -msgstr "nomen retractare" - -#: aleksis/core/menus.py:75 -msgid "2FA" -msgstr "" - -#: aleksis/core/menus.py:83 -#: aleksis/core/templates/account/password_change.html:5 -#: aleksis/core/templates/account/password_change.html:6 -#: aleksis/core/templates/account/password_change.html:19 -#: aleksis/core/templates/account/password_reset_from_key.html:5 -#: aleksis/core/templates/account/password_reset_from_key.html:42 -#: aleksis/core/templates/account/password_reset_from_key.html:46 -#: aleksis/core/templates/account/password_reset_from_key_done.html:5 -#: aleksis/core/templates/account/password_reset_from_key_done.html:6 -msgid "Change password" -msgstr "" - -#: aleksis/core/menus.py:95 -msgid "Me" -msgstr "" - -#: aleksis/core/menus.py:104 -#: aleksis/core/templates/dynamic_preferences/form.html:5 -msgid "Preferences" -msgstr "" - -#: aleksis/core/menus.py:113 -#, fuzzy -#| msgid "Persons and accounts" -msgid "Third-party accounts" -msgstr "Personae et computi" - -#: aleksis/core/menus.py:122 -#: aleksis/core/templates/oauth2_provider/authorized-tokens.html:5 -#: aleksis/core/templates/oauth2_provider/authorized-tokens.html:6 -#, fuzzy -#| msgid "Notifications" -msgid "Authorized applications" -msgstr "Nuntii" - -#: aleksis/core/menus.py:133 msgid "Admin" msgstr "Administratio" -#: aleksis/core/menus.py:141 aleksis/core/models.py:834 +#: aleksis/core/menus.py:61 aleksis/core/models.py:865 #: aleksis/core/templates/core/announcement/list.html:7 #: aleksis/core/templates/core/announcement/list.html:8 msgid "Announcements" msgstr "Nuntii" -#: aleksis/core/menus.py:152 aleksis/core/models.py:131 +#: aleksis/core/menus.py:72 aleksis/core/models.py:135 #: aleksis/core/templates/core/school_term/list.html:8 #: aleksis/core/templates/core/school_term/list.html:9 msgid "School terms" msgstr "ani scolae" -#: aleksis/core/menus.py:163 +#: aleksis/core/menus.py:83 #: aleksis/core/templates/core/dashboard_widget/list.html:8 #: aleksis/core/templates/core/dashboard_widget/list.html:9 #, fuzzy @@ -404,41 +361,41 @@ msgstr "ani scolae" msgid "Dashboard widgets" msgstr "Forum" -#: aleksis/core/menus.py:174 +#: aleksis/core/menus.py:94 #: aleksis/core/templates/core/management/data_management.html:6 #: aleksis/core/templates/core/management/data_management.html:7 msgid "Data management" msgstr "Adminstratio datarum" -#: aleksis/core/menus.py:185 +#: aleksis/core/menus.py:105 #: aleksis/core/templates/core/pages/system_status.html:5 #: aleksis/core/templates/core/pages/system_status.html:7 msgid "System status" msgstr "Status systemae" -#: aleksis/core/menus.py:196 +#: aleksis/core/menus.py:116 #, fuzzy #| msgid "Notification" msgid "Configuration" msgstr "Nuntius" -#: aleksis/core/menus.py:207 aleksis/core/templates/core/data_check/list.html:9 +#: aleksis/core/menus.py:127 aleksis/core/templates/core/data_check/list.html:9 #: aleksis/core/templates/core/data_check/list.html:10 #, fuzzy #| msgid "System status" msgid "Data checks" msgstr "Status systemae" -#: aleksis/core/menus.py:213 aleksis/core/templates/core/perms/list.html:13 +#: aleksis/core/menus.py:133 aleksis/core/templates/core/perms/list.html:13 #: aleksis/core/templates/core/perms/list.html:14 msgid "Manage permissions" msgstr "" -#: aleksis/core/menus.py:224 +#: aleksis/core/menus.py:144 msgid "Backend Admin" msgstr "" -#: aleksis/core/menus.py:232 +#: aleksis/core/menus.py:152 #: aleksis/core/templates/oauth2_provider/application/list.html:5 #: aleksis/core/templates/oauth2_provider/application/list.html:6 #, fuzzy @@ -446,11 +403,11 @@ msgstr "" msgid "OAuth2 Applications" msgstr "Nuntii" -#: aleksis/core/menus.py:245 +#: aleksis/core/menus.py:165 msgid "People" msgstr "Personae" -#: aleksis/core/menus.py:276 aleksis/core/models.py:1055 +#: aleksis/core/menus.py:196 aleksis/core/models.py:1099 #: aleksis/core/templates/core/group_type/list.html:8 #: aleksis/core/templates/core/group_type/list.html:9 #, fuzzy @@ -458,11 +415,11 @@ msgstr "Personae" msgid "Group types" msgstr "Greges" -#: aleksis/core/menus.py:287 +#: aleksis/core/menus.py:207 msgid "Groups and child groups" msgstr "" -#: aleksis/core/menus.py:298 aleksis/core/models.py:510 +#: aleksis/core/menus.py:218 aleksis/core/models.py:535 #: aleksis/core/templates/core/additional_field/list.html:8 #: aleksis/core/templates/core/additional_field/list.html:9 #, fuzzy @@ -470,616 +427,691 @@ msgstr "" msgid "Additional fields" msgstr "addita nomines" -#: aleksis/core/menus.py:309 +#: aleksis/core/menus.py:229 #, fuzzy #| msgid "Stop impersonation" msgid "Invite person" msgstr "Simulandum aliquem finire" -#: aleksis/core/menus.py:322 +#: aleksis/core/menus.py:242 #: aleksis/core/templates/core/group/child_groups.html:7 #: aleksis/core/templates/core/group/child_groups.html:9 msgid "Assign child groups to groups" msgstr "" +#: aleksis/core/menus.py:254 +msgid "Stop impersonation" +msgstr "Simulandum aliquem finire" + +#: aleksis/core/menus.py:263 +msgid "Account" +msgstr "" + +#: aleksis/core/menus.py:272 +#: aleksis/core/templates/dynamic_preferences/form.html:5 +msgid "Preferences" +msgstr "" + +#: aleksis/core/menus.py:281 +msgid "2FA" +msgstr "" + +#: aleksis/core/menus.py:289 +#: aleksis/core/templates/account/password_change.html:5 +#: aleksis/core/templates/account/password_change.html:6 +#: aleksis/core/templates/account/password_change.html:19 +#: aleksis/core/templates/account/password_reset_from_key.html:5 +#: aleksis/core/templates/account/password_reset_from_key.html:42 +#: aleksis/core/templates/account/password_reset_from_key.html:46 +#: aleksis/core/templates/account/password_reset_from_key_done.html:5 +#: aleksis/core/templates/account/password_reset_from_key_done.html:6 +msgid "Change password" +msgstr "" + +#: aleksis/core/menus.py:301 +#, fuzzy +#| msgid "Persons and accounts" +msgid "Third-party accounts" +msgstr "Personae et computi" + +#: aleksis/core/menus.py:310 +#: aleksis/core/templates/oauth2_provider/authorized-tokens.html:5 +#: aleksis/core/templates/oauth2_provider/authorized-tokens.html:6 +#, fuzzy +#| msgid "Notifications" +msgid "Authorized applications" +msgstr "Nuntii" + +#: aleksis/core/menus.py:320 +msgid "Logout" +msgstr "nomen retractare" + #: aleksis/core/mixins.py:511 #, fuzzy #| msgid "Edit school term" msgid "Linked school term" msgstr "Muta anum scolae" -#: aleksis/core/models.py:71 +#: aleksis/core/models.py:75 msgid "Boolean (Yes/No)" msgstr "" -#: aleksis/core/models.py:72 +#: aleksis/core/models.py:76 msgid "Text (one line)" msgstr "" -#: aleksis/core/models.py:74 +#: aleksis/core/models.py:78 msgid "Date and time" msgstr "Dies et hora" -#: aleksis/core/models.py:75 +#: aleksis/core/models.py:79 msgid "Decimal number" msgstr "" -#: aleksis/core/models.py:76 aleksis/core/models.py:199 +#: aleksis/core/models.py:80 aleksis/core/models.py:203 msgid "E-mail address" msgstr "Inscriptio electronica" -#: aleksis/core/models.py:77 +#: aleksis/core/models.py:81 msgid "Integer" msgstr "" -#: aleksis/core/models.py:78 +#: aleksis/core/models.py:82 #, fuzzy #| msgid "E-mail address" msgid "IP address" msgstr "Inscriptio electronica" -#: aleksis/core/models.py:79 +#: aleksis/core/models.py:83 msgid "Boolean or empty (Yes/No/Neither)" msgstr "" -#: aleksis/core/models.py:80 +#: aleksis/core/models.py:84 msgid "Text (multi-line)" msgstr "" -#: aleksis/core/models.py:82 +#: aleksis/core/models.py:86 msgid "URL / Link" msgstr "" -#: aleksis/core/models.py:94 aleksis/core/models.py:1024 +#: aleksis/core/models.py:98 aleksis/core/models.py:1068 msgid "Name" msgstr "Nomen" -#: aleksis/core/models.py:96 +#: aleksis/core/models.py:100 msgid "Start date" msgstr "" -#: aleksis/core/models.py:97 +#: aleksis/core/models.py:101 msgid "End date" msgstr "" -#: aleksis/core/models.py:116 +#: aleksis/core/models.py:120 msgid "The start date must be earlier than the end date." msgstr "" -#: aleksis/core/models.py:123 +#: aleksis/core/models.py:127 msgid "There is already a school term for this time or a part of this time." msgstr "" -#: aleksis/core/models.py:152 aleksis/core/models.py:973 +#: aleksis/core/models.py:156 aleksis/core/models.py:1017 msgid "Person" msgstr "Persona" -#: aleksis/core/models.py:155 +#: aleksis/core/models.py:159 #, fuzzy #| msgid "E-mail address" msgid "Can view address" msgstr "Inscriptio electronica" -#: aleksis/core/models.py:156 +#: aleksis/core/models.py:160 #, fuzzy #| msgid "E-mail address" msgid "Can view contact details" msgstr "Inscriptio electronica" -#: aleksis/core/models.py:157 +#: aleksis/core/models.py:161 #, fuzzy #| msgid "E-mail address" msgid "Can view photo" msgstr "Inscriptio electronica" -#: aleksis/core/models.py:158 +#: aleksis/core/models.py:162 #, fuzzy #| msgid "E-mail address" msgid "Can view avatar image" msgstr "Inscriptio electronica" -#: aleksis/core/models.py:159 +#: aleksis/core/models.py:163 #, fuzzy #| msgid "Persons and accounts" msgid "Can view persons groups" msgstr "Personae et computi" -#: aleksis/core/models.py:160 +#: aleksis/core/models.py:164 #, fuzzy #| msgid "Stop impersonation" msgid "Can view personal details" msgstr "Simulandum aliquem finire" -#: aleksis/core/models.py:170 +#: aleksis/core/models.py:174 msgid "female" msgstr "femininum" -#: aleksis/core/models.py:170 +#: aleksis/core/models.py:174 msgid "male" msgstr "maskulinum" -#: aleksis/core/models.py:178 aleksis/core/models.py:1227 +#: aleksis/core/models.py:182 aleksis/core/models.py:1271 msgid "Linked user" msgstr "" -#: aleksis/core/models.py:184 +#: aleksis/core/models.py:188 msgid "Additional name(s)" msgstr "addita nomines" -#: aleksis/core/models.py:188 aleksis/core/models.py:479 +#: aleksis/core/models.py:192 aleksis/core/models.py:504 msgid "Short name" msgstr "Breve nomen" -#: aleksis/core/models.py:191 +#: aleksis/core/models.py:195 msgid "Street" msgstr "Via" -#: aleksis/core/models.py:192 +#: aleksis/core/models.py:196 msgid "Street number" msgstr "Numerus domini" -#: aleksis/core/models.py:193 +#: aleksis/core/models.py:197 msgid "Postal code" msgstr "Numerus directorius" -#: aleksis/core/models.py:194 +#: aleksis/core/models.py:198 msgid "Place" msgstr "Urbs" -#: aleksis/core/models.py:196 aleksis/core/templates/core/person/full.html:172 +#: aleksis/core/models.py:200 aleksis/core/templates/core/person/full.html:160 msgid "Home phone" msgstr "Numerus telephoni domi" -#: aleksis/core/models.py:197 aleksis/core/templates/core/person/full.html:182 +#: aleksis/core/models.py:201 aleksis/core/templates/core/person/full.html:170 msgid "Mobile phone" msgstr "Numerus telephoni mobilis" -#: aleksis/core/models.py:201 +#: aleksis/core/models.py:205 msgid "Date of birth" msgstr "Dies natalis" -#: aleksis/core/models.py:202 +#: aleksis/core/models.py:206 #, fuzzy #| msgid "Date of birth" msgid "Place of birth" msgstr "Dies natalis" -#: aleksis/core/models.py:203 +#: aleksis/core/models.py:207 msgid "Sex" msgstr "Genus" -#: aleksis/core/models.py:210 aleksis/core/models.py:518 +#: aleksis/core/models.py:214 aleksis/core/models.py:543 msgid "This is an official photo, used for official documents and for internal use cases." msgstr "" -#: aleksis/core/models.py:215 aleksis/core/models.py:522 +#: aleksis/core/models.py:219 aleksis/core/models.py:547 msgid "Display picture / Avatar" msgstr "" -#: aleksis/core/models.py:218 aleksis/core/models.py:525 +#: aleksis/core/models.py:222 aleksis/core/models.py:550 msgid "This is a picture or an avatar for public display." msgstr "" -#: aleksis/core/models.py:223 aleksis/core/templates/core/person/full.html:239 +#: aleksis/core/models.py:227 aleksis/core/templates/core/person/full.html:235 msgid "Guardians / Parents" msgstr "Parentes" -#: aleksis/core/models.py:230 +#: aleksis/core/models.py:234 msgid "Primary group" msgstr "" -#: aleksis/core/models.py:233 aleksis/core/models.py:692 -#: aleksis/core/models.py:716 aleksis/core/models.py:801 -#: aleksis/core/models.py:1048 +#: aleksis/core/models.py:237 aleksis/core/models.py:717 +#: aleksis/core/models.py:741 aleksis/core/models.py:832 +#: aleksis/core/models.py:1092 msgid "Description" msgstr "Descriptio" -#: aleksis/core/models.py:434 +#: aleksis/core/models.py:457 msgid "Title of field" msgstr "" -#: aleksis/core/models.py:436 +#: aleksis/core/models.py:459 msgid "Type of field" msgstr "" -#: aleksis/core/models.py:443 +#: aleksis/core/models.py:461 +msgid "Required" +msgstr "" + +#: aleksis/core/models.py:462 +#, fuzzy +#| msgid "Site description" +msgid "Help text / description" +msgstr "Descriptio paginae" + +#: aleksis/core/models.py:468 #, fuzzy #| msgid "Additional name(s)" msgid "Addtitional field for groups" msgstr "addita nomines" -#: aleksis/core/models.py:444 +#: aleksis/core/models.py:469 #, fuzzy #| msgid "Additional name(s)" msgid "Addtitional fields for groups" msgstr "addita nomines" -#: aleksis/core/models.py:464 +#: aleksis/core/models.py:489 msgid "Can assign child groups to groups" msgstr "" -#: aleksis/core/models.py:465 +#: aleksis/core/models.py:490 #, fuzzy #| msgid "Persons and accounts" msgid "Can view statistics about group." msgstr "Personae et computi" -#: aleksis/core/models.py:477 +#: aleksis/core/models.py:502 #, fuzzy #| msgid "Last name" msgid "Long name" msgstr "Secondus nomen" -#: aleksis/core/models.py:487 aleksis/core/templates/core/group/full.html:85 +#: aleksis/core/models.py:512 aleksis/core/templates/core/group/full.html:85 msgid "Members" msgstr "" -#: aleksis/core/models.py:490 aleksis/core/templates/core/group/full.html:82 +#: aleksis/core/models.py:515 aleksis/core/templates/core/group/full.html:82 msgid "Owners" msgstr "" -#: aleksis/core/models.py:497 aleksis/core/templates/core/group/full.html:55 +#: aleksis/core/models.py:522 aleksis/core/templates/core/group/full.html:55 msgid "Parent groups" msgstr "" -#: aleksis/core/models.py:505 +#: aleksis/core/models.py:530 msgid "Type of group" msgstr "" -#: aleksis/core/models.py:691 aleksis/core/models.py:715 -#: aleksis/core/models.py:800 +#: aleksis/core/models.py:716 aleksis/core/models.py:740 +#: aleksis/core/models.py:831 #: aleksis/core/templates/core/announcement/list.html:18 msgid "Title" msgstr "Titulus" -#: aleksis/core/models.py:694 +#: aleksis/core/models.py:719 msgid "Application" msgstr "" -#: aleksis/core/models.py:700 +#: aleksis/core/models.py:725 msgid "Activity" msgstr "" -#: aleksis/core/models.py:701 +#: aleksis/core/models.py:726 msgid "Activities" msgstr "" -#: aleksis/core/models.py:707 +#: aleksis/core/models.py:732 msgid "Sender" msgstr "Mittens" -#: aleksis/core/models.py:712 +#: aleksis/core/models.py:737 msgid "Recipient" msgstr "" -#: aleksis/core/models.py:717 aleksis/core/models.py:1025 +#: aleksis/core/models.py:742 aleksis/core/models.py:1069 msgid "Link" msgstr "" -#: aleksis/core/models.py:719 +#: aleksis/core/models.py:744 +#, fuzzy +#| msgid "Notification" +msgid "Send notification at" +msgstr "Nuntius" + +#: aleksis/core/models.py:746 msgid "Read" msgstr "" -#: aleksis/core/models.py:720 +#: aleksis/core/models.py:747 msgid "Sent" msgstr "" -#: aleksis/core/models.py:733 +#: aleksis/core/models.py:764 #, fuzzy #| msgid "Notifications" msgid "Notification" msgstr "Nuntii" -#: aleksis/core/models.py:802 +#: aleksis/core/models.py:833 msgid "Link to detailed view" msgstr "" -#: aleksis/core/models.py:805 +#: aleksis/core/models.py:836 msgid "Date and time from when to show" msgstr "" -#: aleksis/core/models.py:808 +#: aleksis/core/models.py:839 msgid "Date and time until when to show" msgstr "" -#: aleksis/core/models.py:833 +#: aleksis/core/models.py:864 #, fuzzy #| msgid "Announcements" msgid "Announcement" msgstr "Nuntii" -#: aleksis/core/models.py:871 +#: aleksis/core/models.py:902 #, fuzzy #| msgid "Announcements" msgid "Announcement recipient" msgstr "Nuntii" -#: aleksis/core/models.py:872 +#: aleksis/core/models.py:903 #, fuzzy #| msgid "Announcements" msgid "Announcement recipients" msgstr "Nuntii" -#: aleksis/core/models.py:894 +#: aleksis/core/models.py:925 #, fuzzy #| msgid "Site title" msgid "Widget Title" msgstr "Titulus paginae" -#: aleksis/core/models.py:895 +#: aleksis/core/models.py:926 msgid "Activate Widget" msgstr "" -#: aleksis/core/models.py:896 +#: aleksis/core/models.py:927 #, fuzzy #| msgid "Site title" msgid "Widget is broken" msgstr "Titulus paginae" -#: aleksis/core/models.py:899 +#: aleksis/core/models.py:930 msgid "Size on mobile devices" msgstr "" -#: aleksis/core/models.py:900 +#: aleksis/core/models.py:931 msgid "<= 600 px, 12 columns" msgstr "" -#: aleksis/core/models.py:905 +#: aleksis/core/models.py:936 msgid "Size on tablet devices" msgstr "" -#: aleksis/core/models.py:906 +#: aleksis/core/models.py:937 msgid "> 600 px, 12 columns" msgstr "" -#: aleksis/core/models.py:911 +#: aleksis/core/models.py:942 msgid "Size on desktop devices" msgstr "" -#: aleksis/core/models.py:912 +#: aleksis/core/models.py:943 msgid "> 992 px, 12 columns" msgstr "" -#: aleksis/core/models.py:917 +#: aleksis/core/models.py:948 msgid "Size on large desktop devices" msgstr "" -#: aleksis/core/models.py:918 +#: aleksis/core/models.py:949 msgid "> 1200 px>, 12 columns" msgstr "" -#: aleksis/core/models.py:949 +#: aleksis/core/models.py:980 #, fuzzy #| msgid "Dashboard" msgid "Can edit default dashboard" msgstr "Forum" -#: aleksis/core/models.py:950 +#: aleksis/core/models.py:981 #, fuzzy #| msgid "Dashboard" msgid "Dashboard Widget" msgstr "Forum" -#: aleksis/core/models.py:951 +#: aleksis/core/models.py:982 #, fuzzy #| msgid "Dashboard" msgid "Dashboard Widgets" msgstr "Forum" -#: aleksis/core/models.py:957 +#: aleksis/core/models.py:988 msgid "URL" msgstr "" -#: aleksis/core/models.py:958 +#: aleksis/core/models.py:989 #, fuzzy #| msgid "Icon" msgid "Icon URL" msgstr "Nota" -#: aleksis/core/models.py:964 +#: aleksis/core/models.py:995 msgid "External link widget" msgstr "" -#: aleksis/core/models.py:965 +#: aleksis/core/models.py:996 msgid "External link widgets" msgstr "" -#: aleksis/core/models.py:970 +#: aleksis/core/models.py:1002 +msgid "Content" +msgstr "" + +#: aleksis/core/models.py:1008 +msgid "Static content widget" +msgstr "" + +#: aleksis/core/models.py:1009 +msgid "Static content widgets" +msgstr "" + +#: aleksis/core/models.py:1014 #, fuzzy #| msgid "Dashboard" msgid "Dashboard widget" msgstr "Forum" -#: aleksis/core/models.py:975 +#: aleksis/core/models.py:1019 msgid "Order" msgstr "" -#: aleksis/core/models.py:976 +#: aleksis/core/models.py:1020 msgid "Part of the default dashboard" msgstr "" -#: aleksis/core/models.py:991 +#: aleksis/core/models.py:1035 #, fuzzy #| msgid "Dashboard" msgid "Dashboard widget order" msgstr "Forum" -#: aleksis/core/models.py:992 +#: aleksis/core/models.py:1036 #, fuzzy #| msgid "Dashboard" msgid "Dashboard widget orders" msgstr "Forum" -#: aleksis/core/models.py:998 +#: aleksis/core/models.py:1042 msgid "Menu ID" msgstr "" -#: aleksis/core/models.py:1011 +#: aleksis/core/models.py:1055 msgid "Custom menu" msgstr "" -#: aleksis/core/models.py:1012 +#: aleksis/core/models.py:1056 msgid "Custom menus" msgstr "" -#: aleksis/core/models.py:1022 +#: aleksis/core/models.py:1066 msgid "Menu" msgstr "" -#: aleksis/core/models.py:1026 aleksis/core/models.py:1274 +#: aleksis/core/models.py:1070 aleksis/core/models.py:1318 #: aleksis/core/templates/oauth2_provider/application/detail.html:26 msgid "Icon" msgstr "Nota" -#: aleksis/core/models.py:1032 +#: aleksis/core/models.py:1076 msgid "Custom menu item" msgstr "" -#: aleksis/core/models.py:1033 +#: aleksis/core/models.py:1077 msgid "Custom menu items" msgstr "" -#: aleksis/core/models.py:1047 +#: aleksis/core/models.py:1091 msgid "Title of type" msgstr "" -#: aleksis/core/models.py:1054 aleksis/core/templates/core/group/full.html:47 +#: aleksis/core/models.py:1098 aleksis/core/templates/core/group/full.html:47 #, fuzzy #| msgid "Group" msgid "Group type" msgstr "Grex" -#: aleksis/core/models.py:1068 +#: aleksis/core/models.py:1112 #, fuzzy #| msgid "System status" msgid "Can view system status" msgstr "Status systemae" -#: aleksis/core/models.py:1069 +#: aleksis/core/models.py:1113 #, fuzzy #| msgid "Data management" msgid "Can manage data" msgstr "Adminstratio datarum" -#: aleksis/core/models.py:1070 +#: aleksis/core/models.py:1114 #, fuzzy #| msgid "Stop impersonation" msgid "Can impersonate" msgstr "Simulandum aliquem finire" -#: aleksis/core/models.py:1071 +#: aleksis/core/models.py:1115 msgid "Can use search" msgstr "" -#: aleksis/core/models.py:1072 +#: aleksis/core/models.py:1116 msgid "Can change site preferences" msgstr "" -#: aleksis/core/models.py:1073 +#: aleksis/core/models.py:1117 msgid "Can change person preferences" msgstr "" -#: aleksis/core/models.py:1074 +#: aleksis/core/models.py:1118 msgid "Can change group preferences" msgstr "" -#: aleksis/core/models.py:1075 +#: aleksis/core/models.py:1119 msgid "Can test PDF generation" msgstr "" -#: aleksis/core/models.py:1076 +#: aleksis/core/models.py:1120 #, fuzzy #| msgid "Stop impersonation" msgid "Can invite persons" msgstr "Simulandum aliquem finire" -#: aleksis/core/models.py:1112 +#: aleksis/core/models.py:1156 msgid "Related data check task" msgstr "" -#: aleksis/core/models.py:1120 +#: aleksis/core/models.py:1164 msgid "Issue solved" msgstr "" -#: aleksis/core/models.py:1121 +#: aleksis/core/models.py:1165 #, fuzzy #| msgid "Notifications" msgid "Notification sent" msgstr "Nuntii" -#: aleksis/core/models.py:1134 +#: aleksis/core/models.py:1178 msgid "Data check result" msgstr "" -#: aleksis/core/models.py:1135 +#: aleksis/core/models.py:1179 msgid "Data check results" msgstr "" -#: aleksis/core/models.py:1137 +#: aleksis/core/models.py:1181 msgid "Can run data checks" msgstr "" -#: aleksis/core/models.py:1138 +#: aleksis/core/models.py:1182 msgid "Can solve data check problems" msgstr "" -#: aleksis/core/models.py:1145 +#: aleksis/core/models.py:1189 #, fuzzy #| msgid "E-mail address" msgid "E-Mail address" msgstr "Inscriptio electronica" -#: aleksis/core/models.py:1177 +#: aleksis/core/models.py:1221 msgid "Owner" msgstr "" -#: aleksis/core/models.py:1181 +#: aleksis/core/models.py:1225 msgid "File expires at" msgstr "" -#: aleksis/core/models.py:1183 +#: aleksis/core/models.py:1227 msgid "Generated HTML file" msgstr "" -#: aleksis/core/models.py:1185 +#: aleksis/core/models.py:1229 msgid "Generated PDF file" msgstr "" -#: aleksis/core/models.py:1192 +#: aleksis/core/models.py:1236 msgid "PDF file" msgstr "" -#: aleksis/core/models.py:1193 +#: aleksis/core/models.py:1237 msgid "PDF files" msgstr "" -#: aleksis/core/models.py:1198 +#: aleksis/core/models.py:1242 msgid "Task result" msgstr "" -#: aleksis/core/models.py:1201 +#: aleksis/core/models.py:1245 msgid "Task user" msgstr "" -#: aleksis/core/models.py:1213 +#: aleksis/core/models.py:1257 msgid "Task user assignment" msgstr "" -#: aleksis/core/models.py:1214 +#: aleksis/core/models.py:1258 msgid "Task user assignments" msgstr "" -#: aleksis/core/models.py:1230 +#: aleksis/core/models.py:1274 #, fuzzy #| msgid "Additional name(s)" msgid "Additional attributes" msgstr "addita nomines" -#: aleksis/core/models.py:1268 +#: aleksis/core/models.py:1312 msgid "Allowed scopes that clients can request" msgstr "" -#: aleksis/core/models.py:1278 +#: aleksis/core/models.py:1322 msgid "This image will be shown as icon in the authorization flow. It should be squared." msgstr "" @@ -1214,88 +1246,100 @@ msgid "Allow users to change their passwords" msgstr "" #: aleksis/core/preferences.py:279 -msgid "Enable signup" +msgid "Allow users to reset their passwords" msgstr "" #: aleksis/core/preferences.py:287 -msgid "Enable invitations" +msgid "Enable signup" msgstr "" #: aleksis/core/preferences.py:295 -msgid "Length of invite code. (Default 3: abcde-acbde-abcde)" +msgid "Regular expression for allowed usernames" msgstr "" #: aleksis/core/preferences.py:303 +msgid "Enable invitations" +msgstr "" + +#: aleksis/core/preferences.py:311 +msgid "Length of invite code. (Default 3: abcde-acbde-abcde)" +msgstr "" + +#: aleksis/core/preferences.py:319 msgid "Size of packets. (Default 5: abcde)" msgstr "" -#: aleksis/core/preferences.py:314 +#: aleksis/core/preferences.py:330 #, fuzzy #| msgid "E-mail address" msgid "Allowed Grant Flows for OAuth applications" msgstr "Inscriptio electronica" -#: aleksis/core/preferences.py:328 +#: aleksis/core/preferences.py:344 msgid "Available languages" msgstr "" -#: aleksis/core/preferences.py:341 +#: aleksis/core/preferences.py:357 msgid "Send emails if data checks detect problems" msgstr "" -#: aleksis/core/preferences.py:352 +#: aleksis/core/preferences.py:368 msgid "Email recipients for data checks problem emails" msgstr "" -#: aleksis/core/preferences.py:363 +#: aleksis/core/preferences.py:379 msgid "Email recipient groups for data checks problem emails" msgstr "" -#: aleksis/core/preferences.py:372 +#: aleksis/core/preferences.py:388 msgid "Show dashboard to users without login" msgstr "" -#: aleksis/core/preferences.py:381 +#: aleksis/core/preferences.py:397 msgid "Allow users to edit their dashboard" msgstr "" -#: aleksis/core/preferences.py:392 +#: aleksis/core/preferences.py:408 msgid "Fields on person model which are editable by themselves." msgstr "" -#: aleksis/core/preferences.py:407 +#: aleksis/core/preferences.py:423 msgid "Editable fields on person model which should trigger a notification on change" msgstr "" -#: aleksis/core/preferences.py:421 +#: aleksis/core/preferences.py:437 msgid "Contact for notification if a person changes their data" msgstr "" -#: aleksis/core/preferences.py:432 +#: aleksis/core/preferences.py:448 +msgid "Prefer personal photos over avatars" +msgstr "" + +#: aleksis/core/preferences.py:458 msgid "PDF file expiration duration" msgstr "" -#: aleksis/core/preferences.py:433 +#: aleksis/core/preferences.py:459 msgid "in minutes" msgstr "" -#: aleksis/core/preferences.py:443 +#: aleksis/core/preferences.py:469 msgid "Automatically update the dashboard and its widgets" msgstr "" -#: aleksis/core/preferences.py:453 +#: aleksis/core/preferences.py:479 msgid "Automatically update the dashboard and its widgets sitewide" msgstr "" -#: aleksis/core/preferences.py:463 +#: aleksis/core/preferences.py:489 msgid "Country for phone number parsing" msgstr "" -#: aleksis/core/settings.py:529 +#: aleksis/core/settings.py:540 msgid "English" msgstr "Britannicus" -#: aleksis/core/settings.py:530 +#: aleksis/core/settings.py:541 msgid "German" msgstr "Germanus" @@ -1303,7 +1347,7 @@ msgstr "Germanus" #: aleksis/core/templates/core/announcement/list.html:36 #: aleksis/core/templates/core/group/full.html:24 #: aleksis/core/templates/core/person/full.html:26 -#: aleksis/core/templates/core/person/full.html:98 +#: aleksis/core/templates/core/person/full.html:86 #: aleksis/core/templates/oauth2_provider/application/detail.html:17 msgid "Edit" msgstr "" @@ -1323,7 +1367,7 @@ msgstr "Nuntii" #: aleksis/core/templates/core/group/full.html:31 #: aleksis/core/templates/core/pages/delete.html:22 #: aleksis/core/templates/core/person/full.html:33 -#: aleksis/core/templates/core/person/full.html:105 +#: aleksis/core/templates/core/person/full.html:93 #: aleksis/core/templates/oauth2_provider/application/detail.html:21 msgid "Delete" msgstr "" @@ -1370,6 +1414,10 @@ msgid "" " " msgstr "" +#: aleksis/core/templates/500.html:21 +msgid "Retry" +msgstr "" + #: aleksis/core/templates/503.html:10 msgid "" "The maintenance mode is currently enabled. Please try again\n" @@ -1646,19 +1694,15 @@ msgstr "" msgid "There are no announcements." msgstr "Scribe nuntium:" -#: aleksis/core/templates/core/base.html:78 -msgid "Logged in as" -msgstr "" - -#: aleksis/core/templates/core/base.html:179 +#: aleksis/core/templates/core/base.html:213 msgid "About AlekSIS® — The Free School Information System" msgstr "" -#: aleksis/core/templates/core/base.html:187 +#: aleksis/core/templates/core/base.html:221 msgid "Imprint" msgstr "" -#: aleksis/core/templates/core/base.html:195 +#: aleksis/core/templates/core/base.html:229 msgid "Privacy Policy" msgstr "" @@ -1893,7 +1937,7 @@ msgstr "" #: aleksis/core/templates/core/group/full.html:38 #: aleksis/core/templates/core/person/full.html:40 -#: aleksis/core/templates/core/person/full.html:112 +#: aleksis/core/templates/core/person/full.html:100 msgid "Change preferences" msgstr "" @@ -2099,87 +2143,87 @@ msgstr "" msgid "System checks" msgstr "Status systemae" -#: aleksis/core/templates/core/pages/system_status.html:21 +#: aleksis/core/templates/core/pages/system_status.html:22 msgid "Maintenance mode enabled" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:23 +#: aleksis/core/templates/core/pages/system_status.html:24 msgid "" "\n" " Only admin and visitors from internal IPs can access thesite.\n" " " msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:34 +#: aleksis/core/templates/core/pages/system_status.html:36 msgid "Maintenance mode disabled" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:35 +#: aleksis/core/templates/core/pages/system_status.html:37 msgid "Everyone can access the site." msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:45 +#: aleksis/core/templates/core/pages/system_status.html:47 msgid "Debug mode enabled" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:47 +#: aleksis/core/templates/core/pages/system_status.html:49 msgid "" "\n" " The web server throws back debug information on errors. Do not use in production!\n" " " msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:54 +#: aleksis/core/templates/core/pages/system_status.html:56 msgid "Debug mode disabled" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:56 +#: aleksis/core/templates/core/pages/system_status.html:58 msgid "" "\n" " Debug mode is disabled. Default error pages are displayed on errors.\n" " " msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:69 +#: aleksis/core/templates/core/pages/system_status.html:71 #, fuzzy #| msgid "System status" msgid "System health checks" msgstr "Status systemae" -#: aleksis/core/templates/core/pages/system_status.html:75 +#: aleksis/core/templates/core/pages/system_status.html:77 msgid "Service" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:76 -#: aleksis/core/templates/core/pages/system_status.html:115 +#: aleksis/core/templates/core/pages/system_status.html:78 +#: aleksis/core/templates/core/pages/system_status.html:119 #, fuzzy #| msgid "System status" msgid "Status" msgstr "Status systemae" -#: aleksis/core/templates/core/pages/system_status.html:77 +#: aleksis/core/templates/core/pages/system_status.html:79 msgid "Time taken" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:96 +#: aleksis/core/templates/core/pages/system_status.html:100 msgid "seconds" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:107 +#: aleksis/core/templates/core/pages/system_status.html:111 msgid "Celery task results" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:112 +#: aleksis/core/templates/core/pages/system_status.html:116 #: aleksis/core/templates/templated_email/celery_failure.email:9 #: aleksis/core/templates/templated_email/celery_failure.email:28 msgid "Task" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:113 +#: aleksis/core/templates/core/pages/system_status.html:117 msgid "ID" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:114 +#: aleksis/core/templates/core/pages/system_status.html:118 #, fuzzy #| msgid "Date" msgid "Date done" @@ -2222,6 +2266,20 @@ msgid "" " " msgstr "" +#: aleksis/core/templates/core/partials/avatar_content.html:14 +#: aleksis/core/templates/core/partials/avatar_content.html:15 +#: aleksis/core/templates/core/person/full.html:213 +#: aleksis/core/templates/core/person/full.html:214 +msgid "Avatar" +msgstr "" + +#: aleksis/core/templates/core/partials/avatar_content.html:19 +#: aleksis/core/templates/core/partials/avatar_content.html:20 +#, fuzzy +#| msgid "Notifications" +msgid "Identicon" +msgstr "Nuntii" + #: aleksis/core/templates/core/partials/crud_events.html:15 msgid "Changed by" msgstr "" @@ -2316,28 +2374,28 @@ msgid "Edit person" msgstr "" #: aleksis/core/templates/core/person/full.html:47 -#: aleksis/core/templates/core/person/full.html:119 +#: aleksis/core/templates/core/person/full.html:107 #, fuzzy #| msgid "Impersonation" msgid "Impersonate" msgstr "Simulare aliquem" #: aleksis/core/templates/core/person/full.html:54 -#: aleksis/core/templates/core/person/full.html:126 +#: aleksis/core/templates/core/person/full.html:114 #, fuzzy #| msgid "Impersonation" msgid "Invite user" msgstr "Simulare aliquem" -#: aleksis/core/templates/core/person/full.html:133 +#: aleksis/core/templates/core/person/full.html:121 msgid "Contact details" msgstr "" -#: aleksis/core/templates/core/person/full.html:224 +#: aleksis/core/templates/core/person/full.html:220 msgid "This person didn't upload a personal photo." msgstr "" -#: aleksis/core/templates/core/person/full.html:232 +#: aleksis/core/templates/core/person/full.html:228 msgid "Children" msgstr "" @@ -2559,13 +2617,11 @@ msgstr "Nuntii" msgid "Network error" msgstr "" -#: aleksis/core/templates/offline.html:8 -msgid "" -"No internet\n" -" connection." +#: aleksis/core/templates/offline.html:10 +msgid "No internet connection." msgstr "" -#: aleksis/core/templates/offline.html:12 +#: aleksis/core/templates/offline.html:14 msgid "" "\n" " There was an error accessing this page. You probably don't have an internet connection. Check to see if your WiFi\n" @@ -2824,7 +2880,7 @@ msgstr "" #: aleksis/core/templates/two_factor/_base_focus.html:6 #: aleksis/core/templates/two_factor/core/otp_required.html:22 #: aleksis/core/templates/two_factor/core/setup.html:5 -#: aleksis/core/templates/two_factor/profile/profile.html:87 +#: aleksis/core/templates/two_factor/profile/profile.html:88 msgid "Enable Two-Factor Authentication" msgstr "" @@ -2929,15 +2985,15 @@ msgstr "" msgid "Or, alternatively, use one of your backup phones:" msgstr "" -#: aleksis/core/templates/two_factor/core/login.html:121 +#: aleksis/core/templates/two_factor/core/login.html:122 msgid "As a last resort, you can use a backup token:" msgstr "" -#: aleksis/core/templates/two_factor/core/login.html:124 +#: aleksis/core/templates/two_factor/core/login.html:125 msgid "Use Backup Token" msgstr "" -#: aleksis/core/templates/two_factor/core/login.html:135 +#: aleksis/core/templates/two_factor/core/login.html:136 msgid "Use alternative login options" msgstr "" @@ -3174,11 +3230,11 @@ msgid "" " " msgstr "" -#: aleksis/core/util/notifications.py:63 +#: aleksis/core/util/notifications.py:64 msgid "E-Mail" msgstr "" -#: aleksis/core/util/notifications.py:64 +#: aleksis/core/util/notifications.py:65 msgid "SMS" msgstr "" @@ -3202,159 +3258,159 @@ msgstr "" msgid "Download PDF" msgstr "" -#: aleksis/core/views.py:285 +#: aleksis/core/views.py:289 msgid "The school term has been created." msgstr "" -#: aleksis/core/views.py:297 +#: aleksis/core/views.py:301 msgid "The school term has been saved." msgstr "" -#: aleksis/core/views.py:417 +#: aleksis/core/views.py:421 msgid "The child groups were successfully saved." msgstr "" -#: aleksis/core/views.py:436 aleksis/core/views.py:446 +#: aleksis/core/views.py:440 aleksis/core/views.py:450 msgid "The person has been saved." msgstr "" -#: aleksis/core/views.py:496 +#: aleksis/core/views.py:500 msgid "The group has been saved." msgstr "" -#: aleksis/core/views.py:593 +#: aleksis/core/views.py:597 msgid "The announcement has been saved." msgstr "" -#: aleksis/core/views.py:609 +#: aleksis/core/views.py:613 msgid "The announcement has been deleted." msgstr "" -#: aleksis/core/views.py:677 +#: aleksis/core/views.py:681 msgid "The requested preference registry does not exist" msgstr "" -#: aleksis/core/views.py:696 +#: aleksis/core/views.py:700 msgid "The preferences have been saved successfully." msgstr "" -#: aleksis/core/views.py:720 +#: aleksis/core/views.py:724 msgid "The person has been deleted." msgstr "" -#: aleksis/core/views.py:734 +#: aleksis/core/views.py:738 msgid "The group has been deleted." msgstr "" -#: aleksis/core/views.py:766 +#: aleksis/core/views.py:770 msgid "The additional_field has been saved." msgstr "" -#: aleksis/core/views.py:800 +#: aleksis/core/views.py:804 msgid "The additional field has been deleted." msgstr "" -#: aleksis/core/views.py:825 +#: aleksis/core/views.py:829 msgid "The group type has been saved." msgstr "" -#: aleksis/core/views.py:855 +#: aleksis/core/views.py:859 msgid "The group type has been deleted." msgstr "" -#: aleksis/core/views.py:888 +#: aleksis/core/views.py:892 msgid "Progress: Run data checks" msgstr "" -#: aleksis/core/views.py:889 +#: aleksis/core/views.py:893 #, fuzzy #| msgid "System status" msgid "Run data checks …" msgstr "Status systemae" -#: aleksis/core/views.py:890 +#: aleksis/core/views.py:894 msgid "The data checks were run successfully." msgstr "" -#: aleksis/core/views.py:891 +#: aleksis/core/views.py:895 msgid "There was a problem while running data checks." msgstr "" -#: aleksis/core/views.py:907 +#: aleksis/core/views.py:911 #, python-brace-format msgid "The solve option '{solve_option_obj.verbose_name}' " msgstr "" -#: aleksis/core/views.py:917 +#: aleksis/core/views.py:921 msgid "The requested solve option does not exist" msgstr "" -#: aleksis/core/views.py:949 +#: aleksis/core/views.py:953 msgid "The dashboard widget has been saved." msgstr "" -#: aleksis/core/views.py:979 +#: aleksis/core/views.py:983 msgid "The dashboard widget has been created." msgstr "" -#: aleksis/core/views.py:989 +#: aleksis/core/views.py:993 msgid "The dashboard widget has been deleted." msgstr "" -#: aleksis/core/views.py:1060 +#: aleksis/core/views.py:1064 msgid "Your dashboard configuration has been saved successfully." msgstr "" -#: aleksis/core/views.py:1062 +#: aleksis/core/views.py:1066 msgid "The configuration of the default dashboard has been saved successfully." msgstr "" -#: aleksis/core/views.py:1138 +#: aleksis/core/views.py:1142 #, python-brace-format msgid "The invitation was successfully created. The invitation code is {code}" msgstr "" -#: aleksis/core/views.py:1229 +#: aleksis/core/views.py:1233 msgid "We have successfully assigned the permissions." msgstr "" -#: aleksis/core/views.py:1239 +#: aleksis/core/views.py:1243 msgid "The global user permission has been deleted." msgstr "" -#: aleksis/core/views.py:1249 +#: aleksis/core/views.py:1253 msgid "The global group permission has been deleted." msgstr "" -#: aleksis/core/views.py:1259 +#: aleksis/core/views.py:1263 msgid "The object user permission has been deleted." msgstr "" -#: aleksis/core/views.py:1269 +#: aleksis/core/views.py:1273 msgid "The object group permission has been deleted." msgstr "" -#: aleksis/core/views.py:1337 +#: aleksis/core/views.py:1341 msgid "The requested PDF file does not exist" msgstr "" -#: aleksis/core/views.py:1346 aleksis/core/views.py:1350 +#: aleksis/core/views.py:1350 aleksis/core/views.py:1354 msgid "The requested task does not exist or is not accessible" msgstr "" -#: aleksis/core/views.py:1388 +#: aleksis/core/views.py:1406 msgid "The third-party account could not be disconnected because it is the only login method available." msgstr "" -#: aleksis/core/views.py:1395 +#: aleksis/core/views.py:1413 msgid "The third-party account has been successfully disconnected." msgstr "" -#: aleksis/core/views.py:1466 +#: aleksis/core/views.py:1484 msgid "Person was invited successfully and an email with further instructions has been send to them." msgstr "" -#: aleksis/core/views.py:1477 +#: aleksis/core/views.py:1495 msgid "Person was already invited." msgstr "" diff --git a/aleksis/core/locale/la/LC_MESSAGES/djangojs.po b/aleksis/core/locale/la/LC_MESSAGES/djangojs.po index dfec73c5c894d3d686092593be9c21a811cd0535..f3df4c3fc6d2848a739ddd1faac44cb9048c97b2 100644 --- a/aleksis/core/locale/la/LC_MESSAGES/djangojs.po +++ b/aleksis/core/locale/la/LC_MESSAGES/djangojs.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-02-08 23:16+0000\n" +"POT-Creation-Date: 2022-03-23 11:20+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -29,6 +29,6 @@ msgstr "" msgid "OK" msgstr "" -#: aleksis/core/static/js/main.js:191 +#: aleksis/core/static/js/main.js:195 msgid "This page may contain outdated information since there is no internet connection." msgstr "" diff --git a/aleksis/core/locale/nb_NO/LC_MESSAGES/django.po b/aleksis/core/locale/nb_NO/LC_MESSAGES/django.po index ab1f6b974dc48a296d3eead2faacea0232b1461d..71dc8727c985e991974f2700347f6fb37e4f7b47 100644 --- a/aleksis/core/locale/nb_NO/LC_MESSAGES/django.po +++ b/aleksis/core/locale/nb_NO/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: AlekSIS (School Information System) 0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-02-08 23:16+0000\n" +"POT-Creation-Date: 2022-03-23 11:19+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -37,10 +37,10 @@ msgstr "" msgid "Home and mobile phone" msgstr "" -#: aleksis/core/apps.py:171 aleksis/core/forms.py:220 aleksis/core/menus.py:265 -#: aleksis/core/models.py:462 aleksis/core/templates/core/group/list.html:8 +#: aleksis/core/apps.py:171 aleksis/core/forms.py:220 aleksis/core/menus.py:185 +#: aleksis/core/models.py:487 aleksis/core/templates/core/group/list.html:8 #: aleksis/core/templates/core/group/list.html:9 -#: aleksis/core/templates/core/person/full.html:250 +#: aleksis/core/templates/core/person/full.html:246 msgid "Groups" msgstr "" @@ -65,8 +65,8 @@ msgstr "" msgid "The DashboardWidget was reported broken automatically." msgstr "" -#: aleksis/core/filters.py:42 aleksis/core/templates/core/base.html:105 -#: aleksis/core/templates/core/base.html:106 +#: aleksis/core/filters.py:42 aleksis/core/templates/core/base.html:139 +#: aleksis/core/templates/core/base.html:140 #: aleksis/core/templates/core/group/list.html:20 #: aleksis/core/templates/core/person/list.html:24 #: aleksis/core/templates/search/search.html:7 @@ -90,11 +90,11 @@ msgstr "" msgid "Content type" msgstr "" -#: aleksis/core/filters.py:113 aleksis/core/models.py:688 +#: aleksis/core/filters.py:113 aleksis/core/models.py:713 msgid "User" msgstr "" -#: aleksis/core/filters.py:135 aleksis/core/models.py:461 +#: aleksis/core/filters.py:135 aleksis/core/models.py:486 msgid "Group" msgstr "" @@ -130,7 +130,7 @@ msgstr "" msgid "This username is already in use." msgstr "" -#: aleksis/core/forms.py:153 aleksis/core/models.py:130 +#: aleksis/core/forms.py:153 aleksis/core/models.py:134 msgid "School term" msgstr "" @@ -139,7 +139,7 @@ msgid "Common data" msgstr "" #: aleksis/core/forms.py:155 aleksis/core/forms.py:207 -#: aleksis/core/menus.py:254 aleksis/core/models.py:153 +#: aleksis/core/menus.py:174 aleksis/core/models.py:157 #: aleksis/core/templates/core/person/list.html:8 #: aleksis/core/templates/core/person/list.html:9 msgid "Persons" @@ -149,18 +149,18 @@ msgstr "" msgid "Additional data" msgstr "" -#: aleksis/core/forms.py:157 aleksis/core/models.py:206 -#: aleksis/core/models.py:514 +#: aleksis/core/forms.py:157 aleksis/core/models.py:210 +#: aleksis/core/models.py:539 msgid "Photo" msgstr "" #: aleksis/core/forms.py:199 aleksis/core/forms.py:202 -#: aleksis/core/models.py:73 +#: aleksis/core/models.py:77 msgid "Date" msgstr "" #: aleksis/core/forms.py:200 aleksis/core/forms.py:203 -#: aleksis/core/models.py:81 +#: aleksis/core/models.py:85 msgid "Time" msgstr "" @@ -196,11 +196,11 @@ msgstr "" msgid "Please enter your invitation code." msgstr "" -#: aleksis/core/forms.py:418 aleksis/core/models.py:181 +#: aleksis/core/forms.py:418 aleksis/core/models.py:185 msgid "First name" msgstr "" -#: aleksis/core/forms.py:419 aleksis/core/models.py:182 +#: aleksis/core/forms.py:419 aleksis/core/models.py:186 msgid "Last name" msgstr "" @@ -248,7 +248,15 @@ msgstr "" msgid "Password (again)" msgstr "" -#: aleksis/core/forms.py:775 +#: aleksis/core/forms.py:728 +msgid "The selected action does not exist." +msgstr "" + +#: aleksis/core/forms.py:739 +msgid "You do not have permission to run {} on all selected objects." +msgstr "" + +#: aleksis/core/forms.py:795 msgid "No valid selection." msgstr "" @@ -291,678 +299,698 @@ msgstr "" msgid "Dashboard" msgstr "" -#: aleksis/core/menus.py:41 aleksis/core/models.py:734 -#: aleksis/core/preferences.py:29 +#: aleksis/core/menus.py:41 aleksis/core/models.py:765 +#: aleksis/core/preferences.py:29 aleksis/core/templates/core/base.html:81 #: aleksis/core/templates/core/notifications.html:4 #: aleksis/core/templates/core/notifications.html:5 msgid "Notifications" msgstr "" #: aleksis/core/menus.py:53 -msgid "Account" -msgstr "" - -#: aleksis/core/menus.py:60 -msgid "Stop impersonation" -msgstr "" - -#: aleksis/core/menus.py:69 aleksis/core/templates/core/base.html:80 -msgid "Logout" -msgstr "" - -#: aleksis/core/menus.py:75 -msgid "2FA" -msgstr "" - -#: aleksis/core/menus.py:83 -#: aleksis/core/templates/account/password_change.html:5 -#: aleksis/core/templates/account/password_change.html:6 -#: aleksis/core/templates/account/password_change.html:19 -#: aleksis/core/templates/account/password_reset_from_key.html:5 -#: aleksis/core/templates/account/password_reset_from_key.html:42 -#: aleksis/core/templates/account/password_reset_from_key.html:46 -#: aleksis/core/templates/account/password_reset_from_key_done.html:5 -#: aleksis/core/templates/account/password_reset_from_key_done.html:6 -msgid "Change password" -msgstr "" - -#: aleksis/core/menus.py:95 -msgid "Me" -msgstr "" - -#: aleksis/core/menus.py:104 -#: aleksis/core/templates/dynamic_preferences/form.html:5 -msgid "Preferences" -msgstr "" - -#: aleksis/core/menus.py:113 -msgid "Third-party accounts" -msgstr "" - -#: aleksis/core/menus.py:122 -#: aleksis/core/templates/oauth2_provider/authorized-tokens.html:5 -#: aleksis/core/templates/oauth2_provider/authorized-tokens.html:6 -msgid "Authorized applications" -msgstr "" - -#: aleksis/core/menus.py:133 msgid "Admin" msgstr "" -#: aleksis/core/menus.py:141 aleksis/core/models.py:834 +#: aleksis/core/menus.py:61 aleksis/core/models.py:865 #: aleksis/core/templates/core/announcement/list.html:7 #: aleksis/core/templates/core/announcement/list.html:8 msgid "Announcements" msgstr "" -#: aleksis/core/menus.py:152 aleksis/core/models.py:131 +#: aleksis/core/menus.py:72 aleksis/core/models.py:135 #: aleksis/core/templates/core/school_term/list.html:8 #: aleksis/core/templates/core/school_term/list.html:9 msgid "School terms" msgstr "" -#: aleksis/core/menus.py:163 +#: aleksis/core/menus.py:83 #: aleksis/core/templates/core/dashboard_widget/list.html:8 #: aleksis/core/templates/core/dashboard_widget/list.html:9 msgid "Dashboard widgets" msgstr "" -#: aleksis/core/menus.py:174 +#: aleksis/core/menus.py:94 #: aleksis/core/templates/core/management/data_management.html:6 #: aleksis/core/templates/core/management/data_management.html:7 msgid "Data management" msgstr "" -#: aleksis/core/menus.py:185 +#: aleksis/core/menus.py:105 #: aleksis/core/templates/core/pages/system_status.html:5 #: aleksis/core/templates/core/pages/system_status.html:7 msgid "System status" msgstr "" -#: aleksis/core/menus.py:196 +#: aleksis/core/menus.py:116 msgid "Configuration" msgstr "" -#: aleksis/core/menus.py:207 aleksis/core/templates/core/data_check/list.html:9 +#: aleksis/core/menus.py:127 aleksis/core/templates/core/data_check/list.html:9 #: aleksis/core/templates/core/data_check/list.html:10 msgid "Data checks" msgstr "" -#: aleksis/core/menus.py:213 aleksis/core/templates/core/perms/list.html:13 +#: aleksis/core/menus.py:133 aleksis/core/templates/core/perms/list.html:13 #: aleksis/core/templates/core/perms/list.html:14 msgid "Manage permissions" msgstr "" -#: aleksis/core/menus.py:224 +#: aleksis/core/menus.py:144 msgid "Backend Admin" msgstr "" -#: aleksis/core/menus.py:232 +#: aleksis/core/menus.py:152 #: aleksis/core/templates/oauth2_provider/application/list.html:5 #: aleksis/core/templates/oauth2_provider/application/list.html:6 msgid "OAuth2 Applications" msgstr "" -#: aleksis/core/menus.py:245 +#: aleksis/core/menus.py:165 msgid "People" msgstr "" -#: aleksis/core/menus.py:276 aleksis/core/models.py:1055 +#: aleksis/core/menus.py:196 aleksis/core/models.py:1099 #: aleksis/core/templates/core/group_type/list.html:8 #: aleksis/core/templates/core/group_type/list.html:9 msgid "Group types" msgstr "" -#: aleksis/core/menus.py:287 +#: aleksis/core/menus.py:207 msgid "Groups and child groups" msgstr "" -#: aleksis/core/menus.py:298 aleksis/core/models.py:510 +#: aleksis/core/menus.py:218 aleksis/core/models.py:535 #: aleksis/core/templates/core/additional_field/list.html:8 #: aleksis/core/templates/core/additional_field/list.html:9 msgid "Additional fields" msgstr "" -#: aleksis/core/menus.py:309 +#: aleksis/core/menus.py:229 msgid "Invite person" msgstr "" -#: aleksis/core/menus.py:322 +#: aleksis/core/menus.py:242 #: aleksis/core/templates/core/group/child_groups.html:7 #: aleksis/core/templates/core/group/child_groups.html:9 msgid "Assign child groups to groups" msgstr "" +#: aleksis/core/menus.py:254 +msgid "Stop impersonation" +msgstr "" + +#: aleksis/core/menus.py:263 +msgid "Account" +msgstr "" + +#: aleksis/core/menus.py:272 +#: aleksis/core/templates/dynamic_preferences/form.html:5 +msgid "Preferences" +msgstr "" + +#: aleksis/core/menus.py:281 +msgid "2FA" +msgstr "" + +#: aleksis/core/menus.py:289 +#: aleksis/core/templates/account/password_change.html:5 +#: aleksis/core/templates/account/password_change.html:6 +#: aleksis/core/templates/account/password_change.html:19 +#: aleksis/core/templates/account/password_reset_from_key.html:5 +#: aleksis/core/templates/account/password_reset_from_key.html:42 +#: aleksis/core/templates/account/password_reset_from_key.html:46 +#: aleksis/core/templates/account/password_reset_from_key_done.html:5 +#: aleksis/core/templates/account/password_reset_from_key_done.html:6 +msgid "Change password" +msgstr "" + +#: aleksis/core/menus.py:301 +msgid "Third-party accounts" +msgstr "" + +#: aleksis/core/menus.py:310 +#: aleksis/core/templates/oauth2_provider/authorized-tokens.html:5 +#: aleksis/core/templates/oauth2_provider/authorized-tokens.html:6 +msgid "Authorized applications" +msgstr "" + +#: aleksis/core/menus.py:320 +msgid "Logout" +msgstr "" + #: aleksis/core/mixins.py:511 msgid "Linked school term" msgstr "" -#: aleksis/core/models.py:71 +#: aleksis/core/models.py:75 msgid "Boolean (Yes/No)" msgstr "" -#: aleksis/core/models.py:72 +#: aleksis/core/models.py:76 msgid "Text (one line)" msgstr "" -#: aleksis/core/models.py:74 +#: aleksis/core/models.py:78 msgid "Date and time" msgstr "" -#: aleksis/core/models.py:75 +#: aleksis/core/models.py:79 msgid "Decimal number" msgstr "" -#: aleksis/core/models.py:76 aleksis/core/models.py:199 +#: aleksis/core/models.py:80 aleksis/core/models.py:203 msgid "E-mail address" msgstr "" -#: aleksis/core/models.py:77 +#: aleksis/core/models.py:81 msgid "Integer" msgstr "" -#: aleksis/core/models.py:78 +#: aleksis/core/models.py:82 msgid "IP address" msgstr "" -#: aleksis/core/models.py:79 +#: aleksis/core/models.py:83 msgid "Boolean or empty (Yes/No/Neither)" msgstr "" -#: aleksis/core/models.py:80 +#: aleksis/core/models.py:84 msgid "Text (multi-line)" msgstr "" -#: aleksis/core/models.py:82 +#: aleksis/core/models.py:86 msgid "URL / Link" msgstr "" -#: aleksis/core/models.py:94 aleksis/core/models.py:1024 +#: aleksis/core/models.py:98 aleksis/core/models.py:1068 msgid "Name" msgstr "" -#: aleksis/core/models.py:96 +#: aleksis/core/models.py:100 msgid "Start date" msgstr "" -#: aleksis/core/models.py:97 +#: aleksis/core/models.py:101 msgid "End date" msgstr "" -#: aleksis/core/models.py:116 +#: aleksis/core/models.py:120 msgid "The start date must be earlier than the end date." msgstr "" -#: aleksis/core/models.py:123 +#: aleksis/core/models.py:127 msgid "There is already a school term for this time or a part of this time." msgstr "" -#: aleksis/core/models.py:152 aleksis/core/models.py:973 +#: aleksis/core/models.py:156 aleksis/core/models.py:1017 msgid "Person" msgstr "" -#: aleksis/core/models.py:155 +#: aleksis/core/models.py:159 msgid "Can view address" msgstr "" -#: aleksis/core/models.py:156 +#: aleksis/core/models.py:160 msgid "Can view contact details" msgstr "" -#: aleksis/core/models.py:157 +#: aleksis/core/models.py:161 msgid "Can view photo" msgstr "" -#: aleksis/core/models.py:158 +#: aleksis/core/models.py:162 msgid "Can view avatar image" msgstr "" -#: aleksis/core/models.py:159 +#: aleksis/core/models.py:163 msgid "Can view persons groups" msgstr "" -#: aleksis/core/models.py:160 +#: aleksis/core/models.py:164 msgid "Can view personal details" msgstr "" -#: aleksis/core/models.py:170 +#: aleksis/core/models.py:174 msgid "female" msgstr "" -#: aleksis/core/models.py:170 +#: aleksis/core/models.py:174 msgid "male" msgstr "" -#: aleksis/core/models.py:178 aleksis/core/models.py:1227 +#: aleksis/core/models.py:182 aleksis/core/models.py:1271 msgid "Linked user" msgstr "" -#: aleksis/core/models.py:184 +#: aleksis/core/models.py:188 msgid "Additional name(s)" msgstr "" -#: aleksis/core/models.py:188 aleksis/core/models.py:479 +#: aleksis/core/models.py:192 aleksis/core/models.py:504 msgid "Short name" msgstr "" -#: aleksis/core/models.py:191 +#: aleksis/core/models.py:195 msgid "Street" msgstr "" -#: aleksis/core/models.py:192 +#: aleksis/core/models.py:196 msgid "Street number" msgstr "" -#: aleksis/core/models.py:193 +#: aleksis/core/models.py:197 msgid "Postal code" msgstr "" -#: aleksis/core/models.py:194 +#: aleksis/core/models.py:198 msgid "Place" msgstr "" -#: aleksis/core/models.py:196 aleksis/core/templates/core/person/full.html:172 +#: aleksis/core/models.py:200 aleksis/core/templates/core/person/full.html:160 msgid "Home phone" msgstr "" -#: aleksis/core/models.py:197 aleksis/core/templates/core/person/full.html:182 +#: aleksis/core/models.py:201 aleksis/core/templates/core/person/full.html:170 msgid "Mobile phone" msgstr "" -#: aleksis/core/models.py:201 +#: aleksis/core/models.py:205 msgid "Date of birth" msgstr "" -#: aleksis/core/models.py:202 +#: aleksis/core/models.py:206 msgid "Place of birth" msgstr "" -#: aleksis/core/models.py:203 +#: aleksis/core/models.py:207 msgid "Sex" msgstr "" -#: aleksis/core/models.py:210 aleksis/core/models.py:518 +#: aleksis/core/models.py:214 aleksis/core/models.py:543 msgid "This is an official photo, used for official documents and for internal use cases." msgstr "" -#: aleksis/core/models.py:215 aleksis/core/models.py:522 +#: aleksis/core/models.py:219 aleksis/core/models.py:547 msgid "Display picture / Avatar" msgstr "" -#: aleksis/core/models.py:218 aleksis/core/models.py:525 +#: aleksis/core/models.py:222 aleksis/core/models.py:550 msgid "This is a picture or an avatar for public display." msgstr "" -#: aleksis/core/models.py:223 aleksis/core/templates/core/person/full.html:239 +#: aleksis/core/models.py:227 aleksis/core/templates/core/person/full.html:235 msgid "Guardians / Parents" msgstr "" -#: aleksis/core/models.py:230 +#: aleksis/core/models.py:234 msgid "Primary group" msgstr "" -#: aleksis/core/models.py:233 aleksis/core/models.py:692 -#: aleksis/core/models.py:716 aleksis/core/models.py:801 -#: aleksis/core/models.py:1048 +#: aleksis/core/models.py:237 aleksis/core/models.py:717 +#: aleksis/core/models.py:741 aleksis/core/models.py:832 +#: aleksis/core/models.py:1092 msgid "Description" msgstr "" -#: aleksis/core/models.py:434 +#: aleksis/core/models.py:457 msgid "Title of field" msgstr "" -#: aleksis/core/models.py:436 +#: aleksis/core/models.py:459 msgid "Type of field" msgstr "" -#: aleksis/core/models.py:443 +#: aleksis/core/models.py:461 +msgid "Required" +msgstr "" + +#: aleksis/core/models.py:462 +msgid "Help text / description" +msgstr "" + +#: aleksis/core/models.py:468 msgid "Addtitional field for groups" msgstr "" -#: aleksis/core/models.py:444 +#: aleksis/core/models.py:469 msgid "Addtitional fields for groups" msgstr "" -#: aleksis/core/models.py:464 +#: aleksis/core/models.py:489 msgid "Can assign child groups to groups" msgstr "" -#: aleksis/core/models.py:465 +#: aleksis/core/models.py:490 msgid "Can view statistics about group." msgstr "" -#: aleksis/core/models.py:477 +#: aleksis/core/models.py:502 msgid "Long name" msgstr "" -#: aleksis/core/models.py:487 aleksis/core/templates/core/group/full.html:85 +#: aleksis/core/models.py:512 aleksis/core/templates/core/group/full.html:85 msgid "Members" msgstr "" -#: aleksis/core/models.py:490 aleksis/core/templates/core/group/full.html:82 +#: aleksis/core/models.py:515 aleksis/core/templates/core/group/full.html:82 msgid "Owners" msgstr "" -#: aleksis/core/models.py:497 aleksis/core/templates/core/group/full.html:55 +#: aleksis/core/models.py:522 aleksis/core/templates/core/group/full.html:55 msgid "Parent groups" msgstr "" -#: aleksis/core/models.py:505 +#: aleksis/core/models.py:530 msgid "Type of group" msgstr "" -#: aleksis/core/models.py:691 aleksis/core/models.py:715 -#: aleksis/core/models.py:800 +#: aleksis/core/models.py:716 aleksis/core/models.py:740 +#: aleksis/core/models.py:831 #: aleksis/core/templates/core/announcement/list.html:18 msgid "Title" msgstr "" -#: aleksis/core/models.py:694 +#: aleksis/core/models.py:719 msgid "Application" msgstr "" -#: aleksis/core/models.py:700 +#: aleksis/core/models.py:725 msgid "Activity" msgstr "" -#: aleksis/core/models.py:701 +#: aleksis/core/models.py:726 msgid "Activities" msgstr "" -#: aleksis/core/models.py:707 +#: aleksis/core/models.py:732 msgid "Sender" msgstr "" -#: aleksis/core/models.py:712 +#: aleksis/core/models.py:737 msgid "Recipient" msgstr "" -#: aleksis/core/models.py:717 aleksis/core/models.py:1025 +#: aleksis/core/models.py:742 aleksis/core/models.py:1069 msgid "Link" msgstr "" -#: aleksis/core/models.py:719 +#: aleksis/core/models.py:744 +msgid "Send notification at" +msgstr "" + +#: aleksis/core/models.py:746 msgid "Read" msgstr "" -#: aleksis/core/models.py:720 +#: aleksis/core/models.py:747 msgid "Sent" msgstr "" -#: aleksis/core/models.py:733 +#: aleksis/core/models.py:764 msgid "Notification" msgstr "" -#: aleksis/core/models.py:802 +#: aleksis/core/models.py:833 msgid "Link to detailed view" msgstr "" -#: aleksis/core/models.py:805 +#: aleksis/core/models.py:836 msgid "Date and time from when to show" msgstr "" -#: aleksis/core/models.py:808 +#: aleksis/core/models.py:839 msgid "Date and time until when to show" msgstr "" -#: aleksis/core/models.py:833 +#: aleksis/core/models.py:864 msgid "Announcement" msgstr "" -#: aleksis/core/models.py:871 +#: aleksis/core/models.py:902 msgid "Announcement recipient" msgstr "" -#: aleksis/core/models.py:872 +#: aleksis/core/models.py:903 msgid "Announcement recipients" msgstr "" -#: aleksis/core/models.py:894 +#: aleksis/core/models.py:925 msgid "Widget Title" msgstr "" -#: aleksis/core/models.py:895 +#: aleksis/core/models.py:926 msgid "Activate Widget" msgstr "" -#: aleksis/core/models.py:896 +#: aleksis/core/models.py:927 msgid "Widget is broken" msgstr "" -#: aleksis/core/models.py:899 +#: aleksis/core/models.py:930 msgid "Size on mobile devices" msgstr "" -#: aleksis/core/models.py:900 +#: aleksis/core/models.py:931 msgid "<= 600 px, 12 columns" msgstr "" -#: aleksis/core/models.py:905 +#: aleksis/core/models.py:936 msgid "Size on tablet devices" msgstr "" -#: aleksis/core/models.py:906 +#: aleksis/core/models.py:937 msgid "> 600 px, 12 columns" msgstr "" -#: aleksis/core/models.py:911 +#: aleksis/core/models.py:942 msgid "Size on desktop devices" msgstr "" -#: aleksis/core/models.py:912 +#: aleksis/core/models.py:943 msgid "> 992 px, 12 columns" msgstr "" -#: aleksis/core/models.py:917 +#: aleksis/core/models.py:948 msgid "Size on large desktop devices" msgstr "" -#: aleksis/core/models.py:918 +#: aleksis/core/models.py:949 msgid "> 1200 px>, 12 columns" msgstr "" -#: aleksis/core/models.py:949 +#: aleksis/core/models.py:980 msgid "Can edit default dashboard" msgstr "" -#: aleksis/core/models.py:950 +#: aleksis/core/models.py:981 msgid "Dashboard Widget" msgstr "" -#: aleksis/core/models.py:951 +#: aleksis/core/models.py:982 msgid "Dashboard Widgets" msgstr "" -#: aleksis/core/models.py:957 +#: aleksis/core/models.py:988 msgid "URL" msgstr "" -#: aleksis/core/models.py:958 +#: aleksis/core/models.py:989 msgid "Icon URL" msgstr "" -#: aleksis/core/models.py:964 +#: aleksis/core/models.py:995 msgid "External link widget" msgstr "" -#: aleksis/core/models.py:965 +#: aleksis/core/models.py:996 msgid "External link widgets" msgstr "" -#: aleksis/core/models.py:970 +#: aleksis/core/models.py:1002 +msgid "Content" +msgstr "" + +#: aleksis/core/models.py:1008 +msgid "Static content widget" +msgstr "" + +#: aleksis/core/models.py:1009 +msgid "Static content widgets" +msgstr "" + +#: aleksis/core/models.py:1014 msgid "Dashboard widget" msgstr "" -#: aleksis/core/models.py:975 +#: aleksis/core/models.py:1019 msgid "Order" msgstr "" -#: aleksis/core/models.py:976 +#: aleksis/core/models.py:1020 msgid "Part of the default dashboard" msgstr "" -#: aleksis/core/models.py:991 +#: aleksis/core/models.py:1035 msgid "Dashboard widget order" msgstr "" -#: aleksis/core/models.py:992 +#: aleksis/core/models.py:1036 msgid "Dashboard widget orders" msgstr "" -#: aleksis/core/models.py:998 +#: aleksis/core/models.py:1042 msgid "Menu ID" msgstr "" -#: aleksis/core/models.py:1011 +#: aleksis/core/models.py:1055 msgid "Custom menu" msgstr "" -#: aleksis/core/models.py:1012 +#: aleksis/core/models.py:1056 msgid "Custom menus" msgstr "" -#: aleksis/core/models.py:1022 +#: aleksis/core/models.py:1066 msgid "Menu" msgstr "" -#: aleksis/core/models.py:1026 aleksis/core/models.py:1274 +#: aleksis/core/models.py:1070 aleksis/core/models.py:1318 #: aleksis/core/templates/oauth2_provider/application/detail.html:26 msgid "Icon" msgstr "" -#: aleksis/core/models.py:1032 +#: aleksis/core/models.py:1076 msgid "Custom menu item" msgstr "" -#: aleksis/core/models.py:1033 +#: aleksis/core/models.py:1077 msgid "Custom menu items" msgstr "" -#: aleksis/core/models.py:1047 +#: aleksis/core/models.py:1091 msgid "Title of type" msgstr "" -#: aleksis/core/models.py:1054 aleksis/core/templates/core/group/full.html:47 +#: aleksis/core/models.py:1098 aleksis/core/templates/core/group/full.html:47 msgid "Group type" msgstr "" -#: aleksis/core/models.py:1068 +#: aleksis/core/models.py:1112 msgid "Can view system status" msgstr "" -#: aleksis/core/models.py:1069 +#: aleksis/core/models.py:1113 msgid "Can manage data" msgstr "" -#: aleksis/core/models.py:1070 +#: aleksis/core/models.py:1114 msgid "Can impersonate" msgstr "" -#: aleksis/core/models.py:1071 +#: aleksis/core/models.py:1115 msgid "Can use search" msgstr "" -#: aleksis/core/models.py:1072 +#: aleksis/core/models.py:1116 msgid "Can change site preferences" msgstr "" -#: aleksis/core/models.py:1073 +#: aleksis/core/models.py:1117 msgid "Can change person preferences" msgstr "" -#: aleksis/core/models.py:1074 +#: aleksis/core/models.py:1118 msgid "Can change group preferences" msgstr "" -#: aleksis/core/models.py:1075 +#: aleksis/core/models.py:1119 msgid "Can test PDF generation" msgstr "" -#: aleksis/core/models.py:1076 +#: aleksis/core/models.py:1120 msgid "Can invite persons" msgstr "" -#: aleksis/core/models.py:1112 +#: aleksis/core/models.py:1156 msgid "Related data check task" msgstr "" -#: aleksis/core/models.py:1120 +#: aleksis/core/models.py:1164 msgid "Issue solved" msgstr "" -#: aleksis/core/models.py:1121 +#: aleksis/core/models.py:1165 msgid "Notification sent" msgstr "" -#: aleksis/core/models.py:1134 +#: aleksis/core/models.py:1178 msgid "Data check result" msgstr "" -#: aleksis/core/models.py:1135 +#: aleksis/core/models.py:1179 msgid "Data check results" msgstr "" -#: aleksis/core/models.py:1137 +#: aleksis/core/models.py:1181 msgid "Can run data checks" msgstr "" -#: aleksis/core/models.py:1138 +#: aleksis/core/models.py:1182 msgid "Can solve data check problems" msgstr "" -#: aleksis/core/models.py:1145 +#: aleksis/core/models.py:1189 msgid "E-Mail address" msgstr "" -#: aleksis/core/models.py:1177 +#: aleksis/core/models.py:1221 msgid "Owner" msgstr "" -#: aleksis/core/models.py:1181 +#: aleksis/core/models.py:1225 msgid "File expires at" msgstr "" -#: aleksis/core/models.py:1183 +#: aleksis/core/models.py:1227 msgid "Generated HTML file" msgstr "" -#: aleksis/core/models.py:1185 +#: aleksis/core/models.py:1229 msgid "Generated PDF file" msgstr "" -#: aleksis/core/models.py:1192 +#: aleksis/core/models.py:1236 msgid "PDF file" msgstr "" -#: aleksis/core/models.py:1193 +#: aleksis/core/models.py:1237 msgid "PDF files" msgstr "" -#: aleksis/core/models.py:1198 +#: aleksis/core/models.py:1242 msgid "Task result" msgstr "" -#: aleksis/core/models.py:1201 +#: aleksis/core/models.py:1245 msgid "Task user" msgstr "" -#: aleksis/core/models.py:1213 +#: aleksis/core/models.py:1257 msgid "Task user assignment" msgstr "" -#: aleksis/core/models.py:1214 +#: aleksis/core/models.py:1258 msgid "Task user assignments" msgstr "" -#: aleksis/core/models.py:1230 +#: aleksis/core/models.py:1274 msgid "Additional attributes" msgstr "" -#: aleksis/core/models.py:1268 +#: aleksis/core/models.py:1312 msgid "Allowed scopes that clients can request" msgstr "" -#: aleksis/core/models.py:1278 +#: aleksis/core/models.py:1322 msgid "This image will be shown as icon in the authorization flow. It should be squared." msgstr "" @@ -1083,86 +1111,98 @@ msgid "Allow users to change their passwords" msgstr "" #: aleksis/core/preferences.py:279 -msgid "Enable signup" +msgid "Allow users to reset their passwords" msgstr "" #: aleksis/core/preferences.py:287 -msgid "Enable invitations" +msgid "Enable signup" msgstr "" #: aleksis/core/preferences.py:295 -msgid "Length of invite code. (Default 3: abcde-acbde-abcde)" +msgid "Regular expression for allowed usernames" msgstr "" #: aleksis/core/preferences.py:303 +msgid "Enable invitations" +msgstr "" + +#: aleksis/core/preferences.py:311 +msgid "Length of invite code. (Default 3: abcde-acbde-abcde)" +msgstr "" + +#: aleksis/core/preferences.py:319 msgid "Size of packets. (Default 5: abcde)" msgstr "" -#: aleksis/core/preferences.py:314 +#: aleksis/core/preferences.py:330 msgid "Allowed Grant Flows for OAuth applications" msgstr "" -#: aleksis/core/preferences.py:328 +#: aleksis/core/preferences.py:344 msgid "Available languages" msgstr "" -#: aleksis/core/preferences.py:341 +#: aleksis/core/preferences.py:357 msgid "Send emails if data checks detect problems" msgstr "" -#: aleksis/core/preferences.py:352 +#: aleksis/core/preferences.py:368 msgid "Email recipients for data checks problem emails" msgstr "" -#: aleksis/core/preferences.py:363 +#: aleksis/core/preferences.py:379 msgid "Email recipient groups for data checks problem emails" msgstr "" -#: aleksis/core/preferences.py:372 +#: aleksis/core/preferences.py:388 msgid "Show dashboard to users without login" msgstr "" -#: aleksis/core/preferences.py:381 +#: aleksis/core/preferences.py:397 msgid "Allow users to edit their dashboard" msgstr "" -#: aleksis/core/preferences.py:392 +#: aleksis/core/preferences.py:408 msgid "Fields on person model which are editable by themselves." msgstr "" -#: aleksis/core/preferences.py:407 +#: aleksis/core/preferences.py:423 msgid "Editable fields on person model which should trigger a notification on change" msgstr "" -#: aleksis/core/preferences.py:421 +#: aleksis/core/preferences.py:437 msgid "Contact for notification if a person changes their data" msgstr "" -#: aleksis/core/preferences.py:432 +#: aleksis/core/preferences.py:448 +msgid "Prefer personal photos over avatars" +msgstr "" + +#: aleksis/core/preferences.py:458 msgid "PDF file expiration duration" msgstr "" -#: aleksis/core/preferences.py:433 +#: aleksis/core/preferences.py:459 msgid "in minutes" msgstr "" -#: aleksis/core/preferences.py:443 +#: aleksis/core/preferences.py:469 msgid "Automatically update the dashboard and its widgets" msgstr "" -#: aleksis/core/preferences.py:453 +#: aleksis/core/preferences.py:479 msgid "Automatically update the dashboard and its widgets sitewide" msgstr "" -#: aleksis/core/preferences.py:463 +#: aleksis/core/preferences.py:489 msgid "Country for phone number parsing" msgstr "" -#: aleksis/core/settings.py:529 +#: aleksis/core/settings.py:540 msgid "English" msgstr "" -#: aleksis/core/settings.py:530 +#: aleksis/core/settings.py:541 msgid "German" msgstr "" @@ -1170,7 +1210,7 @@ msgstr "" #: aleksis/core/templates/core/announcement/list.html:36 #: aleksis/core/templates/core/group/full.html:24 #: aleksis/core/templates/core/person/full.html:26 -#: aleksis/core/templates/core/person/full.html:98 +#: aleksis/core/templates/core/person/full.html:86 #: aleksis/core/templates/oauth2_provider/application/detail.html:17 msgid "Edit" msgstr "" @@ -1188,7 +1228,7 @@ msgstr "" #: aleksis/core/templates/core/group/full.html:31 #: aleksis/core/templates/core/pages/delete.html:22 #: aleksis/core/templates/core/person/full.html:33 -#: aleksis/core/templates/core/person/full.html:105 +#: aleksis/core/templates/core/person/full.html:93 #: aleksis/core/templates/oauth2_provider/application/detail.html:21 msgid "Delete" msgstr "" @@ -1235,6 +1275,10 @@ msgid "" " " msgstr "" +#: aleksis/core/templates/500.html:21 +msgid "Retry" +msgstr "" + #: aleksis/core/templates/503.html:10 msgid "" "The maintenance mode is currently enabled. Please try again\n" @@ -1493,19 +1537,15 @@ msgstr "" msgid "There are no announcements." msgstr "" -#: aleksis/core/templates/core/base.html:78 -msgid "Logged in as" -msgstr "" - -#: aleksis/core/templates/core/base.html:179 +#: aleksis/core/templates/core/base.html:213 msgid "About AlekSIS® — The Free School Information System" msgstr "" -#: aleksis/core/templates/core/base.html:187 +#: aleksis/core/templates/core/base.html:221 msgid "Imprint" msgstr "" -#: aleksis/core/templates/core/base.html:195 +#: aleksis/core/templates/core/base.html:229 msgid "Privacy Policy" msgstr "" @@ -1726,7 +1766,7 @@ msgstr "" #: aleksis/core/templates/core/group/full.html:38 #: aleksis/core/templates/core/person/full.html:40 -#: aleksis/core/templates/core/person/full.html:112 +#: aleksis/core/templates/core/person/full.html:100 msgid "Change preferences" msgstr "" @@ -1916,83 +1956,83 @@ msgstr "" msgid "System checks" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:21 +#: aleksis/core/templates/core/pages/system_status.html:22 msgid "Maintenance mode enabled" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:23 +#: aleksis/core/templates/core/pages/system_status.html:24 msgid "" "\n" " Only admin and visitors from internal IPs can access thesite.\n" " " msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:34 +#: aleksis/core/templates/core/pages/system_status.html:36 msgid "Maintenance mode disabled" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:35 +#: aleksis/core/templates/core/pages/system_status.html:37 msgid "Everyone can access the site." msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:45 +#: aleksis/core/templates/core/pages/system_status.html:47 msgid "Debug mode enabled" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:47 +#: aleksis/core/templates/core/pages/system_status.html:49 msgid "" "\n" " The web server throws back debug information on errors. Do not use in production!\n" " " msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:54 +#: aleksis/core/templates/core/pages/system_status.html:56 msgid "Debug mode disabled" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:56 +#: aleksis/core/templates/core/pages/system_status.html:58 msgid "" "\n" " Debug mode is disabled. Default error pages are displayed on errors.\n" " " msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:69 +#: aleksis/core/templates/core/pages/system_status.html:71 msgid "System health checks" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:75 +#: aleksis/core/templates/core/pages/system_status.html:77 msgid "Service" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:76 -#: aleksis/core/templates/core/pages/system_status.html:115 +#: aleksis/core/templates/core/pages/system_status.html:78 +#: aleksis/core/templates/core/pages/system_status.html:119 msgid "Status" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:77 +#: aleksis/core/templates/core/pages/system_status.html:79 msgid "Time taken" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:96 +#: aleksis/core/templates/core/pages/system_status.html:100 msgid "seconds" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:107 +#: aleksis/core/templates/core/pages/system_status.html:111 msgid "Celery task results" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:112 +#: aleksis/core/templates/core/pages/system_status.html:116 #: aleksis/core/templates/templated_email/celery_failure.email:9 #: aleksis/core/templates/templated_email/celery_failure.email:28 msgid "Task" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:113 +#: aleksis/core/templates/core/pages/system_status.html:117 msgid "ID" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:114 +#: aleksis/core/templates/core/pages/system_status.html:118 msgid "Date done" msgstr "" @@ -2033,6 +2073,18 @@ msgid "" " " msgstr "" +#: aleksis/core/templates/core/partials/avatar_content.html:14 +#: aleksis/core/templates/core/partials/avatar_content.html:15 +#: aleksis/core/templates/core/person/full.html:213 +#: aleksis/core/templates/core/person/full.html:214 +msgid "Avatar" +msgstr "" + +#: aleksis/core/templates/core/partials/avatar_content.html:19 +#: aleksis/core/templates/core/partials/avatar_content.html:20 +msgid "Identicon" +msgstr "" + #: aleksis/core/templates/core/partials/crud_events.html:15 msgid "Changed by" msgstr "" @@ -2123,24 +2175,24 @@ msgid "Edit person" msgstr "" #: aleksis/core/templates/core/person/full.html:47 -#: aleksis/core/templates/core/person/full.html:119 +#: aleksis/core/templates/core/person/full.html:107 msgid "Impersonate" msgstr "" #: aleksis/core/templates/core/person/full.html:54 -#: aleksis/core/templates/core/person/full.html:126 +#: aleksis/core/templates/core/person/full.html:114 msgid "Invite user" msgstr "" -#: aleksis/core/templates/core/person/full.html:133 +#: aleksis/core/templates/core/person/full.html:121 msgid "Contact details" msgstr "" -#: aleksis/core/templates/core/person/full.html:224 +#: aleksis/core/templates/core/person/full.html:220 msgid "This person didn't upload a personal photo." msgstr "" -#: aleksis/core/templates/core/person/full.html:232 +#: aleksis/core/templates/core/person/full.html:228 msgid "Children" msgstr "" @@ -2345,13 +2397,11 @@ msgstr "" msgid "Network error" msgstr "" -#: aleksis/core/templates/offline.html:8 -msgid "" -"No internet\n" -" connection." +#: aleksis/core/templates/offline.html:10 +msgid "No internet connection." msgstr "" -#: aleksis/core/templates/offline.html:12 +#: aleksis/core/templates/offline.html:14 msgid "" "\n" " There was an error accessing this page. You probably don't have an internet connection. Check to see if your WiFi\n" @@ -2595,7 +2645,7 @@ msgstr "" #: aleksis/core/templates/two_factor/_base_focus.html:6 #: aleksis/core/templates/two_factor/core/otp_required.html:22 #: aleksis/core/templates/two_factor/core/setup.html:5 -#: aleksis/core/templates/two_factor/profile/profile.html:87 +#: aleksis/core/templates/two_factor/profile/profile.html:88 msgid "Enable Two-Factor Authentication" msgstr "" @@ -2699,15 +2749,15 @@ msgstr "" msgid "Or, alternatively, use one of your backup phones:" msgstr "" -#: aleksis/core/templates/two_factor/core/login.html:121 +#: aleksis/core/templates/two_factor/core/login.html:122 msgid "As a last resort, you can use a backup token:" msgstr "" -#: aleksis/core/templates/two_factor/core/login.html:124 +#: aleksis/core/templates/two_factor/core/login.html:125 msgid "Use Backup Token" msgstr "" -#: aleksis/core/templates/two_factor/core/login.html:135 +#: aleksis/core/templates/two_factor/core/login.html:136 msgid "Use alternative login options" msgstr "" @@ -2944,11 +2994,11 @@ msgid "" " " msgstr "" -#: aleksis/core/util/notifications.py:63 +#: aleksis/core/util/notifications.py:64 msgid "E-Mail" msgstr "" -#: aleksis/core/util/notifications.py:64 +#: aleksis/core/util/notifications.py:65 msgid "SMS" msgstr "" @@ -2972,157 +3022,157 @@ msgstr "" msgid "Download PDF" msgstr "" -#: aleksis/core/views.py:285 +#: aleksis/core/views.py:289 msgid "The school term has been created." msgstr "" -#: aleksis/core/views.py:297 +#: aleksis/core/views.py:301 msgid "The school term has been saved." msgstr "" -#: aleksis/core/views.py:417 +#: aleksis/core/views.py:421 msgid "The child groups were successfully saved." msgstr "" -#: aleksis/core/views.py:436 aleksis/core/views.py:446 +#: aleksis/core/views.py:440 aleksis/core/views.py:450 msgid "The person has been saved." msgstr "" -#: aleksis/core/views.py:496 +#: aleksis/core/views.py:500 msgid "The group has been saved." msgstr "" -#: aleksis/core/views.py:593 +#: aleksis/core/views.py:597 msgid "The announcement has been saved." msgstr "" -#: aleksis/core/views.py:609 +#: aleksis/core/views.py:613 msgid "The announcement has been deleted." msgstr "" -#: aleksis/core/views.py:677 +#: aleksis/core/views.py:681 msgid "The requested preference registry does not exist" msgstr "" -#: aleksis/core/views.py:696 +#: aleksis/core/views.py:700 msgid "The preferences have been saved successfully." msgstr "" -#: aleksis/core/views.py:720 +#: aleksis/core/views.py:724 msgid "The person has been deleted." msgstr "" -#: aleksis/core/views.py:734 +#: aleksis/core/views.py:738 msgid "The group has been deleted." msgstr "" -#: aleksis/core/views.py:766 +#: aleksis/core/views.py:770 msgid "The additional_field has been saved." msgstr "" -#: aleksis/core/views.py:800 +#: aleksis/core/views.py:804 msgid "The additional field has been deleted." msgstr "" -#: aleksis/core/views.py:825 +#: aleksis/core/views.py:829 msgid "The group type has been saved." msgstr "" -#: aleksis/core/views.py:855 +#: aleksis/core/views.py:859 msgid "The group type has been deleted." msgstr "" -#: aleksis/core/views.py:888 +#: aleksis/core/views.py:892 msgid "Progress: Run data checks" msgstr "" -#: aleksis/core/views.py:889 +#: aleksis/core/views.py:893 msgid "Run data checks …" msgstr "" -#: aleksis/core/views.py:890 +#: aleksis/core/views.py:894 msgid "The data checks were run successfully." msgstr "" -#: aleksis/core/views.py:891 +#: aleksis/core/views.py:895 msgid "There was a problem while running data checks." msgstr "" -#: aleksis/core/views.py:907 +#: aleksis/core/views.py:911 #, python-brace-format msgid "The solve option '{solve_option_obj.verbose_name}' " msgstr "" -#: aleksis/core/views.py:917 +#: aleksis/core/views.py:921 msgid "The requested solve option does not exist" msgstr "" -#: aleksis/core/views.py:949 +#: aleksis/core/views.py:953 msgid "The dashboard widget has been saved." msgstr "" -#: aleksis/core/views.py:979 +#: aleksis/core/views.py:983 msgid "The dashboard widget has been created." msgstr "" -#: aleksis/core/views.py:989 +#: aleksis/core/views.py:993 msgid "The dashboard widget has been deleted." msgstr "" -#: aleksis/core/views.py:1060 +#: aleksis/core/views.py:1064 msgid "Your dashboard configuration has been saved successfully." msgstr "" -#: aleksis/core/views.py:1062 +#: aleksis/core/views.py:1066 msgid "The configuration of the default dashboard has been saved successfully." msgstr "" -#: aleksis/core/views.py:1138 +#: aleksis/core/views.py:1142 #, python-brace-format msgid "The invitation was successfully created. The invitation code is {code}" msgstr "" -#: aleksis/core/views.py:1229 +#: aleksis/core/views.py:1233 msgid "We have successfully assigned the permissions." msgstr "" -#: aleksis/core/views.py:1239 +#: aleksis/core/views.py:1243 msgid "The global user permission has been deleted." msgstr "" -#: aleksis/core/views.py:1249 +#: aleksis/core/views.py:1253 msgid "The global group permission has been deleted." msgstr "" -#: aleksis/core/views.py:1259 +#: aleksis/core/views.py:1263 msgid "The object user permission has been deleted." msgstr "" -#: aleksis/core/views.py:1269 +#: aleksis/core/views.py:1273 msgid "The object group permission has been deleted." msgstr "" -#: aleksis/core/views.py:1337 +#: aleksis/core/views.py:1341 msgid "The requested PDF file does not exist" msgstr "" -#: aleksis/core/views.py:1346 aleksis/core/views.py:1350 +#: aleksis/core/views.py:1350 aleksis/core/views.py:1354 msgid "The requested task does not exist or is not accessible" msgstr "" -#: aleksis/core/views.py:1388 +#: aleksis/core/views.py:1406 msgid "The third-party account could not be disconnected because it is the only login method available." msgstr "" -#: aleksis/core/views.py:1395 +#: aleksis/core/views.py:1413 msgid "The third-party account has been successfully disconnected." msgstr "" -#: aleksis/core/views.py:1466 +#: aleksis/core/views.py:1484 msgid "Person was invited successfully and an email with further instructions has been send to them." msgstr "" -#: aleksis/core/views.py:1477 +#: aleksis/core/views.py:1495 msgid "Person was already invited." msgstr "" diff --git a/aleksis/core/locale/nb_NO/LC_MESSAGES/djangojs.po b/aleksis/core/locale/nb_NO/LC_MESSAGES/djangojs.po index dfec73c5c894d3d686092593be9c21a811cd0535..f3df4c3fc6d2848a739ddd1faac44cb9048c97b2 100644 --- a/aleksis/core/locale/nb_NO/LC_MESSAGES/djangojs.po +++ b/aleksis/core/locale/nb_NO/LC_MESSAGES/djangojs.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-02-08 23:16+0000\n" +"POT-Creation-Date: 2022-03-23 11:20+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -29,6 +29,6 @@ msgstr "" msgid "OK" msgstr "" -#: aleksis/core/static/js/main.js:191 +#: aleksis/core/static/js/main.js:195 msgid "This page may contain outdated information since there is no internet connection." msgstr "" diff --git a/aleksis/core/locale/tr_TR/LC_MESSAGES/django.po b/aleksis/core/locale/tr_TR/LC_MESSAGES/django.po index 2973720cd0f3f85a06ca9d68c21a2c09a92961a5..d5a2d5f0647e2460b313fb20d6cca3d9059a3d8b 100644 --- a/aleksis/core/locale/tr_TR/LC_MESSAGES/django.po +++ b/aleksis/core/locale/tr_TR/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: AlekSIS (School Information System) 0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-02-08 23:16+0000\n" +"POT-Creation-Date: 2022-03-23 11:19+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -37,10 +37,10 @@ msgstr "" msgid "Home and mobile phone" msgstr "" -#: aleksis/core/apps.py:171 aleksis/core/forms.py:220 aleksis/core/menus.py:265 -#: aleksis/core/models.py:462 aleksis/core/templates/core/group/list.html:8 +#: aleksis/core/apps.py:171 aleksis/core/forms.py:220 aleksis/core/menus.py:185 +#: aleksis/core/models.py:487 aleksis/core/templates/core/group/list.html:8 #: aleksis/core/templates/core/group/list.html:9 -#: aleksis/core/templates/core/person/full.html:250 +#: aleksis/core/templates/core/person/full.html:246 msgid "Groups" msgstr "" @@ -65,8 +65,8 @@ msgstr "" msgid "The DashboardWidget was reported broken automatically." msgstr "" -#: aleksis/core/filters.py:42 aleksis/core/templates/core/base.html:105 -#: aleksis/core/templates/core/base.html:106 +#: aleksis/core/filters.py:42 aleksis/core/templates/core/base.html:139 +#: aleksis/core/templates/core/base.html:140 #: aleksis/core/templates/core/group/list.html:20 #: aleksis/core/templates/core/person/list.html:24 #: aleksis/core/templates/search/search.html:7 @@ -90,11 +90,11 @@ msgstr "" msgid "Content type" msgstr "" -#: aleksis/core/filters.py:113 aleksis/core/models.py:688 +#: aleksis/core/filters.py:113 aleksis/core/models.py:713 msgid "User" msgstr "" -#: aleksis/core/filters.py:135 aleksis/core/models.py:461 +#: aleksis/core/filters.py:135 aleksis/core/models.py:486 msgid "Group" msgstr "" @@ -130,7 +130,7 @@ msgstr "" msgid "This username is already in use." msgstr "" -#: aleksis/core/forms.py:153 aleksis/core/models.py:130 +#: aleksis/core/forms.py:153 aleksis/core/models.py:134 msgid "School term" msgstr "" @@ -139,7 +139,7 @@ msgid "Common data" msgstr "" #: aleksis/core/forms.py:155 aleksis/core/forms.py:207 -#: aleksis/core/menus.py:254 aleksis/core/models.py:153 +#: aleksis/core/menus.py:174 aleksis/core/models.py:157 #: aleksis/core/templates/core/person/list.html:8 #: aleksis/core/templates/core/person/list.html:9 msgid "Persons" @@ -149,18 +149,18 @@ msgstr "" msgid "Additional data" msgstr "" -#: aleksis/core/forms.py:157 aleksis/core/models.py:206 -#: aleksis/core/models.py:514 +#: aleksis/core/forms.py:157 aleksis/core/models.py:210 +#: aleksis/core/models.py:539 msgid "Photo" msgstr "" #: aleksis/core/forms.py:199 aleksis/core/forms.py:202 -#: aleksis/core/models.py:73 +#: aleksis/core/models.py:77 msgid "Date" msgstr "" #: aleksis/core/forms.py:200 aleksis/core/forms.py:203 -#: aleksis/core/models.py:81 +#: aleksis/core/models.py:85 msgid "Time" msgstr "" @@ -196,11 +196,11 @@ msgstr "" msgid "Please enter your invitation code." msgstr "" -#: aleksis/core/forms.py:418 aleksis/core/models.py:181 +#: aleksis/core/forms.py:418 aleksis/core/models.py:185 msgid "First name" msgstr "" -#: aleksis/core/forms.py:419 aleksis/core/models.py:182 +#: aleksis/core/forms.py:419 aleksis/core/models.py:186 msgid "Last name" msgstr "" @@ -248,7 +248,15 @@ msgstr "" msgid "Password (again)" msgstr "" -#: aleksis/core/forms.py:775 +#: aleksis/core/forms.py:728 +msgid "The selected action does not exist." +msgstr "" + +#: aleksis/core/forms.py:739 +msgid "You do not have permission to run {} on all selected objects." +msgstr "" + +#: aleksis/core/forms.py:795 msgid "No valid selection." msgstr "" @@ -291,678 +299,698 @@ msgstr "" msgid "Dashboard" msgstr "" -#: aleksis/core/menus.py:41 aleksis/core/models.py:734 -#: aleksis/core/preferences.py:29 +#: aleksis/core/menus.py:41 aleksis/core/models.py:765 +#: aleksis/core/preferences.py:29 aleksis/core/templates/core/base.html:81 #: aleksis/core/templates/core/notifications.html:4 #: aleksis/core/templates/core/notifications.html:5 msgid "Notifications" msgstr "" #: aleksis/core/menus.py:53 -msgid "Account" -msgstr "" - -#: aleksis/core/menus.py:60 -msgid "Stop impersonation" -msgstr "" - -#: aleksis/core/menus.py:69 aleksis/core/templates/core/base.html:80 -msgid "Logout" -msgstr "" - -#: aleksis/core/menus.py:75 -msgid "2FA" -msgstr "" - -#: aleksis/core/menus.py:83 -#: aleksis/core/templates/account/password_change.html:5 -#: aleksis/core/templates/account/password_change.html:6 -#: aleksis/core/templates/account/password_change.html:19 -#: aleksis/core/templates/account/password_reset_from_key.html:5 -#: aleksis/core/templates/account/password_reset_from_key.html:42 -#: aleksis/core/templates/account/password_reset_from_key.html:46 -#: aleksis/core/templates/account/password_reset_from_key_done.html:5 -#: aleksis/core/templates/account/password_reset_from_key_done.html:6 -msgid "Change password" -msgstr "" - -#: aleksis/core/menus.py:95 -msgid "Me" -msgstr "" - -#: aleksis/core/menus.py:104 -#: aleksis/core/templates/dynamic_preferences/form.html:5 -msgid "Preferences" -msgstr "" - -#: aleksis/core/menus.py:113 -msgid "Third-party accounts" -msgstr "" - -#: aleksis/core/menus.py:122 -#: aleksis/core/templates/oauth2_provider/authorized-tokens.html:5 -#: aleksis/core/templates/oauth2_provider/authorized-tokens.html:6 -msgid "Authorized applications" -msgstr "" - -#: aleksis/core/menus.py:133 msgid "Admin" msgstr "" -#: aleksis/core/menus.py:141 aleksis/core/models.py:834 +#: aleksis/core/menus.py:61 aleksis/core/models.py:865 #: aleksis/core/templates/core/announcement/list.html:7 #: aleksis/core/templates/core/announcement/list.html:8 msgid "Announcements" msgstr "" -#: aleksis/core/menus.py:152 aleksis/core/models.py:131 +#: aleksis/core/menus.py:72 aleksis/core/models.py:135 #: aleksis/core/templates/core/school_term/list.html:8 #: aleksis/core/templates/core/school_term/list.html:9 msgid "School terms" msgstr "" -#: aleksis/core/menus.py:163 +#: aleksis/core/menus.py:83 #: aleksis/core/templates/core/dashboard_widget/list.html:8 #: aleksis/core/templates/core/dashboard_widget/list.html:9 msgid "Dashboard widgets" msgstr "" -#: aleksis/core/menus.py:174 +#: aleksis/core/menus.py:94 #: aleksis/core/templates/core/management/data_management.html:6 #: aleksis/core/templates/core/management/data_management.html:7 msgid "Data management" msgstr "" -#: aleksis/core/menus.py:185 +#: aleksis/core/menus.py:105 #: aleksis/core/templates/core/pages/system_status.html:5 #: aleksis/core/templates/core/pages/system_status.html:7 msgid "System status" msgstr "" -#: aleksis/core/menus.py:196 +#: aleksis/core/menus.py:116 msgid "Configuration" msgstr "" -#: aleksis/core/menus.py:207 aleksis/core/templates/core/data_check/list.html:9 +#: aleksis/core/menus.py:127 aleksis/core/templates/core/data_check/list.html:9 #: aleksis/core/templates/core/data_check/list.html:10 msgid "Data checks" msgstr "" -#: aleksis/core/menus.py:213 aleksis/core/templates/core/perms/list.html:13 +#: aleksis/core/menus.py:133 aleksis/core/templates/core/perms/list.html:13 #: aleksis/core/templates/core/perms/list.html:14 msgid "Manage permissions" msgstr "" -#: aleksis/core/menus.py:224 +#: aleksis/core/menus.py:144 msgid "Backend Admin" msgstr "" -#: aleksis/core/menus.py:232 +#: aleksis/core/menus.py:152 #: aleksis/core/templates/oauth2_provider/application/list.html:5 #: aleksis/core/templates/oauth2_provider/application/list.html:6 msgid "OAuth2 Applications" msgstr "" -#: aleksis/core/menus.py:245 +#: aleksis/core/menus.py:165 msgid "People" msgstr "" -#: aleksis/core/menus.py:276 aleksis/core/models.py:1055 +#: aleksis/core/menus.py:196 aleksis/core/models.py:1099 #: aleksis/core/templates/core/group_type/list.html:8 #: aleksis/core/templates/core/group_type/list.html:9 msgid "Group types" msgstr "" -#: aleksis/core/menus.py:287 +#: aleksis/core/menus.py:207 msgid "Groups and child groups" msgstr "" -#: aleksis/core/menus.py:298 aleksis/core/models.py:510 +#: aleksis/core/menus.py:218 aleksis/core/models.py:535 #: aleksis/core/templates/core/additional_field/list.html:8 #: aleksis/core/templates/core/additional_field/list.html:9 msgid "Additional fields" msgstr "" -#: aleksis/core/menus.py:309 +#: aleksis/core/menus.py:229 msgid "Invite person" msgstr "" -#: aleksis/core/menus.py:322 +#: aleksis/core/menus.py:242 #: aleksis/core/templates/core/group/child_groups.html:7 #: aleksis/core/templates/core/group/child_groups.html:9 msgid "Assign child groups to groups" msgstr "" +#: aleksis/core/menus.py:254 +msgid "Stop impersonation" +msgstr "" + +#: aleksis/core/menus.py:263 +msgid "Account" +msgstr "" + +#: aleksis/core/menus.py:272 +#: aleksis/core/templates/dynamic_preferences/form.html:5 +msgid "Preferences" +msgstr "" + +#: aleksis/core/menus.py:281 +msgid "2FA" +msgstr "" + +#: aleksis/core/menus.py:289 +#: aleksis/core/templates/account/password_change.html:5 +#: aleksis/core/templates/account/password_change.html:6 +#: aleksis/core/templates/account/password_change.html:19 +#: aleksis/core/templates/account/password_reset_from_key.html:5 +#: aleksis/core/templates/account/password_reset_from_key.html:42 +#: aleksis/core/templates/account/password_reset_from_key.html:46 +#: aleksis/core/templates/account/password_reset_from_key_done.html:5 +#: aleksis/core/templates/account/password_reset_from_key_done.html:6 +msgid "Change password" +msgstr "" + +#: aleksis/core/menus.py:301 +msgid "Third-party accounts" +msgstr "" + +#: aleksis/core/menus.py:310 +#: aleksis/core/templates/oauth2_provider/authorized-tokens.html:5 +#: aleksis/core/templates/oauth2_provider/authorized-tokens.html:6 +msgid "Authorized applications" +msgstr "" + +#: aleksis/core/menus.py:320 +msgid "Logout" +msgstr "" + #: aleksis/core/mixins.py:511 msgid "Linked school term" msgstr "" -#: aleksis/core/models.py:71 +#: aleksis/core/models.py:75 msgid "Boolean (Yes/No)" msgstr "" -#: aleksis/core/models.py:72 +#: aleksis/core/models.py:76 msgid "Text (one line)" msgstr "" -#: aleksis/core/models.py:74 +#: aleksis/core/models.py:78 msgid "Date and time" msgstr "" -#: aleksis/core/models.py:75 +#: aleksis/core/models.py:79 msgid "Decimal number" msgstr "" -#: aleksis/core/models.py:76 aleksis/core/models.py:199 +#: aleksis/core/models.py:80 aleksis/core/models.py:203 msgid "E-mail address" msgstr "" -#: aleksis/core/models.py:77 +#: aleksis/core/models.py:81 msgid "Integer" msgstr "" -#: aleksis/core/models.py:78 +#: aleksis/core/models.py:82 msgid "IP address" msgstr "" -#: aleksis/core/models.py:79 +#: aleksis/core/models.py:83 msgid "Boolean or empty (Yes/No/Neither)" msgstr "" -#: aleksis/core/models.py:80 +#: aleksis/core/models.py:84 msgid "Text (multi-line)" msgstr "" -#: aleksis/core/models.py:82 +#: aleksis/core/models.py:86 msgid "URL / Link" msgstr "" -#: aleksis/core/models.py:94 aleksis/core/models.py:1024 +#: aleksis/core/models.py:98 aleksis/core/models.py:1068 msgid "Name" msgstr "" -#: aleksis/core/models.py:96 +#: aleksis/core/models.py:100 msgid "Start date" msgstr "" -#: aleksis/core/models.py:97 +#: aleksis/core/models.py:101 msgid "End date" msgstr "" -#: aleksis/core/models.py:116 +#: aleksis/core/models.py:120 msgid "The start date must be earlier than the end date." msgstr "" -#: aleksis/core/models.py:123 +#: aleksis/core/models.py:127 msgid "There is already a school term for this time or a part of this time." msgstr "" -#: aleksis/core/models.py:152 aleksis/core/models.py:973 +#: aleksis/core/models.py:156 aleksis/core/models.py:1017 msgid "Person" msgstr "" -#: aleksis/core/models.py:155 +#: aleksis/core/models.py:159 msgid "Can view address" msgstr "" -#: aleksis/core/models.py:156 +#: aleksis/core/models.py:160 msgid "Can view contact details" msgstr "" -#: aleksis/core/models.py:157 +#: aleksis/core/models.py:161 msgid "Can view photo" msgstr "" -#: aleksis/core/models.py:158 +#: aleksis/core/models.py:162 msgid "Can view avatar image" msgstr "" -#: aleksis/core/models.py:159 +#: aleksis/core/models.py:163 msgid "Can view persons groups" msgstr "" -#: aleksis/core/models.py:160 +#: aleksis/core/models.py:164 msgid "Can view personal details" msgstr "" -#: aleksis/core/models.py:170 +#: aleksis/core/models.py:174 msgid "female" msgstr "" -#: aleksis/core/models.py:170 +#: aleksis/core/models.py:174 msgid "male" msgstr "" -#: aleksis/core/models.py:178 aleksis/core/models.py:1227 +#: aleksis/core/models.py:182 aleksis/core/models.py:1271 msgid "Linked user" msgstr "" -#: aleksis/core/models.py:184 +#: aleksis/core/models.py:188 msgid "Additional name(s)" msgstr "" -#: aleksis/core/models.py:188 aleksis/core/models.py:479 +#: aleksis/core/models.py:192 aleksis/core/models.py:504 msgid "Short name" msgstr "" -#: aleksis/core/models.py:191 +#: aleksis/core/models.py:195 msgid "Street" msgstr "" -#: aleksis/core/models.py:192 +#: aleksis/core/models.py:196 msgid "Street number" msgstr "" -#: aleksis/core/models.py:193 +#: aleksis/core/models.py:197 msgid "Postal code" msgstr "" -#: aleksis/core/models.py:194 +#: aleksis/core/models.py:198 msgid "Place" msgstr "" -#: aleksis/core/models.py:196 aleksis/core/templates/core/person/full.html:172 +#: aleksis/core/models.py:200 aleksis/core/templates/core/person/full.html:160 msgid "Home phone" msgstr "" -#: aleksis/core/models.py:197 aleksis/core/templates/core/person/full.html:182 +#: aleksis/core/models.py:201 aleksis/core/templates/core/person/full.html:170 msgid "Mobile phone" msgstr "" -#: aleksis/core/models.py:201 +#: aleksis/core/models.py:205 msgid "Date of birth" msgstr "" -#: aleksis/core/models.py:202 +#: aleksis/core/models.py:206 msgid "Place of birth" msgstr "" -#: aleksis/core/models.py:203 +#: aleksis/core/models.py:207 msgid "Sex" msgstr "" -#: aleksis/core/models.py:210 aleksis/core/models.py:518 +#: aleksis/core/models.py:214 aleksis/core/models.py:543 msgid "This is an official photo, used for official documents and for internal use cases." msgstr "" -#: aleksis/core/models.py:215 aleksis/core/models.py:522 +#: aleksis/core/models.py:219 aleksis/core/models.py:547 msgid "Display picture / Avatar" msgstr "" -#: aleksis/core/models.py:218 aleksis/core/models.py:525 +#: aleksis/core/models.py:222 aleksis/core/models.py:550 msgid "This is a picture or an avatar for public display." msgstr "" -#: aleksis/core/models.py:223 aleksis/core/templates/core/person/full.html:239 +#: aleksis/core/models.py:227 aleksis/core/templates/core/person/full.html:235 msgid "Guardians / Parents" msgstr "" -#: aleksis/core/models.py:230 +#: aleksis/core/models.py:234 msgid "Primary group" msgstr "" -#: aleksis/core/models.py:233 aleksis/core/models.py:692 -#: aleksis/core/models.py:716 aleksis/core/models.py:801 -#: aleksis/core/models.py:1048 +#: aleksis/core/models.py:237 aleksis/core/models.py:717 +#: aleksis/core/models.py:741 aleksis/core/models.py:832 +#: aleksis/core/models.py:1092 msgid "Description" msgstr "" -#: aleksis/core/models.py:434 +#: aleksis/core/models.py:457 msgid "Title of field" msgstr "" -#: aleksis/core/models.py:436 +#: aleksis/core/models.py:459 msgid "Type of field" msgstr "" -#: aleksis/core/models.py:443 +#: aleksis/core/models.py:461 +msgid "Required" +msgstr "" + +#: aleksis/core/models.py:462 +msgid "Help text / description" +msgstr "" + +#: aleksis/core/models.py:468 msgid "Addtitional field for groups" msgstr "" -#: aleksis/core/models.py:444 +#: aleksis/core/models.py:469 msgid "Addtitional fields for groups" msgstr "" -#: aleksis/core/models.py:464 +#: aleksis/core/models.py:489 msgid "Can assign child groups to groups" msgstr "" -#: aleksis/core/models.py:465 +#: aleksis/core/models.py:490 msgid "Can view statistics about group." msgstr "" -#: aleksis/core/models.py:477 +#: aleksis/core/models.py:502 msgid "Long name" msgstr "" -#: aleksis/core/models.py:487 aleksis/core/templates/core/group/full.html:85 +#: aleksis/core/models.py:512 aleksis/core/templates/core/group/full.html:85 msgid "Members" msgstr "" -#: aleksis/core/models.py:490 aleksis/core/templates/core/group/full.html:82 +#: aleksis/core/models.py:515 aleksis/core/templates/core/group/full.html:82 msgid "Owners" msgstr "" -#: aleksis/core/models.py:497 aleksis/core/templates/core/group/full.html:55 +#: aleksis/core/models.py:522 aleksis/core/templates/core/group/full.html:55 msgid "Parent groups" msgstr "" -#: aleksis/core/models.py:505 +#: aleksis/core/models.py:530 msgid "Type of group" msgstr "" -#: aleksis/core/models.py:691 aleksis/core/models.py:715 -#: aleksis/core/models.py:800 +#: aleksis/core/models.py:716 aleksis/core/models.py:740 +#: aleksis/core/models.py:831 #: aleksis/core/templates/core/announcement/list.html:18 msgid "Title" msgstr "" -#: aleksis/core/models.py:694 +#: aleksis/core/models.py:719 msgid "Application" msgstr "" -#: aleksis/core/models.py:700 +#: aleksis/core/models.py:725 msgid "Activity" msgstr "" -#: aleksis/core/models.py:701 +#: aleksis/core/models.py:726 msgid "Activities" msgstr "" -#: aleksis/core/models.py:707 +#: aleksis/core/models.py:732 msgid "Sender" msgstr "" -#: aleksis/core/models.py:712 +#: aleksis/core/models.py:737 msgid "Recipient" msgstr "" -#: aleksis/core/models.py:717 aleksis/core/models.py:1025 +#: aleksis/core/models.py:742 aleksis/core/models.py:1069 msgid "Link" msgstr "" -#: aleksis/core/models.py:719 +#: aleksis/core/models.py:744 +msgid "Send notification at" +msgstr "" + +#: aleksis/core/models.py:746 msgid "Read" msgstr "" -#: aleksis/core/models.py:720 +#: aleksis/core/models.py:747 msgid "Sent" msgstr "" -#: aleksis/core/models.py:733 +#: aleksis/core/models.py:764 msgid "Notification" msgstr "" -#: aleksis/core/models.py:802 +#: aleksis/core/models.py:833 msgid "Link to detailed view" msgstr "" -#: aleksis/core/models.py:805 +#: aleksis/core/models.py:836 msgid "Date and time from when to show" msgstr "" -#: aleksis/core/models.py:808 +#: aleksis/core/models.py:839 msgid "Date and time until when to show" msgstr "" -#: aleksis/core/models.py:833 +#: aleksis/core/models.py:864 msgid "Announcement" msgstr "" -#: aleksis/core/models.py:871 +#: aleksis/core/models.py:902 msgid "Announcement recipient" msgstr "" -#: aleksis/core/models.py:872 +#: aleksis/core/models.py:903 msgid "Announcement recipients" msgstr "" -#: aleksis/core/models.py:894 +#: aleksis/core/models.py:925 msgid "Widget Title" msgstr "" -#: aleksis/core/models.py:895 +#: aleksis/core/models.py:926 msgid "Activate Widget" msgstr "" -#: aleksis/core/models.py:896 +#: aleksis/core/models.py:927 msgid "Widget is broken" msgstr "" -#: aleksis/core/models.py:899 +#: aleksis/core/models.py:930 msgid "Size on mobile devices" msgstr "" -#: aleksis/core/models.py:900 +#: aleksis/core/models.py:931 msgid "<= 600 px, 12 columns" msgstr "" -#: aleksis/core/models.py:905 +#: aleksis/core/models.py:936 msgid "Size on tablet devices" msgstr "" -#: aleksis/core/models.py:906 +#: aleksis/core/models.py:937 msgid "> 600 px, 12 columns" msgstr "" -#: aleksis/core/models.py:911 +#: aleksis/core/models.py:942 msgid "Size on desktop devices" msgstr "" -#: aleksis/core/models.py:912 +#: aleksis/core/models.py:943 msgid "> 992 px, 12 columns" msgstr "" -#: aleksis/core/models.py:917 +#: aleksis/core/models.py:948 msgid "Size on large desktop devices" msgstr "" -#: aleksis/core/models.py:918 +#: aleksis/core/models.py:949 msgid "> 1200 px>, 12 columns" msgstr "" -#: aleksis/core/models.py:949 +#: aleksis/core/models.py:980 msgid "Can edit default dashboard" msgstr "" -#: aleksis/core/models.py:950 +#: aleksis/core/models.py:981 msgid "Dashboard Widget" msgstr "" -#: aleksis/core/models.py:951 +#: aleksis/core/models.py:982 msgid "Dashboard Widgets" msgstr "" -#: aleksis/core/models.py:957 +#: aleksis/core/models.py:988 msgid "URL" msgstr "" -#: aleksis/core/models.py:958 +#: aleksis/core/models.py:989 msgid "Icon URL" msgstr "" -#: aleksis/core/models.py:964 +#: aleksis/core/models.py:995 msgid "External link widget" msgstr "" -#: aleksis/core/models.py:965 +#: aleksis/core/models.py:996 msgid "External link widgets" msgstr "" -#: aleksis/core/models.py:970 +#: aleksis/core/models.py:1002 +msgid "Content" +msgstr "" + +#: aleksis/core/models.py:1008 +msgid "Static content widget" +msgstr "" + +#: aleksis/core/models.py:1009 +msgid "Static content widgets" +msgstr "" + +#: aleksis/core/models.py:1014 msgid "Dashboard widget" msgstr "" -#: aleksis/core/models.py:975 +#: aleksis/core/models.py:1019 msgid "Order" msgstr "" -#: aleksis/core/models.py:976 +#: aleksis/core/models.py:1020 msgid "Part of the default dashboard" msgstr "" -#: aleksis/core/models.py:991 +#: aleksis/core/models.py:1035 msgid "Dashboard widget order" msgstr "" -#: aleksis/core/models.py:992 +#: aleksis/core/models.py:1036 msgid "Dashboard widget orders" msgstr "" -#: aleksis/core/models.py:998 +#: aleksis/core/models.py:1042 msgid "Menu ID" msgstr "" -#: aleksis/core/models.py:1011 +#: aleksis/core/models.py:1055 msgid "Custom menu" msgstr "" -#: aleksis/core/models.py:1012 +#: aleksis/core/models.py:1056 msgid "Custom menus" msgstr "" -#: aleksis/core/models.py:1022 +#: aleksis/core/models.py:1066 msgid "Menu" msgstr "" -#: aleksis/core/models.py:1026 aleksis/core/models.py:1274 +#: aleksis/core/models.py:1070 aleksis/core/models.py:1318 #: aleksis/core/templates/oauth2_provider/application/detail.html:26 msgid "Icon" msgstr "" -#: aleksis/core/models.py:1032 +#: aleksis/core/models.py:1076 msgid "Custom menu item" msgstr "" -#: aleksis/core/models.py:1033 +#: aleksis/core/models.py:1077 msgid "Custom menu items" msgstr "" -#: aleksis/core/models.py:1047 +#: aleksis/core/models.py:1091 msgid "Title of type" msgstr "" -#: aleksis/core/models.py:1054 aleksis/core/templates/core/group/full.html:47 +#: aleksis/core/models.py:1098 aleksis/core/templates/core/group/full.html:47 msgid "Group type" msgstr "" -#: aleksis/core/models.py:1068 +#: aleksis/core/models.py:1112 msgid "Can view system status" msgstr "" -#: aleksis/core/models.py:1069 +#: aleksis/core/models.py:1113 msgid "Can manage data" msgstr "" -#: aleksis/core/models.py:1070 +#: aleksis/core/models.py:1114 msgid "Can impersonate" msgstr "" -#: aleksis/core/models.py:1071 +#: aleksis/core/models.py:1115 msgid "Can use search" msgstr "" -#: aleksis/core/models.py:1072 +#: aleksis/core/models.py:1116 msgid "Can change site preferences" msgstr "" -#: aleksis/core/models.py:1073 +#: aleksis/core/models.py:1117 msgid "Can change person preferences" msgstr "" -#: aleksis/core/models.py:1074 +#: aleksis/core/models.py:1118 msgid "Can change group preferences" msgstr "" -#: aleksis/core/models.py:1075 +#: aleksis/core/models.py:1119 msgid "Can test PDF generation" msgstr "" -#: aleksis/core/models.py:1076 +#: aleksis/core/models.py:1120 msgid "Can invite persons" msgstr "" -#: aleksis/core/models.py:1112 +#: aleksis/core/models.py:1156 msgid "Related data check task" msgstr "" -#: aleksis/core/models.py:1120 +#: aleksis/core/models.py:1164 msgid "Issue solved" msgstr "" -#: aleksis/core/models.py:1121 +#: aleksis/core/models.py:1165 msgid "Notification sent" msgstr "" -#: aleksis/core/models.py:1134 +#: aleksis/core/models.py:1178 msgid "Data check result" msgstr "" -#: aleksis/core/models.py:1135 +#: aleksis/core/models.py:1179 msgid "Data check results" msgstr "" -#: aleksis/core/models.py:1137 +#: aleksis/core/models.py:1181 msgid "Can run data checks" msgstr "" -#: aleksis/core/models.py:1138 +#: aleksis/core/models.py:1182 msgid "Can solve data check problems" msgstr "" -#: aleksis/core/models.py:1145 +#: aleksis/core/models.py:1189 msgid "E-Mail address" msgstr "" -#: aleksis/core/models.py:1177 +#: aleksis/core/models.py:1221 msgid "Owner" msgstr "" -#: aleksis/core/models.py:1181 +#: aleksis/core/models.py:1225 msgid "File expires at" msgstr "" -#: aleksis/core/models.py:1183 +#: aleksis/core/models.py:1227 msgid "Generated HTML file" msgstr "" -#: aleksis/core/models.py:1185 +#: aleksis/core/models.py:1229 msgid "Generated PDF file" msgstr "" -#: aleksis/core/models.py:1192 +#: aleksis/core/models.py:1236 msgid "PDF file" msgstr "" -#: aleksis/core/models.py:1193 +#: aleksis/core/models.py:1237 msgid "PDF files" msgstr "" -#: aleksis/core/models.py:1198 +#: aleksis/core/models.py:1242 msgid "Task result" msgstr "" -#: aleksis/core/models.py:1201 +#: aleksis/core/models.py:1245 msgid "Task user" msgstr "" -#: aleksis/core/models.py:1213 +#: aleksis/core/models.py:1257 msgid "Task user assignment" msgstr "" -#: aleksis/core/models.py:1214 +#: aleksis/core/models.py:1258 msgid "Task user assignments" msgstr "" -#: aleksis/core/models.py:1230 +#: aleksis/core/models.py:1274 msgid "Additional attributes" msgstr "" -#: aleksis/core/models.py:1268 +#: aleksis/core/models.py:1312 msgid "Allowed scopes that clients can request" msgstr "" -#: aleksis/core/models.py:1278 +#: aleksis/core/models.py:1322 msgid "This image will be shown as icon in the authorization flow. It should be squared." msgstr "" @@ -1083,86 +1111,98 @@ msgid "Allow users to change their passwords" msgstr "" #: aleksis/core/preferences.py:279 -msgid "Enable signup" +msgid "Allow users to reset their passwords" msgstr "" #: aleksis/core/preferences.py:287 -msgid "Enable invitations" +msgid "Enable signup" msgstr "" #: aleksis/core/preferences.py:295 -msgid "Length of invite code. (Default 3: abcde-acbde-abcde)" +msgid "Regular expression for allowed usernames" msgstr "" #: aleksis/core/preferences.py:303 +msgid "Enable invitations" +msgstr "" + +#: aleksis/core/preferences.py:311 +msgid "Length of invite code. (Default 3: abcde-acbde-abcde)" +msgstr "" + +#: aleksis/core/preferences.py:319 msgid "Size of packets. (Default 5: abcde)" msgstr "" -#: aleksis/core/preferences.py:314 +#: aleksis/core/preferences.py:330 msgid "Allowed Grant Flows for OAuth applications" msgstr "" -#: aleksis/core/preferences.py:328 +#: aleksis/core/preferences.py:344 msgid "Available languages" msgstr "" -#: aleksis/core/preferences.py:341 +#: aleksis/core/preferences.py:357 msgid "Send emails if data checks detect problems" msgstr "" -#: aleksis/core/preferences.py:352 +#: aleksis/core/preferences.py:368 msgid "Email recipients for data checks problem emails" msgstr "" -#: aleksis/core/preferences.py:363 +#: aleksis/core/preferences.py:379 msgid "Email recipient groups for data checks problem emails" msgstr "" -#: aleksis/core/preferences.py:372 +#: aleksis/core/preferences.py:388 msgid "Show dashboard to users without login" msgstr "" -#: aleksis/core/preferences.py:381 +#: aleksis/core/preferences.py:397 msgid "Allow users to edit their dashboard" msgstr "" -#: aleksis/core/preferences.py:392 +#: aleksis/core/preferences.py:408 msgid "Fields on person model which are editable by themselves." msgstr "" -#: aleksis/core/preferences.py:407 +#: aleksis/core/preferences.py:423 msgid "Editable fields on person model which should trigger a notification on change" msgstr "" -#: aleksis/core/preferences.py:421 +#: aleksis/core/preferences.py:437 msgid "Contact for notification if a person changes their data" msgstr "" -#: aleksis/core/preferences.py:432 +#: aleksis/core/preferences.py:448 +msgid "Prefer personal photos over avatars" +msgstr "" + +#: aleksis/core/preferences.py:458 msgid "PDF file expiration duration" msgstr "" -#: aleksis/core/preferences.py:433 +#: aleksis/core/preferences.py:459 msgid "in minutes" msgstr "" -#: aleksis/core/preferences.py:443 +#: aleksis/core/preferences.py:469 msgid "Automatically update the dashboard and its widgets" msgstr "" -#: aleksis/core/preferences.py:453 +#: aleksis/core/preferences.py:479 msgid "Automatically update the dashboard and its widgets sitewide" msgstr "" -#: aleksis/core/preferences.py:463 +#: aleksis/core/preferences.py:489 msgid "Country for phone number parsing" msgstr "" -#: aleksis/core/settings.py:529 +#: aleksis/core/settings.py:540 msgid "English" msgstr "" -#: aleksis/core/settings.py:530 +#: aleksis/core/settings.py:541 msgid "German" msgstr "" @@ -1170,7 +1210,7 @@ msgstr "" #: aleksis/core/templates/core/announcement/list.html:36 #: aleksis/core/templates/core/group/full.html:24 #: aleksis/core/templates/core/person/full.html:26 -#: aleksis/core/templates/core/person/full.html:98 +#: aleksis/core/templates/core/person/full.html:86 #: aleksis/core/templates/oauth2_provider/application/detail.html:17 msgid "Edit" msgstr "" @@ -1188,7 +1228,7 @@ msgstr "" #: aleksis/core/templates/core/group/full.html:31 #: aleksis/core/templates/core/pages/delete.html:22 #: aleksis/core/templates/core/person/full.html:33 -#: aleksis/core/templates/core/person/full.html:105 +#: aleksis/core/templates/core/person/full.html:93 #: aleksis/core/templates/oauth2_provider/application/detail.html:21 msgid "Delete" msgstr "" @@ -1235,6 +1275,10 @@ msgid "" " " msgstr "" +#: aleksis/core/templates/500.html:21 +msgid "Retry" +msgstr "" + #: aleksis/core/templates/503.html:10 msgid "" "The maintenance mode is currently enabled. Please try again\n" @@ -1493,19 +1537,15 @@ msgstr "" msgid "There are no announcements." msgstr "" -#: aleksis/core/templates/core/base.html:78 -msgid "Logged in as" -msgstr "" - -#: aleksis/core/templates/core/base.html:179 +#: aleksis/core/templates/core/base.html:213 msgid "About AlekSIS® — The Free School Information System" msgstr "" -#: aleksis/core/templates/core/base.html:187 +#: aleksis/core/templates/core/base.html:221 msgid "Imprint" msgstr "" -#: aleksis/core/templates/core/base.html:195 +#: aleksis/core/templates/core/base.html:229 msgid "Privacy Policy" msgstr "" @@ -1726,7 +1766,7 @@ msgstr "" #: aleksis/core/templates/core/group/full.html:38 #: aleksis/core/templates/core/person/full.html:40 -#: aleksis/core/templates/core/person/full.html:112 +#: aleksis/core/templates/core/person/full.html:100 msgid "Change preferences" msgstr "" @@ -1916,83 +1956,83 @@ msgstr "" msgid "System checks" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:21 +#: aleksis/core/templates/core/pages/system_status.html:22 msgid "Maintenance mode enabled" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:23 +#: aleksis/core/templates/core/pages/system_status.html:24 msgid "" "\n" " Only admin and visitors from internal IPs can access thesite.\n" " " msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:34 +#: aleksis/core/templates/core/pages/system_status.html:36 msgid "Maintenance mode disabled" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:35 +#: aleksis/core/templates/core/pages/system_status.html:37 msgid "Everyone can access the site." msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:45 +#: aleksis/core/templates/core/pages/system_status.html:47 msgid "Debug mode enabled" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:47 +#: aleksis/core/templates/core/pages/system_status.html:49 msgid "" "\n" " The web server throws back debug information on errors. Do not use in production!\n" " " msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:54 +#: aleksis/core/templates/core/pages/system_status.html:56 msgid "Debug mode disabled" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:56 +#: aleksis/core/templates/core/pages/system_status.html:58 msgid "" "\n" " Debug mode is disabled. Default error pages are displayed on errors.\n" " " msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:69 +#: aleksis/core/templates/core/pages/system_status.html:71 msgid "System health checks" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:75 +#: aleksis/core/templates/core/pages/system_status.html:77 msgid "Service" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:76 -#: aleksis/core/templates/core/pages/system_status.html:115 +#: aleksis/core/templates/core/pages/system_status.html:78 +#: aleksis/core/templates/core/pages/system_status.html:119 msgid "Status" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:77 +#: aleksis/core/templates/core/pages/system_status.html:79 msgid "Time taken" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:96 +#: aleksis/core/templates/core/pages/system_status.html:100 msgid "seconds" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:107 +#: aleksis/core/templates/core/pages/system_status.html:111 msgid "Celery task results" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:112 +#: aleksis/core/templates/core/pages/system_status.html:116 #: aleksis/core/templates/templated_email/celery_failure.email:9 #: aleksis/core/templates/templated_email/celery_failure.email:28 msgid "Task" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:113 +#: aleksis/core/templates/core/pages/system_status.html:117 msgid "ID" msgstr "" -#: aleksis/core/templates/core/pages/system_status.html:114 +#: aleksis/core/templates/core/pages/system_status.html:118 msgid "Date done" msgstr "" @@ -2033,6 +2073,18 @@ msgid "" " " msgstr "" +#: aleksis/core/templates/core/partials/avatar_content.html:14 +#: aleksis/core/templates/core/partials/avatar_content.html:15 +#: aleksis/core/templates/core/person/full.html:213 +#: aleksis/core/templates/core/person/full.html:214 +msgid "Avatar" +msgstr "" + +#: aleksis/core/templates/core/partials/avatar_content.html:19 +#: aleksis/core/templates/core/partials/avatar_content.html:20 +msgid "Identicon" +msgstr "" + #: aleksis/core/templates/core/partials/crud_events.html:15 msgid "Changed by" msgstr "" @@ -2123,24 +2175,24 @@ msgid "Edit person" msgstr "" #: aleksis/core/templates/core/person/full.html:47 -#: aleksis/core/templates/core/person/full.html:119 +#: aleksis/core/templates/core/person/full.html:107 msgid "Impersonate" msgstr "" #: aleksis/core/templates/core/person/full.html:54 -#: aleksis/core/templates/core/person/full.html:126 +#: aleksis/core/templates/core/person/full.html:114 msgid "Invite user" msgstr "" -#: aleksis/core/templates/core/person/full.html:133 +#: aleksis/core/templates/core/person/full.html:121 msgid "Contact details" msgstr "" -#: aleksis/core/templates/core/person/full.html:224 +#: aleksis/core/templates/core/person/full.html:220 msgid "This person didn't upload a personal photo." msgstr "" -#: aleksis/core/templates/core/person/full.html:232 +#: aleksis/core/templates/core/person/full.html:228 msgid "Children" msgstr "" @@ -2345,13 +2397,11 @@ msgstr "" msgid "Network error" msgstr "" -#: aleksis/core/templates/offline.html:8 -msgid "" -"No internet\n" -" connection." +#: aleksis/core/templates/offline.html:10 +msgid "No internet connection." msgstr "" -#: aleksis/core/templates/offline.html:12 +#: aleksis/core/templates/offline.html:14 msgid "" "\n" " There was an error accessing this page. You probably don't have an internet connection. Check to see if your WiFi\n" @@ -2595,7 +2645,7 @@ msgstr "" #: aleksis/core/templates/two_factor/_base_focus.html:6 #: aleksis/core/templates/two_factor/core/otp_required.html:22 #: aleksis/core/templates/two_factor/core/setup.html:5 -#: aleksis/core/templates/two_factor/profile/profile.html:87 +#: aleksis/core/templates/two_factor/profile/profile.html:88 msgid "Enable Two-Factor Authentication" msgstr "" @@ -2699,15 +2749,15 @@ msgstr "" msgid "Or, alternatively, use one of your backup phones:" msgstr "" -#: aleksis/core/templates/two_factor/core/login.html:121 +#: aleksis/core/templates/two_factor/core/login.html:122 msgid "As a last resort, you can use a backup token:" msgstr "" -#: aleksis/core/templates/two_factor/core/login.html:124 +#: aleksis/core/templates/two_factor/core/login.html:125 msgid "Use Backup Token" msgstr "" -#: aleksis/core/templates/two_factor/core/login.html:135 +#: aleksis/core/templates/two_factor/core/login.html:136 msgid "Use alternative login options" msgstr "" @@ -2944,11 +2994,11 @@ msgid "" " " msgstr "" -#: aleksis/core/util/notifications.py:63 +#: aleksis/core/util/notifications.py:64 msgid "E-Mail" msgstr "" -#: aleksis/core/util/notifications.py:64 +#: aleksis/core/util/notifications.py:65 msgid "SMS" msgstr "" @@ -2972,156 +3022,156 @@ msgstr "" msgid "Download PDF" msgstr "" -#: aleksis/core/views.py:285 +#: aleksis/core/views.py:289 msgid "The school term has been created." msgstr "" -#: aleksis/core/views.py:297 +#: aleksis/core/views.py:301 msgid "The school term has been saved." msgstr "" -#: aleksis/core/views.py:417 +#: aleksis/core/views.py:421 msgid "The child groups were successfully saved." msgstr "" -#: aleksis/core/views.py:436 aleksis/core/views.py:446 +#: aleksis/core/views.py:440 aleksis/core/views.py:450 msgid "The person has been saved." msgstr "" -#: aleksis/core/views.py:496 +#: aleksis/core/views.py:500 msgid "The group has been saved." msgstr "" -#: aleksis/core/views.py:593 +#: aleksis/core/views.py:597 msgid "The announcement has been saved." msgstr "" -#: aleksis/core/views.py:609 +#: aleksis/core/views.py:613 msgid "The announcement has been deleted." msgstr "" -#: aleksis/core/views.py:677 +#: aleksis/core/views.py:681 msgid "The requested preference registry does not exist" msgstr "" -#: aleksis/core/views.py:696 +#: aleksis/core/views.py:700 msgid "The preferences have been saved successfully." msgstr "" -#: aleksis/core/views.py:720 +#: aleksis/core/views.py:724 msgid "The person has been deleted." msgstr "" -#: aleksis/core/views.py:734 +#: aleksis/core/views.py:738 msgid "The group has been deleted." msgstr "" -#: aleksis/core/views.py:766 +#: aleksis/core/views.py:770 msgid "The additional_field has been saved." msgstr "" -#: aleksis/core/views.py:800 +#: aleksis/core/views.py:804 msgid "The additional field has been deleted." msgstr "" -#: aleksis/core/views.py:825 +#: aleksis/core/views.py:829 msgid "The group type has been saved." msgstr "" -#: aleksis/core/views.py:855 +#: aleksis/core/views.py:859 msgid "The group type has been deleted." msgstr "" -#: aleksis/core/views.py:888 +#: aleksis/core/views.py:892 msgid "Progress: Run data checks" msgstr "" -#: aleksis/core/views.py:889 +#: aleksis/core/views.py:893 msgid "Run data checks …" msgstr "" -#: aleksis/core/views.py:890 +#: aleksis/core/views.py:894 msgid "The data checks were run successfully." msgstr "" -#: aleksis/core/views.py:891 +#: aleksis/core/views.py:895 msgid "There was a problem while running data checks." msgstr "" -#: aleksis/core/views.py:907 +#: aleksis/core/views.py:911 #, python-brace-format msgid "The solve option '{solve_option_obj.verbose_name}' " msgstr "" -#: aleksis/core/views.py:917 +#: aleksis/core/views.py:921 msgid "The requested solve option does not exist" msgstr "" -#: aleksis/core/views.py:949 +#: aleksis/core/views.py:953 msgid "The dashboard widget has been saved." msgstr "" -#: aleksis/core/views.py:979 +#: aleksis/core/views.py:983 msgid "The dashboard widget has been created." msgstr "" -#: aleksis/core/views.py:989 +#: aleksis/core/views.py:993 msgid "The dashboard widget has been deleted." msgstr "" -#: aleksis/core/views.py:1060 +#: aleksis/core/views.py:1064 msgid "Your dashboard configuration has been saved successfully." msgstr "" -#: aleksis/core/views.py:1062 +#: aleksis/core/views.py:1066 msgid "The configuration of the default dashboard has been saved successfully." msgstr "" -#: aleksis/core/views.py:1138 +#: aleksis/core/views.py:1142 #, python-brace-format msgid "The invitation was successfully created. The invitation code is {code}" msgstr "" -#: aleksis/core/views.py:1229 +#: aleksis/core/views.py:1233 msgid "We have successfully assigned the permissions." msgstr "" -#: aleksis/core/views.py:1239 +#: aleksis/core/views.py:1243 msgid "The global user permission has been deleted." msgstr "" -#: aleksis/core/views.py:1249 +#: aleksis/core/views.py:1253 msgid "The global group permission has been deleted." msgstr "" -#: aleksis/core/views.py:1259 +#: aleksis/core/views.py:1263 msgid "The object user permission has been deleted." msgstr "" -#: aleksis/core/views.py:1269 +#: aleksis/core/views.py:1273 msgid "The object group permission has been deleted." msgstr "" -#: aleksis/core/views.py:1337 +#: aleksis/core/views.py:1341 msgid "The requested PDF file does not exist" msgstr "" -#: aleksis/core/views.py:1346 aleksis/core/views.py:1350 +#: aleksis/core/views.py:1350 aleksis/core/views.py:1354 msgid "The requested task does not exist or is not accessible" msgstr "" -#: aleksis/core/views.py:1388 +#: aleksis/core/views.py:1406 msgid "The third-party account could not be disconnected because it is the only login method available." msgstr "" -#: aleksis/core/views.py:1395 +#: aleksis/core/views.py:1413 msgid "The third-party account has been successfully disconnected." msgstr "" -#: aleksis/core/views.py:1466 +#: aleksis/core/views.py:1484 msgid "Person was invited successfully and an email with further instructions has been send to them." msgstr "" -#: aleksis/core/views.py:1477 +#: aleksis/core/views.py:1495 msgid "Person was already invited." msgstr "" diff --git a/aleksis/core/locale/tr_TR/LC_MESSAGES/djangojs.po b/aleksis/core/locale/tr_TR/LC_MESSAGES/djangojs.po index dfec73c5c894d3d686092593be9c21a811cd0535..f3df4c3fc6d2848a739ddd1faac44cb9048c97b2 100644 --- a/aleksis/core/locale/tr_TR/LC_MESSAGES/djangojs.po +++ b/aleksis/core/locale/tr_TR/LC_MESSAGES/djangojs.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-02-08 23:16+0000\n" +"POT-Creation-Date: 2022-03-23 11:20+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -29,6 +29,6 @@ msgstr "" msgid "OK" msgstr "" -#: aleksis/core/static/js/main.js:191 +#: aleksis/core/static/js/main.js:195 msgid "This page may contain outdated information since there is no internet connection." msgstr "" diff --git a/aleksis/core/menus.py b/aleksis/core/menus.py index 7938539c53327936d86d6c08334834e8e2a4fb0a..49ddd4af743769252cbdbbae26d7de1d68c55776 100644 --- a/aleksis/core/menus.py +++ b/aleksis/core/menus.py @@ -1,20 +1,18 @@ from django.conf import settings from django.utils.translation import gettext_lazy as _ -from .util.core_helpers import unread_notifications_badge - MENUS = { "NAV_MENU_CORE": [ { "name": _("Login"), "url": settings.LOGIN_URL, - "icon": "lock_open", + "svg_icon": "mdi:login-variant", "validators": ["menu_generator.validators.is_anonymous"], }, { "name": _("Sign up"), "url": "account_signup", - "icon": "how_to_reg", + "svg_icon": "mdi:account-plus-outline", "validators": [ "menu_generator.validators.is_anonymous", ("aleksis.core.util.predicates.permission_validator", "core.can_register"), @@ -23,7 +21,7 @@ MENUS = { { "name": _("Accept invitation"), "url": "enter_invitation_code", - "icon": "vpn_key", + "svg_icon": "mdi:key-outline", "validators": [ "menu_generator.validators.is_anonymous", ("aleksis.core.util.predicates.permission_validator", "core.invite_enabled"), @@ -32,107 +30,15 @@ MENUS = { { "name": _("Dashboard"), "url": "index", - "icon": "home", + "svg_icon": "mdi:home-outline", "validators": [ ("aleksis.core.util.predicates.permission_validator", "core.view_dashboard_rule") ], }, - { - "name": _("Notifications"), - "url": "notifications", - "icon": "notifications", - "badge": unread_notifications_badge, - "validators": [ - ( - "aleksis.core.util.predicates.permission_validator", - "core.view_notifications", - ), - ], - }, - { - "name": _("Account"), - "url": "#", - "icon": "person", - "root": True, - "validators": ["menu_generator.validators.is_authenticated"], - "submenu": [ - { - "name": _("Stop impersonation"), - "url": "impersonate-stop", - "icon": "stop", - "validators": [ - "menu_generator.validators.is_authenticated", - "aleksis.core.util.core_helpers.is_impersonate", - ], - }, - { - "name": _("Logout"), - "url": "logout", - "icon": "exit_to_app", - "validators": ["menu_generator.validators.is_authenticated"], - }, - { - "name": _("2FA"), - "url": "two_factor:profile", - "icon": "phonelink_lock", - "validators": [ - "menu_generator.validators.is_authenticated", - ], - }, - { - "name": _("Change password"), - "url": "account_change_password", - "icon": "lock", - "validators": [ - "menu_generator.validators.is_authenticated", - ( - "aleksis.core.util.predicates.permission_validator", - "core.can_change_password", - ), - ], - }, - { - "name": _("Me"), - "url": "person", - "icon": "insert_emoticon", - "validators": [ - "menu_generator.validators.is_authenticated", - "aleksis.core.util.core_helpers.has_person", - ], - }, - { - "name": _("Preferences"), - "url": "preferences_person", - "icon": "settings", - "validators": [ - "menu_generator.validators.is_authenticated", - "aleksis.core.util.core_helpers.has_person", - ], - }, - { - "name": _("Third-party accounts"), - "url": "socialaccount_connections", - "icon": "public", - "validators": [ - "menu_generator.validators.is_authenticated", - "aleksis.core.util.core_helpers.has_person", - ], - }, - { - "name": _("Authorized applications"), - "url": "oauth2_provider:authorized-token-list", - "icon": "touch_app", - "validators": [ - "menu_generator.validators.is_authenticated", - "aleksis.core.util.core_helpers.has_person", - ], - }, - ], - }, { "name": _("Admin"), "url": "#", - "icon": "security", + "svg_icon": "mdi:security", "validators": [ ("aleksis.core.util.predicates.permission_validator", "core.view_admin_menu"), ], @@ -140,7 +46,7 @@ MENUS = { { "name": _("Announcements"), "url": "announcements", - "icon": "announcement", + "svg_icon": "mdi:message-alert-outline", "validators": [ ( "aleksis.core.util.predicates.permission_validator", @@ -151,7 +57,7 @@ MENUS = { { "name": _("School terms"), "url": "school_terms", - "icon": "date_range", + "svg_icon": "mdi:calendar-range-outline", "validators": [ ( "aleksis.core.util.predicates.permission_validator", @@ -162,7 +68,7 @@ MENUS = { { "name": _("Dashboard widgets"), "url": "dashboard_widgets", - "icon": "dashboard", + "svg_icon": "mdi:view-dashboard-outline", "validators": [ ( "aleksis.core.util.predicates.permission_validator", @@ -173,7 +79,7 @@ MENUS = { { "name": _("Data management"), "url": "data_management", - "icon": "view_list", + "svg_icon": "mdi:chart-donut", "validators": [ ( "aleksis.core.util.predicates.permission_validator", @@ -184,7 +90,7 @@ MENUS = { { "name": _("System status"), "url": "system_status", - "icon": "power_settings_new", + "svg_icon": "mdi:power-settings", "validators": [ ( "aleksis.core.util.predicates.permission_validator", @@ -195,7 +101,7 @@ MENUS = { { "name": _("Configuration"), "url": "preferences_site", - "icon": "settings", + "svg_icon": "mdi:tune", "validators": [ ( "aleksis.core.util.predicates.permission_validator", @@ -206,13 +112,13 @@ MENUS = { { "name": _("Data checks"), "url": "check_data", - "icon": "done_all", + "svg_icon": "mdi:list-status", "validators": ["menu_generator.validators.is_superuser"], }, { "name": _("Manage permissions"), "url": "manage_user_global_permissions", - "icon": "shield", + "svg_icon": "mdi:shield-outline", "validators": [ ( "aleksis.core.util.predicates.permission_validator", @@ -223,7 +129,7 @@ MENUS = { { "name": _("Backend Admin"), "url": "admin:index", - "icon": "settings", + "svg_icon": "mdi:database-cog-outline", "validators": [ "menu_generator.validators.is_superuser", ], @@ -231,7 +137,7 @@ MENUS = { { "name": _("OAuth2 Applications"), "url": "oauth2_applications", - "icon": "touch_app", + "svg_icon": "mdi:gesture-tap-hold", "validators": [ ( "aleksis.core.util.predicates.permission_validator", @@ -244,7 +150,7 @@ MENUS = { { "name": _("People"), "url": "#", - "icon": "people", + "svg_icon": "mdi:account-group-outline", "root": True, "validators": [ ("aleksis.core.util.predicates.permission_validator", "core.view_people_menu_rule") @@ -253,7 +159,7 @@ MENUS = { { "name": _("Persons"), "url": "persons", - "icon": "person", + "svg_icon": "mdi:account-outline", "validators": [ ( "aleksis.core.util.predicates.permission_validator", @@ -264,7 +170,7 @@ MENUS = { { "name": _("Groups"), "url": "groups", - "icon": "group", + "svg_icon": "mdi:account-multiple-outline", "validators": [ ( "aleksis.core.util.predicates.permission_validator", @@ -275,7 +181,7 @@ MENUS = { { "name": _("Group types"), "url": "group_types", - "icon": "category", + "svg_icon": "mdi:shape-outline", "validators": [ ( "aleksis.core.util.predicates.permission_validator", @@ -286,7 +192,7 @@ MENUS = { { "name": _("Groups and child groups"), "url": "groups_child_groups", - "icon": "group_add", + "svg_icon": "mdi:account-multiple-plus-outline", "validators": [ ( "aleksis.core.util.predicates.permission_validator", @@ -297,7 +203,7 @@ MENUS = { { "name": _("Additional fields"), "url": "additional_fields", - "icon": "style", + "svg_icon": "mdi:palette-swatch-outline", "validators": [ ( "aleksis.core.util.predicates.permission_validator", @@ -308,7 +214,7 @@ MENUS = { { "name": _("Invite person"), "url": "invite_person", - "icon": "card_giftcard", + "svg_icon": "mdi:account-plus-outline", "validators": [ "menu_generator.validators.is_authenticated", ("aleksis.core.util.predicates.permission_validator", "core.can_invite"), @@ -329,4 +235,90 @@ MENUS = { ], }, ], + "NAVBAR_ACCOUNT_MENU": [ + { + "name": _("Stop impersonation"), + "url": "impersonate-stop", + "svg_icon": "mdi:stop", + "validators": [ + "menu_generator.validators.is_authenticated", + "aleksis.core.util.core_helpers.is_impersonate", + ], + }, + { + "name": _("Account"), + "url": "person", + "svg_icon": "mdi:account-outline", + "validators": [ + "menu_generator.validators.is_authenticated", + "aleksis.core.util.core_helpers.has_person", + ], + }, + { + "name": _("Preferences"), + "url": "preferences_person", + "svg_icon": "mdi:cog-outline", + "validators": [ + "menu_generator.validators.is_authenticated", + "aleksis.core.util.core_helpers.has_person", + ], + }, + { + "name": _("2FA"), + "url": "two_factor:profile", + "svg_icon": "mdi:two-factor-authentication", + "validators": [ + "menu_generator.validators.is_authenticated", + ], + }, + { + "name": _("Change password"), + "url": "account_change_password", + "svg_icon": "mdi:form-textbox-password", + "validators": [ + "menu_generator.validators.is_authenticated", + ( + "aleksis.core.util.predicates.permission_validator", + "core.can_change_password", + ), + ], + }, + { + "name": _("Third-party accounts"), + "url": "socialaccount_connections", + "svg_icon": "mdi:earth", + "validators": [ + "menu_generator.validators.is_authenticated", + "aleksis.core.util.core_helpers.has_person", + ], + }, + { + "name": _("Authorized applications"), + "url": "oauth2_provider:authorized-token-list", + "svg_icon": "mdi:gesture-tap-hold", + "validators": [ + "menu_generator.validators.is_authenticated", + "aleksis.core.util.core_helpers.has_person", + ], + }, + { + "name": _("Calendar Feeds"), + "url": "ical_feed_list", + "svg_icon": "mdi:calendar-multiple", + "validators": [ + "menu_generator.validators.is_authenticated", + ( + "aleksis.core.util.predicates.permission_validator", + "core.view_ical_rule", + ), + ], + }, + { + "divider": True, + "name": _("Logout"), + "url": "logout", + "svg_icon": "mdi:logout-variant", + "validators": ["menu_generator.validators.is_authenticated"], + }, + ], } diff --git a/aleksis/core/migrations/0036_additionalfields_helptext_required.py b/aleksis/core/migrations/0036_additionalfields_helptext_required.py new file mode 100644 index 0000000000000000000000000000000000000000..9486105645a238f437b0a25eced23e56d7d805c2 --- /dev/null +++ b/aleksis/core/migrations/0036_additionalfields_helptext_required.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.12 on 2022-02-18 21:48 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0035_preference_model_unique'), + ] + + operations = [ + migrations.AddField( + model_name='additionalfield', + name='help_text', + field=models.TextField(blank=True, verbose_name='Help text / description'), + ), + migrations.AddField( + model_name='additionalfield', + name='required', + field=models.BooleanField(default=False, verbose_name='Required'), + ), + ] diff --git a/aleksis/core/migrations/0037_add_static_content_widget.py b/aleksis/core/migrations/0037_add_static_content_widget.py new file mode 100644 index 0000000000000000000000000000000000000000..bb4e810a614c1357243bdda4c5ac42b7f844058a --- /dev/null +++ b/aleksis/core/migrations/0037_add_static_content_widget.py @@ -0,0 +1,27 @@ +# Generated by Django 3.2.12 on 2022-02-23 18:03 + +import ckeditor.fields +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0036_additionalfields_helptext_required'), + ] + + operations = [ + migrations.CreateModel( + name='StaticContentWidget', + fields=[ + ('dashboardwidget_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='core.dashboardwidget')), + ('content', ckeditor.fields.RichTextField(verbose_name='Content')), + ], + options={ + 'verbose_name': 'Static content widget', + 'verbose_name_plural': 'Static content widgets', + }, + bases=('core.dashboardwidget',), + ), + ] diff --git a/aleksis/core/migrations/0038_notification_send_at.py b/aleksis/core/migrations/0038_notification_send_at.py new file mode 100644 index 0000000000000000000000000000000000000000..edb96f1e87f143d60477a1578aea5d90226389a8 --- /dev/null +++ b/aleksis/core/migrations/0038_notification_send_at.py @@ -0,0 +1,20 @@ +# Generated by Django 3.2.12 on 2022-02-23 19:33 + +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0037_add_static_content_widget'), + ] + + operations = [ + migrations.AddField( + model_name='notification', + name='send_at', + field=models.DateTimeField(default=django.utils.timezone.now, verbose_name='Send notification at'), + preserve_default=False, + ), + ] diff --git a/aleksis/core/migrations/0039_personal_ical_url.py b/aleksis/core/migrations/0039_personal_ical_url.py new file mode 100644 index 0000000000000000000000000000000000000000..02d9cb3a9e3589563c7dd68ce211271264c5245e --- /dev/null +++ b/aleksis/core/migrations/0039_personal_ical_url.py @@ -0,0 +1,31 @@ +# Generated by Django 3.2.12 on 2022-02-20 21:04 + +from django.db import migrations, models +import django.db.models.deletion +import uuid + +from aleksis.core.feeds import PersonalICalFeedBase + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0038_notification_send_at'), + ] + + operations = [ + migrations.CreateModel( + name='PersonalICalUrl', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, unique=True, verbose_name='UUID')), + ('name', models.CharField(max_length=255, verbose_name='Name')), + ('ical_feed', models.CharField(choices=PersonalICalFeedBase.subclass_choices, max_length=255, verbose_name='Selected ICal feed')), + ('person', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='calendar_urls', to='core.person', verbose_name='Person')), + ], + options={ + 'verbose_name': 'Personal Calendar URL', + 'verbose_name_plural': 'Personal Calendar URLs', + }, + ), + ] diff --git a/aleksis/core/models.py b/aleksis/core/models.py index 812a9d254ca4bff2e9372ed7969d0cb2b811c176..963c60c99ef8e8b1a9b0ca7ebc31c7c8f298a2f5 100644 --- a/aleksis/core/models.py +++ b/aleksis/core/models.py @@ -1,5 +1,7 @@ # flake8: noqa: DJ01 +import base64 import hmac +import uuid from datetime import date, datetime, timedelta from typing import Any, Iterable, List, Optional, Sequence, Union from urllib.parse import urlparse @@ -24,9 +26,12 @@ from django.utils.functional import classproperty from django.utils.text import slugify from django.utils.translation import gettext_lazy as _ +import customidenticon import jsonstore from cachalot.api import cachalot_disabled from cache_memoize import cache_memoize +from celery.result import AsyncResult +from ckeditor.fields import RichTextField from django_celery_results.models import TaskResult from django_cte import CTEQuerySet, With from dynamic_preferences.models import PerInstancePreferenceModel @@ -48,6 +53,7 @@ from polymorphic.models import PolymorphicModel from aleksis.core.data_checks import BrokenDashboardWidgetDataCheck, DataCheck, DataCheckRegistry +from .feeds import PersonalICalFeedBase from .managers import ( CurrentSiteManagerWithoutMigrations, GroupManager, @@ -305,7 +311,7 @@ class Person(ExtensibleModel): @property def unread_notifications(self) -> QuerySet: """Get all unread notifications for this person.""" - return self.notifications.filter(read=False) + return self.notifications.filter(read=False, send_at__lte=timezone.now()) @property def unread_notifications_count(self) -> int: @@ -314,7 +320,12 @@ class Person(ExtensibleModel): @property def initials(self): - return f"{self.first_name[0]}{self.last_name[0]}".upper() + initials = "" + if self.first_name: + initials += self.first_name[0] + if self.last_name: + initials += self.last_name[0] + return initials.upper() or "?" user_info_tracker = FieldTracker(fields=("first_name", "last_name", "email", "user_id")) @@ -334,6 +345,20 @@ class Person(ExtensibleModel): q = q.union(group.child_groups_recursive) return q + @property + @cache_memoize(60 * 60) + def identicon_url(self): + identicon = customidenticon.create(self.full_name, border=35) + base64_data = base64.b64encode(identicon).decode("ascii") + return f"data:image/png;base64,{base64_data}" + + @property + def avatar_url(self): + if self.avatar: + return self.avatar.url + else: + return self.identicon_url + def save(self, *args, **kwargs): # Determine all fields that were changed since last load changed = self.user_info_tracker.changed() @@ -435,6 +460,8 @@ class AdditionalField(ExtensibleModel): field_type = models.CharField( verbose_name=_("Type of field"), choices=FIELD_CHOICES, max_length=50 ) + required = models.BooleanField(verbose_name=_("Required"), default=False) + help_text = models.TextField(verbose_name=_("Help text / description"), blank=True) def __str__(self) -> str: return self.title @@ -716,6 +743,8 @@ class Notification(ExtensibleModel, TimeStampedModel): description = models.TextField(max_length=500, verbose_name=_("Description")) link = models.URLField(blank=True, verbose_name=_("Link")) + send_at = models.DateTimeField(default=timezone.now, verbose_name=_("Send notification at")) + read = models.BooleanField(default=False, verbose_name=_("Read")) sent = models.BooleanField(default=False, verbose_name=_("Sent")) @@ -724,10 +753,14 @@ class Notification(ExtensibleModel, TimeStampedModel): def save(self, **kwargs): super().save(**kwargs) - if not self.sent: - send_notification(self.pk, resend=True) - self.sent = True - super().save(**kwargs) + if not self.sent and self.send_at <= timezone.now(): + self.send() + super().save(**kwargs) + + def send(self, resend: bool = False) -> Optional[AsyncResult]: + """Send the notification to the recipient.""" + if not self.sent or resend: + return send_notification.delay(self.pk, resend=True) class Meta: verbose_name = _("Notification") @@ -965,6 +998,19 @@ class ExternalLinkWidget(DashboardWidget): verbose_name_plural = _("External link widgets") +class StaticContentWidget(DashboardWidget): + template = "core/dashboard_widget/static_content_widget.html" + + content = RichTextField(verbose_name=_("Content")) + + def get_context(self, request): + return {"title": self.title, "content": self.content} + + class Meta: + verbose_name = _("Static content widget") + verbose_name_plural = _("Static content widgets") + + class DashboardWidgetOrder(ExtensibleModel): widget = models.ForeignKey( DashboardWidget, on_delete=models.CASCADE, verbose_name=_("Dashboard widget") @@ -1307,3 +1353,41 @@ class OAuthRefreshToken(AbstractRefreshToken): """Placeholder for customising the RefreshToken model.""" pass + + +class PersonalICalUrl(models.Model): + """Calendar URL for a person. + + This is used to connect iCalendar subscriptions to a person. A person can have multiple + URLs. The URL is used to generate the iCalendar feed and have personalized results. It + is possible to create multiple URLs for the same person and the same iCal feed, e.g. to + allow a person to share and unshare their calendar with other people. + """ + + person = models.ForeignKey( + "Person", + on_delete=models.CASCADE, + related_name="calendar_urls", + verbose_name=_("Person"), + ) + uuid = models.UUIDField(default=uuid.uuid4, editable=False, verbose_name=_("UUID"), unique=True) + name = models.CharField(max_length=255, verbose_name=_("Name")) + ical_feed = models.CharField( + max_length=255, + verbose_name=_("Selected ICal feed"), + choices=PersonalICalFeedBase.subclass_choices, + ) + + @property + def ical_feed_object(self): + return PersonalICalFeedBase.subclasses_dict.get(self.ical_feed) + + class Meta: + verbose_name = _("Personal Calendar URL") + verbose_name_plural = _("Personal Calendar URLs") + + def __str__(self): + return self.name + + def get_absolute_url(self): + return reverse("ical_feed", kwargs={"slug": self.uuid}) diff --git a/aleksis/core/preferences.py b/aleksis/core/preferences.py index f1fb0227eab16a152f29918e91b37d0808471812..78b1874356a3a11eab121a56963c9aaf3595d872 100644 --- a/aleksis/core/preferences.py +++ b/aleksis/core/preferences.py @@ -271,6 +271,14 @@ class AllowPasswordChange(BooleanPreference): verbose_name = _("Allow users to change their passwords") +@site_preferences_registry.register +class AllowPasswordReset(BooleanPreference): + section = auth + name = "allow_password_reset" + default = True + verbose_name = _("Allow users to reset their passwords") + + @site_preferences_registry.register class SignupEnabled(BooleanPreference): section = auth @@ -279,6 +287,14 @@ class SignupEnabled(BooleanPreference): verbose_name = _("Enable signup") +@site_preferences_registry.register +class AllowedUsernameRegex(StringPreference): + section = auth + name = "allowed_username_regex" + default = ".+" + verbose_name = _("Regular expression for allowed usernames") + + @site_preferences_registry.register class InviteEnabled(BooleanPreference): section = auth @@ -422,6 +438,16 @@ class PersonChangeNotificationContact(StringPreference): required = False +@site_preferences_registry.register +class PersonPreferPhoto(BooleanPreference): + """Preference, whether personal photos should be displayed instead of avatars.""" + + section = account + name = "person_prefer_photo" + default = False + verbose_name = _("Prefer personal photos over avatars") + + @site_preferences_registry.register class PDFFileExpirationDuration(IntegerPreference): """PDF file expiration duration.""" diff --git a/aleksis/core/rules.py b/aleksis/core/rules.py index 022fa11a00671a3acb0775c2229a378bd3981342..a6b478f26144b9fdea74804dccdb7a1913b01c30 100644 --- a/aleksis/core/rules.py +++ b/aleksis/core/rules.py @@ -7,6 +7,7 @@ from .util.predicates import ( has_global_perm, has_object_perm, has_person, + is_assigned_to_current_person, is_current_person, is_group_owner, is_notification_recipient, @@ -357,3 +358,16 @@ rules.add_perm("core.manage_permissions", manage_person_permissions_predicate) test_pdf_generation_predicate = has_person & has_global_perm("core.test_pdf") rules.add_perm("core.test_pdf_rule", test_pdf_generation_predicate) + +# Do CRUD on PersonalICalUrls +view_ical_predicate = has_person +rules.add_perm("core.view_ical_rule", view_ical_predicate) + +create_ical_predicate = view_ical_predicate +rules.add_perm("core.create_ical_rule", create_ical_predicate) + +edit_ical_predicate = view_ical_predicate & is_assigned_to_current_person +rules.add_perm("core.edit_ical_rule", edit_ical_predicate) + +delete_ical_predicate = edit_ical_predicate +rules.add_perm("core.delete_ical_rule", delete_ical_predicate) diff --git a/aleksis/core/settings.py b/aleksis/core/settings.py index ce99ff32c66db9ca4576668308de67fe43aa6aa7..b708e991fb59d8ac978c638dda2ae150c8e66938 100644 --- a/aleksis/core/settings.py +++ b/aleksis/core/settings.py @@ -1,13 +1,20 @@ import os import warnings +from copy import deepcopy from glob import glob from socket import getfqdn +from django.utils.log import DEFAULT_LOGGING from django.utils.translation import gettext_lazy as _ from dynaconf import LazySettings -from .util.core_helpers import get_app_packages, merge_app_settings, monkey_patch +from .util.core_helpers import ( + get_app_packages, + get_app_settings_overrides, + merge_app_settings, + monkey_patch, +) monkey_patch() @@ -147,6 +154,7 @@ INSTALLED_APPS = [ "django_filters", "oauth2_provider", "rest_framework", + "dj_iconify.apps.DjIconifyConfig", ] merge_app_settings("INSTALLED_APPS", INSTALLED_APPS, True) @@ -362,6 +370,9 @@ ACCOUNT_SIGNUP_EMAIL_ENTER_TWICE = True # Enforce uniqueness of email addresses ACCOUNT_UNIQUE_EMAIL = _settings.get("auth.login.registration.unique_email", True) +# Configurable username validators +ACCOUNT_USERNAME_VALIDATORS = "aleksis.core.util.auth_helpers.custom_username_validators" + # Configuration for django-invitations # Use custom account adapter @@ -566,6 +577,8 @@ YARN_INSTALLED_APPS = [ "sortablejs", "@sentry/tracing", "luxon", + "@iconify/iconify", + "@iconify/json", ] merge_app_settings("YARN_INSTALLED_APPS", YARN_INSTALLED_APPS, True) @@ -599,6 +612,7 @@ ANY_JS = { "Sentry": {"js_url": JS_URL + "/@sentry/tracing/build/bundle.tracing.js"}, "cleavejs": {"js_url": JS_URL + "/cleave.js/dist/cleave.min.js"}, "luxon": {"js_url": JS_URL + "/luxon/build/global/luxon.min.js"}, + "iconify": {"js_url": JS_URL + "/@iconify/iconify/dist/iconify.min.js"}, } merge_app_settings("ANY_JS", ANY_JS, True) @@ -618,6 +632,8 @@ SASS_PROCESSOR_INCLUDE_DIRS = [ os.path.join(STATIC_ROOT, "public"), ] +ICONIFY_JSON_ROOT = os.path.join(JS_ROOT, "@iconify", "json") + ADMINS = _settings.get( "contact.admins", [(AUTH_INITIAL_SUPERUSER["username"], AUTH_INITIAL_SUPERUSER["email"])] ) @@ -860,21 +876,22 @@ BLEACH_STRIP_TAGS = True # Strip comments, or leave them in. BLEACH_STRIP_COMMENTS = True -LOGGING = { - "version": 1, - "disable_existing_loggers": False, - "handlers": { - "console": {"class": "logging.StreamHandler", "formatter": "verbose"}, - "null": {"class": "logging.NullHandler"}, - }, - "formatters": {"verbose": {"format": "%(levelname)s %(asctime)s %(module)s: %(message)s"}}, - "root": { - "handlers": ["console"], - "level": _settings.get("logging.level", "WARNING"), - }, - "loggers": {}, +LOGGING = deepcopy(DEFAULT_LOGGING) +# Set root logging level as default +LOGGING["root"] = { + "handlers": ["console"], + "level": _settings.get("logging.level", "WARNING"), } - +# Add null handler for selective silencing +LOGGING["handlers"]["null"] = {"class": "logging.NullHandler"} +# Make console logging independent of DEBUG +LOGGING["handlers"]["console"]["filters"].remove("require_debug_true") +# Use root log level for console +del LOGGING["handlers"]["console"]["level"] +# Disable exception mails if not desired +if not _settings.get("logging.mail_admins", True): + LOGGING["loggers"]["django"]["handlers"].remove("mail_admins") +# Disable mails on disaalowed host by default if not _settings.get("logging.disallowed_host", False): LOGGING["loggers"]["django.security.DisallowedHost"] = { "handlers": ["null"], @@ -1002,3 +1019,5 @@ merge_app_settings("SHELL_PLUS_DONT_LOAD", SHELL_PLUS_DONT_LOAD) # Add django-cleanup after all apps to ensure that it gets all signals as last app INSTALLED_APPS.append("django_cleanup.apps.CleanupConfig") + +locals().update(get_app_settings_overrides()) diff --git a/aleksis/core/static/js/copy_button.js b/aleksis/core/static/js/copy_button.js new file mode 100644 index 0000000000000000000000000000000000000000..554f6230e4f9c8b9bb012875e31da25c4f61c2c6 --- /dev/null +++ b/aleksis/core/static/js/copy_button.js @@ -0,0 +1,16 @@ +$(".copy-button").click((e) => { + const target = $(e.currentTarget); + const input = $("#" + target.data("target")); + const copy_icon = target.children(".copy-icon-copy").first(); + const check_icon = target.children(".copy-icon-success").first(); + + console.log("Copying to clipboard"); + navigator.clipboard.writeText(input.val()).then(r => { + check_icon.show(); + copy_icon.hide(); + setTimeout(() => { + check_icon.hide(); + copy_icon.show(); + }, 1000); + }); +}); diff --git a/aleksis/core/static/js/main.js b/aleksis/core/static/js/main.js index 9b4c133e1ae7db5906645963cfd7182da313ca01..b735e2bb53d4a3c6a8f5b1edc9a9bb307214e1b4 100644 --- a/aleksis/core/static/js/main.js +++ b/aleksis/core/static/js/main.js @@ -121,6 +121,10 @@ $(document).ready(function () { // Initialize dropdown [MAT] $('.dropdown-trigger').dropdown(); + $('.navbar-dropdown-trigger').dropdown({ + "coverTrigger": false, + "constrainWidth": false, + }); // If JS is activated, the language form will be auto-submitted $('.language-field select').change(function () { @@ -188,6 +192,6 @@ $(document).ready(function () { const channel = new BroadcastChannel("cache-or-not"); channel.addEventListener("message", event => { if ((event.data) && !($("#cache-alert").length)) { - $("main").prepend('<div id="cache-alert" class="alert warning"><p><i class="material-icons left">warning</i>' + gettext("This page may contain outdated information since there is no internet connection.") + '</p> </div>') + $("main").prepend('<div id="cache-alert" class="alert warning"><p><i class="material-icons iconify left" data-icon="mdi:alert-outline"></i>' + gettext("This page may contain outdated information since there is no internet connection.") + '</p> </div>') } }); diff --git a/aleksis/core/static/js/progress.js b/aleksis/core/static/js/progress.js index 0b2509006029421273159617c9ff2646bb12800b..5fa0213f8466738466158a56ca6e1df50654a811 100644 --- a/aleksis/core/static/js/progress.js +++ b/aleksis/core/static/js/progress.js @@ -9,11 +9,11 @@ const STYLE_CLASSES = { }; const ICONS = { - 10: 'info', - 20: 'info', - 25: 'check_circle', - 30: 'warning', - 40: 'error', + 10: 'mdi:information', + 20: 'mdi:information', + 25: 'mdi:check-circle', + 30: 'mdi:alert-outline', + 40: 'mdi:alert-octagon-outline', }; function setProgress(progress) { @@ -21,7 +21,7 @@ function setProgress(progress) { } function renderMessageBox(level, text) { - return '<div class="alert ' + STYLE_CLASSES[level] + '"><p><i class="material-icons left">' + ICONS[level] + '</i>' + text + '</p></div>'; + return '<div class="alert ' + STYLE_CLASSES[level] + '"><p><i class="material-icons iconify left" data-icon="' + ICONS[level] + '"></i>' + text + '</p></div>'; } function customProgress(progressBarElement, progressBarMessageElement, progress) { @@ -44,7 +44,7 @@ function customProgress(progressBarElement, progressBarMessageElement, progress) function customSuccess(progressBarElement, progressBarMessageElement) { setProgress(100); $("#result-alert").addClass("success"); - $("#result-icon").text("check_circle"); + $("#result-icon").attr("data-icon", "mdi:check-circle-outline"); $("#result-text").text(OPTIONS.success); $("#result-box").show(); $("#result-button").show(); @@ -57,7 +57,7 @@ function customSuccess(progressBarElement, progressBarMessageElement) { function customError(progressBarElement, progressBarMessageElement) { setProgress(100); $("#result-alert").addClass("error"); - $("#result-icon").text("error"); + $("#result-icon").attr("data-icon", "mdi:alert-octagon-outline"); $("#result-text").text(OPTIONS.error); $("#result-box").show(); } diff --git a/aleksis/core/static/public/style.scss b/aleksis/core/static/public/style.scss index e448c8aa54e55d4667c8dde9826c37e70fed6db0..5a35561c389f5656fd573e8f9b698ae456d42ad5 100644 --- a/aleksis/core/static/public/style.scss +++ b/aleksis/core/static/public/style.scss @@ -24,6 +24,10 @@ rect#background { background-color: lighten($primary-color, 5%); } +.waves-effect.waves-secondary .waves-ripple { + background-color: lighten($secondary-color, 5%); +} + .success { @extend .light-green, .lighten-3 } @@ -77,6 +81,9 @@ header, main, footer { .materialize-circle { @extend .circle; } +.collection .collection-item.avatar > .materialize-circle > .materialize-circle { + left: 0; +} /**********/ /* HEADER */ @@ -211,25 +218,6 @@ div#search-results { } -// Sidenav trigger - -header a.sidenav-trigger { - position: absolute; - left: 7.5%; - top: 0; - - height: 64px; - font-size: 38px; - - float: none; - - text-align: center; - color: white; - - z-index: 2; -} - - // Footer .footer-icon { @@ -445,41 +433,17 @@ th.orderable > a { height: inherit; } -th.orderable > a::after { - @extend .material-icons; - font-family: 'Material Icons'; - font-weight: normal; - font-style: normal; - font-size: 24px; - display: inline-block; - line-height: 1; - text-transform: none; - letter-spacing: normal; - word-wrap: normal; - white-space: nowrap; - direction: ltr; - -webkit-font-smoothing: antialiased; - text-rendering: optimizeLegibility; - -moz-osx-font-smoothing: grayscale; - font-feature-settings: 'liga'; - float: right; - content: "unfold_more"; +th.orderable { + background: no-repeat right center; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M12,18.17L8.83,15L7.42,16.41L12,21L16.59,16.41L15.17,15M12,5.83L15.17,9L16.58,7.59L12,3L7.41,7.59L8.83,9L12,5.83Z' /%3E%3C/svg%3E"); } -th.orderable.asc > a { - color: inherit; - - &::after { - content: "expand_less"; - } +th.orderable.asc { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M7.41,15.41L12,10.83L16.59,15.41L18,14L12,8L6,14L7.41,15.41Z' /%3E%3C/svg%3E"); } -th.orderable.desc > a { - color: inherit; - - &::after { - content: "expand_more"; - } +th.orderable.desc { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z' /%3E%3C/svg%3E"); } /*+++++++*/ @@ -828,8 +792,8 @@ $person-logo-size: 20vh; & img { border-radius: 50%; - width: 20vh; - height: 20vh; + width: 100%; + height: 100%; object-fit: cover; } } @@ -844,6 +808,64 @@ $person-logo-size: 20vh; user-select: none; cursor: default; border-radius: 50%; + height: unset; +} + +.nav-wrapper { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 1rem; + > a { + position: static!important; + transform: none!important; + } + & .nav-spacer { + width: 60px; + } + & ul.account-nav { + display: flex; + margin-inline: 7.5px; + & > li > a { + padding: 0 7.5px; + } + } +} + +.nav-wrapper .navbar-dropdown-trigger { + cursor: pointer; + height: 100%; + display: grid; +} + +.navbar-dropdown-trigger .clip-circle { + margin: auto; + width: $navbar-height*0.75; + height: $navbar-height*0.75; + cursor: pointer; + + &.no-image, &.no-image > i.material-icons { + font-size: calc(#{$navbar-height} * 0.75 * 0.5); + color: #6f6f6f; + background: #f2f2f2; + line-height: $navbar-height*0.75; + width: $navbar-height*0.75; + cursor: pointer; + } +} + +a.new-notification { + position: relative; + &:after { + content: ""; + position: absolute; + width: 10px; + height: 10px; + bottom: 30%; + right: 19%; + background-color: $secondary-color; + border-radius: 50%; + } } #hero-bg { @@ -937,3 +959,35 @@ $person-logo-size: 20vh; @extend .application-circle; object-fit: cover; } + +svg.iconify { + @extend i; +} + +.btn .iconify.material-icons, .btn-flat .iconify.material-icons{ + height: $button-height; +} + +// Login Page +.login-card-action { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); + row-gap: 0.7rem; + & *:last-child { + grid-column: -2; + text-align: center; + } +} + +.btn-small-line-height { + line-height: $button-small-height; +} + +.btn-smaller-padding { + padding: 0 8px; +} + +p.ical-description { + margin: 0; + font-weight: 300; +} diff --git a/aleksis/core/tasks.py b/aleksis/core/tasks.py index 847fc41281a0266cff16bbe2117e326e13abc0dd..7b7e529b3a1fa21c5a6620170296d9ee1eb777ec 100644 --- a/aleksis/core/tasks.py +++ b/aleksis/core/tasks.py @@ -4,6 +4,7 @@ from django.conf import settings from django.core import management from .celery import app +from .util.notifications import _send_due_notifications as _send_due_notifications from .util.notifications import send_notification as _send_notification @@ -48,3 +49,9 @@ def clear_oauth_tokens(): from oauth2_provider.models import clear_expired # noqa return clear_expired() + + +@app.task(run_every=timedelta(minutes=5)) +def send_notifications(): + """Send due notifications to users.""" + _send_due_notifications() diff --git a/aleksis/core/templates/403.html b/aleksis/core/templates/403.html index cbc962a93da9f8e8efd91d1af1b493c254834281..03e600b49e533de68bd25e8f07ea6ed4dbc8fb51 100644 --- a/aleksis/core/templates/403.html +++ b/aleksis/core/templates/403.html @@ -6,7 +6,7 @@ <div class="container"> <div class="card red"> <div class="card-content white-text"> - <i class="material-icons small left">error_outline</i> + <i class="material-icons iconify small left" data-icon="mdi:alert-octagon-outline"></i> <span class="card-title"> {% if exception %} {{ exception }} diff --git a/aleksis/core/templates/404.html b/aleksis/core/templates/404.html index cf68c12bf63624ecf40107ee6f3994b288548c3c..969166bea0fb127705f19d8462569a60b4ae88ea 100644 --- a/aleksis/core/templates/404.html +++ b/aleksis/core/templates/404.html @@ -6,7 +6,7 @@ <div class="container"> <div class="card red"> <div class="card-content white-text"> - <i class="material-icons small left">error_outline</i> + <i class="material-icons iconify small left" data-icon="mdi:alert-octagon-outline"></i> <span class="card-title">{{ exception }}</span> <p> {% blocktrans %} diff --git a/aleksis/core/templates/500.html b/aleksis/core/templates/500.html index bf56e08db5b6fd6d6052585ce216bd50cbea3796..fee566258f556cf5ea2922abd170873d3c212733 100644 --- a/aleksis/core/templates/500.html +++ b/aleksis/core/templates/500.html @@ -6,7 +6,7 @@ <div class="container"> <div class="card red"> <div class="card-content white-text"> - <i class="material-icons small left">error_outline</i> + <i class="material-icons iconify small left" data-icon="mdi:alert-octagon-outline"></i> <span class="card-title">{% trans "Error" %} (500): {% blocktrans %}An unexpected error has occured.{% endblocktrans %}</span> <p> diff --git a/aleksis/core/templates/503.html b/aleksis/core/templates/503.html index 97d76caa4fab9e641bf522779f7c282a9ab2d2dd..21578e63238f09081e35081b4ed45cf1e0a47a1c 100644 --- a/aleksis/core/templates/503.html +++ b/aleksis/core/templates/503.html @@ -6,7 +6,7 @@ <div class="container"> <div class="card red"> <div class="card-content white-text"> - <i class="material-icons small left">error_outline</i> + <i class="material-icons iconify small left" data-icon="mdi:alert-octagon-outline"></i> <span class="card-title">{% blocktrans %}The maintenance mode is currently enabled. Please try again later.{% endblocktrans %}</span> <p> diff --git a/aleksis/core/templates/account/account_inactive.html b/aleksis/core/templates/account/account_inactive.html index 5c328abcfbca48c6499f71b4b11fac5f1f91ccad..e5fc162e6eea9c1a3418d2a151880dfcdd9003f9 100644 --- a/aleksis/core/templates/account/account_inactive.html +++ b/aleksis/core/templates/account/account_inactive.html @@ -10,7 +10,7 @@ <div class="card red"> <div class="card-content white-text"> <div class="card-title"> - <i class="material-icons small left">error_outline</i> + <i class="material-icons iconify small left" data-icon="mdi:alert-octagon-outline"></i> {% blocktrans %}Account inactive.{% endblocktrans %} </div> <p> diff --git a/aleksis/core/templates/account/email_confirm.html b/aleksis/core/templates/account/email_confirm.html index 0f560556b6567f0a2133d0efb5c324730761243c..189df8516b9446550783fd8ecb7d2751e38dd2d3 100644 --- a/aleksis/core/templates/account/email_confirm.html +++ b/aleksis/core/templates/account/email_confirm.html @@ -15,13 +15,13 @@ {% csrf_token %} {% form form=form %}{% endform %} {% trans "Confirm" as caption %} - {% include "core/partials/save_button.html" with caption=caption icon="how_to_reg" %} + {% include "core/partials/save_button.html" with caption=caption icon="mdi:account-plus-outline" %} </form> {% else %} {% url "account_email" as email_url %} <div class="alert warning"> <p> - <i class="material-icons left">warning</i> + <i class="material-icons iconify left" data-icon="mdi:alert-outline"></i> {% blocktrans %}This e-mail confirmation link expired or is invalid. Please <a href="{{ email_url }}">issue a new e-mail confirmation request</a>.{% endblocktrans %} </p> </div> diff --git a/aleksis/core/templates/account/password_change.html b/aleksis/core/templates/account/password_change.html index be331751b31187a792b72cf97a178ddddf4de42b..3bcf728890412e39f69929db3d85c945343a5126 100644 --- a/aleksis/core/templates/account/password_change.html +++ b/aleksis/core/templates/account/password_change.html @@ -8,7 +8,7 @@ {% block content %} <div class="alert warning"> <p> - <i class="material-icons left">warning</i> + <i class="material-icons iconify left" data-icon="mdi:alert-outline"></i> {% trans "Forgot your current password? Click here to reset it:" %} <a href="{% url 'account_reset_password' %}">{% trans "Forgot Password?" %}</a>. </p> </div> @@ -17,7 +17,7 @@ {% csrf_token %} {% form form=form %}{% endform %} {% trans "Change password" as caption %} - {% include "core/partials/save_button.html" with caption=caption icon="priority_high" %} + {% include "core/partials/save_button.html" with caption=caption icon="mdi:exclamation" %} </form> {% endblock %} diff --git a/aleksis/core/templates/account/password_change_disabled.html b/aleksis/core/templates/account/password_change_disabled.html index 131df489102ec8d257f584892ceb94f04d8e93b1..996ecfa9fa6368ab45772be4064dc058ac59567f 100644 --- a/aleksis/core/templates/account/password_change_disabled.html +++ b/aleksis/core/templates/account/password_change_disabled.html @@ -9,7 +9,7 @@ <div class="container"> <div class="card red"> <div class="card-content white-text"> - <div class="material-icons small left">error_outline</div> + <div class="material-icons iconify small left" data-icon="mdi:alert-octagon-outline"></div> <span class="card-title">{% blocktrans %}Changing of password disabled.{% endblocktrans %}</span> <p> {% blocktrans %} diff --git a/aleksis/core/templates/account/password_reset.html b/aleksis/core/templates/account/password_reset.html index 4e93262643e0e28919e405c9b2f0465bf2a2bcf8..6253e0df3643b9fb6434bee35944583c40056b15 100644 --- a/aleksis/core/templates/account/password_reset.html +++ b/aleksis/core/templates/account/password_reset.html @@ -15,13 +15,13 @@ <div class="card-title">{% trans "Reset password" %}</div> <p class="margin-bottom"> {% blocktrans %}Forgotten your password? Enter your e-mail address below, and we'll send you an e-mail allowing you to reset it.{% endblocktrans %} - </p> + </p> {% csrf_token %} {% form form=form %}{% endform %} - </div> + </div> <div class="card-action-light"> {% trans "Reset password" as caption %} - {% include "core/partials/save_button.html" with caption=caption icon="priority_high" %} + {% include "core/partials/save_button.html" with caption=caption icon="mdi:exclamation" %} </div> </form> </div> diff --git a/aleksis/core/templates/account/password_reset_done.html b/aleksis/core/templates/account/password_reset_done.html index ddd8b3871c242e8ee2eb9b22cc472778a3b096b9..f97816fea191b4435d53ea6ea61884186883ccbb 100644 --- a/aleksis/core/templates/account/password_reset_done.html +++ b/aleksis/core/templates/account/password_reset_done.html @@ -11,7 +11,7 @@ <div class="card green"> <div class="card-content white-text"> <div class="card-title"> - <i class="material-icons small left">check_circle</i> + <i class="material-icons iconify small left" data-icon="mdi:check-circle-outline"></i> {% blocktrans %}Password reset mail sent{% endblocktrans %} </div> <p> diff --git a/aleksis/core/templates/account/password_reset_from_key.html b/aleksis/core/templates/account/password_reset_from_key.html index 4b2b91a28c875e7c1337fd0543646eae881da356..7afae12f4b0141d0a8a9af2ba2ecb33e893c41a0 100644 --- a/aleksis/core/templates/account/password_reset_from_key.html +++ b/aleksis/core/templates/account/password_reset_from_key.html @@ -11,7 +11,7 @@ <div class="card red"> <div class="card-content white-text"> <div class="card-title"> - <i class="material-icons small left">error_outline</i> + <i class="material-icons iconify small left" data-icon="mdi:alert-octagon-outline"></i> {% blocktrans %}Bad token{% endblocktrans %} </div> <p> @@ -44,7 +44,7 @@ {% form form=form %}{% endform %} <div class="card-action-light"> {% trans "Change password" as caption %} - {% include "core/partials/save_button.html" with caption=caption icon="priority_high" %} + {% include "core/partials/save_button.html" with caption=caption icon="mdi:exclamation" %} </div> </div> </form> @@ -52,7 +52,7 @@ </div> <div class="alert success"> <p> - <i class="material-icons left">success</i> + <i class="material-icons iconify left" data-icon="mdi:check"></i> {% blocktrans %} Your password is now changed! {% endblocktrans %} diff --git a/aleksis/core/templates/account/password_reset_from_key_done.html b/aleksis/core/templates/account/password_reset_from_key_done.html index b32538e53ee5b1b0f2115e645d0f955d235ba958..8fdd9232f065d093549358c485b523a40d83a996 100644 --- a/aleksis/core/templates/account/password_reset_from_key_done.html +++ b/aleksis/core/templates/account/password_reset_from_key_done.html @@ -9,7 +9,7 @@ <div class="container"> <div class="card green"> <div class="card-content white-text"> - <div class="material-icons small left">success</div> + <i class="material-icons iconify small left" data-icon="mdi:check"></i> <span class="card-title">{% blocktrans %}Password changed!{% endblocktrans %}</span> <p> {% blocktrans %} diff --git a/aleksis/core/templates/account/password_set.html b/aleksis/core/templates/account/password_set.html index 08819c1e0904f53e62f11d86bd2e82ccef7b2469..2c550502354719da4959adb7c9b12739378b1c23 100644 --- a/aleksis/core/templates/account/password_set.html +++ b/aleksis/core/templates/account/password_set.html @@ -10,7 +10,7 @@ {% csrf_token %} {% form form=form %}{% endform %} {% trans "Set password" as caption %} - {% include "core/partials/save_button.html" with caption=caption icon="priority_high" %} + {% include "core/partials/save_button.html" with caption=caption icon="mdi:exclamation" %} </form> {% endblock %} diff --git a/aleksis/core/templates/account/signup.html b/aleksis/core/templates/account/signup.html index 8885e3902af13c609a69a595df3d125b66dc79ce..eb606114eae4fbbab8cab0543a59ce549e7bb35d 100644 --- a/aleksis/core/templates/account/signup.html +++ b/aleksis/core/templates/account/signup.html @@ -8,7 +8,7 @@ {% block content %} <div class="alert warning"> <p> - <i class="material-icons left">warning</i> + <i class="material-icons iconify left" data-icon="mdi:alert-outline"></i> {% blocktrans %}Already have an account? Then please <a href="{{ login_url }}">sign in</a>.{% endblocktrans %} </p> </div> @@ -20,7 +20,7 @@ <input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" /> {% endif %} {% trans "Sign up" as caption %} - {% include "core/partials/save_button.html" with caption=caption icon="how_to_reg" %} + {% include "core/partials/save_button.html" with caption=caption icon="mdi:account-plus-outline" %} </form> {% endblock %} diff --git a/aleksis/core/templates/account/signup_closed.html b/aleksis/core/templates/account/signup_closed.html index 0d5cbd51095e9c24fceacbc4ba8f6a510a5705a9..ca0a124ec3922d6a530bec9548863cb981a0b629 100644 --- a/aleksis/core/templates/account/signup_closed.html +++ b/aleksis/core/templates/account/signup_closed.html @@ -10,7 +10,7 @@ <div class="card red"> <div class="card-content white-text"> <div class="card-title"> - <i class="material-icons small left">error_outline</i> + <i class="material-icons iconify small left" data-icon="mdi:alert-octagon-outline"></i> {% blocktrans %}Signup closed.{% endblocktrans %} </div> <p> diff --git a/aleksis/core/templates/account/verification_email_required.html b/aleksis/core/templates/account/verification_email_required.html index b1a4a482a3ee64b0f2c6339e76ed44c66b29ef50..d1f826fff71270f8b207e03e070ac1373ec85924 100644 --- a/aleksis/core/templates/account/verification_email_required.html +++ b/aleksis/core/templates/account/verification_email_required.html @@ -10,7 +10,7 @@ <div class="container"> <div class="card green"> <div class="card-content white-text"> - <div class="material-icons small left">success</div> + <div class="material-icons iconify small left" data-icon="mdi:check"></div> <span class="card-title">{% blocktrans %}Password reset mail sent!{% endblocktrans %}</span> <p> {% blocktrans %} diff --git a/aleksis/core/templates/account/verification_sent.html b/aleksis/core/templates/account/verification_sent.html index df3ae47c82911a01997ac9f4d7919c9e1b95a36e..65bb4c188c3279a5d2bf4bdab37edf92b9fa7760 100644 --- a/aleksis/core/templates/account/verification_sent.html +++ b/aleksis/core/templates/account/verification_sent.html @@ -10,7 +10,7 @@ <div class="container"> <div class="card red"> <div class="card-content white-text"> - <div class="material-icons small left">error_outline</div> + <div class="material-icons iconify small left" data-icon="mdi:alert-octagon-outline"></div> <span class="card-title">{% blocktrans %}Verify your email!{% endblocktrans %}</span> <p> {% blocktrans %} diff --git a/aleksis/core/templates/components/materialize-chips.html b/aleksis/core/templates/components/materialize-chips.html index e02662adc354dcb1e3784804fdf46783b282ea39..c4bea23ae6ec79b4e3598053b81348cb6286254f 100644 --- a/aleksis/core/templates/components/materialize-chips.html +++ b/aleksis/core/templates/components/materialize-chips.html @@ -3,10 +3,10 @@ <img class="{{ img_classes }}" src="{{ img }}" alt="{{ alt }}"> {% endif %} {% if icon %} - <i class="material-icons left">{{ icon }}</i> + <i class="material-icons iconify left" data-icon="{{ icon }}"></i> {% endif %} {{ content }} {% if close %} - <i class="close material-icons"></i> + <i class="material-icons iconify" data-icon="mdi:close"></i> {% endif %} </div> diff --git a/aleksis/core/templates/components/msgbox.html b/aleksis/core/templates/components/msgbox.html index 8903ebd1a750f1965326cd59499605872b997fc0..de7b12e5eafdfa0974989c20a86dfda3c8372517 100644 --- a/aleksis/core/templates/components/msgbox.html +++ b/aleksis/core/templates/components/msgbox.html @@ -2,7 +2,7 @@ <div class="alert {{ status }}"> <div> {% if icon != "" %} - <i class="material-icons left">{{ icon }}</i> + <i class="material-icons iconify left" data-icon="{{ icon }}"></i> {% endif %} {{ msg }} </div> diff --git a/aleksis/core/templates/components/pagination.html b/aleksis/core/templates/components/pagination.html index 5eb33cdf8fff272d766a628e1656c109ed87e32c..03d05ecf053ddb498d6ab5181f1b774b24e9884a 100644 --- a/aleksis/core/templates/components/pagination.html +++ b/aleksis/core/templates/components/pagination.html @@ -5,7 +5,7 @@ {% if page.has_previous %} <li class="waves-effect"> <a href="?page={{ page.previous_page_number }}" class="page-link"> - <i class="material-icons">chevron_left</i> + <i class="material-icons iconify" data-icon="mdi:chevron-right"></i> </a> </li> {% endif %} @@ -21,7 +21,7 @@ {% if page.has_next %} <li class="waves-effect"> <a href="?page={{ page.next_page_number }}" class="page-link"> - <i class="material-icons">chevron_right</i> + <i class="material-icons iconify" data-icon="mdi:chevron-right"></i> </a> </li> {% endif %} diff --git a/aleksis/core/templates/components/text_collapsible.html b/aleksis/core/templates/components/text_collapsible.html index 7096e8e9311d7fdcd5f6cffb6af0934fa9d56977..bceac0eb58eb83cc9def914fce97d625ac13802a 100644 --- a/aleksis/core/templates/components/text_collapsible.html +++ b/aleksis/core/templates/components/text_collapsible.html @@ -3,11 +3,11 @@ {% include template with item=qs.first %} – {% include template with item=qs.last %} </span> - <i class="material-icons open-icon" title="Show more">add_circle_outline</i> + <i class="material-icons iconify open-icon" title="Show more">plus-circle-outline</i> <span class="b"> {% for item in qs %} {% include template with item=item %} {% endfor %} </span> - <i class="material-icons close-icon" title="Show less">remove_circle_outline</i> + <i class="material-icons iconify close-icon" title="Show less">minus-circle-outline</i> </span> diff --git a/aleksis/core/templates/core/additional_field/list.html b/aleksis/core/templates/core/additional_field/list.html index 1ba2a77a32c528b8443f4dc5a4c201b5739414fe..13f320520f2c695e315dd28cec9c78d367d1b6bf 100644 --- a/aleksis/core/templates/core/additional_field/list.html +++ b/aleksis/core/templates/core/additional_field/list.html @@ -10,7 +10,7 @@ {% block content %} <a class="btn green waves-effect waves-light" href="{% url 'create_additional_field' %}"> - <i class="material-icons left">add</i> + <i class="material-icons left iconify" data-icon="mdi:add"></i> {% trans "Create additional field" %} </a> diff --git a/aleksis/core/templates/core/announcement/form.html b/aleksis/core/templates/core/announcement/form.html index 44d60280c6d358f74c60cb9c5ccff2c7aba89b07..f085758a3395ca74de1dba8e0affec9fb453cc03 100644 --- a/aleksis/core/templates/core/announcement/form.html +++ b/aleksis/core/templates/core/announcement/form.html @@ -30,7 +30,7 @@ {% form form=form %}{% endform %} <button type="submit" class="btn green waves-effect waves-light"> - <i class="material-icons left">save</i> + <i class="material-icons left iconify" data-icon="mdi:content-save-outline"></i> {% trans "Save und publish announcement" %} </button> </form> diff --git a/aleksis/core/templates/core/announcement/list.html b/aleksis/core/templates/core/announcement/list.html index 9f84617e255c78b7ee37e502c212e0704aa1da5e..763f4f10cce6c240f80812502c7a378bbdb3a0f7 100644 --- a/aleksis/core/templates/core/announcement/list.html +++ b/aleksis/core/templates/core/announcement/list.html @@ -9,7 +9,7 @@ {% block content %} <a class="btn green waves-effect waves-light" href="{% url "add_announcement" %}"> - <i class="material-icons left">add</i> + <i class="material-icons left iconify" data-icon="mdi:add"></i> {% trans "Publish new announcement" %} </a> <table class="highlight"> @@ -32,13 +32,13 @@ <td> <a class="btn-flat waves-effect waves-orange orange-text" href="{% url "edit_announcement" announcement.id %}"> - <i class="material-icons left">edit</i> + <i class="material-icons left iconify" data-icon="mdi:pencil-outline"></i> {% trans "Edit" %} </a> <form action="{% url "delete_announcement" announcement.id %}" method="post"> {% csrf_token %} <button class="btn-flat waves-effect waves-re red-text" type="submit"> - <i class="material-icons left">delete</i> + <i class="material-icons left iconify" data-icon="mdi:delete-outline"></i> {% trans "Delete" %} </button> </form> diff --git a/aleksis/core/templates/core/base.html b/aleksis/core/templates/core/base.html index 745a6668cdc42eb265536950a0acbecfb57ee537..3158986ac5ed921244b43663e64c2fe9d728cd32 100644 --- a/aleksis/core/templates/core/base.html +++ b/aleksis/core/templates/core/base.html @@ -53,6 +53,12 @@ </script> {% endif %} + <script type="text/javascript" src="{% url 'config.js' %}"></script> + {% include_js "iconify" %} + + <script type="text/javascript" src="{% url 'config.js' %}"></script> + {% include_js "iconify" %} + {# Include jQuery early to provide $(document).ready #} {% include_js "jQuery" %} @@ -61,32 +67,60 @@ <body {% if no_menu %}class="without-menu"{% endif %}> <header> - <!-- Menu button (sidenav) --> - <div class="container"> - <a href="#" data-target="slide-out" class="top-nav sidenav-trigger hide-on-large-only"> - <i class="material-icons">menu</i> - </a> - </div> - <!-- Nav bar (logged in as, logout) --> <nav class="nav-extended"> <div class="nav-wrapper"> + <a href="#" data-target="slide-out" class="top-nav sidenav-trigger hide-on-large-only"> + <i class="material-icons iconify" data-icon="mdi:menu"></i> + </a> + <a class="brand-logo" href="/">{{ request.site.preferences.general__title }}</a> - <ul id="nav-mobile" class="right hide-on-med-and-down"> - {% if user.is_authenticated %} - <li>{% trans "Logged in as" %} {{ user.get_username }}</li> + {% if user.is_authenticated %} + <ul class="account-nav"> + {% trans "Notifications" as notifications_text %} <li> - <a href="{% url 'logout' %}">{% trans "Logout" %} <i class="material-icons right">exit_to_app</i></a> + <a href="{% url "notifications" %}" data-position="bottom" + class="tooltipped {% if request.user.person.unread_notifications_count > 0 %}new-notification{% endif %}" + data-tooltip="{{ notifications_text }}" aria-label="{{ notifications_text }}"> + <i class="material-icons iconify" data-icon="mdi:bell-outline"></i> + </a> </li> - {% endif %} - </ul> + <li> + <a href="#!" class="navbar-dropdown-trigger" data-target="account-dropdown"> + {{ request.user.person.identicon }} + {% include "core/partials/avatar_content.html" with person_or_user=request.user.person %} + </a> + </li> + </ul> + {% else %} + <span class="nav-spacer"></span> + {% endif %} </div> <div class="nav-content"> {% block nav_content %}{% endblock %} </div> </nav> + {% get_menu "NAVBAR_ACCOUNT_MENU" as account_menu %} + <ul id="account-dropdown" class="dropdown-content"> + {% for item in account_menu %} + {% if item.divider %} + <li class="divider"></li> + {% endif %} + <li> + <a href="{{ item.url }}"> + {% if item.icon %} + <i class="material-icons">{{ item.icon }}</i> + {% elif item.svg_icon %} + <i class="material-icons iconify" data-icon="{{ item.svg_icon }}"></i> + {% endif %} + {{ item.name }} + </a> + </li> + {% endfor %} + </ul> + <!-- Main nav (sidenav) --> {% if not no_menu %} <ul id="slide-out" class="sidenav sidenav-fixed"> @@ -104,7 +138,7 @@ <div class="search-wrapper"> <input id="search" name="q" type="search" enterkeyhint="search" placeholder="{% trans "Search" %}"> <button class="btn btn-flat search-button" type="submit" aria-label="{% trans "Search" %}"> - <i class="material-icons">search</i> + <i class="material-icons iconify" data-icon="mdi:search">search</i> </button> <div class="progress" id="search-loader"> <div class="indeterminate"></div> @@ -127,16 +161,16 @@ {% if messages %} {% for message in messages %} <figure class="alert {% if message.tags %}{{ message.tags }}{% else %}info{% endif %}"> - {% if message.tags == "success" %} - <i class="material-icons left">check_circle</i> - {% elif message.tags == "info" %} - <i class="material-icons left">info</i> - {% elif message.tags == "warning" %} - <i class="material-icons left">warning</i> - {% elif message.tags == "error" %} - <i class="material-icons left">error</i> - {% endif %} - {{ message }} + {% if message.tags == "success" %} + <i class="material-icons left iconify" data-icon="mdi:check-circle-outline"></i> + {% elif message.tags == "info" %} + <i class="material-icons left iconify" data-icon="mdi:information-outline"></i> + {% elif message.tags == "warning" %} + <i class="material-icons left iconify" data-icon="mdi:alert-outline"></i> + {% elif message.tags == "error" %} + <i class="material-icons left iconify" data-icon="mdi:alert-octagon-outline"></i> + {% endif %} + {{ message }} </figure> {% endfor %} {% endif %} diff --git a/aleksis/core/templates/core/dashboard_widget/dashboardwidget_broken.html b/aleksis/core/templates/core/dashboard_widget/dashboardwidget_broken.html index 23a18714637bf90d9610547210b412eec6fae729..950f925e138e1f3583e0099926fbcbaf79f581e3 100644 --- a/aleksis/core/templates/core/dashboard_widget/dashboardwidget_broken.html +++ b/aleksis/core/templates/core/dashboard_widget/dashboardwidget_broken.html @@ -2,7 +2,7 @@ <div class="card horizontal"> <div class="card-image"> - <i class="material-icons large red-text stacked-card-icon">assignment_late</i> + <i class="material-icons large red-text stacked-card-icon iconify" data-icon="mdi:clipboard-alert-outline"></i> </div> <div class="card-stacked"> <div class="card-content"> diff --git a/aleksis/core/templates/core/dashboard_widget/list.html b/aleksis/core/templates/core/dashboard_widget/list.html index ec5fac70d20c3997d2a02128691b947719eb4309..78356cfed3e3b3cce6358855cbdf615d07712a0d 100644 --- a/aleksis/core/templates/core/dashboard_widget/list.html +++ b/aleksis/core/templates/core/dashboard_widget/list.html @@ -11,7 +11,7 @@ {% block content %} <a class="btn green waves-effect waves-light dropdown-trigger" href="#" data-target="widget-dropdown"> - <i class="material-icons left">add</i> + <i class="material-icons left iconify" data-icon="mdi:add"></i> {% trans "Create dashboard widget" %} </a> <ul id="widget-dropdown" class="dropdown-content"> @@ -28,7 +28,7 @@ {% has_perm "core.edit_default_dashboard_rule" user as can_edit_default_dashboard %} {% if can_edit_default_dashboard %} <a class="btn orange waves-effect waves-light" href="{% url "edit_default_dashboard" %}"> - <i class="material-icons left">edit</i> + <i class="material-icons left iconify" data-icon="mdi:pencil-outline"></i> {% trans "Edit default dashboard" %} </a> {% endif %} diff --git a/aleksis/core/templates/core/dashboard_widget/static_content_widget.html b/aleksis/core/templates/core/dashboard_widget/static_content_widget.html new file mode 100644 index 0000000000000000000000000000000000000000..96e5549d5890e4cc95dbe6b4a843f1b1612c5d7f --- /dev/null +++ b/aleksis/core/templates/core/dashboard_widget/static_content_widget.html @@ -0,0 +1,10 @@ +{% load html_helpers %} + +<div class="card" style="padding: 2em"> + <div class="card-title"> + {{ title }} + </div> + <div class="card-text"> + {{ content|add_class_to_el:"ul, browser-default"|safe }} + </div> +</div> diff --git a/aleksis/core/templates/core/data_check/list.html b/aleksis/core/templates/core/data_check/list.html index 36d83d4cd7d3c917db98c104586bd2aa9c82c139..b192dcdc1623a05fa3ad7b3568b4b8bdc3622abf 100644 --- a/aleksis/core/templates/core/data_check/list.html +++ b/aleksis/core/templates/core/data_check/list.html @@ -11,14 +11,14 @@ {% block content %} <a class="btn green waves-effect waves-light" href="{% url "data_check_run" %}"> - <i class="material-icons left">refresh</i> + <i class="material-icons left iconify" data-icon="mdi:refresh"></i> {% trans "Check data again" %} </a> {% if results %} <div class="card"> <div class="card-content"> - <i class="material-icons left medium red-text">warning</i> + <i class="material-icons left medium red-text iconify" data-icon="mdi:alert-outline"></i> <span class="card-title">{% trans "The system detected some problems with your data." %}</span> <p>{% blocktrans %}Please go through all data and check whether some extra action is needed.{% endblocktrans %}</p> @@ -27,7 +27,7 @@ {% else %} <div class="card"> <div class="card-content"> - <i class="material-icons left medium green-text">check_circle</i> + <i class="material-icons left medium green-text iconify" data-icon="mdi:check-circle-outline"></i> <span class="card-title">{% trans "Everything is fine." %}</span> <p>{% blocktrans %}The system hasn't detected any problems with your data.{% endblocktrans %}</p> </div> @@ -86,7 +86,7 @@ <div class="card-title">{% trans "Registered checks" %}</div> <div class="alert primary"> <div> - <i class="material-icons left">info</i> + <i class="material-icons left iconify" data-icon="mdi:information-outline"></i> {% blocktrans %} The system will check for the following problems: {% endblocktrans %} @@ -95,7 +95,7 @@ <ul class="collection"> {% for check in registered_checks %} <li class="collection-item"> - <i class="material-icons left">check</i> + <i class="material-icons left iconify" data-icon="mdi:check"></i> {{ check.verbose_name }} </li> {% endfor %} diff --git a/aleksis/core/templates/core/edit_dashboard.html b/aleksis/core/templates/core/edit_dashboard.html index da50adeea4b2380075113753a9626ef3cbb30fbe..ba4614db61abf50ba8c4bfbabb5383175351c8d8 100644 --- a/aleksis/core/templates/core/edit_dashboard.html +++ b/aleksis/core/templates/core/edit_dashboard.html @@ -19,7 +19,7 @@ {% block content %} <div class="alert primary"> <p> - <i class="material-icons left">info</i> + <i class="material-icons iconify left" data-icon="mdi:information-outline"></i> {% if not default_dashboard %} {% blocktrans %} On this page you can arrange your personal dashboard. You can drag any items from "Available widgets" to "Your diff --git a/aleksis/core/templates/core/group/child_groups.html b/aleksis/core/templates/core/group/child_groups.html index 900df71a59f24817bbec128b5ec15748b5a9d752..a9b93355b8d775b32d3c20123980828fdcae0fd7 100644 --- a/aleksis/core/templates/core/group/child_groups.html +++ b/aleksis/core/templates/core/group/child_groups.html @@ -14,7 +14,7 @@ {% if not page %} <div class="alert info"> <p> - <i class="material-icons left">info</i> + <i class="material-icons left iconify" data-icon="mdi:information-outline"></i> {% blocktrans %} You can use this to assign child groups to groups. Please use the filters below to select groups you want to change and click "Next". @@ -27,11 +27,11 @@ {% form form=filter.form %}{% endform %} <button type="submit" class="btn green waves-effect waves-light"> - <i class="material-icons left">refresh</i> + <i class="material-icons left iconify" data-icon="mdi:refresh"></i> {% trans "Update selection" %} </button> <a href="{% url "groups_child_groups" %}" class="btn red waves-effect waves-light"> - <i class="material-icons left">clear</i> + <i class="material-icons left iconify" data-icon="mdi:close"></i> {% trans "Clear all filters" %} </a> </form> @@ -50,14 +50,14 @@ {% csrf_token %} <button class="btn btn-primary waves-effect waves-light" type="submit" name="page" value="1"> {% trans "Start assigning child groups for this groups" %} - <i class="material-icons right">arrow_forward</i> + <i class="material-icons left iconify" data-icon="mdi:arrow-right"></i> </button> </form> </p> {% else %} <div class="alert warning"> <p> - <i class="material-icons left">warning</i> + <i class="material-icons left iconify" data-icon="mdi:pencil-outline"></i> {% blocktrans %} Please select some groups in order to go on with assigning. {% endblocktrans %} diff --git a/aleksis/core/templates/core/group/full.html b/aleksis/core/templates/core/group/full.html index 65d94ad13a7e563302e9ae283fe4df24c6135353..3c6e5488d6174e30847eabcfda2e97b244112938 100644 --- a/aleksis/core/templates/core/group/full.html +++ b/aleksis/core/templates/core/group/full.html @@ -20,21 +20,21 @@ <p> {% if can_change_group %} <a href="{% url 'edit_group_by_id' group.id %}" class="btn waves-effect waves-light"> - <i class="material-icons left">edit</i> + <i class="material-icons iconify left" data-icon="mdi:pencil-outline"></i> {% trans "Edit" %} </a> {% endif %} {% if can_delete_group %} <a href="{% url 'delete_group_by_id' group.id %}" class="btn waves-effect waves-light red"> - <i class="material-icons left">delete</i> + <i class="material-icons iconify left" data-icon="mdi:delete-outline"></i> {% trans "Delete" %} </a> {% endif %} {% if can_change_group_preferences %} <a href="{% url "preferences_group" group.id %}" class="btn waves-effect waves-light"> - <i class="material-icons left">settings</i> + <i class="material-icons iconify left" data-icon="mdi:cog-outline"></i> {% trans "Change preferences" %} </a> {% endif %} @@ -44,7 +44,7 @@ <table> <tr> <th> - <i class="material-icons center" title="{% trans "Group type" %}">category</i> + <i class="material-icons iconify center" data-icon="mdi:shape-outline" title="{% trans "Group type" %}"></i> </th> <td> {{ group.group_type }} @@ -52,7 +52,7 @@ </tr> <tr> <th> - <i class="material-icons center" title="{% trans "Parent groups" %}">vertical_align_top</i> + <i class="material-icons iconify center" data-icon="mdi:format-vertical-align-top" title="{% trans "Parent groups" %}"></i> </th> <td> {{ group.parent_groups.all|join:", " }} diff --git a/aleksis/core/templates/core/group/list.html b/aleksis/core/templates/core/group/list.html index 9fe2c925f79f423cba0e8d195fb0299cca1c906b..38391cad82a3ff007b02bdca0f6cdda06d53ca2c 100644 --- a/aleksis/core/templates/core/group/list.html +++ b/aleksis/core/templates/core/group/list.html @@ -10,7 +10,7 @@ {% block content %} <a class="btn green waves-effect waves-light" href="{% url 'create_group' %}"> - <i class="material-icons left">add</i> + <i class="material-icons iconify left" data-icon="mdi:add"></i> {% trans "Create group" %} </a> @@ -20,7 +20,7 @@ {% trans "Search" as caption %} {% include "core/partials/save_button.html" with caption=caption icon="search" %} <button type="reset" class="btn red waves-effect waves-light"> - <i class="material-icons left">clear</i> + <i class="material-icons iconify left" data-icon="mdi:close"></i> {% trans "Clear" %} </button> </form> diff --git a/aleksis/core/templates/core/group_type/list.html b/aleksis/core/templates/core/group_type/list.html index 6344416b1a8292fd5400e57d63c056e1b2839ef8..e862cb0191533178546b7b481b0db3ce26fa70a0 100644 --- a/aleksis/core/templates/core/group_type/list.html +++ b/aleksis/core/templates/core/group_type/list.html @@ -10,7 +10,7 @@ {% block content %} <a class="btn green waves-effect waves-light" href="{% url 'create_group_type' %}"> - <i class="material-icons left">add</i> + <i class="material-icons iconify left" data-icon="mdi:add"></i> {% trans "Create group type" %} </a> diff --git a/aleksis/core/templates/core/ical/ical_create.html b/aleksis/core/templates/core/ical/ical_create.html new file mode 100644 index 0000000000000000000000000000000000000000..64ff80083ebab3e61cd108d46ee1bff158cdd236 --- /dev/null +++ b/aleksis/core/templates/core/ical/ical_create.html @@ -0,0 +1,20 @@ +{% extends 'core/base.html' %} +{% load i18n material_form %} + +{% block page_title %}{% blocktrans %}Create iCal URL{% endblocktrans %}{% endblock page_title %} +{% block browser_title %}{% blocktrans %}Create iCal URL{% endblocktrans %}{% endblock browser_title %} + +{% block content %} + <form method="post"> + {% csrf_token %} + + {% form form=form %}{% endform %} + + {% include "core/partials/save_button.html" %} + <a href="{% url "ical_feed_list" %}" class="btn red"> + <i class="material-icons iconify left" data-icon="mdi:close"></i> + {% blocktrans %}Cancel{% endblocktrans %} + </a> + </form> + +{% endblock content %} diff --git a/aleksis/core/templates/core/ical/ical_edit.html b/aleksis/core/templates/core/ical/ical_edit.html new file mode 100644 index 0000000000000000000000000000000000000000..cd46c475531bc1154f5f36c16ae1476b79e73137 --- /dev/null +++ b/aleksis/core/templates/core/ical/ical_edit.html @@ -0,0 +1,20 @@ +{% extends 'core/base.html' %} +{% load i18n material_form %} + +{% block page_title %}{% blocktrans %}Edit iCal URL {{ object }}{% endblocktrans %}{% endblock page_title %} +{% block browser_title %}{% blocktrans %}Edit iCal URL {{ object }}{% endblocktrans %}{% endblock browser_title %} + +{% block content %} + <form method="post"> + {% csrf_token %} + + {% form form=form %}{% endform %} + + {% include "core/partials/save_button.html" %} + <a href="{% url "ical_feed_list" %}" class="btn red"> + <i class="material-icons iconify left" data-icon="mdi:close"></i> + {% blocktrans %}Cancel{% endblocktrans %} + </a> + </form> + +{% endblock content %} diff --git a/aleksis/core/templates/core/ical/ical_list.html b/aleksis/core/templates/core/ical/ical_list.html new file mode 100644 index 0000000000000000000000000000000000000000..2388feb2daa9c4b31abb80bc830055e2d2d3efc6 --- /dev/null +++ b/aleksis/core/templates/core/ical/ical_list.html @@ -0,0 +1,38 @@ +{% extends 'core/base.html' %} +{% load i18n msg_box static html_helpers %} + +{% block page_title %}{% trans "ICal Feeds" %}{% endblock page_title %} +{% block browser_title %}{% trans "ICal Feeds" %}{% endblock browser_title %} + +{% block content %} + {% trans "These are URLs for different Calendar Feeds in the iCal (.ics) format. You can create as many as you want and import them in your calendar software." as msg %} + {% msg_box msg=msg status="info" %} + <a href="{% url "ical_feed_create" %}" class="btn green"> + <i class="material-icons iconify left" data-icon="mdi:add"></i> + {% trans "Create iCal URL" %} + </a> + <h2>{% trans "Your iCal URLs" %}</h2> + <div class="collection"> + {% for object in object_list %} + <div class="collection-item"> + <span class="title btn-small-line-height"> + {{ object }} + <a href="{% url "ical_feed_delete" object.pk %}" + class="secondary-content btn-flat btn-small red-text btn-smaller-padding waves-effect waves-red"> + <i class="material-icons iconify" data-icon="mdi:delete-outline"></i> + </a> + <a href="{% url "ical_feed_edit" object.pk %}" + class="secondary-content btn-flat btn-small primary-color-text btn-smaller-padding waves-effect waves-primary"> + <i class="material-icons iconify" data-icon="mdi:pencil-outline"></i> + </a> + {% generate_random_id "ical-copy-" as id %} + {% include "core/partials/copy_button.html" with classes="secondary-content btn-flat btn-small secondary-color-text btn-smaller-padding" target=id %} + </span> + <p class="ical-description">{{ object.ical_feed_object.title }} – {{ object.ical_feed_object.description }}</p> + <input type="url" readonly value="https://{{ request.site }}{{ object.get_absolute_url }}" + id="{{ id }}"> + </div> + {% endfor %} + </div> + <script src="{% static "js/copy_button.js" %}" type="text/javascript"></script> +{% endblock content %} diff --git a/aleksis/core/templates/core/index.html b/aleksis/core/templates/core/index.html index 7c9c018ca8102172dbd6e46c41048bcbcff4d46f..766c88278ca688381356c35e79b3424b7fb5ce75 100644 --- a/aleksis/core/templates/core/index.html +++ b/aleksis/core/templates/core/index.html @@ -13,7 +13,7 @@ {% if can_edit_dashboard and show_edit_dashboard_button %} <div class="row no-margin"> <a class="btn-flat waves-effect waves-light right" href="{% url "edit_dashboard" %}"> - <i class="material-icons left">edit</i> + <i class="material-icons left iconify" data-icon="mdi:pencil-outline"></i> {% trans "Edit dashboard" %} </a> </div> @@ -21,11 +21,11 @@ {% for notification in unread_notifications %} <figure class="alert primary scale-transition"> - <i class="material-icons left">info</i> + <i class="material-icons left iconify" data-icon="mdi:information-outline"></i> <div class="right"> <a class="btn-flat waves-effect" href="{% url "notification_mark_read" notification.id %}"> - <i class="material-icons center">close</i> + <i class="material-icons center iconify" data-icon="mdi:close"></i> </a> </div> @@ -65,7 +65,7 @@ <span class="badge new primary-color">{{ activity.app }}</span> <span class="title">{{ activity.title }}</span> <p> - <i class="material-icons left">access_time</i> {{ activity.created }} + <i class="material-icons left iconify" data-icon="mdi:clock-outline"></i> {{ activity.created }} </p> <p> {{ activity.description }} @@ -88,7 +88,7 @@ <span class="badge new primary-color">{{ notification.sender }}</span> <span class="title">{{ notification.title }}</span> <p> - <i class="material-icons left">access_time</i> {{ notification.created }} + <i class="material-icons left iconify" data-icon="mdi:clock-outline"></i> {{ notification.created }} </p> <p> {{ notification.description }} diff --git a/aleksis/core/templates/core/notifications.html b/aleksis/core/templates/core/notifications.html index 499bbcc4c866142ce9062efd75fab039dbd303f6..60640670e6ca02ae788c4c37ff5f65d7c9969e2d 100644 --- a/aleksis/core/templates/core/notifications.html +++ b/aleksis/core/templates/core/notifications.html @@ -13,7 +13,7 @@ <span class="badge new primary-color">{{ notification.sender }}</span> <span class="title">{{ notification.title }}</span> <p> - <i class="material-icons left">access_time</i> {{ notification.created }} + <i class="material-icons iconify left" data-icon="mdi:clock-outline"></i> {{ notification.created }} </p> <p> {{ notification.description|linebreaks }} diff --git a/aleksis/core/templates/core/pages/delete.html b/aleksis/core/templates/core/pages/delete.html index db64ee8fc3b977ed9cb74333e1a25834ce3e58b7..9cbe50ca73913a6cd06ac1eca32b39f88941ee78 100644 --- a/aleksis/core/templates/core/pages/delete.html +++ b/aleksis/core/templates/core/pages/delete.html @@ -18,7 +18,7 @@ <form method="post" action=""> {% csrf_token %} <button type="submit" class="btn red waves-effect waves-light"> - <i class="material-icons left">delete</i> + <i class="material-icons iconify left" data-icon="mdi:delete-outline"></i> {% trans "Delete" %} </button> </form> diff --git a/aleksis/core/templates/core/pages/progress.html b/aleksis/core/templates/core/pages/progress.html index fca1ddfc2ebe5980ee132de77bdf1baafce24ae0..dc12869c8130a26bf2d5d96f1d30e8a83444bd61 100644 --- a/aleksis/core/templates/core/pages/progress.html +++ b/aleksis/core/templates/core/pages/progress.html @@ -23,32 +23,32 @@ <noscript> <div class="alert warning"> <p> - <i class="material-icons left">warning</i> + <i class="material-icons iconify left" data-icon="mdi:alert-outline"></i> {% blocktrans %} Without activated JavaScript the progress status can't be updated. {% endblocktrans %} </p> </div> </noscript> - + <div id="messages"></div> <div id="result-box" style="display: none;"> <div class="alert" id="result-alert"> <div> - <i class="material-icons left" id="result-icon">check_circle</i> + <i class="material-icons iconify left" id="result-icon" data-icon="mdi:check-circle-outline"></i> <p id="result-text"></p> </div> </div> {% url "index" as index_url %} <a class="btn waves-effect waves-light" href="{{ back_url|default:index_url }}"> - <i class="material-icons left">arrow_back</i> + <i class="material-icons iconify left" data-icon="mdi:arrow-left"></i> {% trans "Go back" %} </a> {% if additional_button %} <a class="btn waves-effect waves-light" href="{{ additional_button.href }}" id="result-button" style="display: none;"> - <i class="material-icons left">{{ additional_button.icon|default:"" }}</i> + <i class="material-icons iconify left" data-icon="{{ additional_button.icon|default:"" }}"></i> {{ additional_button.caption }} </a> {% endif %} diff --git a/aleksis/core/templates/core/pages/system_status.html b/aleksis/core/templates/core/pages/system_status.html index 89c6ed65e3982a0318838a66ef7f6716935d0af3..4eee117807c2b2a45a1271e1f4aa9673189d105d 100644 --- a/aleksis/core/templates/core/pages/system_status.html +++ b/aleksis/core/templates/core/pages/system_status.html @@ -15,8 +15,9 @@ <div class="row"> {% if maintenance_mode %} <a class="btn-flat btn-flat-medium right waves-effect waves-red no-padding" - href="{% url 'maintenance_mode_off' %}"><i - class="material-icons small red-text center">power_settings_new</i></a> + href="{% url 'maintenance_mode_off' %}"> + <i class="material-icons iconify small red-text center" data-icon="mdi:power"></i> + </a> <div> <p class="flow-text">{% blocktrans %}Maintenance mode enabled{% endblocktrans %}</p> <p class="grey-text"> @@ -28,8 +29,9 @@ <span class="badge badge-danger mdi mdi-power"><a href="{% url 'maintenance_mode_off' %}"></a></span> {% else %} <a class="btn-flat btn-flat-medium right waves-effect waves-green no-padding" - href="{% url 'maintenance_mode_on' %}"><i - class="material-icons small green-text center">power_settings_new</i></a> + href="{% url 'maintenance_mode_on' %}"> + <i class="material-icons iconify small green-text center" data-icon="mdi:power"></i> + </a> <div> <p class="flow-text">{% blocktrans %}Maintenance mode disabled{% endblocktrans %}</p> <p class="grey-text">{% blocktrans %}Everyone can access the site.{% endblocktrans %}</p> @@ -40,7 +42,7 @@ {# Debug mode #} <div class="row"> {% if DEBUG %} - <i class="material-icons small red-text right">power_settings_new</i> + <i class="material-icons iconify small red-text right" data-icon="mdi:power"></i> <div> <p class="flow-text">{% blocktrans %}Debug mode enabled{% endblocktrans %}</p> <p class="grey-text"> @@ -49,7 +51,7 @@ {% endblocktrans %}</p> </div> {% else %} - <i class="material-icons small green-text right">power_settings_new</i> + <i class="material-icons iconify small green-text right" data-icon="mdi:power"></i> <div> <p class="flow-text">{% blocktrans %}Debug mode disabled{% endblocktrans %}</p> <p class="grey-text"> @@ -82,11 +84,13 @@ <tr> <td> <a class="tooltipped" data-position="top" data-tooltip="{{ plugin.pretty_status }}"> - {% if plugin.status %} - <i class="material-icons green-text" aria-hidden="true" title="{{ plugin.pretty_status }}">check</i> - {% else %} - <i class="material-icons red-text" aria-hidden="true" title="{{ plugin.pretty_status }}">warning</i> - {% endif %} + {% if plugin.status %} + <i class="material-icons iconify green-text" aria-hidden="true" title="{{ plugin.pretty_status }}" + data-icon="mdi:check"></i> + {% else %} + <i class="material-icons iconify red-text" aria-hidden="true" title="{{ plugin.pretty_status }}" + data-icon="mdi:alert-outline"></i> + {% endif %} </a> </td> <td>{{ plugin.identifier }}</td> @@ -126,32 +130,32 @@ {% if task.status == "PENDING" %} <a class="tooltipped" data-position="top" data-tooltip="{{ task.status }}"> - <i class="material-icons orange-text">hourglass_empty</i> + <i class="material-icons iconify orange-text" data-icon="mdi:timer-sand-empty"></i> </a> {% elif task.status == "STARTED" %} <a class="tooltipped" data-position="top" data-tooltip="{{ task.status }}"> - <i class="material-icons orange-text">directions_run</i> + <i class="material-icons iconify orange-text" data-icon="mdi:timer-sand"></i> </a> {% elif task.status == "SUCCESS" %} <a class="tooltipped" data-position="top" data-tooltip="{{ task.status }}"> - <i class="material-icons green-text">done</i> + <i class="material-icons iconify green-text" data-icon="mdi:check"></i> </a> {% elif task.status == "FAILURE" %} <a class="tooltipped" data-position="top" data-tooltip="{{ task.status }}"> - <i class="material-icons red-text">error</i> + <i class="material-icons iconify red-text" data-icon="mdi:alert-octagon-outline"></i> </a> {% elif task.status == "RETRY" %} <a class="tooltipped" data-position="top" data-tooltip="{{ task.status }}"> - <i class="material-icons orange-text">hourglass_full</i> + <i class="material-icons iconify orange-text" data-icon="mdi:timer-sand-full"></i> </a> {% elif task.status == "REVOKED" %} <a class="tooltipped" data-position="top" data-tooltip="{{ task.status }}"> - <i class="material-icons red-text">clear</i> + <i class="material-icons iconify red-text" data-icon="mdi:close"></i> </a> {% endif %} </td> diff --git a/aleksis/core/templates/core/pages/test_pdf.html b/aleksis/core/templates/core/pages/test_pdf.html index f0c0a6169c85a6f37252136b3777dc0967350e43..1730d10e655759ad193cd7282654374795951721 100644 --- a/aleksis/core/templates/core/pages/test_pdf.html +++ b/aleksis/core/templates/core/pages/test_pdf.html @@ -10,7 +10,7 @@ {% block content %} <div class="alert primary"> <p> - <i class="material-icons left">info</i> + <i class="material-icons iconify left" data-icon="mdi:information-outline"></i> {% blocktrans %} This simple view can be used to ensure the correct function of the built-in PDF generation system. {% endblocktrans %} diff --git a/aleksis/core/templates/core/partials/announcements.html b/aleksis/core/templates/core/partials/announcements.html index e3dcd5165f4149e3d5fa2016487ef771ad84f12d..4a286a5d79224023995f48dc38a43fb27f2988d7 100644 --- a/aleksis/core/templates/core/partials/announcements.html +++ b/aleksis/core/templates/core/partials/announcements.html @@ -16,7 +16,7 @@ </em> {% endif %} - <i class="material-icons left">announcement</i> + <i class="material-icons iconify left" data-icon="mdi:message-alert-outline"></i> {% if show_recipients and announcement.recipients %} <p> diff --git a/aleksis/core/templates/core/partials/avatar_content.html b/aleksis/core/templates/core/partials/avatar_content.html new file mode 100644 index 0000000000000000000000000000000000000000..deef48489f4ed118a4420f05ea226f87d7c0b895 --- /dev/null +++ b/aleksis/core/templates/core/partials/avatar_content.html @@ -0,0 +1,29 @@ +{% load rules i18n %} +{% has_perm 'core.view_avatar_rule' request.user person_or_user as can_view_avatar %} +{% has_perm 'core.view_photo_rule' request.user person_or_user as can_view_photo %} +{% if SITE_PREFERENCES.account__person_prefer_photo and person_or_user.photo and can_view_photo %} + <div class="{% firstof class "clip-circle" %}"> + <img class="{% firstof img_class "hundred-percent" %}" src="{{ person_or_user.photo.url }}" + alt="{{ person_or_user.full_name }}" {% if title %} title="{{ person_or_user.full_name }}"{% endif %}/> + </div> +{% elif person_or_user.identicon_url %} + {# If this is a person #} + <div class="{% firstof class "clip-circle" %}"> + {% if can_view_avatar %} + <img class="{% firstof img_class "hundred-percent" %}" src="{{ person_or_user.avatar_url }}" + alt="{{ person_or_user.full_name }} ({% trans "Avatar" %})" {% if title %} + title="{{ person_or_user.full_name }} ({% trans "Avatar" %})"{% endif %}/> + {% else %} + + <img class="{% firstof img_class "hundred-percent" %}" src="{{ person_or_user.identicon_url }}" + alt="{{ person_or_user.full_name }} ({% trans "Identicon" %})" {% if title %} + title="{{ person_or_user.full_name }} ({% trans "Identicon" %})"{% endif %} /> + {% endif %} + </div> + +{% else %} + {# There is a user without a person #} + <div class="{% firstof class "clip-circle" %} no-image"> + <i class="material-icons">person</i> + </div> +{% endif %} diff --git a/aleksis/core/templates/core/partials/copy_button.html b/aleksis/core/templates/core/partials/copy_button.html new file mode 100644 index 0000000000000000000000000000000000000000..2ca0168333bc7215a580b05316c4556db436bb12 --- /dev/null +++ b/aleksis/core/templates/core/partials/copy_button.html @@ -0,0 +1,5 @@ +<button type="button" data-target="{{ target }}" + class="{{ classes }} copy-button waves-effect waves-secondary"> + <i class="material-icons iconify copy-icon-copy" data-icon="mdi:content-copy"></i> + <i class="material-icons iconify copy-icon-success" style="display: none" data-icon="mdi:check"></i> +</button> diff --git a/aleksis/core/templates/core/partials/crud_events.html b/aleksis/core/templates/core/partials/crud_events.html index b0edf14d154690e33a2fac523f5fa38429fcdb5e..d0eba480a1cceec09117f96d7e18c4141729be45 100644 --- a/aleksis/core/templates/core/partials/crud_events.html +++ b/aleksis/core/templates/core/partials/crud_events.html @@ -5,9 +5,9 @@ <div class="collection-item"> <div class="left" style="margin-right: 10px;"> {% if forloop.first %} - <i class="material-icons">add_circle</i> + <i class="material-icons iconify" data-icon="mdi:plus-circle-outline"></i> {% else %} - <i class="material-icons">edit</i> + <i class="material-icons iconify" data-icon="mdi:pencil-circle-outline"></i> {% endif %} </div> <strong> diff --git a/aleksis/core/templates/core/partials/edit_dashboard_widget.html b/aleksis/core/templates/core/partials/edit_dashboard_widget.html index b842c0937f05c4e90a4d7337871460130fa43012..1a469c9cee2a129334bc93779521084c6297074c 100644 --- a/aleksis/core/templates/core/partials/edit_dashboard_widget.html +++ b/aleksis/core/templates/core/partials/edit_dashboard_widget.html @@ -2,7 +2,7 @@ data-pk="{{ widget.pk }}"> <div class="card placeholder"> <div class="card-content"> - <i class="material-icons left small">drag_handle</i> + <i class="material-icons iconify left small" data-icon="mdi:drag-horizontal-variant"></i> <span class="card-title">{{ widget.title }}</span> </div> </div> diff --git a/aleksis/core/templates/core/partials/footer-menu.html b/aleksis/core/templates/core/partials/footer-menu.html index 5a1d268ea2916899bb3d5bddd47e26d4962734ba..2db2689efed0b3488dc7ba4362d2ff6747863f0e 100644 --- a/aleksis/core/templates/core/partials/footer-menu.html +++ b/aleksis/core/templates/core/partials/footer-menu.html @@ -3,7 +3,7 @@ {% for item in FOOTER_MENU.items.all %} <a class="blue-text text-lighten-4 btn-flat" href="{{ item.url }}"> {% if item.icon %} - <i class="material-icons footer-icon left">{{ item.icon }}</i> + <i class="material-icons iconify footer-icon left" data-icon="{{ item.icon }}">{{ item.icon }}</i> {% endif %} {{ item.name }} </a> diff --git a/aleksis/core/templates/core/partials/no_person.html b/aleksis/core/templates/core/partials/no_person.html index 62b398a1af779b0fc17eef8aa2c0e845760a4e5d..d99a1e0cbcbd0d6a39ea8565bbcadcb39d7482ce 100644 --- a/aleksis/core/templates/core/partials/no_person.html +++ b/aleksis/core/templates/core/partials/no_person.html @@ -5,7 +5,7 @@ {% if user.person.is_dummy or not user.person and not user.is_anonymous %} <div class="alert error"> <div> - <i class="material-icons left">error</i> + <i class="material-icons iconify left" data-icon="mdi:alert-octagon-outline"></i> {% if user.person.is_dummy %} <p> diff --git a/aleksis/core/templates/core/partials/save_button.html b/aleksis/core/templates/core/partials/save_button.html index ebc48f2db3d4529f292e3352dbf0cd45ccec2868..3a43323677c44ab6e393c818b451c2b8b846610c 100644 --- a/aleksis/core/templates/core/partials/save_button.html +++ b/aleksis/core/templates/core/partials/save_button.html @@ -1,5 +1,6 @@ {% load i18n %} <button type="submit" class="btn waves-effect waves-light green"> {% trans "Save" as default %} - <i class="material-icons left">{{ icon|default:"save" }}</i> {{ caption|default:default }} + <i class="material-icons left iconify" data-icon="{{ icon|default:"mdi:content-save-outline" }}"></i> + {{ caption|default:default }} </button> diff --git a/aleksis/core/templates/core/partials/sidenav.html b/aleksis/core/templates/core/partials/sidenav.html index 9b3be97059ca834238d39a4dd6f6bfe35205a9d2..0120f6b71b0f505e6376e4b3a36894d71b38b914 100644 --- a/aleksis/core/templates/core/partials/sidenav.html +++ b/aleksis/core/templates/core/partials/sidenav.html @@ -14,6 +14,8 @@ <i class="{{ item.icon_class }}"></i> {% elif item.icon %} <i class="material-icons">{{ item.icon }}</i> + {% elif item.svg_icon %} + <i class="material-icons iconify" data-icon="{{item.svg_icon}}"></i> {% endif %} {{ item.name }} {% build_badge item as badge %} @@ -30,6 +32,8 @@ <i class="{{ item.icon_class }}"></i> {% elif item.icon %} <i class="material-icons">{{ item.icon }}</i> + {% elif item.svg_icon %} + <i class="material-icons iconify" data-icon="{{item.svg_icon}}"></i> {% endif %} {{ item.name }} {% build_badge item as badge %} @@ -46,6 +50,8 @@ <i class="{{ menu.icon_class }}"></i> {% elif menu.icon %} <i class="material-icons">{{ menu.icon }}</i> + {% elif menu.svg_icon %} + <i class="material-icons iconify" data-icon="{{menu.svg_icon}}"></i> {% endif %} {{ menu.name }} {% build_badge item as badge %} diff --git a/aleksis/core/templates/core/partials/turnable.html b/aleksis/core/templates/core/partials/turnable.html index e122b2fa4396282fe0941376161fe3086cda4deb..dabfcbb93ddce6d9323a84757c3753e713c8efea 100644 --- a/aleksis/core/templates/core/partials/turnable.html +++ b/aleksis/core/templates/core/partials/turnable.html @@ -2,9 +2,9 @@ <div class="row"> <a href="{{ url_prev }}" class="btn-flat left"> - <i class="material-icons small">chevron_left</i> + <i class="material-icons iconify small"data-icon="mdi:chevron-left"></i> </a> <a href="{{ url_next }}" class="btn-flat right"> - <i class="material-icons small">chevron_right</i> + <i class="material-icons iconify small" data-icon="mdi:chevron-right"></i> </a> </div> diff --git a/aleksis/core/templates/core/perms/assign.html b/aleksis/core/templates/core/perms/assign.html index 1833ece952d04f01f2f38440cc0fe8fc1d509bf7..75ca29dbad18c1b84e79638cf1c192a7b6b9707d 100644 --- a/aleksis/core/templates/core/perms/assign.html +++ b/aleksis/core/templates/core/perms/assign.html @@ -22,7 +22,7 @@ <input type="hidden" name="step" value="{{ step }}"> {% form form=form %}{% endform %} <button type="submit" class="btn green waves-effect waves-light"> - <i class="material-icons left">save</i> + <i class="material-icons left iconify" data-icon="mdi:content-save-outline"></i> {% trans "Assign" %} </button> </form> diff --git a/aleksis/core/templates/core/perms/list.html b/aleksis/core/templates/core/perms/list.html index 73dcfb8730d5e2235b3b398a4ef0f0fd70c8c31b..319b00285f10753a966047df23669ac40d5b4c95 100644 --- a/aleksis/core/templates/core/perms/list.html +++ b/aleksis/core/templates/core/perms/list.html @@ -54,7 +54,7 @@ {% csrf_token %} {% form form=filter.form %}{% endform %} <button type="submit" class="btn waves-effect waves-light"> - <i class="material-icons left">refresh</i> + <i class="material-icons left iconify" data-icon="mdi:refresh"></i> {% trans "Update" %} </button> </form> diff --git a/aleksis/core/templates/core/person/collection.html b/aleksis/core/templates/core/person/collection.html index fb8518e97e3e8d770260c8e6b004df420d8efa15..c86da61e43ae19ceaa0f601c2f3ec012357bc04d 100644 --- a/aleksis/core/templates/core/person/collection.html +++ b/aleksis/core/templates/core/person/collection.html @@ -3,13 +3,7 @@ <div class="collection person-collection"> {% for person in persons %} <a class="collection-item avatar waves-effect" href="{% url "person_by_id" person.pk %}"> - {% has_perm 'core.view_photo_rule' user person as can_view_photo %} - {% if person.photo and can_view_photo %} - <img class="circle" src="{{ person.photo.url }}" - alt="{{ person.first_name }} {{ person.last_name }}"/> - {% else %} - <i class="material-icons materialize-circle">person</i> - {% endif %} + {% include "core/partials/avatar_content.html" with person_or_user=person class="materialize-circle" img_class="materialize-circle" %} {{ person }} </a> {% endfor %} diff --git a/aleksis/core/templates/core/person/full.html b/aleksis/core/templates/core/person/full.html index 23f8ba29b30188dd4cdf5b76af23991a0f618119..9a58951118e4bdafe3278cb7e4280e455fa99943 100644 --- a/aleksis/core/templates/core/person/full.html +++ b/aleksis/core/templates/core/person/full.html @@ -22,35 +22,35 @@ <p class="person-buttons hide-on-med-and-down"> {% if can_change_person %} <a href="{% url 'edit_person_by_id' person.id %}" class="btn waves-effect waves-light"> - <i class="material-icons left">edit</i> + <i class="material-icons left iconify" data-icon="mdi:pencil-outline"></i> {% trans "Edit" %} </a> {% endif %} {% if can_delete_person %} <a href="{% url 'delete_person_by_id' person.id %}" class="btn waves-effect waves-light red"> - <i class="material-icons left">delete</i> + <i class="material-icons left iconify" data-icon="mdi:delete-outline"></i> {% trans "Delete" %} </a> {% endif %} {% if can_change_person_preferences %} <a href="{% url 'preferences_person' person.id %}" class="btn waves-effect waves-light"> - <i class="material-icons left">settings</i> + <i class="material-icons left iconify" data-icon="mdi:cog-outline"></i> {% trans "Change preferences" %} </a> {% endif %} {% if can_impersonate and person.user %} <a href="{% url 'impersonate-start' person.user.id %}" class="btn waves-effect waves-light"> - <i class="material-icons left">portrait</i> + <i class="material-icons left iconify" data-icon="mdi:account-box-outline"></i> {% trans "Impersonate" %} </a> {% endif %} {% if invite_enabled and can_invite and not person.user %} <a href="{% url "invite_person_by_id" person.id %}" class="btn waves-effect waves-light"> - <i class="material-icons left">card_giftcard</i> + <i class="material-icons iconify left" data-icon="mdi:account-plus-outline"></i> {% trans "Invite user" %} </a> {% endif %} @@ -59,19 +59,7 @@ <header class="person-container"> <div class="image-wrapper"> - {% has_perm 'core.view_avatar_rule' user person as can_view_avatar %} - {% if person.avatar and can_view_avatar %} - <div class="clip-circle materialboxed z-depth-2"> - <img class="hundred-percent" src="{{ person.avatar.url }}" - alt="{{ person.first_name }} {{ person.last_name }}"/> - </div> - - {% else %} - - <div class="clip-circle no-image z-depth-2"> - {{ person.initials }} - </div> - {% endif %} + {% include "core/partials/avatar_content.html" with class="clip-circle materialboxed z-depth-2" person_or_user=person title=True %} </div> <h1> {{ person.first_name }} {{ person.last_name }} @@ -94,35 +82,35 @@ <div class="collection"> {% if can_change_person %} <a href="{% url 'edit_person_by_id' person.id %}" class="collection-item waves-effect waves-dark"> - <i class="material-icons left">edit</i> + <i class="material-icons iconify left" data-icon="mdi:pencil-outline"></i> {% trans "Edit" %} </a> {% endif %} {% if can_delete_person %} <a href="{% url 'delete_person_by_id' person.id %}" class="collection-item waves-effect waves-red red-text"> - <i class="material-icons left">delete</i> + <i class="material-icons iconify left" data-icon="mdi:delete-outline"></i> {% trans "Delete" %} </a> {% endif %} {% if can_change_person_preferences %} <a href="{% url 'preferences_person' person.id %}" class="collection-item waves-effect waves-dark"> - <i class="material-icons left">settings</i> + <i class="material-icons iconify left" data-icon="mdi:cog-outline"></i> {% trans "Change preferences" %} </a> {% endif %} {% if can_impersonate and person.user %} <a href="{% url 'impersonate-start' person.user.id %}" class="collection-item waves-effect waves-dark"> - <i class="material-icons left">portrait</i> + <i class="material-icons iconify left" data-icon="mdi:account-box-outline"></i> {% trans "Impersonate" %} </a> {% endif %} {% if can_invite and not person.user %} <a href="{% url "invite_person_by_id" person.id %}" class="collection-item waves-effect waves-light"> - <i class="material-icons left">card_giftcard</i> + <i class="material-icons iconify left" data-icon="mdi:account-plus-outline"></i> {% trans "Invite user" %} </a> {% endif %} @@ -135,13 +123,13 @@ <table class="highlight"> <tr> <td> - <i class="material-icons small">person</i> + <i class="material-icons small iconify" data-icon="mdi:account-outline"></i> </td> <td>{{ person.first_name }} {{ person.additional_name }} {{ person.last_name }}</td> </tr> <tr> <td> - <i class="material-icons small">face</i> + <i class="material-icons small iconify" data-icon="mdi:human-non-binary"></i> </td> <td>{% firstof person.get_sex_display "–" %}</td> </tr> @@ -149,7 +137,7 @@ {% if can_view_address %} <tr> <td rowspan="2"> - <i class="material-icons small">home</i> + <i class="material-icons small iconify" data-icon="mdi:map-marker-outline"></i> </td> <td>{% firstof person.street "–" %} {{ person.housenumber }}</td> </tr> @@ -161,7 +149,7 @@ {% if can_view_contact_details %} <tr> <td rowspan="2"> - <i class="material-icons small">phone</i> + <i class="material-icons small iconify" data-icon="mdi:phone-outline"></i> </td> <td> {% if person.phone_number %} @@ -184,7 +172,7 @@ </tr> <tr> <td> - <i class="material-icons small">email</i> + <i class="material-icons small iconify" data-icon="mdi:email-outline"></i> </td> <td> {% if person.email %} @@ -199,7 +187,7 @@ {% if can_view_personal_details %} <tr> <td> - <i class="material-icons small">cake</i> + <i class="material-icons small iconify" data-icon="mdi:cake"></i> </td> <td> <time datetime="{{ person.date_of_birth|date:'c' }}">{{ person.date_of_birth|date }}</time> @@ -209,18 +197,26 @@ {% endif %} </table> </div> + {% has_perm 'core.view_avatar_rule' user person as can_view_avatar %} {% has_perm 'core.view_photo_rule' user person as can_view_photo %} - {% if person.photo and can_view_photo %} + {% if person.photo and can_view_photo and not SITE_PREFERENCES.account__person_prefer_photo %} <div class="card"> <div class="card-image"> <img src="{{ person.photo.url }}" alt="{{ person.first_name }} {{ person.last_name }}" class="materialboxed"> <span class="card-title">{{ person.first_name }} {{ person.last_name }}</span> </div> </div> - + {% elif person.avatar and can_view_avatar %} + <div class="card"> + <div class="card-image"> + <img src="{{ person.avatar.url }}" + alt="{{ person.first_name }} {{ person.last_name }} ({% trans "Avatar" %})" class="materialboxed"> + <span class="card-title">{{ person.first_name }} {{ person.last_name }} ({% trans "Avatar" %})</span> + </div> + </div> {% else %} <div class="card-panel"> - <i class="material-icons left">image_not_supported</i> + <i class="material-icons iconify left" data-icon="mdi:image-off-outline"></i> {% trans "This person didn't upload a personal photo." %} </div> {% endif %} diff --git a/aleksis/core/templates/core/person/list.html b/aleksis/core/templates/core/person/list.html index ca441cac485847cf6a4975071d73787473804694..acafd75bad5762e3367f4f00b50010987c4f3fae 100644 --- a/aleksis/core/templates/core/person/list.html +++ b/aleksis/core/templates/core/person/list.html @@ -13,7 +13,7 @@ {% if can_create_person %} <a class="btn green waves-effect waves-light" href="{% url 'create_person' %}"> - <i class="material-icons left">add</i> + <i class="material-icons iconify left" data-icon="mdi:add"></i> {% trans "Create person" %} </a> {% endif %} @@ -22,9 +22,9 @@ <form method="get"> {% form form=persons_filter.form %}{% endform %} {% trans "Search" as caption %} - {% include "core/partials/save_button.html" with caption=caption icon="search" %} + {% include "core/partials/save_button.html" with caption=caption icon="mdi:search" %} <button type="reset" class="btn red waves-effect waves-light"> - <i class="material-icons left">clear</i> + <i class="material-icons iconify left" data-icon="mdi:close"></i> {% trans "Clear" %} </button> </form> diff --git a/aleksis/core/templates/core/school_term/list.html b/aleksis/core/templates/core/school_term/list.html index 14aa2f0a697a3efd54b27154b431ef3f424923de..9df6af9727b868e13d43a75c42730b375ff6aa47 100644 --- a/aleksis/core/templates/core/school_term/list.html +++ b/aleksis/core/templates/core/school_term/list.html @@ -10,7 +10,7 @@ {% block content %} <a class="btn green waves-effect waves-light" href="{% url 'create_school_term' %}"> - <i class="material-icons left">add</i> + <i class="material-icons left iconify" data-icon="mdi:add"></i> {% trans "Create school term" %} </a> diff --git a/aleksis/core/templates/django_tables2/materialize.html b/aleksis/core/templates/django_tables2/materialize.html index 8901c2d5d9dfddf14934195dee11641bca9bcb8d..b472a5b0c9d5e185482959c7536c5c6dd513f211 100644 --- a/aleksis/core/templates/django_tables2/materialize.html +++ b/aleksis/core/templates/django_tables2/materialize.html @@ -66,7 +66,7 @@ <li class="waves-effect"> <a href="{% querystring table.prefixed_page_field=table.page.previous_page_number %}" class="page-link"> - <i class="material-icons">chevron_left</i> + <i class="material-icons iconify" data-icon="mdi:chevron-left"></i> </a> </li> {% endblock pagination.previous %} @@ -86,7 +86,7 @@ {% block pagination.next %} <li class="waves-effect"> <a href="{% querystring table.prefixed_page_field=table.page.next_page_number %}" class="page-link"> - <i class="material-icons">chevron_right</i> + <i class="material-icons iconify" data-icon="mdi:chevron-right"></i> </a> </li> {% endblock pagination.next %} diff --git a/aleksis/core/templates/material/fields/colorfield_colorwidget.html b/aleksis/core/templates/material/fields/colorfield_colorwidget.html index ab8bc7f955126d365be64085b7be740ef70a398f..5fff8c00ac913134abcb8e869464aeb7fe1e6330 100644 --- a/aleksis/core/templates/material/fields/colorfield_colorwidget.html +++ b/aleksis/core/templates/material/fields/colorfield_colorwidget.html @@ -2,7 +2,7 @@ {% part bound_field.field %} <div class="row"> <div class="input-field col s12{% if widget.attrs.required %} required{% endif %}"> - <i class="material-icons prefix" id="{{ bound_field.html_name }}_preview" style="color: {% firstof bound_field.value field.widget.attrs.default '' %};">color_lens</i> + <i class="material-icons iconify prefix" id="{{ bound_field.html_name }}_preview" style="color: {% firstof bound_field.value field.widget.attrs.default '' %};" data-icon="mdi:palette-outline"></i> {% part field prefix %}{% endpart %}{% part field control %} <input type="text" diff --git a/aleksis/core/templates/material/non_field_errors.html b/aleksis/core/templates/material/non_field_errors.html index c8a92eb7ef813325580738a7819fccf6da2dfa70..b64aa87982a9285f6ee023cff210bbff1ae6b67a 100644 --- a/aleksis/core/templates/material/non_field_errors.html +++ b/aleksis/core/templates/material/non_field_errors.html @@ -1,7 +1,7 @@ {% if form.non_field_errors %} <div class="alert error"> {% for error in form.non_field_errors %} - <div><i class="material-icons left">error</i> {{ error }}</div> + <div><i class="material-icons iconify left" data-icon="mdi:alert-octagon-outline"></i> {{ error }}</div> {% endfor %} </div> {% endif %} diff --git a/aleksis/core/templates/oauth2_provider/application/create.html b/aleksis/core/templates/oauth2_provider/application/create.html index 73b94677206d38fca163858551536d575b2dce3d..683c81fa25966dea43c5737537ff090b4b042f01 100644 --- a/aleksis/core/templates/oauth2_provider/application/create.html +++ b/aleksis/core/templates/oauth2_provider/application/create.html @@ -11,7 +11,7 @@ {% form form=form %}{% endform %} {% include "core/partials/save_button.html" %} <a class="btn waves-effect red waves-light" href="{% url "oauth2_applications" %}"> - <i class="material-icons left">clear</i> {% trans "Cancel" %} + <i class="material-icons iconify left" data-icon="mdi:close"></i> {% trans "Cancel" %} </a> </form> {% endblock %} diff --git a/aleksis/core/templates/oauth2_provider/application/detail.html b/aleksis/core/templates/oauth2_provider/application/detail.html index 28e2af7d70ff4b6dd5d93b46b8ec52d31bc36538..1a7709f14dacdef5ab414d516ec35d72cbc1e5f8 100644 --- a/aleksis/core/templates/oauth2_provider/application/detail.html +++ b/aleksis/core/templates/oauth2_provider/application/detail.html @@ -6,18 +6,18 @@ {% block page_title %} <a href="{% url "oauth2_applications" %}" class="btn-flat primary-color-text waves-light waves-effect"> - <i class="material-icons left">chevron_left</i> {% trans "Back" %} + <i class="material-icons iconify left" data-icon="mdi:chevron-left"></i> {% trans "Back" %} </a> {{ application.name }} {% endblock %} {% block content %} <a class="btn orange waves-effect waves-light btn-margin" href="{% url "edit_oauth2_application" application.id %}"> - <i class="material-icons left">edit</i> + <i class="material-icons iconify left" data-icon="mdi:pencil-outline"></i> {% trans "Edit" %} </a> <a class="btn red waves-effect waves-light btn-margin" href="{% url "delete_oauth2_application" application.id %}"> - <i class="material-icons left">delete</i> + <i class="material-icons iconify left" data-icon="mdi:delete-outline"></i> {% trans "Delete" %} </a> <table class="responsive-table"> @@ -79,7 +79,7 @@ {% trans "Skip Authorisation" %} </th> <td> - <i class="material-icons">{{ application.skip_authorization|yesno:"check,close" }}</i> + <i class="material-icons iconify" data-icon="mdi:{{ application.skip_authorization|yesno:"check,close" }}"></i> </td> </tr> </tbody> diff --git a/aleksis/core/templates/oauth2_provider/application/edit.html b/aleksis/core/templates/oauth2_provider/application/edit.html index 30f50fff94e330e941d7b4730fe7d875b039d74e..e4d837a32d713ef07b05656425e97979efef92cd 100644 --- a/aleksis/core/templates/oauth2_provider/application/edit.html +++ b/aleksis/core/templates/oauth2_provider/application/edit.html @@ -11,7 +11,7 @@ {% form form=form %}{% endform %} {% include "core/partials/save_button.html" %} <a class="btn waves-effect red waves-light" href="{% url "oauth2_application" application.id %}"> - <i class="material-icons left">clear</i> {% trans "Cancel" %} + <i class="material-icons iconify left" data-icon="mdi:close"></i> {% trans "Cancel" %} </a> </form> {% endblock %} diff --git a/aleksis/core/templates/oauth2_provider/application/list.html b/aleksis/core/templates/oauth2_provider/application/list.html index ced7d718dfe1b561c2ea8253e25658a9f449024d..1525dc99c28326701d5b91a59c1992a23abff439 100644 --- a/aleksis/core/templates/oauth2_provider/application/list.html +++ b/aleksis/core/templates/oauth2_provider/application/list.html @@ -7,7 +7,7 @@ {% block content %} <a href="{% url "register_oauth_application" %}" class="btn green waves-effect waves-light"> - <i class="material-icons left">add</i> + <i class="material-icons iconify left" data-icon="mdi:add"></i> {% blocktrans %}Register new application{% endblocktrans %} </a> <div class="collection"> diff --git a/aleksis/core/templates/oauth2_provider/authorize.html b/aleksis/core/templates/oauth2_provider/authorize.html index c90d5e8dd9d3d72cff9e19ce167487900e904636..09293713fc126ec63fadec4e470206f78177a475 100644 --- a/aleksis/core/templates/oauth2_provider/authorize.html +++ b/aleksis/core/templates/oauth2_provider/authorize.html @@ -25,7 +25,7 @@ <p class="margin-bottom">{% trans "The application requests access to the following scopes:" %}</p> {% for scope in scopes_descriptions %} <p class="margin-bottom"> - <i class="material-icons left">check</i> + <i class="material-icons iconify left" data-icon="mdi:check"></i> {{ scope }} </p> {% endfor %} @@ -37,10 +37,10 @@ {% part form.allow %}<input type="hidden" value="true" name="allow">{% endpart %} {% endform %} <button type="submit" class="btn green waves-effect waves-light btn-margin"> - <i class="material-icons left">done_all</i> {% trans "Allow" %} + <i class="material-icons iconify left" data-icon="mdi:check-all"></i> {% trans "Allow" %} </button> <a class="btn red waves-effect waves-light btn-margin" href="{% block app-form-back-url %}{% url "oauth2_application" application.id %}{% endblock app-form-back-url %}"> - <i class="material-icons left">cancel</i> {% trans "Disallow" %} + <i class="material-icons iconify left" data-icon="mdi:close"></i> {% trans "Disallow" %} </a> </form> </div> @@ -50,7 +50,7 @@ <div class="container"> <div class="card red"> <div class="card-content white-text"> - <div class="material-icons small left">error_outline</div> + <div class="material-icons iconify small left" data-icon="mdi:alert-octagon-outline"></div> <span class="card-title">{% trans "Error" %}: {{ error.error }}</span> <p> {{ error.description }} diff --git a/aleksis/core/templates/oauth2_provider/authorized-oob.html b/aleksis/core/templates/oauth2_provider/authorized-oob.html index 3e95b0bf3a25691e0fc84e36dbcf71559cf86dc1..892ae5c9f863dcc32259210e652d18cfa3a27598 100644 --- a/aleksis/core/templates/oauth2_provider/authorized-oob.html +++ b/aleksis/core/templates/oauth2_provider/authorized-oob.html @@ -8,7 +8,7 @@ <div class="container"> <div class="card green"> <div class="card-content white-text"> - <div class="material-icons small left">check</div> + <div class="material-icons iconify small left" data-icon="mdi:check"></div> <span class="card-title">{% blocktrans %}Success!{% endblocktrans %}</span> <p> {% trans "Please return to your application and enter this code:" %} {{ code }} @@ -20,7 +20,7 @@ <div class="container"> <div class="card red"> <div class="card-content white-text"> - <div class="material-icons small left">error_outline</div> + <div class="material-icons iconify small left" data-icon="mdi:alert-octagon-outline"></div> <span class="card-title">{% trans "Error" %}: {{ error.error }}</span> <p> {{ error.description }} diff --git a/aleksis/core/templates/oauth2_provider/authorized-token-delete.html b/aleksis/core/templates/oauth2_provider/authorized-token-delete.html index 7f6f25920bebcbbaad7bb93fd486db617f25d662..ece2011b6e6170bd8ed845f8464302bb1e6fb8fb 100644 --- a/aleksis/core/templates/oauth2_provider/authorized-token-delete.html +++ b/aleksis/core/templates/oauth2_provider/authorized-token-delete.html @@ -8,7 +8,7 @@ {% block content %} <div class="alert info"> <p> - <i class="material-icons left">warning</i> + <i class="material-icons iconify left" data-icon="mdi:alert-outline"></i> {% trans "Are you sure to revoke the access for this application?" %} </p> </div> @@ -16,11 +16,11 @@ <form method="post"> {% csrf_token %} <a class="btn waves-effect waves-light red" href="{% url "oauth2_applications" %}"> - <i class="material-icons left">delete</i> + <i class="material-icons iconify left" data-icon="mdi:delete-outline"></i> {% trans "Revoke" %} </a> <a class="btn waves-effect waves-light" href="{% url "oauth2_applications" %}"> - <i class="material-icons left">cancel</i> + <i class="material-icons iconify left" data-icon="mdi:close"></i> {% trans "Cancel" %} </a> </form> diff --git a/aleksis/core/templates/oauth2_provider/authorized-tokens.html b/aleksis/core/templates/oauth2_provider/authorized-tokens.html index 46b0ce570a5ec1077825b283a244b6652045c437..dfe058056fb4ffaabd2a44eaac04adaa8aa3ad3b 100644 --- a/aleksis/core/templates/oauth2_provider/authorized-tokens.html +++ b/aleksis/core/templates/oauth2_provider/authorized-tokens.html @@ -29,7 +29,7 @@ {% else %} <div class="alert info"> <p> - <i class="material-icons left">info</i> + <i class="material-icons iconify left" data-icon="mdi:information-outline"></i> {% trans "No authorized applications." %} </p> </div> diff --git a/aleksis/core/templates/offline.html b/aleksis/core/templates/offline.html index bd741268a8902ac6708f33e353337695c03158a3..a386d40c1f9eb3d900676427f05904957f03211b 100644 --- a/aleksis/core/templates/offline.html +++ b/aleksis/core/templates/offline.html @@ -5,8 +5,10 @@ {% block browser_title %}{% blocktrans %}Network error{% endblocktrans %}{% endblock %} {% block content %} - <h3><i class="material-icons left medium" style="font-size: 2.92rem;">signal_wifi_off</i>{% blocktrans %}No internet - connection.{% endblocktrans %}</h3> + <h3> + <i class="material-icons iconify left medium" style="font-size: 2.92rem;" data-icon="mdi:wifi-strength-alert-outline"></i> + {% blocktrans %}No internet connection.{% endblocktrans %} + </h3> <p class="flow-text"> {% blocktrans %} diff --git a/aleksis/core/templates/search/search.html b/aleksis/core/templates/search/search.html index 5af1e55cc1076e404a921596da1cbc0774f7dbc3..ca32339d6d88010d2f4dab4d9e7557cd191705fe 100644 --- a/aleksis/core/templates/search/search.html +++ b/aleksis/core/templates/search/search.html @@ -18,7 +18,7 @@ <p> <button type="submit" class="btn waves-effect waves-light green"> - <i class="material-icons left">search</i> + <i class="material-icons iconify left" data-icon="mdi:search"></i> {% blocktrans %}Search{% endblocktrans %} </button> </p> @@ -29,7 +29,7 @@ <div class="collection"> {% for result in page_obj.object_list %} <a href="{{ result.object.get_absolute_url|default:"#" }}" class="collection-item"> - <i class="material-icons left">{{ result.object.icon_ }}</i> + <i class="material-icons iconify left" data-icon="mdi:{{ result.object.icon_ }}"></i> {{ result.object }} </a> {% empty %} @@ -46,12 +46,12 @@ {% if page_obj.has_previous %} <li class="waves-effect"> <a href="?q={{ query }}&page={{ page_obj.previous_page_number }}"> - <i class="material-icons">chevron_left</i> + <i class="material-icons iconify" data-icon="mdi:chevron-left"></i> </a> </li> {% else %} <li class="disabled"> - <a href="#"><i class="material-icons">chevron_left</i></a> + <a href="#"><i class="material-icons iconify" data-icon="mdi:chevron-left"></i></a> </li> {% endif %} @@ -70,12 +70,12 @@ {% if page_obj.has_next %} <li class="waves-effect"> <a href="?q={{ query }}&page={{ page_obj.next_page_number }}"> - <i class="material-icons">chevron_right</i> + <i class="material-icons iconify" data-icon="mdi:chevron-right"></i> </a> </li> {% else %} <li class="disabled"> - <a href="#"><i class="material-icons">chevron_right</i></a> + <a href="#"><i class="material-icons iconify" data-icon="mdi:chevron-right"></i></a> </li> {% endif %} </ul> diff --git a/aleksis/core/templates/search/searchbar_snippet.html b/aleksis/core/templates/search/searchbar_snippet.html index b5b7188c6a1e0381fd30f41b6fccc7e587949a30..d2a401c4f874d6a2c2a71c5b122eb3879cd83d57 100644 --- a/aleksis/core/templates/search/searchbar_snippet.html +++ b/aleksis/core/templates/search/searchbar_snippet.html @@ -1,4 +1,4 @@ <a href="{{ result.object.get_absolute_url|default:"#" }}" class="collection-item search-item"> {{ result.object }} - <i class="material-icons secondary-content search-result-icon">{{ result.object.icon_ }}</i> + <i class="material-icons secondary-content search-result-icon" data-icon="mdi:{{ result.object.icon_ }}"></i> </a> diff --git a/aleksis/core/templates/socialaccount/authentication_error.html b/aleksis/core/templates/socialaccount/authentication_error.html index 00901daf7fc3542ba07490381f7903e8f6d14048..43288dbc00e6ce84139254bf1b15d0781074d9eb 100644 --- a/aleksis/core/templates/socialaccount/authentication_error.html +++ b/aleksis/core/templates/socialaccount/authentication_error.html @@ -9,7 +9,7 @@ <div class="container"> <div class="card red"> <div class="card-content white-text"> - <div class="material-icons small left">error_outline</div> + <div class="material-icons iconify small left" data-icon="mdi:alert-octagon-outline"></div> <span class="card-title">{% blocktrans %}Third-party Account Login Failure.{% endblocktrans %}</span> <p> {% blocktrans %} diff --git a/aleksis/core/templates/socialaccount/login.html b/aleksis/core/templates/socialaccount/login.html index 1630b01fa4104f563a92663bc7fd386a2abd5266..6f9747e82978371eda6bbda59d1e195d399fc782 100644 --- a/aleksis/core/templates/socialaccount/login.html +++ b/aleksis/core/templates/socialaccount/login.html @@ -8,7 +8,7 @@ {% block content %} {% if process == "connect" %} <p class="flow-text"> - <i class="material-icons left">info</i> + <i class="material-icons iconify left" data-icon="mdi:information-outline"></i> {% blocktrans with provider.name as provider %}You are about to connect a new third party account from {{ provider }}.{% endblocktrans %} </p> <form method="post"> @@ -19,7 +19,7 @@ </form> {% else %} <p class="flow-text"> - <i class="material-icons left small">info</i> + <i class="material-icons iconify left small" data-icon="mdi:information-outline"></i> {% blocktrans with provider.name as provider %}You are about to sign in using a third party account from {{ provider }}.{% endblocktrans %} </p> <form method="post"> diff --git a/aleksis/core/templates/socialaccount/login_cancelled.html b/aleksis/core/templates/socialaccount/login_cancelled.html index bc1ebb6cb31a6b15a9d448cb93fa40a7cccb7d26..cb56d41b013e43c56853a3816ad63d8047e08a29 100644 --- a/aleksis/core/templates/socialaccount/login_cancelled.html +++ b/aleksis/core/templates/socialaccount/login_cancelled.html @@ -9,7 +9,7 @@ <div class="container"> <div class="card red"> <div class="card-content white-text"> - <div class="material-icons small left">error_outline</div> + <div class="material-icons iconify small left" data-icon="mdi:alert-octagon-outline"></div> <span class="card-title">{% blocktrans %}Login cancelled{% endblocktrans %}</span> <p> {% blocktrans %} diff --git a/aleksis/core/templates/socialaccount/signup.html b/aleksis/core/templates/socialaccount/signup.html index df79ecce459fa0ea7bcd8fe83ea21f530944c49b..7b11a3c40537933c4c4425a51b8c8913d3d0f8aa 100644 --- a/aleksis/core/templates/socialaccount/signup.html +++ b/aleksis/core/templates/socialaccount/signup.html @@ -8,7 +8,7 @@ {% block content %} <div class="alert success"> <p> - <i class="material-icons left">check_circle_outline</i> + <i class="material-icons iconify left" data-icon="mdi:check-circle-outline"></i> {% blocktrans with provider_name=account.get_provider.name site_name=site.name %}You are about to use your {{provider_name}} account to login to {{site_name}}. As a final step, please complete the following form:{% endblocktrans %} </p> diff --git a/aleksis/core/templates/socialaccount/snippets/provider_list.html b/aleksis/core/templates/socialaccount/snippets/provider_list.html index 9d9a9c87712076d8954ebce192ea2ac38383cc48..ea75c04fbd6d323308144e11a511a9e2fa7d4770 100644 --- a/aleksis/core/templates/socialaccount/snippets/provider_list.html +++ b/aleksis/core/templates/socialaccount/snippets/provider_list.html @@ -5,9 +5,9 @@ {% for provider in socialaccount_providers %} {% if provider.id == "openid" %} {% for brand in provider.get_brands %} - <a title="{{brand.name}}" + <a title="{{brand.name}}" class="socialaccount_provider {{provider.id}} {{brand.id}} - btn-large waves-effect waves-light primary-color" + btn-large waves-effect waves-light primary-color margin-bottom" href="{% provider_login_url provider.id openid=brand.openid_url process=process %}"> {% blocktrans with name=brand.name %} Login with {{ name }} @@ -16,7 +16,7 @@ {% endfor %} {% endif %} <a title="{{provider.name}}" class="socialaccount_provider {{provider.id}} - btn hundred-percent waves-effect waves-light primary-color" + btn hundred-percent waves-effect waves-light primary-color margin-bottom" href="{% provider_login_url provider.id process=process scope=scope auth_params=auth_params %}"> {% blocktrans with name=provider.name %} Login with {{ name }} @@ -26,7 +26,7 @@ {% else %} <div class="alert primary"> <div> - <i class="material-icons left">info</i> + <i class="material-icons iconify left" data-icon="mdi:information-outline"></i> {% blocktrans %} No third-party account providers available. {% endblocktrans %} diff --git a/aleksis/core/templates/two_factor/_wizard_actions.html b/aleksis/core/templates/two_factor/_wizard_actions.html index 95be950552fe6abf47e481bd507e6c28899986b0..dc4a046d6ce3ac4aa1a390b444f0080267a865d4 100644 --- a/aleksis/core/templates/two_factor/_wizard_actions.html +++ b/aleksis/core/templates/two_factor/_wizard_actions.html @@ -2,7 +2,7 @@ {% if cancel_url %} <a href="{{ cancel_url }}" class="btn red waves-effect waves-light"> - <i class="material-icons left">cancel</i> + <i class="material-icons iconify left" data-icon="mdi:close"></i> {% trans "Cancel" %} </a> {% endif %} @@ -11,17 +11,17 @@ <button name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}" class="btn grey waves-effect waves-light"> - <i class="material-icons left">arrow_back</i> + <i class="material-icons iconify left" data-icon="mdi:arrow-left"></i> {% trans "Back" %} </button> {% else %} <button disabled name="" type="button" class="btn grey disabled"> - <i class="material-icons left">arrow_back</i> + <i class="material-icons iconify left" data-icon="mdi:arrow-left"></i> {% trans "Back" %} </button> {% endif %} <button type="submit" class="btn green waves-effect waves-light"> - <i class="material-icons right">arrow_forward</i> + <i class="material-icons iconify right" data-icon="mdi:arrow-right"></i> {% trans "Next" %} </button> diff --git a/aleksis/core/templates/two_factor/core/backup_tokens.html b/aleksis/core/templates/two_factor/core/backup_tokens.html index b85450747fbe00623900af8d2832c0060446a042..94631e14d0bd993341bd51b3fdb493254fbb23e3 100644 --- a/aleksis/core/templates/two_factor/core/backup_tokens.html +++ b/aleksis/core/templates/two_factor/core/backup_tokens.html @@ -10,7 +10,7 @@ <div class="alert info"> <p> - <i class="material-icons left">info</i> + <i class="material-icons iconify left" data-icon="mdi:information-outline"></i> {% blocktrans %} Backup tokens can be used when your primary and backup phone numbers aren't available. The backup tokens below can be used @@ -29,7 +29,7 @@ </ul> <div class="alert warning"> <p> - <i class="material-icons left">warning</i> + <i class="material-icons iconify left" data-icon="mdi:alert-outline"></i> {% blocktrans %} Print these tokens and keep them somewhere safe. {% endblocktrans %} @@ -41,11 +41,11 @@ <form method="post">{% csrf_token %}{{ form }} <a href="{% url 'two_factor:profile' %}" class="btn primary waves-effect waves-light"> - <i class="material-icons left">arrow_back</i> + <i class="material-icons iconify left" data-icon="mdi:arrow-left"></i> {% trans "Back to Account Security" %} </a> <button class="btn green waves-effect waves-light" type="submit"> - <i class="material-icons left">vpn_key</i> + <i class="material-icons iconify left" data-icon="mdi:key-outline"></i> {% trans "Generate Tokens" %} </button> </form> diff --git a/aleksis/core/templates/two_factor/core/login.html b/aleksis/core/templates/two_factor/core/login.html index 834c4b98b543bd994542b105aec1b99932f7d186..77b135569d797181a45bd49d7fd7e9cded4e9a5c 100644 --- a/aleksis/core/templates/two_factor/core/login.html +++ b/aleksis/core/templates/two_factor/core/login.html @@ -90,13 +90,13 @@ {% include "two_factor/_wizard_forms.html" %} </div> - <div class="card-action-light"> + <div class="card-action-light login-card-action"> <button type="submit" class="btn green waves-effect waves-light"> {% trans "Login" %} <i class="material-icons right">send</i> </button> - {% if request.site.preferences.auth__allow_password_change and wizard.steps.current == "auth" %} - <a href="{% url "account_reset_password" %}" class="btn-flat right waves-effect waves-light"> + {% if request.site.preferences.auth__allow_password_reset and wizard.steps.current == "auth" %} + <a href="{% url "account_reset_password" %}" class="btn-flat right waves-effect waves-red"> {% trans "Reset password" %} </a> {% endif %} @@ -111,7 +111,8 @@ <p>{% trans "Or, alternatively, use one of your backup phones:" %}</p> <p> {% for other in other_devices %} - <button name="challenge_device" value="{{ other.persistent_id }}" class="btn" type="submit"> + <button name="challenge_device" value="{{ other.persistent_id }}" class="btn margin-bottom" + type="submit"> {{ other|device_action }} </button> {% endfor %} diff --git a/aleksis/core/templates/two_factor/core/setup_complete.html b/aleksis/core/templates/two_factor/core/setup_complete.html index df3f5e93acb1ded3138b9aea2375ce7d529c9033..afd9f1722b168bfe30807f5e8a4d4cb49c4bc900 100644 --- a/aleksis/core/templates/two_factor/core/setup_complete.html +++ b/aleksis/core/templates/two_factor/core/setup_complete.html @@ -10,7 +10,7 @@ <div class="alert success"> <p> - <i class="material-icons left">check_circle</i> + <i class="material-icons iconify left" data-icon="mdi:check-circle-outline"></i> {% blocktrans %} Congratulations, you've successfully enabled two-factor authentication. {% endblocktrans %} @@ -20,17 +20,17 @@ {% if not phone_methods %} <a href="{% url 'two_factor:profile' %}" class="btn btn-primary waves-effect waves-light"> - <i class="material-icons left">arrow_back</i> + <i class="material-icons iconify left" data-icon="mdi:arrow-left"></i> {% trans "Back to Profile" %} </a> <a href="{% url 'two_factor:backup_tokens' %}" class="btn green waves-effect waves-light"> - <i class="material-icons left">vpn_key</i> + <i class="material-icons iconify left" data-icon="mdi:key-outline"></i> {% trans "Generate backup codes" %} </a> {% else %} <div class="warning"> <p> - <i class="material-icons left">warning</i> + <i class="material-icons iconify left" data-icon="mdi:alert-outline"></i> {% blocktrans %} However, it might happen that you don't have access to your primary token device. To enable account recovery, generate backup codes @@ -40,15 +40,15 @@ </div> <a href="{% url 'two_factor:profile' %}" class="btn btn-primary waves-effect waves-light"> - <i class="material-icons left">arrow_back</i> + <i class="material-icons iconify left" data-icon="mdi:arrow-left"></i> {% trans "Back to Profile" %} </a> <a href="{% url 'two_factor:backup_tokens' %}" class="btn green waves-effect waves-light"> - <i class="material-icons left">vpn_key</i> + <i class="material-icons iconify left" data-icon="mdi:key-outline"></i> {% trans "Generate backup codes" %} </a> <a href="{% url 'two_factor:phone_create' %}" class="btn green waves-effect waves-light"> - <i class="material-icons left">add</i> + <i class="material-icons iconify left" data-icon="mdi:phone-plus"></i> {% trans "Add Phone Number" %} </a> {% endif %} diff --git a/aleksis/core/templates/two_factor/profile/disable.html b/aleksis/core/templates/two_factor/profile/disable.html index 56bf20164b16b75a2b1d7e0759c9d43ba8d5b242..4fe45187e3bbb9ae4ffadb5807f0d26a8bafff9a 100644 --- a/aleksis/core/templates/two_factor/profile/disable.html +++ b/aleksis/core/templates/two_factor/profile/disable.html @@ -22,7 +22,7 @@ </p> <button class="btn red waves-effect waves-light" type="submit"> - <i class="material-icons left">power_settings_new</i> + <i class="material-icons iconify left" data-icon="mdi:power"></i> {% trans "Disable" %} </button> </form> diff --git a/aleksis/core/templates/two_factor/profile/profile.html b/aleksis/core/templates/two_factor/profile/profile.html index eaaa0ff6a5a1bde9463682100dfb9cc6f6b0f3dc..dd9472e7fb9a09051b35d7be57f59dcab1549dae 100644 --- a/aleksis/core/templates/two_factor/profile/profile.html +++ b/aleksis/core/templates/two_factor/profile/profile.html @@ -37,7 +37,7 @@ </ul> <p> <a href="{% url 'two_factor:phone_create' %}" class="btn green waves-effect waves-light"> - <i class="material-icons left">add</i> + <i class="material-icons iconify left" data-icon="mdi:phone-plus"></i> {% trans "Add Phone Number" %} </a> </p> @@ -55,7 +55,7 @@ </p> <p> <a href="{% url 'two_factor:backup_tokens' %}" class="btn primary waves-effect waves-light"> - <i class="material-icons left">vpn_key</i> + <i class="material-icons iconify left" data-icon="mdi:key-outline"></i> {% trans "Show Codes" %} </a> </p> @@ -69,7 +69,7 @@ </p> <p> <a class="btn red waves-effect waves-light" href="{% url 'two_factor:disable' %}"> - <i class="material-icons left">power_settings_new</i> + <i class="material-icons iconify left" data-icon="mdi:power"></i> {% trans "Disable Two-Factor Authentication" %} </a> </p> @@ -84,6 +84,7 @@ <p> <a href="{% url 'two_factor:setup' %}" class="green btn waves-effect waves-light "> + <i class="material-icons iconify left" data-icon="mdi:key-outline"></i> {% trans "Enable Two-Factor Authentication" %} </a> </p> diff --git a/aleksis/core/templatetags/html_helpers.py b/aleksis/core/templatetags/html_helpers.py index 5f78b1b195f9030cc97d96a0488c14845d450741..34066192527930c2a4096f49deb3d247f883c31e 100644 --- a/aleksis/core/templatetags/html_helpers.py +++ b/aleksis/core/templatetags/html_helpers.py @@ -1,3 +1,6 @@ +import random +import string + from django import template from bs4 import BeautifulSoup @@ -22,3 +25,18 @@ def add_class_to_el(value: str, arg: str) -> str: el["class"] = el.get("class", []) + [cls] return str(soup) + + +@register.simple_tag +def generate_random_id(prefix: str, length: int = 10) -> str: + """Generate a random ID for templates. + + :Example: + + .. code-block:: + + {% generate_random_id "prefix-" %} + """ + return prefix + "".join( + random.choice(string.ascii_lowercase) for i in range(length) # noqa: S311 + ) diff --git a/aleksis/core/tests/models/test_notification.py b/aleksis/core/tests/models/test_notification.py index 1b1a6df054fe24f06bd363e825df3f1259af53e8..cdb01a04b99a398469ddfcd4466101c0b2d79f34 100644 --- a/aleksis/core/tests/models/test_notification.py +++ b/aleksis/core/tests/models/test_notification.py @@ -1,11 +1,81 @@ +from datetime import timedelta +from time import sleep +from unittest.mock import patch + +from django.test import override_settings +from django.utils import timezone + import pytest +from freezegun import freeze_time from aleksis.core.models import Notification, Person +from aleksis.core.util.notifications import _send_due_notifications pytestmark = pytest.mark.django_db -def test_email_notification(mailoutbox): +def test_send_notification(): + email = "doe@example.com" + recipient = Person.objects.create(first_name="Jane", last_name="Doe", email=email) + + sender = "Foo" + title = "There is happened something." + description = "Here you get some more information." + link = "https://aleksis.org/" + + notification = Notification( + sender=sender, + recipient=recipient, + title=title, + description=description, + link=link, + ) + + with patch("aleksis.core.models.Notification.send") as patched_send: + patched_send.assert_not_called() + + notification.save() + + patched_send.assert_called() + + +def test_send_scheduled_notification(): + email = "doe@example.com" + recipient = Person.objects.create(first_name="Jane", last_name="Doe", email=email) + + sender = "Foo" + title = "There is happened something." + description = "Here you get some more information." + link = "https://aleksis.org/" + + notification = Notification( + sender=sender, + recipient=recipient, + title=title, + description=description, + link=link, + send_at=timezone.now() + timedelta(days=1), + ) + notification.save() + + with patch("aleksis.core.models.Notification.send") as patched_send: + patched_send.assert_not_called() + + _send_due_notifications() + + patched_send.assert_not_called() + + with freeze_time(timezone.now() + timedelta(days=1)): + _send_due_notifications() + + patched_send.assert_called() + + +@override_settings(CELERY_BROKER_URL="memory://localhost//") +@pytest.mark.django_db( + databases=["default", "default_oot"], serialized_rollback=True, transaction=True +) +def test_email_notification(mailoutbox, celery_worker): email = "doe@example.com" recipient = Person.objects.create(first_name="Jane", last_name="Doe", email=email) @@ -19,6 +89,9 @@ def test_email_notification(mailoutbox): ) notification.save() + sleep(3) + + notification.refresh_from_db() assert notification.sent assert len(mailoutbox) == 1 diff --git a/aleksis/core/urls.py b/aleksis/core/urls.py index c91bae7f29c978d30e96361f92213eec7c5679d1..e76da89d18ed2078fc2405db11829aa344725fdf 100644 --- a/aleksis/core/urls.py +++ b/aleksis/core/urls.py @@ -30,6 +30,11 @@ urlpatterns = [ views.CustomPasswordChangeView.as_view(), name="account_change_password", ), + path( + "accounts/password/reset/", + views.CustomPasswordResetView.as_view(), + name="account_reset_password", + ), path("accounts/", include("allauth.urls")), path("invitations/send-invite", views.InvitePerson.as_view(), name="invite_person"), path( @@ -315,6 +320,12 @@ urlpatterns = [ name="assign_permission", ), path("pdfs/<int:pk>/", views.RedirectToPDFFile.as_view(), name="redirect_to_pdf_file"), + path("ical/", views.ICalFeedListView.as_view(), name="ical_feed_list"), + path("ical/create/", views.ICalFeedCreateView.as_view(), name="ical_feed_create"), + path("ical/<int:pk>/edit/", views.ICalFeedEditView.as_view(), name="ical_feed_edit"), + path("ical/<int:pk>/delete/", views.ICalFeedDeleteView.as_view(), name="ical_feed_delete"), + path("ical/<slug:slug>.ics", views.ICalFeedView.as_view(), name="ical_feed"), + path("__icons__/", include("dj_iconify.urls")), ] # Use custom server error handler to get a request object in the template diff --git a/aleksis/core/util/auth_helpers.py b/aleksis/core/util/auth_helpers.py index 056b5156da68233d3b3ee2378ccffdff95cfbcd6..6edfac83373882d077d0a588d822fd3a0d0cc9b4 100644 --- a/aleksis/core/util/auth_helpers.py +++ b/aleksis/core/util/auth_helpers.py @@ -3,6 +3,8 @@ from typing import Any, Optional from django.conf import settings +from django.contrib.auth.validators import ASCIIUsernameValidator +from django.core.validators import RegexValidator from django.http import HttpRequest from allauth.account.adapter import DefaultAccountAdapter @@ -16,6 +18,7 @@ from oauth2_provider.views.mixins import ( from oauthlib.common import Request as OauthlibRequest from .apps import AppConfig +from .core_helpers import get_site_preferences class OurSocialAccountAdapter(DefaultSocialAccountAdapter): @@ -134,3 +137,11 @@ class ClientProtectedResourceMixin(_ClientProtectedResourceMixin): required_scopes = set(self.get_scopes() or []) allowed_scopes = set(AppScopes().get_available_scopes(oauth_request.client) or []) return required_scopes.issubset(allowed_scopes) + + +def validate_username_preference_regex(value: str): + regex = get_site_preferences()["auth__allowed_username_regex"] + return RegexValidator(regex)(value) + + +custom_username_validators = [validate_username_preference_regex, ASCIIUsernameValidator()] diff --git a/aleksis/core/util/core_helpers.py b/aleksis/core/util/core_helpers.py index 6988dd53137f2d5ca364bcfd7091d9b1795e7f10..ffdba5f45c55454489c8b21c81688458c9808163 100644 --- a/aleksis/core/util/core_helpers.py +++ b/aleksis/core/util/core_helpers.py @@ -3,6 +3,7 @@ from datetime import datetime, timedelta from importlib import import_module, metadata from itertools import groupby from operator import itemgetter +from types import ModuleType from typing import Any, Callable, Dict, Optional, Sequence, Union from warnings import warn @@ -59,9 +60,31 @@ def dt_show_toolbar(request: HttpRequest) -> bool: return False -def get_app_packages() -> Sequence[str]: +def get_app_packages(only_official: bool = False) -> Sequence[str]: """Find all registered apps from the setuptools entrypoint.""" - return [f"{ep.module}.{ep.attr}" for ep in metadata.entry_points().get("aleksis.app", [])] + apps = [] + + for ep in metadata.entry_points().get("aleksis.app", []): + path = f"{ep.module}.{ep.attr}" + if path.startswith("aleksis.apps.") or not only_official: + apps.append(path) + + return apps + + +def get_app_settings_module(app: str) -> Optional[ModuleType]: + """Get the settings module of an app.""" + pkg = ".".join(app.split(".")[:-2]) + mod_settings = None + while "." in pkg: + try: + return import_module(pkg + ".settings") + except ImportError: + # Import errors are non-fatal. + pkg = ".".join(pkg.split(".")[:-1]) + + # The app does not have settings + return None def merge_app_settings( @@ -77,18 +100,8 @@ def merge_app_settings( potentially malicious apps! """ for app in get_app_packages(): - pkg = ".".join(app.split(".")[:-2]) - mod_settings = None - while "." in pkg: - try: - mod_settings = import_module(pkg + ".settings") - except ImportError: - # Import errors are non-fatal. - pkg = ".".join(pkg.split(".")[:-1]) - continue - break + mod_settings = get_app_settings_module(app) if not mod_settings: - # The app does not have settings continue app_setting = getattr(mod_settings, setting, None) @@ -109,6 +122,26 @@ def merge_app_settings( raise TypeError("Only dict and list settings can be merged.") +def get_app_settings_overrides() -> dict[str, Any]: + """Get app settings overrides. + + Official apps (those under the ``aleksis.apps` namespace) can override + or add settings by listing them in their ``settings.overrides``. + """ + overrides = {} + + for app in get_app_packages(True): + mod_settings = get_app_settings_module(app) + if not mod_settings: + continue + + if hasattr(mod_settings, "overrides"): + for name in mod_settings.overrides: + overrides[name] = getattr(mod_settings, name) + + return overrides + + def get_site_preferences(): """Get the preferences manager of the current site.""" from django.contrib.sites.models import Site # noqa @@ -288,11 +321,6 @@ def generate_random_code(length, packet_size) -> str: return get_random_string(packet_size * length).lower() -def unread_notifications_badge(request: HttpRequest) -> int: - """Generate badge content with the number of unread notifications.""" - return request.user.person.unread_notifications_count - - def monkey_patch() -> None: # noqa """Monkey-patch dependencies for special behaviour.""" # Unwrap promises in JSON serializer instead of stringifying diff --git a/aleksis/core/util/notifications.py b/aleksis/core/util/notifications.py index 13887a197defb9e24f5a9b1538561287b80c942f..061b8d3d8fae61f68b1c3f2fa9e9f3f421491292 100644 --- a/aleksis/core/util/notifications.py +++ b/aleksis/core/util/notifications.py @@ -5,6 +5,7 @@ from typing import Sequence, Union from django.apps import apps from django.conf import settings from django.template.loader import get_template +from django.utils import timezone from django.utils.functional import lazy from django.utils.translation import gettext_lazy as _ @@ -82,6 +83,8 @@ def send_notification(notification: Union[int, "Notification"], resend: bool = F name, check, send = _CHANNELS_MAP[channel] if check(): send(notification) + notification.sent = True + notification.save() def get_notification_choices() -> list: @@ -99,3 +102,12 @@ def get_notification_choices() -> list: get_notification_choices_lazy = lazy(get_notification_choices, tuple) + + +def _send_due_notifications(): + """Send all notifications that are due to be sent.""" + Notification = apps.get_model("core", "Notification") + + due_notifications = Notification.objects.filter(sent=False, send_at__lte=timezone.now()) + for notification in due_notifications: + notification.send() diff --git a/aleksis/core/util/predicates.py b/aleksis/core/util/predicates.py index bcba7e8637d81aa9c554aef65cdb431b059753a9..5ba4271c08a4244ba5f359e9c46e01eff6c6d112 100644 --- a/aleksis/core/util/predicates.py +++ b/aleksis/core/util/predicates.py @@ -154,3 +154,9 @@ def contains_site_preference_value(section: str, pref: str, value: str): def has_activated_2fa(user: User) -> bool: """Check if the user has activated two-factor authentication.""" return user_has_device(user) + + +@predicate +def is_assigned_to_current_person(user: User, obj: Model) -> bool: + """Check if the object is assigned to the current person.""" + return getattr(obj, "person", None) == user.person diff --git a/aleksis/core/views.py b/aleksis/core/views.py index 7be99d6a0e67aa552f53822f3b9fcbc4abf9e87b..ed20571dd83aee3bfc5d3bc4fd1dc2c8a7211b1d 100644 --- a/aleksis/core/views.py +++ b/aleksis/core/views.py @@ -36,7 +36,7 @@ from django.views.generic.list import ListView import reversion from allauth.account.utils import _has_verified_for_login, send_email_confirmation -from allauth.account.views import PasswordChangeView, SignupView +from allauth.account.views import PasswordChangeView, PasswordResetView, SignupView from allauth.socialaccount.adapter import get_adapter from allauth.socialaccount.models import SocialAccount from celery_progress.views import get_progress @@ -102,6 +102,7 @@ from .models import ( OAuthApplication, PDFFile, Person, + PersonalICalUrl, PersonInvitation, SchoolTerm, TaskUserAssignment, @@ -216,8 +217,12 @@ def index(request: HttpRequest) -> HttpResponse: widgets = [] activities = person.activities.all().order_by("-created")[:5] - notifications = person.notifications.all().order_by("-created")[:5] - unread_notifications = person.notifications.all().filter(read=False).order_by("-created") + notifications = person.notifications.filter(send_at__lte=timezone.now()).order_by("-created")[ + :5 + ] + unread_notifications = person.notifications.filter( + send_at__lte=timezone.now(), read=False + ).order_by("-created") context["activities"] = activities context["notifications"] = notifications @@ -246,7 +251,9 @@ class NotificationsListView(PermissionRequiredMixin, ListView): template_name = "core/notifications.html" def get_queryset(self) -> QuerySet: - return self.request.user.person.notifications.order_by("-created") + return self.request.user.person.notifications.filter(send_at__lte=timezone.now()).order_by( + "-created" + ) def get_context_data(self, **kwargs: Any) -> dict[str, Any]: self.get_queryset().filter(read=False).update(read=True) @@ -1365,6 +1372,20 @@ class CustomPasswordChangeView(PermissionRequiredMixin, PasswordChangeView): super().__init__(*args, **kwargs) +class CustomPasswordResetView(PermissionRequiredMixin, PasswordResetView): + """Custom password reset view to allow to disable resetting of password.""" + + permission_required = "core.can_reset_password" + + def __init__(self, *args, **kwargs): + if get_site_preferences()["auth__allow_password_reset"]: + self.template_name = "account/password_reset.html" + else: + self.template_name = "account/password_change_disabled.html" + + super().__init__(*args, **kwargs) + + class SocialAccountDeleteView(DeleteView): """Custom view to delete django-allauth social account.""" @@ -1546,3 +1567,59 @@ class CustomAuthorizationView(AuthorizationView): context = super().get_context_data(**kwargs) context["no_menu"] = True return context + + +class ICalFeedView(DetailView): + model = PersonalICalUrl + slug_field = "uuid" + + def get(self, request, *args, **kwargs): + obj: PersonalICalUrl = self.get_object() + if obj.ical_feed_object: + kwargs["person"] = obj.person + return obj.ical_feed_object()(request, *args, **kwargs) + else: + return HttpResponse(status=410) + + +class ICalFeedListView(PermissionRequiredMixin, ListView): + model = PersonalICalUrl + template_name = "core/ical/ical_list.html" + permission_required = "core.view_ical_rule" + + def get_queryset(self): + return self.model.objects.filter(person=self.request.user.person) + + +class ICalFeedEditView(PermissionRequiredMixin, AdvancedEditView): + model = PersonalICalUrl + template_name = "core/ical/ical_edit.html" + success_url = reverse_lazy("ical_feed_list") + success_message = _("ICal feed updated successfully") + permission_required = "core.edit_ical_rule" + + fields = ["name", "ical_feed"] + + +class ICalFeedDeleteView(PermissionRequiredMixin, AdvancedDeleteView): + model = PersonalICalUrl + template_name = "core/pages/delete.html" + success_url = reverse_lazy("ical_feed_list") + success_message = _("ICal feed deleted successfully") + permission_required = "core.delete_ical_rule" + + +class ICalFeedCreateView(PermissionRequiredMixin, AdvancedCreateView): + model = PersonalICalUrl + template_name = "core/ical/ical_create.html" + success_url = reverse_lazy("ical_feed_list") + success_message = _("ICal feed created successfully") + permission_required = "core.create_ical_rule" + + fields = ["name", "ical_feed"] + + def form_valid(self, form): + obj = form.save(commit=False) + obj.person = self.request.user.person + obj.save() + return super().form_valid(form) diff --git a/docs/admin/10_install.rst b/docs/admin/10_install.rst index c234fa5d7dfcd472c1e786a9909dca503a40e362..f8b41d0d98efd5daa1df64a5fceea9ae5b86c662 100644 --- a/docs/admin/10_install.rst +++ b/docs/admin/10_install.rst @@ -34,6 +34,7 @@ For an installation on a dedicated server, the following prerequisites are neede * nginx * Python 3.9 * Some system dependencies to build Python modules and manage frontend files + * System locales for all supported languages * The aforementioned paths Install system packages @@ -53,7 +54,8 @@ Install some packages from the Debian package system. python3-virtualenv \ chromium \ redis-server \ - postgresql + postgresql \ + locales-all Create PostgreSQL user and database ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -252,6 +254,5 @@ Finally, bring the stack up using: AlekSIS will be reachable on port 80 if you forgot to configure the environment. You are responsible for adding a reverse proxy like nginx providing TLS, etc. -.. _Dynaconf: https://dynaconf.readthedocs.io/en/latest/ .. _Let's Encrypt: https://certbot.eff.org/instructions .. _PyPI: https://pypi.org diff --git a/docs/admin/15_config_files.rst b/docs/admin/15_config_files.rst index adb94a8cac6375ec1b06dbb1de4b60fb0c761165..556713437cc467c38a4b3f2acf05c070b46554c6 100644 --- a/docs/admin/15_config_files.rst +++ b/docs/admin/15_config_files.rst @@ -40,7 +40,7 @@ A configuration file might look like this:: password = "SuperSecretPassword" [caching] - redis = { enabled = true, address = "127.0.0.1" } + redis = { enabled = true, address = "redis://127.0.0.1" } The `secret_key` setting above defines a single value. The following `http` section defines a table (cf. a dictionary) in one way, and you can see the diff --git a/docs/admin/22_registration.rst b/docs/admin/22_registration.rst index 2442b5ce6c59314928fb3f6504b2db51eaa02010..510500f2198ec6377c91d97bf1be903411f0daea 100644 --- a/docs/admin/22_registration.rst +++ b/docs/admin/22_registration.rst @@ -26,6 +26,16 @@ signup for everyone. A menu item will be added for public registration. .. warning:: Do not enable this feature unless you intend to run a public AlekSIS instance. +Before enabling registration, you should consider restricting allowed usernames. +By default, all ASCII characters are allowed in usernames. Often, it is advisable +to not allow special characters. This often depends on the systems that will be +linked to AlekSIS. + +To restrict usernames to a certain format, a regular expression can be defined +in the ``Regular expression for allowed usernames`` preference. For example, to +restrict the username to lower case letters and numbers, and beginning with a number, +the regex can be set to ``^[a-z][a-z0-9]+$`. + User invitations ~~~~~~~~~~~~~~~~ diff --git a/docs/admin/32_tasks.rst b/docs/admin/32_tasks.rst index f8e2dcaf2597487a853568fb6517d35d5d0093ae..4b7fd22353deebdf51b9ebec74fda531bc465633 100644 --- a/docs/admin/32_tasks.rst +++ b/docs/admin/32_tasks.rst @@ -24,3 +24,5 @@ is currently only possible through the Django Admin backend, under Under the *Periodic Tasks* app, you can define schedules and tasks. The names of tasks you can add manually are documented in the respective sections of the manual. + +.. _Celery: https://celeryproject.org/ diff --git a/docs/admin/50_dashboard.rst b/docs/admin/50_dashboard.rst index 0c7f6a3b5a5ebda81f417b1a86a1135540a580ba..bf2c72d8d4ed0d76832635bc727612ac982e182f 100644 --- a/docs/admin/50_dashboard.rst +++ b/docs/admin/50_dashboard.rst @@ -18,6 +18,14 @@ optionally with an icon or picture next to it. It therefore provides the followi As link title, the widget title will be used. +Static content widget +^^^^^^^^^^^^^^^^^^^^ + +The static content widget allows to display custom static information on the dashboard, +It therefore provides the following additional attribute: + +* **Content**: The content of the widget. HTML can be used for formatting. + More dashboard widgets from apps -------------------------------- diff --git a/docs/conf.py b/docs/conf.py index 2acaa4acf472ffb6ea2a1124d9371644186cc5c6..dc58a3b9a1acc1ecb89552e27e33a4c66dd48c96 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -29,9 +29,9 @@ copyright = "2019-2022 The AlekSIS team" author = "The AlekSIS Team" # The short X.Y version -version = "2.7" +version = "2.8" # The full version, including alpha/beta/rc tags -release = "2.7.5.dev0" +release = "2.8.2.dev0" # -- General configuration --------------------------------------------------- diff --git a/docs/dev/02_install_apps.rst b/docs/dev/02_install_apps.rst index 335f92f56735e0f1eb02eecdde626d5a074674ff..a376dd4f413380750c8b466c73fdd07973ac36f6 100644 --- a/docs/dev/02_install_apps.rst +++ b/docs/dev/02_install_apps.rst @@ -13,7 +13,7 @@ Installing a development environment for own apps ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If you are developing your own app, you probably do not want to -ru na development environment from the `AlekSIS-Core` repository. +run a development environment from the `AlekSIS-Core` repository. Instead, simply install the environment using ``poetry install`` from your app repository – it will pull in `AlekSIS-Core` as a dependency diff --git a/docs/dev/04_materialize_templates.rst b/docs/dev/04_materialize_templates.rst index b997c32f293e6268a2deae5b69001abaf9a84e10..b49677252af51905bf46084f42eb6a5811f173d7 100644 --- a/docs/dev/04_materialize_templates.rst +++ b/docs/dev/04_materialize_templates.rst @@ -56,13 +56,13 @@ Furthermore, you can use tabs with integrated icons that are higher, but more co <ul class="tabs tabs-transparent tabs-icons tabs-fixed-width"> <li class="tab"> <a href="#test1"> - <i class="material-icons">speaker_notes</i> + <i class="material-icons iconify" data-icon="mdi:speaker_notes"></i> Test 1 </a> </li> <li class="tab"> <a href="#test2"> - <i class="material-icons">people</i> + <i class="material-icons iconify" data-icon="mdi:people"></i> Test 2 </a> </li> diff --git a/docs/dev/06_merging_app_settings.rst b/docs/dev/06_merging_app_settings.rst index ad30c595f3dc8ef7bc39ab1b3a06b4785cc7276a..3c0c1affd210c706ac2959d02324f6ad9e009a2b 100644 --- a/docs/dev/06_merging_app_settings.rst +++ b/docs/dev/06_merging_app_settings.rst @@ -3,9 +3,15 @@ Merging of app settings AlekSIS provides features to merge app settings into main ``settings.py``. +Third-party apps can only add values to some select existing settings. +Official apps (those under the ``aleksis.apps.`` namespace) can mark any +setting for overriding. + Currently mergable settings --------------------------- +The following settings can be amended by any app: + * INSTALLED_APPS * DATABASES * YARN_INSTALLED_APPS @@ -23,3 +29,14 @@ the following into your ``settings.py``:: "HOST": "127.0.0.1", "PORT": 5432, } + } + +Overriding any setting +---------------------- + +Official apps only (currently) can override any setting, but need to explicitly +mark it by listing it in a list called ``overrides`` in their ``settings.py``:: + + PAYMENT_MODEL = "tezor.Invoice" + + overrides = ["PAYMENT_MODEL"] diff --git a/pyproject.toml b/pyproject.toml index 12199f73cd28724dffa7087dcb6628ea68943fe1..51f859a3a864acf61fc4755581242f751567d6dd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "AlekSIS-Core" -version = "2.7.5.dev0" +version = "2.8.2.dev0" packages = [ { include = "aleksis" } ] @@ -60,7 +60,7 @@ django-any-js = "^1.1" django-debug-toolbar = "^3.2" django-menu-generator-ng = "^1.2.3" django-tables2 = "^2.1" -django-phonenumber-field = {version = "^5.2", extras = ["phonenumbers"]} +django-phonenumber-field = {version = "^6.1", extras = ["phonenumbers"]} django-sass-processor = "1.0" libsass = "^0.21.0" colour = "^0.1.5" @@ -98,7 +98,7 @@ celery-haystack-ng = "^2.0" django-dbbackup = "^3.3.0" spdx-license-list = "^0.5.0" license-expression = "^21.6" -django-reversion = "^4.0.0" +django-reversion = "^5.0.0" django-favicon-plus-reloaded = "^1.1.5" django-health-check = "^3.12.1" psutil = "^5.7.0" @@ -126,6 +126,9 @@ python-gnupg = "^0.4.7" sentry-sdk = {version = "^1.4.3", optional = true} django-cte = "^1.1.5" pycountry = "^22.0.0" +django-ical = "^1.8.3" +django-iconify = "^0.2.0" +customidenticon = "^0.1.5" [tool.poetry.extras] ldap = ["django-auth-ldap"] @@ -133,7 +136,7 @@ s3 = ["boto3", "django-storages"] sentry = ["sentry-sdk"] [tool.poetry.dev-dependencies] -aleksis-builddeps = "^6" +aleksis-builddeps = "*" uwsgi = "^2.0" [tool.poetry.scripts]