diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 955750958d170e723e9714295750d0e1204e878f..b2516b9ec034623bc679680e228e6b96bbc0ef91 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -2,8 +2,14 @@ include:
     - project: "AlekSIS/official/AlekSIS"
       file: /ci/general.yml
     - project: "AlekSIS/official/AlekSIS"
-      file: /ci/test.yml
+      file: /ci/test/test.yml
     - project: "AlekSIS/official/AlekSIS"
-      file: /ci/build_dist.yml
+      file: /ci/test/lint.yml
     - project: "AlekSIS/official/AlekSIS"
-      file: /ci/deploy_pypi.yml
+      file: /ci/test/security.yml
+    - project: "AlekSIS/official/AlekSIS"
+      file: /ci/build/dist.yml
+    - project: "AlekSIS/official/AlekSIS"
+      file: /ci/deploy/pages.yml
+    - project: "AlekSIS/official/AlekSIS"
+      file: /ci/deploy/pypi.yml
diff --git a/aleksis/core/data_checks.py b/aleksis/core/data_checks.py
index cb15f66713dee2e66cd4b561fa360ca8fed8641b..1279822f8d1f28bb40e040d9eaf0bb8126540940 100644
--- a/aleksis/core/data_checks.py
+++ b/aleksis/core/data_checks.py
@@ -2,7 +2,7 @@ import logging
 
 from django.contrib.contenttypes.models import ContentType
 from django.db.models.aggregates import Count
-from django.utils.decorators import classproperty
+from django.utils.functional import classproperty
 from django.utils.translation import gettext as _
 
 import reversion
diff --git a/aleksis/core/locale/ar/LC_MESSAGES/django.po b/aleksis/core/locale/ar/LC_MESSAGES/django.po
index 72222e03530aaeaa08c80eee54cbcdb4d79acdb5..26513bbf79d22e23b2c3f8f90b93b5474034a972 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: 2020-12-28 21:33+0100\n"
+"POT-Creation-Date: 2021-01-11 21:30+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"
@@ -215,7 +215,7 @@ msgstr ""
 msgid "People"
 msgstr ""
 
-#: menus.py:185 models.py:803 templates/core/group_type/list.html:8
+#: menus.py:185 models.py:812 templates/core/group_type/list.html:8
 #: templates/core/group_type/list.html:9
 msgid "Group types"
 msgstr ""
@@ -282,7 +282,7 @@ msgstr ""
 msgid "URL / Link"
 msgstr ""
 
-#: models.py:66 models.py:776
+#: models.py:66 models.py:785
 msgid "Name"
 msgstr ""
 
@@ -302,7 +302,7 @@ msgstr ""
 msgid "There is already a school term for this time or a part of this time."
 msgstr ""
 
-#: models.py:115 models.py:742 templates/core/person/accounts.html:41
+#: models.py:115 models.py:744 templates/core/person/accounts.html:41
 msgid "Person"
 msgstr ""
 
@@ -402,7 +402,7 @@ msgstr ""
 msgid "Primary group"
 msgstr ""
 
-#: models.py:176 models.py:461 models.py:485 models.py:570 models.py:796
+#: models.py:176 models.py:461 models.py:485 models.py:570 models.py:805
 #: templates/core/person/full.html:120
 msgid "Description"
 msgstr ""
@@ -484,7 +484,7 @@ msgstr ""
 msgid "Recipient"
 msgstr ""
 
-#: models.py:486 models.py:777
+#: models.py:486 models.py:786
 msgid "Link"
 msgstr ""
 
@@ -569,122 +569,130 @@ msgid "> 1200 px>, 12 columns"
 msgstr ""
 
 #: models.py:734
-msgid "Dashboard Widget"
+msgid "Can edit default dashboard"
 msgstr ""
 
 #: models.py:735
+msgid "Dashboard Widget"
+msgstr ""
+
+#: models.py:736
 msgid "Dashboard Widgets"
 msgstr ""
 
-#: models.py:740
+#: models.py:741
 msgid "Dashboard widget"
 msgstr ""
 
-#: models.py:743
+#: models.py:746
 msgid "Order"
 msgstr ""
 
-#: models.py:746
+#: models.py:747
+msgid "Part of the default dashboard"
+msgstr ""
+
+#: models.py:755
 msgid "Dashboard widget order"
 msgstr ""
 
-#: models.py:747
+#: models.py:756
 msgid "Dashboard widget orders"
 msgstr ""
 
-#: models.py:753
+#: models.py:762
 msgid "Menu ID"
 msgstr ""
 
-#: models.py:766
+#: models.py:775
 msgid "Custom menu"
 msgstr ""
 
-#: models.py:767
+#: models.py:776
 msgid "Custom menus"
 msgstr ""
 
-#: models.py:774
+#: models.py:783
 msgid "Menu"
 msgstr ""
 
-#: models.py:778
+#: models.py:787
 msgid "Icon"
 msgstr ""
 
-#: models.py:784
+#: models.py:793
 msgid "Custom menu item"
 msgstr ""
 
-#: models.py:785
+#: models.py:794
 msgid "Custom menu items"
 msgstr ""
 
-#: models.py:795
+#: models.py:804
 msgid "Title of type"
 msgstr ""
 
-#: models.py:802 templates/core/group/full.html:47
+#: models.py:811 templates/core/group/full.html:47
 msgid "Group type"
 msgstr ""
 
-#: models.py:812
+#: models.py:821
 msgid "Can view system status"
 msgstr ""
 
-#: models.py:813
+#: models.py:822
 msgid "Can link persons to accounts"
 msgstr ""
 
-#: models.py:814
+#: models.py:823
 msgid "Can manage data"
 msgstr ""
 
-#: models.py:815
+#: models.py:824
 msgid "Can impersonate"
 msgstr ""
 
-#: models.py:816
+#: models.py:825
 msgid "Can use search"
 msgstr ""
 
-#: models.py:817
+#: models.py:826
 msgid "Can change site preferences"
 msgstr ""
 
-#: models.py:818
+#: models.py:827
 msgid "Can change person preferences"
 msgstr ""
 
-#: models.py:819
+#: models.py:828
 msgid "Can change group preferences"
 msgstr ""
 
-#: models.py:855
+#: models.py:864
 msgid "Related data check task"
 msgstr ""
 
-#: models.py:863
+#: models.py:872
 msgid "Issue solved"
 msgstr ""
 
-#: models.py:864
+#: models.py:873
 msgid "Notification sent"
 msgstr ""
 
-#: models.py:877
+#: models.py:886
 msgid "Data check result"
 msgstr ""
 
-#: models.py:878
+#: models.py:887
 msgid "Data check results"
 msgstr ""
 
-#: models.py:880
+#: models.py:889
 msgid "Can run data checks"
 msgstr ""
 
-#: models.py:881
+#: models.py:890
 msgid "Can solve data check problems"
 msgstr ""
 
@@ -954,6 +962,11 @@ msgstr ""
 msgid "Create %(name)s"
 msgstr ""
 
+#: templates/core/dashboard_widget/list.html:25
+#: templates/core/edit_dashboard.html:8 templates/core/edit_dashboard.html:15
+msgid "Edit default dashboard"
+msgstr ""
+
 #: templates/core/data_check/list.html:15
 msgid "Check data again"
 msgstr ""
@@ -1011,19 +1024,41 @@ msgid ""
 "          "
 msgstr ""
 
-#: templates/core/edit_dashboard.html:4 templates/core/edit_dashboard.html:5
+#: templates/core/edit_dashboard.html:6 templates/core/edit_dashboard.html:13
 #: templates/core/index.html:14
 msgid "Edit dashboard"
 msgstr ""
 
-#: templates/core/edit_dashboard.html:26
+#: templates/core/edit_dashboard.html:24
+msgid ""
+"\n"
+"          On this page you can arrange your personal dashboard. You can drag any items from \"Available widgets\" to \"Your\n"
+"          Dashboard\" or change the order by moving the widgets. After you have finished, please don't forget to click on\n"
+"          \"Save\".\n"
+"        "
+msgstr ""
+
+#: templates/core/edit_dashboard.html:30
+msgid ""
+"\n"
+"          On this page you can arrange the default dashboard which is shown when a user doesn't arrange his own\n"
+"          dashboard. You can drag any items from \"Available widgets\" to \"Default Dashboard\" or change the order\n"
+"          by moving the widgets. After you have finished, please don't forget to click on \"Save\".\n"
+"        "
+msgstr ""
+
+#: templates/core/edit_dashboard.html:48
 msgid "Available widgets"
 msgstr ""
 
-#: templates/core/edit_dashboard.html:33
+#: templates/core/edit_dashboard.html:57
 msgid "Your dashboard"
 msgstr ""
 
+#: templates/core/edit_dashboard.html:59
+msgid "Default dashboard"
+msgstr ""
+
 #: templates/core/group/child_groups.html:18
 msgid ""
 "\n"
@@ -1156,31 +1191,31 @@ msgstr ""
 msgid "Home"
 msgstr ""
 
-#: templates/core/index.html:49
+#: templates/core/index.html:50
 msgid ""
 "\n"
-"              You haven't selected any dashboard widgets. Please click on \"Edit dashboard\" to add widgets to your\n"
-"              personal dashboard.\n"
-"            "
+"          You didn't customise your dashboard so that you see the system default. Please click on \"Edit dashboard\" to\n"
+"          customise your personal dashboard.\n"
+"        "
 msgstr ""
 
-#: templates/core/index.html:60
+#: templates/core/index.html:59
 msgid "Last activities"
 msgstr ""
 
-#: templates/core/index.html:78
+#: templates/core/index.html:77
 msgid "No activities available yet."
 msgstr ""
 
-#: templates/core/index.html:83
+#: templates/core/index.html:82
 msgid "Recent notifications"
 msgstr ""
 
-#: templates/core/index.html:99
+#: templates/core/index.html:98
 msgid "More information →"
 msgstr ""
 
-#: templates/core/index.html:106
+#: templates/core/index.html:105
 msgid "No notifications available yet."
 msgstr ""
 
@@ -1495,10 +1530,6 @@ msgstr ""
 msgid "Save preferences"
 msgstr ""
 
-#: templates/dynamic_preferences/sections.html:7
-msgid "All"
-msgstr ""
-
 #: templates/impersonate/list_users.html:8
 msgid "Impersonate user"
 msgstr ""
@@ -1961,87 +1992,91 @@ msgstr ""
 msgid "SMS"
 msgstr ""
 
-#: views.py:134
+#: views.py:141
 msgid "The school term has been created."
 msgstr ""
 
-#: views.py:146
+#: views.py:153
 msgid "The school term has been saved."
 msgstr ""
 
-#: views.py:291
+#: views.py:298
 msgid "The child groups were successfully saved."
 msgstr ""
 
-#: views.py:329
+#: views.py:336
 msgid "The person has been saved."
 msgstr ""
 
-#: views.py:368
+#: views.py:375
 msgid "The group has been saved."
 msgstr ""
 
-#: views.py:460
+#: views.py:467
 msgid "The announcement has been saved."
 msgstr ""
 
-#: views.py:476
+#: views.py:483
 msgid "The announcement has been deleted."
 msgstr ""
 
-#: views.py:548
+#: views.py:562
 msgid "The preferences have been saved successfully."
 msgstr ""
 
-#: views.py:572
+#: views.py:586
 msgid "The person has been deleted."
 msgstr ""
 
-#: views.py:586
+#: views.py:600
 msgid "The group has been deleted."
 msgstr ""
 
-#: views.py:618
+#: views.py:632
 msgid "The additional_field has been saved."
 msgstr ""
 
-#: views.py:652
+#: views.py:666
 msgid "The additional field has been deleted."
 msgstr ""
 
-#: views.py:677
+#: views.py:691
 msgid "The group type has been saved."
 msgstr ""
 
-#: views.py:707
+#: views.py:721
 msgid "The group type has been deleted."
 msgstr ""
 
-#: views.py:735
+#: views.py:749
 msgid "The data check has been started. Please note that it may take a while before you are able to fetch the data on this page."
 msgstr ""
 
-#: views.py:740
+#: views.py:754
 msgid "The data check has finished."
 msgstr ""
 
-#: views.py:755
+#: views.py:769
 #, python-brace-format
 msgid "The solve option '{solve_option_obj.verbose_name}' "
 msgstr ""
 
-#: views.py:797
+#: views.py:811
 msgid "The dashboard widget has been saved."
 msgstr ""
 
-#: views.py:827
+#: views.py:841
 msgid "The dashboard widget has been created."
 msgstr ""
 
-#: views.py:837
+#: views.py:851
 msgid "The dashboard widget has been deleted."
 msgstr ""
 
-#: views.py:888
+#: views.py:914
 msgid "Your dashboard configuration has been saved successfully."
 msgstr ""
+
+#: views.py:916
+msgid "The configuration of the default dashboard has been saved successfully."
+msgstr ""
diff --git a/aleksis/core/locale/ar/LC_MESSAGES/djangojs.po b/aleksis/core/locale/ar/LC_MESSAGES/djangojs.po
index 64d17df1ddcb7ad0f6bf82e50d180900dc783cad..126b0ef841fd5c5732a533ae0604af89fcfb093b 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: 2020-12-28 21:33+0100\n"
+"POT-Creation-Date: 2021-01-11 21:30+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,3 +29,7 @@ msgstr ""
 #: static/js/main.js:17
 msgid "OK"
 msgstr ""
+
+#: static/js/main.js:118
+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 028c25be855ae4da39821f853500a18cc45ea81a..f44814ae73c4edaaa27294f5468eb3cb5eb9e44f 100644
--- a/aleksis/core/locale/de_DE/LC_MESSAGES/django.po
+++ b/aleksis/core/locale/de_DE/LC_MESSAGES/django.po
@@ -7,8 +7,8 @@ msgid ""
 msgstr ""
 "Project-Id-Version: AlekSIS (School Information System) 0.1\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-12-28 21:33+0100\n"
-"PO-Revision-Date: 2020-12-28 20:51+0000\n"
+"POT-Creation-Date: 2021-01-11 21:30+0100\n"
+"PO-Revision-Date: 2021-01-11 20:42+0000\n"
 "Last-Translator: Jonathan Weth <teckids@jonathanweth.de>\n"
 "Language-Team: German <https://translate.edugit.org/projects/aleksis/aleksis/"
 "de/>\n"
@@ -17,7 +17,7 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.3.2\n"
+"X-Generator: Weblate 4.4\n"
 
 #: data_checks.py:53
 msgid "Ignore problem"
@@ -216,7 +216,7 @@ msgstr "Backend-Administration"
 msgid "People"
 msgstr "Leute"
 
-#: menus.py:185 models.py:803 templates/core/group_type/list.html:8
+#: menus.py:185 models.py:812 templates/core/group_type/list.html:8
 #: templates/core/group_type/list.html:9
 msgid "Group types"
 msgstr "Gruppentypen"
@@ -283,7 +283,7 @@ msgstr "Text (mehrzeilig)"
 msgid "URL / Link"
 msgstr "URL / Link"
 
-#: models.py:66 models.py:776
+#: models.py:66 models.py:785
 msgid "Name"
 msgstr "Name"
 
@@ -303,7 +303,7 @@ msgstr "Das Startdatum muss vor dem Enddatum liegen."
 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."
 
-#: models.py:115 models.py:742 templates/core/person/accounts.html:41
+#: models.py:115 models.py:744 templates/core/person/accounts.html:41
 msgid "Person"
 msgstr "Person"
 
@@ -403,7 +403,7 @@ msgstr "Erziehungsberechtigte / Eltern"
 msgid "Primary group"
 msgstr "Primärgruppe"
 
-#: models.py:176 models.py:461 models.py:485 models.py:570 models.py:796
+#: models.py:176 models.py:461 models.py:485 models.py:570 models.py:805
 #: templates/core/person/full.html:120
 msgid "Description"
 msgstr "Beschreibung"
@@ -434,7 +434,7 @@ msgstr "Kann Kindgruppen zu Gruppen zuordnen"
 
 #: models.py:341
 msgid "Can view statistics about group."
-msgstr "Kann Statistiken über Gruppen sehen"
+msgstr "Kann Statistiken über Gruppen sehen."
 
 #: models.py:352
 msgid "Long name"
@@ -485,7 +485,7 @@ msgstr "Absender"
 msgid "Recipient"
 msgstr "Empfänger"
 
-#: models.py:486 models.py:777
+#: models.py:486 models.py:786
 msgid "Link"
 msgstr "Link"
 
@@ -570,122 +570,130 @@ msgid "> 1200 px>, 12 columns"
 msgstr "> 1200 px, 12 Spalten"
 
 #: models.py:734
+msgid "Can edit default dashboard"
+msgstr "Kann Standarddashboard bearbeiten"
+
+#: models.py:735
 msgid "Dashboard Widget"
 msgstr "Dashboard-Widget"
 
-#: models.py:735
+#: models.py:736
 msgid "Dashboard Widgets"
 msgstr "Dashboard-Widgets"
 
-#: models.py:740
+#: models.py:741
 msgid "Dashboard widget"
 msgstr "Dashboard-Widget"
 
-#: models.py:743
+#: models.py:746
 msgid "Order"
 msgstr "Reihenfolge"
 
-#: models.py:746
+#: models.py:747
+msgid "Part of the default dashboard"
+msgstr "Teil des Standarddashboards"
+
+#: models.py:755
 msgid "Dashboard widget order"
 msgstr "Reihenfolge der Dashboard-Widgets"
 
-#: models.py:747
+#: models.py:756
 msgid "Dashboard widget orders"
 msgstr "Reihenfolgen der Dashboard-Widgets"
 
-#: models.py:753
+#: models.py:762
 msgid "Menu ID"
 msgstr "Menü-ID"
 
-#: models.py:766
+#: models.py:775
 msgid "Custom menu"
 msgstr "Benutzerdefiniertes Menü"
 
-#: models.py:767
+#: models.py:776
 msgid "Custom menus"
 msgstr "Benutzerdefinierte Menüs"
 
-#: models.py:774
+#: models.py:783
 msgid "Menu"
 msgstr "Menü"
 
-#: models.py:778
+#: models.py:787
 msgid "Icon"
 msgstr "Icon"
 
-#: models.py:784
+#: models.py:793
 msgid "Custom menu item"
 msgstr "Benutzerdefiniertes Menüelement"
 
-#: models.py:785
+#: models.py:794
 msgid "Custom menu items"
 msgstr "Benutzerdefinierte Menüelemente"
 
-#: models.py:795
+#: models.py:804
 msgid "Title of type"
 msgstr "Titel des Typs"
 
-#: models.py:802 templates/core/group/full.html:47
+#: models.py:811 templates/core/group/full.html:47
 msgid "Group type"
 msgstr "Gruppentyp"
 
-#: models.py:812
+#: models.py:821
 msgid "Can view system status"
 msgstr "Kann Systemstatus sehen"
 
-#: models.py:813
+#: models.py:822
 msgid "Can link persons to accounts"
 msgstr "Kann Personen mit Benutzerkonten verknüpfen"
 
-#: models.py:814
+#: models.py:823
 msgid "Can manage data"
 msgstr "Kann Daten verwalten"
 
-#: models.py:815
+#: models.py:824
 msgid "Can impersonate"
 msgstr "Kann sich verkleiden"
 
-#: models.py:816
+#: models.py:825
 msgid "Can use search"
 msgstr "Kann Suche benutzen"
 
-#: models.py:817
+#: models.py:826
 msgid "Can change site preferences"
 msgstr "Kann Konfiguration ändern"
 
-#: models.py:818
+#: models.py:827
 msgid "Can change person preferences"
 msgstr "Kann Einstellungen einer Person verändern"
 
-#: models.py:819
+#: models.py:828
 msgid "Can change group preferences"
 msgstr "Kann Einstellungen einer Gruppe verändern"
 
-#: models.py:855
+#: models.py:864
 msgid "Related data check task"
 msgstr "Zugehörige Datenprüfungsaufgabe"
 
-#: models.py:863
+#: models.py:872
 msgid "Issue solved"
 msgstr "Problem gelöst"
 
-#: models.py:864
+#: models.py:873
 msgid "Notification sent"
 msgstr "Benachrichtigung gesendet"
 
-#: models.py:877
+#: models.py:886
 msgid "Data check result"
 msgstr "Datenprüfungsergebnis"
 
-#: models.py:878
+#: models.py:887
 msgid "Data check results"
 msgstr "Datenprüfungsergebnisse"
 
-#: models.py:880
+#: models.py:889
 msgid "Can run data checks"
 msgstr "Kann Datenprüfungen ausführen"
 
-#: models.py:881
+#: models.py:890
 msgid "Can solve data check problems"
 msgstr "Kann Datenprüfungsprobleme lösen"
 
@@ -978,6 +986,11 @@ msgstr "%(widget)s bearbeiten"
 msgid "Create %(name)s"
 msgstr "%(name)s erstellen"
 
+#: templates/core/dashboard_widget/list.html:25
+#: templates/core/edit_dashboard.html:8 templates/core/edit_dashboard.html:15
+msgid "Edit default dashboard"
+msgstr "Standard-Dashboard bearbeiten"
+
 #: templates/core/data_check/list.html:15
 msgid "Check data again"
 msgstr "Daten erneut prüfen"
@@ -1040,19 +1053,59 @@ msgstr ""
 "            Das System wird nach folgenden Problemen suchen:\n"
 "          "
 
-#: templates/core/edit_dashboard.html:4 templates/core/edit_dashboard.html:5
+#: templates/core/edit_dashboard.html:6 templates/core/edit_dashboard.html:13
 #: templates/core/index.html:14
 msgid "Edit dashboard"
 msgstr "Dashboard bearbeiten"
 
-#: templates/core/edit_dashboard.html:26
+#: templates/core/edit_dashboard.html:24
+msgid ""
+"\n"
+"          On this page you can arrange your personal dashboard. You can drag any items from \"Available widgets\" to \"Your\n"
+"          Dashboard\" or change the order by moving the widgets. After you have finished, please don't forget to click on\n"
+"          \"Save\".\n"
+"        "
+msgstr ""
+"\n"
+"          Auf dieser Seite können Sie Ihr persönliches Dashboard "
+"zusammenstallen. Sie können beliebige Elemente von den \"Verfügbaren "
+"Widgets\" \n"
+"in \"Ihr Dashboard\" ziehen oder die Reihenfolge verändern, indem Sie die "
+"Widgets bewegen. Wenn Sie fertig sind, vergessen Sie bitte nicht, \n"
+"auf \"Speichern\" zu drücken.\n"
+"        "
+
+#: templates/core/edit_dashboard.html:30
+msgid ""
+"\n"
+"          On this page you can arrange the default dashboard which is shown when a user doesn't arrange his own\n"
+"          dashboard. You can drag any items from \"Available widgets\" to \"Default Dashboard\" or change the order\n"
+"          by moving the widgets. After you have finished, please don't forget to click on \"Save\".\n"
+"        "
+msgstr ""
+"\n"
+"          Auf dieser Seite können Sie Ihr das Standard-Dashboard "
+"zusammenstallen, welches angezeigt wird, wenn ein Nutzer kein eigenes "
+"definiert. \n"
+"Sie können beliebige Elemente von den \"Verfügbaren Widgets\" in \"Standard-"
+"Dashboard\" ziehen oder die Reihenfolge verändern, indem Sie die Widgets "
+"bewegen. \n"
+"Wenn Sie fertig sind, vergessen Sie bitte nicht, auf \"Speichern\" zu "
+"drücken.\n"
+"        "
+
+#: templates/core/edit_dashboard.html:48
 msgid "Available widgets"
 msgstr "Verfügbare Widgets"
 
-#: templates/core/edit_dashboard.html:33
+#: templates/core/edit_dashboard.html:57
 msgid "Your dashboard"
 msgstr "Ihr Dashboard"
 
+#: templates/core/edit_dashboard.html:59
+msgid "Default dashboard"
+msgstr "Standard-Dashboard"
+
 #: templates/core/group/child_groups.html:18
 msgid ""
 "\n"
@@ -1197,36 +1250,37 @@ msgstr "Gruppentyp erstellen"
 msgid "Home"
 msgstr "Startseite"
 
-#: templates/core/index.html:49
+#: templates/core/index.html:50
 msgid ""
 "\n"
-"              You haven't selected any dashboard widgets. Please click on \"Edit dashboard\" to add widgets to your\n"
-"              personal dashboard.\n"
-"            "
+"          You didn't customise your dashboard so that you see the system default. Please click on \"Edit dashboard\" to\n"
+"          customise your personal dashboard.\n"
+"        "
 msgstr ""
 "\n"
-"              Sie haben keine Dashboard-Widgets ausgewählt. Bitte klicken "
-"Sie auf \"Dashboard bearbeiten\",\n"
-" um Widgets zu Ihrem persönlichen Dashboard hinzuzufügen.\n"
-"            "
+"          Sie haben Ihr Dashboard nicht angepasst, sodass Sie das Standard-"
+"Dashboard sehen.\n"
+"Bitte klicken Sie auf \"Dashboard bearbeiten\", um Ihr persönliches "
+"Dashboard anzupassen.\n"
+"        "
 
-#: templates/core/index.html:60
+#: templates/core/index.html:59
 msgid "Last activities"
 msgstr "Letzte Aktivitäten"
 
-#: templates/core/index.html:78
+#: templates/core/index.html:77
 msgid "No activities available yet."
 msgstr "Aktuell keine Aktivitäten verfügbar."
 
-#: templates/core/index.html:83
+#: templates/core/index.html:82
 msgid "Recent notifications"
 msgstr "Letzte Benachrichtigungen"
 
-#: templates/core/index.html:99
+#: templates/core/index.html:98
 msgid "More information →"
 msgstr "Mehr Informationen →"
 
-#: templates/core/index.html:106
+#: templates/core/index.html:105
 msgid "No notifications available yet."
 msgstr "Aktuell keine Benachrichtigungen verfügbar."
 
@@ -1593,10 +1647,6 @@ msgstr "Einstellungen für %(instance)s"
 msgid "Save preferences"
 msgstr "Einstellungen speichern"
 
-#: templates/dynamic_preferences/sections.html:7
-msgid "All"
-msgstr "Alle"
-
 #: templates/impersonate/list_users.html:8
 msgid "Impersonate user"
 msgstr "Als Benutzer verkleiden"
@@ -1665,8 +1715,7 @@ msgid ""
 msgstr ""
 "\n"
 "  das System hat einige neue Probleme mit Ihren Daten entdeckt.\n"
-"Bitte nehmen Sie sich etwas Zeit, diese zu überprüfen und sie zu lösen oder "
-"als ignoriert zu markieren.\n"
+"Bitte nehmen Sie sich etwas Zeit, diese zu überprüfen und sie zu lösen oder als ignoriert zu markieren.\n"
 " "
 
 #: templates/templated_email/data_checks.email:26
@@ -1678,8 +1727,7 @@ msgid ""
 msgstr ""
 "\n"
 "   das System hat einige neue Probleme mit Ihren Daten entdeckt.\n"
-"Bitte nehmen Sie sich etwas Zeit, diese zu überprüfen und sie zu lösen oder "
-"als ignoriert zu markieren.\n"
+"Bitte nehmen Sie sich etwas Zeit, diese zu überprüfen und sie zu lösen oder als ignoriert zu markieren.\n"
 "  "
 
 #: templates/templated_email/data_checks.email:34
@@ -2172,93 +2220,99 @@ msgstr "E-Mail"
 msgid "SMS"
 msgstr "SMS"
 
-#: views.py:134
+#: views.py:141
 msgid "The school term has been created."
 msgstr "Das Schuljahr wurde erstellt."
 
-#: views.py:146
+#: views.py:153
 msgid "The school term has been saved."
 msgstr "Das Schuljahr wurde gespeichert."
 
-#: views.py:291
+#: views.py:298
 msgid "The child groups were successfully saved."
 msgstr "Die Untergruppen wurden gespeichert."
 
-#: views.py:329
+#: views.py:336
 msgid "The person has been saved."
 msgstr "Die Person wurde gespeichert."
 
-#: views.py:368
+#: views.py:375
 msgid "The group has been saved."
 msgstr "Die Gruppe wurde gespeichert."
 
-#: views.py:460
+#: views.py:467
 msgid "The announcement has been saved."
 msgstr "Die Ankündigung wurde gespeichert."
 
-#: views.py:476
+#: views.py:483
 msgid "The announcement has been deleted."
 msgstr "Ankündigung wurde gelöscht."
 
-#: views.py:548
+#: views.py:562
 msgid "The preferences have been saved successfully."
 msgstr "Die Einstellungen wurde gespeichert."
 
-#: views.py:572
+#: views.py:586
 msgid "The person has been deleted."
 msgstr "Die Person wurde gelöscht."
 
-#: views.py:586
+#: views.py:600
 msgid "The group has been deleted."
 msgstr "Die Gruppe wurde gelöscht."
 
-#: views.py:618
+#: views.py:632
 msgid "The additional_field has been saved."
 msgstr "Das zusätzliche Feld wurde gespeichert."
 
-#: views.py:652
+#: views.py:666
 msgid "The additional field has been deleted."
 msgstr "Das zusätzliche Feld wurde gelöscht."
 
-#: views.py:677
+#: views.py:691
 msgid "The group type has been saved."
 msgstr "Der Gruppentyp wurde gespeichert."
 
-#: views.py:707
+#: views.py:721
 msgid "The group type has been deleted."
 msgstr "Der Gruppentyp wurde gelöscht."
 
-#: views.py:735
+#: views.py:749
 msgid "The data check has been started. Please note that it may take a while before you are able to fetch the data on this page."
-msgstr ""
-"Die Datenüberprüfung wurde gestartet. Bitte beachten Sie, dass es eine Weile "
-"dauern kann, bevor Sie auf dieser Seite Ergebnisse abrufen können."
+msgstr "Die Datenüberprüfung wurde gestartet. Bitte beachten Sie, dass es eine Weile dauern kann, bevor Sie auf dieser Seite Ergebnisse abrufen können."
 
-#: views.py:740
+#: views.py:754
 msgid "The data check has finished."
 msgstr "Die Datenüberprüfung wurde beendet."
 
-#: views.py:755
+#: views.py:769
 #, python-brace-format
 msgid "The solve option '{solve_option_obj.verbose_name}' "
 msgstr "Die Lösungsoption \"{solve_option_obj.verbose_name}\" "
 
-#: views.py:797
+#: views.py:811
 msgid "The dashboard widget has been saved."
 msgstr "Das Dashboard-Widget wurde gespeichert."
 
-#: views.py:827
+#: views.py:841
 msgid "The dashboard widget has been created."
 msgstr "Das Dashboard-Widget wurde erstellt."
 
-#: views.py:837
+#: views.py:851
 msgid "The dashboard widget has been deleted."
 msgstr "Das Dashboard-Widget wurde gelöscht."
 
-#: views.py:888
+#: views.py:914
 msgid "Your dashboard configuration has been saved successfully."
 msgstr "Ihre Dashboardkonfiguration wurde erfolgreich gespeichert."
 
+#: views.py:916
+msgid "The configuration of the default dashboard has been saved successfully."
+msgstr ""
+"Die Konfiguration des Standard-Dashboardes wurde erfolgreich gespeichert."
+
+#~ msgid "All"
+#~ msgstr "Alle"
+
 #~ msgid ""
 #~ "\n"
 #~ "              Created by %(person)s\n"
diff --git a/aleksis/core/locale/de_DE/LC_MESSAGES/djangojs.po b/aleksis/core/locale/de_DE/LC_MESSAGES/djangojs.po
index 5bb148cb4b38e3e00e9803ce59278400cb7ccc3f..ea24fc3ff92afc211898fb8b426dccb97fce56ed 100644
--- a/aleksis/core/locale/de_DE/LC_MESSAGES/djangojs.po
+++ b/aleksis/core/locale/de_DE/LC_MESSAGES/djangojs.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-12-28 21:33+0100\n"
+"POT-Creation-Date: 2021-01-11 21:30+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"
@@ -28,3 +28,7 @@ msgstr ""
 #: static/js/main.js:17
 msgid "OK"
 msgstr ""
+
+#: static/js/main.js:118
+msgid "This page may contain outdated information since there is no internet connection."
+msgstr ""
diff --git a/aleksis/core/locale/fr/LC_MESSAGES/django.po b/aleksis/core/locale/fr/LC_MESSAGES/django.po
index c174394217c798996b0946f14ff1ed79d3a2e215..0938d0f9e68b50c905b6e0c232ade944ee0907a6 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: 2020-12-28 21:33+0100\n"
+"POT-Creation-Date: 2021-01-11 21:30+0100\n"
 "PO-Revision-Date: 2020-04-27 13:03+0000\n"
 "Last-Translator: Marlene Grundey <grundema@katharineum.de>\n"
 "Language-Team: French <https://translate.edugit.org/projects/aleksis/aleksis/fr/>\n"
@@ -229,7 +229,7 @@ msgstr ""
 msgid "People"
 msgstr ""
 
-#: menus.py:185 models.py:803 templates/core/group_type/list.html:8
+#: menus.py:185 models.py:812 templates/core/group_type/list.html:8
 #: templates/core/group_type/list.html:9
 #, fuzzy
 #| msgid "Group"
@@ -298,7 +298,7 @@ msgstr ""
 msgid "URL / Link"
 msgstr ""
 
-#: models.py:66 models.py:776
+#: models.py:66 models.py:785
 msgid "Name"
 msgstr ""
 
@@ -320,7 +320,7 @@ msgstr ""
 msgid "There is already a school term for this time or a part of this time."
 msgstr ""
 
-#: models.py:115 models.py:742 templates/core/person/accounts.html:41
+#: models.py:115 models.py:744 templates/core/person/accounts.html:41
 msgid "Person"
 msgstr "Personne"
 
@@ -432,7 +432,7 @@ msgstr ""
 msgid "Primary group"
 msgstr ""
 
-#: models.py:176 models.py:461 models.py:485 models.py:570 models.py:796
+#: models.py:176 models.py:461 models.py:485 models.py:570 models.py:805
 #: templates/core/person/full.html:120
 msgid "Description"
 msgstr "Description"
@@ -518,7 +518,7 @@ msgstr ""
 msgid "Recipient"
 msgstr ""
 
-#: models.py:486 models.py:777
+#: models.py:486 models.py:786
 msgid "Link"
 msgstr ""
 
@@ -603,130 +603,138 @@ msgid "> 1200 px>, 12 columns"
 msgstr ""
 
 #: models.py:734
-msgid "Dashboard Widget"
+msgid "Can edit default dashboard"
 msgstr ""
 
 #: models.py:735
+msgid "Dashboard Widget"
+msgstr ""
+
+#: models.py:736
 msgid "Dashboard Widgets"
 msgstr ""
 
-#: models.py:740
+#: models.py:741
 msgid "Dashboard widget"
 msgstr ""
 
-#: models.py:743
+#: models.py:746
 msgid "Order"
 msgstr ""
 
-#: models.py:746
+#: models.py:747
+msgid "Part of the default dashboard"
+msgstr ""
+
+#: models.py:755
 msgid "Dashboard widget order"
 msgstr ""
 
-#: models.py:747
+#: models.py:756
 msgid "Dashboard widget orders"
 msgstr ""
 
-#: models.py:753
+#: models.py:762
 msgid "Menu ID"
 msgstr ""
 
-#: models.py:766
+#: models.py:775
 msgid "Custom menu"
 msgstr ""
 
-#: models.py:767
+#: models.py:776
 msgid "Custom menus"
 msgstr ""
 
-#: models.py:774
+#: models.py:783
 msgid "Menu"
 msgstr ""
 
-#: models.py:778
+#: models.py:787
 msgid "Icon"
 msgstr ""
 
-#: models.py:784
+#: models.py:793
 msgid "Custom menu item"
 msgstr ""
 
-#: models.py:785
+#: models.py:794
 msgid "Custom menu items"
 msgstr ""
 
-#: models.py:795
+#: models.py:804
 msgid "Title of type"
 msgstr ""
 
-#: models.py:802 templates/core/group/full.html:47
+#: models.py:811 templates/core/group/full.html:47
 #, fuzzy
 #| msgid "Group"
 msgid "Group type"
 msgstr "Groupe"
 
-#: models.py:812
+#: models.py:821
 #, fuzzy
 #| msgid "Contact details"
 msgid "Can view system status"
 msgstr "Détails de contact"
 
-#: models.py:813
+#: models.py:822
 #, fuzzy
 #| msgid "Contact details"
 msgid "Can link persons to accounts"
 msgstr "Détails de contact"
 
-#: models.py:814
+#: models.py:823
 msgid "Can manage data"
 msgstr ""
 
-#: models.py:815
+#: models.py:824
 #, fuzzy
 #| msgid "Contact details"
 msgid "Can impersonate"
 msgstr "Détails de contact"
 
-#: models.py:816
+#: models.py:825
 msgid "Can use search"
 msgstr ""
 
-#: models.py:817
+#: models.py:826
 msgid "Can change site preferences"
 msgstr ""
 
-#: models.py:818
+#: models.py:827
 msgid "Can change person preferences"
 msgstr ""
 
-#: models.py:819
+#: models.py:828
 msgid "Can change group preferences"
 msgstr ""
 
-#: models.py:855
+#: models.py:864
 msgid "Related data check task"
 msgstr ""
 
-#: models.py:863
+#: models.py:872
 msgid "Issue solved"
 msgstr ""
 
-#: models.py:864
+#: models.py:873
 msgid "Notification sent"
 msgstr ""
 
-#: models.py:877
+#: models.py:886
 msgid "Data check result"
 msgstr ""
 
-#: models.py:878
+#: models.py:887
 msgid "Data check results"
 msgstr ""
 
-#: models.py:880
+#: models.py:889
 msgid "Can run data checks"
 msgstr ""
 
-#: models.py:881
+#: models.py:890
 msgid "Can solve data check problems"
 msgstr ""
 
@@ -1002,6 +1010,11 @@ msgstr ""
 msgid "Create %(name)s"
 msgstr "Détails de contact"
 
+#: templates/core/dashboard_widget/list.html:25
+#: templates/core/edit_dashboard.html:8 templates/core/edit_dashboard.html:15
+msgid "Edit default dashboard"
+msgstr ""
+
 #: templates/core/data_check/list.html:15
 msgid "Check data again"
 msgstr ""
@@ -1061,19 +1074,41 @@ msgid ""
 "          "
 msgstr ""
 
-#: templates/core/edit_dashboard.html:4 templates/core/edit_dashboard.html:5
+#: templates/core/edit_dashboard.html:6 templates/core/edit_dashboard.html:13
 #: templates/core/index.html:14
 msgid "Edit dashboard"
 msgstr ""
 
-#: templates/core/edit_dashboard.html:26
+#: templates/core/edit_dashboard.html:24
+msgid ""
+"\n"
+"          On this page you can arrange your personal dashboard. You can drag any items from \"Available widgets\" to \"Your\n"
+"          Dashboard\" or change the order by moving the widgets. After you have finished, please don't forget to click on\n"
+"          \"Save\".\n"
+"        "
+msgstr ""
+
+#: templates/core/edit_dashboard.html:30
+msgid ""
+"\n"
+"          On this page you can arrange the default dashboard which is shown when a user doesn't arrange his own\n"
+"          dashboard. You can drag any items from \"Available widgets\" to \"Default Dashboard\" or change the order\n"
+"          by moving the widgets. After you have finished, please don't forget to click on \"Save\".\n"
+"        "
+msgstr ""
+
+#: templates/core/edit_dashboard.html:48
 msgid "Available widgets"
 msgstr ""
 
-#: templates/core/edit_dashboard.html:33
+#: templates/core/edit_dashboard.html:57
 msgid "Your dashboard"
 msgstr ""
 
+#: templates/core/edit_dashboard.html:59
+msgid "Default dashboard"
+msgstr ""
+
 #: templates/core/group/child_groups.html:18
 msgid ""
 "\n"
@@ -1210,31 +1245,31 @@ msgstr "Groupe"
 msgid "Home"
 msgstr ""
 
-#: templates/core/index.html:49
+#: templates/core/index.html:50
 msgid ""
 "\n"
-"              You haven't selected any dashboard widgets. Please click on \"Edit dashboard\" to add widgets to your\n"
-"              personal dashboard.\n"
-"            "
+"          You didn't customise your dashboard so that you see the system default. Please click on \"Edit dashboard\" to\n"
+"          customise your personal dashboard.\n"
+"        "
 msgstr ""
 
-#: templates/core/index.html:60
+#: templates/core/index.html:59
 msgid "Last activities"
 msgstr ""
 
-#: templates/core/index.html:78
+#: templates/core/index.html:77
 msgid "No activities available yet."
 msgstr ""
 
-#: templates/core/index.html:83
+#: templates/core/index.html:82
 msgid "Recent notifications"
 msgstr ""
 
-#: templates/core/index.html:99
+#: templates/core/index.html:98
 msgid "More information →"
 msgstr ""
 
-#: templates/core/index.html:106
+#: templates/core/index.html:105
 msgid "No notifications available yet."
 msgstr ""
 
@@ -1555,10 +1590,6 @@ msgstr ""
 msgid "Save preferences"
 msgstr ""
 
-#: templates/dynamic_preferences/sections.html:7
-msgid "All"
-msgstr ""
-
 #: templates/impersonate/list_users.html:8
 msgid "Impersonate user"
 msgstr ""
@@ -2019,87 +2050,91 @@ msgstr ""
 msgid "SMS"
 msgstr ""
 
-#: views.py:134
+#: views.py:141
 msgid "The school term has been created."
 msgstr ""
 
-#: views.py:146
+#: views.py:153
 msgid "The school term has been saved."
 msgstr ""
 
-#: views.py:291
+#: views.py:298
 msgid "The child groups were successfully saved."
 msgstr ""
 
-#: views.py:329
+#: views.py:336
 msgid "The person has been saved."
 msgstr ""
 
-#: views.py:368
+#: views.py:375
 msgid "The group has been saved."
 msgstr ""
 
-#: views.py:460
+#: views.py:467
 msgid "The announcement has been saved."
 msgstr ""
 
-#: views.py:476
+#: views.py:483
 msgid "The announcement has been deleted."
 msgstr ""
 
-#: views.py:548
+#: views.py:562
 msgid "The preferences have been saved successfully."
 msgstr ""
 
-#: views.py:572
+#: views.py:586
 msgid "The person has been deleted."
 msgstr ""
 
-#: views.py:586
+#: views.py:600
 msgid "The group has been deleted."
 msgstr ""
 
-#: views.py:618
+#: views.py:632
 msgid "The additional_field has been saved."
 msgstr ""
 
-#: views.py:652
+#: views.py:666
 msgid "The additional field has been deleted."
 msgstr ""
 
-#: views.py:677
+#: views.py:691
 msgid "The group type has been saved."
 msgstr ""
 
-#: views.py:707
+#: views.py:721
 msgid "The group type has been deleted."
 msgstr ""
 
-#: views.py:735
+#: views.py:749
 msgid "The data check has been started. Please note that it may take a while before you are able to fetch the data on this page."
 msgstr ""
 
-#: views.py:740
+#: views.py:754
 msgid "The data check has finished."
 msgstr ""
 
-#: views.py:755
+#: views.py:769
 #, python-brace-format
 msgid "The solve option '{solve_option_obj.verbose_name}' "
 msgstr ""
 
-#: views.py:797
+#: views.py:811
 msgid "The dashboard widget has been saved."
 msgstr ""
 
-#: views.py:827
+#: views.py:841
 msgid "The dashboard widget has been created."
 msgstr ""
 
-#: views.py:837
+#: views.py:851
 msgid "The dashboard widget has been deleted."
 msgstr ""
 
-#: views.py:888
+#: views.py:914
 msgid "Your dashboard configuration has been saved successfully."
 msgstr ""
+
+#: views.py:916
+msgid "The configuration of the default dashboard has been saved successfully."
+msgstr ""
diff --git a/aleksis/core/locale/fr/LC_MESSAGES/djangojs.po b/aleksis/core/locale/fr/LC_MESSAGES/djangojs.po
index 2fe8c926b2c2043a6ba551656f1be68a09a21feb..83a1c140c8889eef6a1633f00a741cd110c52e05 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: 2020-12-28 21:33+0100\n"
+"POT-Creation-Date: 2021-01-11 21:30+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,3 +29,7 @@ msgstr ""
 #: static/js/main.js:17
 msgid "OK"
 msgstr ""
+
+#: static/js/main.js:118
+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 5eb551539462b883ac631d0a7fbae0b0f0421734..5fb260aac6828ea32031b9b03bd64424984cd8ab 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: 2020-12-28 21:33+0100\n"
+"POT-Creation-Date: 2021-01-11 21:30+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"
@@ -233,7 +233,7 @@ msgstr ""
 msgid "People"
 msgstr "Personae"
 
-#: menus.py:185 models.py:803 templates/core/group_type/list.html:8
+#: menus.py:185 models.py:812 templates/core/group_type/list.html:8
 #: templates/core/group_type/list.html:9
 #, fuzzy
 #| msgid "Groups"
@@ -308,7 +308,7 @@ msgstr ""
 msgid "URL / Link"
 msgstr ""
 
-#: models.py:66 models.py:776
+#: models.py:66 models.py:785
 msgid "Name"
 msgstr "Nomen"
 
@@ -328,7 +328,7 @@ msgstr ""
 msgid "There is already a school term for this time or a part of this time."
 msgstr ""
 
-#: models.py:115 models.py:742 templates/core/person/accounts.html:41
+#: models.py:115 models.py:744 templates/core/person/accounts.html:41
 msgid "Person"
 msgstr "Persona"
 
@@ -440,7 +440,7 @@ msgstr "Parentes"
 msgid "Primary group"
 msgstr ""
 
-#: models.py:176 models.py:461 models.py:485 models.py:570 models.py:796
+#: models.py:176 models.py:461 models.py:485 models.py:570 models.py:805
 #: templates/core/person/full.html:120
 msgid "Description"
 msgstr "Descriptio"
@@ -530,7 +530,7 @@ msgstr "Mittens"
 msgid "Recipient"
 msgstr ""
 
-#: models.py:486 models.py:777
+#: models.py:486 models.py:786
 msgid "Link"
 msgstr ""
 
@@ -627,142 +627,152 @@ msgstr ""
 #: models.py:734
 #, fuzzy
 #| msgid "Dashboard"
-msgid "Dashboard Widget"
+msgid "Can edit default dashboard"
 msgstr "Forum"
 
 #: models.py:735
 #, fuzzy
 #| msgid "Dashboard"
+msgid "Dashboard Widget"
+msgstr "Forum"
+
+#: models.py:736
+#, fuzzy
+#| msgid "Dashboard"
 msgid "Dashboard Widgets"
 msgstr "Forum"
 
-#: models.py:740
+#: models.py:741
 #, fuzzy
 #| msgid "Dashboard"
 msgid "Dashboard widget"
 msgstr "Forum"
 
-#: models.py:743
+#: models.py:746
 msgid "Order"
 msgstr ""
 
-#: models.py:746
+#: models.py:747
+msgid "Part of the default dashboard"
+msgstr ""
+
+#: models.py:755
 #, fuzzy
 #| msgid "Dashboard"
 msgid "Dashboard widget order"
 msgstr "Forum"
 
-#: models.py:747
+#: models.py:756
 #, fuzzy
 #| msgid "Dashboard"
 msgid "Dashboard widget orders"
 msgstr "Forum"
 
-#: models.py:753
+#: models.py:762
 msgid "Menu ID"
 msgstr ""
 
-#: models.py:766
+#: models.py:775
 msgid "Custom menu"
 msgstr ""
 
-#: models.py:767
+#: models.py:776
 msgid "Custom menus"
 msgstr ""
 
-#: models.py:774
+#: models.py:783
 msgid "Menu"
 msgstr ""
 
-#: models.py:778
+#: models.py:787
 msgid "Icon"
 msgstr "Nota"
 
-#: models.py:784
+#: models.py:793
 msgid "Custom menu item"
 msgstr ""
 
-#: models.py:785
+#: models.py:794
 msgid "Custom menu items"
 msgstr ""
 
-#: models.py:795
+#: models.py:804
 msgid "Title of type"
 msgstr ""
 
-#: models.py:802 templates/core/group/full.html:47
+#: models.py:811 templates/core/group/full.html:47
 #, fuzzy
 #| msgid "Group"
 msgid "Group type"
 msgstr "Grex"
 
-#: models.py:812
+#: models.py:821
 #, fuzzy
 #| msgid "System status"
 msgid "Can view system status"
 msgstr "Status systemae"
 
-#: models.py:813
+#: models.py:822
 #, fuzzy
 #| msgid "Persons and accounts"
 msgid "Can link persons to accounts"
 msgstr "Personae et computi"
 
-#: models.py:814
+#: models.py:823
 #, fuzzy
 #| msgid "Data management"
 msgid "Can manage data"
 msgstr "Adminstratio datarum"
 
-#: models.py:815
+#: models.py:824
 #, fuzzy
 #| msgid "Stop impersonation"
 msgid "Can impersonate"
 msgstr "Simulandum aliquem finire"
 
-#: models.py:816
+#: models.py:825
 msgid "Can use search"
 msgstr ""
 
-#: models.py:817
+#: models.py:826
 msgid "Can change site preferences"
 msgstr ""
 
-#: models.py:818
+#: models.py:827
 msgid "Can change person preferences"
 msgstr ""
 
-#: models.py:819
+#: models.py:828
 msgid "Can change group preferences"
 msgstr ""
 
-#: models.py:855
+#: models.py:864
 msgid "Related data check task"
 msgstr ""
 
-#: models.py:863
+#: models.py:872
 msgid "Issue solved"
 msgstr ""
 
-#: models.py:864
+#: models.py:873
 #, fuzzy
 #| msgid "Notifications"
 msgid "Notification sent"
 msgstr "Nuntii"
 
-#: models.py:877
+#: models.py:886
 msgid "Data check result"
 msgstr ""
 
-#: models.py:878
+#: models.py:887
 msgid "Data check results"
 msgstr ""
 
-#: models.py:880
+#: models.py:889
 msgid "Can run data checks"
 msgstr ""
 
-#: models.py:881
+#: models.py:890
 msgid "Can solve data check problems"
 msgstr ""
 
@@ -1062,6 +1072,13 @@ msgstr ""
 msgid "Create %(name)s"
 msgstr "Simulandum aliquem finire"
 
+#: templates/core/dashboard_widget/list.html:25
+#: templates/core/edit_dashboard.html:8 templates/core/edit_dashboard.html:15
+#, fuzzy
+#| msgid "Dashboard"
+msgid "Edit default dashboard"
+msgstr "Forum"
+
 #: templates/core/data_check/list.html:15
 msgid "Check data again"
 msgstr ""
@@ -1121,23 +1138,47 @@ msgid ""
 "          "
 msgstr ""
 
-#: templates/core/edit_dashboard.html:4 templates/core/edit_dashboard.html:5
+#: templates/core/edit_dashboard.html:6 templates/core/edit_dashboard.html:13
 #: templates/core/index.html:14
 #, fuzzy
 #| msgid "Dashboard"
 msgid "Edit dashboard"
 msgstr "Forum"
 
-#: templates/core/edit_dashboard.html:26
+#: templates/core/edit_dashboard.html:24
+msgid ""
+"\n"
+"          On this page you can arrange your personal dashboard. You can drag any items from \"Available widgets\" to \"Your\n"
+"          Dashboard\" or change the order by moving the widgets. After you have finished, please don't forget to click on\n"
+"          \"Save\".\n"
+"        "
+msgstr ""
+
+#: templates/core/edit_dashboard.html:30
+msgid ""
+"\n"
+"          On this page you can arrange the default dashboard which is shown when a user doesn't arrange his own\n"
+"          dashboard. You can drag any items from \"Available widgets\" to \"Default Dashboard\" or change the order\n"
+"          by moving the widgets. After you have finished, please don't forget to click on \"Save\".\n"
+"        "
+msgstr ""
+
+#: templates/core/edit_dashboard.html:48
 msgid "Available widgets"
 msgstr ""
 
-#: templates/core/edit_dashboard.html:33
+#: templates/core/edit_dashboard.html:57
 #, fuzzy
 #| msgid "Dashboard"
 msgid "Your dashboard"
 msgstr "Forum"
 
+#: templates/core/edit_dashboard.html:59
+#, fuzzy
+#| msgid "Dashboard"
+msgid "Default dashboard"
+msgstr "Forum"
+
 #: templates/core/group/child_groups.html:18
 msgid ""
 "\n"
@@ -1276,35 +1317,35 @@ msgstr "Grex"
 msgid "Home"
 msgstr ""
 
-#: templates/core/index.html:49
+#: templates/core/index.html:50
 msgid ""
 "\n"
-"              You haven't selected any dashboard widgets. Please click on \"Edit dashboard\" to add widgets to your\n"
-"              personal dashboard.\n"
-"            "
+"          You didn't customise your dashboard so that you see the system default. Please click on \"Edit dashboard\" to\n"
+"          customise your personal dashboard.\n"
+"        "
 msgstr ""
 
-#: templates/core/index.html:60
+#: templates/core/index.html:59
 msgid "Last activities"
 msgstr ""
 
-#: templates/core/index.html:78
+#: templates/core/index.html:77
 msgid "No activities available yet."
 msgstr ""
 
-#: templates/core/index.html:83
+#: templates/core/index.html:82
 #, fuzzy
 #| msgid "Notifications"
 msgid "Recent notifications"
 msgstr "Nuntii"
 
-#: templates/core/index.html:99
+#: templates/core/index.html:98
 #, fuzzy
 #| msgid "Edit school information"
 msgid "More information →"
 msgstr "Muta informationes scolae"
 
-#: templates/core/index.html:106
+#: templates/core/index.html:105
 msgid "No notifications available yet."
 msgstr ""
 
@@ -1639,10 +1680,6 @@ msgstr ""
 msgid "Save preferences"
 msgstr ""
 
-#: templates/dynamic_preferences/sections.html:7
-msgid "All"
-msgstr ""
-
 #: templates/impersonate/list_users.html:8
 #, fuzzy
 #| msgid "Impersonation"
@@ -2112,91 +2149,95 @@ msgstr ""
 msgid "SMS"
 msgstr ""
 
-#: views.py:134
+#: views.py:141
 msgid "The school term has been created."
 msgstr ""
 
-#: views.py:146
+#: views.py:153
 msgid "The school term has been saved."
 msgstr ""
 
-#: views.py:291
+#: views.py:298
 msgid "The child groups were successfully saved."
 msgstr ""
 
-#: views.py:329
+#: views.py:336
 msgid "The person has been saved."
 msgstr ""
 
-#: views.py:368
+#: views.py:375
 msgid "The group has been saved."
 msgstr ""
 
-#: views.py:460
+#: views.py:467
 msgid "The announcement has been saved."
 msgstr ""
 
-#: views.py:476
+#: views.py:483
 msgid "The announcement has been deleted."
 msgstr ""
 
-#: views.py:548
+#: views.py:562
 msgid "The preferences have been saved successfully."
 msgstr ""
 
-#: views.py:572
+#: views.py:586
 msgid "The person has been deleted."
 msgstr ""
 
-#: views.py:586
+#: views.py:600
 msgid "The group has been deleted."
 msgstr ""
 
-#: views.py:618
+#: views.py:632
 msgid "The additional_field has been saved."
 msgstr ""
 
-#: views.py:652
+#: views.py:666
 msgid "The additional field has been deleted."
 msgstr ""
 
-#: views.py:677
+#: views.py:691
 msgid "The group type has been saved."
 msgstr ""
 
-#: views.py:707
+#: views.py:721
 msgid "The group type has been deleted."
 msgstr ""
 
-#: views.py:735
+#: views.py:749
 msgid "The data check has been started. Please note that it may take a while before you are able to fetch the data on this page."
 msgstr ""
 
-#: views.py:740
+#: views.py:754
 msgid "The data check has finished."
 msgstr ""
 
-#: views.py:755
+#: views.py:769
 #, python-brace-format
 msgid "The solve option '{solve_option_obj.verbose_name}' "
 msgstr ""
 
-#: views.py:797
+#: views.py:811
 msgid "The dashboard widget has been saved."
 msgstr ""
 
-#: views.py:827
+#: views.py:841
 msgid "The dashboard widget has been created."
 msgstr ""
 
-#: views.py:837
+#: views.py:851
 msgid "The dashboard widget has been deleted."
 msgstr ""
 
-#: views.py:888
+#: views.py:914
 msgid "Your dashboard configuration has been saved successfully."
 msgstr ""
 
+#: views.py:916
+msgid "The configuration of the default dashboard has been saved successfully."
+msgstr ""
+
 #~ msgid "School logo"
 #~ msgstr "Imago scolae"
 
diff --git a/aleksis/core/locale/la/LC_MESSAGES/djangojs.po b/aleksis/core/locale/la/LC_MESSAGES/djangojs.po
index 5bb148cb4b38e3e00e9803ce59278400cb7ccc3f..ea24fc3ff92afc211898fb8b426dccb97fce56ed 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: 2020-12-28 21:33+0100\n"
+"POT-Creation-Date: 2021-01-11 21:30+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"
@@ -28,3 +28,7 @@ msgstr ""
 #: static/js/main.js:17
 msgid "OK"
 msgstr ""
+
+#: static/js/main.js:118
+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 980bf6e6fcf0fd6b0584e07e7b2a7177a52d14b0..6b4be05da6b0a53f60a6ffa060739c419ea4af3a 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: 2020-12-28 21:33+0100\n"
+"POT-Creation-Date: 2021-01-11 21:30+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"
@@ -214,7 +214,7 @@ msgstr ""
 msgid "People"
 msgstr ""
 
-#: menus.py:185 models.py:803 templates/core/group_type/list.html:8
+#: menus.py:185 models.py:812 templates/core/group_type/list.html:8
 #: templates/core/group_type/list.html:9
 msgid "Group types"
 msgstr ""
@@ -281,7 +281,7 @@ msgstr ""
 msgid "URL / Link"
 msgstr ""
 
-#: models.py:66 models.py:776
+#: models.py:66 models.py:785
 msgid "Name"
 msgstr ""
 
@@ -301,7 +301,7 @@ msgstr ""
 msgid "There is already a school term for this time or a part of this time."
 msgstr ""
 
-#: models.py:115 models.py:742 templates/core/person/accounts.html:41
+#: models.py:115 models.py:744 templates/core/person/accounts.html:41
 msgid "Person"
 msgstr ""
 
@@ -401,7 +401,7 @@ msgstr ""
 msgid "Primary group"
 msgstr ""
 
-#: models.py:176 models.py:461 models.py:485 models.py:570 models.py:796
+#: models.py:176 models.py:461 models.py:485 models.py:570 models.py:805
 #: templates/core/person/full.html:120
 msgid "Description"
 msgstr ""
@@ -483,7 +483,7 @@ msgstr ""
 msgid "Recipient"
 msgstr ""
 
-#: models.py:486 models.py:777
+#: models.py:486 models.py:786
 msgid "Link"
 msgstr ""
 
@@ -568,122 +568,130 @@ msgid "> 1200 px>, 12 columns"
 msgstr ""
 
 #: models.py:734
-msgid "Dashboard Widget"
+msgid "Can edit default dashboard"
 msgstr ""
 
 #: models.py:735
+msgid "Dashboard Widget"
+msgstr ""
+
+#: models.py:736
 msgid "Dashboard Widgets"
 msgstr ""
 
-#: models.py:740
+#: models.py:741
 msgid "Dashboard widget"
 msgstr ""
 
-#: models.py:743
+#: models.py:746
 msgid "Order"
 msgstr ""
 
-#: models.py:746
+#: models.py:747
+msgid "Part of the default dashboard"
+msgstr ""
+
+#: models.py:755
 msgid "Dashboard widget order"
 msgstr ""
 
-#: models.py:747
+#: models.py:756
 msgid "Dashboard widget orders"
 msgstr ""
 
-#: models.py:753
+#: models.py:762
 msgid "Menu ID"
 msgstr ""
 
-#: models.py:766
+#: models.py:775
 msgid "Custom menu"
 msgstr ""
 
-#: models.py:767
+#: models.py:776
 msgid "Custom menus"
 msgstr ""
 
-#: models.py:774
+#: models.py:783
 msgid "Menu"
 msgstr ""
 
-#: models.py:778
+#: models.py:787
 msgid "Icon"
 msgstr ""
 
-#: models.py:784
+#: models.py:793
 msgid "Custom menu item"
 msgstr ""
 
-#: models.py:785
+#: models.py:794
 msgid "Custom menu items"
 msgstr ""
 
-#: models.py:795
+#: models.py:804
 msgid "Title of type"
 msgstr ""
 
-#: models.py:802 templates/core/group/full.html:47
+#: models.py:811 templates/core/group/full.html:47
 msgid "Group type"
 msgstr ""
 
-#: models.py:812
+#: models.py:821
 msgid "Can view system status"
 msgstr ""
 
-#: models.py:813
+#: models.py:822
 msgid "Can link persons to accounts"
 msgstr ""
 
-#: models.py:814
+#: models.py:823
 msgid "Can manage data"
 msgstr ""
 
-#: models.py:815
+#: models.py:824
 msgid "Can impersonate"
 msgstr ""
 
-#: models.py:816
+#: models.py:825
 msgid "Can use search"
 msgstr ""
 
-#: models.py:817
+#: models.py:826
 msgid "Can change site preferences"
 msgstr ""
 
-#: models.py:818
+#: models.py:827
 msgid "Can change person preferences"
 msgstr ""
 
-#: models.py:819
+#: models.py:828
 msgid "Can change group preferences"
 msgstr ""
 
-#: models.py:855
+#: models.py:864
 msgid "Related data check task"
 msgstr ""
 
-#: models.py:863
+#: models.py:872
 msgid "Issue solved"
 msgstr ""
 
-#: models.py:864
+#: models.py:873
 msgid "Notification sent"
 msgstr ""
 
-#: models.py:877
+#: models.py:886
 msgid "Data check result"
 msgstr ""
 
-#: models.py:878
+#: models.py:887
 msgid "Data check results"
 msgstr ""
 
-#: models.py:880
+#: models.py:889
 msgid "Can run data checks"
 msgstr ""
 
-#: models.py:881
+#: models.py:890
 msgid "Can solve data check problems"
 msgstr ""
 
@@ -953,6 +961,11 @@ msgstr ""
 msgid "Create %(name)s"
 msgstr ""
 
+#: templates/core/dashboard_widget/list.html:25
+#: templates/core/edit_dashboard.html:8 templates/core/edit_dashboard.html:15
+msgid "Edit default dashboard"
+msgstr ""
+
 #: templates/core/data_check/list.html:15
 msgid "Check data again"
 msgstr ""
@@ -1010,19 +1023,41 @@ msgid ""
 "          "
 msgstr ""
 
-#: templates/core/edit_dashboard.html:4 templates/core/edit_dashboard.html:5
+#: templates/core/edit_dashboard.html:6 templates/core/edit_dashboard.html:13
 #: templates/core/index.html:14
 msgid "Edit dashboard"
 msgstr ""
 
-#: templates/core/edit_dashboard.html:26
+#: templates/core/edit_dashboard.html:24
+msgid ""
+"\n"
+"          On this page you can arrange your personal dashboard. You can drag any items from \"Available widgets\" to \"Your\n"
+"          Dashboard\" or change the order by moving the widgets. After you have finished, please don't forget to click on\n"
+"          \"Save\".\n"
+"        "
+msgstr ""
+
+#: templates/core/edit_dashboard.html:30
+msgid ""
+"\n"
+"          On this page you can arrange the default dashboard which is shown when a user doesn't arrange his own\n"
+"          dashboard. You can drag any items from \"Available widgets\" to \"Default Dashboard\" or change the order\n"
+"          by moving the widgets. After you have finished, please don't forget to click on \"Save\".\n"
+"        "
+msgstr ""
+
+#: templates/core/edit_dashboard.html:48
 msgid "Available widgets"
 msgstr ""
 
-#: templates/core/edit_dashboard.html:33
+#: templates/core/edit_dashboard.html:57
 msgid "Your dashboard"
 msgstr ""
 
+#: templates/core/edit_dashboard.html:59
+msgid "Default dashboard"
+msgstr ""
+
 #: templates/core/group/child_groups.html:18
 msgid ""
 "\n"
@@ -1155,31 +1190,31 @@ msgstr ""
 msgid "Home"
 msgstr ""
 
-#: templates/core/index.html:49
+#: templates/core/index.html:50
 msgid ""
 "\n"
-"              You haven't selected any dashboard widgets. Please click on \"Edit dashboard\" to add widgets to your\n"
-"              personal dashboard.\n"
-"            "
+"          You didn't customise your dashboard so that you see the system default. Please click on \"Edit dashboard\" to\n"
+"          customise your personal dashboard.\n"
+"        "
 msgstr ""
 
-#: templates/core/index.html:60
+#: templates/core/index.html:59
 msgid "Last activities"
 msgstr ""
 
-#: templates/core/index.html:78
+#: templates/core/index.html:77
 msgid "No activities available yet."
 msgstr ""
 
-#: templates/core/index.html:83
+#: templates/core/index.html:82
 msgid "Recent notifications"
 msgstr ""
 
-#: templates/core/index.html:99
+#: templates/core/index.html:98
 msgid "More information →"
 msgstr ""
 
-#: templates/core/index.html:106
+#: templates/core/index.html:105
 msgid "No notifications available yet."
 msgstr ""
 
@@ -1494,10 +1529,6 @@ msgstr ""
 msgid "Save preferences"
 msgstr ""
 
-#: templates/dynamic_preferences/sections.html:7
-msgid "All"
-msgstr ""
-
 #: templates/impersonate/list_users.html:8
 msgid "Impersonate user"
 msgstr ""
@@ -1956,87 +1987,91 @@ msgstr ""
 msgid "SMS"
 msgstr ""
 
-#: views.py:134
+#: views.py:141
 msgid "The school term has been created."
 msgstr ""
 
-#: views.py:146
+#: views.py:153
 msgid "The school term has been saved."
 msgstr ""
 
-#: views.py:291
+#: views.py:298
 msgid "The child groups were successfully saved."
 msgstr ""
 
-#: views.py:329
+#: views.py:336
 msgid "The person has been saved."
 msgstr ""
 
-#: views.py:368
+#: views.py:375
 msgid "The group has been saved."
 msgstr ""
 
-#: views.py:460
+#: views.py:467
 msgid "The announcement has been saved."
 msgstr ""
 
-#: views.py:476
+#: views.py:483
 msgid "The announcement has been deleted."
 msgstr ""
 
-#: views.py:548
+#: views.py:562
 msgid "The preferences have been saved successfully."
 msgstr ""
 
-#: views.py:572
+#: views.py:586
 msgid "The person has been deleted."
 msgstr ""
 
-#: views.py:586
+#: views.py:600
 msgid "The group has been deleted."
 msgstr ""
 
-#: views.py:618
+#: views.py:632
 msgid "The additional_field has been saved."
 msgstr ""
 
-#: views.py:652
+#: views.py:666
 msgid "The additional field has been deleted."
 msgstr ""
 
-#: views.py:677
+#: views.py:691
 msgid "The group type has been saved."
 msgstr ""
 
-#: views.py:707
+#: views.py:721
 msgid "The group type has been deleted."
 msgstr ""
 
-#: views.py:735
+#: views.py:749
 msgid "The data check has been started. Please note that it may take a while before you are able to fetch the data on this page."
 msgstr ""
 
-#: views.py:740
+#: views.py:754
 msgid "The data check has finished."
 msgstr ""
 
-#: views.py:755
+#: views.py:769
 #, python-brace-format
 msgid "The solve option '{solve_option_obj.verbose_name}' "
 msgstr ""
 
-#: views.py:797
+#: views.py:811
 msgid "The dashboard widget has been saved."
 msgstr ""
 
-#: views.py:827
+#: views.py:841
 msgid "The dashboard widget has been created."
 msgstr ""
 
-#: views.py:837
+#: views.py:851
 msgid "The dashboard widget has been deleted."
 msgstr ""
 
-#: views.py:888
+#: views.py:914
 msgid "Your dashboard configuration has been saved successfully."
 msgstr ""
+
+#: views.py:916
+msgid "The configuration of the default dashboard has been saved successfully."
+msgstr ""
diff --git a/aleksis/core/locale/nb_NO/LC_MESSAGES/djangojs.po b/aleksis/core/locale/nb_NO/LC_MESSAGES/djangojs.po
index 5bb148cb4b38e3e00e9803ce59278400cb7ccc3f..ea24fc3ff92afc211898fb8b426dccb97fce56ed 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: 2020-12-28 21:33+0100\n"
+"POT-Creation-Date: 2021-01-11 21:30+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"
@@ -28,3 +28,7 @@ msgstr ""
 #: static/js/main.js:17
 msgid "OK"
 msgstr ""
+
+#: static/js/main.js:118
+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 f882c57b2efe81069d437848d28246eee6398d6f..7ecf671cf7dd018f3d159265a13605f8f050e518 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: 2020-12-28 21:33+0100\n"
+"POT-Creation-Date: 2021-01-11 21:30+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"
@@ -214,7 +214,7 @@ msgstr ""
 msgid "People"
 msgstr ""
 
-#: menus.py:185 models.py:803 templates/core/group_type/list.html:8
+#: menus.py:185 models.py:812 templates/core/group_type/list.html:8
 #: templates/core/group_type/list.html:9
 msgid "Group types"
 msgstr ""
@@ -281,7 +281,7 @@ msgstr ""
 msgid "URL / Link"
 msgstr ""
 
-#: models.py:66 models.py:776
+#: models.py:66 models.py:785
 msgid "Name"
 msgstr ""
 
@@ -301,7 +301,7 @@ msgstr ""
 msgid "There is already a school term for this time or a part of this time."
 msgstr ""
 
-#: models.py:115 models.py:742 templates/core/person/accounts.html:41
+#: models.py:115 models.py:744 templates/core/person/accounts.html:41
 msgid "Person"
 msgstr ""
 
@@ -401,7 +401,7 @@ msgstr ""
 msgid "Primary group"
 msgstr ""
 
-#: models.py:176 models.py:461 models.py:485 models.py:570 models.py:796
+#: models.py:176 models.py:461 models.py:485 models.py:570 models.py:805
 #: templates/core/person/full.html:120
 msgid "Description"
 msgstr ""
@@ -483,7 +483,7 @@ msgstr ""
 msgid "Recipient"
 msgstr ""
 
-#: models.py:486 models.py:777
+#: models.py:486 models.py:786
 msgid "Link"
 msgstr ""
 
@@ -568,122 +568,130 @@ msgid "> 1200 px>, 12 columns"
 msgstr ""
 
 #: models.py:734
-msgid "Dashboard Widget"
+msgid "Can edit default dashboard"
 msgstr ""
 
 #: models.py:735
+msgid "Dashboard Widget"
+msgstr ""
+
+#: models.py:736
 msgid "Dashboard Widgets"
 msgstr ""
 
-#: models.py:740
+#: models.py:741
 msgid "Dashboard widget"
 msgstr ""
 
-#: models.py:743
+#: models.py:746
 msgid "Order"
 msgstr ""
 
-#: models.py:746
+#: models.py:747
+msgid "Part of the default dashboard"
+msgstr ""
+
+#: models.py:755
 msgid "Dashboard widget order"
 msgstr ""
 
-#: models.py:747
+#: models.py:756
 msgid "Dashboard widget orders"
 msgstr ""
 
-#: models.py:753
+#: models.py:762
 msgid "Menu ID"
 msgstr ""
 
-#: models.py:766
+#: models.py:775
 msgid "Custom menu"
 msgstr ""
 
-#: models.py:767
+#: models.py:776
 msgid "Custom menus"
 msgstr ""
 
-#: models.py:774
+#: models.py:783
 msgid "Menu"
 msgstr ""
 
-#: models.py:778
+#: models.py:787
 msgid "Icon"
 msgstr ""
 
-#: models.py:784
+#: models.py:793
 msgid "Custom menu item"
 msgstr ""
 
-#: models.py:785
+#: models.py:794
 msgid "Custom menu items"
 msgstr ""
 
-#: models.py:795
+#: models.py:804
 msgid "Title of type"
 msgstr ""
 
-#: models.py:802 templates/core/group/full.html:47
+#: models.py:811 templates/core/group/full.html:47
 msgid "Group type"
 msgstr ""
 
-#: models.py:812
+#: models.py:821
 msgid "Can view system status"
 msgstr ""
 
-#: models.py:813
+#: models.py:822
 msgid "Can link persons to accounts"
 msgstr ""
 
-#: models.py:814
+#: models.py:823
 msgid "Can manage data"
 msgstr ""
 
-#: models.py:815
+#: models.py:824
 msgid "Can impersonate"
 msgstr ""
 
-#: models.py:816
+#: models.py:825
 msgid "Can use search"
 msgstr ""
 
-#: models.py:817
+#: models.py:826
 msgid "Can change site preferences"
 msgstr ""
 
-#: models.py:818
+#: models.py:827
 msgid "Can change person preferences"
 msgstr ""
 
-#: models.py:819
+#: models.py:828
 msgid "Can change group preferences"
 msgstr ""
 
-#: models.py:855
+#: models.py:864
 msgid "Related data check task"
 msgstr ""
 
-#: models.py:863
+#: models.py:872
 msgid "Issue solved"
 msgstr ""
 
-#: models.py:864
+#: models.py:873
 msgid "Notification sent"
 msgstr ""
 
-#: models.py:877
+#: models.py:886
 msgid "Data check result"
 msgstr ""
 
-#: models.py:878
+#: models.py:887
 msgid "Data check results"
 msgstr ""
 
-#: models.py:880
+#: models.py:889
 msgid "Can run data checks"
 msgstr ""
 
-#: models.py:881
+#: models.py:890
 msgid "Can solve data check problems"
 msgstr ""
 
@@ -953,6 +961,11 @@ msgstr ""
 msgid "Create %(name)s"
 msgstr ""
 
+#: templates/core/dashboard_widget/list.html:25
+#: templates/core/edit_dashboard.html:8 templates/core/edit_dashboard.html:15
+msgid "Edit default dashboard"
+msgstr ""
+
 #: templates/core/data_check/list.html:15
 msgid "Check data again"
 msgstr ""
@@ -1010,19 +1023,41 @@ msgid ""
 "          "
 msgstr ""
 
-#: templates/core/edit_dashboard.html:4 templates/core/edit_dashboard.html:5
+#: templates/core/edit_dashboard.html:6 templates/core/edit_dashboard.html:13
 #: templates/core/index.html:14
 msgid "Edit dashboard"
 msgstr ""
 
-#: templates/core/edit_dashboard.html:26
+#: templates/core/edit_dashboard.html:24
+msgid ""
+"\n"
+"          On this page you can arrange your personal dashboard. You can drag any items from \"Available widgets\" to \"Your\n"
+"          Dashboard\" or change the order by moving the widgets. After you have finished, please don't forget to click on\n"
+"          \"Save\".\n"
+"        "
+msgstr ""
+
+#: templates/core/edit_dashboard.html:30
+msgid ""
+"\n"
+"          On this page you can arrange the default dashboard which is shown when a user doesn't arrange his own\n"
+"          dashboard. You can drag any items from \"Available widgets\" to \"Default Dashboard\" or change the order\n"
+"          by moving the widgets. After you have finished, please don't forget to click on \"Save\".\n"
+"        "
+msgstr ""
+
+#: templates/core/edit_dashboard.html:48
 msgid "Available widgets"
 msgstr ""
 
-#: templates/core/edit_dashboard.html:33
+#: templates/core/edit_dashboard.html:57
 msgid "Your dashboard"
 msgstr ""
 
+#: templates/core/edit_dashboard.html:59
+msgid "Default dashboard"
+msgstr ""
+
 #: templates/core/group/child_groups.html:18
 msgid ""
 "\n"
@@ -1155,31 +1190,31 @@ msgstr ""
 msgid "Home"
 msgstr ""
 
-#: templates/core/index.html:49
+#: templates/core/index.html:50
 msgid ""
 "\n"
-"              You haven't selected any dashboard widgets. Please click on \"Edit dashboard\" to add widgets to your\n"
-"              personal dashboard.\n"
-"            "
+"          You didn't customise your dashboard so that you see the system default. Please click on \"Edit dashboard\" to\n"
+"          customise your personal dashboard.\n"
+"        "
 msgstr ""
 
-#: templates/core/index.html:60
+#: templates/core/index.html:59
 msgid "Last activities"
 msgstr ""
 
-#: templates/core/index.html:78
+#: templates/core/index.html:77
 msgid "No activities available yet."
 msgstr ""
 
-#: templates/core/index.html:83
+#: templates/core/index.html:82
 msgid "Recent notifications"
 msgstr ""
 
-#: templates/core/index.html:99
+#: templates/core/index.html:98
 msgid "More information →"
 msgstr ""
 
-#: templates/core/index.html:106
+#: templates/core/index.html:105
 msgid "No notifications available yet."
 msgstr ""
 
@@ -1494,10 +1529,6 @@ msgstr ""
 msgid "Save preferences"
 msgstr ""
 
-#: templates/dynamic_preferences/sections.html:7
-msgid "All"
-msgstr ""
-
 #: templates/impersonate/list_users.html:8
 msgid "Impersonate user"
 msgstr ""
@@ -1956,87 +1987,91 @@ msgstr ""
 msgid "SMS"
 msgstr ""
 
-#: views.py:134
+#: views.py:141
 msgid "The school term has been created."
 msgstr ""
 
-#: views.py:146
+#: views.py:153
 msgid "The school term has been saved."
 msgstr ""
 
-#: views.py:291
+#: views.py:298
 msgid "The child groups were successfully saved."
 msgstr ""
 
-#: views.py:329
+#: views.py:336
 msgid "The person has been saved."
 msgstr ""
 
-#: views.py:368
+#: views.py:375
 msgid "The group has been saved."
 msgstr ""
 
-#: views.py:460
+#: views.py:467
 msgid "The announcement has been saved."
 msgstr ""
 
-#: views.py:476
+#: views.py:483
 msgid "The announcement has been deleted."
 msgstr ""
 
-#: views.py:548
+#: views.py:562
 msgid "The preferences have been saved successfully."
 msgstr ""
 
-#: views.py:572
+#: views.py:586
 msgid "The person has been deleted."
 msgstr ""
 
-#: views.py:586
+#: views.py:600
 msgid "The group has been deleted."
 msgstr ""
 
-#: views.py:618
+#: views.py:632
 msgid "The additional_field has been saved."
 msgstr ""
 
-#: views.py:652
+#: views.py:666
 msgid "The additional field has been deleted."
 msgstr ""
 
-#: views.py:677
+#: views.py:691
 msgid "The group type has been saved."
 msgstr ""
 
-#: views.py:707
+#: views.py:721
 msgid "The group type has been deleted."
 msgstr ""
 
-#: views.py:735
+#: views.py:749
 msgid "The data check has been started. Please note that it may take a while before you are able to fetch the data on this page."
 msgstr ""
 
-#: views.py:740
+#: views.py:754
 msgid "The data check has finished."
 msgstr ""
 
-#: views.py:755
+#: views.py:769
 #, python-brace-format
 msgid "The solve option '{solve_option_obj.verbose_name}' "
 msgstr ""
 
-#: views.py:797
+#: views.py:811
 msgid "The dashboard widget has been saved."
 msgstr ""
 
-#: views.py:827
+#: views.py:841
 msgid "The dashboard widget has been created."
 msgstr ""
 
-#: views.py:837
+#: views.py:851
 msgid "The dashboard widget has been deleted."
 msgstr ""
 
-#: views.py:888
+#: views.py:914
 msgid "Your dashboard configuration has been saved successfully."
 msgstr ""
+
+#: views.py:916
+msgid "The configuration of the default dashboard has been saved successfully."
+msgstr ""
diff --git a/aleksis/core/locale/tr_TR/LC_MESSAGES/djangojs.po b/aleksis/core/locale/tr_TR/LC_MESSAGES/djangojs.po
index 5bb148cb4b38e3e00e9803ce59278400cb7ccc3f..ea24fc3ff92afc211898fb8b426dccb97fce56ed 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: 2020-12-28 21:33+0100\n"
+"POT-Creation-Date: 2021-01-11 21:30+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"
@@ -28,3 +28,7 @@ msgstr ""
 #: static/js/main.js:17
 msgid "OK"
 msgstr ""
+
+#: static/js/main.js:118
+msgid "This page may contain outdated information since there is no internet connection."
+msgstr ""
diff --git a/aleksis/core/migrations/0009_default_dashboard.py b/aleksis/core/migrations/0009_default_dashboard.py
new file mode 100644
index 0000000000000000000000000000000000000000..401396bb064139d5c9bdda37f1c9a5dece65dc22
--- /dev/null
+++ b/aleksis/core/migrations/0009_default_dashboard.py
@@ -0,0 +1,30 @@
+# Generated by Django 3.1.4 on 2021-01-04 13:39
+
+from django.db import migrations, models
+import django.db.models.deletion
+import django.utils.timezone
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0008_data_check_result'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='dashboardwidgetorder',
+            name='default',
+            field=models.BooleanField(default=False, verbose_name='Part of the default dashboard'),
+        ),
+        migrations.AlterField(
+            model_name='dashboardwidgetorder',
+            name='person',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='core.person', verbose_name='Person'),
+        ),
+        migrations.AlterModelOptions(
+            name='dashboardwidget',
+            options={'permissions': (('edit_default_dashboard', 'Can edit default dashboard'),),
+                     'verbose_name': 'Dashboard Widget', 'verbose_name_plural': 'Dashboard Widgets'},
+        ),
+    ]
diff --git a/aleksis/core/models.py b/aleksis/core/models.py
index 5f5facd33939560c81fd8197271d1fd8ec9fe4ec..8927844a47da2f30e030a9b0815e82539940d8ba 100644
--- a/aleksis/core/models.py
+++ b/aleksis/core/models.py
@@ -239,7 +239,10 @@ class Person(ExtensibleModel):
     @property
     def dashboard_widgets(self):
         return [
-            w.widget for w in DashboardWidgetOrder.objects.filter(person=self).order_by("order")
+            w.widget
+            for w in DashboardWidgetOrder.objects.filter(person=self, widget__active=True).order_by(
+                "order"
+            )
         ]
 
     def save(self, *args, **kwargs):
@@ -494,7 +497,7 @@ class Notification(ExtensibleModel, TimeStampedModel):
     def save(self, **kwargs):
         super().save(**kwargs)
         if not self.sent:
-            transaction.on_commit(lambda: send_notification(self.pk, resend=True))
+            send_notification(self.pk, resend=True)
         self.sent = True
         super().save(**kwargs)
 
@@ -731,6 +734,7 @@ class DashboardWidget(PolymorphicModel, PureDjangoModel):
         return self.title
 
     class Meta:
+        permissions = (("edit_default_dashboard", _("Can edit default dashboard")),)
         verbose_name = _("Dashboard Widget")
         verbose_name_plural = _("Dashboard Widgets")
 
@@ -739,8 +743,21 @@ class DashboardWidgetOrder(ExtensibleModel):
     widget = models.ForeignKey(
         DashboardWidget, on_delete=models.CASCADE, verbose_name=_("Dashboard widget")
     )
-    person = models.ForeignKey(Person, on_delete=models.CASCADE, verbose_name=_("Person"))
+    person = models.ForeignKey(
+        Person, on_delete=models.CASCADE, verbose_name=_("Person"), null=True, blank=True
+    )
     order = models.PositiveIntegerField(verbose_name=_("Order"))
+    default = models.BooleanField(default=False, verbose_name=_("Part of the default dashboard"))
+
+    @classproperty
+    def default_dashboard_widgets(cls):
+        """Get default order for dashboard widgets."""
+        return [
+            w.widget
+            for w in cls.objects.filter(person=None, default=True, widget__active=True).order_by(
+                "order"
+            )
+        ]
 
     class Meta:
         verbose_name = _("Dashboard widget order")
diff --git a/aleksis/core/rules.py b/aleksis/core/rules.py
index 8ad48fbf18db6cac37270680792aa784a49eb77c..ac713bbe54a937d529da6c4e0266209dae593fd5 100644
--- a/aleksis/core/rules.py
+++ b/aleksis/core/rules.py
@@ -306,3 +306,6 @@ rules.add_perm("core.edit_dashboardwidget", edit_dashboard_widget_predicate)
 
 delete_dashboard_widget_predicate = has_person & has_global_perm("core.delete_dashboardwidget")
 rules.add_perm("core.delete_dashboardwidget", delete_dashboard_widget_predicate)
+
+edit_default_dashboard_predicate = has_person & has_global_perm("core.edit_default_dashboard")
+rules.add_perm("core.edit_default_dashboard", edit_default_dashboard_predicate)
diff --git a/aleksis/core/settings.py b/aleksis/core/settings.py
index e8870dc656e05c566ab1e83131d7fc4c70e0b9d5..f6f8f538345f76bbfd3a340ae748c9bbc77e3f09 100644
--- a/aleksis/core/settings.py
+++ b/aleksis/core/settings.py
@@ -377,7 +377,7 @@ ANY_JS = {
         "css_url": JS_URL + "/select2-materialize/select2-materialize.css",
         "js_url": JS_URL + "/select2-materialize/index.js",
     },
-    "sortablejs": {"js_url": JS_URL + "/sortablejs/dist/sortable.umd.js"},
+    "sortablejs": {"js_url": JS_URL + "/sortablejs/Sortable.min.js"},
     "jquery-sortablejs": {"js_url": JS_URL + "/jquery-sortablejs/jquery-sortable.js"},
 }
 
diff --git a/aleksis/core/static/js/main.js b/aleksis/core/static/js/main.js
index 615f8b287df18ed38c57d1f44358073bb74bcf61..45fee5c5bde0eb54655b2fe556c05f9aee573c4f 100644
--- a/aleksis/core/static/js/main.js
+++ b/aleksis/core/static/js/main.js
@@ -58,6 +58,9 @@ $(document).ready(function () {
     // Initialize select [MAT]
     $('select').formSelect();
 
+    // Initialize dropdown [MAT]
+    $('.dropdown-trigger').dropdown();
+
     // If JS is activated, the language form will be auto-submitted
     $('.language-field select').change(function () {
 
@@ -110,3 +113,11 @@ $(document).ready(function () {
         el.addClass("closed").removeClass("opened");
     });
 });
+
+// Show notice if serviceworker broadcasts that the current page comes from its cache
+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>')
+    }
+});
diff --git a/aleksis/core/static/js/serviceworker.js b/aleksis/core/static/js/serviceworker.js
index 818e27cb7d28e820431a4ac28ba6fdf0c422deb7..16382ec00c5dadb22c63060a227451377202d363 100644
--- a/aleksis/core/static/js/serviceworker.js
+++ b/aleksis/core/static/js/serviceworker.js
@@ -5,6 +5,10 @@ const CACHE = 'aleksis-cache';
 
 const offlineFallbackPage = 'offline/';
 
+const channel = new BroadcastChannel('cache-or-not');
+
+var comesFromCache = false;
+
 self.addEventListener("install", function (event) {
     console.log("[AlekSIS PWA] Install Event processing.");
 
@@ -29,6 +33,7 @@ self.addEventListener("activate", function (event) {
 self.addEventListener("fetch", function (event) {
     if (event.request.method !== "GET") return;
     networkFirstFetch(event);
+    if (comesFromCache) channel.postMessage(true);
 });
 
 function networkFirstFetch(event) {
@@ -38,6 +43,7 @@ function networkFirstFetch(event) {
                 // If request was successful, add or update it in the cache
                 console.log("[AlekSIS PWA] Network request successful.");
                 event.waitUntil(updateCache(event.request, response.clone()));
+                comesFromCache = false;
                 return response;
             })
             .catch(function (error) {
@@ -56,10 +62,11 @@ function fromCache(event) {
             .then(function (matching) {
                 if (!matching || matching.status === 404) {
                     console.log("[AlekSIS PWA] Cache request failed. Serving offline fallback page.");
+                    comesFromCache = false;
                     // Use the precached offline page as fallback
-                    return caches.match(offlineFallbackPage)
+                    return caches.match(offlineFallbackPage);
                 }
-
+                comesFromCache = true;
                 return matching;
             });
     });
diff --git a/aleksis/core/templates/components/materialize-chips.html b/aleksis/core/templates/components/materialize-chips.html
new file mode 100644
index 0000000000000000000000000000000000000000..e8a37bbb456dd47eb1231ecbc7ec541a7944be74
--- /dev/null
+++ b/aleksis/core/templates/components/materialize-chips.html
@@ -0,0 +1,9 @@
+<div class="chip {{ classes }}">
+  {% if img %}
+    <img class="{{ img_classes }}" src="{{ img }}" alt="{{ alt }}">
+  {% endif %}
+  {{ content }}
+  {% if close %}
+    <i class="close material-icons"></i>
+  {% endif %}
+</div>
diff --git a/aleksis/core/templates/core/dashboard_widget/list.html b/aleksis/core/templates/core/dashboard_widget/list.html
index ab384e8620f7c6499adb3e663fdb98e4eb598b2c..6715e3df96e2faed4a1afc78333529039000de32 100644
--- a/aleksis/core/templates/core/dashboard_widget/list.html
+++ b/aleksis/core/templates/core/dashboard_widget/list.html
@@ -2,7 +2,7 @@
 
 {% extends "core/base.html" %}
 
-{% load i18n data_helpers %}
+{% load i18n data_helpers rules %}
 {% load render_table from django_tables2 %}
 
 {% block browser_title %}{% blocktrans %}Dashboard widgets{% endblocktrans %}{% endblock %}
@@ -10,13 +10,28 @@
 
 {% block content %}
 
-  {% for ct, model in widget_types %}
-    <a class="btn green waves-effect waves-light" href="{% url 'create_dashboard_widget' ct.app_label ct.model  %}">
-      <i class="material-icons left">add</i>
-      {% verbose_name_object model as widget_name %}
-      {% blocktrans with name=widget_name %}Create {{ name }}{% endblocktrans %}
+  <a class="btn green waves-effect waves-light dropdown-trigger" href="#" data-target="widget-dropdown">
+    <i class="material-icons left">add</i>
+    {% trans "Create dashboard widget" %}
+  </a>
+  <ul id="widget-dropdown" class="dropdown-content">
+    {% for ct, model in widget_types %}
+      <li>
+        <a href="{% url 'create_dashboard_widget' ct.app_label ct.model %}">
+          {% verbose_name_object model as widget_name %}
+          {% blocktrans with name=widget_name %}Create {{ name }}{% endblocktrans %}
+        </a>
+      </li>
+    {% endfor %}
+  </ul>
+
+  {% has_perm "core.edit_default_dashboard" 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>
+      {% trans "Edit default dashboard" %}
     </a>
-  {% endfor %}
+  {% endif %}
 
   {% render_table table %}
 {% endblock %}
diff --git a/aleksis/core/templates/core/edit_dashboard.html b/aleksis/core/templates/core/edit_dashboard.html
index a15f24bff8ebcca6a7f9b4ea081d9d8c008f3b0a..09d9afd97ee8b983ed4577267641eae77fd2f14e 100644
--- a/aleksis/core/templates/core/edit_dashboard.html
+++ b/aleksis/core/templates/core/edit_dashboard.html
@@ -1,16 +1,38 @@
 {% extends 'core/base.html' %}
 {% load i18n static dashboard any_js %}
 
-{% block browser_title %}{% blocktrans %}Edit dashboard{% endblocktrans %}{% endblock %}
-{% block page_title %}{% blocktrans %}Edit dashboard{% endblocktrans %}{% endblock %}
+{% block browser_title %}
+  {% if not default_dashboard %}
+    {% trans "Edit dashboard" %}
+  {% else %}
+    {% trans "Edit default dashboard" %}
+  {% endif %}
+{% endblock %}
+{% block page_title %}
+  {% if not default_dashboard %}
+    {% trans "Edit dashboard" %}
+  {% else %}
+    {% trans "Edit default dashboard" %}
+  {% endif %}
+{% endblock %}
 
 {% block content %}
   <div class="alert primary">
     <p>
       <i class="material-icons left">info</i>
-      On this page you can arrange your personal dashboard. You can drag any items from "Available widgets" to "Your
-      Dashboard" or change the order by moving the widgets. After you have finished, please don't forget to click on
-      "Save".
+      {% if not default_dashboard %}
+        {% blocktrans %}
+          On this page you can arrange your personal dashboard. You can drag any items from "Available widgets" to "Your
+          Dashboard" or change the order by moving the widgets. After you have finished, please don't forget to click on
+          "Save".
+        {% endblocktrans %}
+      {% else %}
+        {% blocktrans %}
+          On this page you can arrange the default dashboard which is shown when a user doesn't arrange his own
+          dashboard. You can drag any items from "Available widgets" to "Default Dashboard" or change the order
+          by moving the widgets. After you have finished, please don't forget to click on "Save".
+        {% endblocktrans %}
+      {% endif %}
     </p>
   </div>
 
@@ -30,7 +52,14 @@
     {% endfor %}
   </div>
 
-  <h5>{% trans "Your dashboard" %}</h5>
+  <h5>
+    {% if not default_dashboard %}
+      {% trans "Your dashboard" %}
+    {% else %}
+      {% trans "Default dashboard" %}
+    {% endif %}
+  </h5>
+
   <div class="row card-panel grey lighten-3" id="widgets">
     {% for widget in widgets %}
       {% include "core/partials/edit_dashboard_widget.html" %}
diff --git a/aleksis/core/templates/core/index.html b/aleksis/core/templates/core/index.html
index 93b80ddefffaa8cf72db56a7ef503a694f0514f5..419bb59f11b5084eee7ac379605c3cefe00d530b 100644
--- a/aleksis/core/templates/core/index.html
+++ b/aleksis/core/templates/core/index.html
@@ -42,19 +42,18 @@
         <div class="col s{{ widget.size_s }} m{{ widget.size_m }} l{{ widget.size_l }} xl{{ widget.size_xl }}">
           {% include_widget widget %}
         </div>
-        {% empty %}
-        <div class="col s12 grey-text center">
-          <i class="material-icons medium ">widgets</i>
-          <p class="flow-text">
-            {% blocktrans %}
-              You haven't selected any dashboard widgets. Please click on "Edit dashboard" to add widgets to your
-              personal dashboard.
-            {% endblocktrans %}
-          </p>
-        </div>
       {% endfor %}
     </div>
 
+    {% if default_dashboard and widgets %}
+      <div class="grey-text right">
+        {% blocktrans %}
+          You didn't customise your dashboard so that you see the system default. Please click on "Edit dashboard" to
+          customise your personal dashboard.
+        {% endblocktrans %}
+      </div>
+    {% endif %}
+
     <div class="row">
       <div class="col s12 m6">
         <h5>{% blocktrans %}Last activities{% endblocktrans %}</h5>
diff --git a/aleksis/core/templates/dynamic_preferences/sections.html b/aleksis/core/templates/dynamic_preferences/sections.html
index 39b97496fd4542cfbad440f3571eb2b6f8df86d2..344962dfdfd6ed21ff25aef9056a823904260234 100644
--- a/aleksis/core/templates/dynamic_preferences/sections.html
+++ b/aleksis/core/templates/dynamic_preferences/sections.html
@@ -1,11 +1,6 @@
 {% load i18n %}
 <ul class="tabs">
   <li class="tab ">
-    <a href="{% url registry_url %}"
-       class="{% if not active_section %}active{% endif %}"
-       target="_self">
-      {% trans "All" %}
-    </a>
     {% for section in registry.section_objects.values %}
       <li class="tab">
         <a class="{% if active_section == section.name %}active{% endif %}"
diff --git a/aleksis/core/urls.py b/aleksis/core/urls.py
index 930b3fbc8e8bec19bd32cadb6a6fd6bd7833f0f7..30c38b11c9c1e884f62f88a0f62b369f55fe2969 100644
--- a/aleksis/core/urls.py
+++ b/aleksis/core/urls.py
@@ -177,6 +177,12 @@ urlpatterns = [
         views.DashboardWidgetCreateView.as_view(),
         name="create_dashboard_widget",
     ),
+    path(
+        "dashboard_widgets/default/",
+        views.EditDashboardView.as_view(),
+        {"default": True},
+        name="edit_default_dashboard",
+    ),
 ]
 
 # Serve static files from STATIC_ROOT to make it work with runserver
diff --git a/aleksis/core/util/core_helpers.py b/aleksis/core/util/core_helpers.py
index fcbf1b65f7b20aea5c2bf1d7b5098c922c12dd1f..18fcfc241ea76d96312e1339fbde6fd526218307 100644
--- a/aleksis/core/util/core_helpers.py
+++ b/aleksis/core/util/core_helpers.py
@@ -14,6 +14,7 @@ else:
     import importlib_metadata as metadata
 
 from django.conf import settings
+from django.db import transaction
 from django.db.models import Model, QuerySet
 from django.http import HttpRequest
 from django.shortcuts import get_object_or_404
@@ -209,7 +210,7 @@ def celery_optional(orig: Callable) -> Callable:
 
     def wrapped(*args, **kwargs):
         if is_celery_enabled():
-            return task.delay(*args, **kwargs), False
+            return transaction.on_commit(lambda: task.delay(*args, **kwargs)), False
         else:
             return orig(*args, **kwargs), True
 
diff --git a/aleksis/core/util/forms.py b/aleksis/core/util/forms.py
new file mode 100644
index 0000000000000000000000000000000000000000..9d7279892f89f47bccebef95786df79ce1f737f1
--- /dev/null
+++ b/aleksis/core/util/forms.py
@@ -0,0 +1,34 @@
+from collections import OrderedDict
+
+from material import Layout, Row
+
+
+class PreferenceLayout(Layout):
+    """django-material Layout object for managing preferences."""
+
+    def __init__(self, form_base_class, section=None):
+        """
+        Create Layout object for the given form_base_class.
+
+        :param form_base_class: A Form class used as the base. Must have a ``registry` attribute
+        :param section: A section where the layout builder will load preferences
+        """
+        registry = form_base_class.registry
+        if section:
+            # Try to use section param
+            preferences_obj = registry.preferences(section=section)
+        else:
+            # display all preferences in the form
+            preferences_obj = registry.preferences()
+
+        rows = OrderedDict()
+
+        for preference in preferences_obj:
+            row_name = preference.get("row", preference.identifier())
+            rows.setdefault(row_name, [])
+            rows[row_name].append(preference.identifier())
+
+        rows_material = []
+        for fields in rows.values():
+            rows_material.append(Row(*fields))
+        super().__init__(*rows_material)
diff --git a/aleksis/core/views.py b/aleksis/core/views.py
index 016b49052f9272bd3743c78eb86689a0395194bd..41b36acfbcff7573366a2328d2d0f9f2a92fe1df 100644
--- a/aleksis/core/views.py
+++ b/aleksis/core/views.py
@@ -75,6 +75,7 @@ from .tables import (
 from .util import messages
 from .util.apps import AppConfig
 from .util.core_helpers import objectgetter_optional
+from .util.forms import PreferenceLayout
 
 
 @permission_required("core.view_dashboard")
@@ -94,6 +95,12 @@ def index(request: HttpRequest) -> HttpResponse:
     context["announcements"] = announcements
 
     widgets = request.user.person.dashboard_widgets
+
+    if len(widgets) == 0:
+        # Use default dashboard if there are no widgets
+        widgets = DashboardWidgetOrder.default_dashboard_widgets
+        context["default_dashboard"] = True
+
     media = DashboardWidget.get_media(widgets)
 
     context["widgets"] = widgets
@@ -113,7 +120,7 @@ def about(request: HttpRequest) -> HttpResponse:
     return render(request, "core/pages/about.html", context)
 
 
-class SchoolTermListView(SingleTableView, PermissionRequiredMixin):
+class SchoolTermListView(PermissionRequiredMixin, SingleTableView):
     """Table of all school terms."""
 
     model = SchoolTerm
@@ -123,7 +130,7 @@ class SchoolTermListView(SingleTableView, PermissionRequiredMixin):
 
 
 @method_decorator(never_cache, name="dispatch")
-class SchoolTermCreateView(AdvancedCreateView, PermissionRequiredMixin):
+class SchoolTermCreateView(PermissionRequiredMixin, AdvancedCreateView):
     """Create view for school terms."""
 
     model = SchoolTerm
@@ -135,7 +142,7 @@ class SchoolTermCreateView(AdvancedCreateView, PermissionRequiredMixin):
 
 
 @method_decorator(never_cache, name="dispatch")
-class SchoolTermEditView(AdvancedEditView, PermissionRequiredMixin):
+class SchoolTermEditView(PermissionRequiredMixin, AdvancedEditView):
     """Edit view for school terms."""
 
     model = SchoolTerm
@@ -381,7 +388,7 @@ def data_management(request: HttpRequest) -> HttpResponse:
     return render(request, "core/management/data_management.html", context)
 
 
-class SystemStatus(MainView, PermissionRequiredMixin):
+class SystemStatus(PermissionRequiredMixin, MainView):
     """View giving information about the system status."""
 
     template_name = "core/pages/system_status.html"
@@ -538,9 +545,16 @@ def preferences(
         # Invalid registry name passed from URL
         return HttpResponseNotFound()
 
+    if not section and len(registry.sections()) > 0:
+        default_section = list(registry.sections())[0]
+        return redirect(f"preferences_{registry_name}", default_section)
+
     # Build final form from dynamic-preferences
     form_class = preference_form_builder(form_class, instance=instance, section=section)
 
+    # Get layout
+    form_class.layout = PreferenceLayout(form_class, section=section)
+
     if request.method == "POST":
         form = form_class(request.POST, request.FILES or None)
         if form.is_valid():
@@ -765,7 +779,7 @@ class SolveDataCheckView(PermissionRequiredMixin, RevisionMixin, DetailView):
             return HttpResponseNotFound()
 
 
-class DashboardWidgetListView(SingleTableView, PermissionRequiredMixin):
+class DashboardWidgetListView(PermissionRequiredMixin, SingleTableView):
     """Table of all dashboard widgets."""
 
     model = DashboardWidget
@@ -783,7 +797,7 @@ class DashboardWidgetListView(SingleTableView, PermissionRequiredMixin):
 
 
 @method_decorator(never_cache, name="dispatch")
-class DashboardWidgetEditView(AdvancedEditView, PermissionRequiredMixin):
+class DashboardWidgetEditView(PermissionRequiredMixin, AdvancedEditView):
     """Edit view for dashboard widgets."""
 
     def get_form_class(self) -> Type[BaseModelForm]:
@@ -798,7 +812,7 @@ class DashboardWidgetEditView(AdvancedEditView, PermissionRequiredMixin):
 
 
 @method_decorator(never_cache, name="dispatch")
-class DashboardWidgetCreateView(AdvancedCreateView, PermissionRequiredMixin):
+class DashboardWidgetCreateView(PermissionRequiredMixin, AdvancedCreateView):
     """Create view for dashboard widgets."""
 
     def get_model(self, request, *args, **kwargs):
@@ -840,11 +854,23 @@ class DashboardWidgetDeleteView(PermissionRequiredMixin, AdvancedDeleteView):
 class EditDashboardView(View):
     """View for editing dashboard widget order."""
 
-    def get_context_data(self, request):
+    def get_context_data(self, request, **kwargs):
         context = {}
+        self.default_dashboard = kwargs.get("default", False)
+
+        if self.default_dashboard and not request.user.has_perm("core.edit_default_dashboard"):
+            raise PermissionDenied()
 
-        widgets = request.user.person.dashboard_widgets
-        not_used_widgets = DashboardWidget.objects.exclude(pk__in=[w.pk for w in widgets])
+        context["default_dashboard"] = self.default_dashboard
+
+        widgets = (
+            request.user.person.dashboard_widgets
+            if not self.default_dashboard
+            else DashboardWidgetOrder.default_dashboard_widgets
+        )
+        not_used_widgets = DashboardWidget.objects.exclude(pk__in=[w.pk for w in widgets]).filter(
+            active=True
+        )
         context["widgets"] = widgets
         context["not_used_widgets"] = not_used_widgets
 
@@ -863,8 +889,8 @@ class EditDashboardView(View):
 
         return context
 
-    def post(self, request):
-        context = self.get_context_data(request)
+    def post(self, request, **kwargs):
+        context = self.get_context_data(request, **kwargs)
 
         if context["formset"].is_valid():
             added_objects = []
@@ -874,22 +900,26 @@ class EditDashboardView(View):
 
                 obj, created = DashboardWidgetOrder.objects.update_or_create(
                     widget=form.cleaned_data["pk"],
-                    person=request.user.person,
+                    person=request.user.person if not self.default_dashboard else None,
+                    default=self.default_dashboard,
                     defaults={"order": form.cleaned_data["order"]},
                 )
 
                 added_objects.append(obj.pk)
 
-            DashboardWidgetOrder.objects.filter(person=request.user.person).exclude(
-                pk__in=added_objects
-            ).delete()
+            DashboardWidgetOrder.objects.filter(
+                person=request.user.person if not self.default_dashboard else None,
+                default=self.default_dashboard,
+            ).exclude(pk__in=added_objects).delete()
 
-            messages.success(
-                request, _("Your dashboard configuration has been saved successfully.")
-            )
-            return redirect("index")
+            if not self.default_dashboard:
+                msg = _("Your dashboard configuration has been saved successfully.")
+            else:
+                msg = _("The configuration of the default dashboard has been saved successfully.")
+            messages.success(request, msg)
+            return redirect("index" if not self.default_dashboard else "dashboard_widgets")
 
-    def get(self, request):
-        context = self.get_context_data(request)
+    def get(self, request, **kwargs):
+        context = self.get_context_data(request, **kwargs)
 
         return render(request, "core/edit_dashboard.html", context=context)
diff --git a/poetry.lock b/poetry.lock
index 87c5870817ad750ff89f8dfdd3fdf1a759fb5759..050abe9881f5ea2dd89b14b83932f3954791bf80 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -46,7 +46,7 @@ reference = "gitlab"
 
 [[package]]
 name = "amqp"
-version = "5.0.2"
+version = "5.0.3"
 description = "Low-level AMQP client for Python (fork of amqplib)."
 category = "main"
 optional = true
@@ -122,6 +122,21 @@ PyYAML = ">=5.3.1"
 six = ">=1.10.0"
 stevedore = ">=1.20.0"
 
+[[package]]
+name = "beautifulsoup4"
+version = "4.9.3"
+description = "Screen-scraping library"
+category = "main"
+optional = false
+python-versions = "*"
+
+[package.dependencies]
+soupsieve = {version = ">1.2", markers = "python_version >= \"3.0\""}
+
+[package.extras]
+html5lib = ["html5lib"]
+lxml = ["lxml"]
+
 [[package]]
 name = "billiard"
 version = "3.6.3.0"
@@ -152,7 +167,7 @@ d = ["aiohttp (>=3.3.2)", "aiohttp-cors"]
 
 [[package]]
 name = "bleach"
-version = "3.2.1"
+version = "3.2.2"
 description = "An easy safelist-based HTML-sanitizing tool."
 category = "main"
 optional = false
@@ -171,6 +186,17 @@ category = "main"
 optional = false
 python-versions = "*"
 
+[[package]]
+name = "bs4"
+version = "0.0.1"
+description = "Dummy package for Beautiful Soup"
+category = "main"
+optional = false
+python-versions = "*"
+
+[package.dependencies]
+beautifulsoup4 = "*"
+
 [[package]]
 name = "calendarweek"
 version = "0.4.7"
@@ -373,7 +399,7 @@ python-versions = "*"
 
 [[package]]
 name = "django"
-version = "3.1.4"
+version = "3.1.5"
 description = "A high-level Python Web framework that encourages rapid development and clean, pragmatic design."
 category = "main"
 optional = false
@@ -469,7 +495,7 @@ dev = ["flake8", "tox", "twine", "therapist", "black"]
 
 [[package]]
 name = "django-celery-beat"
-version = "2.1.0"
+version = "2.2.0"
 description = "Database-backed Periodic Tasks."
 category = "main"
 optional = true
@@ -477,8 +503,8 @@ python-versions = "*"
 
 [package.dependencies]
 celery = ">=4.4,<6.0"
-Django = ">=2.2"
-django-timezone-field = ">=4.0,<5.0"
+Django = ">=2.2,<4.0"
+django-timezone-field = ">=4.1.0,<5.0"
 python-crontab = ">=2.3.4"
 
 [[package]]
@@ -496,7 +522,7 @@ django-appconf = "*"
 
 [[package]]
 name = "django-celery-results"
-version = "2.0.0"
+version = "2.0.1"
 description = "Celery result backends for Django."
 category = "main"
 optional = true
@@ -635,7 +661,7 @@ Django = ">=2.2"
 
 [[package]]
 name = "django-health-check"
-version = "3.16.1"
+version = "3.16.2"
 description = "Run checks on services like databases, queue servers, celery processes, etc."
 category = "main"
 optional = false
@@ -646,7 +672,7 @@ django = ">=1.11"
 
 [[package]]
 name = "django-impersonate"
-version = "1.7.1"
+version = "1.7.2"
 description = "Django app to allow superusers to impersonate other users."
 category = "main"
 optional = false
@@ -681,7 +707,7 @@ Django = ">=1.5"
 
 [[package]]
 name = "django-jsonstore"
-version = "0.4.1"
+version = "0.5.0"
 description = "Expose JSONField data as a virtual django model fields."
 category = "main"
 optional = false
@@ -701,7 +727,7 @@ python-versions = "*"
 
 [[package]]
 name = "django-material"
-version = "1.7.3"
+version = "1.7.4"
 description = "Material design for django forms and admin"
 category = "main"
 optional = false
@@ -711,8 +737,8 @@ python-versions = "*"
 six = "*"
 
 [[package]]
-name = "django-menu-generator"
-version = "1.1.0"
+name = "django-menu-generator-ng"
+version = "1.2.0"
 description = "A straightforward menu generator for Django"
 category = "main"
 optional = false
@@ -852,7 +878,7 @@ management-command = ["django-compressor (>=2.4)"]
 
 [[package]]
 name = "django-select2"
-version = "7.5.0"
+version = "7.6.1"
 description = "Select2 option fields for Django"
 category = "main"
 optional = false
@@ -888,7 +914,7 @@ typing-extensions = "*"
 
 [[package]]
 name = "django-tables2"
-version = "2.3.3"
+version = "2.3.4"
 description = "Table/data-grid framework for Django"
 category = "main"
 optional = false
@@ -1020,7 +1046,7 @@ yaml = ["ruamel.yaml"]
 
 [[package]]
 name = "faker"
-version = "5.0.2"
+version = "5.6.5"
 description = "Faker is a Python package that generates fake data for you."
 category = "main"
 optional = false
@@ -1180,7 +1206,7 @@ smmap = ">=3.0.1,<4"
 
 [[package]]
 name = "gitpython"
-version = "3.1.11"
+version = "3.1.12"
 description = "Python Git Library"
 category = "dev"
 optional = false
@@ -1215,7 +1241,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
 
 [[package]]
 name = "importlib-metadata"
-version = "3.3.0"
+version = "3.4.0"
 description = "Read metadata from Python packages"
 category = "main"
 optional = false
@@ -1226,8 +1252,8 @@ typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""}
 zipp = ">=0.5"
 
 [package.extras]
-docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"]
-testing = ["pytest (>=3.5,!=3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-cov", "jaraco.test (>=3.2.0)", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"]
+docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"]
+testing = ["pytest (>=3.5,!=3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-cov", "pytest-enabler", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"]
 
 [[package]]
 name = "iniconfig"
@@ -1239,7 +1265,7 @@ python-versions = "*"
 
 [[package]]
 name = "isort"
-version = "5.6.4"
+version = "5.7.0"
 description = "A Python utility / library to sort Python imports."
 category = "dev"
 optional = false
@@ -1402,7 +1428,7 @@ scramp = "1.2.0"
 
 [[package]]
 name = "phonenumbers"
-version = "8.12.15"
+version = "8.12.16"
 description = "Python version of Google's common library for parsing, formatting, storing and validating international phone numbers."
 category = "main"
 optional = false
@@ -1410,7 +1436,7 @@ python-versions = "*"
 
 [[package]]
 name = "pillow"
-version = "8.0.1"
+version = "8.1.0"
 description = "Python Imaging Library (Fork)"
 category = "main"
 optional = false
@@ -1443,7 +1469,7 @@ twisted = ["twisted"]
 
 [[package]]
 name = "prompt-toolkit"
-version = "3.0.8"
+version = "3.0.11"
 description = "Library for building powerful interactive command lines in Python"
 category = "main"
 optional = true
@@ -1535,7 +1561,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
 
 [[package]]
 name = "pygments"
-version = "2.7.3"
+version = "2.7.4"
 description = "Pygments is a syntax highlighting package written in Python."
 category = "dev"
 optional = false
@@ -1543,17 +1569,16 @@ python-versions = ">=3.5"
 
 [[package]]
 name = "pyjwt"
-version = "2.0.0"
+version = "1.7.1"
 description = "JSON Web Token implementation in Python"
 category = "main"
 optional = false
-python-versions = ">=3.6"
+python-versions = "*"
 
 [package.extras]
-crypto = ["cryptography (>=3.3.1,<4.0.0)"]
-dev = ["sphinx", "sphinx-rtd-theme", "zope.interface", "cryptography (>=3.3.1,<4.0.0)", "pytest (>=6.0.0,<7.0.0)", "coverage[toml] (==5.0.4)", "mypy", "pre-commit"]
-docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"]
-tests = ["pytest (>=6.0.0,<7.0.0)", "coverage[toml] (==5.0.4)"]
+crypto = ["cryptography (>=1.4)"]
+flake8 = ["flake8", "flake8-import-order", "pep8-naming"]
+test = ["pytest (>=4.0.1,<5.0.0)", "pytest-cov (>=2.6.0,<3.0.0)", "pytest-runner (>=4.2,<5.0.0)"]
 
 [[package]]
 name = "pyparsing"
@@ -1587,14 +1612,14 @@ testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xm
 
 [[package]]
 name = "pytest-cov"
-version = "2.10.1"
+version = "2.11.1"
 description = "Pytest plugin for measuring coverage."
 category = "dev"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
 
 [package.dependencies]
-coverage = ">=4.4"
+coverage = ">=5.2.1"
 pytest = ">=4.6"
 
 [package.extras]
@@ -1699,11 +1724,11 @@ python-versions = "*"
 
 [[package]]
 name = "pyyaml"
-version = "5.3.1"
+version = "5.4.1"
 description = "YAML parser and emitter for Python"
 category = "dev"
 optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
 
 [[package]]
 name = "qrcode"
@@ -1804,7 +1829,7 @@ python-versions = "*"
 
 [[package]]
 name = "safety"
-version = "1.10.0"
+version = "1.10.3"
 description = "Checks installed dependencies for known vulnerabilities."
 category = "dev"
 optional = false
@@ -1859,6 +1884,14 @@ category = "dev"
 optional = false
 python-versions = "*"
 
+[[package]]
+name = "soupsieve"
+version = "2.1"
+description = "A modern CSS selector implementation for Beautiful Soup."
+category = "main"
+optional = false
+python-versions = ">=3.5"
+
 [[package]]
 name = "spdx-license-list"
 version = "0.5.2"
@@ -1869,7 +1902,7 @@ python-versions = "*"
 
 [[package]]
 name = "sphinx"
-version = "3.4.1"
+version = "3.4.3"
 description = "Python documentation generator"
 category = "dev"
 optional = false
@@ -2022,7 +2055,7 @@ python-versions = "*"
 
 [[package]]
 name = "testfixtures"
-version = "6.17.0"
+version = "6.17.1"
 description = "A collection of helpers and mock objects for unit tests and doc tests."
 category = "dev"
 optional = false
@@ -2077,7 +2110,7 @@ python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
 
 [[package]]
 name = "tqdm"
-version = "4.55.0"
+version = "4.56.0"
 description = "Fast, Extensible Progress Meter"
 category = "main"
 optional = false
@@ -2089,21 +2122,21 @@ telegram = ["requests"]
 
 [[package]]
 name = "twilio"
-version = "6.50.1"
+version = "6.51.0"
 description = "Twilio API client and TwiML generator"
 category = "main"
 optional = false
 python-versions = "*"
 
 [package.dependencies]
-PyJWT = ">=1.4.2"
+PyJWT = "1.7.1"
 pytz = "*"
 requests = {version = ">=2.0.0", markers = "python_version >= \"3.0\""}
 six = "*"
 
 [[package]]
 name = "typed-ast"
-version = "1.4.1"
+version = "1.4.2"
 description = "a fork of Python 2 and 3 ast modules with type comment support"
 category = "dev"
 optional = false
@@ -2184,7 +2217,7 @@ ldap = ["django-auth-ldap"]
 [metadata]
 lock-version = "1.1"
 python-versions = "^3.7"
-content-hash = "65a4b7b891965a330e7fec9ed64213579550aac1ac8295aa8c3022a4978d488c"
+content-hash = "b8b44ac64723c99f10cbeaa085976eb30a503e29379801c21495d362933e4aa0"
 
 [metadata.files]
 alabaster = [
@@ -2195,8 +2228,8 @@ aleksis-builddeps = [
     {file = "AlekSIS-Builddeps-1.tar.gz", hash = "sha256:97a19597f422593cbdc438aabf17f95748126c8951df6ac7db7991fc99c108c4"},
 ]
 amqp = [
-    {file = "amqp-5.0.2-py3-none-any.whl", hash = "sha256:5b9062d5c0812335c75434bf17ce33d7a20ecfedaa0733faec7379868eb4068a"},
-    {file = "amqp-5.0.2.tar.gz", hash = "sha256:fcd5b3baeeb7fc19b3486ff6d10543099d40ae1f5c9196eae695d1cde1b2f784"},
+    {file = "amqp-5.0.3-py3-none-any.whl", hash = "sha256:2c58528a05dcbf2ae080f3141b6a5bf467949fad9234edd8b9085b8db2e325fe"},
+    {file = "amqp-5.0.3.tar.gz", hash = "sha256:1733ebf713050504fd9d2ebc661f1fc95b3588f99ee87d2e39c84c27bfd815dc"},
 ]
 appdirs = [
     {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"},
@@ -2222,6 +2255,11 @@ bandit = [
     {file = "bandit-1.7.0-py3-none-any.whl", hash = "sha256:216be4d044209fa06cf2a3e51b319769a51be8318140659719aa7a115c35ed07"},
     {file = "bandit-1.7.0.tar.gz", hash = "sha256:8a4c7415254d75df8ff3c3b15cfe9042ecee628a1e40b44c15a98890fbfc2608"},
 ]
+beautifulsoup4 = [
+    {file = "beautifulsoup4-4.9.3-py2-none-any.whl", hash = "sha256:4c98143716ef1cb40bf7f39a8e3eec8f8b009509e74904ba3a7b315431577e35"},
+    {file = "beautifulsoup4-4.9.3-py3-none-any.whl", hash = "sha256:fff47e031e34ec82bf17e00da8f592fe7de69aeea38be00523c04623c04fb666"},
+    {file = "beautifulsoup4-4.9.3.tar.gz", hash = "sha256:84729e322ad1d5b4d25f805bfa05b902dd96450f43842c4e99067d5e1369eb25"},
+]
 billiard = [
     {file = "billiard-3.6.3.0-py3-none-any.whl", hash = "sha256:bff575450859a6e0fbc2f9877d9b715b0bbc07c3565bb7ed2280526a0cdf5ede"},
     {file = "billiard-3.6.3.0.tar.gz", hash = "sha256:d91725ce6425f33a97dfa72fb6bfef0e47d4652acd98a032bd1a7fbf06d5fa6a"},
@@ -2231,13 +2269,16 @@ black = [
     {file = "black-19.10b0.tar.gz", hash = "sha256:c2edb73a08e9e0e6f65a0e6af18b059b8b1cdd5bef997d7a0b181df93dc81539"},
 ]
 bleach = [
-    {file = "bleach-3.2.1-py2.py3-none-any.whl", hash = "sha256:9f8ccbeb6183c6e6cddea37592dfb0167485c1e3b13b3363bc325aa8bda3adbd"},
-    {file = "bleach-3.2.1.tar.gz", hash = "sha256:52b5919b81842b1854196eaae5ca29679a2f2e378905c346d3ca8227c2c66080"},
+    {file = "bleach-3.2.2-py2.py3-none-any.whl", hash = "sha256:a690ccc41a10d806a7c0a9130767750925e4863e332f7e4ea93da1bc12a24300"},
+    {file = "bleach-3.2.2.tar.gz", hash = "sha256:ce6270dd0ae56cd810495b8d994551ae16b41f2b4043cf50064f298985afdb3c"},
 ]
 "boolean.py" = [
     {file = "boolean.py-3.8-py2.py3-none-any.whl", hash = "sha256:d75da0fd0354425fa64f6bbc6cec6ae1485d0eec3447b73187ff8cbf9b572e26"},
     {file = "boolean.py-3.8.tar.gz", hash = "sha256:cc24e20f985d60cd4a3a5a1c0956dd12611159d32a75081dabd0c9ab981acaa4"},
 ]
+bs4 = [
+    {file = "bs4-0.0.1.tar.gz", hash = "sha256:36ecea1fd7cc5c0c6e4a1ff075df26d50da647b75376626cc186e2212886dd3a"},
+]
 calendarweek = [
     {file = "calendarweek-0.4.7-py3-none-any.whl", hash = "sha256:ee65caea113503dcdb33d96bca9f79f88b3ab4f66279d4cb568d89f1f662608a"},
     {file = "calendarweek-0.4.7.tar.gz", hash = "sha256:7655d6a4c3b4f6a4e01aa7d23b49cd121db0399050e9c08cd8d1210155be25dd"},
@@ -2344,8 +2385,8 @@ dj-database-url = [
     {file = "dj_database_url-0.5.0-py2.py3-none-any.whl", hash = "sha256:851785365761ebe4994a921b433062309eb882fedd318e1b0fcecc607ed02da9"},
 ]
 django = [
-    {file = "Django-3.1.4-py3-none-any.whl", hash = "sha256:5c866205f15e7a7123f1eec6ab939d22d5bde1416635cab259684af66d8e48a2"},
-    {file = "Django-3.1.4.tar.gz", hash = "sha256:edb10b5c45e7e9c0fb1dc00b76ec7449aca258a39ffd613dbd078c51d19c9f03"},
+    {file = "Django-3.1.5-py3-none-any.whl", hash = "sha256:efa2ab96b33b20c2182db93147a0c3cd7769d418926f9e9f140a60dca7c64ca9"},
+    {file = "Django-3.1.5.tar.gz", hash = "sha256:2d78425ba74c7a1a74b196058b261b9733a8570782f4e2828974777ccca7edf7"},
 ]
 django-any-js = [
     {file = "django-any-js-1.0.3.post0.tar.gz", hash = "sha256:1da88b44b861b0f54f6b8ea0eb4c7c4fa1a5772e9a4320532cd4e0871a4e23f7"},
@@ -2375,16 +2416,16 @@ django-cache-memoize = [
     {file = "django_cache_memoize-0.1.7-py2.py3-none-any.whl", hash = "sha256:bc7f53725558244af62197d0125732d7ec88ecc1281a3a2f37d77ae1a8c269d3"},
 ]
 django-celery-beat = [
-    {file = "django-celery-beat-2.1.0.tar.gz", hash = "sha256:4eb0e8412e2e05ba0029912a6f80d1054731001eecbcb4d59688c4e07cf4d9d3"},
-    {file = "django_celery_beat-2.1.0-py2.py3-none-any.whl", hash = "sha256:8a169e11d96faed8b72d505ddbc70e7fe0b16cdc854df43cb209c153ed08d651"},
+    {file = "django-celery-beat-2.2.0.tar.gz", hash = "sha256:b8a13afb15e7c53fc04f4f847ac71a6d32088959aba701eb7c4a59f0c28ba543"},
+    {file = "django_celery_beat-2.2.0-py2.py3-none-any.whl", hash = "sha256:c4c72a9579f20eff4c4ccf1b58ebdca5ef940f4210065057db1754ea5f8dffdc"},
 ]
 django-celery-email = [
     {file = "django-celery-email-3.0.0.tar.gz", hash = "sha256:5546cbba80952cc3b8a0ffa4206ce90a4a996a7ffd1c385a2bdb65903ca18ece"},
     {file = "django_celery_email-3.0.0-py2.py3-none-any.whl", hash = "sha256:0f72da39cb2ea83c69440566e87f27cd72f68f247f98ce99fb29889fcf329406"},
 ]
 django-celery-results = [
-    {file = "django_celery_results-2.0.0-py2.py3-none-any.whl", hash = "sha256:f82280a9a25c44048b9e64ae4d47ade7d522c8221304b0e25388080021b95468"},
-    {file = "django_celery_results-2.0.0.tar.gz", hash = "sha256:754e01f22f70fddee5f2ca95c18f183fccee42ad98f9803577bffa717d45ac5d"},
+    {file = "django_celery_results-2.0.1-py2.py3-none-any.whl", hash = "sha256:a2f7d172f7f57dd972538acc6e80a5bf50c673fb4d82fe027189c8659c60dfce"},
+    {file = "django_celery_results-2.0.1.tar.gz", hash = "sha256:d625e324138e5b2ef46ffa9e89fa353c16d619420066ac8b240ef9247b293a84"},
 ]
 django-ckeditor = [
     {file = "django-ckeditor-6.0.0.tar.gz", hash = "sha256:29fd1a333cb9741ac2c3fd4e427a5c00115ed33a2389716a09af7656022dcdde"},
@@ -2430,11 +2471,11 @@ django-haystack = [
     {file = "django_haystack-3.0b1-py3-none-any.whl", hash = "sha256:b83705e1cf8141cd1755fc6683ac65fea4e1281f4b4306bc9224af96495b0df3"},
 ]
 django-health-check = [
-    {file = "django-health-check-3.16.1.tar.gz", hash = "sha256:2cb3944e313e435bdf299288e109f398b6c08b610e09cc90d7f5f6a2bcf469fc"},
-    {file = "django_health_check-3.16.1-py2.py3-none-any.whl", hash = "sha256:8b0835f04ebaeb0d12498a5ef47dd22196237c3987ff28bcce9ed28b5a169d5e"},
+    {file = "django-health-check-3.16.2.tar.gz", hash = "sha256:d5edf773b59e4091ac6bd65280091dbb13d92e70eba5cf8573faa738a9cb481c"},
+    {file = "django_health_check-3.16.2-py2.py3-none-any.whl", hash = "sha256:aec4dd5cfb8333071f535c3611ef805ec2012af9568cf984be351ff1bd4020be"},
 ]
 django-impersonate = [
-    {file = "django-impersonate-1.7.1.tar.gz", hash = "sha256:732e1d6d0fc9b4cd33f0914ee9e627b50f9c63452acb6466d674df87364c5e28"},
+    {file = "django-impersonate-1.7.2.tar.gz", hash = "sha256:ef1f9fa3180f4d95db0abbca3403f389e901e0beb781afd0db0edface72d148d"},
 ]
 django-ipware = [
     {file = "django-ipware-3.0.2.tar.gz", hash = "sha256:c7df8e1410a8e5d6b1fbae58728402ea59950f043c3582e033e866f0f0cf5e94"},
@@ -2448,18 +2489,20 @@ django-js-reverse = [
     {file = "django_js_reverse-0.9.1-py2.py3-none-any.whl", hash = "sha256:8134c2ab6307c945edfa90671ca65e85d6c1754d48566bdd6464be259cc80c30"},
 ]
 django-jsonstore = [
-    {file = "django-jsonstore-0.4.1.tar.gz", hash = "sha256:d6e42152af3f924e4657c99e80144ba9a6410799256f6134b5a4e9fa4282ec10"},
+    {file = "django-jsonstore-0.5.0.tar.gz", hash = "sha256:896dc10b08f59807eda1c6cebf43cd26e50d0db29d13495c027dc31e464be3c3"},
+    {file = "django_jsonstore-0.5.0-py2-none-any.whl", hash = "sha256:9630c1fb43ae9f8e32733c5cf7d4c3775ba6f08532f517c64025053352d72844"},
 ]
 django-maintenance-mode = [
     {file = "django-maintenance-mode-0.15.1.tar.gz", hash = "sha256:d07102cab88dd707a82232f0c552c287e62aa53af582a0ca4f2aa31f14f5ed27"},
     {file = "django_maintenance_mode-0.15.1-py3-none-any.whl", hash = "sha256:8c45b400253076655562c99a2ffb88f8353fc1c84496c1b9de812cc8132aea6f"},
 ]
 django-material = [
-    {file = "django-material-1.7.3.tar.gz", hash = "sha256:00599cd87f19f3a66be065865b223801afa9da680744a5eac10c489a10d98eba"},
-    {file = "django_material-1.7.3-py2.py3-none-any.whl", hash = "sha256:6c010aa47618ceae2617f8a476b55aaed0884b1a4a6f5bdf969448a1ba72e352"},
+    {file = "django-material-1.7.4.tar.gz", hash = "sha256:93af86e740b6db15a3b9df913c343217b198d7342a083db694acb319b49cb2dd"},
+    {file = "django_material-1.7.4-py2.py3-none-any.whl", hash = "sha256:70dcaa34b35dbc31fbdb7454c7a376358586d0f166abe15870e07e468d729425"},
 ]
-django-menu-generator = [
-    {file = "django-menu-generator-1.1.0.tar.gz", hash = "sha256:e8f9b808080c4b281f9c5962f39078c76c2007a5ef8ab1f7a81c81dbbe6a9848"},
+django-menu-generator-ng = [
+    {file = "django-menu-generator-ng-1.2.0.tar.gz", hash = "sha256:ed3666ffe7d669045958ff45254a8d5afcedfc1824ed27df5c63823f624bf521"},
+    {file = "django_menu_generator_ng-1.2.0-py3-none-any.whl", hash = "sha256:aea14db10b81899c022074dfb0dce058effef1c899b0bd1d2b3491bea1e86ee2"},
 ]
 django-middleware-global-request = [
     {file = "django-middleware-global-request-0.1.2.tar.gz", hash = "sha256:f6490759bc9f7dbde4001709554e29ca715daf847f2222914b4e47117dca9313"},
@@ -2504,8 +2547,8 @@ django-sass-processor = [
     {file = "django-sass-processor-0.8.2.tar.gz", hash = "sha256:9b46a12ca8bdcb397d46fbcc49e6a926ff9f76a93c5efeb23b495419fd01fc7a"},
 ]
 django-select2 = [
-    {file = "django-select2-7.5.0.tar.gz", hash = "sha256:df71dedba9a362041b65e3cd692cb8b4f9e1e17a19681c7b4e61f331868bae0c"},
-    {file = "django_select2-7.5.0-py2.py3-none-any.whl", hash = "sha256:6662aa1c21d4839b8fff38e4c9d402ed3da81f7c5ef7f7e703c862255ba3b9ed"},
+    {file = "django-select2-7.6.1.tar.gz", hash = "sha256:25362c5bafe082a19add598fb0a69e3239b94759691a0ac8e01ab7fba8e650ad"},
+    {file = "django_select2-7.6.1-py2.py3-none-any.whl", hash = "sha256:dc6b6fa737b6ea0b673e27c218955dd51a3fb81b2b28af93ce87703b24f4faf8"},
 ]
 django-settings-context-processor = [
     {file = "django-settings-context-processor-0.2.tar.gz", hash = "sha256:d37c853d69a3069f5abbf94c7f4f6fc0fac38bbd0524190cd5a250ba800e496a"},
@@ -2515,8 +2558,8 @@ django-stubs = [
     {file = "django_stubs-1.7.0-py3-none-any.whl", hash = "sha256:30a7d99c694acf79c5d93d69a5a8e4b54d2a8c11dd672aa869006789e2189fa6"},
 ]
 django-tables2 = [
-    {file = "django-tables2-2.3.3.tar.gz", hash = "sha256:ad38ece83157b8b9c1fb72b0316fcffc4b32d7fec53eec3f2847b83c4c0a2cb2"},
-    {file = "django_tables2-2.3.3-py2.py3-none-any.whl", hash = "sha256:9c175834130ebb2b3a5644431391e09128405e4538637804d5e74a8b96fc9f68"},
+    {file = "django-tables2-2.3.4.tar.gz", hash = "sha256:50ccadbd13740a996d8a4d4f144ef80134745cd0b5ec278061537e341f5ef7a2"},
+    {file = "django_tables2-2.3.4-py2.py3-none-any.whl", hash = "sha256:af5f70a9845fd8690c6b44120b065e55b9771cae99c1dcd0eb4f1cfa3f0a71e4"},
 ]
 django-templated-email = [
     {file = "django-templated-email-2.3.0.tar.gz", hash = "sha256:536c4e5ae099eabfb9aab36087d4d7799948c654e73da55a744213d086d5bb33"},
@@ -2549,8 +2592,8 @@ dynaconf = [
     {file = "dynaconf-3.1.2.tar.gz", hash = "sha256:9b34ab2f811a81755f5eb4beac77a69e1e0887528c7e37fc4bc83fed52dcf502"},
 ]
 faker = [
-    {file = "Faker-5.0.2-py3-none-any.whl", hash = "sha256:5b17c95cfb013a22b062b8df18286f08ce4ea880f9948ec74295e5a42dbb2e44"},
-    {file = "Faker-5.0.2.tar.gz", hash = "sha256:00ce4342c221b1931b2f35d46f5027d35bc62a4ca3a34628b2c5b514b4ca958a"},
+    {file = "Faker-5.6.5-py3-none-any.whl", hash = "sha256:8fe22be90c0db35d830464918f84beb50f970f4caacae4d88e92692857b78aa7"},
+    {file = "Faker-5.6.5.tar.gz", hash = "sha256:0f8198d876bc65edd3699e2542c6ae13cc93fbc4a478c17db190d5d9b6ce790e"},
 ]
 flake8 = [
     {file = "flake8-3.8.4-py2.py3-none-any.whl", hash = "sha256:749dbbd6bfd0cf1318af27bf97a14e28e5ff548ef8e5b1566ccfb25a11e7c839"},
@@ -2598,8 +2641,8 @@ gitdb = [
     {file = "gitdb-4.0.5.tar.gz", hash = "sha256:c9e1f2d0db7ddb9a704c2a0217be31214e91a4fe1dea1efad19ae42ba0c285c9"},
 ]
 gitpython = [
-    {file = "GitPython-3.1.11-py3-none-any.whl", hash = "sha256:6eea89b655917b500437e9668e4a12eabdcf00229a0df1762aabd692ef9b746b"},
-    {file = "GitPython-3.1.11.tar.gz", hash = "sha256:befa4d101f91bad1b632df4308ec64555db684c360bd7d2130b4807d49ce86b8"},
+    {file = "GitPython-3.1.12-py3-none-any.whl", hash = "sha256:867ec3dfb126aac0f8296b19fb63b8c4a399f32b4b6fafe84c4b10af5fa9f7b5"},
+    {file = "GitPython-3.1.12.tar.gz", hash = "sha256:42dbefd8d9e2576c496ed0059f3103dcef7125b9ce16f9d5f9c834aed44a1dac"},
 ]
 html2text = [
     {file = "html2text-2020.1.16-py3-none-any.whl", hash = "sha256:c7c629882da0cf377d66f073329ccf34a12ed2adf0169b9285ae4e63ef54c82b"},
@@ -2614,16 +2657,16 @@ imagesize = [
     {file = "imagesize-1.2.0.tar.gz", hash = "sha256:b1f6b5a4eab1f73479a50fb79fcf729514a900c341d8503d62a62dbc4127a2b1"},
 ]
 importlib-metadata = [
-    {file = "importlib_metadata-3.3.0-py3-none-any.whl", hash = "sha256:bf792d480abbd5eda85794e4afb09dd538393f7d6e6ffef6e9f03d2014cf9450"},
-    {file = "importlib_metadata-3.3.0.tar.gz", hash = "sha256:5c5a2720817414a6c41f0a49993908068243ae02c1635a228126519b509c8aed"},
+    {file = "importlib_metadata-3.4.0-py3-none-any.whl", hash = "sha256:ace61d5fc652dc280e7b6b4ff732a9c2d40db2c0f92bc6cb74e07b73d53a1771"},
+    {file = "importlib_metadata-3.4.0.tar.gz", hash = "sha256:fa5daa4477a7414ae34e95942e4dd07f62adf589143c875c133c1e53c4eff38d"},
 ]
 iniconfig = [
     {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
     {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
 ]
 isort = [
-    {file = "isort-5.6.4-py3-none-any.whl", hash = "sha256:dcab1d98b469a12a1a624ead220584391648790275560e1a43e54c5dceae65e7"},
-    {file = "isort-5.6.4.tar.gz", hash = "sha256:dcaeec1b5f0eca77faea2a35ab790b4f3680ff75590bfcb7145986905aab2f58"},
+    {file = "isort-5.7.0-py3-none-any.whl", hash = "sha256:fff4f0c04e1825522ce6949973e83110a6e907750cd92d128b0d14aaaadbffdc"},
+    {file = "isort-5.7.0.tar.gz", hash = "sha256:c729845434366216d320e936b8ad6f9d681aab72dc7cbc2d51bedc3582f3ad1e"},
 ]
 jinja2 = [
     {file = "Jinja2-2.11.2-py2.py3-none-any.whl", hash = "sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035"},
@@ -2731,38 +2774,42 @@ pg8000 = [
     {file = "pg8000-1.16.6.tar.gz", hash = "sha256:8fc1e6a62ccb7c9830f1e7e9288e2d20eaf373cc8875b5c55b7d5d9b7717be91"},
 ]
 phonenumbers = [
-    {file = "phonenumbers-8.12.15-py2.py3-none-any.whl", hash = "sha256:13d499f7114c4b37c54ee844b188d5e7441951a7da41de5fc1a25ff8fdceef80"},
-    {file = "phonenumbers-8.12.15.tar.gz", hash = "sha256:b734bfcf33e87ddae72196a40b3d1af35abd0beb263816ae18e1bff612926406"},
+    {file = "phonenumbers-8.12.16-py2.py3-none-any.whl", hash = "sha256:56ad29025b8f885945506350b06d77afbc506c5463141d77a5df767280a7ee0b"},
+    {file = "phonenumbers-8.12.16.tar.gz", hash = "sha256:a820ab08c980ef24a2d2a1ead4f8d7016fdf008e484d1aecf7ff0b32cc475e16"},
 ]
 pillow = [
-    {file = "Pillow-8.0.1-cp36-cp36m-macosx_10_10_x86_64.whl", hash = "sha256:b63d4ff734263ae4ce6593798bcfee6dbfb00523c82753a3a03cbc05555a9cc3"},
-    {file = "Pillow-8.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:5f9403af9c790cc18411ea398a6950ee2def2a830ad0cfe6dc9122e6d528b302"},
-    {file = "Pillow-8.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:6b4a8fd632b4ebee28282a9fef4c341835a1aa8671e2770b6f89adc8e8c2703c"},
-    {file = "Pillow-8.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:cc3ea6b23954da84dbee8025c616040d9aa5eaf34ea6895a0a762ee9d3e12e11"},
-    {file = "Pillow-8.0.1-cp36-cp36m-win32.whl", hash = "sha256:d8a96747df78cda35980905bf26e72960cba6d355ace4780d4bdde3b217cdf1e"},
-    {file = "Pillow-8.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:7ba0ba61252ab23052e642abdb17fd08fdcfdbbf3b74c969a30c58ac1ade7cd3"},
-    {file = "Pillow-8.0.1-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:795e91a60f291e75de2e20e6bdd67770f793c8605b553cb6e4387ce0cb302e09"},
-    {file = "Pillow-8.0.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:0a2e8d03787ec7ad71dc18aec9367c946ef8ef50e1e78c71f743bc3a770f9fae"},
-    {file = "Pillow-8.0.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:006de60d7580d81f4a1a7e9f0173dc90a932e3905cc4d47ea909bc946302311a"},
-    {file = "Pillow-8.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:bd7bf289e05470b1bc74889d1466d9ad4a56d201f24397557b6f65c24a6844b8"},
-    {file = "Pillow-8.0.1-cp37-cp37m-win32.whl", hash = "sha256:95edb1ed513e68bddc2aee3de66ceaf743590bf16c023fb9977adc4be15bd3f0"},
-    {file = "Pillow-8.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:e38d58d9138ef972fceb7aeec4be02e3f01d383723965bfcef14d174c8ccd039"},
-    {file = "Pillow-8.0.1-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:d3d07c86d4efa1facdf32aa878bd508c0dc4f87c48125cc16b937baa4e5b5e11"},
-    {file = "Pillow-8.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:fbd922f702582cb0d71ef94442bfca57624352622d75e3be7a1e7e9360b07e72"},
-    {file = "Pillow-8.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:92c882b70a40c79de9f5294dc99390671e07fc0b0113d472cbea3fde15db1792"},
-    {file = "Pillow-8.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:7c9401e68730d6c4245b8e361d3d13e1035cbc94db86b49dc7da8bec235d0015"},
-    {file = "Pillow-8.0.1-cp38-cp38-win32.whl", hash = "sha256:6c1aca8231625115104a06e4389fcd9ec88f0c9befbabd80dc206c35561be271"},
-    {file = "Pillow-8.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:cc9ec588c6ef3a1325fa032ec14d97b7309db493782ea8c304666fb10c3bd9a7"},
-    {file = "Pillow-8.0.1-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:eb472586374dc66b31e36e14720747595c2b265ae962987261f044e5cce644b5"},
-    {file = "Pillow-8.0.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:0eeeae397e5a79dc088d8297a4c2c6f901f8fb30db47795113a4a605d0f1e5ce"},
-    {file = "Pillow-8.0.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:81f812d8f5e8a09b246515fac141e9d10113229bc33ea073fec11403b016bcf3"},
-    {file = "Pillow-8.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:895d54c0ddc78a478c80f9c438579ac15f3e27bf442c2a9aa74d41d0e4d12544"},
-    {file = "Pillow-8.0.1-cp39-cp39-win32.whl", hash = "sha256:2fb113757a369a6cdb189f8df3226e995acfed0a8919a72416626af1a0a71140"},
-    {file = "Pillow-8.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:59e903ca800c8cfd1ebe482349ec7c35687b95e98cefae213e271c8c7fffa021"},
-    {file = "Pillow-8.0.1-pp36-pypy36_pp73-macosx_10_10_x86_64.whl", hash = "sha256:5abd653a23c35d980b332bc0431d39663b1709d64142e3652890df4c9b6970f6"},
-    {file = "Pillow-8.0.1-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:4b0ef2470c4979e345e4e0cc1bbac65fda11d0d7b789dbac035e4c6ce3f98adb"},
-    {file = "Pillow-8.0.1-pp37-pypy37_pp73-win32.whl", hash = "sha256:8de332053707c80963b589b22f8e0229f1be1f3ca862a932c1bcd48dafb18dd8"},
-    {file = "Pillow-8.0.1.tar.gz", hash = "sha256:11c5c6e9b02c9dac08af04f093eb5a2f84857df70a7d4a6a6ad461aca803fb9e"},
+    {file = "Pillow-8.1.0-cp36-cp36m-macosx_10_10_x86_64.whl", hash = "sha256:d355502dce85ade85a2511b40b4c61a128902f246504f7de29bbeec1ae27933a"},
+    {file = "Pillow-8.1.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:93a473b53cc6e0b3ce6bf51b1b95b7b1e7e6084be3a07e40f79b42e83503fbf2"},
+    {file = "Pillow-8.1.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:2353834b2c49b95e1313fb34edf18fca4d57446675d05298bb694bca4b194174"},
+    {file = "Pillow-8.1.0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:1d208e670abfeb41b6143537a681299ef86e92d2a3dac299d3cd6830d5c7bded"},
+    {file = "Pillow-8.1.0-cp36-cp36m-win32.whl", hash = "sha256:dd9eef866c70d2cbbea1ae58134eaffda0d4bfea403025f4db6859724b18ab3d"},
+    {file = "Pillow-8.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:b09e10ec453de97f9a23a5aa5e30b334195e8d2ddd1ce76cc32e52ba63c8b31d"},
+    {file = "Pillow-8.1.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:b02a0b9f332086657852b1f7cb380f6a42403a6d9c42a4c34a561aa4530d5234"},
+    {file = "Pillow-8.1.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:ca20739e303254287138234485579b28cb0d524401f83d5129b5ff9d606cb0a8"},
+    {file = "Pillow-8.1.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:604815c55fd92e735f9738f65dabf4edc3e79f88541c221d292faec1904a4b17"},
+    {file = "Pillow-8.1.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:cf6e33d92b1526190a1de904df21663c46a456758c0424e4f947ae9aa6088bf7"},
+    {file = "Pillow-8.1.0-cp37-cp37m-win32.whl", hash = "sha256:47c0d93ee9c8b181f353dbead6530b26980fe4f5485aa18be8f1fd3c3cbc685e"},
+    {file = "Pillow-8.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:96d4dc103d1a0fa6d47c6c55a47de5f5dafd5ef0114fa10c85a1fd8e0216284b"},
+    {file = "Pillow-8.1.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:7916cbc94f1c6b1301ac04510d0881b9e9feb20ae34094d3615a8a7c3db0dcc0"},
+    {file = "Pillow-8.1.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:3de6b2ee4f78c6b3d89d184ade5d8fa68af0848f9b6b6da2b9ab7943ec46971a"},
+    {file = "Pillow-8.1.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:cdbbe7dff4a677fb555a54f9bc0450f2a21a93c5ba2b44e09e54fcb72d2bd13d"},
+    {file = "Pillow-8.1.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:f50e7a98b0453f39000619d845be8b06e611e56ee6e8186f7f60c3b1e2f0feae"},
+    {file = "Pillow-8.1.0-cp38-cp38-win32.whl", hash = "sha256:cb192176b477d49b0a327b2a5a4979552b7a58cd42037034316b8018ac3ebb59"},
+    {file = "Pillow-8.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:6c5275bd82711cd3dcd0af8ce0bb99113ae8911fc2952805f1d012de7d600a4c"},
+    {file = "Pillow-8.1.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:165c88bc9d8dba670110c689e3cc5c71dbe4bfb984ffa7cbebf1fac9554071d6"},
+    {file = "Pillow-8.1.0-cp39-cp39-manylinux1_i686.whl", hash = "sha256:5e2fe3bb2363b862671eba632537cd3a823847db4d98be95690b7e382f3d6378"},
+    {file = "Pillow-8.1.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:7612520e5e1a371d77e1d1ca3a3ee6227eef00d0a9cddb4ef7ecb0b7396eddf7"},
+    {file = "Pillow-8.1.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:d673c4990acd016229a5c1c4ee8a9e6d8f481b27ade5fc3d95938697fa443ce0"},
+    {file = "Pillow-8.1.0-cp39-cp39-win32.whl", hash = "sha256:dc577f4cfdda354db3ae37a572428a90ffdbe4e51eda7849bf442fb803f09c9b"},
+    {file = "Pillow-8.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:22d070ca2e60c99929ef274cfced04294d2368193e935c5d6febfd8b601bf865"},
+    {file = "Pillow-8.1.0-pp36-pypy36_pp73-macosx_10_10_x86_64.whl", hash = "sha256:a3d3e086474ef12ef13d42e5f9b7bbf09d39cf6bd4940f982263d6954b13f6a9"},
+    {file = "Pillow-8.1.0-pp36-pypy36_pp73-manylinux2010_i686.whl", hash = "sha256:731ca5aabe9085160cf68b2dbef95fc1991015bc0a3a6ea46a371ab88f3d0913"},
+    {file = "Pillow-8.1.0-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:bba80df38cfc17f490ec651c73bb37cd896bc2400cfba27d078c2135223c1206"},
+    {file = "Pillow-8.1.0-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:c3d911614b008e8a576b8e5303e3db29224b455d3d66d1b2848ba6ca83f9ece9"},
+    {file = "Pillow-8.1.0-pp37-pypy37_pp73-manylinux2010_i686.whl", hash = "sha256:39725acf2d2e9c17356e6835dccebe7a697db55f25a09207e38b835d5e1bc032"},
+    {file = "Pillow-8.1.0-pp37-pypy37_pp73-manylinux2010_x86_64.whl", hash = "sha256:81c3fa9a75d9f1afafdb916d5995633f319db09bd773cb56b8e39f1e98d90820"},
+    {file = "Pillow-8.1.0-pp37-pypy37_pp73-win32.whl", hash = "sha256:b6f00ad5ebe846cc91763b1d0c6d30a8042e02b2316e27b05de04fa6ec831ec5"},
+    {file = "Pillow-8.1.0.tar.gz", hash = "sha256:887668e792b7edbfb1d3c9d8b5d8c859269a0f0eba4dda562adb95500f60dbba"},
 ]
 pluggy = [
     {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"},
@@ -2773,8 +2820,8 @@ prometheus-client = [
     {file = "prometheus_client-0.9.0.tar.gz", hash = "sha256:9da7b32f02439d8c04f7777021c304ed51d9ec180604700c1ba72a4d44dceb03"},
 ]
 prompt-toolkit = [
-    {file = "prompt_toolkit-3.0.8-py3-none-any.whl", hash = "sha256:7debb9a521e0b1ee7d2fe96ee4bd60ef03c6492784de0547337ca4433e46aa63"},
-    {file = "prompt_toolkit-3.0.8.tar.gz", hash = "sha256:25c95d2ac813909f813c93fde734b6e44406d1477a9faef7c915ff37d39c0a8c"},
+    {file = "prompt_toolkit-3.0.11-py3-none-any.whl", hash = "sha256:0bdd2585e5afd00c5f91dd28eb2090ea67e94c385878921939bb4ccfa3904723"},
+    {file = "prompt_toolkit-3.0.11.tar.gz", hash = "sha256:dc83e6368b0edd9ceabe17a055f2e22f6ed95b9aa39dbd59d0b4f3585bdfe9ed"},
 ]
 psutil = [
     {file = "psutil-5.8.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:0066a82f7b1b37d334e68697faba68e5ad5e858279fd6351c8ca6024e8d6ba64"},
@@ -2907,12 +2954,12 @@ pyflakes = [
     {file = "pyflakes-2.2.0.tar.gz", hash = "sha256:35b2d75ee967ea93b55750aa9edbbf72813e06a66ba54438df2cfac9e3c27fc8"},
 ]
 pygments = [
-    {file = "Pygments-2.7.3-py3-none-any.whl", hash = "sha256:f275b6c0909e5dafd2d6269a656aa90fa58ebf4a74f8fcf9053195d226b24a08"},
-    {file = "Pygments-2.7.3.tar.gz", hash = "sha256:ccf3acacf3782cbed4a989426012f1c535c9a90d3a7fc3f16d231b9372d2b716"},
+    {file = "Pygments-2.7.4-py3-none-any.whl", hash = "sha256:bc9591213a8f0e0ca1a5e68a479b4887fdc3e75d0774e5c71c31920c427de435"},
+    {file = "Pygments-2.7.4.tar.gz", hash = "sha256:df49d09b498e83c1a73128295860250b0b7edd4c723a32e9bc0d295c7c2ec337"},
 ]
 pyjwt = [
-    {file = "PyJWT-2.0.0-py3-none-any.whl", hash = "sha256:5c2ff2eb27d7e342dfc3cafcc16412781f06db2690fbef81922b0172598f085b"},
-    {file = "PyJWT-2.0.0.tar.gz", hash = "sha256:7a2b271c6dac2fda9e0c33d176c4253faba2c6c6b3a99c7f28a32c3c97522779"},
+    {file = "PyJWT-1.7.1-py2.py3-none-any.whl", hash = "sha256:5c6eca3c2940464d106b99ba83b00c6add741c9becaec087fb7ccdefea71350e"},
+    {file = "PyJWT-1.7.1.tar.gz", hash = "sha256:8d59a976fb773f3e6a39c85636357c4f0e242707394cadadd9814f5cbaa20e96"},
 ]
 pyparsing = [
     {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"},
@@ -2923,8 +2970,8 @@ pytest = [
     {file = "pytest-6.2.1.tar.gz", hash = "sha256:66e419b1899bc27346cb2c993e12c5e5e8daba9073c1fbce33b9807abc95c306"},
 ]
 pytest-cov = [
-    {file = "pytest-cov-2.10.1.tar.gz", hash = "sha256:47bd0ce14056fdd79f93e1713f88fad7bdcc583dcd7783da86ef2f085a0bb88e"},
-    {file = "pytest_cov-2.10.1-py2.py3-none-any.whl", hash = "sha256:45ec2d5182f89a81fc3eb29e3d1ed3113b9e9a873bcddb2a71faaab066110191"},
+    {file = "pytest-cov-2.11.1.tar.gz", hash = "sha256:359952d9d39b9f822d9d29324483e7ba04a3a17dd7d05aa6beb7ea01e359e5f7"},
+    {file = "pytest_cov-2.11.1-py2.py3-none-any.whl", hash = "sha256:bdb9fdb0b85a7cc825269a4c56b48ccaa5c7e365054b6038772c32ddcdc969da"},
 ]
 pytest-django = [
     {file = "pytest-django-3.10.0.tar.gz", hash = "sha256:4de6dbd077ed8606616958f77655fed0d5e3ee45159475671c7fa67596c6dba6"},
@@ -2956,19 +3003,27 @@ pytz = [
     {file = "pytz-2020.5.tar.gz", hash = "sha256:180befebb1927b16f6b57101720075a984c019ac16b1b7575673bea42c6c3da5"},
 ]
 pyyaml = [
-    {file = "PyYAML-5.3.1-cp27-cp27m-win32.whl", hash = "sha256:74809a57b329d6cc0fdccee6318f44b9b8649961fa73144a98735b0aaf029f1f"},
-    {file = "PyYAML-5.3.1-cp27-cp27m-win_amd64.whl", hash = "sha256:240097ff019d7c70a4922b6869d8a86407758333f02203e0fc6ff79c5dcede76"},
-    {file = "PyYAML-5.3.1-cp35-cp35m-win32.whl", hash = "sha256:4f4b913ca1a7319b33cfb1369e91e50354d6f07a135f3b901aca02aa95940bd2"},
-    {file = "PyYAML-5.3.1-cp35-cp35m-win_amd64.whl", hash = "sha256:cc8955cfbfc7a115fa81d85284ee61147059a753344bc51098f3ccd69b0d7e0c"},
-    {file = "PyYAML-5.3.1-cp36-cp36m-win32.whl", hash = "sha256:7739fc0fa8205b3ee8808aea45e968bc90082c10aef6ea95e855e10abf4a37b2"},
-    {file = "PyYAML-5.3.1-cp36-cp36m-win_amd64.whl", hash = "sha256:69f00dca373f240f842b2931fb2c7e14ddbacd1397d57157a9b005a6a9942648"},
-    {file = "PyYAML-5.3.1-cp37-cp37m-win32.whl", hash = "sha256:d13155f591e6fcc1ec3b30685d50bf0711574e2c0dfffd7644babf8b5102ca1a"},
-    {file = "PyYAML-5.3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:73f099454b799e05e5ab51423c7bcf361c58d3206fa7b0d555426b1f4d9a3eaf"},
-    {file = "PyYAML-5.3.1-cp38-cp38-win32.whl", hash = "sha256:06a0d7ba600ce0b2d2fe2e78453a470b5a6e000a985dd4a4e54e436cc36b0e97"},
-    {file = "PyYAML-5.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:95f71d2af0ff4227885f7a6605c37fd53d3a106fcab511b8860ecca9fcf400ee"},
-    {file = "PyYAML-5.3.1-cp39-cp39-win32.whl", hash = "sha256:ad9c67312c84def58f3c04504727ca879cb0013b2517c85a9a253f0cb6380c0a"},
-    {file = "PyYAML-5.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:6034f55dab5fea9e53f436aa68fa3ace2634918e8b5994d82f3621c04ff5ed2e"},
-    {file = "PyYAML-5.3.1.tar.gz", hash = "sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d"},
+    {file = "PyYAML-5.4.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922"},
+    {file = "PyYAML-5.4.1-cp27-cp27m-win32.whl", hash = "sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393"},
+    {file = "PyYAML-5.4.1-cp27-cp27m-win_amd64.whl", hash = "sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8"},
+    {file = "PyYAML-5.4.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185"},
+    {file = "PyYAML-5.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253"},
+    {file = "PyYAML-5.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc"},
+    {file = "PyYAML-5.4.1-cp36-cp36m-win32.whl", hash = "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5"},
+    {file = "PyYAML-5.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df"},
+    {file = "PyYAML-5.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018"},
+    {file = "PyYAML-5.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63"},
+    {file = "PyYAML-5.4.1-cp37-cp37m-win32.whl", hash = "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b"},
+    {file = "PyYAML-5.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf"},
+    {file = "PyYAML-5.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46"},
+    {file = "PyYAML-5.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb"},
+    {file = "PyYAML-5.4.1-cp38-cp38-win32.whl", hash = "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc"},
+    {file = "PyYAML-5.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696"},
+    {file = "PyYAML-5.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77"},
+    {file = "PyYAML-5.4.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183"},
+    {file = "PyYAML-5.4.1-cp39-cp39-win32.whl", hash = "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10"},
+    {file = "PyYAML-5.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db"},
+    {file = "PyYAML-5.4.1.tar.gz", hash = "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e"},
 ]
 qrcode = [
     {file = "qrcode-6.1-py2.py3-none-any.whl", hash = "sha256:3996ee560fc39532910603704c82980ff6d4d5d629f9c3f25f34174ce8606cf5"},
@@ -3069,8 +3124,8 @@ rules = [
     {file = "rules-2.2.tar.gz", hash = "sha256:9bae429f9d4f91a375402990da1541f9e093b0ac077221d57124d06eeeca4405"},
 ]
 safety = [
-    {file = "safety-1.10.0-py2.py3-none-any.whl", hash = "sha256:69437acf5dd617abd7086ccd0d50e813e67aa969bb9ca90f1847d5fbea047dcc"},
-    {file = "safety-1.10.0.tar.gz", hash = "sha256:2ebc71b44666588d7898905d86d575933fcd5fa3c92d301ed12482602b1e928a"},
+    {file = "safety-1.10.3-py2.py3-none-any.whl", hash = "sha256:5f802ad5df5614f9622d8d71fedec2757099705c2356f862847c58c6dfe13e84"},
+    {file = "safety-1.10.3.tar.gz", hash = "sha256:30e394d02a20ac49b7f65292d19d38fa927a8f9582cdfd3ad1adbbc66c641ad5"},
 ]
 scramp = [
     {file = "scramp-1.2.0-py3-none-any.whl", hash = "sha256:74815c25aad1fe0b5fb994e96c3de63e8695164358a80138352aaadfa4760350"},
@@ -3092,13 +3147,17 @@ snowballstemmer = [
     {file = "snowballstemmer-2.0.0-py2.py3-none-any.whl", hash = "sha256:209f257d7533fdb3cb73bdbd24f436239ca3b2fa67d56f6ff88e86be08cc5ef0"},
     {file = "snowballstemmer-2.0.0.tar.gz", hash = "sha256:df3bac3df4c2c01363f3dd2cfa78cce2840a79b9f1c2d2de9ce8d31683992f52"},
 ]
+soupsieve = [
+    {file = "soupsieve-2.1-py3-none-any.whl", hash = "sha256:4bb21a6ee4707bf43b61230e80740e71bfe56e55d1f1f50924b087bb2975c851"},
+    {file = "soupsieve-2.1.tar.gz", hash = "sha256:6dc52924dc0bc710a5d16794e6b3480b2c7c08b07729505feab2b2c16661ff6e"},
+]
 spdx-license-list = [
     {file = "spdx_license_list-0.5.2-py3-none-any.whl", hash = "sha256:1b338470c7b403dbecceca563a316382c7977516128ca6c1e8f7078e3ed6e7b0"},
     {file = "spdx_license_list-0.5.2.tar.gz", hash = "sha256:952996f72ab807972dc2278bb9b91e5294767211e51f09aad9c0e2ff5b82a31b"},
 ]
 sphinx = [
-    {file = "Sphinx-3.4.1-py3-none-any.whl", hash = "sha256:aeef652b14629431c82d3fe994ce39ead65b3fe87cf41b9a3714168ff8b83376"},
-    {file = "Sphinx-3.4.1.tar.gz", hash = "sha256:e450cb205ff8924611085183bf1353da26802ae73d9251a8fcdf220a8f8712ef"},
+    {file = "Sphinx-3.4.3-py3-none-any.whl", hash = "sha256:c314c857e7cd47c856d2c5adff514ac2e6495f8b8e0f886a8a37e9305dfea0d8"},
+    {file = "Sphinx-3.4.3.tar.gz", hash = "sha256:41cad293f954f7d37f803d97eb184158cfd90f51195131e94875bc07cd08b93c"},
 ]
 sphinx-autodoc-typehints = [
     {file = "sphinx-autodoc-typehints-1.11.1.tar.gz", hash = "sha256:244ba6d3e2fdb854622f643c7763d6f95b6886eba24bec28e86edf205e4ddb20"},
@@ -3144,8 +3203,8 @@ termcolor = [
     {file = "termcolor-1.1.0.tar.gz", hash = "sha256:1d6d69ce66211143803fbc56652b41d73b4a400a2891d7bf7a1cdf4c02de613b"},
 ]
 testfixtures = [
-    {file = "testfixtures-6.17.0-py2.py3-none-any.whl", hash = "sha256:ebcc3e024d47bb58a60cdc678604151baa0c920ae2814004c89ac9066de31b2c"},
-    {file = "testfixtures-6.17.0.tar.gz", hash = "sha256:fa7c170df68ca6367eda061e9ec339ae3e6d3679c31e04033f83ef97a7d7d0ce"},
+    {file = "testfixtures-6.17.1-py2.py3-none-any.whl", hash = "sha256:9ed31e83f59619e2fa17df053b241e16e0608f4580f7b5a9333a0c9bdcc99137"},
+    {file = "testfixtures-6.17.1.tar.gz", hash = "sha256:5ec3a0dd6f71cc4c304fbc024a10cc293d3e0b852c868014b9f233203e149bda"},
 ]
 "testing.common.database" = [
     {file = "testing.common.database-2.0.3-py2.py3-none-any.whl", hash = "sha256:e3ed492bf480a87f271f74c53b262caf5d85c8bc09989a8f534fa2283ec52492"},
@@ -3164,43 +3223,43 @@ toml = [
     {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
 ]
 tqdm = [
-    {file = "tqdm-4.55.0-py2.py3-none-any.whl", hash = "sha256:0cd81710de29754bf17b6fee07bdb86f956b4fa20d3078f02040f83e64309416"},
-    {file = "tqdm-4.55.0.tar.gz", hash = "sha256:f4f80b96e2ceafea69add7bf971b8403b9cba8fb4451c1220f91c79be4ebd208"},
+    {file = "tqdm-4.56.0-py2.py3-none-any.whl", hash = "sha256:4621f6823bab46a9cc33d48105753ccbea671b68bab2c50a9f0be23d4065cb5a"},
+    {file = "tqdm-4.56.0.tar.gz", hash = "sha256:fe3d08dd00a526850568d542ff9de9bbc2a09a791da3c334f3213d8d0bbbca65"},
 ]
 twilio = [
-    {file = "twilio-6.50.1.tar.gz", hash = "sha256:dd8371c9b4ea422d6de7526b63b587da82e8488f2b3f6b1258d2cad6e4006a65"},
+    {file = "twilio-6.51.0.tar.gz", hash = "sha256:de98a05858e6efdf87bfa4c8f7e773adf1885cfcbb6531356840bcd17dc4c444"},
 ]
 typed-ast = [
-    {file = "typed_ast-1.4.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3"},
-    {file = "typed_ast-1.4.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb"},
-    {file = "typed_ast-1.4.1-cp35-cp35m-win32.whl", hash = "sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919"},
-    {file = "typed_ast-1.4.1-cp35-cp35m-win_amd64.whl", hash = "sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01"},
-    {file = "typed_ast-1.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75"},
-    {file = "typed_ast-1.4.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652"},
-    {file = "typed_ast-1.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7"},
-    {file = "typed_ast-1.4.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:fcf135e17cc74dbfbc05894ebca928ffeb23d9790b3167a674921db19082401f"},
-    {file = "typed_ast-1.4.1-cp36-cp36m-win32.whl", hash = "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1"},
-    {file = "typed_ast-1.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa"},
-    {file = "typed_ast-1.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614"},
-    {file = "typed_ast-1.4.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41"},
-    {file = "typed_ast-1.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b"},
-    {file = "typed_ast-1.4.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:f208eb7aff048f6bea9586e61af041ddf7f9ade7caed625742af423f6bae3298"},
-    {file = "typed_ast-1.4.1-cp37-cp37m-win32.whl", hash = "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe"},
-    {file = "typed_ast-1.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355"},
-    {file = "typed_ast-1.4.1-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6"},
-    {file = "typed_ast-1.4.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907"},
-    {file = "typed_ast-1.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d"},
-    {file = "typed_ast-1.4.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:7e4c9d7658aaa1fc80018593abdf8598bf91325af6af5cce4ce7c73bc45ea53d"},
-    {file = "typed_ast-1.4.1-cp38-cp38-win32.whl", hash = "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c"},
-    {file = "typed_ast-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4"},
-    {file = "typed_ast-1.4.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34"},
-    {file = "typed_ast-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:92c325624e304ebf0e025d1224b77dd4e6393f18aab8d829b5b7e04afe9b7a2c"},
-    {file = "typed_ast-1.4.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:d648b8e3bf2fe648745c8ffcee3db3ff903d0817a01a12dd6a6ea7a8f4889072"},
-    {file = "typed_ast-1.4.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:fac11badff8313e23717f3dada86a15389d0708275bddf766cca67a84ead3e91"},
-    {file = "typed_ast-1.4.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:0d8110d78a5736e16e26213114a38ca35cb15b6515d535413b090bd50951556d"},
-    {file = "typed_ast-1.4.1-cp39-cp39-win32.whl", hash = "sha256:b52ccf7cfe4ce2a1064b18594381bccf4179c2ecf7f513134ec2f993dd4ab395"},
-    {file = "typed_ast-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:3742b32cf1c6ef124d57f95be609c473d7ec4c14d0090e5a5e05a15269fb4d0c"},
-    {file = "typed_ast-1.4.1.tar.gz", hash = "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b"},
+    {file = "typed_ast-1.4.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:7703620125e4fb79b64aa52427ec192822e9f45d37d4b6625ab37ef403e1df70"},
+    {file = "typed_ast-1.4.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:c9aadc4924d4b5799112837b226160428524a9a45f830e0d0f184b19e4090487"},
+    {file = "typed_ast-1.4.2-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:9ec45db0c766f196ae629e509f059ff05fc3148f9ffd28f3cfe75d4afb485412"},
+    {file = "typed_ast-1.4.2-cp35-cp35m-win32.whl", hash = "sha256:85f95aa97a35bdb2f2f7d10ec5bbdac0aeb9dafdaf88e17492da0504de2e6400"},
+    {file = "typed_ast-1.4.2-cp35-cp35m-win_amd64.whl", hash = "sha256:9044ef2df88d7f33692ae3f18d3be63dec69c4fb1b5a4a9ac950f9b4ba571606"},
+    {file = "typed_ast-1.4.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c1c876fd795b36126f773db9cbb393f19808edd2637e00fd6caba0e25f2c7b64"},
+    {file = "typed_ast-1.4.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:5dcfc2e264bd8a1db8b11a892bd1647154ce03eeba94b461effe68790d8b8e07"},
+    {file = "typed_ast-1.4.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:8db0e856712f79c45956da0c9a40ca4246abc3485ae0d7ecc86a20f5e4c09abc"},
+    {file = "typed_ast-1.4.2-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:d003156bb6a59cda9050e983441b7fa2487f7800d76bdc065566b7d728b4581a"},
+    {file = "typed_ast-1.4.2-cp36-cp36m-win32.whl", hash = "sha256:4c790331247081ea7c632a76d5b2a265e6d325ecd3179d06e9cf8d46d90dd151"},
+    {file = "typed_ast-1.4.2-cp36-cp36m-win_amd64.whl", hash = "sha256:d175297e9533d8d37437abc14e8a83cbc68af93cc9c1c59c2c292ec59a0697a3"},
+    {file = "typed_ast-1.4.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cf54cfa843f297991b7388c281cb3855d911137223c6b6d2dd82a47ae5125a41"},
+    {file = "typed_ast-1.4.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:b4fcdcfa302538f70929eb7b392f536a237cbe2ed9cba88e3bf5027b39f5f77f"},
+    {file = "typed_ast-1.4.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:987f15737aba2ab5f3928c617ccf1ce412e2e321c77ab16ca5a293e7bbffd581"},
+    {file = "typed_ast-1.4.2-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:37f48d46d733d57cc70fd5f30572d11ab8ed92da6e6b28e024e4a3edfb456e37"},
+    {file = "typed_ast-1.4.2-cp37-cp37m-win32.whl", hash = "sha256:36d829b31ab67d6fcb30e185ec996e1f72b892255a745d3a82138c97d21ed1cd"},
+    {file = "typed_ast-1.4.2-cp37-cp37m-win_amd64.whl", hash = "sha256:8368f83e93c7156ccd40e49a783a6a6850ca25b556c0fa0240ed0f659d2fe496"},
+    {file = "typed_ast-1.4.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:963c80b583b0661918718b095e02303d8078950b26cc00b5e5ea9ababe0de1fc"},
+    {file = "typed_ast-1.4.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:e683e409e5c45d5c9082dc1daf13f6374300806240719f95dc783d1fc942af10"},
+    {file = "typed_ast-1.4.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:84aa6223d71012c68d577c83f4e7db50d11d6b1399a9c779046d75e24bed74ea"},
+    {file = "typed_ast-1.4.2-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:a38878a223bdd37c9709d07cd357bb79f4c760b29210e14ad0fb395294583787"},
+    {file = "typed_ast-1.4.2-cp38-cp38-win32.whl", hash = "sha256:a2c927c49f2029291fbabd673d51a2180038f8cd5a5b2f290f78c4516be48be2"},
+    {file = "typed_ast-1.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:c0c74e5579af4b977c8b932f40a5464764b2f86681327410aa028a22d2f54937"},
+    {file = "typed_ast-1.4.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:07d49388d5bf7e863f7fa2f124b1b1d89d8aa0e2f7812faff0a5658c01c59aa1"},
+    {file = "typed_ast-1.4.2-cp39-cp39-manylinux1_i686.whl", hash = "sha256:240296b27397e4e37874abb1df2a608a92df85cf3e2a04d0d4d61055c8305ba6"},
+    {file = "typed_ast-1.4.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:d746a437cdbca200622385305aedd9aef68e8a645e385cc483bdc5e488f07166"},
+    {file = "typed_ast-1.4.2-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:14bf1522cdee369e8f5581238edac09150c765ec1cb33615855889cf33dcb92d"},
+    {file = "typed_ast-1.4.2-cp39-cp39-win32.whl", hash = "sha256:cc7b98bf58167b7f2db91a4327da24fb93368838eb84a44c472283778fc2446b"},
+    {file = "typed_ast-1.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:7147e2a76c75f0f64c4319886e7639e490fee87c9d25cb1d4faef1d8cf83a440"},
+    {file = "typed_ast-1.4.2.tar.gz", hash = "sha256:9fc0b3cb5d1720e7141d103cf4819aea239f7d136acf9ee4a69b047b7986175a"},
 ]
 typing-extensions = [
     {file = "typing_extensions-3.7.4.3-py2-none-any.whl", hash = "sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f"},
diff --git a/pyproject.toml b/pyproject.toml
index cfb02aa3649f591f00fac32004c0a397e43a09ab..9a388a12d9da6e4e195a175072832dc8ce7a59fc 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
 [tool.poetry]
 name = "AlekSIS-Core"
-version = "2.0a3.dev0"
+version = "2.0a4.dev0"
 packages = [
     { include = "aleksis" }
 ]
@@ -38,7 +38,7 @@ Django = "^3.0"
 django-any-js = "^1.0"
 django-debug-toolbar = "^2.0"
 django-middleware-global-request = "^0.1.2"
-django-menu-generator = "^1.0.4"
+django-menu-generator-ng = "^1.2.0"
 django-tables2 = "^2.1"
 Pillow = "^8.0"
 django-phonenumber-field = {version = "<5.1", extras = ["phonenumbers"]}
@@ -72,7 +72,7 @@ Celery = {version="^5.0.0", optional=true, extras=["django", "redis"]}
 django-celery-results = {version="^2.0.0", optional=true}
 django-celery-beat = {version="^2.0.0", optional=true}
 django-celery-email = {version="^3.0.0", optional=true}
-django-jsonstore = "^0.4.1"
+django-jsonstore = "^0.5.0"
 django-polymorphic = "^3.0.0"
 django-colorfield = "^0.3.0"
 django-bleach = "^0.6.1"
@@ -93,6 +93,7 @@ django-cachalot = "^2.3.2"
 django-prometheus = "^2.1.0"
 importlib-metadata = {version = "^3.0.0", python = "<3.9"}
 django-model-utils = "^4.0.0"
+bs4 = "^0.0.1"
 
 [tool.poetry.extras]
 ldap = ["django-auth-ldap"]
diff --git a/tox.ini b/tox.ini
index 98fce3af53aa48d1eac2e28454c26e7b74c23f72..e1283a1b72150383c5c2c9b7fbf43abb6cdf6ea2 100644
--- a/tox.ini
+++ b/tox.ini
@@ -9,9 +9,11 @@ whitelist_externals = poetry
 skip_install = true
 envdir = {toxworkdir}/globalenv
 commands_pre =
-     - poetry install
+     poetry install
+     poetry run aleksis-admin yarn install
+     poetry run aleksis-admin collectstatic --no-input
 commands =
-    - poetry run pytest --cov=. {posargs} aleksis/
+    poetry run pytest --cov=. {posargs} aleksis/
 
 [testenv:selenium]
 setenv =