wbcore 1.46.0__py2.py3-none-any.whl → 1.58.2__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- wbcore/cache/decorators.py +5 -3
- wbcore/cache/registry.py +14 -7
- wbcore/configs/__init__.py +1 -0
- wbcore/configs/configs.py +5 -0
- wbcore/configs/decorators.py +1 -1
- wbcore/configurations/configurations/apps.py +3 -2
- wbcore/configurations/configurations/authentication.py +1 -1
- wbcore/configurations/configurations/base.py +1 -1
- wbcore/configurations/configurations/cache.py +1 -1
- wbcore/configurations/configurations/i18nl10n.py +2 -1
- wbcore/configurations/configurations/maintenance.py +1 -1
- wbcore/configurations/configurations/media.py +1 -1
- wbcore/configurations/configurations/middleware.py +1 -1
- wbcore/configurations/configurations/rest_framework.py +1 -1
- wbcore/configurations/configurations/static.py +3 -3
- wbcore/configurations/configurations/wbcore.py +1 -1
- wbcore/content_type/serializers.py +13 -5
- wbcore/content_type/utils.py +3 -3
- wbcore/content_type/viewsets.py +2 -2
- wbcore/contrib/agenda/filters/calendar_item.py +5 -4
- wbcore/contrib/agenda/locale/de/LC_MESSAGES/django.po +145 -52
- wbcore/contrib/agenda/locale/de/LC_MESSAGES/django.po.translated +236 -0
- wbcore/contrib/agenda/locale/en/LC_MESSAGES/django.po +200 -0
- wbcore/contrib/agenda/locale/fr/LC_MESSAGES/django.po +201 -0
- wbcore/contrib/agenda/viewsets/calendar_items.py +7 -7
- wbcore/contrib/agenda/viewsets/menu/calendar_items.py +0 -6
- wbcore/contrib/ai/exceptions.py +5 -5
- wbcore/contrib/ai/llm/config.py +76 -27
- wbcore/contrib/ai/llm/mixins.py +5 -8
- wbcore/contrib/ai/llm/utils.py +50 -26
- wbcore/contrib/authentication/admin.py +2 -2
- wbcore/contrib/authentication/factories/__init__.py +8 -1
- wbcore/contrib/authentication/factories/users.py +19 -0
- wbcore/contrib/authentication/filters.py +1 -2
- wbcore/contrib/authentication/locale/de/LC_MESSAGES/django.po +209 -187
- wbcore/contrib/authentication/locale/de/LC_MESSAGES/django.po.translated +634 -0
- wbcore/contrib/authentication/locale/en/LC_MESSAGES/django.po +590 -0
- wbcore/contrib/authentication/locale/fr/LC_MESSAGES/django.po +592 -0
- wbcore/contrib/authentication/models/users.py +3 -3
- wbcore/contrib/authentication/models/users_activities.py +1 -1
- wbcore/contrib/authentication/serializers/users.py +2 -2
- wbcore/contrib/authentication/tests/test_tokens.py +3 -3
- wbcore/contrib/authentication/tests/test_users.py +0 -1
- wbcore/contrib/authentication/urls.py +0 -4
- wbcore/contrib/authentication/viewsets/endpoints/user_activities.py +2 -11
- wbcore/contrib/authentication/viewsets/endpoints/users.py +0 -3
- wbcore/contrib/authentication/viewsets/user_activities.py +2 -1
- wbcore/contrib/authentication/viewsets/users.py +6 -4
- wbcore/contrib/color/models.py +2 -1
- wbcore/contrib/currency/factories.py +1 -1
- wbcore/contrib/currency/import_export/backends/fixerio/currency_fx_rates.py +3 -1
- wbcore/contrib/currency/models.py +30 -8
- wbcore/contrib/currency/serializers.py +5 -1
- wbcore/contrib/currency/tests/test_serializers.py +7 -3
- wbcore/contrib/currency/tests/test_viewsets.py +1 -1
- wbcore/contrib/currency/viewsets/currency.py +2 -2
- wbcore/contrib/currency/viewsets/endpoints/currency_fx_rates.py +0 -9
- wbcore/contrib/dataloader/tests/test/dataloaders/protocols.py +1 -2
- wbcore/contrib/dataloader/utils.py +2 -2
- wbcore/contrib/directory/factories/__init__.py +1 -1
- wbcore/contrib/directory/factories/entries.py +2 -1
- wbcore/contrib/directory/filters/entries.py +9 -0
- wbcore/contrib/directory/locale/de/LC_MESSAGES/django.po +728 -714
- wbcore/contrib/directory/locale/de/LC_MESSAGES/django.po.translated +1779 -0
- wbcore/contrib/directory/locale/en/LC_MESSAGES/django.po +1652 -0
- wbcore/contrib/directory/locale/fr/LC_MESSAGES/django.po +1654 -0
- wbcore/contrib/directory/migrations/0011_person_description_person_i18n.py +24 -0
- wbcore/contrib/directory/migrations/0012_alter_person_managers.py +20 -0
- wbcore/contrib/directory/migrations/0013_alter_clientmanagerrelationship_options.py +17 -0
- wbcore/contrib/directory/models/contacts.py +2 -2
- wbcore/contrib/directory/models/entries.py +31 -5
- wbcore/contrib/directory/models/relationships.py +31 -35
- wbcore/contrib/directory/permissions.py +6 -0
- wbcore/contrib/directory/serializers/companies.py +16 -8
- wbcore/contrib/directory/serializers/contacts.py +8 -8
- wbcore/contrib/directory/serializers/entries.py +26 -15
- wbcore/contrib/directory/serializers/entry_representations.py +4 -2
- wbcore/contrib/directory/serializers/persons.py +12 -10
- wbcore/contrib/directory/serializers/relationships.py +2 -2
- wbcore/contrib/directory/tests/conftest.py +2 -0
- wbcore/contrib/directory/tests/disable_signals.py +11 -1
- wbcore/contrib/directory/tests/signals.py +2 -2
- wbcore/contrib/directory/tests/test_models.py +88 -66
- wbcore/contrib/directory/tests/test_serializers.py +1 -1
- wbcore/contrib/directory/tests/test_viewsets.py +8 -8
- wbcore/contrib/directory/viewsets/buttons/__init__.py +1 -1
- wbcore/contrib/directory/viewsets/buttons/relationships.py +32 -0
- wbcore/contrib/directory/viewsets/contacts.py +6 -6
- wbcore/contrib/directory/viewsets/display/__init__.py +1 -1
- wbcore/contrib/directory/viewsets/display/contacts.py +1 -14
- wbcore/contrib/directory/viewsets/display/entries.py +68 -38
- wbcore/contrib/directory/viewsets/display/relationships.py +26 -50
- wbcore/contrib/directory/viewsets/endpoints/relationships.py +1 -26
- wbcore/contrib/directory/viewsets/entries.py +8 -6
- wbcore/contrib/directory/viewsets/previews/entries.py +3 -3
- wbcore/contrib/directory/viewsets/relationships.py +16 -2
- wbcore/contrib/directory/viewsets/titles/relationships.py +2 -3
- wbcore/contrib/documents/filters.py +0 -2
- wbcore/contrib/documents/locale/de/LC_MESSAGES/django.po +103 -94
- wbcore/contrib/documents/locale/de/LC_MESSAGES/django.po.translated +285 -0
- wbcore/contrib/documents/locale/en/LC_MESSAGES/django.po +271 -0
- wbcore/contrib/documents/locale/fr/LC_MESSAGES/django.po +270 -0
- wbcore/contrib/documents/tests/test_models.py +32 -28
- wbcore/contrib/documents/viewsets/endpoints/shareable_links.py +2 -21
- wbcore/contrib/dynamic_preferences/types.py +108 -0
- wbcore/contrib/dynamic_preferences/viewsets.py +27 -0
- wbcore/contrib/example_app/filters/event.py +3 -1
- wbcore/contrib/example_app/filters/match.py +1 -1
- wbcore/contrib/example_app/models.py +91 -22
- wbcore/contrib/example_app/serializers/person_team.py +4 -4
- wbcore/contrib/example_app/templates/example_app/embedded_view.html +19 -0
- wbcore/contrib/example_app/tests/e2e/test_teams.py +1 -1
- wbcore/contrib/example_app/tests/test_models/test_match.py +17 -7
- wbcore/contrib/example_app/urls.py +2 -0
- wbcore/contrib/example_app/views.py +7 -0
- wbcore/contrib/example_app/viewsets/displays/team.py +23 -4
- wbcore/contrib/example_app/viewsets/menu/menus.py +1 -1
- wbcore/contrib/example_app/viewsets/menus.py +1 -1
- wbcore/contrib/geography/tests/conftest.py +14 -0
- wbcore/contrib/geography/tests/test_models.py +23 -8
- wbcore/contrib/geography/tests/test_viewsets.py +96 -2
- wbcore/contrib/guardian/tests/test_model_mixins.py +3 -4
- wbcore/contrib/guardian/tests/test_tasks.py +9 -9
- wbcore/contrib/guardian/tests/test_viewsets.py +2 -2
- wbcore/contrib/guardian/viewsets/configs/__init__.py +1 -1
- wbcore/contrib/guardian/viewsets/configs/buttons.py +9 -0
- wbcore/contrib/guardian/viewsets/configs/endpoints.py +7 -0
- wbcore/contrib/guardian/viewsets/viewsets.py +2 -0
- wbcore/contrib/i18n/__init__.py +2 -0
- wbcore/contrib/i18n/buttons.py +33 -0
- wbcore/contrib/i18n/serializers/__init__.py +0 -0
- wbcore/contrib/i18n/serializers/fields.py +20 -0
- wbcore/contrib/i18n/serializers/mixins.py +13 -0
- wbcore/contrib/i18n/tests/conftest.py +11 -0
- wbcore/contrib/i18n/tests/test_viewsets.py +67 -0
- wbcore/contrib/i18n/translation.py +140 -0
- wbcore/contrib/i18n/viewsets.py +36 -0
- wbcore/contrib/icons/backends/default.py +1 -0
- wbcore/contrib/icons/backends/material.py +1 -0
- wbcore/contrib/icons/icons.py +5 -8
- wbcore/contrib/io/admin.py +1 -0
- wbcore/contrib/io/backends/mail.py +3 -2
- wbcore/contrib/io/backends/utils.py +14 -17
- wbcore/contrib/io/exceptions.py +8 -0
- wbcore/contrib/io/factories.py +1 -1
- wbcore/contrib/io/import_export/backends/mail.py +1 -0
- wbcore/contrib/io/import_export/backends/sftp.py +29 -20
- wbcore/contrib/io/import_export/backends/stream.py +2 -2
- wbcore/contrib/io/import_export/parsers/__init__.py +0 -0
- wbcore/contrib/io/import_export/parsers/base_csv.py +36 -0
- wbcore/contrib/io/import_export/parsers/resources.py +50 -0
- wbcore/contrib/io/imports.py +33 -25
- wbcore/contrib/io/locale/de/LC_MESSAGES/django.po +114 -22
- wbcore/contrib/io/locale/de/LC_MESSAGES/django.po.translated +103 -0
- wbcore/contrib/io/locale/en/LC_MESSAGES/django.po +138 -0
- wbcore/contrib/io/locale/fr/LC_MESSAGES/django.po +138 -0
- wbcore/contrib/io/migrations/0008_importsource_resource_kwargs.py +18 -0
- wbcore/contrib/io/models.py +65 -45
- wbcore/contrib/io/resources.py +0 -6
- wbcore/contrib/io/serializers.py +2 -2
- wbcore/contrib/io/signals.py +4 -0
- wbcore/contrib/io/tests/test_backends.py +19 -13
- wbcore/contrib/io/tests/test_exports.py +1 -1
- wbcore/contrib/io/tests/test_imports.py +1 -1
- wbcore/contrib/io/tests/test_models.py +47 -14
- wbcore/contrib/io/tests/test_viewsets.py +271 -0
- wbcore/contrib/io/viewset_mixins.py +41 -54
- wbcore/contrib/notifications/admin.py +1 -0
- wbcore/contrib/notifications/apps.py +2 -1
- wbcore/contrib/notifications/backends/abstract_backend.py +2 -4
- wbcore/contrib/notifications/backends/firebase/backends.py +5 -2
- wbcore/contrib/notifications/dispatch.py +18 -7
- wbcore/contrib/notifications/factories/notification_types.py +1 -0
- wbcore/contrib/notifications/locale/de/LC_MESSAGES/django.po +25 -19
- wbcore/contrib/notifications/locale/de/LC_MESSAGES/django.po.translated +63 -0
- wbcore/contrib/notifications/locale/en/LC_MESSAGES/django.po +61 -0
- wbcore/contrib/notifications/locale/fr/LC_MESSAGES/django.po +62 -0
- wbcore/contrib/notifications/migrations/0008_notificationtype_is_lock.py +18 -0
- wbcore/contrib/notifications/migrations/0009_alter_notificationtypesetting_options_and_more.py +32 -0
- wbcore/contrib/notifications/models/notification_types.py +67 -24
- wbcore/contrib/notifications/serializers/notification_types.py +16 -1
- wbcore/contrib/notifications/tests/test_models/test_tokens.py +8 -0
- wbcore/contrib/notifications/tests/test_serializers/test_notification_types.py +5 -0
- wbcore/contrib/notifications/tests/test_viewsets/test_notification_types.py +3 -5
- wbcore/contrib/notifications/utils.py +3 -2
- wbcore/contrib/notifications/viewsets/configs/notification_types.py +28 -6
- wbcore/contrib/notifications/viewsets/menus.py +1 -1
- wbcore/contrib/notifications/viewsets/notification_types.py +12 -2
- wbcore/contrib/pandas/fields.py +38 -10
- wbcore/contrib/pandas/filters.py +4 -1
- wbcore/contrib/pandas/filterset.py +8 -7
- wbcore/contrib/pandas/tests/test_fields/test_number_fields.py +2 -7
- wbcore/contrib/pandas/utils.py +1 -1
- wbcore/contrib/pandas/views.py +14 -13
- wbcore/contrib/tags/models/tags.py +4 -1
- wbcore/contrib/workflow/factories/display.py +2 -2
- wbcore/contrib/workflow/factories/transition.py +16 -15
- wbcore/contrib/workflow/locale/de/LC_MESSAGES/django.po +457 -566
- wbcore/contrib/workflow/locale/de/LC_MESSAGES/django.po.translated +1326 -0
- wbcore/contrib/workflow/locale/en/LC_MESSAGES/django.po +1102 -0
- wbcore/contrib/workflow/locale/fr/LC_MESSAGES/django.po +1114 -0
- wbcore/contrib/workflow/models/data.py +7 -4
- wbcore/contrib/workflow/models/process.py +2 -2
- wbcore/contrib/workflow/models/step.py +57 -15
- wbcore/contrib/workflow/serializers/data.py +8 -8
- wbcore/contrib/workflow/serializers/process.py +3 -2
- wbcore/contrib/workflow/tests/conftest.py +224 -0
- wbcore/contrib/workflow/tests/test_dispatch.py +82 -77
- wbcore/contrib/workflow/tests/test_displays.py +10 -88
- wbcore/contrib/workflow/tests/test_filters.py +57 -40
- wbcore/contrib/workflow/tests/test_models/step/test_decision_step.py +71 -68
- wbcore/contrib/workflow/tests/test_models/step/test_email_step.py +78 -38
- wbcore/contrib/workflow/tests/test_models/step/test_finish_step.py +152 -90
- wbcore/contrib/workflow/tests/test_models/step/test_join_step.py +100 -110
- wbcore/contrib/workflow/tests/test_models/step/test_step.py +168 -33
- wbcore/contrib/workflow/tests/test_models/test_condition.py +1 -1
- wbcore/contrib/workflow/tests/test_models/test_workflow.py +3 -3
- wbcore/contrib/workflow/tests/test_serializers.py +172 -150
- wbcore/contrib/workflow/tests/test_viewsets.py +264 -323
- wbcore/contrib/workflow/tests/test_workflow_assignees.py +215 -205
- wbcore/contrib/workflow/viewsets/process.py +4 -1
- wbcore/contrib/workflow/workflows/assignees.py +12 -7
- wbcore/dynamic_preferences_registry.py +102 -0
- wbcore/enums.py +2 -51
- wbcore/filters/fields/choices.py +4 -6
- wbcore/filters/fields/content_type.py +15 -4
- wbcore/filters/fields/datetime.py +50 -25
- wbcore/filters/fields/models.py +18 -9
- wbcore/filters/fields/numbers.py +9 -8
- wbcore/filters/filterset.py +27 -6
- wbcore/filters/mixins.py +41 -42
- wbcore/forms.py +6 -6
- wbcore/fsm/markdown_extensions.py +1 -1
- wbcore/fsm/mixins.py +20 -6
- wbcore/locale/de/LC_MESSAGES/django.po +982 -397
- wbcore/locale/de/LC_MESSAGES/django.po.translated +1580 -0
- wbcore/locale/en/LC_MESSAGES/django.po +1234 -0
- wbcore/locale/fr/LC_MESSAGES/django.po +1235 -0
- wbcore/markdown/models.py +8 -5
- wbcore/markdown/views.py +1 -1
- wbcore/menus/menus.py +2 -2
- wbcore/metadata/configs/buttons/bases.py +10 -7
- wbcore/metadata/configs/buttons/buttons.py +2 -1
- wbcore/metadata/configs/buttons/enums.py +50 -0
- wbcore/metadata/configs/buttons/view_config.py +13 -46
- wbcore/metadata/configs/display/display.py +2 -2
- wbcore/metadata/configs/display/formatting.py +6 -9
- wbcore/metadata/configs/display/instance_display/display.py +5 -2
- wbcore/metadata/configs/display/instance_display/pages.py +1 -1
- wbcore/metadata/configs/display/instance_display/shortcuts.py +1 -1
- wbcore/metadata/configs/display/list_display.py +54 -40
- wbcore/metadata/configs/display/models.py +6 -0
- wbcore/metadata/configs/display/view_config.py +11 -9
- wbcore/metadata/configs/endpoints.py +11 -4
- wbcore/metadata/configs/fields.py +6 -1
- wbcore/metadata/configs/filter_fields.py +12 -13
- wbcore/metadata/configs/identifiers.py +3 -1
- wbcore/metadata/tests/test_buttons.py +13 -16
- wbcore/models/fields.py +2 -2
- wbcore/pagination.py +1 -2
- wbcore/permissions/permissions.py +2 -2
- wbcore/permissions/utils.py +2 -2
- wbcore/release_notes/display.py +2 -8
- wbcore/release_notes/serializers.py +2 -9
- wbcore/release_notes/viewsets.py +8 -2
- wbcore/reversion/viewsets/titles.py +4 -3
- wbcore/serializers/__init__.py +2 -0
- wbcore/serializers/fields/__init__.py +2 -1
- wbcore/serializers/fields/boolean.py +1 -1
- wbcore/serializers/fields/choice.py +28 -4
- wbcore/serializers/fields/datetime.py +45 -36
- wbcore/serializers/fields/fields.py +1 -1
- wbcore/serializers/fields/fsm.py +1 -1
- wbcore/serializers/fields/list.py +2 -5
- wbcore/serializers/fields/mixins.py +24 -11
- wbcore/serializers/fields/number.py +6 -23
- wbcore/serializers/fields/other.py +2 -10
- wbcore/serializers/fields/related.py +4 -6
- wbcore/serializers/fields/text.py +1 -1
- wbcore/serializers/fields/types.py +2 -0
- wbcore/serializers/serializers.py +12 -3
- wbcore/signals/__init__.py +1 -0
- wbcore/signals/clone.py +4 -0
- wbcore/signals/models.py +2 -6
- wbcore/tasks.py +2 -2
- wbcore/templates/wbcore/email_base_template.html +3 -3
- wbcore/test/e2e_helpers_methods/e2e_checks.py +10 -4
- wbcore/test/e2e_helpers_methods/e2e_helper_methods.py +4 -2
- wbcore/test/mixins.py +52 -102
- wbcore/test/tests.py +6 -9
- wbcore/test/utils.py +3 -4
- wbcore/tests/e2e/test_e2e.py +2 -2
- wbcore/tests/test_cache/test_decorators.py +4 -7
- wbcore/tests/test_configs.py +2 -5
- wbcore/tests/test_enums.py +2 -1
- wbcore/tests/test_fields/test_choice_fields.py +9 -1
- wbcore/tests/test_fields/test_number_fields.py +7 -15
- wbcore/tests/test_fields/test_other_fields.py +1 -2
- wbcore/tests/test_filters/test_mixins.py +35 -35
- wbcore/tests/test_list_display.py +0 -2
- wbcore/tests/test_models/test_mixins.py +1 -1
- wbcore/tests/test_utils/test_date.py +1 -1
- wbcore/tests/test_utils/test_date_builder.py +25 -1
- wbcore/tests/test_utils/test_primary.py +1 -1
- wbcore/urls.py +4 -0
- wbcore/utils/date.py +18 -2
- wbcore/utils/figures.py +2 -2
- wbcore/utils/models.py +21 -4
- wbcore/utils/reportlab.py +7 -0
- wbcore/utils/rrules.py +3 -1
- wbcore/utils/string_loader.py +1 -1
- wbcore/utils/strings.py +3 -3
- wbcore/utils/views.py +8 -3
- wbcore/viewsets/mixins.py +9 -4
- {wbcore-1.46.0.dist-info → wbcore-1.58.2.dist-info}/METADATA +9 -5
- {wbcore-1.46.0.dist-info → wbcore-1.58.2.dist-info}/RECORD +317 -271
- wbcore/contrib/geography/tests/test_serializers.py +0 -7
- wbcore/contrib/geography/tests/tests.py +0 -13
- wbcore/contrib/io/tests/tests.py +0 -19
- wbcore/contrib/workflow/tests/tests.py +0 -25
- {wbcore-1.46.0.dist-info → wbcore-1.58.2.dist-info}/WHEEL +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from typing import Iterable
|
|
2
2
|
|
|
3
|
+
from celery import shared_task
|
|
3
4
|
from django.conf import settings
|
|
4
5
|
from django.contrib.auth import get_user_model
|
|
5
6
|
from django.db import transaction
|
|
@@ -43,22 +44,32 @@ def send_notification(
|
|
|
43
44
|
if isinstance(users, User):
|
|
44
45
|
users = [users]
|
|
45
46
|
for user in users:
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
user
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
notification_type = NotificationType.objects.get(code=code)
|
|
48
|
+
if (
|
|
49
|
+
user.is_active
|
|
50
|
+
and NotificationTypeSetting.objects.filter(notification_type=notification_type, user=user).exists()
|
|
51
|
+
):
|
|
51
52
|
if not endpoint:
|
|
52
53
|
endpoint = reverse(reverse_name, reverse_args, reverse_kwargs) if reverse_name else None
|
|
53
54
|
notification = Notification.objects.create(
|
|
54
55
|
title=title,
|
|
55
56
|
body=body,
|
|
56
57
|
user=user,
|
|
57
|
-
notification_type=
|
|
58
|
+
notification_type=notification_type,
|
|
58
59
|
endpoint=endpoint,
|
|
59
60
|
sent=timezone.now(),
|
|
60
61
|
)
|
|
61
|
-
transaction.on_commit(
|
|
62
|
+
transaction.on_commit(
|
|
63
|
+
lambda notification_pk=notification.pk: send_notification_task.delay(notification_pk)
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@shared_task()
|
|
68
|
+
def send_notification_as_task(code, title, body, user_id, **kwargs):
|
|
69
|
+
if not isinstance(user_id, list):
|
|
70
|
+
user_id = [user_id]
|
|
71
|
+
user = User.objects.filter(id__in=user_id)
|
|
72
|
+
send_notification(code, title, body, user, **kwargs)
|
|
62
73
|
|
|
63
74
|
|
|
64
75
|
@receiver(handle_widget_sharing)
|
|
@@ -1,60 +1,66 @@
|
|
|
1
|
-
#
|
|
1
|
+
# SOME DESCRIPTIVE TITLE.
|
|
2
2
|
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
|
3
3
|
# This file is distributed under the same license as the PACKAGE package.
|
|
4
4
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
|
5
5
|
#
|
|
6
|
+
# Translators:
|
|
7
|
+
# Kevin Decoster, 2025
|
|
8
|
+
#
|
|
9
|
+
#, fuzzy
|
|
6
10
|
msgid ""
|
|
7
11
|
msgstr ""
|
|
8
|
-
"Project-Id-Version: \n"
|
|
12
|
+
"Project-Id-Version: PACKAGE VERSION\n"
|
|
9
13
|
"Report-Msgid-Bugs-To: \n"
|
|
10
|
-
"POT-Creation-Date:
|
|
11
|
-
"PO-Revision-Date:
|
|
12
|
-
"Last-Translator: \n"
|
|
13
|
-
"Language-Team: \n"
|
|
14
|
-
"Language: de\n"
|
|
14
|
+
"POT-Creation-Date: 2025-05-30 11:37+0200\n"
|
|
15
|
+
"PO-Revision-Date: 2025-05-30 09:40+0000\n"
|
|
16
|
+
"Last-Translator: Kevin Decoster, 2025\n"
|
|
17
|
+
"Language-Team: German (https://app.transifex.com/stainly/teams/171242/de/)\n"
|
|
15
18
|
"MIME-Version: 1.0\n"
|
|
16
19
|
"Content-Type: text/plain; charset=UTF-8\n"
|
|
17
20
|
"Content-Transfer-Encoding: 8bit\n"
|
|
21
|
+
"Language: de\n"
|
|
18
22
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
19
|
-
"X-Generator: Poedit 3.2.2\n"
|
|
20
23
|
|
|
21
|
-
#:
|
|
24
|
+
#: contrib/notifications/dispatch.py:72
|
|
25
|
+
msgid "{} shared a widget with you"
|
|
26
|
+
msgstr ""
|
|
27
|
+
|
|
28
|
+
#: contrib/notifications/templates/notifications/notification_template.html:28
|
|
22
29
|
msgid "Open"
|
|
23
30
|
msgstr "Öffnen"
|
|
24
31
|
|
|
25
|
-
#:
|
|
32
|
+
#: contrib/notifications/viewsets/configs/notifications.py:27
|
|
26
33
|
msgid "Reading all notifications"
|
|
27
34
|
msgstr "Lesen aller Benachrichtigungen"
|
|
28
35
|
|
|
29
|
-
#:
|
|
36
|
+
#: contrib/notifications/viewsets/configs/notifications.py:29
|
|
30
37
|
msgid "Do you want to mark notifications as read?"
|
|
31
38
|
msgstr "Möchten Sie alle Benachrichtigungen als gelesen markieren?"
|
|
32
39
|
|
|
33
|
-
#:
|
|
40
|
+
#: contrib/notifications/viewsets/configs/notifications.py:30
|
|
34
41
|
msgid "Mark all read"
|
|
35
42
|
msgstr "Alle als gelesen markieren"
|
|
36
43
|
|
|
37
|
-
#:
|
|
44
|
+
#: contrib/notifications/viewsets/configs/notifications.py:37
|
|
38
45
|
msgid "Deleting all read notifications"
|
|
39
46
|
msgstr "Löschen aller gelesenen Benachrichtigungen"
|
|
40
47
|
|
|
41
|
-
#:
|
|
48
|
+
#: contrib/notifications/viewsets/configs/notifications.py:39
|
|
42
49
|
msgid "Do you want delete all read notifications?"
|
|
43
50
|
msgstr "Möchten Sie alle gelesenen Benachrichtigungen löschen?"
|
|
44
51
|
|
|
45
|
-
#:
|
|
52
|
+
#: contrib/notifications/viewsets/configs/notifications.py:40
|
|
46
53
|
msgid "Delete all read"
|
|
47
54
|
msgstr "Alle gelesenen löschen"
|
|
48
55
|
|
|
49
|
-
#:
|
|
50
|
-
#: wbcore/contrib/notifications/viewsets/configs/notifications.py:41
|
|
56
|
+
#: contrib/notifications/viewsets/configs/notifications.py:48
|
|
51
57
|
msgid "Open Resource"
|
|
52
58
|
msgstr "Ressource Öffnen"
|
|
53
59
|
|
|
54
|
-
#:
|
|
60
|
+
#: contrib/notifications/viewsets/menus.py:6
|
|
55
61
|
msgid "Notification Types"
|
|
56
62
|
msgstr "Benachrichtigungstypen"
|
|
57
63
|
|
|
58
|
-
#:
|
|
64
|
+
#: contrib/notifications/viewsets/menus.py:12
|
|
59
65
|
msgid "Notifications"
|
|
60
66
|
msgstr "Benachrichtigungen"
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# GERMAN TRANSLATIONS FOR NOTIFICATION
|
|
2
|
+
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
|
3
|
+
# This file is distributed under the same license as the PACKAGE package.
|
|
4
|
+
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
|
5
|
+
#
|
|
6
|
+
msgid ""
|
|
7
|
+
msgstr ""
|
|
8
|
+
"Project-Id-Version: \n"
|
|
9
|
+
"Report-Msgid-Bugs-To: \n"
|
|
10
|
+
"POT-Creation-Date: 2025-05-20 09:30+0200\n"
|
|
11
|
+
"PO-Revision-Date: 2023-04-25 17:03+0200\n"
|
|
12
|
+
"Last-Translator: \n"
|
|
13
|
+
"Language-Team: \n"
|
|
14
|
+
"Language: de\n"
|
|
15
|
+
"MIME-Version: 1.0\n"
|
|
16
|
+
"Content-Type: text/plain; charset=UTF-8\n"
|
|
17
|
+
"Content-Transfer-Encoding: 8bit\n"
|
|
18
|
+
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
19
|
+
"X-Generator: Poedit 3.2.2\n"
|
|
20
|
+
|
|
21
|
+
#: wbcore/contrib/notifications/dispatch.py:72
|
|
22
|
+
msgid "{} shared a widget with you"
|
|
23
|
+
msgstr ""
|
|
24
|
+
|
|
25
|
+
#: wbcore/contrib/notifications/templates/notifications/notification_template.html:28
|
|
26
|
+
msgid "Open"
|
|
27
|
+
msgstr "Öffnen"
|
|
28
|
+
|
|
29
|
+
#: wbcore/contrib/notifications/viewsets/configs/notifications.py:27
|
|
30
|
+
msgid "Reading all notifications"
|
|
31
|
+
msgstr "Lesen aller Benachrichtigungen"
|
|
32
|
+
|
|
33
|
+
#: wbcore/contrib/notifications/viewsets/configs/notifications.py:29
|
|
34
|
+
msgid "Do you want to mark notifications as read?"
|
|
35
|
+
msgstr "Möchten Sie alle Benachrichtigungen als gelesen markieren?"
|
|
36
|
+
|
|
37
|
+
#: wbcore/contrib/notifications/viewsets/configs/notifications.py:30
|
|
38
|
+
msgid "Mark all read"
|
|
39
|
+
msgstr "Alle als gelesen markieren"
|
|
40
|
+
|
|
41
|
+
#: wbcore/contrib/notifications/viewsets/configs/notifications.py:37
|
|
42
|
+
msgid "Deleting all read notifications"
|
|
43
|
+
msgstr "Löschen aller gelesenen Benachrichtigungen"
|
|
44
|
+
|
|
45
|
+
#: wbcore/contrib/notifications/viewsets/configs/notifications.py:39
|
|
46
|
+
msgid "Do you want delete all read notifications?"
|
|
47
|
+
msgstr "Möchten Sie alle gelesenen Benachrichtigungen löschen?"
|
|
48
|
+
|
|
49
|
+
#: wbcore/contrib/notifications/viewsets/configs/notifications.py:40
|
|
50
|
+
msgid "Delete all read"
|
|
51
|
+
msgstr "Alle gelesenen löschen"
|
|
52
|
+
|
|
53
|
+
#: wbcore/contrib/notifications/viewsets/configs/notifications.py:48
|
|
54
|
+
msgid "Open Resource"
|
|
55
|
+
msgstr "Ressource Öffnen"
|
|
56
|
+
|
|
57
|
+
#: wbcore/contrib/notifications/viewsets/menus.py:6
|
|
58
|
+
msgid "Notification Types"
|
|
59
|
+
msgstr "Benachrichtigungstypen"
|
|
60
|
+
|
|
61
|
+
#: wbcore/contrib/notifications/viewsets/menus.py:12
|
|
62
|
+
msgid "Notifications"
|
|
63
|
+
msgstr "Benachrichtigungen"
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# SOME DESCRIPTIVE TITLE.
|
|
2
|
+
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
|
3
|
+
# This file is distributed under the same license as the PACKAGE package.
|
|
4
|
+
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
|
5
|
+
#
|
|
6
|
+
msgid ""
|
|
7
|
+
msgstr ""
|
|
8
|
+
"Project-Id-Version: PACKAGE VERSION\n"
|
|
9
|
+
"Report-Msgid-Bugs-To: \n"
|
|
10
|
+
"POT-Creation-Date: 2025-05-30 11:37+0200\n"
|
|
11
|
+
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
|
12
|
+
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
|
13
|
+
"Language-Team: LANGUAGE <LL@li.org>\n"
|
|
14
|
+
"Language: \n"
|
|
15
|
+
"MIME-Version: 1.0\n"
|
|
16
|
+
"Content-Type: text/plain; charset=UTF-8\n"
|
|
17
|
+
"Content-Transfer-Encoding: 8bit\n"
|
|
18
|
+
|
|
19
|
+
#: contrib/notifications/dispatch.py:72
|
|
20
|
+
msgid "{} shared a widget with you"
|
|
21
|
+
msgstr ""
|
|
22
|
+
|
|
23
|
+
#: contrib/notifications/templates/notifications/notification_template.html:28
|
|
24
|
+
msgid "Open"
|
|
25
|
+
msgstr ""
|
|
26
|
+
|
|
27
|
+
#: contrib/notifications/viewsets/configs/notifications.py:27
|
|
28
|
+
msgid "Reading all notifications"
|
|
29
|
+
msgstr ""
|
|
30
|
+
|
|
31
|
+
#: contrib/notifications/viewsets/configs/notifications.py:29
|
|
32
|
+
msgid "Do you want to mark notifications as read?"
|
|
33
|
+
msgstr ""
|
|
34
|
+
|
|
35
|
+
#: contrib/notifications/viewsets/configs/notifications.py:30
|
|
36
|
+
msgid "Mark all read"
|
|
37
|
+
msgstr ""
|
|
38
|
+
|
|
39
|
+
#: contrib/notifications/viewsets/configs/notifications.py:37
|
|
40
|
+
msgid "Deleting all read notifications"
|
|
41
|
+
msgstr ""
|
|
42
|
+
|
|
43
|
+
#: contrib/notifications/viewsets/configs/notifications.py:39
|
|
44
|
+
msgid "Do you want delete all read notifications?"
|
|
45
|
+
msgstr ""
|
|
46
|
+
|
|
47
|
+
#: contrib/notifications/viewsets/configs/notifications.py:40
|
|
48
|
+
msgid "Delete all read"
|
|
49
|
+
msgstr ""
|
|
50
|
+
|
|
51
|
+
#: contrib/notifications/viewsets/configs/notifications.py:48
|
|
52
|
+
msgid "Open Resource"
|
|
53
|
+
msgstr ""
|
|
54
|
+
|
|
55
|
+
#: contrib/notifications/viewsets/menus.py:6
|
|
56
|
+
msgid "Notification Types"
|
|
57
|
+
msgstr ""
|
|
58
|
+
|
|
59
|
+
#: contrib/notifications/viewsets/menus.py:12
|
|
60
|
+
msgid "Notifications"
|
|
61
|
+
msgstr ""
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# SOME DESCRIPTIVE TITLE.
|
|
2
|
+
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
|
3
|
+
# This file is distributed under the same license as the PACKAGE package.
|
|
4
|
+
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
|
5
|
+
#
|
|
6
|
+
#, fuzzy
|
|
7
|
+
msgid ""
|
|
8
|
+
msgstr ""
|
|
9
|
+
"Project-Id-Version: PACKAGE VERSION\n"
|
|
10
|
+
"Report-Msgid-Bugs-To: \n"
|
|
11
|
+
"POT-Creation-Date: 2025-05-30 11:37+0200\n"
|
|
12
|
+
"PO-Revision-Date: 2025-05-30 09:40+0000\n"
|
|
13
|
+
"Language-Team: French (https://app.transifex.com/stainly/teams/171242/fr/)\n"
|
|
14
|
+
"MIME-Version: 1.0\n"
|
|
15
|
+
"Content-Type: text/plain; charset=UTF-8\n"
|
|
16
|
+
"Content-Transfer-Encoding: 8bit\n"
|
|
17
|
+
"Language: fr\n"
|
|
18
|
+
"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
|
|
19
|
+
|
|
20
|
+
#: contrib/notifications/dispatch.py:72
|
|
21
|
+
msgid "{} shared a widget with you"
|
|
22
|
+
msgstr ""
|
|
23
|
+
|
|
24
|
+
#: contrib/notifications/templates/notifications/notification_template.html:28
|
|
25
|
+
msgid "Open"
|
|
26
|
+
msgstr ""
|
|
27
|
+
|
|
28
|
+
#: contrib/notifications/viewsets/configs/notifications.py:27
|
|
29
|
+
msgid "Reading all notifications"
|
|
30
|
+
msgstr ""
|
|
31
|
+
|
|
32
|
+
#: contrib/notifications/viewsets/configs/notifications.py:29
|
|
33
|
+
msgid "Do you want to mark notifications as read?"
|
|
34
|
+
msgstr ""
|
|
35
|
+
|
|
36
|
+
#: contrib/notifications/viewsets/configs/notifications.py:30
|
|
37
|
+
msgid "Mark all read"
|
|
38
|
+
msgstr ""
|
|
39
|
+
|
|
40
|
+
#: contrib/notifications/viewsets/configs/notifications.py:37
|
|
41
|
+
msgid "Deleting all read notifications"
|
|
42
|
+
msgstr ""
|
|
43
|
+
|
|
44
|
+
#: contrib/notifications/viewsets/configs/notifications.py:39
|
|
45
|
+
msgid "Do you want delete all read notifications?"
|
|
46
|
+
msgstr ""
|
|
47
|
+
|
|
48
|
+
#: contrib/notifications/viewsets/configs/notifications.py:40
|
|
49
|
+
msgid "Delete all read"
|
|
50
|
+
msgstr ""
|
|
51
|
+
|
|
52
|
+
#: contrib/notifications/viewsets/configs/notifications.py:48
|
|
53
|
+
msgid "Open Resource"
|
|
54
|
+
msgstr ""
|
|
55
|
+
|
|
56
|
+
#: contrib/notifications/viewsets/menus.py:6
|
|
57
|
+
msgid "Notification Types"
|
|
58
|
+
msgstr ""
|
|
59
|
+
|
|
60
|
+
#: contrib/notifications/viewsets/menus.py:12
|
|
61
|
+
msgid "Notifications"
|
|
62
|
+
msgstr ""
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Generated by Django 5.0.13 on 2025-03-13 12:50
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
('notifications', '0007_notificationtype_resource_button_label'),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.AddField(
|
|
14
|
+
model_name='notificationtype',
|
|
15
|
+
name='is_lock',
|
|
16
|
+
field=models.BooleanField(default=False),
|
|
17
|
+
),
|
|
18
|
+
]
|
wbcore/contrib/notifications/migrations/0009_alter_notificationtypesetting_options_and_more.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Generated by Django 5.0.14 on 2025-05-21 11:05
|
|
2
|
+
|
|
3
|
+
from django.conf import settings
|
|
4
|
+
from django.db import migrations, models
|
|
5
|
+
from django.db.models import Count
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def handle_duplicates(apps, schema_editor):
|
|
9
|
+
NotificationTypeSetting = apps.get_model("notifications", "NotificationTypeSetting")
|
|
10
|
+
for row in NotificationTypeSetting.objects.values('user', 'notification_type').annotate(c=Count("*")).filter(c__gt=1):
|
|
11
|
+
duplicates = NotificationTypeSetting.objects.filter(user=row['user'], notification_type=row['notification_type'])
|
|
12
|
+
for duplicate in duplicates[1:]:
|
|
13
|
+
duplicate.delete()
|
|
14
|
+
|
|
15
|
+
class Migration(migrations.Migration):
|
|
16
|
+
|
|
17
|
+
dependencies = [
|
|
18
|
+
('notifications', '0008_notificationtype_is_lock'),
|
|
19
|
+
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
operations = [
|
|
23
|
+
migrations.RunPython(handle_duplicates),
|
|
24
|
+
migrations.AlterModelOptions(
|
|
25
|
+
name='notificationtypesetting',
|
|
26
|
+
options={'verbose_name': 'Notification Type Setting', 'verbose_name_plural': 'Notification Type Settings'},
|
|
27
|
+
),
|
|
28
|
+
migrations.AddConstraint(
|
|
29
|
+
model_name='notificationtypesetting',
|
|
30
|
+
constraint=models.UniqueConstraint(fields=('user', 'notification_type'), name='unique_notification_setting'),
|
|
31
|
+
),
|
|
32
|
+
]
|
|
@@ -2,6 +2,7 @@ from contextlib import suppress
|
|
|
2
2
|
|
|
3
3
|
from django.contrib.auth import get_user_model
|
|
4
4
|
from django.db import models
|
|
5
|
+
from django.db.models import UniqueConstraint
|
|
5
6
|
from django.db.models.signals import post_save
|
|
6
7
|
from django.dispatch import receiver
|
|
7
8
|
from guardian.utils import get_anonymous_user
|
|
@@ -23,6 +24,7 @@ class NotificationType(WBModel):
|
|
|
23
24
|
default_enable_web = models.BooleanField(default=False)
|
|
24
25
|
default_enable_mobile = models.BooleanField(default=False)
|
|
25
26
|
default_enable_email = models.BooleanField(default=False)
|
|
27
|
+
is_lock = models.BooleanField(default=False)
|
|
26
28
|
|
|
27
29
|
def __str__(self) -> str:
|
|
28
30
|
return f"{self.title}"
|
|
@@ -71,6 +73,24 @@ class NotificationTypeSetting(WBModel):
|
|
|
71
73
|
def __str__(self) -> str:
|
|
72
74
|
return f"{self.user}: {self.notification_type} ({self.enable_web}/{self.enable_mobile}/{self.enable_email})"
|
|
73
75
|
|
|
76
|
+
class Meta:
|
|
77
|
+
verbose_name = "Notification Type Setting"
|
|
78
|
+
verbose_name_plural = "Notification Type Settings"
|
|
79
|
+
constraints = [
|
|
80
|
+
UniqueConstraint(
|
|
81
|
+
name="unique_notification_setting",
|
|
82
|
+
fields=["user", "notification_type"],
|
|
83
|
+
)
|
|
84
|
+
]
|
|
85
|
+
|
|
86
|
+
def save(self, *args, **kwargs):
|
|
87
|
+
if self.notification_type.is_lock:
|
|
88
|
+
self.enable_web = self.notification_type.default_enable_web
|
|
89
|
+
self.enable_mobile = self.notification_type.default_enable_mobile
|
|
90
|
+
self.enable_email = self.notification_type.default_enable_email
|
|
91
|
+
|
|
92
|
+
super().save(*args, **kwargs)
|
|
93
|
+
|
|
74
94
|
@classmethod
|
|
75
95
|
def get_endpoint_basename(cls):
|
|
76
96
|
return "wbcore:notifications:notification_type_setting"
|
|
@@ -91,32 +111,55 @@ class NotificationTypeSetting(WBModel):
|
|
|
91
111
|
@receiver(post_save, sender="notifications.NotificationType")
|
|
92
112
|
def post_save_notification_type(instance, **kwargs):
|
|
93
113
|
anonymous_user = get_anonymous_user()
|
|
114
|
+
|
|
115
|
+
objs = []
|
|
94
116
|
for user in get_user_model().objects.filter(~models.Q(pk=anonymous_user.pk)):
|
|
95
|
-
|
|
96
|
-
notification_type=instance
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
117
|
+
try:
|
|
118
|
+
existing_setting = NotificationTypeSetting.objects.get(user=user, notification_type=instance)
|
|
119
|
+
enable_web = existing_setting.enable_web if not instance.is_lock else instance.default_enable_web
|
|
120
|
+
enable_mobile = existing_setting.enable_mobile if not instance.is_lock else instance.default_enable_mobile
|
|
121
|
+
enable_email = existing_setting.enable_email if not instance.is_lock else instance.default_enable_email
|
|
122
|
+
except NotificationTypeSetting.DoesNotExist:
|
|
123
|
+
enable_web = instance.default_enable_web
|
|
124
|
+
enable_mobile = instance.default_enable_mobile
|
|
125
|
+
enable_email = instance.default_enable_email
|
|
126
|
+
|
|
127
|
+
objs.append(
|
|
128
|
+
NotificationTypeSetting(
|
|
129
|
+
notification_type=instance,
|
|
130
|
+
user=user,
|
|
131
|
+
enable_web=enable_web,
|
|
132
|
+
enable_mobile=enable_mobile,
|
|
133
|
+
enable_email=enable_email,
|
|
134
|
+
)
|
|
135
|
+
)
|
|
136
|
+
if objs:
|
|
137
|
+
NotificationTypeSetting.objects.bulk_create(
|
|
138
|
+
objs,
|
|
139
|
+
unique_fields=["notification_type", "user"],
|
|
140
|
+
update_fields=["enable_web", "enable_mobile", "enable_email"],
|
|
141
|
+
update_conflicts=True,
|
|
103
142
|
)
|
|
104
143
|
|
|
105
144
|
|
|
106
145
|
@receiver(post_save, sender=get_user_model())
|
|
107
|
-
def post_save_user(instance, **kwargs):
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
146
|
+
def post_save_user(sender, instance, created, raw, **kwargs):
|
|
147
|
+
if created:
|
|
148
|
+
with suppress(get_user_model().DoesNotExist):
|
|
149
|
+
anonymous_user = get_anonymous_user()
|
|
150
|
+
if instance.pk == anonymous_user.pk:
|
|
151
|
+
return
|
|
152
|
+
|
|
153
|
+
objs = []
|
|
154
|
+
for notification_type in NotificationType.objects.all():
|
|
155
|
+
objs.append(
|
|
156
|
+
NotificationTypeSetting(
|
|
157
|
+
notification_type=notification_type,
|
|
158
|
+
user=instance,
|
|
159
|
+
enable_web=notification_type.default_enable_web,
|
|
160
|
+
enable_mobile=notification_type.default_enable_mobile,
|
|
161
|
+
enable_email=notification_type.default_enable_email,
|
|
162
|
+
)
|
|
163
|
+
)
|
|
164
|
+
if objs:
|
|
165
|
+
NotificationTypeSetting.objects.bulk_create(objs, unique_fields=["notification_type", "user"])
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from rest_framework.reverse import reverse
|
|
2
|
+
|
|
1
3
|
from wbcore import serializers
|
|
2
4
|
from wbcore.contrib.notifications.models import (
|
|
3
5
|
NotificationType,
|
|
@@ -19,9 +21,19 @@ class NotificationTypeRepresentationSerializer(serializers.RepresentationSeriali
|
|
|
19
21
|
class NotificationTypeSettingModelSerializer(serializers.ModelSerializer):
|
|
20
22
|
_notification_type = NotificationTypeRepresentationSerializer(source="notification_type")
|
|
21
23
|
help_text = serializers.CharField()
|
|
24
|
+
locked_icon = serializers.IconSelectField(read_only=True)
|
|
25
|
+
locked = serializers.BooleanField(read_only=True)
|
|
26
|
+
_update_url = serializers.SerializerMethodField()
|
|
27
|
+
|
|
28
|
+
def get__update_url(self, obj):
|
|
29
|
+
if not obj.notification_type.is_lock:
|
|
30
|
+
return reverse(
|
|
31
|
+
"wbcore:notifications:notification_type_setting-list", args=[], request=self.context["request"]
|
|
32
|
+
)
|
|
33
|
+
return None
|
|
22
34
|
|
|
23
35
|
class Meta:
|
|
24
|
-
read_only_fields = ("user", "notification_type")
|
|
36
|
+
read_only_fields = ("user", "notification_type", "help_text")
|
|
25
37
|
model = NotificationTypeSetting
|
|
26
38
|
fields = (
|
|
27
39
|
"id",
|
|
@@ -32,5 +44,8 @@ class NotificationTypeSettingModelSerializer(serializers.ModelSerializer):
|
|
|
32
44
|
"enable_web",
|
|
33
45
|
"enable_mobile",
|
|
34
46
|
"enable_email",
|
|
47
|
+
"locked",
|
|
48
|
+
"locked_icon",
|
|
35
49
|
"_additional_resources",
|
|
50
|
+
"_update_url",
|
|
36
51
|
)
|
|
@@ -19,4 +19,12 @@ class TestNotificationUserToken:
|
|
|
19
19
|
setting = NotificationTypeSettingModelFactory(
|
|
20
20
|
user=notification_user_token.user, enable_web=True, enable_mobile=True
|
|
21
21
|
)
|
|
22
|
+
assert setting.enable_web is False
|
|
23
|
+
assert setting.enable_mobile is False
|
|
24
|
+
assert not NotificationUserToken.objects.filter_for_user_settings(setting).exists()
|
|
25
|
+
|
|
26
|
+
setting.enable_web = True
|
|
27
|
+
setting.enable_mobile = True
|
|
28
|
+
setting.save()
|
|
29
|
+
|
|
22
30
|
assert NotificationUserToken.objects.filter_for_user_settings(setting).first() == notification_user_token # type: ignore
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import pytest
|
|
2
|
+
from rest_framework.reverse import reverse
|
|
2
3
|
|
|
3
4
|
from wbcore.contrib.notifications.serializers import (
|
|
4
5
|
NotificationTypeRepresentationSerializer,
|
|
@@ -40,6 +41,10 @@ class TestNotificationTypeSettingModelSerializer:
|
|
|
40
41
|
"enable_mobile": notification_type_setting.enable_mobile,
|
|
41
42
|
"enable_email": notification_type_setting.enable_email,
|
|
42
43
|
"_additional_resources": {},
|
|
44
|
+
"_update_url": reverse(
|
|
45
|
+
"wbcore:notifications:notification_type_setting-list", args=[], request=request_with_user
|
|
46
|
+
),
|
|
47
|
+
"locked_icon": None,
|
|
43
48
|
}
|
|
44
49
|
|
|
45
50
|
def test_deserialize_partial_instance(self, notification_type_setting, request_with_user):
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import pytest
|
|
2
2
|
from rest_framework.reverse import reverse
|
|
3
3
|
|
|
4
|
-
from wbcore.contrib.authentication.factories import UserFactory
|
|
4
|
+
from wbcore.contrib.authentication.factories import InternalUserFactory, UserFactory
|
|
5
5
|
from wbcore.contrib.notifications.factories.notification_types import (
|
|
6
6
|
NotificationTypeModelFactory,
|
|
7
7
|
)
|
|
@@ -110,11 +110,9 @@ class TestNotificationTypeSettingModelViewSet:
|
|
|
110
110
|
)
|
|
111
111
|
def test_change_setting_from_other_user(self, notification_type_setting, client, user, status_code):
|
|
112
112
|
"""Regardless of permission, no user should ever be able to change a setting from a different user"""
|
|
113
|
-
|
|
114
|
-
notification_type_setting.user = user2
|
|
115
|
-
notification_type_setting.save()
|
|
113
|
+
other_user = InternalUserFactory(is_superuser=True)
|
|
116
114
|
|
|
117
|
-
client.force_authenticate(
|
|
115
|
+
client.force_authenticate(other_user)
|
|
118
116
|
response = client.patch(
|
|
119
117
|
reverse("wbcore:notifications:notification_type_setting-detail", args=[notification_type_setting.id]),
|
|
120
118
|
{"enable_web": True},
|
|
@@ -22,5 +22,6 @@ def create_notification_type(
|
|
|
22
22
|
mobile: bool = True,
|
|
23
23
|
email: bool = False,
|
|
24
24
|
resource_button_label: str = "",
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
is_lock: bool = False, # set to true if user cannot modified the preference for this notification type
|
|
26
|
+
) -> tuple[str, str, str, bool, bool, bool, str, bool]:
|
|
27
|
+
return (code, title, help_text, web, mobile, email, resource_button_label, is_lock)
|
|
@@ -1,20 +1,34 @@
|
|
|
1
|
-
from wbcore.
|
|
1
|
+
from wbcore.contrib.icons import WBIcon
|
|
2
|
+
from wbcore.enums import Unit
|
|
3
|
+
from wbcore.metadata.configs.display import Field, Legend, LegendItem, ListDisplay
|
|
2
4
|
from wbcore.metadata.configs.display.instance_display import Display
|
|
3
5
|
from wbcore.metadata.configs.display.instance_display.shortcuts import (
|
|
4
6
|
create_simple_display,
|
|
5
7
|
)
|
|
6
8
|
from wbcore.metadata.configs.display.view_config import DisplayViewConfig
|
|
9
|
+
from wbcore.metadata.configs.endpoints import EndpointViewConfig
|
|
7
10
|
|
|
8
11
|
|
|
9
12
|
class NotificationTypeSettingDisplayConfig(DisplayViewConfig):
|
|
10
13
|
def get_list_display(self) -> ListDisplay:
|
|
11
14
|
return ListDisplay(
|
|
12
15
|
fields=[
|
|
13
|
-
Field(key="
|
|
14
|
-
Field(key="
|
|
15
|
-
Field(key="
|
|
16
|
-
Field(key="
|
|
17
|
-
Field(key="
|
|
16
|
+
Field(key="locked_icon", label=" ", width=Unit.PIXEL(40)),
|
|
17
|
+
Field(key="notification_type", label="Notification", width=Unit.PIXEL(250)),
|
|
18
|
+
Field(key="help_text", label="Help Text", width=Unit.PIXEL(500)),
|
|
19
|
+
Field(key="enable_web", label="Web", width=Unit.PIXEL(100)),
|
|
20
|
+
Field(key="enable_mobile", label="Mobile", width=Unit.PIXEL(100)),
|
|
21
|
+
Field(key="enable_email", label="E-Mail", width=Unit.PIXEL(100)),
|
|
22
|
+
],
|
|
23
|
+
legends=[
|
|
24
|
+
Legend(
|
|
25
|
+
items=[
|
|
26
|
+
LegendItem(
|
|
27
|
+
icon=WBIcon.LOCK.icon,
|
|
28
|
+
label="Locked",
|
|
29
|
+
),
|
|
30
|
+
],
|
|
31
|
+
)
|
|
18
32
|
],
|
|
19
33
|
)
|
|
20
34
|
|
|
@@ -25,3 +39,11 @@ class NotificationTypeSettingDisplayConfig(DisplayViewConfig):
|
|
|
25
39
|
["enable_web", "enable_mobile", "enable_email"],
|
|
26
40
|
]
|
|
27
41
|
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class NotificationTypeSettingEndpointConfig(EndpointViewConfig):
|
|
45
|
+
def get_endpoint(self, **kwargs):
|
|
46
|
+
return None
|
|
47
|
+
|
|
48
|
+
def get_update_endpoint(self):
|
|
49
|
+
return "{{_update_url}}"
|