wbcore 2.2.1__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/__init__.py +1 -0
- wbcore/admin.py +197 -0
- wbcore/apps.py +17 -0
- wbcore/cache/__init__.py +0 -0
- wbcore/cache/buttons.py +22 -0
- wbcore/cache/decorators.py +29 -0
- wbcore/cache/mixins.py +48 -0
- wbcore/cache/registry.py +90 -0
- wbcore/cache/views.py +18 -0
- wbcore/configs/__init__.py +11 -0
- wbcore/configs/configs.py +51 -0
- wbcore/configs/decorators.py +11 -0
- wbcore/configs/registry.py +35 -0
- wbcore/configs/views.py +11 -0
- wbcore/configurations/__init__.py +1 -0
- wbcore/configurations/base.py +45 -0
- wbcore/configurations/configurations/__init__.py +16 -0
- wbcore/configurations/configurations/apps.py +54 -0
- wbcore/configurations/configurations/authentication.py +43 -0
- wbcore/configurations/configurations/base.py +15 -0
- wbcore/configurations/configurations/cache.py +20 -0
- wbcore/configurations/configurations/celery.py +26 -0
- wbcore/configurations/configurations/i18nl10n.py +10 -0
- wbcore/configurations/configurations/mail.py +2 -0
- wbcore/configurations/configurations/maintenance.py +53 -0
- wbcore/configurations/configurations/media.py +22 -0
- wbcore/configurations/configurations/middleware.py +27 -0
- wbcore/configurations/configurations/network.py +19 -0
- wbcore/configurations/configurations/rest_framework.py +42 -0
- wbcore/configurations/configurations/static.py +28 -0
- wbcore/configurations/configurations/templates.py +17 -0
- wbcore/configurations/configurations/uvicorn.py +9 -0
- wbcore/configurations/configurations/wbcore.py +68 -0
- wbcore/content_type/__init__.py +0 -0
- wbcore/content_type/admin.py +8 -0
- wbcore/content_type/filters.py +19 -0
- wbcore/content_type/serializers.py +89 -0
- wbcore/content_type/utils.py +30 -0
- wbcore/content_type/viewsets.py +80 -0
- wbcore/contrib/__init__.py +0 -0
- wbcore/contrib/agenda/__init__.py +0 -0
- wbcore/contrib/agenda/admin/__init__.py +2 -0
- wbcore/contrib/agenda/admin/calendar_item.py +13 -0
- wbcore/contrib/agenda/admin/conference_room.py +18 -0
- wbcore/contrib/agenda/apps.py +6 -0
- wbcore/contrib/agenda/configurations.py +11 -0
- wbcore/contrib/agenda/factories/__init__.py +2 -0
- wbcore/contrib/agenda/factories/calendar_item.py +47 -0
- wbcore/contrib/agenda/factories/conference_room.py +19 -0
- wbcore/contrib/agenda/filters/__init__.py +2 -0
- wbcore/contrib/agenda/filters/calendar_item.py +64 -0
- wbcore/contrib/agenda/filters/conference_room.py +41 -0
- wbcore/contrib/agenda/migrations/0001_initial.py +84 -0
- wbcore/contrib/agenda/migrations/0002_initial.py +26 -0
- wbcore/contrib/agenda/migrations/0003_calendaritem_endpoint_basename.py +42 -0
- wbcore/contrib/agenda/migrations/0004_alter_calendaritem_item_type.py +17 -0
- wbcore/contrib/agenda/migrations/0005_building_and_more.py +94 -0
- wbcore/contrib/agenda/migrations/0006_calendaritem_is_deletable.py +17 -0
- wbcore/contrib/agenda/migrations/0007_alter_calendaritem_options.py +21 -0
- wbcore/contrib/agenda/migrations/0008_alter_calendaritem_item_type.py +17 -0
- wbcore/contrib/agenda/migrations/0009_alter_calendaritem_icon.py +18 -0
- wbcore/contrib/agenda/migrations/__init__.py +0 -0
- wbcore/contrib/agenda/models/__init__.py +2 -0
- wbcore/contrib/agenda/models/calendar_item.py +238 -0
- wbcore/contrib/agenda/models/conference_room.py +95 -0
- wbcore/contrib/agenda/release_notes/1_0_0.md +13 -0
- wbcore/contrib/agenda/release_notes/__init__.py +0 -0
- wbcore/contrib/agenda/serializers/__init__.py +10 -0
- wbcore/contrib/agenda/serializers/calendar_item.py +76 -0
- wbcore/contrib/agenda/serializers/conference_room.py +98 -0
- wbcore/contrib/agenda/signals.py +8 -0
- wbcore/contrib/agenda/tests/__init__.py +0 -0
- wbcore/contrib/agenda/tests/conftest.py +14 -0
- wbcore/contrib/agenda/tests/signals.py +16 -0
- wbcore/contrib/agenda/tests/test_models.py +34 -0
- wbcore/contrib/agenda/tests/test_viewsets.py +171 -0
- wbcore/contrib/agenda/tests/tests.py +25 -0
- wbcore/contrib/agenda/typings.py +19 -0
- wbcore/contrib/agenda/urls.py +25 -0
- wbcore/contrib/agenda/viewsets/__init__.py +13 -0
- wbcore/contrib/agenda/viewsets/buttons/__init__.py +1 -0
- wbcore/contrib/agenda/viewsets/buttons/conference_room.py +20 -0
- wbcore/contrib/agenda/viewsets/calendar_items.py +168 -0
- wbcore/contrib/agenda/viewsets/conference_room.py +48 -0
- wbcore/contrib/agenda/viewsets/display/__init__.py +2 -0
- wbcore/contrib/agenda/viewsets/display/calendar_items.py +17 -0
- wbcore/contrib/agenda/viewsets/display/conference_room.py +41 -0
- wbcore/contrib/agenda/viewsets/endpoints/__init__.py +1 -0
- wbcore/contrib/agenda/viewsets/endpoints/calendar_items.py +18 -0
- wbcore/contrib/agenda/viewsets/menu/__init__.py +2 -0
- wbcore/contrib/agenda/viewsets/menu/calendar_items.py +17 -0
- wbcore/contrib/agenda/viewsets/menu/conference_room.py +37 -0
- wbcore/contrib/agenda/viewsets/titles/__init__.py +2 -0
- wbcore/contrib/agenda/viewsets/titles/calendar_items.py +7 -0
- wbcore/contrib/agenda/viewsets/titles/conference_room.py +24 -0
- wbcore/contrib/ai/__init__.py +0 -0
- wbcore/contrib/ai/apps.py +5 -0
- wbcore/contrib/ai/exceptions.py +42 -0
- wbcore/contrib/ai/llm/__init__.py +0 -0
- wbcore/contrib/ai/llm/config.py +107 -0
- wbcore/contrib/ai/llm/decorators.py +10 -0
- wbcore/contrib/ai/llm/mixins.py +35 -0
- wbcore/contrib/ai/llm/utils.py +45 -0
- wbcore/contrib/authentication/__init__.py +9 -0
- wbcore/contrib/authentication/admin.py +247 -0
- wbcore/contrib/authentication/apps.py +14 -0
- wbcore/contrib/authentication/authentication.py +162 -0
- wbcore/contrib/authentication/configs.py +9 -0
- wbcore/contrib/authentication/configurations.py +53 -0
- wbcore/contrib/authentication/dynamic_preferences_registry.py +26 -0
- wbcore/contrib/authentication/factories/__init__.py +3 -0
- wbcore/contrib/authentication/factories/tokens.py +15 -0
- wbcore/contrib/authentication/factories/users.py +82 -0
- wbcore/contrib/authentication/factories/users_activities.py +19 -0
- wbcore/contrib/authentication/filters.py +18 -0
- wbcore/contrib/authentication/management/__init__.py +14 -0
- wbcore/contrib/authentication/migrations/0001_initial_squashed.py +174 -0
- wbcore/contrib/authentication/migrations/0002_profile.py +26 -0
- wbcore/contrib/authentication/migrations/0003_alter_user_profile.py +34 -0
- wbcore/contrib/authentication/migrations/0004_token.py +51 -0
- wbcore/contrib/authentication/migrations/0005_user_external_calendar_settings.py +17 -0
- wbcore/contrib/authentication/migrations/0006_auto_20231206_1422.py +13 -0
- wbcore/contrib/authentication/migrations/__init__.py +0 -0
- wbcore/contrib/authentication/models/__init__.py +3 -0
- wbcore/contrib/authentication/models/tokens.py +140 -0
- wbcore/contrib/authentication/models/users.py +225 -0
- wbcore/contrib/authentication/models/users_activities.py +112 -0
- wbcore/contrib/authentication/release_notes/1_0_0.md +13 -0
- wbcore/contrib/authentication/release_notes/__init__.py +0 -0
- wbcore/contrib/authentication/serializers/__init__.py +14 -0
- wbcore/contrib/authentication/serializers/users.py +350 -0
- wbcore/contrib/authentication/serializers/users_activites.py +37 -0
- wbcore/contrib/authentication/tasks.py +29 -0
- wbcore/contrib/authentication/tests/__init__.py +0 -0
- wbcore/contrib/authentication/tests/conftest.py +18 -0
- wbcore/contrib/authentication/tests/e2e/__init__.py +1 -0
- wbcore/contrib/authentication/tests/e2e/e2e_auth_utility.py +20 -0
- wbcore/contrib/authentication/tests/signals.py +17 -0
- wbcore/contrib/authentication/tests/test_configs.py +6 -0
- wbcore/contrib/authentication/tests/test_serializers.py +6 -0
- wbcore/contrib/authentication/tests/test_tasks.py +33 -0
- wbcore/contrib/authentication/tests/test_tokens.py +126 -0
- wbcore/contrib/authentication/tests/test_users.py +338 -0
- wbcore/contrib/authentication/tests/test_viewsets.py +6 -0
- wbcore/contrib/authentication/tests/tests.py +15 -0
- wbcore/contrib/authentication/urls.py +97 -0
- wbcore/contrib/authentication/utils.py +10 -0
- wbcore/contrib/authentication/viewsets/__init__.py +19 -0
- wbcore/contrib/authentication/viewsets/buttons/__init__.py +1 -0
- wbcore/contrib/authentication/viewsets/buttons/users.py +55 -0
- wbcore/contrib/authentication/viewsets/display/__init__.py +6 -0
- wbcore/contrib/authentication/viewsets/display/user_activities.py +85 -0
- wbcore/contrib/authentication/viewsets/display/users.py +72 -0
- wbcore/contrib/authentication/viewsets/endpoints/__init__.py +6 -0
- wbcore/contrib/authentication/viewsets/endpoints/user_activities.py +22 -0
- wbcore/contrib/authentication/viewsets/endpoints/users.py +20 -0
- wbcore/contrib/authentication/viewsets/menu/__init__.py +6 -0
- wbcore/contrib/authentication/viewsets/menu/user_activities.py +39 -0
- wbcore/contrib/authentication/viewsets/menu/users.py +16 -0
- wbcore/contrib/authentication/viewsets/titles/__init__.py +12 -0
- wbcore/contrib/authentication/viewsets/titles/user_activities.py +31 -0
- wbcore/contrib/authentication/viewsets/titles/users.py +26 -0
- wbcore/contrib/authentication/viewsets/user_activities.py +222 -0
- wbcore/contrib/authentication/viewsets/users.py +328 -0
- wbcore/contrib/color/migrations/0001_initial.py +33 -0
- wbcore/contrib/color/migrations/0002_alter_colorgradient_colors.py +25 -0
- wbcore/contrib/color/migrations/__init__.py +0 -0
- wbcore/contrib/currency/__init__.py +0 -0
- wbcore/contrib/currency/admin.py +32 -0
- wbcore/contrib/currency/apps.py +5 -0
- wbcore/contrib/currency/dynamic_preferences_registry.py +39 -0
- wbcore/contrib/currency/factories.py +39 -0
- wbcore/contrib/currency/import_export/__init__.py +0 -0
- wbcore/contrib/currency/import_export/backends/__init__.py +1 -0
- wbcore/contrib/currency/import_export/backends/fixerio/__init__.py +1 -0
- wbcore/contrib/currency/import_export/backends/fixerio/currency_fx_rates.py +66 -0
- wbcore/contrib/currency/import_export/backends/utils.py +5 -0
- wbcore/contrib/currency/import_export/handlers/__init__.py +2 -0
- wbcore/contrib/currency/import_export/handlers/currency.py +24 -0
- wbcore/contrib/currency/import_export/handlers/currency_fx_rates.py +28 -0
- wbcore/contrib/currency/import_export/parsers/__init__.py +0 -0
- wbcore/contrib/currency/import_export/parsers/fixerio/__init__.py +0 -0
- wbcore/contrib/currency/import_export/parsers/fixerio/currency_fx_rates.py +34 -0
- wbcore/contrib/currency/migrations/0001_initial.py +89 -0
- wbcore/contrib/currency/migrations/__init__.py +0 -0
- wbcore/contrib/currency/models.py +176 -0
- wbcore/contrib/currency/release_notes/1_0_0.md +13 -0
- wbcore/contrib/currency/release_notes/__init__.py +0 -0
- wbcore/contrib/currency/serializers.py +40 -0
- wbcore/contrib/currency/tests/__init__.py +0 -0
- wbcore/contrib/currency/tests/conftest.py +7 -0
- wbcore/contrib/currency/tests/test_models.py +104 -0
- wbcore/contrib/currency/tests/test_serializers.py +62 -0
- wbcore/contrib/currency/tests/test_viewsets.py +197 -0
- wbcore/contrib/currency/urls.py +19 -0
- wbcore/contrib/currency/viewsets/__init__.py +2 -0
- wbcore/contrib/currency/viewsets/buttons/__init__.py +0 -0
- wbcore/contrib/currency/viewsets/currency.py +56 -0
- wbcore/contrib/currency/viewsets/currency_fx_rates.py +32 -0
- wbcore/contrib/currency/viewsets/display/__init__.py +2 -0
- wbcore/contrib/currency/viewsets/display/currency.py +37 -0
- wbcore/contrib/currency/viewsets/display/currency_fx_rates.py +9 -0
- wbcore/contrib/currency/viewsets/endpoints/__init__.py +1 -0
- wbcore/contrib/currency/viewsets/endpoints/currency_fx_rates.py +14 -0
- wbcore/contrib/currency/viewsets/menu/__init__.py +1 -0
- wbcore/contrib/currency/viewsets/menu/currency.py +8 -0
- wbcore/contrib/currency/viewsets/preview/__init__.py +1 -0
- wbcore/contrib/currency/viewsets/preview/currency.py +10 -0
- wbcore/contrib/currency/viewsets/titles/__init__.py +2 -0
- wbcore/contrib/currency/viewsets/titles/currency.py +6 -0
- wbcore/contrib/currency/viewsets/titles/currency_fx_rates.py +8 -0
- wbcore/contrib/dataloader/__init__.py +1 -0
- wbcore/contrib/dataloader/apps.py +5 -0
- wbcore/contrib/dataloader/dataloaders/__init__.py +2 -0
- wbcore/contrib/dataloader/dataloaders/dataloaders.py +24 -0
- wbcore/contrib/dataloader/dataloaders/proxies.py +81 -0
- wbcore/contrib/dataloader/models/__init__.py +1 -0
- wbcore/contrib/dataloader/models/entities.py +29 -0
- wbcore/contrib/dataloader/models/querysets/__init__.py +1 -0
- wbcore/contrib/dataloader/models/querysets/entities.py +27 -0
- wbcore/contrib/dataloader/tests/__init__.py +0 -0
- wbcore/contrib/dataloader/tests/conftest.py +26 -0
- wbcore/contrib/dataloader/tests/test/__init__.py +0 -0
- wbcore/contrib/dataloader/tests/test/dataloaders/__init__.py +0 -0
- wbcore/contrib/dataloader/tests/test/dataloaders/dataloaders.py +18 -0
- wbcore/contrib/dataloader/tests/test/dataloaders/protocols.py +6 -0
- wbcore/contrib/dataloader/tests/test/dataloaders/proxies.py +11 -0
- wbcore/contrib/dataloader/tests/test/factories.py +13 -0
- wbcore/contrib/dataloader/tests/test/models.py +10 -0
- wbcore/contrib/dataloader/tests/test_dataloaders.py +37 -0
- wbcore/contrib/dataloader/tests/test_entities.py +12 -0
- wbcore/contrib/dataloader/utils.py +17 -0
- wbcore/contrib/directory/__init__.py +0 -0
- wbcore/contrib/directory/admin/__init__.py +14 -0
- wbcore/contrib/directory/admin/contacts.py +54 -0
- wbcore/contrib/directory/admin/entries.py +230 -0
- wbcore/contrib/directory/admin/relationships.py +73 -0
- wbcore/contrib/directory/apps.py +6 -0
- wbcore/contrib/directory/configs.py +8 -0
- wbcore/contrib/directory/configurations.py +69 -0
- wbcore/contrib/directory/dynamic_preferences_registry.py +61 -0
- wbcore/contrib/directory/factories/__init__.py +34 -0
- wbcore/contrib/directory/factories/contacts.py +71 -0
- wbcore/contrib/directory/factories/entries.py +169 -0
- wbcore/contrib/directory/factories/relationships.py +77 -0
- wbcore/contrib/directory/filters/__init__.py +22 -0
- wbcore/contrib/directory/filters/contacts.py +233 -0
- wbcore/contrib/directory/filters/entries.py +247 -0
- wbcore/contrib/directory/filters/relationships.py +89 -0
- wbcore/contrib/directory/migrations/0001_initial.py +871 -0
- wbcore/contrib/directory/migrations/0002_auto_20230414_1553.py +42 -0
- wbcore/contrib/directory/migrations/0003_remove_entry_last_event.py +16 -0
- wbcore/contrib/directory/migrations/0004_entry_is_draft_entry.py +21 -0
- wbcore/contrib/directory/migrations/0005_entry_salutation.py +17 -0
- wbcore/contrib/directory/migrations/0006_employeremployeerelationship_position_name.py +23 -0
- wbcore/contrib/directory/migrations/0007_alter_bankingcontact_options.py +20 -0
- wbcore/contrib/directory/migrations/0008_bankingcontact_access.py +17 -0
- wbcore/contrib/directory/migrations/0009_remove_entry_external_identfier_and_more.py +22 -0
- wbcore/contrib/directory/migrations/__init__.py +0 -0
- wbcore/contrib/directory/models/__init__.py +27 -0
- wbcore/contrib/directory/models/contacts.py +554 -0
- wbcore/contrib/directory/models/entries.py +889 -0
- wbcore/contrib/directory/models/relationships.py +634 -0
- wbcore/contrib/directory/preferences.py +10 -0
- wbcore/contrib/directory/release_notes/1_0_0.md +13 -0
- wbcore/contrib/directory/release_notes/1_0_1.md +13 -0
- wbcore/contrib/directory/release_notes/__init__.py +0 -0
- wbcore/contrib/directory/serializers/__init__.py +63 -0
- wbcore/contrib/directory/serializers/companies.py +158 -0
- wbcore/contrib/directory/serializers/contacts.py +404 -0
- wbcore/contrib/directory/serializers/entries.py +344 -0
- wbcore/contrib/directory/serializers/entry_representations.py +35 -0
- wbcore/contrib/directory/serializers/persons.py +209 -0
- wbcore/contrib/directory/serializers/relationships.py +332 -0
- wbcore/contrib/directory/signals.py +3 -0
- wbcore/contrib/directory/tests/__init__.py +0 -0
- wbcore/contrib/directory/tests/conftest.py +60 -0
- wbcore/contrib/directory/tests/disable_signals.py +52 -0
- wbcore/contrib/directory/tests/e2e/__init__.py +7 -0
- wbcore/contrib/directory/tests/e2e/e2e_directory_utility.py +162 -0
- wbcore/contrib/directory/tests/signals.py +90 -0
- wbcore/contrib/directory/tests/test_configs.py +6 -0
- wbcore/contrib/directory/tests/test_filters.py +59 -0
- wbcore/contrib/directory/tests/test_models.py +285 -0
- wbcore/contrib/directory/tests/test_permissions.py +122 -0
- wbcore/contrib/directory/tests/test_serializers.py +201 -0
- wbcore/contrib/directory/tests/test_viewsets.py +677 -0
- wbcore/contrib/directory/tests/tests.py +130 -0
- wbcore/contrib/directory/typings.py +17 -0
- wbcore/contrib/directory/urls.py +135 -0
- wbcore/contrib/directory/viewsets/__init__.py +58 -0
- wbcore/contrib/directory/viewsets/buttons/__init__.py +7 -0
- wbcore/contrib/directory/viewsets/buttons/contacts.py +16 -0
- wbcore/contrib/directory/viewsets/buttons/entries.py +133 -0
- wbcore/contrib/directory/viewsets/buttons/relationships.py +31 -0
- wbcore/contrib/directory/viewsets/contacts.py +393 -0
- wbcore/contrib/directory/viewsets/display/__init__.py +36 -0
- wbcore/contrib/directory/viewsets/display/contacts.py +380 -0
- wbcore/contrib/directory/viewsets/display/entries.py +501 -0
- wbcore/contrib/directory/viewsets/display/relationships.py +315 -0
- wbcore/contrib/directory/viewsets/display/utils.py +33 -0
- wbcore/contrib/directory/viewsets/endpoints/__init__.py +22 -0
- wbcore/contrib/directory/viewsets/endpoints/contacts.py +54 -0
- wbcore/contrib/directory/viewsets/endpoints/entries.py +30 -0
- wbcore/contrib/directory/viewsets/endpoints/relationships.py +105 -0
- wbcore/contrib/directory/viewsets/entries.py +212 -0
- wbcore/contrib/directory/viewsets/menu/__init__.py +16 -0
- wbcore/contrib/directory/viewsets/menu/contacts.py +25 -0
- wbcore/contrib/directory/viewsets/menu/entries.py +61 -0
- wbcore/contrib/directory/viewsets/menu/relationships.py +31 -0
- wbcore/contrib/directory/viewsets/menu/utils.py +72 -0
- wbcore/contrib/directory/viewsets/mixins.py +11 -0
- wbcore/contrib/directory/viewsets/previews/__init__.py +2 -0
- wbcore/contrib/directory/viewsets/previews/contacts.py +18 -0
- wbcore/contrib/directory/viewsets/previews/entries.py +31 -0
- wbcore/contrib/directory/viewsets/relationships.py +241 -0
- wbcore/contrib/directory/viewsets/titles/__init__.py +30 -0
- wbcore/contrib/directory/viewsets/titles/contacts.py +122 -0
- wbcore/contrib/directory/viewsets/titles/entries.py +29 -0
- wbcore/contrib/directory/viewsets/titles/relationships.py +86 -0
- wbcore/contrib/directory/viewsets/titles/utils.py +46 -0
- wbcore/contrib/directory/viewsets/utils.py +101 -0
- wbcore/contrib/documents/__init__.py +0 -0
- wbcore/contrib/documents/admin.py +79 -0
- wbcore/contrib/documents/apps.py +6 -0
- wbcore/contrib/documents/factories.py +43 -0
- wbcore/contrib/documents/filters.py +82 -0
- wbcore/contrib/documents/migrations/0001_initial.py +189 -0
- wbcore/contrib/documents/migrations/0002_documentmodelrelationship_primary_and_more.py +22 -0
- wbcore/contrib/documents/migrations/0003_alter_documentmodelrelationship_unique_together_and_more.py +30 -0
- wbcore/contrib/documents/migrations/0004_auto_20240103_0958.py +44 -0
- wbcore/contrib/documents/migrations/0005_document_valid_from_document_valid_until_and_more.py +32 -0
- wbcore/contrib/documents/migrations/__init__.py +0 -0
- wbcore/contrib/documents/models/__init__.py +4 -0
- wbcore/contrib/documents/models/document_model_relationships.py +57 -0
- wbcore/contrib/documents/models/document_types.py +35 -0
- wbcore/contrib/documents/models/documents.py +309 -0
- wbcore/contrib/documents/models/mixins.py +10 -0
- wbcore/contrib/documents/models/shareable_links.py +90 -0
- wbcore/contrib/documents/release_notes/1_0_0.md +13 -0
- wbcore/contrib/documents/release_notes/__init__.py +0 -0
- wbcore/contrib/documents/serializers/__init__.py +12 -0
- wbcore/contrib/documents/serializers/document_model_relationships.py +31 -0
- wbcore/contrib/documents/serializers/document_types.py +40 -0
- wbcore/contrib/documents/serializers/documents.py +64 -0
- wbcore/contrib/documents/serializers/shareable_links.py +90 -0
- wbcore/contrib/documents/urls.py +42 -0
- wbcore/contrib/documents/viewsets/__init__.py +10 -0
- wbcore/contrib/documents/viewsets/buttons/__init__.py +3 -0
- wbcore/contrib/documents/viewsets/buttons/documents.py +53 -0
- wbcore/contrib/documents/viewsets/buttons/shareable_links.py +20 -0
- wbcore/contrib/documents/viewsets/buttons/signals.py +13 -0
- wbcore/contrib/documents/viewsets/display/__init__.py +4 -0
- wbcore/contrib/documents/viewsets/display/document_model_relationships.py +18 -0
- wbcore/contrib/documents/viewsets/display/document_types.py +23 -0
- wbcore/contrib/documents/viewsets/display/documents.py +101 -0
- wbcore/contrib/documents/viewsets/display/shareable_links.py +65 -0
- wbcore/contrib/documents/viewsets/document_model_relationships.py +25 -0
- wbcore/contrib/documents/viewsets/document_types.py +37 -0
- wbcore/contrib/documents/viewsets/documents.py +107 -0
- wbcore/contrib/documents/viewsets/endpoints/__init__.py +5 -0
- wbcore/contrib/documents/viewsets/endpoints/documents.py +19 -0
- wbcore/contrib/documents/viewsets/endpoints/documents_model_relationships.py +13 -0
- wbcore/contrib/documents/viewsets/endpoints/shareable_links.py +45 -0
- wbcore/contrib/documents/viewsets/menu/__init__.py +1 -0
- wbcore/contrib/documents/viewsets/menu/documents.py +24 -0
- wbcore/contrib/documents/viewsets/previews/__init__.py +1 -0
- wbcore/contrib/documents/viewsets/previews/documents.py +10 -0
- wbcore/contrib/documents/viewsets/shareable_links.py +109 -0
- wbcore/contrib/documents/viewsets/titles/__init__.py +3 -0
- wbcore/contrib/documents/viewsets/titles/document_types.py +13 -0
- wbcore/contrib/documents/viewsets/titles/documents.py +26 -0
- wbcore/contrib/documents/viewsets/titles/shareable_links.py +13 -0
- wbcore/contrib/dynamic_preferences/__init__.py +0 -0
- wbcore/contrib/dynamic_preferences/types.py +19 -0
- wbcore/contrib/example_app/__init__.py +0 -0
- wbcore/contrib/example_app/admin.py +117 -0
- wbcore/contrib/example_app/apps.py +6 -0
- wbcore/contrib/example_app/factories/__init__.py +8 -0
- wbcore/contrib/example_app/factories/event.py +26 -0
- wbcore/contrib/example_app/factories/league.py +15 -0
- wbcore/contrib/example_app/factories/match.py +25 -0
- wbcore/contrib/example_app/factories/person.py +32 -0
- wbcore/contrib/example_app/factories/role.py +9 -0
- wbcore/contrib/example_app/factories/sport.py +12 -0
- wbcore/contrib/example_app/factories/stadium.py +12 -0
- wbcore/contrib/example_app/factories/team.py +35 -0
- wbcore/contrib/example_app/filters/__init__.py +9 -0
- wbcore/contrib/example_app/filters/event.py +80 -0
- wbcore/contrib/example_app/filters/league.py +74 -0
- wbcore/contrib/example_app/filters/match.py +92 -0
- wbcore/contrib/example_app/filters/person.py +77 -0
- wbcore/contrib/example_app/filters/role.py +17 -0
- wbcore/contrib/example_app/filters/sport.py +26 -0
- wbcore/contrib/example_app/filters/stadium.py +30 -0
- wbcore/contrib/example_app/filters/team.py +77 -0
- wbcore/contrib/example_app/filters/teamresult.py +47 -0
- wbcore/contrib/example_app/migrations/0001_initial.py +498 -0
- wbcore/contrib/example_app/migrations/0002_sportperson_profile.py +49 -0
- wbcore/contrib/example_app/migrations/0003_change_stadium_capacity.py +31 -0
- wbcore/contrib/example_app/migrations/0004_alter_player_transfer_value.py +21 -0
- wbcore/contrib/example_app/migrations/0005_sportperson_profile_image.py +23 -0
- wbcore/contrib/example_app/migrations/0006_league_season_period_player_is_active_and_more.py +116 -0
- wbcore/contrib/example_app/migrations/0007_alter_player_options_alter_team_options_and_more.py +40 -0
- wbcore/contrib/example_app/migrations/__init__.py +0 -0
- wbcore/contrib/example_app/models.py +906 -0
- wbcore/contrib/example_app/serializers/__init__.py +31 -0
- wbcore/contrib/example_app/serializers/league.py +111 -0
- wbcore/contrib/example_app/serializers/match_event.py +304 -0
- wbcore/contrib/example_app/serializers/person_team.py +280 -0
- wbcore/contrib/example_app/serializers/role.py +16 -0
- wbcore/contrib/example_app/serializers/season.py +53 -0
- wbcore/contrib/example_app/serializers/sport.py +37 -0
- wbcore/contrib/example_app/serializers/stadium.py +58 -0
- wbcore/contrib/example_app/serializers/teamresult.py +43 -0
- wbcore/contrib/example_app/tests/__init__.py +0 -0
- wbcore/contrib/example_app/tests/conftest.py +13 -0
- wbcore/contrib/example_app/tests/e2e/__init__.py +1 -0
- wbcore/contrib/example_app/tests/e2e/e2e_example_app_utility.py +51 -0
- wbcore/contrib/example_app/tests/e2e/test_league.py +69 -0
- wbcore/contrib/example_app/tests/e2e/test_person.py +67 -0
- wbcore/contrib/example_app/tests/e2e/test_teams.py +56 -0
- wbcore/contrib/example_app/tests/signals.py +7 -0
- wbcore/contrib/example_app/tests/test_displays.py +40 -0
- wbcore/contrib/example_app/tests/test_filters.py +70 -0
- wbcore/contrib/example_app/tests/test_utils.py +25 -0
- wbcore/contrib/example_app/urls.py +79 -0
- wbcore/contrib/example_app/utils.py +20 -0
- wbcore/contrib/example_app/viewsets/__init__.py +29 -0
- wbcore/contrib/example_app/viewsets/buttons/__init__.py +2 -0
- wbcore/contrib/example_app/viewsets/buttons/person.py +18 -0
- wbcore/contrib/example_app/viewsets/buttons/team.py +23 -0
- wbcore/contrib/example_app/viewsets/displays/__init__.py +23 -0
- wbcore/contrib/example_app/viewsets/displays/event.py +186 -0
- wbcore/contrib/example_app/viewsets/displays/league.py +390 -0
- wbcore/contrib/example_app/viewsets/displays/match.py +264 -0
- wbcore/contrib/example_app/viewsets/displays/person.py +251 -0
- wbcore/contrib/example_app/viewsets/displays/role.py +16 -0
- wbcore/contrib/example_app/viewsets/displays/season.py +65 -0
- wbcore/contrib/example_app/viewsets/displays/sport.py +115 -0
- wbcore/contrib/example_app/viewsets/displays/stadium.py +149 -0
- wbcore/contrib/example_app/viewsets/displays/team.py +230 -0
- wbcore/contrib/example_app/viewsets/displays/teamresult.py +30 -0
- wbcore/contrib/example_app/viewsets/endpoints/__init__.py +12 -0
- wbcore/contrib/example_app/viewsets/endpoints/endpoints.py +79 -0
- wbcore/contrib/example_app/viewsets/event.py +287 -0
- wbcore/contrib/example_app/viewsets/league.py +72 -0
- wbcore/contrib/example_app/viewsets/match.py +119 -0
- wbcore/contrib/example_app/viewsets/menu/__init__.py +1 -0
- wbcore/contrib/example_app/viewsets/menu/menus.py +102 -0
- wbcore/contrib/example_app/viewsets/menus.py +63 -0
- wbcore/contrib/example_app/viewsets/person.py +133 -0
- wbcore/contrib/example_app/viewsets/role.py +25 -0
- wbcore/contrib/example_app/viewsets/season.py +23 -0
- wbcore/contrib/example_app/viewsets/sport.py +26 -0
- wbcore/contrib/example_app/viewsets/stadium.py +30 -0
- wbcore/contrib/example_app/viewsets/team.py +68 -0
- wbcore/contrib/example_app/viewsets/teamresult.py +106 -0
- wbcore/contrib/example_app/viewsets/titles/__init__.py +9 -0
- wbcore/contrib/example_app/viewsets/titles/event.py +41 -0
- wbcore/contrib/example_app/viewsets/titles/league.py +24 -0
- wbcore/contrib/example_app/viewsets/titles/match.py +34 -0
- wbcore/contrib/example_app/viewsets/titles/person.py +35 -0
- wbcore/contrib/example_app/viewsets/titles/role.py +13 -0
- wbcore/contrib/example_app/viewsets/titles/sport.py +13 -0
- wbcore/contrib/example_app/viewsets/titles/stadium.py +13 -0
- wbcore/contrib/example_app/viewsets/titles/team.py +24 -0
- wbcore/contrib/example_app/viewsets/titles/teamresult.py +12 -0
- wbcore/contrib/geography/__init__.py +0 -0
- wbcore/contrib/geography/admin.py +30 -0
- wbcore/contrib/geography/apps.py +5 -0
- wbcore/contrib/geography/factories.py +46 -0
- wbcore/contrib/geography/import_export/__init__.py +0 -0
- wbcore/contrib/geography/import_export/resources/__init__.py +0 -0
- wbcore/contrib/geography/import_export/resources/geography.py +10 -0
- wbcore/contrib/geography/migrations/0001_initial.py +110 -0
- wbcore/contrib/geography/migrations/__init__.py +0 -0
- wbcore/contrib/geography/models.py +147 -0
- wbcore/contrib/geography/release_notes/1_0_0.md +13 -0
- wbcore/contrib/geography/release_notes/__init__.py +0 -0
- wbcore/contrib/geography/serializers.py +32 -0
- wbcore/contrib/geography/tests/__init__.py +0 -0
- wbcore/contrib/geography/tests/conftest.py +12 -0
- wbcore/contrib/geography/tests/signals.py +7 -0
- wbcore/contrib/geography/tests/test_models.py +12 -0
- wbcore/contrib/geography/tests/test_serializers.py +7 -0
- wbcore/contrib/geography/tests/test_viewsets.py +6 -0
- wbcore/contrib/geography/tests/tests.py +12 -0
- wbcore/contrib/geography/urls.py +12 -0
- wbcore/contrib/geography/viewsets/__init__.py +1 -0
- wbcore/contrib/geography/viewsets/buttons/__init__.py +0 -0
- wbcore/contrib/geography/viewsets/display/__init__.py +1 -0
- wbcore/contrib/geography/viewsets/display/geography.py +32 -0
- wbcore/contrib/geography/viewsets/endpoints/__init__.py +0 -0
- wbcore/contrib/geography/viewsets/geography.py +57 -0
- wbcore/contrib/geography/viewsets/menu/__init__.py +1 -0
- wbcore/contrib/geography/viewsets/menu/geography.py +8 -0
- wbcore/contrib/geography/viewsets/preview/__init__.py +1 -0
- wbcore/contrib/geography/viewsets/preview/geography.py +19 -0
- wbcore/contrib/geography/viewsets/titles/__init__.py +0 -0
- wbcore/contrib/geography/viewsets/titles/geography.py +14 -0
- wbcore/contrib/gleap/__init__.py +0 -0
- wbcore/contrib/gleap/apps.py +5 -0
- wbcore/contrib/gleap/configs.py +11 -0
- wbcore/contrib/gleap/configurations.py +6 -0
- wbcore/contrib/gleap/hashes.py +13 -0
- wbcore/contrib/gleap/tests/__init__.py +0 -0
- wbcore/contrib/gleap/tests/conftest.py +1 -0
- wbcore/contrib/gleap/tests/tests.py +29 -0
- wbcore/contrib/gleap/urls.py +7 -0
- wbcore/contrib/gleap/views.py +31 -0
- wbcore/contrib/guardian/migrations/0001_initial.py +103 -0
- wbcore/contrib/guardian/migrations/__init__.py +0 -0
- wbcore/contrib/guardian/models/__init__.py +1 -0
- wbcore/contrib/guardian/models/mixins.py +138 -0
- wbcore/contrib/guardian/models/models.py +29 -0
- wbcore/contrib/guardian/tests/__init__.py +0 -0
- wbcore/contrib/guardian/tests/conftest.py +1 -0
- wbcore/contrib/guardian/tests/test_model_mixins.py +93 -0
- wbcore/contrib/guardian/tests/test_tasks.py +77 -0
- wbcore/contrib/guardian/tests/test_utils.py +196 -0
- wbcore/contrib/guardian/tests/test_viewsets.py +48 -0
- wbcore/contrib/guardian/viewsets/__init__.py +1 -0
- wbcore/contrib/guardian/viewsets/configs/__init__.py +4 -0
- wbcore/contrib/guardian/viewsets/configs/buttons.py +27 -0
- wbcore/contrib/guardian/viewsets/configs/displays.py +43 -0
- wbcore/contrib/guardian/viewsets/configs/endpoints.py +18 -0
- wbcore/contrib/guardian/viewsets/configs/titles.py +16 -0
- wbcore/contrib/guardian/viewsets/mixins.py +6 -0
- wbcore/contrib/guardian/viewsets/viewsets.py +139 -0
- wbcore/contrib/icons/__init__.py +1 -0
- wbcore/contrib/icons/apps.py +5 -0
- wbcore/contrib/icons/backends/__init__.py +5 -0
- wbcore/contrib/icons/backends/default.py +374 -0
- wbcore/contrib/icons/backends/material.py +135 -0
- wbcore/contrib/icons/icons.py +169 -0
- wbcore/contrib/icons/models.py +11 -0
- wbcore/contrib/icons/serializers.py +18 -0
- wbcore/contrib/io/__init__.py +0 -0
- wbcore/contrib/io/admin.py +150 -0
- wbcore/contrib/io/apps.py +27 -0
- wbcore/contrib/io/backends/__init__.py +5 -0
- wbcore/contrib/io/backends/abstract.py +60 -0
- wbcore/contrib/io/backends/mail.py +85 -0
- wbcore/contrib/io/backends/sftp.py +63 -0
- wbcore/contrib/io/backends/stream.py +92 -0
- wbcore/contrib/io/backends/utils.py +42 -0
- wbcore/contrib/io/configs/__init__.py +0 -0
- wbcore/contrib/io/configs/endpoints.py +12 -0
- wbcore/contrib/io/configurations/__init__.py +1 -0
- wbcore/contrib/io/configurations/base.py +7 -0
- wbcore/contrib/io/dynamic_preferences_registry.py +15 -0
- wbcore/contrib/io/enums.py +15 -0
- wbcore/contrib/io/exceptions.py +16 -0
- wbcore/contrib/io/factories.py +202 -0
- wbcore/contrib/io/imports.py +305 -0
- wbcore/contrib/io/management/__init__.py +13 -0
- wbcore/contrib/io/migrations/0001_initial_squashed.py +319 -0
- wbcore/contrib/io/migrations/0002_importsource_creator.py +26 -0
- wbcore/contrib/io/migrations/0003_auto_20240103_1000.py +46 -0
- wbcore/contrib/io/migrations/0004_alter_importsource_status_exportsource.py +134 -0
- wbcore/contrib/io/migrations/0005_exportsource_data_alter_exportsource_query_str_and_more.py +67 -0
- wbcore/contrib/io/migrations/0006_alter_exportsource_query_params.py +20 -0
- wbcore/contrib/io/migrations/0007_alter_exportsource_query_params.py +23 -0
- wbcore/contrib/io/migrations/__init__.py +0 -0
- wbcore/contrib/io/mixins.py +37 -0
- wbcore/contrib/io/models.py +1005 -0
- wbcore/contrib/io/release_notes/1_0_0.md +13 -0
- wbcore/contrib/io/release_notes/__init__.py +0 -0
- wbcore/contrib/io/resources.py +177 -0
- wbcore/contrib/io/serializers.py +136 -0
- wbcore/contrib/io/tests/__init__.py +0 -0
- wbcore/contrib/io/tests/conftest.py +42 -0
- wbcore/contrib/io/tests/test_backends.py +128 -0
- wbcore/contrib/io/tests/test_exports.py +130 -0
- wbcore/contrib/io/tests/test_imports.py +167 -0
- wbcore/contrib/io/tests/test_models.py +363 -0
- wbcore/contrib/io/tests/tests.py +18 -0
- wbcore/contrib/io/urls.py +28 -0
- wbcore/contrib/io/utils.py +44 -0
- wbcore/contrib/io/viewset_mixins.py +301 -0
- wbcore/contrib/io/viewsets.py +138 -0
- wbcore/contrib/notifications/__init__.py +0 -0
- wbcore/contrib/notifications/admin.py +61 -0
- wbcore/contrib/notifications/apps.py +38 -0
- wbcore/contrib/notifications/backends/__init__.py +0 -0
- wbcore/contrib/notifications/backends/abstract_backend.py +13 -0
- wbcore/contrib/notifications/backends/console/__init__.py +1 -0
- wbcore/contrib/notifications/backends/console/backends.py +25 -0
- wbcore/contrib/notifications/backends/firebase/__init__.py +1 -0
- wbcore/contrib/notifications/backends/firebase/backends.py +102 -0
- wbcore/contrib/notifications/configs.py +12 -0
- wbcore/contrib/notifications/configurations.py +9 -0
- wbcore/contrib/notifications/dispatch.py +71 -0
- wbcore/contrib/notifications/factories/__init__.py +0 -0
- wbcore/contrib/notifications/factories/notification_types.py +22 -0
- wbcore/contrib/notifications/factories/notifications.py +16 -0
- wbcore/contrib/notifications/factories/tokens.py +11 -0
- wbcore/contrib/notifications/migrations/0001_initial.py +116 -0
- wbcore/contrib/notifications/migrations/0002_notificationusertoken_unique_user_token_device.py +18 -0
- wbcore/contrib/notifications/migrations/0003_notificationusertoken_updated.py +17 -0
- wbcore/contrib/notifications/migrations/0004_alter_notification_body.py +17 -0
- wbcore/contrib/notifications/migrations/0005_alter_notification_endpoint.py +17 -0
- wbcore/contrib/notifications/migrations/0006_notification_created.py +25 -0
- wbcore/contrib/notifications/migrations/__init__.py +0 -0
- wbcore/contrib/notifications/models/__init__.py +3 -0
- wbcore/contrib/notifications/models/notification_types.py +112 -0
- wbcore/contrib/notifications/models/notifications.py +81 -0
- wbcore/contrib/notifications/models/tokens.py +45 -0
- wbcore/contrib/notifications/release_notes/1_0_0.md +13 -0
- wbcore/contrib/notifications/release_notes/__init__.py +0 -0
- wbcore/contrib/notifications/serializers/__init__.py +5 -0
- wbcore/contrib/notifications/serializers/notification_types.py +36 -0
- wbcore/contrib/notifications/serializers/notifications.py +33 -0
- wbcore/contrib/notifications/tasks.py +55 -0
- wbcore/contrib/notifications/tests/__init__.py +0 -0
- wbcore/contrib/notifications/tests/conftest.py +47 -0
- wbcore/contrib/notifications/tests/test_backends/__init__.py +0 -0
- wbcore/contrib/notifications/tests/test_backends/test_firebase.py +78 -0
- wbcore/contrib/notifications/tests/test_configs.py +7 -0
- wbcore/contrib/notifications/tests/test_models/__init__.py +0 -0
- wbcore/contrib/notifications/tests/test_models/test_notification_types.py +84 -0
- wbcore/contrib/notifications/tests/test_models/test_notifications.py +45 -0
- wbcore/contrib/notifications/tests/test_models/test_tokens.py +21 -0
- wbcore/contrib/notifications/tests/test_serializers/__init__.py +0 -0
- wbcore/contrib/notifications/tests/test_serializers/test_notification_types.py +53 -0
- wbcore/contrib/notifications/tests/test_serializers/test_notifications.py +23 -0
- wbcore/contrib/notifications/tests/test_tasks.py +71 -0
- wbcore/contrib/notifications/tests/test_utils.py +0 -0
- wbcore/contrib/notifications/tests/test_viewsets/__init__.py +0 -0
- wbcore/contrib/notifications/tests/test_viewsets/test_notification_types.py +121 -0
- wbcore/contrib/notifications/tests/test_viewsets/test_notifications.py +120 -0
- wbcore/contrib/notifications/urls.py +26 -0
- wbcore/contrib/notifications/utils.py +20 -0
- wbcore/contrib/notifications/views.py +62 -0
- wbcore/contrib/notifications/viewsets/__init__.py +5 -0
- wbcore/contrib/notifications/viewsets/menus.py +14 -0
- wbcore/contrib/notifications/viewsets/notification_types.py +40 -0
- wbcore/contrib/notifications/viewsets/notifications.py +57 -0
- wbcore/contrib/tags/__init__.py +0 -0
- wbcore/contrib/tags/admin.py +17 -0
- wbcore/contrib/tags/apps.py +9 -0
- wbcore/contrib/tags/factories.py +27 -0
- wbcore/contrib/tags/filters.py +42 -0
- wbcore/contrib/tags/migrations/0001_initial.py +62 -0
- wbcore/contrib/tags/migrations/__init__.py +0 -0
- wbcore/contrib/tags/models/__init__.py +2 -0
- wbcore/contrib/tags/models/mixins.py +27 -0
- wbcore/contrib/tags/models/tags.py +103 -0
- wbcore/contrib/tags/release_notes/1_0_0.md +13 -0
- wbcore/contrib/tags/release_notes/__init__.py +0 -0
- wbcore/contrib/tags/serializers.py +87 -0
- wbcore/contrib/tags/signals.py +17 -0
- wbcore/contrib/tags/tests/__init__.py +0 -0
- wbcore/contrib/tags/tests/conftest.py +7 -0
- wbcore/contrib/tags/tests/tests.py +17 -0
- wbcore/contrib/tags/urls.py +14 -0
- wbcore/contrib/tags/viewsets/__init__.py +8 -0
- wbcore/contrib/tags/viewsets/display.py +50 -0
- wbcore/contrib/tags/viewsets/menu.py +15 -0
- wbcore/contrib/tags/viewsets/viewsets.py +58 -0
- wbcore/contrib/workflow/__init__.py +1 -0
- wbcore/contrib/workflow/admin/__init__.py +15 -0
- wbcore/contrib/workflow/admin/condition.py +8 -0
- wbcore/contrib/workflow/admin/data.py +14 -0
- wbcore/contrib/workflow/admin/display.py +8 -0
- wbcore/contrib/workflow/admin/process.py +36 -0
- wbcore/contrib/workflow/admin/step.py +91 -0
- wbcore/contrib/workflow/admin/transition.py +8 -0
- wbcore/contrib/workflow/admin/workflow.py +8 -0
- wbcore/contrib/workflow/apps.py +26 -0
- wbcore/contrib/workflow/configs.py +10 -0
- wbcore/contrib/workflow/decorators.py +25 -0
- wbcore/contrib/workflow/dispatch.py +23 -0
- wbcore/contrib/workflow/factories/__init__.py +18 -0
- wbcore/contrib/workflow/factories/condition.py +15 -0
- wbcore/contrib/workflow/factories/data.py +22 -0
- wbcore/contrib/workflow/factories/display.py +27 -0
- wbcore/contrib/workflow/factories/process.py +69 -0
- wbcore/contrib/workflow/factories/step.py +155 -0
- wbcore/contrib/workflow/factories/transition.py +25 -0
- wbcore/contrib/workflow/factories/workflow.py +19 -0
- wbcore/contrib/workflow/filters/__init__.py +24 -0
- wbcore/contrib/workflow/filters/condition.py +23 -0
- wbcore/contrib/workflow/filters/data.py +24 -0
- wbcore/contrib/workflow/filters/process.py +164 -0
- wbcore/contrib/workflow/filters/step.py +226 -0
- wbcore/contrib/workflow/filters/transition.py +41 -0
- wbcore/contrib/workflow/filters/workflow.py +43 -0
- wbcore/contrib/workflow/migrations/0001_initial.py +788 -0
- wbcore/contrib/workflow/migrations/0002_alter_step_step_type.py +31 -0
- wbcore/contrib/workflow/migrations/0003_alter_condition_attribute_name_and_more.py +75 -0
- wbcore/contrib/workflow/migrations/0004_alter_userstep_assignee_method.py +27 -0
- wbcore/contrib/workflow/migrations/0005_alter_userstep_assignee_method.py +17 -0
- wbcore/contrib/workflow/migrations/__init__.py +0 -0
- wbcore/contrib/workflow/models/__init__.py +19 -0
- wbcore/contrib/workflow/models/condition.py +123 -0
- wbcore/contrib/workflow/models/data.py +238 -0
- wbcore/contrib/workflow/models/display.py +33 -0
- wbcore/contrib/workflow/models/process.py +243 -0
- wbcore/contrib/workflow/models/step.py +735 -0
- wbcore/contrib/workflow/models/transition.py +70 -0
- wbcore/contrib/workflow/models/workflow.py +307 -0
- wbcore/contrib/workflow/serializers/__init__.py +37 -0
- wbcore/contrib/workflow/serializers/condition.py +64 -0
- wbcore/contrib/workflow/serializers/data.py +135 -0
- wbcore/contrib/workflow/serializers/display.py +25 -0
- wbcore/contrib/workflow/serializers/process.py +182 -0
- wbcore/contrib/workflow/serializers/signals.py +25 -0
- wbcore/contrib/workflow/serializers/step.py +364 -0
- wbcore/contrib/workflow/serializers/transition.py +80 -0
- wbcore/contrib/workflow/serializers/workflow.py +124 -0
- wbcore/contrib/workflow/sites.py +43 -0
- wbcore/contrib/workflow/tests/__init__.py +0 -0
- wbcore/contrib/workflow/tests/conftest.py +57 -0
- wbcore/contrib/workflow/tests/test_configs.py +6 -0
- wbcore/contrib/workflow/tests/test_dispatch.py +88 -0
- wbcore/contrib/workflow/tests/test_displays.py +119 -0
- wbcore/contrib/workflow/tests/test_filters.py +86 -0
- wbcore/contrib/workflow/tests/test_serializers.py +177 -0
- wbcore/contrib/workflow/tests/test_viewsets.py +358 -0
- wbcore/contrib/workflow/tests/test_workflow_assignees.py +225 -0
- wbcore/contrib/workflow/tests/tests.py +24 -0
- wbcore/contrib/workflow/urls.py +66 -0
- wbcore/contrib/workflow/utils.py +13 -0
- wbcore/contrib/workflow/viewsets/__init__.py +17 -0
- wbcore/contrib/workflow/viewsets/buttons/__init__.py +1 -0
- wbcore/contrib/workflow/viewsets/buttons/step.py +67 -0
- wbcore/contrib/workflow/viewsets/condition.py +32 -0
- wbcore/contrib/workflow/viewsets/data.py +33 -0
- wbcore/contrib/workflow/viewsets/display/__init__.py +15 -0
- wbcore/contrib/workflow/viewsets/display/condition.py +50 -0
- wbcore/contrib/workflow/viewsets/display/data.py +50 -0
- wbcore/contrib/workflow/viewsets/display/process.py +185 -0
- wbcore/contrib/workflow/viewsets/display/step.py +453 -0
- wbcore/contrib/workflow/viewsets/display/transition.py +75 -0
- wbcore/contrib/workflow/viewsets/display/workflow.py +167 -0
- wbcore/contrib/workflow/viewsets/endpoints/__init__.py +5 -0
- wbcore/contrib/workflow/viewsets/endpoints/condition.py +9 -0
- wbcore/contrib/workflow/viewsets/endpoints/data.py +9 -0
- wbcore/contrib/workflow/viewsets/endpoints/process.py +11 -0
- wbcore/contrib/workflow/viewsets/endpoints/step.py +24 -0
- wbcore/contrib/workflow/viewsets/endpoints/transition.py +18 -0
- wbcore/contrib/workflow/viewsets/menu/__init__.py +15 -0
- wbcore/contrib/workflow/viewsets/menu/condition.py +18 -0
- wbcore/contrib/workflow/viewsets/menu/data.py +18 -0
- wbcore/contrib/workflow/viewsets/menu/process.py +18 -0
- wbcore/contrib/workflow/viewsets/menu/step.py +123 -0
- wbcore/contrib/workflow/viewsets/menu/transition.py +18 -0
- wbcore/contrib/workflow/viewsets/menu/workflow.py +18 -0
- wbcore/contrib/workflow/viewsets/process.py +171 -0
- wbcore/contrib/workflow/viewsets/step.py +229 -0
- wbcore/contrib/workflow/viewsets/titles/__init__.py +16 -0
- wbcore/contrib/workflow/viewsets/titles/condition.py +13 -0
- wbcore/contrib/workflow/viewsets/titles/data.py +13 -0
- wbcore/contrib/workflow/viewsets/titles/process.py +26 -0
- wbcore/contrib/workflow/viewsets/titles/step.py +101 -0
- wbcore/contrib/workflow/viewsets/titles/transition.py +13 -0
- wbcore/contrib/workflow/viewsets/titles/workflow.py +13 -0
- wbcore/contrib/workflow/viewsets/transition.py +57 -0
- wbcore/contrib/workflow/viewsets/workflow.py +36 -0
- wbcore/contrib/workflow/workflows/__init__.py +1 -0
- wbcore/contrib/workflow/workflows/assignees.py +82 -0
- wbcore/crontab/__init__.py +0 -0
- wbcore/crontab/serializers.py +23 -0
- wbcore/crontab/viewsets.py +9 -0
- wbcore/dispatch.py +55 -0
- wbcore/docs/__init__.py +25 -0
- wbcore/docs/orderable.md +29 -0
- wbcore/docs/reparent.md +13 -0
- wbcore/dynamic_preferences_registry.py +29 -0
- wbcore/enums.py +98 -0
- wbcore/filters/__init__.py +21 -0
- wbcore/filters/backends.py +19 -0
- wbcore/filters/defaults.py +69 -0
- wbcore/filters/fields/__init__.py +15 -0
- wbcore/filters/fields/booleans.py +6 -0
- wbcore/filters/fields/choices.py +61 -0
- wbcore/filters/fields/content_type.py +33 -0
- wbcore/filters/fields/datetime.py +91 -0
- wbcore/filters/fields/models.py +113 -0
- wbcore/filters/fields/multiple_lookups.py +19 -0
- wbcore/filters/fields/numbers.py +46 -0
- wbcore/filters/fields/text.py +6 -0
- wbcore/filters/filterset.py +217 -0
- wbcore/filters/lookups.py +41 -0
- wbcore/filters/mixins.py +112 -0
- wbcore/filters/utils.py +21 -0
- wbcore/forms.py +125 -0
- wbcore/frontend.py +23 -0
- wbcore/frontend_user_configuration.py +96 -0
- wbcore/fsm/__init__.py +0 -0
- wbcore/fsm/markdown_extensions.py +31 -0
- wbcore/fsm/mixins.py +114 -0
- wbcore/management/__init__.py +88 -0
- wbcore/management/commands/__init__.py +0 -0
- wbcore/management/commands/bootstrap.py +18 -0
- wbcore/management/commands/clean_obsolete_object.py +21 -0
- wbcore/management/commands/handle_release_notes.py +53 -0
- wbcore/markdown/__init__.py +1 -0
- wbcore/markdown/admin.py +9 -0
- wbcore/markdown/dynamic_preferences_registry.py +16 -0
- wbcore/markdown/models.py +38 -0
- wbcore/markdown/template.py +38 -0
- wbcore/markdown/utils.py +36 -0
- wbcore/markdown/views.py +67 -0
- wbcore/menus/__init__.py +2 -0
- wbcore/menus/menus.py +96 -0
- wbcore/menus/registry.py +28 -0
- wbcore/menus/views.py +41 -0
- wbcore/messages.py +51 -0
- wbcore/metadata/__init__.py +0 -0
- wbcore/metadata/configs/__init__.py +0 -0
- wbcore/metadata/configs/base.py +86 -0
- wbcore/metadata/configs/buttons/__init__.py +4 -0
- wbcore/metadata/configs/buttons/bases.py +91 -0
- wbcore/metadata/configs/buttons/buttons.py +142 -0
- wbcore/metadata/configs/buttons/enums.py +25 -0
- wbcore/metadata/configs/buttons/metadata.py +8 -0
- wbcore/metadata/configs/buttons/view_config.py +176 -0
- wbcore/metadata/configs/display/__init__.py +4 -0
- wbcore/metadata/configs/display/configs.py +15 -0
- wbcore/metadata/configs/display/display.py +234 -0
- wbcore/metadata/configs/display/formatting.py +50 -0
- wbcore/metadata/configs/display/instance_display/__init__.py +15 -0
- wbcore/metadata/configs/display/instance_display/display.py +37 -0
- wbcore/metadata/configs/display/instance_display/enums.py +7 -0
- wbcore/metadata/configs/display/instance_display/layouts/__init__.py +3 -0
- wbcore/metadata/configs/display/instance_display/layouts/inlines.py +58 -0
- wbcore/metadata/configs/display/instance_display/layouts/layouts.py +77 -0
- wbcore/metadata/configs/display/instance_display/layouts/sections.py +43 -0
- wbcore/metadata/configs/display/instance_display/operators.py +22 -0
- wbcore/metadata/configs/display/instance_display/pages.py +40 -0
- wbcore/metadata/configs/display/instance_display/shortcuts.py +70 -0
- wbcore/metadata/configs/display/instance_display/signals.py +3 -0
- wbcore/metadata/configs/display/instance_display/styles.py +42 -0
- wbcore/metadata/configs/display/instance_display/utils.py +74 -0
- wbcore/metadata/configs/display/list_display.py +230 -0
- wbcore/metadata/configs/display/models.py +20 -0
- wbcore/metadata/configs/display/view_config.py +82 -0
- wbcore/metadata/configs/display/views.py +48 -0
- wbcore/metadata/configs/display/windows.py +28 -0
- wbcore/metadata/configs/documentations.py +11 -0
- wbcore/metadata/configs/endpoints.py +176 -0
- wbcore/metadata/configs/fields.py +17 -0
- wbcore/metadata/configs/filter_fields.py +42 -0
- wbcore/metadata/configs/identifiers.py +25 -0
- wbcore/metadata/configs/ordering_fields.py +24 -0
- wbcore/metadata/configs/paginations.py +11 -0
- wbcore/metadata/configs/preview.py +41 -0
- wbcore/metadata/configs/primary_keys.py +9 -0
- wbcore/metadata/configs/search_fields.py +9 -0
- wbcore/metadata/configs/titles.py +48 -0
- wbcore/metadata/configs/window_types.py +13 -0
- wbcore/metadata/exceptions.py +0 -0
- wbcore/metadata/metadata.py +33 -0
- wbcore/metadata/mixins.py +105 -0
- wbcore/metadata/tests/__init__.py +0 -0
- wbcore/metadata/tests/test_buttons.py +179 -0
- wbcore/metadata/utils.py +4 -0
- wbcore/migrations/0001_initial_squashed_squashed_0010_preset_appliedpreset.py +398 -0
- wbcore/migrations/0011_genericmodel.py +22 -0
- wbcore/migrations/0012_delete_notification.py +15 -0
- wbcore/migrations/0013_delete_colorgradient.py +14 -0
- wbcore/migrations/0014_biguserobjectpermission_system.py +44 -0
- wbcore/migrations/__init__.py +0 -0
- wbcore/models/__init__.py +6 -0
- wbcore/models/base.py +182 -0
- wbcore/models/fields.py +29 -0
- wbcore/models/orderable.py +6 -0
- wbcore/pagination.py +65 -0
- wbcore/pandas/__init__.py +0 -0
- wbcore/pandas/fields.py +136 -0
- wbcore/pandas/filters.py +113 -0
- wbcore/pandas/filterset.py +26 -0
- wbcore/pandas/metadata.py +14 -0
- wbcore/pandas/utils.py +129 -0
- wbcore/pandas/views.py +157 -0
- wbcore/permissions/__init__.py +0 -0
- wbcore/permissions/backend.py +35 -0
- wbcore/permissions/mixins.py +72 -0
- wbcore/permissions/permissions.py +50 -0
- wbcore/permissions/registry.py +32 -0
- wbcore/permissions/shortcuts.py +37 -0
- wbcore/permissions/utils.py +26 -0
- wbcore/release_notes/__init__.py +0 -0
- wbcore/release_notes/admin.py +30 -0
- wbcore/release_notes/buttons.py +25 -0
- wbcore/release_notes/display.py +57 -0
- wbcore/release_notes/filters.py +35 -0
- wbcore/release_notes/models.py +65 -0
- wbcore/release_notes/serializers.py +19 -0
- wbcore/release_notes/utils.py +14 -0
- wbcore/release_notes/viewsets.py +45 -0
- wbcore/reversion/__init__.py +0 -0
- wbcore/reversion/filters.py +38 -0
- wbcore/reversion/serializers.py +80 -0
- wbcore/reversion/viewsets/__init__.py +6 -0
- wbcore/reversion/viewsets/buttons.py +94 -0
- wbcore/reversion/viewsets/displays.py +44 -0
- wbcore/reversion/viewsets/endpoints.py +29 -0
- wbcore/reversion/viewsets/titles.py +17 -0
- wbcore/reversion/viewsets/viewsets.py +111 -0
- wbcore/routers.py +63 -0
- wbcore/search/__init__.py +62 -0
- wbcore/serializers/__init__.py +66 -0
- wbcore/serializers/fields/__init__.py +58 -0
- wbcore/serializers/fields/boolean.py +51 -0
- wbcore/serializers/fields/choice.py +36 -0
- wbcore/serializers/fields/datetime.py +143 -0
- wbcore/serializers/fields/fields.py +190 -0
- wbcore/serializers/fields/file.py +20 -0
- wbcore/serializers/fields/fsm.py +20 -0
- wbcore/serializers/fields/json.py +56 -0
- wbcore/serializers/fields/list.py +105 -0
- wbcore/serializers/fields/mixins.py +175 -0
- wbcore/serializers/fields/number.py +103 -0
- wbcore/serializers/fields/other.py +42 -0
- wbcore/serializers/fields/primary_key.py +22 -0
- wbcore/serializers/fields/related.py +152 -0
- wbcore/serializers/fields/text.py +136 -0
- wbcore/serializers/fields/types.py +41 -0
- wbcore/serializers/mixins.py +24 -0
- wbcore/serializers/serializers.py +415 -0
- wbcore/serializers/utils.py +142 -0
- wbcore/shares/__init__.py +1 -0
- wbcore/shares/config.py +63 -0
- wbcore/shares/decorator.py +13 -0
- wbcore/shares/signals.py +3 -0
- wbcore/shares/sites.py +28 -0
- wbcore/shares/views.py +24 -0
- wbcore/signals/__init__.py +6 -0
- wbcore/signals/filters.py +3 -0
- wbcore/signals/instance_buttons.py +5 -0
- wbcore/signals/merge.py +4 -0
- wbcore/signals/models.py +8 -0
- wbcore/signals/permissions.py +3 -0
- wbcore/signals/serializers.py +5 -0
- wbcore/tasks.py +83 -0
- wbcore/templates/reversion/__init__.py +0 -0
- wbcore/templates/reversion/compare_detail.html +19 -0
- wbcore/test/__init__.py +30 -0
- wbcore/test/mixins.py +709 -0
- wbcore/test/signals.py +6 -0
- wbcore/test/tests.py +131 -0
- wbcore/test/utils.py +227 -0
- wbcore/tests/__init__.py +0 -0
- wbcore/tests/conftest.py +55 -0
- wbcore/tests/e2e/__init__.py +0 -0
- wbcore/tests/e2e/test_e2e.py +24 -0
- wbcore/tests/models.py +6 -0
- wbcore/tests/test_cache/__init__.py +0 -0
- wbcore/tests/test_cache/test_decorators.py +30 -0
- wbcore/tests/test_cache/test_mixins.py +29 -0
- wbcore/tests/test_cache/test_registry.py +57 -0
- wbcore/tests/test_configs.py +65 -0
- wbcore/tests/test_enums.py +54 -0
- wbcore/tests/test_fields/__init__.py +0 -0
- wbcore/tests/test_fields/test_boolean_fields.py +48 -0
- wbcore/tests/test_fields/test_choice_fields.py +48 -0
- wbcore/tests/test_fields/test_datetime_fields.py +151 -0
- wbcore/tests/test_fields/test_fields.py +23 -0
- wbcore/tests/test_fields/test_file_fields.py +52 -0
- wbcore/tests/test_fields/test_json_fields.py +28 -0
- wbcore/tests/test_fields/test_list_fields.py +27 -0
- wbcore/tests/test_fields/test_mixins.py +111 -0
- wbcore/tests/test_fields/test_number_fields.py +190 -0
- wbcore/tests/test_fields/test_other_fields.py +61 -0
- wbcore/tests/test_fields/test_primary_key_fields.py +52 -0
- wbcore/tests/test_fields/test_related.py +80 -0
- wbcore/tests/test_fields/test_text_fields.py +117 -0
- wbcore/tests/test_filters/__init__.py +0 -0
- wbcore/tests/test_filters/test_mixins.py +108 -0
- wbcore/tests/test_filters/test_pandas.py +114 -0
- wbcore/tests/test_list_display.py +31 -0
- wbcore/tests/test_models/__init__.py +0 -0
- wbcore/tests/test_models/test_fields.py +25 -0
- wbcore/tests/test_models/test_mixins.py +31 -0
- wbcore/tests/test_new_display/__init__.py +0 -0
- wbcore/tests/test_new_display/test_inlines.py +13 -0
- wbcore/tests/test_new_display/test_layouts.py +15 -0
- wbcore/tests/test_new_display/test_operators.py +15 -0
- wbcore/tests/test_new_display/test_pages.py +8 -0
- wbcore/tests/test_new_display/test_sections.py +0 -0
- wbcore/tests/test_new_display/test_shortcuts.py +38 -0
- wbcore/tests/test_new_display/test_utils.py +48 -0
- wbcore/tests/test_pagination.py +31 -0
- wbcore/tests/test_serializers/__init__.py +0 -0
- wbcore/tests/test_serializers/test_fields.py +140 -0
- wbcore/tests/test_serializers/test_mixins.py +53 -0
- wbcore/tests/test_serializers/test_related.py +77 -0
- wbcore/tests/test_something.py +39 -0
- wbcore/tests/test_utils/__init__.py +0 -0
- wbcore/tests/test_utils/test_date.py +49 -0
- wbcore/tests/test_utils/test_date_builder.py +99 -0
- wbcore/tests/test_utils/test_primary.py +79 -0
- wbcore/tests/test_utils/test_signals.py +38 -0
- wbcore/tests/test_viewsets.py +20 -0
- wbcore/urls.py +114 -0
- wbcore/utils/__init__.py +13 -0
- wbcore/utils/cache.py +8 -0
- wbcore/utils/date.py +220 -0
- wbcore/utils/date_builder/__init__.py +18 -0
- wbcore/utils/date_builder/components.py +42 -0
- wbcore/utils/date_builder/offsets.py +27 -0
- wbcore/utils/deprecations.py +11 -0
- wbcore/utils/enum.py +23 -0
- wbcore/utils/figures.py +290 -0
- wbcore/utils/html.py +8 -0
- wbcore/utils/importlib.py +13 -0
- wbcore/utils/itertools.py +40 -0
- wbcore/utils/models.py +275 -0
- wbcore/utils/numbers.py +69 -0
- wbcore/utils/prettytable.py +35 -0
- wbcore/utils/print.py +29 -0
- wbcore/utils/renderers.py +13 -0
- wbcore/utils/rrules.py +37 -0
- wbcore/utils/serializers.py +8 -0
- wbcore/utils/settings.py +5 -0
- wbcore/utils/signals.py +36 -0
- wbcore/utils/string_loader.py +42 -0
- wbcore/utils/strings.py +77 -0
- wbcore/utils/task.py +6 -0
- wbcore/utils/urls.py +70 -0
- wbcore/utils/views.py +201 -0
- wbcore/views.py +26 -0
- wbcore/viewsets/__init__.py +10 -0
- wbcore/viewsets/encoders.py +18 -0
- wbcore/viewsets/generics.py +5 -0
- wbcore/viewsets/mixins.py +290 -0
- wbcore/viewsets/utils.py +26 -0
- wbcore/viewsets/viewsets.py +142 -0
- wbcore-2.2.1.dist-info/METADATA +62 -0
- wbcore-2.2.1.dist-info/RECORD +1035 -0
- wbcore-2.2.1.dist-info/WHEEL +5 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .assignees import *
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
from random import choices, randint
|
|
2
|
+
|
|
3
|
+
from django.utils.translation import gettext as _
|
|
4
|
+
from wbcore.contrib.authentication.models import User
|
|
5
|
+
from wbcore.contrib.workflow.models import ProcessStep
|
|
6
|
+
|
|
7
|
+
from ..decorators import register_assignee
|
|
8
|
+
|
|
9
|
+
# We need to migrate upon name changes!
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@register_assignee("Instance Assignee's Manager")
|
|
13
|
+
def manager_of_instance_assignee(process_step: ProcessStep, **kwargs) -> User | None:
|
|
14
|
+
if (
|
|
15
|
+
(assignee_field := kwargs.get("assignee_field"))
|
|
16
|
+
and (assignee_type := kwargs.get("assignee_type"))
|
|
17
|
+
and hasattr(process_step.process.instance, assignee_field)
|
|
18
|
+
):
|
|
19
|
+
assignee = getattr(process_step.process.instance, assignee_field)
|
|
20
|
+
if assignee_type == "employee":
|
|
21
|
+
for manager in assignee.get_managers():
|
|
22
|
+
if hasattr(manager, "user_account") and manager.user_account.is_active:
|
|
23
|
+
return manager.user_account
|
|
24
|
+
elif assignee_type == "entry":
|
|
25
|
+
for manager in assignee.relationship_managers.all():
|
|
26
|
+
if hasattr(manager, "user_account") and manager.user_account.is_active:
|
|
27
|
+
return manager.user_account
|
|
28
|
+
|
|
29
|
+
process_step.step.get_casted_step().set_failed(
|
|
30
|
+
process_step, _("Error in assignee method: Incorrect input in kwargs field!")
|
|
31
|
+
)
|
|
32
|
+
return None
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@register_assignee("Weighted Random Group Member")
|
|
36
|
+
def weighted_random(process_step: ProcessStep, **kwargs) -> User | None:
|
|
37
|
+
if (group := process_step.group) and (group_user_count := group.user_set.count()):
|
|
38
|
+
similar_process_steps_selected_assignees: list[str] = list(
|
|
39
|
+
ProcessStep.objects.filter(
|
|
40
|
+
state__in=[ProcessStep.StepState.FINISHED, ProcessStep.StepState.ACTIVE],
|
|
41
|
+
process=process_step.process,
|
|
42
|
+
group=group,
|
|
43
|
+
assignee__isnull=False,
|
|
44
|
+
step__step_type="UserStep",
|
|
45
|
+
)
|
|
46
|
+
.exclude(id=process_step.id)
|
|
47
|
+
.values_list("assignee", flat=True)
|
|
48
|
+
)
|
|
49
|
+
group_member_list: list[User] = list(group.user_set.all())
|
|
50
|
+
number_of_past_assignee_occurrences: list[int] = [
|
|
51
|
+
similar_process_steps_selected_assignees.count(x.pk) for x in group_member_list
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
if sum(number_of_past_assignee_occurrences):
|
|
55
|
+
# We redistribute each occurrence number between all of the other list items to increase their probability
|
|
56
|
+
redistributed_list: list[int] = [0 for i in range(group_user_count)]
|
|
57
|
+
for index, elem in enumerate(number_of_past_assignee_occurrences):
|
|
58
|
+
for index2, elem2 in enumerate(redistributed_list):
|
|
59
|
+
if not index2 == index:
|
|
60
|
+
redistributed_list[index2] += elem / (group_user_count - 1) if elem else 0
|
|
61
|
+
# Transform the list of absolute values into percentages
|
|
62
|
+
new_weights: list[float] = [x / sum(redistributed_list) for x in redistributed_list]
|
|
63
|
+
new_assignee: User = choices(group_member_list, weights=new_weights)[0]
|
|
64
|
+
else:
|
|
65
|
+
new_assignee: User = choices(group_member_list)[0]
|
|
66
|
+
return new_assignee
|
|
67
|
+
|
|
68
|
+
process_step.step.get_casted_step().set_failed(
|
|
69
|
+
process_step, _("Error in assignee method: No populated group to pick assignee from selected!")
|
|
70
|
+
)
|
|
71
|
+
return None
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@register_assignee("Random Group Member")
|
|
75
|
+
def random_group_member(process_step: ProcessStep, **kwargs) -> User | None:
|
|
76
|
+
if (group := process_step.group) and group.user_set.exists():
|
|
77
|
+
return group.user_set.all()[randint(0, group.user_set.count() - 1)]
|
|
78
|
+
|
|
79
|
+
process_step.step.get_casted_step().set_failed(
|
|
80
|
+
process_step, _("Error in assignee method: No populated group to pick assignee from selected!")
|
|
81
|
+
)
|
|
82
|
+
return None
|
|
File without changes
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from django_celery_beat.models import CrontabSchedule
|
|
2
|
+
from wbcore import serializers
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class CrontabScheduleRepresentationSerializer(serializers.RepresentationSerializer):
|
|
6
|
+
endpoint = "wbcore:crontabschedulerepresentation-list"
|
|
7
|
+
value_key = "id"
|
|
8
|
+
|
|
9
|
+
human_readable = serializers.SerializerMethodField()
|
|
10
|
+
obj_str = serializers.SerializerMethodField()
|
|
11
|
+
|
|
12
|
+
def get_obj_str(self, obj):
|
|
13
|
+
return str(obj)
|
|
14
|
+
|
|
15
|
+
def get_human_readable(self, obj):
|
|
16
|
+
return obj.human_readable
|
|
17
|
+
|
|
18
|
+
def __init__(self, *args, label_key="{{human_readable}} [ {{obj_str}} ]", **kwargs):
|
|
19
|
+
super().__init__(*args, label_key=label_key, **kwargs)
|
|
20
|
+
|
|
21
|
+
class Meta:
|
|
22
|
+
model = CrontabSchedule
|
|
23
|
+
fields = ("id", "month_of_year", "day_of_month", "day_of_week", "hour", "minute", "human_readable", "obj_str")
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
from django_celery_beat.models import CrontabSchedule
|
|
2
|
+
from wbcore import viewsets
|
|
3
|
+
|
|
4
|
+
from .serializers import CrontabScheduleRepresentationSerializer
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class CrontabScheduleRepresentationViewSet(viewsets.RepresentationViewSet):
|
|
8
|
+
queryset = CrontabSchedule.objects.all()
|
|
9
|
+
serializer_class = CrontabScheduleRepresentationSerializer
|
wbcore/dispatch.py
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
from django.apps import apps
|
|
2
|
+
from wbcore.utils.itertools import get_inheriting_subclasses
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def receiver_all_subclasses(signal, sender, *args, **kwargs):
|
|
6
|
+
def _decorator(func):
|
|
7
|
+
signal.connect(func, *args, sender=sender, dispatch_uid=func.__name__ + "_" + sender.__name__, **kwargs)
|
|
8
|
+
for subclass in sender.__subclasses__():
|
|
9
|
+
signal.connect(
|
|
10
|
+
func, *args, sender=subclass, dispatch_uid=func.__name__ + "_" + subclass.__name__, **kwargs
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
return func
|
|
14
|
+
|
|
15
|
+
return _decorator
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def receiver_subclasses(signal, sender, *args, only_leaf=True, **kwargs):
|
|
19
|
+
"""
|
|
20
|
+
A decorator for connecting receivers and all receiver's subclasses to signals. Used by passing in the
|
|
21
|
+
signal and keyword arguments to connect::
|
|
22
|
+
The signal needs to be registered after all child models are registered (e.g. by placing the signal in a dedicated
|
|
23
|
+
signal file)
|
|
24
|
+
@receiver_subclasses(post_save, sender=MyModel)
|
|
25
|
+
def signal_receiver(sender, **kwargs):
|
|
26
|
+
...
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
def _decorator(func):
|
|
30
|
+
if isinstance(sender, str):
|
|
31
|
+
sender_class = apps.get_model(sender)
|
|
32
|
+
else:
|
|
33
|
+
sender_class = sender
|
|
34
|
+
for snd in get_inheriting_subclasses(sender_class, only_leaf=only_leaf):
|
|
35
|
+
signal.connect(func, *args, sender=snd, dispatch_uid=func.__name__ + "_" + snd.__name__, **kwargs)
|
|
36
|
+
return func
|
|
37
|
+
|
|
38
|
+
return _decorator
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def receiver_inherited_through_models(signal, sender, through_field_name, **kwargs):
|
|
42
|
+
"""
|
|
43
|
+
A decorator for connecting receivers and all subclasses's through model'.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
def _decorator(func):
|
|
47
|
+
for sub_class in sender.__subclasses__():
|
|
48
|
+
if (through_field := getattr(sub_class, through_field_name, None)) and (
|
|
49
|
+
through_class := getattr(through_field, "through", None)
|
|
50
|
+
):
|
|
51
|
+
signal.connect(
|
|
52
|
+
func, sender=through_class, dispatch_uid=func.__name__ + "_" + through_class.__name__, **kwargs
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
return _decorator
|
wbcore/docs/__init__.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import markdown
|
|
2
|
+
from django.conf import settings
|
|
3
|
+
from markdown.extensions.tables import TableExtension
|
|
4
|
+
from markdown_blockdiag import BlockdiagExtension
|
|
5
|
+
from rest_framework.response import Response
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def get_markdown_docs(docs):
|
|
9
|
+
try:
|
|
10
|
+
with open(docs, "r") as f:
|
|
11
|
+
return Response(
|
|
12
|
+
markdown.markdown(
|
|
13
|
+
f.read(),
|
|
14
|
+
extensions=settings.WBCORE_DEFAULT_MARKDOWN_EXTENSIONS,
|
|
15
|
+
)
|
|
16
|
+
)
|
|
17
|
+
except FileNotFoundError:
|
|
18
|
+
return Response(
|
|
19
|
+
markdown.markdown(
|
|
20
|
+
docs,
|
|
21
|
+
extensions=settings.WBCORE_DEFAULT_MARKDOWN_EXTENSIONS,
|
|
22
|
+
)
|
|
23
|
+
)
|
|
24
|
+
except AttributeError:
|
|
25
|
+
return Response({"errors": "No documentation available."})
|
wbcore/docs/orderable.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Orderable View
|
|
2
|
+
|
|
3
|
+
An orderable view enables the user to freely reorder rows inside AG Grid by drag-and-drop.
|
|
4
|
+
|
|
5
|
+
**NOTE**: As these changes are saved in a model field, this will change the order globally for each user! Reordering on a per-user basis requires a way more sophisticated approach that is currently out of scope. Please also keep in mind that this also means that different orders for different views of the same model are not possible.
|
|
6
|
+
|
|
7
|
+
## Implementation Steps
|
|
8
|
+
|
|
9
|
+
### Simple Reordering
|
|
10
|
+
|
|
11
|
+
Reorder rows inside a basic list view. Also includes the first level of tree views (level 0).
|
|
12
|
+
|
|
13
|
+
1. Add the `OrderableModel` from `wbcore.models.orderable` to your model and migrate. Set initial values for existing instances by either `Model.orderable_objects.reset_order()` or calling `save()` on every object.
|
|
14
|
+
2. Add the `order` field to your serializer.
|
|
15
|
+
3. Add the `OrderableMixin` from `wbcore.viewsets.mixins` to your viewset. If you have defined a viewset ordering, make sure to first order by `order`.
|
|
16
|
+
4. Add both `reorderable_column="order"` and `reorderable_endpoint=reverse(f"{endpoint.basename}-reorder", args=["{{id}}"], request=self.request)` to your list display.
|
|
17
|
+
|
|
18
|
+
### Tree Child Reordering
|
|
19
|
+
|
|
20
|
+
We currently only support reordering the first child row (i.e. level 1).
|
|
21
|
+
|
|
22
|
+
1. Add the `OrderableModel` from `wbcore.models.orderable` to your model and migrate. Also add the class variable `PARTITION_BY` to your class and set it to the name of the foreign key field to the child's parent to partition the order values based on the parent. In this case the order number is unique only for the parent and not over the entire model anymore. Set initial values for existing instances by either `Model.orderable_objects.reset_order()` or calling `save()` on every object.
|
|
23
|
+
2. Add the `order` field to your serializer.
|
|
24
|
+
3. Add the `OrderableMixin` from `wbcore.viewsets.mixins` to your viewset. If you have defined a viewset ordering, make sure to first order by `order`.
|
|
25
|
+
4. Add both `tree_reorderable_column="order"` and `tree_reorderable_endpoint=reverse(f"{endpoint.basename}-reorder", args=["{{id}}"], request=self.request)` to **the parent's** list display.
|
|
26
|
+
|
|
27
|
+
## Example
|
|
28
|
+
|
|
29
|
+
For an example please take a look at _example_app/team_. In this case we wanted both level 0 (Team) and level 1 (Player) to be reorderable so this example incorporates both a simple reordering for the parent level and a tree child reordering for the child level.
|
wbcore/docs/reparent.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Reparent View
|
|
2
|
+
|
|
3
|
+
A reparent view enables the user to switch a child's parent object inside a tree view by drag-and-dropping the child inside the new parent. Please note that this is currently only supported with level 1 children inside the tree view.
|
|
4
|
+
|
|
5
|
+
## Implementation Steps
|
|
6
|
+
|
|
7
|
+
1. Add a `PARENT_FK` class variable to the child's model and set it to the field name of the foreign key to the parent.
|
|
8
|
+
2. Add the `ReparentMixin` from `wbcore.viewsets.mixins` to your viewset.
|
|
9
|
+
3. Add both `tree_reparent_pk_field=f"{pk_field_name}"` and `tree_reparent_endpoint=reverse(f"{endpoint.basename}-reparent", args=["{{id}}"], request=self.request)` to the parent's list display.
|
|
10
|
+
|
|
11
|
+
## Example
|
|
12
|
+
|
|
13
|
+
For an example please take a look at _example_app/team_. Drag-and-dropping a child (Player) inside a new parent (Team) will transfer this player to a new team.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from django.utils.translation import gettext as _
|
|
2
|
+
from dynamic_preferences.preferences import Section
|
|
3
|
+
from dynamic_preferences.registries import global_preferences_registry
|
|
4
|
+
from dynamic_preferences.types import IntegerPreference, StringPreference
|
|
5
|
+
|
|
6
|
+
wbcore = Section("wbcore")
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@global_preferences_registry.register
|
|
10
|
+
class RetentionPeriod(IntegerPreference):
|
|
11
|
+
section = wbcore
|
|
12
|
+
name = "retention_period"
|
|
13
|
+
default = 365
|
|
14
|
+
|
|
15
|
+
verbose_name = _("Retention Period in Days")
|
|
16
|
+
help_text = _(
|
|
17
|
+
"When an object cannot be deleted and is disabled instead, it gets hidden from the queryset but not deleted. For compliance reasons we enable the retention for a specific period of days (defaults to a year)"
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@global_preferences_registry.register
|
|
22
|
+
class SystemUserEmailPeriod(StringPreference):
|
|
23
|
+
section = wbcore
|
|
24
|
+
name = "system_user_email"
|
|
25
|
+
|
|
26
|
+
default = "system@stainly-bench.com"
|
|
27
|
+
|
|
28
|
+
verbose_name = _("System User Email")
|
|
29
|
+
help_text = _("System User Email")
|
wbcore/enums.py
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
from typing import Union
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class RequestType(Enum):
|
|
6
|
+
GET = "get"
|
|
7
|
+
POST = "post"
|
|
8
|
+
DELETE = "delete"
|
|
9
|
+
PATCH = "patch"
|
|
10
|
+
PUT = "put"
|
|
11
|
+
OPTIONS = "options"
|
|
12
|
+
HEAD = "head"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class Button(Enum):
|
|
16
|
+
# Buttons
|
|
17
|
+
REFRESH = "refresh"
|
|
18
|
+
NEW = "new"
|
|
19
|
+
DELETE = "delete"
|
|
20
|
+
|
|
21
|
+
# Buttons and Create Buttons
|
|
22
|
+
SAVE = "save"
|
|
23
|
+
SAVE_AND_CLOSE = "saveandclose"
|
|
24
|
+
SAVE_AND_NEW = "saveandnew"
|
|
25
|
+
|
|
26
|
+
# Create Buttons
|
|
27
|
+
RESET = "reset"
|
|
28
|
+
|
|
29
|
+
# Custom Buttons
|
|
30
|
+
DROPDOWN = "dropdown"
|
|
31
|
+
HYPERLINK = "hyperlink"
|
|
32
|
+
WIDGET = "widget"
|
|
33
|
+
ACTION = "action"
|
|
34
|
+
|
|
35
|
+
@classmethod
|
|
36
|
+
def buttons(cls):
|
|
37
|
+
return [
|
|
38
|
+
cls.REFRESH.value,
|
|
39
|
+
cls.NEW.value,
|
|
40
|
+
cls.DELETE.value,
|
|
41
|
+
cls.SAVE.value,
|
|
42
|
+
cls.SAVE_AND_CLOSE.value,
|
|
43
|
+
cls.SAVE_AND_NEW.value,
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
@classmethod
|
|
47
|
+
def create_buttons(cls):
|
|
48
|
+
return [
|
|
49
|
+
cls.SAVE.value,
|
|
50
|
+
cls.SAVE_AND_CLOSE.value,
|
|
51
|
+
cls.SAVE_AND_NEW.value,
|
|
52
|
+
cls.RESET.value,
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
@classmethod
|
|
56
|
+
def custom_buttons(cls):
|
|
57
|
+
return [
|
|
58
|
+
cls.DROPDOWN.value,
|
|
59
|
+
cls.HYPERLINK.value,
|
|
60
|
+
cls.WIDGET.value,
|
|
61
|
+
cls.ACTION.value,
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class WidgetType(Enum):
|
|
66
|
+
LIST = "list"
|
|
67
|
+
INSTANCE = "instance"
|
|
68
|
+
CHART = "chart"
|
|
69
|
+
SELECT = "select"
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class Operator(Enum):
|
|
73
|
+
EQUAL = "=="
|
|
74
|
+
UNEQUAL = "!="
|
|
75
|
+
GREATER = ">"
|
|
76
|
+
GREATER_EQUAL = ">="
|
|
77
|
+
LESS = "<"
|
|
78
|
+
LESS_EQUAL = "<="
|
|
79
|
+
EXISTS = "∃"
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class Unit(Enum):
|
|
83
|
+
FRACTION = "fr"
|
|
84
|
+
REM = "rem"
|
|
85
|
+
PIXEL = "px"
|
|
86
|
+
|
|
87
|
+
def __call__(self, _value):
|
|
88
|
+
return (float(_value), self.value)
|
|
89
|
+
|
|
90
|
+
def unit(self, _value: Union[float, str, int]):
|
|
91
|
+
assert isinstance(_value, (float, str, int)), "_value needs to be one of str, float or int"
|
|
92
|
+
|
|
93
|
+
return f"{float(_value)}{self.value}"
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class AuthType(Enum):
|
|
97
|
+
NONE = "NONE"
|
|
98
|
+
JWT = "JWT"
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from .backends import DjangoFilterBackend
|
|
2
|
+
from .fields import (
|
|
3
|
+
BooleanFilter,
|
|
4
|
+
CharFilter,
|
|
5
|
+
ChoiceFilter,
|
|
6
|
+
DateFilter,
|
|
7
|
+
DateRangeFilter,
|
|
8
|
+
FinancialPerformanceDateRangeFilter,
|
|
9
|
+
DateTimeFilter,
|
|
10
|
+
DateTimeRangeFilter,
|
|
11
|
+
ModelChoiceFilter,
|
|
12
|
+
ModelMultipleChoiceFilter,
|
|
13
|
+
MultipleChoiceContentTypeFilter,
|
|
14
|
+
MultipleChoiceFilter,
|
|
15
|
+
NumberFilter,
|
|
16
|
+
YearFilter,
|
|
17
|
+
RangeSelectFilter,
|
|
18
|
+
TimeFilter,
|
|
19
|
+
MultipleLookupFilter,
|
|
20
|
+
)
|
|
21
|
+
from .filterset import FilterSet
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from django_filters.rest_framework import DjangoFilterBackend as StandardFilterBackend
|
|
2
|
+
|
|
3
|
+
from .filterset import FilterSet
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class DjangoFilterBackend(StandardFilterBackend):
|
|
7
|
+
filterset_base = FilterSet
|
|
8
|
+
|
|
9
|
+
def get_filterset_kwargs(self, request, queryset, view):
|
|
10
|
+
return {"data": request.query_params, "queryset": queryset, "request": request, "view": view}
|
|
11
|
+
|
|
12
|
+
def get_filterset_class(self, view, queryset=None):
|
|
13
|
+
if method := getattr(view, "get_filterset_class", None):
|
|
14
|
+
view.filterset_class = method(view.request)
|
|
15
|
+
|
|
16
|
+
if method := getattr(view, "get_filterset_fields", None):
|
|
17
|
+
view.filterset_fields = method(view.request)
|
|
18
|
+
|
|
19
|
+
return super().get_filterset_class(view, queryset)
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
from calendar import monthrange
|
|
2
|
+
from datetime import date, timedelta
|
|
3
|
+
|
|
4
|
+
from django.utils.timezone import localdate
|
|
5
|
+
from psycopg.types.range import DateRange
|
|
6
|
+
from rest_framework.exceptions import APIException
|
|
7
|
+
from wbcore.utils.date import get_end_date_from_date, get_start_date_from_date
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def current_quarter_date_start(*args, **kwargs):
|
|
11
|
+
return get_start_date_from_date(localdate())
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def current_quarter_date_end(*args, **kwargs):
|
|
15
|
+
return get_end_date_from_date(localdate())
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def current_quarter_date_range(*args, **kwargs):
|
|
19
|
+
return DateRange(current_quarter_date_start(*args, **kwargs), current_quarter_date_end(*args, **kwargs))
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def current_month_date_start(*args, **kwargs):
|
|
23
|
+
today = date.today()
|
|
24
|
+
return date(today.year, today.month, 1)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def current_month_date_end(*args, **kwargs):
|
|
28
|
+
today = date.today()
|
|
29
|
+
return date(today.year, today.month, monthrange(today.year, today.month)[1])
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def current_month_date_range(*args, **kwargs):
|
|
33
|
+
return DateRange(current_month_date_start(*args, **kwargs), current_month_date_end(*args, **kwargs))
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def current_year_date_range(*args, **kwargs):
|
|
37
|
+
d = localdate()
|
|
38
|
+
return DateRange(date(d.year, 1, 1), max((date(d.year + 1, 1, 1), d + timedelta(days=60))))
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def year_to_date_range(*args, **kwargs):
|
|
42
|
+
d = localdate()
|
|
43
|
+
return DateRange(d.replace(day=1, month=1), d.today())
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def n_year_data_range(n: int, *args, **kwargs):
|
|
47
|
+
d = localdate()
|
|
48
|
+
return DateRange(d - timedelta(days=n * 365), d)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def one_year_date_range(*args, **kwargs):
|
|
52
|
+
return n_year_data_range(1)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def five_year_data_range(*args, **kwargs):
|
|
56
|
+
return n_year_data_range(5)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def current_quarter_date_interval(*args, **kwargs):
|
|
60
|
+
return (
|
|
61
|
+
current_quarter_date_start(),
|
|
62
|
+
current_quarter_date_end(*args, **kwargs),
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class RequiredFilterMissing(APIException):
|
|
67
|
+
status_code = 400
|
|
68
|
+
default_detail = "Required filters are not available in the query parameters."
|
|
69
|
+
default_code = "required_filters_missing"
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from .choices import ChoiceFilter, MultipleChoiceField, MultipleChoiceFilter
|
|
2
|
+
from .datetime import (
|
|
3
|
+
TimeFilter,
|
|
4
|
+
DateTimeFilter,
|
|
5
|
+
DateFilter,
|
|
6
|
+
DateRangeFilter,
|
|
7
|
+
DateTimeRangeFilter,
|
|
8
|
+
FinancialPerformanceDateRangeFilter,
|
|
9
|
+
)
|
|
10
|
+
from .models import ModelChoiceFilter, ModelMultipleChoiceFilter
|
|
11
|
+
from .numbers import NumberFilter, YearFilter, RangeSelectFilter
|
|
12
|
+
from .text import CharFilter
|
|
13
|
+
from .booleans import BooleanFilter
|
|
14
|
+
from .content_type import MultipleChoiceContentTypeFilter
|
|
15
|
+
from .multiple_lookups import MultipleLookupFilter
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import itertools
|
|
2
|
+
from urllib.parse import quote
|
|
3
|
+
|
|
4
|
+
import django_filters
|
|
5
|
+
from django_filters.filters import MultipleChoiceField
|
|
6
|
+
from wbcore.filters.mixins import WBCoreFilterMixin
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class WBCoreChoiceFilterMixin(WBCoreFilterMixin):
|
|
10
|
+
def __init__(self, *args, **kwargs):
|
|
11
|
+
self.choices = kwargs["choices"]
|
|
12
|
+
super().__init__(*args, **kwargs)
|
|
13
|
+
|
|
14
|
+
def get_representation(self, request, name, view):
|
|
15
|
+
representation, lookup_expr = super().get_representation(request, name, view)
|
|
16
|
+
lookup_expr["input_properties"]["choices"] = list()
|
|
17
|
+
if callable(self.choices):
|
|
18
|
+
choice_keys = [
|
|
19
|
+
choice[0] for choice in self.field.choices
|
|
20
|
+
] # we save the choices key for validation in case we narrow down the choices list in get_representation
|
|
21
|
+
# we get a new choices set but make sure its keys are still valid regarding the initial choices
|
|
22
|
+
choices = list(filter(lambda x: x[0] in choice_keys, self.choices(request, view)))
|
|
23
|
+
else:
|
|
24
|
+
choices = self.choices
|
|
25
|
+
|
|
26
|
+
for choice in choices:
|
|
27
|
+
lookup_expr["input_properties"]["choices"].append(
|
|
28
|
+
{"value": quote(choice[0]) if isinstance(choice[0], str) else choice[0], "label": choice[1]}
|
|
29
|
+
)
|
|
30
|
+
return representation, lookup_expr
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class ChoiceFilter(WBCoreChoiceFilterMixin, django_filters.ChoiceFilter):
|
|
34
|
+
filter_type = "select"
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class WBCoreMultipleChoiceField(MultipleChoiceField):
|
|
38
|
+
def to_python(self, value):
|
|
39
|
+
# We do this because DRF wrap a coma seperated list of choices into a one list element
|
|
40
|
+
if value and isinstance(value, list):
|
|
41
|
+
value = list(itertools.chain(*[v.split(",") for v in value]))
|
|
42
|
+
return super().to_python(value)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class MultipleChoiceFilter(WBCoreChoiceFilterMixin, django_filters.MultipleChoiceFilter):
|
|
46
|
+
field_class = WBCoreMultipleChoiceField
|
|
47
|
+
filter_type = "select"
|
|
48
|
+
|
|
49
|
+
def _validate_default_with_request(self, default, request, name):
|
|
50
|
+
if request_default := request.GET.get(name):
|
|
51
|
+
return request_default.split(",")
|
|
52
|
+
return default
|
|
53
|
+
|
|
54
|
+
def get_representation(self, request, name, view):
|
|
55
|
+
representation, lookup_expr = super().get_representation(request, name, view)
|
|
56
|
+
lookup_expr["input_properties"]["multiple"] = True
|
|
57
|
+
if (default := lookup_expr["input_properties"].get("default")) and not isinstance(default, list):
|
|
58
|
+
lookup_expr["input_properties"]["default"] = [default]
|
|
59
|
+
if (initial := lookup_expr["input_properties"].get("initial")) and not isinstance(initial, list):
|
|
60
|
+
lookup_expr["input_properties"]["initial"] = [initial]
|
|
61
|
+
return representation, lookup_expr
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import operator
|
|
2
|
+
from functools import reduce
|
|
3
|
+
|
|
4
|
+
import django_filters
|
|
5
|
+
from django.contrib.contenttypes.models import ContentType
|
|
6
|
+
from django.db.models import Q
|
|
7
|
+
from django_filters.constants import EMPTY_VALUES
|
|
8
|
+
from wbcore.filters.mixins import WBCoreFilterMixin
|
|
9
|
+
from wbcore.forms import ContentTypeMultiValueField
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class MultipleChoiceContentTypeFilter(WBCoreFilterMixin, django_filters.Filter):
|
|
13
|
+
field_class = ContentTypeMultiValueField
|
|
14
|
+
filter_type = "text"
|
|
15
|
+
|
|
16
|
+
def __init__(self, object_id_label="object_id", content_type_label="content_type", **kwargs):
|
|
17
|
+
self.object_id_label = object_id_label
|
|
18
|
+
self.content_type_label = content_type_label
|
|
19
|
+
super().__init__(**kwargs)
|
|
20
|
+
|
|
21
|
+
def filter(self, qs, value):
|
|
22
|
+
if value in EMPTY_VALUES:
|
|
23
|
+
return qs
|
|
24
|
+
if self.distinct:
|
|
25
|
+
qs = qs.distinct()
|
|
26
|
+
conditions = [
|
|
27
|
+
(
|
|
28
|
+
Q(**{self.content_type_label: ContentType.objects.get_for_model(val)})
|
|
29
|
+
& Q(**{self.object_id_label: val.id})
|
|
30
|
+
)
|
|
31
|
+
for val in value
|
|
32
|
+
]
|
|
33
|
+
return qs.filter(reduce(operator.or_, conditions))
|