django-cfg 1.3.11__py3-none-any.whl → 1.4.0__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_cfg/__init__.py +1 -1
- django_cfg/apps/accounts/admin/inlines.py +11 -5
- django_cfg/apps/accounts/admin/user_admin.py +39 -16
- django_cfg/apps/accounts/serializers/profile.py +1 -1
- django_cfg/apps/accounts/services/otp_service.py +18 -11
- django_cfg/apps/accounts/signals.py +15 -24
- django_cfg/apps/accounts/utils/notifications.py +217 -358
- django_cfg/apps/accounts/views/otp.py +2 -2
- django_cfg/apps/accounts/views/webhook.py +1 -1
- django_cfg/apps/agents/core/django_agent.py +1 -1
- django_cfg/apps/api/commands/views.py +66 -83
- django_cfg/apps/api/health/drf_views.py +269 -0
- django_cfg/apps/api/health/serializers.py +45 -0
- django_cfg/apps/api/health/urls.py +6 -1
- django_cfg/apps/knowbase/admin/actions/__init__.py +13 -0
- django_cfg/apps/knowbase/admin/actions/visibility_actions.py +56 -0
- django_cfg/apps/knowbase/admin/document_admin.py +136 -270
- django_cfg/apps/knowbase/admin/helpers/__init__.py +17 -0
- django_cfg/apps/knowbase/admin/helpers/configs.py +72 -0
- django_cfg/apps/knowbase/admin/helpers/display_helpers.py +156 -0
- django_cfg/apps/knowbase/admin/helpers/statistics.py +108 -0
- django_cfg/apps/knowbase/config/constance_fields.py +1 -1
- django_cfg/apps/knowbase/config/settings.py +2 -2
- django_cfg/apps/knowbase/mixins/__init__.py +19 -2
- django_cfg/apps/knowbase/mixins/config/__init__.py +14 -0
- django_cfg/apps/knowbase/mixins/config/defaults.py +75 -0
- django_cfg/apps/knowbase/mixins/config/meta_config.py +120 -0
- django_cfg/apps/knowbase/mixins/creator.py +10 -10
- django_cfg/apps/knowbase/mixins/external_data_mixin.py +105 -403
- django_cfg/apps/knowbase/mixins/generators/__init__.py +16 -0
- django_cfg/apps/knowbase/mixins/generators/content_generator.py +218 -0
- django_cfg/apps/knowbase/mixins/generators/field_analyzer.py +76 -0
- django_cfg/apps/knowbase/mixins/generators/metadata_generator.py +124 -0
- django_cfg/apps/knowbase/mixins/service.py +2 -2
- django_cfg/apps/knowbase/services/archive/__init__.py +1 -0
- django_cfg/apps/knowbase/services/archive/analyzers/__init__.py +17 -0
- django_cfg/apps/knowbase/services/archive/analyzers/complexity_analyzer.py +33 -0
- django_cfg/apps/knowbase/services/archive/analyzers/purpose_detector.py +36 -0
- django_cfg/apps/knowbase/services/archive/analyzers/quality_analyzer.py +39 -0
- django_cfg/apps/knowbase/services/archive/analyzers/tag_generator.py +103 -0
- django_cfg/apps/knowbase/services/archive/chunking/__init__.py +19 -0
- django_cfg/apps/knowbase/services/archive/chunking/base.py +81 -0
- django_cfg/apps/knowbase/services/archive/chunking/json_chunker.py +62 -0
- django_cfg/apps/knowbase/services/archive/chunking/markdown_chunker.py +107 -0
- django_cfg/apps/knowbase/services/archive/chunking/python_chunker.py +248 -0
- django_cfg/apps/knowbase/services/archive/chunking/text_chunker.py +70 -0
- django_cfg/apps/knowbase/services/archive/chunking_service.py +110 -729
- django_cfg/apps/knowbase/services/archive/context/__init__.py +14 -0
- django_cfg/apps/knowbase/services/archive/context/builders.py +220 -0
- django_cfg/apps/knowbase/services/archive/context/models.py +38 -0
- django_cfg/apps/knowbase/services/embedding/models.py +18 -14
- django_cfg/apps/knowbase/services/embedding/processors.py +6 -3
- django_cfg/apps/knowbase/tasks/document_processing.py +11 -3
- django_cfg/apps/leads/tests.py +1 -1
- django_cfg/apps/payments/admin/api_keys_admin.py +1 -1
- django_cfg/apps/payments/admin/balance_admin.py +1 -1
- django_cfg/apps/payments/admin/currencies_admin.py +1 -1
- django_cfg/apps/payments/admin/payments_admin.py +1 -1
- django_cfg/apps/payments/admin/subscriptions_admin.py +1 -1
- django_cfg/apps/payments/admin_interface/templates/payments/base.html +59 -126
- django_cfg/apps/payments/admin_interface/views/api/payments.py +1 -1
- django_cfg/apps/payments/admin_interface/views/api/stats.py +1 -1
- django_cfg/apps/payments/admin_interface/views/api/users.py +1 -1
- django_cfg/apps/payments/admin_interface/views/api/webhook_admin.py +1 -1
- django_cfg/apps/payments/admin_interface/views/api/webhook_public.py +1 -1
- django_cfg/apps/payments/admin_interface/views/base.py +29 -2
- django_cfg/apps/payments/apps.py +1 -1
- django_cfg/apps/payments/config/django_cfg_integration.py +2 -2
- django_cfg/apps/payments/config/helpers.py +3 -2
- django_cfg/apps/payments/management/commands/cleanup_expired_data.py +1 -1
- django_cfg/apps/payments/management/commands/currency_stats.py +1 -1
- django_cfg/apps/payments/management/commands/manage_currencies.py +1 -1
- django_cfg/apps/payments/management/commands/manage_providers.py +1 -1
- django_cfg/apps/payments/management/commands/process_pending_payments.py +1 -1
- django_cfg/apps/payments/management/commands/test_providers.py +1 -1
- django_cfg/apps/payments/middleware/api_access.py +1 -1
- django_cfg/apps/payments/middleware/rate_limiting.py +1 -1
- django_cfg/apps/payments/middleware/usage_tracking.py +1 -1
- django_cfg/apps/payments/models/balance.py +2 -2
- django_cfg/apps/payments/models/managers/api_key_managers.py +1 -1
- django_cfg/apps/payments/models/managers/balance_managers.py +1 -1
- django_cfg/apps/payments/models/managers/currency_managers.py +1 -1
- django_cfg/apps/payments/models/managers/payment_managers.py +1 -1
- django_cfg/apps/payments/models/managers/subscription_managers.py +1 -1
- django_cfg/apps/payments/models/payments.py +2 -2
- django_cfg/apps/payments/services/cache_service/__init__.py +1 -1
- django_cfg/apps/payments/services/cache_service/simple_cache.py +10 -5
- django_cfg/apps/payments/services/core/base.py +1 -1
- django_cfg/apps/payments/services/core/currency/__init__.py +13 -0
- django_cfg/apps/payments/services/core/currency/currency_converter.py +57 -0
- django_cfg/apps/payments/services/core/currency/currency_validator.py +61 -0
- django_cfg/apps/payments/services/core/operations/__init__.py +15 -0
- django_cfg/apps/payments/services/core/operations/payment_canceller.py +100 -0
- django_cfg/apps/payments/services/core/operations/payment_creator.py +196 -0
- django_cfg/apps/payments/services/core/operations/status_checker.py +100 -0
- django_cfg/apps/payments/services/core/payment_service.py +124 -612
- django_cfg/apps/payments/services/core/providers/__init__.py +13 -0
- django_cfg/apps/payments/services/core/providers/provider_client.py +132 -0
- django_cfg/apps/payments/services/core/providers/status_mapper.py +89 -0
- django_cfg/apps/payments/services/core/utils/__init__.py +13 -0
- django_cfg/apps/payments/services/core/utils/data_converter.py +48 -0
- django_cfg/apps/payments/services/core/utils/statistics_calculator.py +69 -0
- django_cfg/apps/payments/services/providers/base.py +1 -1
- django_cfg/apps/payments/services/providers/nowpayments/__init__.py +3 -3
- django_cfg/apps/payments/services/providers/nowpayments/parsers/__init__.py +9 -0
- django_cfg/apps/payments/services/providers/nowpayments/parsers/data/__init__.py +23 -0
- django_cfg/apps/payments/services/providers/nowpayments/parsers/data/constants.py +23 -0
- django_cfg/apps/payments/services/providers/nowpayments/parsers/data/currency_names.py +244 -0
- django_cfg/apps/payments/services/providers/nowpayments/parsers/data/patterns.py +511 -0
- django_cfg/apps/payments/services/providers/nowpayments/parsers/parser.py +168 -0
- django_cfg/apps/payments/services/providers/nowpayments/provider.py +1 -1
- django_cfg/apps/payments/services/providers/nowpayments/sync.py +1 -1
- django_cfg/apps/payments/services/providers/registry.py +1 -1
- django_cfg/apps/payments/services/providers/sync_service.py +1 -1
- django_cfg/apps/payments/signals/__init__.py +1 -1
- django_cfg/apps/payments/signals/api_key_signals.py +1 -1
- django_cfg/apps/payments/signals/balance_signals.py +1 -1
- django_cfg/apps/payments/signals/payment_signals.py +1 -1
- django_cfg/apps/payments/signals/subscription_signals.py +1 -1
- django_cfg/apps/payments/views/api/api_keys.py +1 -1
- django_cfg/apps/payments/views/api/balances.py +1 -1
- django_cfg/apps/payments/views/api/base.py +1 -1
- django_cfg/apps/payments/views/api/currencies.py +1 -1
- django_cfg/apps/payments/views/api/payments.py +1 -1
- django_cfg/apps/payments/views/api/subscriptions.py +1 -1
- django_cfg/apps/payments/views/api/webhooks.py +1 -1
- django_cfg/apps/payments/views/serializers/api_keys.py +1 -1
- django_cfg/apps/payments/views/serializers/balances.py +1 -1
- django_cfg/apps/payments/views/serializers/currencies.py +1 -1
- django_cfg/apps/payments/views/serializers/payments.py +1 -1
- django_cfg/apps/payments/views/serializers/subscriptions.py +1 -1
- django_cfg/apps/payments/views/serializers/webhooks.py +1 -1
- django_cfg/apps/support/admin/support_admin.py +21 -13
- django_cfg/apps/support/templates/support/chat/access_denied.html +21 -27
- django_cfg/apps/support/templates/support/chat/ticket_chat.html +183 -254
- django_cfg/apps/support/utils/support_email_service.py +1 -1
- django_cfg/apps/tasks/templates/tasks/layout/base.html +20 -115
- django_cfg/apps/tasks/utils/simulator.py +1 -1
- django_cfg/apps/tasks/views/dashboard.py +33 -3
- django_cfg/apps/urls.py +5 -1
- django_cfg/cli/README.md +57 -471
- django_cfg/cli/commands/create_project.py +140 -529
- django_cfg/cli/main.py +13 -10
- django_cfg/core/__init__.py +63 -6
- django_cfg/core/base/__init__.py +5 -0
- django_cfg/core/base/config_model.py +652 -0
- django_cfg/core/builders/__init__.py +11 -0
- django_cfg/core/builders/apps_builder.py +258 -0
- django_cfg/core/builders/middleware_builder.py +115 -0
- django_cfg/core/builders/security_builder.py +96 -0
- django_cfg/core/config.py +20 -892
- django_cfg/core/constants.py +69 -0
- django_cfg/core/environment/__init__.py +9 -0
- django_cfg/core/exceptions.py +45 -298
- django_cfg/core/generation/__init__.py +51 -0
- django_cfg/core/generation/core_generators/__init__.py +0 -0
- django_cfg/core/generation/core_generators/settings.py +90 -0
- django_cfg/core/generation/core_generators/static.py +82 -0
- django_cfg/core/generation/core_generators/templates.py +141 -0
- django_cfg/core/generation/data_generators/__init__.py +15 -0
- django_cfg/core/generation/data_generators/cache.py +132 -0
- django_cfg/core/generation/data_generators/database.py +117 -0
- django_cfg/core/generation/generation.py +92 -0
- django_cfg/core/generation/integration_generators/__init__.py +21 -0
- django_cfg/core/generation/integration_generators/api.py +237 -0
- django_cfg/core/generation/integration_generators/sessions.py +65 -0
- django_cfg/core/generation/integration_generators/tailwind.py +54 -0
- django_cfg/core/generation/integration_generators/tasks.py +92 -0
- django_cfg/core/generation/integration_generators/third_party.py +144 -0
- django_cfg/core/generation/orchestrator.py +285 -0
- django_cfg/core/generation/protocols.py +30 -0
- django_cfg/core/generation/security_generators/__init__.py +0 -0
- django_cfg/core/generation/utility_generators/__init__.py +24 -0
- django_cfg/core/generation/utility_generators/email.py +58 -0
- django_cfg/core/generation/utility_generators/i18n.py +66 -0
- django_cfg/core/generation/utility_generators/limits.py +58 -0
- django_cfg/core/generation/utility_generators/logging.py +66 -0
- django_cfg/core/generation/utility_generators/security.py +101 -0
- django_cfg/core/generation/utils/__init__.py +0 -0
- django_cfg/core/generation/utils/helpers.py +32 -0
- django_cfg/core/integration/__init__.py +18 -25
- django_cfg/core/integration/display/startup.py +146 -133
- django_cfg/core/integration/url_integration.py +13 -2
- django_cfg/core/services/__init__.py +5 -0
- django_cfg/core/services/config_service.py +121 -0
- django_cfg/core/state/__init__.py +9 -0
- django_cfg/core/state/registry.py +84 -0
- django_cfg/core/types/__init__.py +15 -0
- django_cfg/core/types/aliases.py +15 -0
- django_cfg/core/types/enums.py +49 -0
- django_cfg/dashboard/DEBUG_README.md +105 -0
- django_cfg/dashboard/REFACTORING_SUMMARY.md +237 -0
- django_cfg/dashboard/__init__.py +24 -0
- django_cfg/dashboard/components.py +308 -0
- django_cfg/dashboard/debug.py +176 -0
- django_cfg/dashboard/management/__init__.py +0 -0
- django_cfg/dashboard/management/commands/__init__.py +0 -0
- django_cfg/dashboard/management/commands/debug_dashboard.py +109 -0
- django_cfg/dashboard/sections/__init__.py +1 -0
- django_cfg/dashboard/sections/base.py +128 -0
- django_cfg/dashboard/sections/commands.py +32 -0
- django_cfg/dashboard/sections/overview.py +394 -0
- django_cfg/dashboard/sections/stats.py +48 -0
- django_cfg/dashboard/sections/system.py +73 -0
- django_cfg/management/commands/check_settings.py +6 -2
- django_cfg/management/commands/clear_constance.py +6 -1
- django_cfg/management/commands/create_token.py +5 -4
- django_cfg/management/commands/generate.py +5 -0
- django_cfg/management/commands/list_urls.py +7 -2
- django_cfg/management/commands/migrate_all.py +6 -2
- django_cfg/management/commands/migrator.py +6 -1
- django_cfg/management/commands/rundramatiq.py +6 -1
- django_cfg/management/commands/rundramatiq_simulator.py +11 -4
- django_cfg/management/commands/runserver_ngrok.py +9 -7
- django_cfg/management/commands/script.py +25 -21
- django_cfg/management/commands/show_config.py +6 -1
- django_cfg/management/commands/show_urls.py +8 -3
- django_cfg/management/commands/superuser.py +5 -4
- django_cfg/management/commands/task_clear.py +8 -3
- django_cfg/management/commands/task_status.py +8 -3
- django_cfg/management/commands/test_email.py +6 -1
- django_cfg/management/commands/test_telegram.py +6 -1
- django_cfg/management/commands/test_twilio.py +6 -1
- django_cfg/management/commands/tree.py +7 -4
- django_cfg/models/__init__.py +88 -3
- django_cfg/models/api/__init__.py +27 -0
- django_cfg/models/{api.py → api/config.py} +1 -1
- django_cfg/models/api/drf/__init__.py +21 -0
- django_cfg/models/api/drf/config.py +101 -0
- django_cfg/models/api/drf/redoc.py +31 -0
- django_cfg/models/api/drf/spectacular.py +129 -0
- django_cfg/models/api/drf/swagger.py +59 -0
- django_cfg/models/{api_keys.py → api/keys.py} +16 -6
- django_cfg/models/{limits.py → api/limits.py} +0 -1
- django_cfg/models/base/__init__.py +14 -0
- django_cfg/models/django/__init__.py +16 -0
- django_cfg/models/{constance.py → django/constance.py} +1 -1
- django_cfg/models/{environment.py → django/environment.py} +1 -1
- django_cfg/models/infrastructure/__init__.py +17 -0
- django_cfg/models/{cache.py → infrastructure/cache.py} +3 -2
- django_cfg/models/infrastructure/database/__init__.py +22 -0
- django_cfg/models/infrastructure/database/config.py +265 -0
- django_cfg/models/infrastructure/database/converters.py +91 -0
- django_cfg/models/infrastructure/database/parsers.py +96 -0
- django_cfg/models/infrastructure/database/routing.py +85 -0
- django_cfg/models/infrastructure/database/validators.py +170 -0
- django_cfg/models/{logging.py → infrastructure/logging.py} +1 -1
- django_cfg/models/{security.py → infrastructure/security.py} +2 -2
- django_cfg/models/ngrok/__init__.py +11 -0
- django_cfg/models/ngrok/auth.py +37 -0
- django_cfg/models/ngrok/config.py +77 -0
- django_cfg/models/ngrok/tunnel.py +35 -0
- django_cfg/models/payments/__init__.py +20 -0
- django_cfg/models/payments/api_keys.py +57 -0
- django_cfg/models/{payments.py → payments/config.py} +56 -154
- django_cfg/models/payments/providers/__init__.py +15 -0
- django_cfg/models/payments/providers/base.py +25 -0
- django_cfg/models/payments/providers/nowpayments.py +48 -0
- django_cfg/models/services/__init__.py +18 -0
- django_cfg/models/services/base.py +65 -0
- django_cfg/models/{email.py → services/email.py} +1 -1
- django_cfg/models/services/telegram.py +172 -0
- django_cfg/models/tasks/__init__.py +51 -0
- django_cfg/models/tasks/backends.py +250 -0
- django_cfg/models/tasks/config.py +314 -0
- django_cfg/models/tasks/utils.py +174 -0
- django_cfg/modules/base.py +18 -3
- django_cfg/modules/django_admin/decorators/actions.py +1 -1
- django_cfg/modules/django_admin/decorators/display.py +1 -1
- django_cfg/modules/django_admin/mixins/standalone_actions_mixin.py +1 -1
- django_cfg/modules/django_cfg_rpc_client/README.md +346 -0
- django_cfg/modules/django_cfg_rpc_client/__init__.py +51 -0
- django_cfg/modules/django_cfg_rpc_client/client.py +540 -0
- django_cfg/modules/django_cfg_rpc_client/config.py +207 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/README.md +517 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/UNFOLD_INTEGRATION.md +439 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/__init__.py +11 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/apps.py +22 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/monitor.py +435 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/static/django_cfg_rpc_dashboard/js/dashboard.js +373 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/templates/django_cfg_rpc_dashboard/base.html +76 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/templates/django_cfg_rpc_dashboard/dashboard.html +200 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/urls.py +22 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/urls_admin.py +9 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/views.py +251 -0
- django_cfg/modules/django_cfg_rpc_client/exceptions.py +201 -0
- django_cfg/modules/django_drf_theme/CHANGELOG.md +210 -0
- django_cfg/modules/django_drf_theme/EXAMPLE.md +465 -0
- django_cfg/modules/django_drf_theme/IMPLEMENTATION.md +232 -0
- django_cfg/modules/django_drf_theme/README.md +207 -0
- django_cfg/modules/django_drf_theme/TAILWIND_CDN_GUIDE.md +274 -0
- django_cfg/modules/django_drf_theme/__init__.py +23 -0
- django_cfg/modules/django_drf_theme/apps.py +15 -0
- django_cfg/modules/django_drf_theme/renderers.py +58 -0
- django_cfg/modules/django_drf_theme/templates/rest_framework/tailwind/api.html +375 -0
- django_cfg/modules/django_drf_theme/templates/rest_framework/tailwind/base.html +938 -0
- django_cfg/modules/django_drf_theme/templates/rest_framework/tailwind/forms/filter_form.html +132 -0
- django_cfg/modules/django_drf_theme/templates/rest_framework/tailwind/forms/raw_data_form.html +123 -0
- django_cfg/modules/django_drf_theme/templatetags/__init__.py +1 -0
- django_cfg/modules/django_drf_theme/templatetags/tailwind_tags.py +57 -0
- django_cfg/modules/django_email/__init__.py +14 -0
- django_cfg/modules/{django_email.py → django_email/service.py} +78 -113
- django_cfg/modules/django_email/utils.py +40 -0
- django_cfg/modules/django_health/__init__.py +9 -0
- django_cfg/modules/{django_health.py → django_health/service.py} +23 -21
- django_cfg/modules/django_llm/llm/client.py +155 -550
- django_cfg/modules/django_llm/llm/embeddings/__init__.py +13 -0
- django_cfg/modules/django_llm/llm/embeddings/mock_embedder.py +106 -0
- django_cfg/modules/django_llm/llm/embeddings/openai_embedder.py +79 -0
- django_cfg/modules/django_llm/llm/models_api/__init__.py +9 -0
- django_cfg/modules/django_llm/llm/models_api/models_query.py +163 -0
- django_cfg/modules/django_llm/llm/providers/__init__.py +15 -0
- django_cfg/modules/django_llm/llm/providers/config_builder.py +103 -0
- django_cfg/modules/django_llm/llm/providers/provider_manager.py +148 -0
- django_cfg/modules/django_llm/llm/providers/provider_selector.py +60 -0
- django_cfg/modules/django_llm/llm/requests/__init__.py +15 -0
- django_cfg/modules/django_llm/llm/requests/cache_manager.py +170 -0
- django_cfg/modules/django_llm/llm/requests/chat_handler.py +199 -0
- django_cfg/modules/django_llm/llm/requests/embedding_handler.py +113 -0
- django_cfg/modules/django_llm/llm/responses/__init__.py +9 -0
- django_cfg/modules/django_llm/llm/responses/response_builder.py +131 -0
- django_cfg/modules/django_llm/llm/stats/__init__.py +9 -0
- django_cfg/modules/django_llm/llm/stats/stats_manager.py +107 -0
- django_cfg/modules/django_llm/translator/detectors/__init__.py +13 -0
- django_cfg/modules/django_llm/translator/detectors/language_detector.py +90 -0
- django_cfg/modules/django_llm/translator/detectors/script_detector.py +153 -0
- django_cfg/modules/django_llm/translator/stats/__init__.py +11 -0
- django_cfg/modules/django_llm/translator/stats/stats_tracker.py +85 -0
- django_cfg/modules/django_llm/translator/translator.py +150 -603
- django_cfg/modules/django_llm/translator/translators/__init__.py +15 -0
- django_cfg/modules/django_llm/translator/translators/json_translator.py +316 -0
- django_cfg/modules/django_llm/translator/translators/text_translator.py +139 -0
- django_cfg/modules/django_llm/translator/utils/__init__.py +13 -0
- django_cfg/modules/django_llm/translator/utils/prompt_builder.py +110 -0
- django_cfg/modules/django_llm/translator/utils/text_utils.py +114 -0
- django_cfg/modules/django_logging/FIXES_SUMMARY.md +276 -0
- django_cfg/modules/django_logging/LOGGING_GUIDE.md +504 -0
- django_cfg/modules/django_logging/__init__.py +14 -0
- django_cfg/modules/{django_logger.py → django_logging/django_logger.py} +13 -13
- django_cfg/modules/{logger.py → django_logging/logger.py} +14 -4
- django_cfg/modules/django_ngrok/__init__.py +39 -0
- django_cfg/modules/{django_ngrok.py → django_ngrok/service.py} +14 -42
- django_cfg/modules/django_rpc_old/POETRY.md +344 -0
- django_cfg/modules/django_rpc_old/README.md +397 -0
- django_cfg/modules/django_rpc_old/TESTING.md +358 -0
- django_cfg/modules/django_rpc_old/__init__.py +39 -0
- django_cfg/modules/django_rpc_old/client.py +531 -0
- django_cfg/modules/django_rpc_old/config.py +279 -0
- django_cfg/modules/django_rpc_old/exceptions.py +172 -0
- django_cfg/modules/django_tailwind/README.md +478 -0
- django_cfg/modules/django_tailwind/__init__.py +7 -0
- django_cfg/modules/django_tailwind/apps.py +10 -0
- django_cfg/modules/django_tailwind/templates/django_tailwind/app.html +5 -0
- django_cfg/modules/django_tailwind/templates/django_tailwind/base.html +117 -0
- django_cfg/modules/django_tailwind/templates/django_tailwind/components/navbar.html +124 -0
- django_cfg/modules/django_tailwind/templates/django_tailwind/components/theme_toggle.html +54 -0
- django_cfg/modules/django_tailwind/templates/django_tailwind/components/user_menu.html +116 -0
- django_cfg/modules/django_tailwind/templates/django_tailwind/simple.html +46 -0
- django_cfg/modules/django_tailwind/templatetags/__init__.py +1 -0
- django_cfg/modules/django_tailwind/templatetags/tailwind_info.py +185 -0
- django_cfg/modules/django_tasks/__init__.py +29 -0
- django_cfg/modules/django_tasks/factory.py +127 -0
- django_cfg/modules/{django_tasks.py → django_tasks/service.py} +45 -274
- django_cfg/modules/django_tasks/settings.py +107 -0
- django_cfg/modules/django_telegram/__init__.py +29 -0
- django_cfg/modules/{django_telegram.py → django_telegram/service.py} +45 -113
- django_cfg/modules/django_telegram/utils.py +62 -0
- django_cfg/modules/django_twilio/__init__.py +54 -107
- django_cfg/modules/django_twilio/_imports.py +30 -0
- django_cfg/modules/django_twilio/base.py +192 -0
- django_cfg/modules/django_twilio/email_otp.py +227 -0
- django_cfg/modules/django_twilio/sendgrid_service.py +1 -1
- django_cfg/modules/django_twilio/simple_service.py +1 -2
- django_cfg/modules/django_twilio/sms.py +94 -0
- django_cfg/modules/django_twilio/twilio_service.py +2 -3
- django_cfg/modules/django_twilio/unified.py +310 -0
- django_cfg/modules/django_twilio/utils.py +190 -0
- django_cfg/modules/django_twilio/whatsapp.py +137 -0
- django_cfg/modules/django_unfold/callbacks/base.py +198 -7
- django_cfg/modules/django_unfold/callbacks/main.py +102 -10
- django_cfg/modules/django_unfold/dashboard.py +65 -43
- django_cfg/modules/django_unfold/models/config.py +13 -12
- django_cfg/modules/django_unfold/models/navigation.py +8 -3
- django_cfg/modules/django_unfold/models/tabs.py +2 -2
- django_cfg/modules/django_unfold/templates/unfold/helpers/app_list.html +102 -0
- django_cfg/registry/core.py +24 -26
- django_cfg/registry/modules.py +5 -2
- django_cfg/registry/services.py +20 -3
- django_cfg/registry/third_party.py +8 -8
- django_cfg/static/admin/css/dashboard.css +260 -0
- django_cfg/static/admin/js/commands.js +171 -0
- django_cfg/static/admin/js/dashboard.js +126 -0
- django_cfg/templates/admin/components/management_commands.js +375 -0
- django_cfg/templates/admin/components/progress_bar.html +18 -23
- django_cfg/templates/admin/index.html +48 -20
- django_cfg/templates/admin/index_new.html +106 -0
- django_cfg/templates/admin/layouts/base_dashboard.html +60 -0
- django_cfg/templates/admin/layouts/dashboard_with_tabs.html +1 -20
- django_cfg/templates/admin/sections/commands_section.html +626 -0
- django_cfg/templates/admin/sections/overview_section.html +112 -0
- django_cfg/templates/admin/sections/stats_section.html +35 -0
- django_cfg/templates/admin/sections/system_section.html +99 -0
- django_cfg/templates/admin/snippets/components/CHARTS_GUIDE.md +322 -0
- django_cfg/templates/admin/snippets/components/activity_tracker.html +85 -47
- django_cfg/templates/admin/snippets/components/charts_section.html +154 -64
- django_cfg/templates/admin/snippets/components/django_commands.html +3 -3
- django_cfg/templates/admin/snippets/components/recent_activity_improved.html +25 -0
- django_cfg/templates/admin/snippets/components/recent_users_table.html +1 -1
- django_cfg/templates/admin/snippets/components/system_metrics.html +179 -93
- django_cfg/templates/admin/snippets/zones/zones_table.html +2 -2
- django_cfg/templatetags/django_cfg.py +7 -1
- django_cfg/utils/smart_defaults.py +4 -4
- django_cfg-1.4.0.dist-info/METADATA +920 -0
- {django_cfg-1.3.11.dist-info → django_cfg-1.4.0.dist-info}/RECORD +425 -196
- django_cfg/apps/accounts/utils/auth_email_service.py +0 -84
- django_cfg/apps/payments/services/providers/nowpayments/parsers.py +0 -879
- django_cfg/core/generation.py +0 -621
- django_cfg/management/commands/validate_config.py +0 -189
- django_cfg/models/database.py +0 -480
- django_cfg/models/drf.py +0 -272
- django_cfg/models/ngrok.py +0 -122
- django_cfg/models/services.py +0 -440
- django_cfg/models/tasks.py +0 -550
- django_cfg/modules/django_twilio/service.py +0 -942
- django_cfg/template_archive/django_sample.zip +0 -0
- django_cfg/templates/rest_framework/api.html +0 -12
- django_cfg/utils/toolkit.py +0 -703
- django_cfg-1.3.11.dist-info/METADATA +0 -1029
- /django_cfg/apps/accounts/management/commands/{test_otp.py → otp_test.py} +0 -0
- /django_cfg/core/{environment.py → environment/detector.py} +0 -0
- /django_cfg/models/{cors.py → api/cors.py} +0 -0
- /django_cfg/models/{jwt.py → api/jwt.py} +0 -0
- /django_cfg/models/{base.py → base/config.py} +0 -0
- /django_cfg/models/{cfg.py → base/module.py} +0 -0
- /django_cfg/models/{revolution.py → django/revolution.py} +0 -0
- /django_cfg/modules/{dramatiq_setup.py → django_tasks/dramatiq_setup.py} +0 -0
- {django_cfg-1.3.11.dist-info → django_cfg-1.4.0.dist-info}/WHEEL +0 -0
- {django_cfg-1.3.11.dist-info → django_cfg-1.4.0.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.3.11.dist-info → django_cfg-1.4.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,281 +1,210 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
<head>
|
4
|
-
<meta charset="UTF-8">
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6
|
-
<title>Support Chat - {{ ticket.subject }}</title>
|
7
|
-
<script src="https://cdn.tailwindcss.com"></script>
|
8
|
-
<script>
|
9
|
-
tailwind.config = {
|
10
|
-
theme: {
|
11
|
-
extend: {
|
12
|
-
colors: {
|
13
|
-
primary: {
|
14
|
-
50: '#f0f9ff',
|
15
|
-
500: '#3b82f6',
|
16
|
-
600: '#2563eb',
|
17
|
-
700: '#1d4ed8',
|
18
|
-
}
|
19
|
-
}
|
20
|
-
}
|
21
|
-
}
|
22
|
-
}
|
23
|
-
</script>
|
24
|
-
</head>
|
25
|
-
<body class="bg-gray-50 min-h-screen">
|
26
|
-
<!-- Header -->
|
27
|
-
<div class="bg-white shadow-sm border-b">
|
28
|
-
<div class="max-w-4xl mx-auto px-4 py-4">
|
29
|
-
<!-- Main Header Row -->
|
30
|
-
<div class="flex items-start justify-between mb-3">
|
31
|
-
<!-- Left: Ticket Title & Status -->
|
32
|
-
<div class="flex-1 min-w-0">
|
33
|
-
<div class="flex items-center space-x-3 mb-1">
|
34
|
-
<!-- Status Badge -->
|
35
|
-
<div class="flex items-center space-x-2">
|
36
|
-
<div class="w-3 h-3 rounded-full {% if ticket.status == 'open' %}bg-green-500{% elif ticket.status == 'in_progress' %}bg-yellow-500{% else %}bg-gray-500{% endif %}"></div>
|
37
|
-
<span class="text-sm font-medium text-gray-600">{{ ticket.get_status_display }}</span>
|
38
|
-
</div>
|
39
|
-
|
40
|
-
<!-- Ticket ID -->
|
41
|
-
<span class="text-sm text-gray-500">Ticket #{{ ticket.uuid|slice:":8" }}</span>
|
42
|
-
</div>
|
43
|
-
|
44
|
-
<!-- Ticket Subject -->
|
45
|
-
<h1 class="text-xl font-semibold text-gray-900 truncate pr-4">{{ ticket.subject }}</h1>
|
46
|
-
</div>
|
1
|
+
{% extends 'django_tailwind/app.html' %}
|
2
|
+
{% load static %}
|
47
3
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
4
|
+
{% block title %}Support Chat - {{ ticket.subject }}{% endblock %}
|
5
|
+
|
6
|
+
{# Navbar with Support title - full width #}
|
7
|
+
{% block header %}
|
8
|
+
{% include 'django_tailwind/components/navbar.html' with title="Support Chat" icon='💬' full_width=True %}
|
9
|
+
{% endblock %}
|
10
|
+
|
11
|
+
{% block container_class %}w-full px-0 py-0{% endblock %}
|
12
|
+
|
13
|
+
{% block content %}
|
14
|
+
<!-- Chat Container -->
|
15
|
+
<div class="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
|
16
|
+
<div class="bg-white dark:bg-gray-800 rounded-xl shadow-lg border border-gray-200 dark:border-gray-700 overflow-hidden flex flex-col" style="height: calc(100vh - 400px); min-height: 500px;">
|
17
|
+
|
18
|
+
<!-- Messages Area -->
|
19
|
+
<div id="messages-container" class="flex-1 overflow-y-auto p-6 space-y-4 bg-gray-50 dark:bg-gray-900">
|
20
|
+
{% for message in messages %}
|
21
|
+
<div class="flex {% if message.sender == user %}justify-end{% else %}justify-start{% endif %} animate-fade-in">
|
22
|
+
<div class="flex {% if message.sender == user %}flex-row-reverse{% else %}flex-row{% endif %} items-end space-x-2 {% if message.sender == user %}space-x-reverse{% endif %} max-w-xl">
|
62
23
|
|
63
|
-
<!-- User Info Row -->
|
64
|
-
<div class="flex items-center justify-between pt-3 border-t border-gray-100">
|
65
|
-
<!-- Customer Info -->
|
66
|
-
<div class="flex items-center space-x-3">
|
67
24
|
<!-- Avatar -->
|
68
25
|
<div class="flex-shrink-0">
|
69
|
-
{% if
|
70
|
-
<img src="{{
|
71
|
-
alt="{{
|
26
|
+
{% if message.sender.avatar %}
|
27
|
+
<img src="{{ message.sender.avatar.url }}"
|
28
|
+
alt="{{ message.sender.get_full_name }}"
|
72
29
|
class="w-8 h-8 rounded-full object-cover">
|
73
30
|
{% else %}
|
74
|
-
<div class="w-8 h-8 rounded-full bg-gray-
|
75
|
-
{{
|
31
|
+
<div class="w-8 h-8 rounded-full {% if message.sender == user %}bg-gradient-to-br from-blue-500 to-blue-600{% else %}bg-gradient-to-br from-gray-500 to-gray-600{% endif %} flex items-center justify-center text-white text-xs font-bold shadow-sm">
|
32
|
+
{{ message.sender.get_full_name|default:message.sender.username|slice:":2"|upper }}
|
76
33
|
</div>
|
77
34
|
{% endif %}
|
78
35
|
</div>
|
79
|
-
|
80
|
-
<!--
|
81
|
-
<div class="flex flex-col">
|
82
|
-
<div class="
|
83
|
-
<
|
84
|
-
|
85
|
-
|
36
|
+
|
37
|
+
<!-- Message Bubble -->
|
38
|
+
<div class="flex flex-col {% if message.sender == user %}items-end{% else %}items-start{% endif %} space-y-1">
|
39
|
+
<div class="px-4 py-3 rounded-2xl shadow-sm {% if message.sender == user %}bg-blue-600 text-white rounded-br-sm{% else %}bg-white dark:bg-gray-800 text-gray-900 dark:text-white border border-gray-200 dark:border-gray-700 rounded-bl-sm{% endif %}">
|
40
|
+
<p class="text-sm leading-relaxed whitespace-pre-wrap break-words">{{ message.text }}</p>
|
41
|
+
</div>
|
42
|
+
<div class="flex items-center space-x-2 text-xs {% if message.sender == user %}text-gray-500 dark:text-gray-400{% else %}text-gray-500 dark:text-gray-400{% endif %} px-1">
|
43
|
+
<span class="font-medium">{{ message.sender.get_full_name|default:message.sender.username }}</span>
|
44
|
+
<span>•</span>
|
45
|
+
<span>{{ message.created_at|date:"M d, H:i" }}</span>
|
46
|
+
{% if message.sender.is_staff %}
|
47
|
+
<span class="bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-400 px-1.5 py-0.5 rounded text-xs font-medium">Staff</span>
|
86
48
|
{% endif %}
|
87
49
|
</div>
|
88
|
-
<span class="text-xs text-gray-500">{{ ticket.user.email }}</span>
|
89
50
|
</div>
|
90
51
|
</div>
|
91
|
-
|
92
|
-
<!-- Ticket Meta -->
|
93
|
-
<div class="flex items-center space-x-4 text-xs text-gray-500">
|
94
|
-
<span>Created {{ ticket.created_at|date:"M d, Y H:i" }}</span>
|
95
|
-
{% if ticket.updated_at != ticket.created_at %}
|
96
|
-
<span>•</span>
|
97
|
-
<span>Updated {{ ticket.updated_at|date:"M d, Y H:i" }}</span>
|
98
|
-
{% endif %}
|
99
|
-
</div>
|
100
52
|
</div>
|
53
|
+
{% empty %}
|
54
|
+
<div class="text-center py-16">
|
55
|
+
<div class="text-6xl mb-4">💬</div>
|
56
|
+
<p class="text-lg text-gray-500 dark:text-gray-400 font-medium">No messages yet</p>
|
57
|
+
<p class="text-sm text-gray-400 dark:text-gray-500">Start the conversation below!</p>
|
58
|
+
</div>
|
59
|
+
{% endfor %}
|
101
60
|
</div>
|
102
|
-
</div>
|
103
|
-
|
104
|
-
<!-- Chat Container -->
|
105
|
-
<div class="max-w-4xl mx-auto px-4 py-6">
|
106
|
-
<div class="bg-white rounded-lg shadow-sm border h-[600px] flex flex-col">
|
107
|
-
|
108
|
-
<!-- Messages Area -->
|
109
|
-
<div id="messages-container" class="flex-1 overflow-y-auto p-6 space-y-4">
|
110
|
-
{% for message in messages %}
|
111
|
-
<div class="flex {% if message.sender == user %}justify-end{% else %}justify-start{% endif %} mb-4">
|
112
|
-
<div class="flex {% if message.sender == user %}flex-row-reverse{% else %}flex-row{% endif %} items-end space-x-2 max-w-xs lg:max-w-md">
|
113
|
-
|
114
|
-
<!-- Avatar -->
|
115
|
-
<div class="flex-shrink-0">
|
116
|
-
{% if message.sender.avatar %}
|
117
|
-
<img src="{{ message.sender.avatar.url }}"
|
118
|
-
alt="{{ message.sender.get_full_name }}"
|
119
|
-
class="w-8 h-8 rounded-full object-cover">
|
120
|
-
{% else %}
|
121
|
-
<div class="w-8 h-8 rounded-full {% if message.sender == user %}bg-primary-500{% else %}bg-gray-500{% endif %} flex items-center justify-center text-white text-sm font-medium">
|
122
|
-
{{ message.sender.get_full_name|default:message.sender.username|slice:":2"|upper }}
|
123
|
-
</div>
|
124
|
-
{% endif %}
|
125
|
-
</div>
|
126
61
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
<span>{{ message.created_at|date:"M d, H:i" }}</span>
|
137
|
-
{% if message.sender.is_staff %}
|
138
|
-
<span class="bg-blue-100 text-blue-800 px-1.5 py-0.5 rounded text-xs font-medium">Staff</span>
|
139
|
-
{% endif %}
|
140
|
-
</div>
|
141
|
-
</div>
|
142
|
-
</div>
|
143
|
-
</div>
|
144
|
-
{% empty %}
|
145
|
-
<div class="text-center py-12">
|
146
|
-
<div class="text-gray-400 text-lg mb-2">💬</div>
|
147
|
-
<p class="text-gray-500">No messages yet. Start the conversation!</p>
|
62
|
+
<!-- Message Input -->
|
63
|
+
<div class="border-t border-gray-200 dark:border-gray-700 p-4 bg-white dark:bg-gray-800">
|
64
|
+
<form id="message-form" class="flex space-x-3">
|
65
|
+
<div class="flex-1">
|
66
|
+
<textarea id="message-input"
|
67
|
+
placeholder="Type your message... (Press Enter to send, Shift+Enter for new line)"
|
68
|
+
rows="2"
|
69
|
+
class="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white placeholder-gray-500 dark:placeholder-gray-400 focus:ring-2 focus:ring-blue-500 focus:border-transparent resize-none transition-shadow"
|
70
|
+
required></textarea>
|
148
71
|
</div>
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
<textarea id="message-input"
|
157
|
-
placeholder="Type your message..."
|
158
|
-
rows="2"
|
159
|
-
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-transparent resize-none"
|
160
|
-
required></textarea>
|
161
|
-
</div>
|
162
|
-
<button type="submit"
|
163
|
-
class="px-6 py-2 bg-primary-500 text-white rounded-lg hover:bg-primary-600 focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 transition-colors font-medium">
|
164
|
-
Send
|
165
|
-
</button>
|
166
|
-
</form>
|
167
|
-
</div>
|
72
|
+
<button type="submit"
|
73
|
+
class="px-6 py-3 bg-blue-600 hover:bg-blue-700 text-white rounded-lg focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 transition-all font-medium shadow-sm hover:shadow-md disabled:opacity-50 disabled:cursor-not-allowed">
|
74
|
+
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
75
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 19l9 2-9-18-9 18 9-2zm0 0v-8"/>
|
76
|
+
</svg>
|
77
|
+
</button>
|
78
|
+
</form>
|
168
79
|
</div>
|
169
80
|
</div>
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
81
|
+
</div>
|
82
|
+
{% endblock %}
|
83
|
+
|
84
|
+
{% block extra_head %}
|
85
|
+
{{ block.super }}
|
86
|
+
<style>
|
87
|
+
@keyframes fade-in {
|
88
|
+
from {
|
89
|
+
opacity: 0;
|
90
|
+
transform: translateY(10px);
|
180
91
|
}
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
92
|
+
to {
|
93
|
+
opacity: 1;
|
94
|
+
transform: translateY(0);
|
95
|
+
}
|
96
|
+
}
|
97
|
+
|
98
|
+
.animate-fade-in {
|
99
|
+
animation: fade-in 0.3s ease-out;
|
100
|
+
}
|
101
|
+
</style>
|
102
|
+
{% endblock %}
|
103
|
+
|
104
|
+
{% block extra_js %}
|
105
|
+
<script>
|
106
|
+
const messageForm = document.getElementById('message-form');
|
107
|
+
const messageInput = document.getElementById('message-input');
|
108
|
+
const messagesContainer = document.getElementById('messages-container');
|
109
|
+
|
110
|
+
// Auto-scroll to bottom
|
111
|
+
function scrollToBottom() {
|
112
|
+
messagesContainer.scrollTop = messagesContainer.scrollHeight;
|
113
|
+
}
|
114
|
+
|
115
|
+
// Initial scroll
|
116
|
+
scrollToBottom();
|
117
|
+
|
118
|
+
// Handle form submission
|
119
|
+
messageForm.addEventListener('submit', async (e) => {
|
120
|
+
e.preventDefault();
|
121
|
+
|
122
|
+
const text = messageInput.value.trim();
|
123
|
+
if (!text) return;
|
124
|
+
|
125
|
+
// Disable form
|
126
|
+
messageInput.disabled = true;
|
127
|
+
const submitBtn = messageForm.querySelector('button[type="submit"]');
|
128
|
+
submitBtn.disabled = true;
|
129
|
+
submitBtn.innerHTML = '<svg class="w-5 h-5 animate-spin" fill="none" stroke="currentColor" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg>';
|
130
|
+
|
131
|
+
try {
|
132
|
+
const response = await fetch(`{% url 'cfg_support:send-message-ajax' ticket_uuid=ticket.uuid %}`, {
|
133
|
+
method: 'POST',
|
134
|
+
headers: {
|
135
|
+
'Content-Type': 'application/json',
|
136
|
+
'X-CSRFToken': '{{ csrf_token }}',
|
137
|
+
},
|
138
|
+
body: JSON.stringify({ text })
|
139
|
+
});
|
140
|
+
|
141
|
+
const data = await response.json();
|
142
|
+
|
143
|
+
if (data.success) {
|
144
|
+
// Clear input
|
145
|
+
messageInput.value = '';
|
146
|
+
|
147
|
+
// Add message to chat
|
148
|
+
addMessageToChat(data.message);
|
149
|
+
|
150
|
+
// Scroll to bottom
|
151
|
+
setTimeout(scrollToBottom, 100);
|
152
|
+
} else {
|
153
|
+
alert('Error: ' + data.error);
|
232
154
|
}
|
233
|
-
})
|
155
|
+
} catch (error) {
|
156
|
+
console.error('Error sending message:', error);
|
157
|
+
alert('Failed to send message. Please try again.');
|
158
|
+
} finally {
|
159
|
+
// Re-enable form
|
160
|
+
messageInput.disabled = false;
|
161
|
+
submitBtn.disabled = false;
|
162
|
+
submitBtn.innerHTML = '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 19l9 2-9-18-9 18 9-2zm0 0v-8"/></svg>';
|
163
|
+
messageInput.focus();
|
164
|
+
}
|
165
|
+
});
|
166
|
+
|
167
|
+
// Add message to chat UI
|
168
|
+
function addMessageToChat(message) {
|
169
|
+
const isCurrentUser = message.sender.id === {{ user.id }};
|
170
|
+
const messageHtml = `
|
171
|
+
<div class="flex ${isCurrentUser ? 'justify-end' : 'justify-start'} animate-fade-in">
|
172
|
+
<div class="flex ${isCurrentUser ? 'flex-row-reverse' : 'flex-row'} items-end space-x-2 ${isCurrentUser ? 'space-x-reverse' : ''} max-w-xl">
|
173
|
+
<!-- Avatar -->
|
174
|
+
<div class="flex-shrink-0">
|
175
|
+
${message.sender.avatar ?
|
176
|
+
`<img src="${message.sender.avatar}" alt="${message.sender.full_name}" class="w-8 h-8 rounded-full object-cover">` :
|
177
|
+
`<div class="w-8 h-8 rounded-full ${isCurrentUser ? 'bg-gradient-to-br from-blue-500 to-blue-600' : 'bg-gradient-to-br from-gray-500 to-gray-600'} flex items-center justify-center text-white text-xs font-bold shadow-sm">
|
178
|
+
${message.sender.initials}
|
179
|
+
</div>`
|
180
|
+
}
|
181
|
+
</div>
|
234
182
|
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
<div class="flex ${isCurrentUser ? 'justify-end' : 'justify-start'} mb-4">
|
240
|
-
<div class="flex ${isCurrentUser ? 'flex-row-reverse' : 'flex-row'} items-end space-x-2 max-w-xs lg:max-w-md">
|
241
|
-
|
242
|
-
<!-- Avatar -->
|
243
|
-
<div class="flex-shrink-0">
|
244
|
-
${message.sender.avatar ?
|
245
|
-
`<img src="${message.sender.avatar}" alt="${message.sender.full_name}" class="w-8 h-8 rounded-full object-cover">` :
|
246
|
-
`<div class="w-8 h-8 rounded-full ${isCurrentUser ? 'bg-primary-500' : 'bg-gray-500'} flex items-center justify-center text-white text-sm font-medium">
|
247
|
-
${message.sender.initials}
|
248
|
-
</div>`
|
249
|
-
}
|
183
|
+
<!-- Message Bubble -->
|
184
|
+
<div class="flex flex-col ${isCurrentUser ? 'items-end' : 'items-start'} space-y-1">
|
185
|
+
<div class="px-4 py-3 rounded-2xl shadow-sm ${isCurrentUser ? 'bg-blue-600 text-white rounded-br-sm' : 'bg-white dark:bg-gray-800 text-gray-900 dark:text-white border border-gray-200 dark:border-gray-700 rounded-bl-sm'}">
|
186
|
+
<p class="text-sm leading-relaxed whitespace-pre-wrap break-words">${message.text}</p>
|
250
187
|
</div>
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
<
|
255
|
-
|
256
|
-
</div>
|
257
|
-
<div class="flex items-center mt-1 space-x-1 text-xs text-gray-500">
|
258
|
-
<span>${message.sender.full_name}</span>
|
259
|
-
<span class="text-gray-400">(${message.sender.email})</span>
|
260
|
-
<span>•</span>
|
261
|
-
<span>Just now</span>
|
262
|
-
${message.sender.is_staff ? '<span class="bg-blue-100 text-blue-800 px-1.5 py-0.5 rounded text-xs font-medium">Staff</span>' : ''}
|
263
|
-
</div>
|
188
|
+
<div class="flex items-center space-x-2 text-xs text-gray-500 dark:text-gray-400 px-1">
|
189
|
+
<span class="font-medium">${message.sender.full_name}</span>
|
190
|
+
<span>•</span>
|
191
|
+
<span>Just now</span>
|
192
|
+
${message.sender.is_staff ? '<span class="bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-400 px-1.5 py-0.5 rounded text-xs font-medium">Staff</span>' : ''}
|
264
193
|
</div>
|
265
194
|
</div>
|
266
195
|
</div>
|
267
|
-
|
268
|
-
|
269
|
-
messagesContainer.insertAdjacentHTML('beforeend', messageHtml);
|
270
|
-
}
|
196
|
+
</div>
|
197
|
+
`;
|
271
198
|
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
199
|
+
messagesContainer.insertAdjacentHTML('beforeend', messageHtml);
|
200
|
+
}
|
201
|
+
|
202
|
+
// Handle Enter key (Shift+Enter for new line)
|
203
|
+
messageInput.addEventListener('keydown', (e) => {
|
204
|
+
if (e.key === 'Enter' && !e.shiftKey) {
|
205
|
+
e.preventDefault();
|
206
|
+
messageForm.dispatchEvent(new Event('submit'));
|
207
|
+
}
|
208
|
+
});
|
209
|
+
</script>
|
210
|
+
{% endblock %}
|
@@ -19,7 +19,7 @@ class SupportEmailService:
|
|
19
19
|
def _get_ticket_url(self, ticket_uuid: str) -> str:
|
20
20
|
"""Get ticket URL from configuration."""
|
21
21
|
try:
|
22
|
-
from django_cfg.core.
|
22
|
+
from django_cfg.core.state import get_current_config
|
23
23
|
config = get_current_config()
|
24
24
|
if config and hasattr(config, 'get_ticket_url'):
|
25
25
|
return config.get_ticket_url(str(ticket_uuid))
|
@@ -1,117 +1,22 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
<head>
|
4
|
-
<meta charset="UTF-8">
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6
|
-
<title>{% block title %}Tasks Dashboard{% endblock %} - Django CFG</title>
|
7
|
-
|
8
|
-
<!-- Tailwind CSS -->
|
9
|
-
<script src="https://cdn.tailwindcss.com"></script>
|
10
|
-
<script>
|
11
|
-
tailwind.config = {
|
12
|
-
darkMode: 'class',
|
13
|
-
theme: {
|
14
|
-
extend: {
|
15
|
-
colors: {
|
16
|
-
primary: {
|
17
|
-
50: '#eff6ff',
|
18
|
-
100: '#dbeafe',
|
19
|
-
200: '#bfdbfe',
|
20
|
-
300: '#93c5fd',
|
21
|
-
400: '#60a5fa',
|
22
|
-
500: '#3b82f6',
|
23
|
-
600: '#2563eb',
|
24
|
-
700: '#1d4ed8',
|
25
|
-
800: '#1e40af',
|
26
|
-
900: '#1e3a8a',
|
27
|
-
}
|
28
|
-
}
|
29
|
-
}
|
30
|
-
}
|
31
|
-
}
|
32
|
-
</script>
|
33
|
-
|
34
|
-
<!-- Material Icons -->
|
35
|
-
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
36
|
-
|
37
|
-
<!-- Custom CSS -->
|
38
|
-
{% load static %}
|
39
|
-
<link rel="stylesheet" href="{% static 'tasks/css/dashboard.css' %}">
|
40
|
-
|
41
|
-
{% block extra_css %}{% endblock %}
|
42
|
-
</head>
|
43
|
-
<body class="h-full bg-gray-50 dark:bg-gray-900">
|
44
|
-
<!-- Navigation -->
|
45
|
-
<nav class="bg-white dark:bg-gray-800 shadow-sm border-b border-gray-200 dark:border-gray-700">
|
46
|
-
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
47
|
-
<div class="flex justify-between h-16">
|
48
|
-
<!-- Logo & Title -->
|
49
|
-
<div class="flex items-center">
|
50
|
-
<div class="flex-shrink-0 flex items-center">
|
51
|
-
<span class="material-icons text-2xl text-primary-600 dark:text-primary-400 mr-3">dashboard</span>
|
52
|
-
<h1 class="text-xl font-semibold text-gray-900 dark:text-white">
|
53
|
-
{% block page_title %}Tasks Dashboard{% endblock %}
|
54
|
-
</h1>
|
55
|
-
</div>
|
56
|
-
</div>
|
57
|
-
|
58
|
-
<!-- Actions -->
|
59
|
-
<div class="flex items-center space-x-3">
|
60
|
-
{% block header_actions %}
|
61
|
-
<a href="/admin/django_dramatiq/task/"
|
62
|
-
class="inline-flex items-center px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600 transition-colors duration-200">
|
63
|
-
<span class="material-icons text-sm mr-2">history</span>
|
64
|
-
Task History
|
65
|
-
</a>
|
66
|
-
<a href="/admin/constance/config/"
|
67
|
-
class="inline-flex items-center px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600 transition-colors duration-200">
|
68
|
-
<span class="material-icons text-sm mr-2">admin_panel_settings</span>
|
69
|
-
Settings
|
70
|
-
</a>
|
71
|
-
<button id="theme-toggle"
|
72
|
-
class="group inline-flex items-center justify-center px-3 py-2 rounded-md bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2">
|
73
|
-
<span class="material-icons text-gray-600 dark:text-yellow-400 group-hover:text-primary-600 dark:group-hover:text-yellow-300 transition-colors duration-200">light_mode</span>
|
74
|
-
</button>
|
75
|
-
{% endblock %}
|
76
|
-
</div>
|
77
|
-
</div>
|
78
|
-
</div>
|
79
|
-
</nav>
|
1
|
+
{% extends 'django_tailwind/app.html' %}
|
2
|
+
{% load static %}
|
80
3
|
|
81
|
-
|
82
|
-
<main class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
|
83
|
-
{% block content %}{% endblock %}
|
84
|
-
</main>
|
4
|
+
{% block title %}{% block page_title_text %}Tasks Dashboard{% endblock %} - Django CFG{% endblock %}
|
85
5
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
html.classList.toggle('dark', isDark);
|
104
|
-
updateThemeIcon(isDark);
|
105
|
-
|
106
|
-
themeToggle?.addEventListener('click', () => {
|
107
|
-
const wasDark = html.classList.contains('dark');
|
108
|
-
html.classList.toggle('dark');
|
109
|
-
const nowDark = html.classList.contains('dark');
|
110
|
-
localStorage.setItem('theme', nowDark ? 'dark' : 'light');
|
111
|
-
updateThemeIcon(nowDark);
|
112
|
-
});
|
113
|
-
</script>
|
114
|
-
|
115
|
-
{% block extra_js %}{% endblock %}
|
116
|
-
</body>
|
117
|
-
</html>
|
6
|
+
{# Navbar configuration #}
|
7
|
+
{% block header %}
|
8
|
+
{% with navbar_items=tasks_nav_items %}
|
9
|
+
{% include 'django_tailwind/components/navbar.html' with title=page_title|default:"Tasks Dashboard" icon='<span class="material-icons text-2xl text-primary-600 dark:text-primary-400">dashboard</span>' nav_items=navbar_items %}
|
10
|
+
{% endwith %}
|
11
|
+
{% endblock %}
|
12
|
+
|
13
|
+
{% block extra_head %}
|
14
|
+
{{ block.super }}
|
15
|
+
<!-- Material Icons -->
|
16
|
+
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
17
|
+
|
18
|
+
<!-- Custom CSS -->
|
19
|
+
<link rel="stylesheet" href="{% static 'tasks/css/dashboard.css' %}">
|
20
|
+
|
21
|
+
{% block extra_css %}{% endblock %}
|
22
|
+
{% endblock %}
|
@@ -25,7 +25,7 @@ class TaskSimulator:
|
|
25
25
|
|
26
26
|
def __init__(self):
|
27
27
|
"""Initialize with Redis connection for real Dramatiq data."""
|
28
|
-
self.queues = ['critical', 'high', 'default', 'low', 'background', 'payments', 'agents']
|
28
|
+
self.queues = ['critical', 'high', 'default', 'low', 'background', 'payments', 'agents', 'knowbase']
|
29
29
|
self._redis_client = None
|
30
30
|
self._setup_redis_connection()
|
31
31
|
|