django-spire 0.23.6__py3-none-any.whl → 0.23.8__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.
- django_spire/ai/admin.py +11 -11
- django_spire/ai/chat/apps.py +1 -0
- django_spire/ai/chat/templates/django_spire/ai/chat/widget/dialog_widget.html +1 -1
- django_spire/ai/chat/tests/factories.py +15 -0
- django_spire/ai/chat/tests/test_controller.py +45 -0
- django_spire/ai/chat/tests/test_models.py +301 -0
- django_spire/ai/chat/tests/test_prompts.py +48 -0
- django_spire/ai/chat/tests/test_responses.py +208 -0
- django_spire/ai/chat/tests/test_router/test_base_chat_router.py +66 -6
- django_spire/ai/chat/tests/test_router/test_chat_workflow.py +73 -3
- django_spire/ai/chat/tests/test_router/test_integration.py +86 -6
- django_spire/ai/chat/tests/test_router/test_intent_decoder.py +93 -1
- django_spire/ai/chat/tests/test_router/test_message_intel.py +60 -1
- django_spire/ai/chat/tests/test_router/test_spire_chat_router.py +110 -0
- django_spire/ai/chat/tests/test_urls/test_json_urls.py +202 -1
- django_spire/ai/context/tests/__init__.py +0 -0
- django_spire/ai/context/tests/test_context.py +188 -0
- django_spire/ai/decorators.py +7 -6
- django_spire/ai/prompt/tests/test_bots.py +100 -10
- django_spire/ai/prompt/tests/test_prompt_intel.py +83 -0
- django_spire/ai/prompt/tests/test_prompt_tuning.py +126 -0
- django_spire/ai/sms/decorators.py +8 -2
- django_spire/ai/sms/tests/test_sms.py +240 -16
- django_spire/ai/sms/tests/test_sms_intel.py +42 -0
- django_spire/ai/sms/tests/test_webhook.py +155 -7
- django_spire/ai/sms/views.py +23 -24
- django_spire/ai/tests/test_ai.py +131 -7
- django_spire/auth/apps.py +4 -2
- django_spire/auth/controller/controller.py +36 -23
- django_spire/auth/controller/exceptions.py +9 -0
- django_spire/auth/group/admin.py +1 -0
- django_spire/auth/group/apps.py +2 -0
- django_spire/auth/group/factories.py +17 -8
- django_spire/auth/group/forms.py +7 -0
- django_spire/auth/group/tests/test_factories.py +146 -0
- django_spire/auth/group/tests/test_forms.py +282 -0
- django_spire/auth/group/tests/test_models.py +192 -0
- django_spire/auth/group/tests/test_querysets.py +98 -0
- django_spire/auth/group/tests/test_utils.py +341 -0
- django_spire/auth/group/tests/test_views.py +377 -0
- django_spire/auth/group/urls/__init__.py +3 -1
- django_spire/auth/group/urls/form_urls.py +2 -0
- django_spire/auth/group/urls/json_urls.py +3 -0
- django_spire/auth/group/urls/page_urls.py +2 -0
- django_spire/auth/group/utils.py +6 -2
- django_spire/auth/group/views/form_views.py +6 -3
- django_spire/auth/group/views/json_views.py +6 -2
- django_spire/auth/mfa/admin.py +2 -0
- django_spire/auth/mfa/apps.py +2 -0
- django_spire/auth/mfa/forms.py +1 -0
- django_spire/auth/mfa/querysets.py +9 -2
- django_spire/auth/mfa/tests/test_models.py +233 -0
- django_spire/auth/mfa/tests/test_utils.py +106 -0
- django_spire/auth/mfa/urls/__init__.py +2 -0
- django_spire/auth/mfa/urls/page_urls.py +2 -0
- django_spire/auth/mfa/urls/redirect_urls.py +2 -0
- django_spire/auth/mfa/views/page_views.py +2 -1
- django_spire/auth/permissions/consts.py +2 -2
- django_spire/auth/permissions/decorators.py +8 -8
- django_spire/auth/permissions/permissions.py +28 -35
- django_spire/auth/permissions/tests/test_decorators.py +333 -0
- django_spire/auth/permissions/tests/test_permissions.py +337 -0
- django_spire/auth/permissions/tests/test_tools.py +305 -0
- django_spire/auth/permissions/tools.py +21 -15
- django_spire/auth/seeding/seed.py +3 -0
- django_spire/auth/seeding/seeder.py +2 -0
- django_spire/auth/tests/test_controller.py +323 -0
- django_spire/auth/tests/test_url_endpoints.py +9 -9
- django_spire/auth/tests/test_views.py +406 -0
- django_spire/auth/urls/admin_urls.py +2 -0
- django_spire/auth/urls/redirect_urls.py +2 -0
- django_spire/auth/user/apps.py +2 -0
- django_spire/auth/user/forms.py +9 -0
- django_spire/auth/user/models.py +1 -1
- django_spire/auth/user/services/services.py +1 -0
- django_spire/auth/user/tests/factories.py +14 -13
- django_spire/auth/user/tests/test_factories.py +166 -2
- django_spire/auth/user/tests/test_forms.py +573 -0
- django_spire/auth/user/tests/test_models.py +257 -0
- django_spire/auth/user/tests/test_services.py +200 -0
- django_spire/auth/user/tests/test_tools.py +153 -0
- django_spire/auth/user/tests/test_user_factories.py +139 -0
- django_spire/auth/user/tests/test_views.py +363 -0
- django_spire/auth/user/tools.py +7 -1
- django_spire/auth/user/urls/form_urls.py +3 -0
- django_spire/auth/user/urls/page_urls.py +3 -0
- django_spire/auth/user/views/form_views.py +19 -10
- django_spire/auth/user/views/page_views.py +8 -2
- django_spire/auth/views/redirect_views.py +14 -9
- django_spire/comment/admin.py +2 -0
- django_spire/comment/apps.py +2 -0
- django_spire/comment/templatetags/comment_tags.py +1 -0
- django_spire/comment/tests/test_forms.py +27 -0
- django_spire/comment/tests/test_models.py +215 -0
- django_spire/comment/tests/test_querysets.py +101 -0
- django_spire/comment/tests/test_utils.py +90 -0
- django_spire/comment/urls.py +2 -0
- django_spire/comment/utils.py +22 -13
- django_spire/comment/views.py +1 -1
- django_spire/conf.py +8 -6
- django_spire/consts.py +1 -1
- django_spire/contrib/breadcrumb/apps.py +2 -0
- django_spire/contrib/breadcrumb/breadcrumbs.py +18 -18
- django_spire/contrib/breadcrumb/tests/test_breadcrumbs.py +198 -0
- django_spire/contrib/constructor/__init__.py +3 -3
- django_spire/contrib/constructor/constructor.py +15 -15
- django_spire/contrib/constructor/django_model_constructor.py +5 -4
- django_spire/contrib/constructor/exceptions.py +5 -3
- django_spire/contrib/constructor/tests/__init__.py +0 -0
- django_spire/contrib/constructor/tests/test_constructor.py +193 -0
- django_spire/contrib/form/tests/__init__.py +0 -0
- django_spire/contrib/form/tests/test_forms.py +203 -0
- django_spire/contrib/generic_views/modal_views.py +2 -1
- django_spire/contrib/generic_views/portal_views.py +20 -19
- django_spire/contrib/generic_views/tests/__init__.py +0 -0
- django_spire/contrib/generic_views/tests/test_views.py +459 -0
- django_spire/contrib/help/apps.py +2 -0
- django_spire/contrib/help/templatetags/help.py +1 -0
- django_spire/contrib/help/tests/__init__.py +0 -0
- django_spire/contrib/help/tests/test_templatetags.py +100 -0
- django_spire/contrib/options/mixins.py +6 -5
- django_spire/contrib/options/tests/factories.py +5 -1
- django_spire/contrib/options/tests/test_options.py +234 -0
- django_spire/contrib/ordering/exceptions.py +7 -3
- django_spire/contrib/ordering/mixins.py +2 -0
- django_spire/contrib/ordering/querysets.py +3 -1
- django_spire/contrib/ordering/services/processor_service.py +8 -4
- django_spire/contrib/ordering/services/service.py +1 -2
- django_spire/contrib/ordering/tests/__init__.py +0 -0
- django_spire/contrib/ordering/tests/test_ordering.py +165 -0
- django_spire/contrib/ordering/validators.py +6 -6
- django_spire/contrib/pagination/templatetags/pagination_tags.py +12 -5
- django_spire/contrib/pagination/tests/__init__.py +0 -0
- django_spire/contrib/pagination/tests/test_pagination.py +179 -0
- django_spire/contrib/performance/decorators.py +16 -6
- django_spire/contrib/performance/tests/__init__.py +0 -0
- django_spire/contrib/performance/tests/test_performance.py +107 -0
- django_spire/contrib/progress/__init__.py +1 -3
- django_spire/contrib/progress/static/django_spire/js/contrib/progress/progress.js +38 -82
- django_spire/contrib/queryset/enums.py +3 -1
- django_spire/contrib/queryset/filter_tools.py +10 -5
- django_spire/contrib/queryset/mixins.py +16 -16
- django_spire/contrib/queryset/tests/__init__.py +0 -0
- django_spire/contrib/queryset/tests/test_queryset.py +137 -0
- django_spire/contrib/seeding/field/base.py +13 -7
- django_spire/contrib/seeding/field/callable.py +8 -1
- django_spire/contrib/seeding/field/cleaners.py +5 -5
- django_spire/contrib/seeding/field/custom.py +20 -10
- django_spire/contrib/seeding/field/django/seeder.py +8 -6
- django_spire/contrib/seeding/field/enums.py +7 -5
- django_spire/contrib/seeding/field/override.py +16 -6
- django_spire/contrib/seeding/field/static.py +9 -2
- django_spire/contrib/seeding/field/tests/test_base.py +18 -14
- django_spire/contrib/seeding/field/tests/test_callable.py +13 -9
- django_spire/contrib/seeding/field/tests/test_cleaners.py +51 -38
- django_spire/contrib/seeding/field/tests/test_static.py +13 -9
- django_spire/contrib/seeding/intelligence/bots/seeder_generator_bot.py +2 -0
- django_spire/contrib/seeding/intelligence/intel.py +5 -1
- django_spire/contrib/seeding/intelligence/prompts/factory.py +6 -1
- django_spire/contrib/seeding/intelligence/prompts/foreign_key_selection_prompt.py +6 -1
- django_spire/contrib/seeding/intelligence/prompts/generate_django_model_seeder_prompts.py +2 -0
- django_spire/contrib/seeding/intelligence/prompts/generic_relationship_selection_prompt.py +7 -1
- django_spire/contrib/seeding/intelligence/prompts/hierarchical_selection_prompt.py +6 -2
- django_spire/contrib/seeding/intelligence/prompts/model_field_choices_prompt.py +8 -2
- django_spire/contrib/seeding/intelligence/prompts/negation_prompt.py +2 -0
- django_spire/contrib/seeding/intelligence/prompts/objective_prompt.py +6 -1
- django_spire/contrib/seeding/management/commands/seeding.py +9 -3
- django_spire/contrib/seeding/management/example.py +2 -0
- django_spire/contrib/seeding/model/base.py +16 -7
- django_spire/contrib/seeding/model/config.py +31 -15
- django_spire/contrib/seeding/model/django/config.py +13 -13
- django_spire/contrib/seeding/model/django/seeder.py +4 -4
- django_spire/contrib/seeding/model/django/tests/test_seeder.py +34 -23
- django_spire/contrib/seeding/model/enums.py +2 -0
- django_spire/contrib/seeding/tests/test_config.py +71 -0
- django_spire/contrib/seeding/tests/test_custom.py +35 -0
- django_spire/contrib/seeding/tests/test_enums.py +40 -0
- django_spire/contrib/seeding/tests/test_intel.py +32 -0
- django_spire/contrib/seeding/tests/test_override.py +63 -0
- django_spire/contrib/service/__init__.py +2 -2
- django_spire/contrib/service/django_model_service.py +16 -15
- django_spire/contrib/service/exceptions.py +5 -3
- django_spire/contrib/service/tests/__init__.py +0 -0
- django_spire/contrib/service/tests/test_service.py +153 -0
- django_spire/contrib/session/apps.py +2 -0
- django_spire/contrib/session/controller.py +48 -42
- django_spire/contrib/session/templatetags/session_tags.py +11 -2
- django_spire/contrib/session/tests/test_session_controller.py +117 -53
- django_spire/contrib/tests/__init__.py +0 -0
- django_spire/contrib/tests/test_utils.py +37 -0
- django_spire/contrib/utils.py +4 -1
- django_spire/core/apps.py +2 -0
- django_spire/core/converters/tests/test_to_data.py +353 -0
- django_spire/core/converters/tests/test_to_enums.py +61 -41
- django_spire/core/converters/tests/test_to_pydantic.py +138 -109
- django_spire/core/converters/to_data.py +29 -10
- django_spire/core/converters/to_enums.py +4 -2
- django_spire/core/converters/to_pydantic.py +22 -22
- django_spire/core/decorators.py +19 -6
- django_spire/core/forms/widgets.py +4 -0
- django_spire/core/maps.py +3 -1
- django_spire/core/middleware/maintenance.py +3 -3
- django_spire/core/middleware.py +8 -6
- django_spire/core/redirect/__init__.py +5 -0
- django_spire/core/redirect/generic_redirect.py +1 -2
- django_spire/core/redirect/tests/__init__.py +0 -0
- django_spire/core/redirect/tests/test_generic_redirect.py +34 -0
- django_spire/core/{tests/tests_redirect.py → redirect/tests/test_safe_redirect.py} +55 -81
- django_spire/core/shortcuts.py +3 -3
- django_spire/core/static/django_spire/css/app-layout.css +1 -1
- django_spire/core/static/django_spire/css/app-navigation.css +3 -3
- django_spire/core/static/django_spire/css/bootstrap-override.css +4 -0
- django_spire/core/tag/admin.py +12 -0
- django_spire/core/tag/intelligence/tag_set_bot.py +2 -0
- django_spire/core/tag/mixins.py +2 -0
- django_spire/core/tag/models.py +2 -0
- django_spire/core/tag/querysets.py +2 -0
- django_spire/core/tag/service/tag_service.py +6 -3
- django_spire/core/tag/tests/test_intelligence.py +9 -9
- django_spire/core/tag/tests/test_tags.py +44 -54
- django_spire/core/tag/tests/test_tools.py +191 -0
- django_spire/core/tag/tools.py +3 -0
- django_spire/core/templates/django_spire/card/card.html +5 -2
- django_spire/core/templates/django_spire/card/title_card.html +9 -4
- django_spire/core/templates/django_spire/infinite_scroll/base.html +1 -0
- django_spire/core/templates/django_spire/navigation/side_navigation.html +19 -24
- django_spire/core/templates/django_spire/page/full_page.html +46 -16
- django_spire/core/templates/django_spire/table/base.html +4 -2
- django_spire/core/templatetags/json.py +6 -2
- django_spire/core/templatetags/message.py +13 -8
- django_spire/core/templatetags/string_formating.py +8 -5
- django_spire/core/templatetags/tests/__init__.py +0 -0
- django_spire/core/templatetags/tests/test_templatetags.py +427 -0
- django_spire/core/templatetags/variable_types.py +17 -9
- django_spire/core/tests/test_cases.py +1 -1
- django_spire/core/tests/test_conf.py +43 -0
- django_spire/core/tests/test_consts.py +28 -0
- django_spire/core/tests/test_context_processors.py +93 -0
- django_spire/core/tests/test_decorators.py +95 -0
- django_spire/core/tests/test_django_spire_utils.py +56 -0
- django_spire/core/tests/test_exceptions.py +37 -0
- django_spire/core/tests/test_models.py +54 -0
- django_spire/core/tests/test_settings.py +45 -0
- django_spire/core/tests/test_shortcuts.py +74 -0
- django_spire/core/tests/test_urls.py +16 -0
- django_spire/core/tests/test_utils.py +58 -0
- django_spire/core/urls.py +4 -1
- django_spire/core/utils.py +12 -8
- django_spire/exceptions.py +16 -1
- django_spire/file/admin.py +4 -2
- django_spire/file/apps.py +8 -10
- django_spire/file/fields.py +7 -7
- django_spire/file/forms.py +1 -1
- django_spire/file/interfaces.py +15 -15
- django_spire/file/mixins.py +1 -4
- django_spire/file/models.py +3 -5
- django_spire/file/tests/factories.py +59 -0
- django_spire/file/tests/test_admin.py +69 -0
- django_spire/file/tests/test_apps.py +24 -0
- django_spire/file/tests/test_fields.py +114 -0
- django_spire/file/tests/test_forms.py +20 -0
- django_spire/file/tests/test_interfaces.py +183 -0
- django_spire/file/tests/test_models.py +82 -0
- django_spire/file/tests/test_querysets.py +102 -0
- django_spire/file/tests/test_utils.py +32 -0
- django_spire/file/tests/test_views.py +145 -0
- django_spire/file/tests/test_widgets.py +82 -0
- django_spire/file/tools.py +8 -2
- django_spire/file/views.py +7 -3
- django_spire/file/widgets.py +12 -12
- django_spire/help_desk/admin.py +15 -0
- django_spire/help_desk/apps.py +2 -0
- django_spire/help_desk/auth/controller.py +2 -0
- django_spire/help_desk/choices.py +2 -0
- django_spire/help_desk/enums.py +2 -0
- django_spire/help_desk/exceptions.py +31 -3
- django_spire/help_desk/forms.py +2 -0
- django_spire/help_desk/models.py +2 -0
- django_spire/help_desk/querysets.py +4 -1
- django_spire/help_desk/services/notification_service.py +26 -27
- django_spire/help_desk/services/service.py +2 -3
- django_spire/help_desk/tests/factories.py +8 -3
- django_spire/help_desk/tests/test_admin.py +41 -0
- django_spire/help_desk/tests/test_apps.py +41 -0
- django_spire/help_desk/tests/test_choices.py +50 -0
- django_spire/help_desk/tests/test_controller.py +87 -0
- django_spire/help_desk/tests/test_enums.py +18 -0
- django_spire/help_desk/tests/test_exceptions.py +37 -0
- django_spire/help_desk/tests/test_forms.py +89 -0
- django_spire/help_desk/tests/test_models.py +59 -0
- django_spire/help_desk/tests/test_querysets.py +38 -0
- django_spire/help_desk/tests/test_services/test_notification_service.py +15 -8
- django_spire/help_desk/tests/test_services/test_service.py +92 -0
- django_spire/help_desk/tests/test_urls/test_form_urls.py +6 -6
- django_spire/help_desk/tests/test_urls/test_page_urls.py +8 -9
- django_spire/help_desk/tests/test_views/test_form_views.py +46 -19
- django_spire/help_desk/tests/test_views/test_page_views.py +32 -9
- django_spire/help_desk/urls/__init__.py +4 -1
- django_spire/help_desk/urls/form_urls.py +3 -0
- django_spire/help_desk/urls/page_urls.py +3 -0
- django_spire/help_desk/views/form_views.py +13 -5
- django_spire/help_desk/views/page_views.py +11 -3
- django_spire/history/activity/admin.py +2 -0
- django_spire/history/activity/apps.py +3 -1
- django_spire/history/activity/mixins.py +13 -7
- django_spire/history/activity/models.py +6 -5
- django_spire/history/activity/querysets.py +2 -0
- django_spire/history/activity/tests/__init__.py +0 -0
- django_spire/history/activity/tests/test_activity.py +176 -0
- django_spire/history/admin.py +9 -2
- django_spire/history/choices.py +3 -0
- django_spire/history/models.py +5 -5
- django_spire/history/tests/test_admin.py +93 -0
- django_spire/history/tests/test_history.py +101 -0
- django_spire/history/tests/test_mixins.py +84 -0
- django_spire/history/viewed/admin.py +3 -1
- django_spire/history/viewed/apps.py +3 -1
- django_spire/history/viewed/models.py +2 -0
- django_spire/history/viewed/tests/__init__.py +0 -0
- django_spire/history/viewed/tests/test_viewed.py +46 -0
- django_spire/knowledge/auth/tests/__init__.py +0 -0
- django_spire/knowledge/auth/tests/test_controller.py +116 -0
- django_spire/knowledge/collection/admin.py +5 -1
- django_spire/knowledge/collection/models.py +3 -1
- django_spire/knowledge/collection/seeding/seed.py +1 -0
- django_spire/knowledge/collection/services/factory_service.py +10 -11
- django_spire/knowledge/collection/services/ordering_service.py +1 -2
- django_spire/knowledge/collection/services/service.py +5 -10
- django_spire/knowledge/collection/services/tag_service.py +5 -2
- django_spire/knowledge/collection/tests/factories.py +28 -1
- django_spire/knowledge/collection/tests/test_models.py +48 -0
- django_spire/knowledge/collection/tests/test_querysets.py +93 -0
- django_spire/knowledge/collection/tests/test_services/test_factory_service.py +100 -0
- django_spire/knowledge/collection/tests/test_services/test_services.py +160 -0
- django_spire/knowledge/collection/tests/test_urls/test_form_urls.py +21 -3
- django_spire/knowledge/collection/tests/test_urls/test_json_urls.py +39 -1
- django_spire/knowledge/collection/tests/test_urls/test_page_urls.py +12 -4
- django_spire/knowledge/collection/urls/__init__.py +3 -0
- django_spire/knowledge/collection/urls/form_urls.py +2 -0
- django_spire/knowledge/collection/urls/json_urls.py +2 -0
- django_spire/knowledge/collection/urls/page_urls.py +2 -0
- django_spire/knowledge/collection/views/form_views.py +4 -4
- django_spire/knowledge/collection/views/json_views.py +5 -1
- django_spire/knowledge/collection/views/page_views.py +5 -2
- django_spire/knowledge/entry/admin.py +7 -1
- django_spire/knowledge/entry/forms.py +2 -0
- django_spire/knowledge/entry/models.py +2 -0
- django_spire/knowledge/entry/seeding/seed.py +3 -0
- django_spire/knowledge/entry/services/automation_service.py +5 -4
- django_spire/knowledge/entry/services/factory_service.py +7 -5
- django_spire/knowledge/entry/services/service.py +4 -7
- django_spire/knowledge/entry/services/tag_service.py +0 -1
- django_spire/knowledge/entry/services/tool_service.py +1 -0
- django_spire/knowledge/entry/services/transformation_services.py +1 -5
- django_spire/knowledge/entry/tests/factories.py +1 -2
- django_spire/knowledge/entry/tests/test_factory_service.py +20 -0
- django_spire/knowledge/entry/tests/test_models.py +41 -0
- django_spire/knowledge/entry/tests/test_querysets.py +71 -0
- django_spire/knowledge/entry/tests/test_services.py +94 -0
- django_spire/knowledge/entry/tests/test_urls/test_form_urls.py +9 -14
- django_spire/knowledge/entry/tests/test_urls/test_json_urls.py +48 -5
- django_spire/knowledge/entry/tests/test_urls/test_page_urls.py +6 -8
- django_spire/knowledge/entry/tests/test_urls/test_template_urls.py +40 -0
- django_spire/knowledge/entry/urls/form_urls.py +2 -0
- django_spire/knowledge/entry/urls/json_urls.py +2 -0
- django_spire/knowledge/entry/urls/page_urls.py +2 -0
- django_spire/knowledge/entry/urls/template_urls.py +2 -0
- django_spire/knowledge/entry/version/block/choices.py +2 -0
- django_spire/knowledge/entry/version/block/data/data.py +1 -0
- django_spire/knowledge/entry/version/block/data/list/data.py +8 -13
- django_spire/knowledge/entry/version/block/data/list/maps.py +3 -0
- django_spire/knowledge/entry/version/block/data/list/meta.py +1 -2
- django_spire/knowledge/entry/version/block/data/list/tests/__init__.py +0 -0
- django_spire/knowledge/entry/version/block/data/list/tests/test_maps.py +32 -0
- django_spire/knowledge/entry/version/block/data/list/tests/test_meta.py +58 -0
- django_spire/knowledge/entry/version/block/data/maps.py +3 -6
- django_spire/knowledge/entry/version/block/models.py +7 -5
- django_spire/knowledge/entry/version/block/seeding/constants.py +5 -4
- django_spire/knowledge/entry/version/block/services/service.py +2 -3
- django_spire/knowledge/entry/version/block/tests/factories.py +4 -10
- django_spire/knowledge/entry/version/block/tests/test_choices.py +56 -0
- django_spire/knowledge/entry/version/block/tests/test_data.py +90 -0
- django_spire/knowledge/entry/version/block/tests/test_maps.py +37 -0
- django_spire/knowledge/entry/version/block/tests/test_models.py +55 -0
- django_spire/knowledge/entry/version/block/tests/test_querysets.py +35 -0
- django_spire/knowledge/entry/version/block/tests/test_services.py +65 -0
- django_spire/knowledge/entry/version/choices.py +2 -0
- django_spire/knowledge/entry/version/converters/converter.py +1 -1
- django_spire/knowledge/entry/version/converters/docx_converter.py +4 -7
- django_spire/knowledge/entry/version/converters/markdown_converter.py +20 -20
- django_spire/knowledge/entry/version/maps.py +4 -5
- django_spire/knowledge/entry/version/querysets.py +1 -1
- django_spire/knowledge/entry/version/seeding/seeder.py +1 -2
- django_spire/knowledge/entry/version/services/processor_service.py +5 -4
- django_spire/knowledge/entry/version/services/service.py +1 -2
- django_spire/knowledge/entry/version/tests/factories.py +2 -2
- django_spire/knowledge/entry/version/tests/test_choices.py +18 -0
- django_spire/knowledge/entry/version/tests/test_converters/test_docx_converter.py +56 -8
- django_spire/knowledge/entry/version/tests/test_converters/test_markdown_converter.py +78 -0
- django_spire/knowledge/entry/version/tests/test_maps.py +58 -0
- django_spire/knowledge/entry/version/tests/test_models.py +23 -0
- django_spire/knowledge/entry/version/tests/test_querysets.py +26 -0
- django_spire/knowledge/entry/version/tests/test_services.py +62 -0
- django_spire/knowledge/entry/version/tests/test_urls/test_json_urls.py +27 -8
- django_spire/knowledge/entry/version/tests/test_urls/test_page_urls.py +15 -8
- django_spire/knowledge/entry/version/tests/test_urls/test_redirect_urls.py +38 -0
- django_spire/knowledge/entry/version/urls/__init__.py +3 -0
- django_spire/knowledge/entry/version/urls/json_urls.py +2 -1
- django_spire/knowledge/entry/version/urls/page_urls.py +2 -0
- django_spire/knowledge/entry/version/urls/redirect_urls.py +2 -0
- django_spire/knowledge/entry/version/views/json_views.py +5 -1
- django_spire/knowledge/entry/version/views/page_views.py +10 -3
- django_spire/knowledge/entry/version/views/redirect_views.py +5 -1
- django_spire/knowledge/entry/views/form_views.py +16 -8
- django_spire/knowledge/entry/views/json_views.py +3 -1
- django_spire/knowledge/entry/views/page_views.py +8 -2
- django_spire/knowledge/entry/views/template_views.py +7 -1
- django_spire/knowledge/exceptions.py +2 -1
- django_spire/knowledge/intelligence/intel/answer_intel.py +2 -1
- django_spire/knowledge/intelligence/intel/entry_intel.py +0 -1
- django_spire/knowledge/intelligence/workflows/knowledge_workflow.py +4 -5
- django_spire/knowledge/models.py +1 -2
- django_spire/knowledge/tests/__init__.py +0 -0
- django_spire/knowledge/tests/test_templatetags.py +40 -0
- django_spire/knowledge/tests/test_urls/__init__.py +0 -0
- django_spire/knowledge/tests/test_urls/test_page_urls.py +24 -0
- django_spire/knowledge/urls/__init__.py +2 -0
- django_spire/knowledge/urls/page_urls.py +2 -0
- django_spire/knowledge/views/page_views.py +8 -3
- django_spire/notification/admin.py +3 -1
- django_spire/notification/app/admin.py +2 -0
- django_spire/notification/app/apps.py +3 -1
- django_spire/notification/app/exceptions.py +9 -2
- django_spire/notification/app/models.py +8 -4
- django_spire/notification/app/processor.py +22 -26
- django_spire/notification/app/querysets.py +2 -0
- django_spire/notification/app/tests/__init__.py +0 -0
- django_spire/notification/app/tests/factories.py +34 -0
- django_spire/notification/app/tests/test_apps.py +24 -0
- django_spire/notification/app/tests/test_models.py +72 -0
- django_spire/notification/app/tests/test_processor.py +111 -0
- django_spire/notification/app/tests/test_querysets.py +90 -0
- django_spire/notification/app/tests/test_views/__init__.py +0 -0
- django_spire/notification/app/tests/test_views/test_json_views.py +48 -0
- django_spire/notification/app/tests/test_views/test_page_views.py +19 -0
- django_spire/notification/app/urls/__init__.py +3 -1
- django_spire/notification/app/urls/json_urls.py +6 -4
- django_spire/notification/app/urls/page_urls.py +4 -3
- django_spire/notification/app/urls/template_urls.py +4 -2
- django_spire/notification/apps.py +4 -1
- django_spire/notification/email/admin.py +5 -1
- django_spire/notification/email/apps.py +3 -1
- django_spire/notification/email/exceptions.py +4 -2
- django_spire/notification/email/helper.py +5 -3
- django_spire/notification/email/models.py +4 -0
- django_spire/notification/email/processor.py +19 -15
- django_spire/notification/email/querysets.py +3 -0
- django_spire/notification/email/tests/__init__.py +0 -0
- django_spire/notification/email/tests/factories.py +35 -0
- django_spire/notification/email/tests/test_apps.py +24 -0
- django_spire/notification/email/tests/test_models.py +52 -0
- django_spire/notification/email/tests/test_processor.py +92 -0
- django_spire/notification/email/tests/test_querysets.py +43 -0
- django_spire/notification/exceptions.py +17 -2
- django_spire/notification/managers.py +7 -1
- django_spire/notification/maps.py +4 -1
- django_spire/notification/mixins.py +2 -0
- django_spire/notification/models.py +3 -1
- django_spire/notification/processors/notification.py +12 -5
- django_spire/notification/processors/processor.py +2 -0
- django_spire/notification/processors/tests/__init__.py +0 -0
- django_spire/notification/processors/tests/test_notification.py +106 -0
- django_spire/notification/push/admin.py +10 -1
- django_spire/notification/push/apps.py +3 -1
- django_spire/notification/push/models.py +2 -3
- django_spire/notification/push/tests/__init__.py +0 -0
- django_spire/notification/push/tests/test_apps.py +24 -0
- django_spire/notification/push/tests/test_models.py +28 -0
- django_spire/notification/querysets.py +7 -1
- django_spire/notification/sms/admin.py +2 -0
- django_spire/notification/sms/apps.py +4 -1
- django_spire/notification/sms/automations.py +2 -0
- django_spire/notification/sms/choices.py +2 -0
- django_spire/notification/sms/exceptions.py +19 -5
- django_spire/notification/sms/helper.py +33 -23
- django_spire/notification/sms/models.py +5 -1
- django_spire/notification/sms/processor.py +20 -20
- django_spire/notification/sms/querysets.py +2 -0
- django_spire/notification/sms/tests/factories.py +33 -0
- django_spire/notification/sms/tests/test_apps.py +24 -0
- django_spire/notification/sms/tests/test_automation.py +38 -0
- django_spire/notification/sms/tests/test_choices.py +15 -0
- django_spire/notification/sms/tests/test_consts.py +17 -0
- django_spire/notification/sms/tests/test_exceptions.py +27 -0
- django_spire/notification/sms/tests/test_helper.py +50 -0
- django_spire/notification/sms/tests/test_models.py +81 -0
- django_spire/notification/sms/tests/test_processor.py +107 -0
- django_spire/notification/sms/tests/test_tools.py +25 -11
- django_spire/notification/sms/tools.py +16 -5
- django_spire/notification/sms/urls/__init__.py +3 -1
- django_spire/notification/sms/urls/media_urls.py +2 -0
- django_spire/notification/sms/views/media_views.py +14 -4
- django_spire/notification/tests/__init__.py +0 -0
- django_spire/notification/tests/factories.py +26 -0
- django_spire/notification/tests/test_admin.py +55 -0
- django_spire/notification/tests/test_apps.py +30 -0
- django_spire/notification/tests/test_automation.py +18 -0
- django_spire/notification/tests/test_choices.py +59 -0
- django_spire/notification/tests/test_exceptions.py +58 -0
- django_spire/notification/tests/test_managers.py +100 -0
- django_spire/notification/tests/test_maps.py +31 -0
- django_spire/notification/tests/test_models.py +76 -0
- django_spire/notification/tests/test_querysets.py +184 -0
- django_spire/notification/tests/test_utils.py +23 -0
- django_spire/notification/urls.py +3 -1
- django_spire/notification/utils.py +3 -1
- django_spire/settings.py +3 -0
- django_spire/theme/tests/test_context_processor.py +15 -13
- django_spire/theme/tests/test_enums.py +2 -2
- django_spire/theme/tests/test_filesystem.py +2 -5
- django_spire/theme/tests/test_integration.py +12 -12
- django_spire/theme/tests/test_model.py +40 -38
- django_spire/theme/tests/test_views/test_json_views.py +33 -33
- django_spire/theme/urls/json_urls.py +3 -0
- django_spire/theme/urls/page_urls.py +3 -0
- django_spire/urls.py +19 -15
- django_spire/utils.py +13 -4
- {django_spire-0.23.6.dist-info → django_spire-0.23.8.dist-info}/METADATA +1 -1
- {django_spire-0.23.6.dist-info → django_spire-0.23.8.dist-info}/RECORD +532 -361
- django_spire/contrib/options/tests/test_unit.py +0 -148
- django_spire/contrib/progress/views.py +0 -64
- django_spire/contrib/seeding/tests/test_seeding.py +0 -25
- django_spire/core/tests/test_templatetags.py +0 -117
- django_spire/core/tests/tests_shortcuts.py +0 -73
- django_spire/history/activity/tests.py +0 -3
- django_spire/history/activity/views.py +0 -3
- django_spire/knowledge/collection/tests/test_services/test_transformation_service.py +0 -71
- django_spire/notification/app/tests.py +0 -3
- {django_spire-0.23.6.dist-info → django_spire-0.23.8.dist-info}/WHEEL +0 -0
- {django_spire-0.23.6.dist-info → django_spire-0.23.8.dist-info}/licenses/LICENSE.md +0 -0
- {django_spire-0.23.6.dist-info → django_spire-0.23.8.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
# import json
|
|
4
|
+
|
|
5
|
+
from django.contrib.sites.models import Site
|
|
6
|
+
# from django.conf import settings
|
|
7
|
+
# from django.test import RequestFactory
|
|
8
|
+
|
|
9
|
+
from django_spire.core.tests.test_cases import BaseTestCase
|
|
10
|
+
from django_spire.knowledge.collection.models import Collection
|
|
11
|
+
from django_spire.knowledge.collection.tests.factories import create_test_collection
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class CollectionServiceTests(BaseTestCase):
|
|
15
|
+
def setUp(self):
|
|
16
|
+
super().setUp()
|
|
17
|
+
self.collection = create_test_collection()
|
|
18
|
+
|
|
19
|
+
def test_save_model_obj_creates_new(self):
|
|
20
|
+
collection, created = Collection.services.save_model_obj(
|
|
21
|
+
name='New Collection',
|
|
22
|
+
description='A new collection'
|
|
23
|
+
)
|
|
24
|
+
assert created is True
|
|
25
|
+
assert collection.name == 'New Collection'
|
|
26
|
+
|
|
27
|
+
def test_save_model_obj_updates_existing(self):
|
|
28
|
+
self.collection.services.obj = self.collection
|
|
29
|
+
updated_collection, created = self.collection.services.save_model_obj(
|
|
30
|
+
name='Updated Name'
|
|
31
|
+
)
|
|
32
|
+
assert created is False
|
|
33
|
+
assert updated_collection.name == 'Updated Name'
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class CollectionOrderingServiceTests(BaseTestCase):
|
|
37
|
+
def setUp(self):
|
|
38
|
+
super().setUp()
|
|
39
|
+
self.parent = create_test_collection(name='Parent')
|
|
40
|
+
self.child1 = create_test_collection(parent=self.parent, name='Child 1')
|
|
41
|
+
self.child2 = create_test_collection(parent=self.parent, name='Child 2')
|
|
42
|
+
|
|
43
|
+
def test_reorder_within_same_parent(self):
|
|
44
|
+
self.child2.services.ordering.reorder(order=0, new_parent_pk=self.parent.pk)
|
|
45
|
+
self.child1.refresh_from_db()
|
|
46
|
+
self.child2.refresh_from_db()
|
|
47
|
+
assert self.child2.order <= self.child1.order
|
|
48
|
+
|
|
49
|
+
def test_reorder_to_new_parent(self):
|
|
50
|
+
new_parent = create_test_collection(name='New Parent')
|
|
51
|
+
self.child1.services.ordering.reorder(order=0, new_parent_pk=new_parent.pk)
|
|
52
|
+
self.child1.refresh_from_db()
|
|
53
|
+
assert self.child1.parent_id == new_parent.pk
|
|
54
|
+
|
|
55
|
+
def test_reorder_to_root(self):
|
|
56
|
+
self.child1.services.ordering.reorder(order=0, new_parent_pk=None)
|
|
57
|
+
self.child1.refresh_from_db()
|
|
58
|
+
assert self.child1.parent_id is None
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class CollectionProcessorServiceTests(BaseTestCase):
|
|
62
|
+
def setUp(self):
|
|
63
|
+
super().setUp()
|
|
64
|
+
self.parent = create_test_collection(name='Parent')
|
|
65
|
+
self.child = create_test_collection(parent=self.parent, name='Child')
|
|
66
|
+
|
|
67
|
+
def test_set_deleted(self):
|
|
68
|
+
self.parent.services.processor.set_deleted()
|
|
69
|
+
self.parent.refresh_from_db()
|
|
70
|
+
assert self.parent.is_deleted is True
|
|
71
|
+
|
|
72
|
+
def test_set_deleted_cascades_to_children(self):
|
|
73
|
+
self.parent.services.processor.set_deleted()
|
|
74
|
+
self.child.refresh_from_db()
|
|
75
|
+
assert self.child.is_deleted is True
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class CollectionToolServiceTests(BaseTestCase):
|
|
79
|
+
def setUp(self):
|
|
80
|
+
super().setUp()
|
|
81
|
+
self.parent = create_test_collection(name='Parent')
|
|
82
|
+
self.child = create_test_collection(parent=self.parent, name='Child')
|
|
83
|
+
self.grandchild = create_test_collection(parent=self.child, name='Grandchild')
|
|
84
|
+
|
|
85
|
+
def test_get_children_ids(self):
|
|
86
|
+
children_ids = Collection.services.tool.get_children_ids(parent_id=self.parent.pk)
|
|
87
|
+
assert self.child.pk in children_ids
|
|
88
|
+
assert self.grandchild.pk in children_ids
|
|
89
|
+
assert self.parent.pk not in children_ids
|
|
90
|
+
|
|
91
|
+
def test_get_root_collection_pk(self):
|
|
92
|
+
self.grandchild.services.tool.obj = self.grandchild
|
|
93
|
+
root_pk = self.grandchild.services.tool.get_root_collection_pk()
|
|
94
|
+
assert root_pk == self.parent.pk
|
|
95
|
+
|
|
96
|
+
def test_get_root_collection_pk_when_already_root(self):
|
|
97
|
+
self.parent.services.tool.obj = self.parent
|
|
98
|
+
root_pk = self.parent.services.tool.get_root_collection_pk()
|
|
99
|
+
assert root_pk == self.parent.pk
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
class TestCollectionTransformationService(BaseTestCase):
|
|
103
|
+
def setUp(self):
|
|
104
|
+
super().setUp()
|
|
105
|
+
self.site = Site.objects.create(domain='', name='')
|
|
106
|
+
|
|
107
|
+
def _test_collection_urls_json(self, collection_json: dict):
|
|
108
|
+
response = self.client.get(collection_json['delete_url'].replace(' ', ''))
|
|
109
|
+
assert response.status_code == 200
|
|
110
|
+
|
|
111
|
+
response = self.client.get(collection_json['create_entry_url'].replace(' ', ''))
|
|
112
|
+
assert response.status_code == 200
|
|
113
|
+
|
|
114
|
+
response = self.client.get(collection_json['import_entry_url'].replace(' ', ''))
|
|
115
|
+
assert response.status_code == 200
|
|
116
|
+
|
|
117
|
+
# # TODO(Tyrell): Talk to Chase about this
|
|
118
|
+
# def test_to_hierarchy_json(self):
|
|
119
|
+
# settings.SITE_ID = self.site.id
|
|
120
|
+
|
|
121
|
+
# self.test_collection_1 = Collection.objects.create(name='Grand Parent A', id=1, parent_id=None)
|
|
122
|
+
# self.test_collection_2 = Collection.objects.create(name='Parent A1', id=2, parent_id=1)
|
|
123
|
+
# self.test_collection_3 = Collection.objects.create(name='Child A1a', id=3, parent_id=2)
|
|
124
|
+
|
|
125
|
+
# request = RequestFactory().get('/')
|
|
126
|
+
# request.user = self.super_user
|
|
127
|
+
|
|
128
|
+
# family_tree = Collection.services.transformation.to_hierarchy_json(
|
|
129
|
+
# request=request
|
|
130
|
+
# )
|
|
131
|
+
|
|
132
|
+
# for collection_json in json.loads(family_tree):
|
|
133
|
+
# assert collection_json['id'] is not None
|
|
134
|
+
# assert collection_json['name'] == 'Grand Parent A'
|
|
135
|
+
|
|
136
|
+
# assert len(collection_json['entries']) == 0
|
|
137
|
+
|
|
138
|
+
# self._test_collection_urls_json(collection_json=collection_json)
|
|
139
|
+
|
|
140
|
+
# assert len(collection_json['children']) == 1
|
|
141
|
+
|
|
142
|
+
# for child_json in collection_json['children']:
|
|
143
|
+
# assert child_json['id'] is not None
|
|
144
|
+
# assert child_json['name'] == 'Parent A1'
|
|
145
|
+
|
|
146
|
+
# assert len(child_json['entries']) == 0
|
|
147
|
+
|
|
148
|
+
# self._test_collection_urls_json(collection_json=child_json)
|
|
149
|
+
|
|
150
|
+
# assert len(child_json['children']) == 1
|
|
151
|
+
|
|
152
|
+
# for grand_child_json in child_json['children']:
|
|
153
|
+
# assert grand_child_json['id'] is not None
|
|
154
|
+
# assert grand_child_json['name'] == 'Child A1a'
|
|
155
|
+
|
|
156
|
+
# assert len(grand_child_json['entries']) == 0
|
|
157
|
+
|
|
158
|
+
# self._test_collection_urls_json(collection_json=grand_child_json)
|
|
159
|
+
|
|
160
|
+
# assert len(grand_child_json['children']) == 0
|
|
@@ -3,17 +3,35 @@ from __future__ import annotations
|
|
|
3
3
|
from django.urls import reverse
|
|
4
4
|
|
|
5
5
|
from django_spire.core.tests.test_cases import BaseTestCase
|
|
6
|
+
from django_spire.knowledge.collection.tests.factories import create_test_collection
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
class CollectionFormUrlsTests(BaseTestCase):
|
|
9
10
|
def setUp(self):
|
|
10
11
|
super().setUp()
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
self.collection = create_test_collection()
|
|
14
|
+
|
|
15
|
+
def test_create_form_view_url_path(self):
|
|
16
|
+
response = self.client.get(
|
|
17
|
+
reverse('django_spire:knowledge:collection:form:create')
|
|
18
|
+
)
|
|
19
|
+
assert response.status_code == 200
|
|
20
|
+
|
|
21
|
+
def test_create_with_parent_form_view_url_path(self):
|
|
13
22
|
response = self.client.get(
|
|
14
23
|
reverse(
|
|
15
|
-
'django_spire:knowledge:collection:form:
|
|
24
|
+
'django_spire:knowledge:collection:form:create_with_parent',
|
|
25
|
+
kwargs={'parent_pk': self.collection.pk}
|
|
16
26
|
)
|
|
17
27
|
)
|
|
28
|
+
assert response.status_code == 200
|
|
18
29
|
|
|
19
|
-
|
|
30
|
+
def test_update_form_view_url_path(self):
|
|
31
|
+
response = self.client.get(
|
|
32
|
+
reverse(
|
|
33
|
+
'django_spire:knowledge:collection:form:update',
|
|
34
|
+
kwargs={'pk': self.collection.pk}
|
|
35
|
+
)
|
|
36
|
+
)
|
|
37
|
+
assert response.status_code == 200
|
|
@@ -21,5 +21,43 @@ class CollectionJsonUrlsTests(BaseTestCase):
|
|
|
21
21
|
},
|
|
22
22
|
content_type='application/json',
|
|
23
23
|
)
|
|
24
|
+
assert response.status_code == 200
|
|
24
25
|
|
|
25
|
-
|
|
26
|
+
def test_reorder_view_with_parent(self):
|
|
27
|
+
child_collection = create_test_collection(
|
|
28
|
+
parent=self.test_collection,
|
|
29
|
+
name='Child Collection'
|
|
30
|
+
)
|
|
31
|
+
response = self.client.post(
|
|
32
|
+
reverse('django_spire:knowledge:collection:json:reorder'),
|
|
33
|
+
data={
|
|
34
|
+
'collection_id': child_collection.pk,
|
|
35
|
+
'order': 0,
|
|
36
|
+
'parent': self.test_collection.pk
|
|
37
|
+
},
|
|
38
|
+
content_type='application/json',
|
|
39
|
+
)
|
|
40
|
+
assert response.status_code == 200
|
|
41
|
+
|
|
42
|
+
def test_reorder_view_invalid_collection(self):
|
|
43
|
+
response = self.client.post(
|
|
44
|
+
reverse('django_spire:knowledge:collection:json:reorder'),
|
|
45
|
+
data={
|
|
46
|
+
'collection_id': 99999,
|
|
47
|
+
'order': 0
|
|
48
|
+
},
|
|
49
|
+
content_type='application/json',
|
|
50
|
+
)
|
|
51
|
+
assert response.status_code == 200
|
|
52
|
+
assert response.json()['type'] == 'error'
|
|
53
|
+
|
|
54
|
+
def test_reorder_view_missing_order(self):
|
|
55
|
+
response = self.client.post(
|
|
56
|
+
reverse('django_spire:knowledge:collection:json:reorder'),
|
|
57
|
+
data={
|
|
58
|
+
'collection_id': self.test_collection.pk,
|
|
59
|
+
},
|
|
60
|
+
content_type='application/json',
|
|
61
|
+
)
|
|
62
|
+
assert response.status_code == 200
|
|
63
|
+
assert response.json()['type'] == 'error'
|
|
@@ -9,8 +9,18 @@ from django_spire.knowledge.collection.tests.factories import create_test_collec
|
|
|
9
9
|
class CollectionPageUrlsTests(BaseTestCase):
|
|
10
10
|
def setUp(self):
|
|
11
11
|
super().setUp()
|
|
12
|
+
|
|
12
13
|
self.test_collection = create_test_collection()
|
|
13
14
|
|
|
15
|
+
def test_top_level_view_url_path(self):
|
|
16
|
+
response = self.client.get(
|
|
17
|
+
reverse(
|
|
18
|
+
'django_spire:knowledge:collection:page:top_level',
|
|
19
|
+
kwargs={'pk': self.test_collection.pk}
|
|
20
|
+
)
|
|
21
|
+
)
|
|
22
|
+
assert response.status_code == 200
|
|
23
|
+
|
|
14
24
|
def test_delete_view_url_path(self):
|
|
15
25
|
response = self.client.get(
|
|
16
26
|
reverse(
|
|
@@ -18,12 +28,10 @@ class CollectionPageUrlsTests(BaseTestCase):
|
|
|
18
28
|
kwargs={'pk': self.test_collection.pk}
|
|
19
29
|
)
|
|
20
30
|
)
|
|
21
|
-
|
|
22
|
-
self.assertEqual(response.status_code, 200)
|
|
31
|
+
assert response.status_code == 200
|
|
23
32
|
|
|
24
33
|
def test_list_view_url_path(self):
|
|
25
34
|
response = self.client.get(
|
|
26
35
|
reverse('django_spire:knowledge:page:home')
|
|
27
36
|
)
|
|
28
|
-
|
|
29
|
-
self.assertEqual(response.status_code, 200)
|
|
37
|
+
assert response.status_code == 200
|
|
@@ -22,9 +22,9 @@ if TYPE_CHECKING:
|
|
|
22
22
|
|
|
23
23
|
@AppAuthController('knowledge').permission_required('can_add')
|
|
24
24
|
def form_view(
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
request: WSGIRequest,
|
|
26
|
+
pk: int = 0,
|
|
27
|
+
parent_pk: int = None
|
|
28
28
|
) -> TemplateResponse | HttpResponseRedirect:
|
|
29
29
|
collection = get_object_or_null_obj(Collection, pk=pk)
|
|
30
30
|
|
|
@@ -55,7 +55,7 @@ def form_view(
|
|
|
55
55
|
if form.is_valid():
|
|
56
56
|
collection, _ = collection.services.save_model_obj(**form.cleaned_data)
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
CollectionGroup.services.factory.replace_groups(
|
|
59
59
|
request=request,
|
|
60
60
|
group_pks=dict(request.POST).get('groups'),
|
|
61
61
|
collection=collection,
|
|
@@ -2,13 +2,17 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
4
|
|
|
5
|
-
from
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
6
7
|
from django.http import JsonResponse
|
|
7
8
|
|
|
8
9
|
from django_spire.core.decorators import valid_ajax_request_required
|
|
9
10
|
from django_spire.core.shortcuts import get_object_or_null_obj
|
|
10
11
|
from django_spire.knowledge.collection.models import Collection
|
|
11
12
|
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from django.core.handlers.wsgi import WSGIRequest
|
|
15
|
+
|
|
12
16
|
|
|
13
17
|
@valid_ajax_request_required
|
|
14
18
|
def reorder_view(request: WSGIRequest) -> JsonResponse:
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from django.core.handlers.wsgi import WSGIRequest
|
|
4
3
|
from django.shortcuts import get_object_or_404
|
|
5
|
-
from django.template.response import TemplateResponse
|
|
6
4
|
from django.urls import reverse
|
|
7
5
|
|
|
8
6
|
from django_spire.auth.controller.controller import AppAuthController
|
|
9
7
|
from django_spire.contrib import Breadcrumbs
|
|
10
8
|
from django_spire.contrib.generic_views import portal_views
|
|
11
9
|
from django_spire.knowledge.collection.models import Collection
|
|
10
|
+
from typing import TYPE_CHECKING
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from django.core.handlers.wsgi import WSGIRequest
|
|
14
|
+
from django.template.response import TemplateResponse
|
|
12
15
|
|
|
13
16
|
|
|
14
17
|
@AppAuthController('knowledge').permission_required('can_view')
|
|
@@ -1,11 +1,17 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
1
5
|
from django.contrib import admin, messages
|
|
2
|
-
from django.db.models import QuerySet
|
|
3
6
|
from django.urls import reverse
|
|
4
7
|
from django.utils.html import format_html
|
|
5
8
|
from django.utils.http import urlencode
|
|
6
9
|
|
|
7
10
|
from django_spire.knowledge.entry.models import Entry
|
|
8
11
|
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from django.db.models import QuerySet
|
|
14
|
+
|
|
9
15
|
|
|
10
16
|
@admin.register(Entry)
|
|
11
17
|
class EntryAdmin(admin.ModelAdmin):
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import traceback
|
|
4
|
-
from typing import TYPE_CHECKING
|
|
5
4
|
|
|
6
|
-
import
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
7
6
|
|
|
8
7
|
from django_spire.contrib.service import BaseDjangoModelService
|
|
9
8
|
from django_spire.core.decorators import close_db_connections
|
|
10
9
|
from django_spire.knowledge.entry.version.block.models import EntryVersionBlock
|
|
11
|
-
from django_spire.knowledge.exceptions import
|
|
10
|
+
from django_spire.knowledge.exceptions import KnowledgeBaseConversionError
|
|
12
11
|
|
|
13
12
|
if TYPE_CHECKING:
|
|
14
13
|
from django_spire.knowledge.entry.models import Entry
|
|
@@ -41,11 +40,13 @@ class EntryAutomationService(BaseDjangoModelService['Entry']):
|
|
|
41
40
|
file_object.set_deleted()
|
|
42
41
|
|
|
43
42
|
message = f'Files Converted: {len(file_objects) - len(errored)}'
|
|
43
|
+
|
|
44
44
|
if errored:
|
|
45
45
|
error_string = f'\n{message}\nFiles Errored:'
|
|
46
|
+
|
|
46
47
|
for error in errored:
|
|
47
48
|
error_string += f' File Name: {error["file"]}\n Error: {error["error"]}'
|
|
48
49
|
|
|
49
|
-
raise
|
|
50
|
+
raise KnowledgeBaseConversionError(error_string)
|
|
50
51
|
|
|
51
52
|
return message
|
|
@@ -4,11 +4,11 @@ from typing import TYPE_CHECKING
|
|
|
4
4
|
|
|
5
5
|
from django.contrib.contenttypes.models import ContentType
|
|
6
6
|
|
|
7
|
-
from django_spire.auth.user.models import AuthUser
|
|
8
7
|
from django_spire.contrib.service import BaseDjangoModelService
|
|
9
8
|
from django_spire.file.models import File
|
|
10
9
|
|
|
11
10
|
if TYPE_CHECKING:
|
|
11
|
+
from django_spire.auth.user.models import AuthUser
|
|
12
12
|
from django_spire.knowledge.entry.models import Entry
|
|
13
13
|
from django_spire.knowledge.collection.models import Collection
|
|
14
14
|
|
|
@@ -17,18 +17,20 @@ class EntryFactoryService(BaseDjangoModelService['Entry']):
|
|
|
17
17
|
obj: Entry
|
|
18
18
|
|
|
19
19
|
def create_from_files(
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
self,
|
|
21
|
+
author: AuthUser,
|
|
22
|
+
collection: Collection,
|
|
23
|
+
files: list[File]
|
|
24
24
|
) -> list[Entry]:
|
|
25
25
|
entries = []
|
|
26
|
+
|
|
26
27
|
for file in files:
|
|
27
28
|
entry, _ = self.obj_class.services.save_model_obj(
|
|
28
29
|
name=file.name,
|
|
29
30
|
author=author,
|
|
30
31
|
collection=collection
|
|
31
32
|
)
|
|
33
|
+
|
|
32
34
|
entries.append(entry)
|
|
33
35
|
|
|
34
36
|
file.content_type = ContentType.objects.get_for_model(entry.__class__)
|
|
@@ -2,21 +2,18 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from typing import TYPE_CHECKING
|
|
4
4
|
|
|
5
|
-
from django_spire.auth.user.models import AuthUser
|
|
6
5
|
from django_spire.contrib.ordering.services.service import OrderingService
|
|
7
6
|
from django_spire.contrib.service import BaseDjangoModelService
|
|
8
|
-
from django_spire.knowledge.entry.services.automation_service import
|
|
9
|
-
EntryAutomationService
|
|
7
|
+
from django_spire.knowledge.entry.services.automation_service import EntryAutomationService
|
|
10
8
|
from django_spire.knowledge.entry.services.factory_service import EntryFactoryService
|
|
11
|
-
from django_spire.knowledge.entry.services.processor_service import
|
|
12
|
-
EntryProcessorService
|
|
9
|
+
from django_spire.knowledge.entry.services.processor_service import EntryProcessorService
|
|
13
10
|
from django_spire.knowledge.entry.services.tag_service import EntryTagService
|
|
14
11
|
from django_spire.knowledge.entry.services.tool_service import EntryToolService
|
|
15
|
-
from django_spire.knowledge.entry.services.transformation_services import
|
|
16
|
-
EntryTransformationService
|
|
12
|
+
from django_spire.knowledge.entry.services.transformation_services import EntryTransformationService
|
|
17
13
|
from django_spire.knowledge.entry.version.models import EntryVersion
|
|
18
14
|
|
|
19
15
|
if TYPE_CHECKING:
|
|
16
|
+
from django_spire.auth.user.models import AuthUser
|
|
20
17
|
from django_spire.knowledge.entry.models import Entry
|
|
21
18
|
|
|
22
19
|
|
|
@@ -18,11 +18,7 @@ class EntryTransformationService(BaseDjangoModelService['Entry']):
|
|
|
18
18
|
|
|
19
19
|
@staticmethod
|
|
20
20
|
def queryset_to_navigation_list(queryset: QuerySet[Entry]) -> list[dict[str, str]]:
|
|
21
|
-
|
|
22
|
-
for entry in queryset:
|
|
23
|
-
json_list.append(entry.services.transformation.to_dict())
|
|
24
|
-
|
|
25
|
-
return json_list
|
|
21
|
+
return [entry.services.transformation.to_dict() for entry in queryset]
|
|
26
22
|
|
|
27
23
|
def to_dict(self):
|
|
28
24
|
site = Site.objects.get_current() if not settings.DEBUG else ''
|
|
@@ -6,11 +6,10 @@ from django_spire.knowledge.entry.models import Entry
|
|
|
6
6
|
|
|
7
7
|
def create_test_entry(**kwargs) -> Entry:
|
|
8
8
|
data = {
|
|
9
|
-
'collection': create_test_collection(),
|
|
9
|
+
'collection': kwargs.pop('collection', None) or create_test_collection(),
|
|
10
10
|
'name': 'Video Game Cheat Codes',
|
|
11
11
|
'is_deleted': False,
|
|
12
12
|
'is_active': True
|
|
13
13
|
}
|
|
14
|
-
|
|
15
14
|
data.update(kwargs)
|
|
16
15
|
return Entry.objects.create(**data)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from django_spire.core.tests.test_cases import BaseTestCase
|
|
4
|
+
from django_spire.knowledge.collection.tests.factories import create_test_collection
|
|
5
|
+
from django_spire.knowledge.entry.models import Entry
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class EntryFactoryServiceTests(BaseTestCase):
|
|
9
|
+
def setUp(self):
|
|
10
|
+
super().setUp()
|
|
11
|
+
|
|
12
|
+
self.collection = create_test_collection()
|
|
13
|
+
|
|
14
|
+
def test_create_from_files_empty_list(self):
|
|
15
|
+
entries = Entry.services.factory.create_from_files(
|
|
16
|
+
author=self.super_user,
|
|
17
|
+
collection=self.collection,
|
|
18
|
+
files=[]
|
|
19
|
+
)
|
|
20
|
+
assert entries == []
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from django_spire.core.tests.test_cases import BaseTestCase
|
|
4
|
+
from django_spire.knowledge.collection.tests.factories import create_test_collection
|
|
5
|
+
from django_spire.knowledge.entry.tests.factories import create_test_entry
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class EntryModelTests(BaseTestCase):
|
|
9
|
+
def setUp(self):
|
|
10
|
+
super().setUp()
|
|
11
|
+
|
|
12
|
+
self.collection = create_test_collection()
|
|
13
|
+
self.entry = create_test_entry(collection=self.collection)
|
|
14
|
+
|
|
15
|
+
def test_str(self):
|
|
16
|
+
assert str(self.entry) == self.entry.name
|
|
17
|
+
|
|
18
|
+
def test_name_short_truncates(self):
|
|
19
|
+
long_name = 'A' * 100
|
|
20
|
+
entry = create_test_entry(name=long_name, collection=self.collection)
|
|
21
|
+
assert len(entry.name_short) <= 35
|
|
22
|
+
|
|
23
|
+
def test_name_short_no_truncate(self):
|
|
24
|
+
short_name = 'Short'
|
|
25
|
+
entry = create_test_entry(name=short_name, collection=self.collection)
|
|
26
|
+
assert entry.name_short == short_name
|
|
27
|
+
|
|
28
|
+
def test_top_level_collection(self):
|
|
29
|
+
child_collection = create_test_collection(
|
|
30
|
+
parent=self.collection,
|
|
31
|
+
name='Child Collection'
|
|
32
|
+
)
|
|
33
|
+
entry = create_test_entry(collection=child_collection)
|
|
34
|
+
assert entry.top_level_collection == self.collection
|
|
35
|
+
|
|
36
|
+
def test_top_level_collection_when_already_top(self):
|
|
37
|
+
assert self.entry.top_level_collection == self.collection
|
|
38
|
+
|
|
39
|
+
def test_base_breadcrumb(self):
|
|
40
|
+
breadcrumbs = self.entry.base_breadcrumb()
|
|
41
|
+
assert breadcrumbs is not None
|