django-cfg 1.3.13__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/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.13.dist-info → django_cfg-1.4.0.dist-info}/RECORD +424 -195
- 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.13.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.13.dist-info → django_cfg-1.4.0.dist-info}/WHEEL +0 -0
- {django_cfg-1.3.13.dist-info → django_cfg-1.4.0.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.3.13.dist-info → django_cfg-1.4.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,626 @@
|
|
1
|
+
{% load unfold %}
|
2
|
+
|
3
|
+
<!-- Commands Section -->
|
4
|
+
<div class="space-y-8">
|
5
|
+
<div class="flex items-center justify-between mb-6">
|
6
|
+
<div>
|
7
|
+
<h1 class="text-2xl font-bold text-font-important-light dark:text-font-important-dark">{{ title|default:"Management Commands" }}</h1>
|
8
|
+
<p class="text-font-default-light dark:text-font-default-dark mt-2">
|
9
|
+
Execute Django management commands directly from the dashboard
|
10
|
+
</p>
|
11
|
+
</div>
|
12
|
+
<div class="text-sm text-font-subtle-light dark:text-font-subtle-dark">
|
13
|
+
Total: <span id="commands-total" class="font-mono font-semibold text-font-important-light dark:text-font-important-dark">{{ data.commands|length }}</span> commands
|
14
|
+
</div>
|
15
|
+
</div>
|
16
|
+
|
17
|
+
<!-- Search Box -->
|
18
|
+
<div class="flex items-center gap-3 mb-6">
|
19
|
+
<div class="relative flex-1 max-w-md">
|
20
|
+
<span class="material-symbols-outlined absolute left-3 top-1/2 -translate-y-1/2 text-base-400 dark:text-base-500">search</span>
|
21
|
+
<input
|
22
|
+
type="text"
|
23
|
+
id="command-search"
|
24
|
+
placeholder="Search commands..."
|
25
|
+
class="w-full pl-10 pr-10 py-2 border border-base-200 dark:border-base-700 rounded-default bg-white dark:bg-base-800 text-font-important-light dark:text-font-important-dark placeholder-font-subtle-light dark:placeholder-font-subtle-dark focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent"
|
26
|
+
/>
|
27
|
+
<button
|
28
|
+
id="clear-search"
|
29
|
+
class="hidden absolute right-3 top-1/2 -translate-y-1/2 text-base-400 dark:text-base-500 hover:text-base-600 dark:hover:text-base-300"
|
30
|
+
onclick="clearSearch()"
|
31
|
+
>
|
32
|
+
<span class="material-symbols-outlined text-lg">close</span>
|
33
|
+
</button>
|
34
|
+
</div>
|
35
|
+
</div>
|
36
|
+
|
37
|
+
<!-- Commands by Category -->
|
38
|
+
{% if data.categories %}
|
39
|
+
<div class="flex flex-col gap-6">
|
40
|
+
{% for category, category_commands in data.categories.items %}
|
41
|
+
{% if category_commands %}
|
42
|
+
<div class="category-block bg-gradient-to-br from-white to-base-50 dark:from-base-800 dark:to-base-900 rounded-default shadow-md border border-base-200 dark:border-base-700 overflow-hidden">
|
43
|
+
<div class="p-6 border-b border-base-200 dark:border-base-700 category-toggle cursor-pointer hover:bg-base-100/50 dark:hover:bg-base-900/30 transition-all duration-200"
|
44
|
+
data-category="{{ category }}">
|
45
|
+
<div class="w-full flex items-center justify-between">
|
46
|
+
<h3 class="text-lg font-semibold text-font-important-light dark:text-font-important-dark flex items-center">
|
47
|
+
<div class="w-10 h-10 rounded-lg bg-primary-100 dark:bg-primary-900/30 flex items-center justify-center mr-3">
|
48
|
+
<span class="material-symbols-outlined text-primary-600 dark:text-primary-400">
|
49
|
+
{% if category == 'django_cfg' %}settings
|
50
|
+
{% elif category == 'django_core' %}apps
|
51
|
+
{% elif category == 'third_party' %}extension
|
52
|
+
{% else %}folder{% endif %}
|
53
|
+
</span>
|
54
|
+
</div>
|
55
|
+
<div>
|
56
|
+
<div class="flex items-center gap-2">
|
57
|
+
{{ category|title }} Commands
|
58
|
+
<span class="px-2 py-0.5 text-xs font-medium rounded-full bg-base-200 dark:bg-base-700 text-font-default-light dark:text-font-default-dark category-count">
|
59
|
+
{{ category_commands|length }}
|
60
|
+
</span>
|
61
|
+
</div>
|
62
|
+
</div>
|
63
|
+
</h3>
|
64
|
+
<span class="material-symbols-outlined text-base-400 dark:text-base-500 toggle-icon transition-transform duration-200 select-none">expand_more</span>
|
65
|
+
</div>
|
66
|
+
</div>
|
67
|
+
<div class="p-6 category-content bg-base-50/30 dark:bg-base-900/30" data-category="{{ category }}" style="display: none;">
|
68
|
+
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
69
|
+
{% for cmd in category_commands %}
|
70
|
+
<button type="button"
|
71
|
+
class="command-btn command-item text-left p-4 rounded-default border border-base-200/60 dark:border-base-700/60 bg-white dark:bg-base-800 hover:border-base-300 dark:hover:border-base-600 hover:bg-white/80 dark:hover:bg-base-800/80 transition-all duration-200 group"
|
72
|
+
data-command="{{ cmd.name }}"
|
73
|
+
data-app="{{ cmd.app }}"
|
74
|
+
data-description="{{ cmd.description|default:'' }}">
|
75
|
+
<div class="flex items-center gap-3">
|
76
|
+
<div class="flex-shrink-0">
|
77
|
+
<span class="material-symbols-outlined text-primary-500 dark:text-primary-400 text-xl group-hover:text-primary-600 dark:group-hover:text-primary-300 transition-colors">terminal</span>
|
78
|
+
</div>
|
79
|
+
<div class="flex-1 grow min-w-0">
|
80
|
+
<p class="font-mono text-sm text-font-important-light dark:text-font-important-dark font-semibold command-name truncate">{{ cmd.name }}</p>
|
81
|
+
{% if cmd.description %}
|
82
|
+
<p class="text-xs text-font-default-light dark:text-font-default-dark mt-1 line-clamp-2">{{ cmd.description }}</p>
|
83
|
+
{% endif %}
|
84
|
+
{% if cmd.app %}
|
85
|
+
<p class="text-xs text-font-subtle-light dark:text-font-subtle-dark mt-1 truncate">
|
86
|
+
<span class="opacity-60">from</span> {{ cmd.app }}
|
87
|
+
</p>
|
88
|
+
{% endif %}
|
89
|
+
</div>
|
90
|
+
<div class="flex-shrink-0">
|
91
|
+
<span class="material-symbols-outlined text-base-400 dark:text-base-600 group-hover:text-primary-500 dark:group-hover:text-primary-400 transition-colors text-2xl">chevron_right</span>
|
92
|
+
</div>
|
93
|
+
</div>
|
94
|
+
</button>
|
95
|
+
{% endfor %}
|
96
|
+
</div>
|
97
|
+
</div>
|
98
|
+
</div>
|
99
|
+
{% endif %}
|
100
|
+
{% endfor %}
|
101
|
+
</div>
|
102
|
+
{% else %}
|
103
|
+
<!-- Fallback: All Commands List -->
|
104
|
+
<div class="bg-white dark:bg-base-800 rounded-default shadow-sm border border-base-200 dark:border-base-700">
|
105
|
+
<div class="p-6 border-b border-base-200 dark:border-base-700">
|
106
|
+
<h3 class="text-lg font-semibold text-font-important-light dark:text-font-important-dark flex items-center">
|
107
|
+
<span class="material-symbols-outlined text-primary-500 mr-2">list</span>
|
108
|
+
All Commands
|
109
|
+
</h3>
|
110
|
+
</div>
|
111
|
+
<div class="p-6">
|
112
|
+
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
113
|
+
{% for cmd in data.commands %}
|
114
|
+
<button type="button"
|
115
|
+
class="command-btn text-left p-4 rounded-default border border-base-200 dark:border-base-700 bg-white dark:bg-base-800 hover:bg-base-100 dark:hover:bg-white/[.04] transition-colors"
|
116
|
+
data-command="{{ cmd.name }}">
|
117
|
+
<div class="flex items-center justify-between">
|
118
|
+
<div>
|
119
|
+
<p class="font-mono text-sm text-font-important-light dark:text-font-important-dark font-semibold">{{ cmd.name }}</p>
|
120
|
+
{% if cmd.app %}
|
121
|
+
<p class="text-xs text-font-subtle-light dark:text-font-subtle-dark mt-1">{{ cmd.app }}</p>
|
122
|
+
{% endif %}
|
123
|
+
</div>
|
124
|
+
<span class="material-symbols-outlined text-primary-500">play_arrow</span>
|
125
|
+
</div>
|
126
|
+
</button>
|
127
|
+
{% endfor %}
|
128
|
+
</div>
|
129
|
+
</div>
|
130
|
+
</div>
|
131
|
+
{% endif %}
|
132
|
+
|
133
|
+
<!-- Confirm Modal -->
|
134
|
+
<div id="confirm-modal" class="hidden backdrop-blur-xs bg-base-900/80 fixed inset-0 p-4 lg:p-32 z-[1000]">
|
135
|
+
<div class="bg-white dark:bg-base-800 rounded-default shadow-lg border border-base-200 dark:border-base-700 max-w-3xl mx-auto w-full">
|
136
|
+
<div class="px-4 py-3 border-b border-base-200 dark:border-base-700">
|
137
|
+
<h3 class="text-lg font-semibold text-font-important-light dark:text-font-important-dark flex items-center gap-2">
|
138
|
+
<span class="material-symbols-outlined text-amber-500 dark:text-amber-400">warning</span>
|
139
|
+
Confirm Command Execution
|
140
|
+
</h3>
|
141
|
+
</div>
|
142
|
+
<div class="p-6">
|
143
|
+
<p class="text-font-default-light dark:text-font-default-dark mb-4">
|
144
|
+
Are you sure you want to execute the following command?
|
145
|
+
</p>
|
146
|
+
<div class="bg-base-100 dark:bg-base-900 rounded-default p-4 border border-base-200 dark:border-base-700">
|
147
|
+
<div class="flex items-start gap-3">
|
148
|
+
<span class="material-symbols-outlined text-primary-600 dark:text-primary-400 text-xl">terminal</span>
|
149
|
+
<div class="flex-1 min-w-0">
|
150
|
+
<p class="font-mono text-sm font-semibold text-font-important-light dark:text-font-important-dark" id="confirm-command-name"></p>
|
151
|
+
<p class="text-xs text-font-subtle-light dark:text-font-subtle-dark mt-2" id="confirm-command-app"></p>
|
152
|
+
<p class="text-xs text-font-default-light dark:text-font-default-dark mt-1" id="confirm-command-desc"></p>
|
153
|
+
</div>
|
154
|
+
</div>
|
155
|
+
</div>
|
156
|
+
</div>
|
157
|
+
<div class="px-4 py-3 border-t border-base-200 dark:border-base-800 flex items-center justify-end gap-3">
|
158
|
+
<button type="button" id="cancel-confirm" class="px-4 py-2 text-font-default-light dark:text-font-default-dark hover:bg-base-100 dark:hover:bg-base-700 rounded-default transition-colors">
|
159
|
+
Cancel
|
160
|
+
</button>
|
161
|
+
<button type="button" id="execute-confirm" class="px-4 py-2 bg-primary-600 text-white rounded-default hover:bg-primary-700 transition-colors font-medium">
|
162
|
+
Execute Command
|
163
|
+
</button>
|
164
|
+
</div>
|
165
|
+
</div>
|
166
|
+
</div>
|
167
|
+
|
168
|
+
<!-- Command Output Modal -->
|
169
|
+
<div id="command-modal" class="hidden backdrop-blur-xs bg-base-900/80 flex flex-col fixed inset-0 p-4 lg:p-32 z-[1000]">
|
170
|
+
<div class="bg-white dark:bg-base-800 flex flex-col max-w-3xl min-h-0 mx-auto overflow-hidden rounded-default shadow-lg w-full">
|
171
|
+
<div class="flex items-center justify-between px-4 py-3 border-b border-base-200 dark:border-base-700">
|
172
|
+
<h3 class="text-lg font-semibold text-font-important-light dark:text-font-important-dark flex items-center gap-2">
|
173
|
+
<span class="material-symbols-outlined text-primary-600 dark:text-primary-400">terminal</span>
|
174
|
+
<span id="modal-command-name" class="font-mono"></span>
|
175
|
+
</h3>
|
176
|
+
<button type="button" id="close-modal" class="text-base-400 dark:text-base-500 hover:text-base-600 dark:hover:text-base-300 transition-colors">
|
177
|
+
<span class="material-symbols-outlined">close</span>
|
178
|
+
</button>
|
179
|
+
</div>
|
180
|
+
<div class="grow overflow-y-auto overflow-x-hidden w-full" data-simplebar id="output-container">
|
181
|
+
<div class="p-4">
|
182
|
+
<pre id="command-output" class="bg-base-900 dark:bg-black text-green-400 p-4 rounded-default font-mono text-xs leading-relaxed whitespace-pre overflow-x-auto"></pre>
|
183
|
+
</div>
|
184
|
+
</div>
|
185
|
+
<div class="px-4 py-3 border-t border-base-200 dark:border-base-700">
|
186
|
+
<div class="flex items-center justify-between">
|
187
|
+
<div id="command-status" class="text-sm font-medium"></div>
|
188
|
+
<button type="button" id="copy-output" class="px-4 py-2 bg-primary-600 text-white rounded-default hover:bg-primary-700 transition-colors flex items-center gap-2 font-medium">
|
189
|
+
<span class="material-symbols-outlined text-base">content_copy</span>
|
190
|
+
Copy Output
|
191
|
+
</button>
|
192
|
+
</div>
|
193
|
+
</div>
|
194
|
+
</div>
|
195
|
+
</div>
|
196
|
+
</div>
|
197
|
+
|
198
|
+
<!-- JavaScript for Commands Section -->
|
199
|
+
<script>
|
200
|
+
document.addEventListener('DOMContentLoaded', function() {
|
201
|
+
// Category toggle functionality
|
202
|
+
const categoryToggles = document.querySelectorAll('.category-toggle');
|
203
|
+
categoryToggles.forEach(toggle => {
|
204
|
+
toggle.addEventListener('click', function() {
|
205
|
+
const category = this.dataset.category;
|
206
|
+
const content = document.querySelector(`.category-content[data-category="${category}"]`);
|
207
|
+
const icon = this.querySelector('.toggle-icon');
|
208
|
+
|
209
|
+
if (content.style.display === 'none' || !content.style.display) {
|
210
|
+
content.style.display = 'block';
|
211
|
+
icon.textContent = 'expand_less';
|
212
|
+
} else {
|
213
|
+
content.style.display = 'none';
|
214
|
+
icon.textContent = 'expand_more';
|
215
|
+
}
|
216
|
+
});
|
217
|
+
|
218
|
+
// Initialize - start collapsed
|
219
|
+
const category = toggle.dataset.category;
|
220
|
+
const content = document.querySelector(`.category-content[data-category="${category}"]`);
|
221
|
+
if (content) {
|
222
|
+
content.style.display = 'none';
|
223
|
+
}
|
224
|
+
});
|
225
|
+
|
226
|
+
// Command click handlers - show confirm first
|
227
|
+
const commandButtons = document.querySelectorAll('.command-btn');
|
228
|
+
commandButtons.forEach(btn => {
|
229
|
+
btn.addEventListener('click', function() {
|
230
|
+
const commandName = this.dataset.command;
|
231
|
+
const commandApp = this.dataset.app || '';
|
232
|
+
const commandDesc = this.dataset.description || '';
|
233
|
+
showConfirmModal(commandName, commandApp, commandDesc);
|
234
|
+
});
|
235
|
+
});
|
236
|
+
|
237
|
+
// Confirm modal handlers
|
238
|
+
const confirmModal = document.getElementById('confirm-modal');
|
239
|
+
const cancelConfirm = document.getElementById('cancel-confirm');
|
240
|
+
const executeConfirm = document.getElementById('execute-confirm');
|
241
|
+
|
242
|
+
if (cancelConfirm) {
|
243
|
+
cancelConfirm.addEventListener('click', function() {
|
244
|
+
confirmModal.classList.add('hidden');
|
245
|
+
});
|
246
|
+
}
|
247
|
+
|
248
|
+
if (executeConfirm) {
|
249
|
+
executeConfirm.addEventListener('click', function() {
|
250
|
+
const commandName = document.getElementById('confirm-command-name').textContent;
|
251
|
+
confirmModal.classList.add('hidden');
|
252
|
+
executeCommand(commandName);
|
253
|
+
});
|
254
|
+
}
|
255
|
+
|
256
|
+
// Close confirm modal on background click
|
257
|
+
if (confirmModal) {
|
258
|
+
confirmModal.addEventListener('click', function(e) {
|
259
|
+
if (e.target === confirmModal) {
|
260
|
+
confirmModal.classList.add('hidden');
|
261
|
+
}
|
262
|
+
});
|
263
|
+
}
|
264
|
+
|
265
|
+
// Output Modal close handlers
|
266
|
+
const outputModal = document.getElementById('command-modal');
|
267
|
+
const closeBtn = document.getElementById('close-modal');
|
268
|
+
|
269
|
+
if (closeBtn) {
|
270
|
+
closeBtn.addEventListener('click', function() {
|
271
|
+
outputModal.classList.add('hidden');
|
272
|
+
});
|
273
|
+
}
|
274
|
+
|
275
|
+
// Close output modal on background click
|
276
|
+
if (outputModal) {
|
277
|
+
outputModal.addEventListener('click', function(e) {
|
278
|
+
if (e.target === outputModal) {
|
279
|
+
outputModal.classList.add('hidden');
|
280
|
+
}
|
281
|
+
});
|
282
|
+
}
|
283
|
+
|
284
|
+
// Copy output functionality
|
285
|
+
const copyBtn = document.getElementById('copy-output');
|
286
|
+
if (copyBtn) {
|
287
|
+
copyBtn.addEventListener('click', function() {
|
288
|
+
const output = document.getElementById('command-output');
|
289
|
+
if (output) {
|
290
|
+
navigator.clipboard.writeText(output.textContent).then(function() {
|
291
|
+
const originalText = copyBtn.innerHTML;
|
292
|
+
copyBtn.innerHTML = '<span class="material-symbols-outlined mr-2">check</span>Copied!';
|
293
|
+
setTimeout(function() {
|
294
|
+
copyBtn.innerHTML = originalText;
|
295
|
+
}, 2000);
|
296
|
+
}).catch(function(err) {
|
297
|
+
console.error('Could not copy text: ', err);
|
298
|
+
});
|
299
|
+
}
|
300
|
+
});
|
301
|
+
}
|
302
|
+
|
303
|
+
// Escape key to close modals
|
304
|
+
document.addEventListener('keydown', function(e) {
|
305
|
+
if (e.key === 'Escape') {
|
306
|
+
if (confirmModal && !confirmModal.classList.contains('hidden')) {
|
307
|
+
confirmModal.classList.add('hidden');
|
308
|
+
}
|
309
|
+
if (outputModal && !outputModal.classList.contains('hidden')) {
|
310
|
+
outputModal.classList.add('hidden');
|
311
|
+
}
|
312
|
+
}
|
313
|
+
});
|
314
|
+
|
315
|
+
// Search functionality
|
316
|
+
const searchInput = document.getElementById('command-search');
|
317
|
+
const clearSearchBtn = document.getElementById('clear-search');
|
318
|
+
|
319
|
+
if (searchInput) {
|
320
|
+
searchInput.addEventListener('input', function(e) {
|
321
|
+
const query = e.target.value.toLowerCase().trim();
|
322
|
+
filterCommands(query);
|
323
|
+
|
324
|
+
// Show/hide clear button
|
325
|
+
if (query) {
|
326
|
+
clearSearchBtn.classList.remove('hidden');
|
327
|
+
} else {
|
328
|
+
clearSearchBtn.classList.add('hidden');
|
329
|
+
}
|
330
|
+
});
|
331
|
+
}
|
332
|
+
});
|
333
|
+
|
334
|
+
// Search/filter commands
|
335
|
+
function filterCommands(query) {
|
336
|
+
const categoryBlocks = document.querySelectorAll('.category-block');
|
337
|
+
let totalVisible = 0;
|
338
|
+
|
339
|
+
categoryBlocks.forEach(block => {
|
340
|
+
const commands = block.querySelectorAll('.command-item');
|
341
|
+
const categoryCount = block.querySelector('.category-count');
|
342
|
+
let visibleCount = 0;
|
343
|
+
|
344
|
+
commands.forEach(cmd => {
|
345
|
+
const commandName = cmd.querySelector('.command-name').textContent.toLowerCase();
|
346
|
+
const commandApp = cmd.dataset.app ? cmd.dataset.app.toLowerCase() : '';
|
347
|
+
const commandDesc = cmd.dataset.description ? cmd.dataset.description.toLowerCase() : '';
|
348
|
+
|
349
|
+
if (!query || commandName.includes(query) || commandApp.includes(query) || commandDesc.includes(query)) {
|
350
|
+
cmd.style.display = 'block';
|
351
|
+
visibleCount++;
|
352
|
+
totalVisible++;
|
353
|
+
} else {
|
354
|
+
cmd.style.display = 'none';
|
355
|
+
}
|
356
|
+
});
|
357
|
+
|
358
|
+
// Update category count
|
359
|
+
if (categoryCount) {
|
360
|
+
categoryCount.textContent = `(${visibleCount})`;
|
361
|
+
}
|
362
|
+
|
363
|
+
// Hide category if no visible commands
|
364
|
+
if (visibleCount === 0) {
|
365
|
+
block.style.display = 'none';
|
366
|
+
} else {
|
367
|
+
block.style.display = 'block';
|
368
|
+
|
369
|
+
// Auto-expand categories when searching
|
370
|
+
if (query) {
|
371
|
+
const content = block.querySelector('.category-content');
|
372
|
+
const icon = block.querySelector('.toggle-icon');
|
373
|
+
if (content && icon) {
|
374
|
+
content.style.display = 'block';
|
375
|
+
icon.textContent = 'expand_less';
|
376
|
+
}
|
377
|
+
}
|
378
|
+
}
|
379
|
+
});
|
380
|
+
|
381
|
+
// Update total commands count
|
382
|
+
const totalCounter = document.getElementById('commands-total');
|
383
|
+
if (totalCounter) {
|
384
|
+
totalCounter.textContent = totalVisible;
|
385
|
+
}
|
386
|
+
}
|
387
|
+
|
388
|
+
// Clear search
|
389
|
+
function clearSearch() {
|
390
|
+
const searchInput = document.getElementById('command-search');
|
391
|
+
const clearBtn = document.getElementById('clear-search');
|
392
|
+
const categoryBlocks = document.querySelectorAll('.category-block');
|
393
|
+
const totalCounter = document.getElementById('commands-total');
|
394
|
+
|
395
|
+
// Clear input
|
396
|
+
if (searchInput) {
|
397
|
+
searchInput.value = '';
|
398
|
+
}
|
399
|
+
|
400
|
+
// Hide clear button
|
401
|
+
if (clearBtn) {
|
402
|
+
clearBtn.classList.add('hidden');
|
403
|
+
}
|
404
|
+
|
405
|
+
// Reset all blocks
|
406
|
+
categoryBlocks.forEach(block => {
|
407
|
+
block.style.display = 'block';
|
408
|
+
const commands = block.querySelectorAll('.command-item');
|
409
|
+
const categoryCount = block.querySelector('.category-count');
|
410
|
+
|
411
|
+
// Show all commands
|
412
|
+
commands.forEach(cmd => {
|
413
|
+
cmd.style.display = 'block';
|
414
|
+
});
|
415
|
+
|
416
|
+
// Reset category count
|
417
|
+
if (categoryCount) {
|
418
|
+
const originalCount = commands.length;
|
419
|
+
categoryCount.textContent = `(${originalCount})`;
|
420
|
+
}
|
421
|
+
|
422
|
+
// Collapse categories
|
423
|
+
const content = block.querySelector('.category-content');
|
424
|
+
const icon = block.querySelector('.toggle-icon');
|
425
|
+
if (content && icon) {
|
426
|
+
content.style.display = 'none';
|
427
|
+
icon.textContent = 'expand_more';
|
428
|
+
}
|
429
|
+
});
|
430
|
+
|
431
|
+
// Reset total
|
432
|
+
if (totalCounter) {
|
433
|
+
const allCommands = document.querySelectorAll('.command-item');
|
434
|
+
totalCounter.textContent = allCommands.length;
|
435
|
+
}
|
436
|
+
}
|
437
|
+
|
438
|
+
// Show confirm modal
|
439
|
+
function showConfirmModal(commandName, commandApp, commandDesc) {
|
440
|
+
const confirmModal = document.getElementById('confirm-modal');
|
441
|
+
const confirmCommandName = document.getElementById('confirm-command-name');
|
442
|
+
const confirmCommandApp = document.getElementById('confirm-command-app');
|
443
|
+
const confirmCommandDesc = document.getElementById('confirm-command-desc');
|
444
|
+
|
445
|
+
if (!confirmModal || !confirmCommandName) {
|
446
|
+
console.error('Confirm modal elements not found');
|
447
|
+
return;
|
448
|
+
}
|
449
|
+
|
450
|
+
confirmCommandName.textContent = commandName;
|
451
|
+
confirmCommandApp.textContent = commandApp ? `from ${commandApp}` : '';
|
452
|
+
confirmCommandDesc.textContent = commandDesc || '';
|
453
|
+
|
454
|
+
confirmModal.classList.remove('hidden');
|
455
|
+
}
|
456
|
+
|
457
|
+
// Execute command function with SSE streaming
|
458
|
+
function executeCommand(commandName) {
|
459
|
+
const modal = document.getElementById('command-modal');
|
460
|
+
const modalCommandName = document.getElementById('modal-command-name');
|
461
|
+
const commandOutput = document.getElementById('command-output');
|
462
|
+
const commandStatus = document.getElementById('command-status');
|
463
|
+
|
464
|
+
if (!modal || !modalCommandName || !commandOutput || !commandStatus) {
|
465
|
+
console.error('Command modal elements not found');
|
466
|
+
return;
|
467
|
+
}
|
468
|
+
|
469
|
+
// Show modal and initialize
|
470
|
+
modalCommandName.textContent = commandName;
|
471
|
+
commandOutput.innerHTML = '';
|
472
|
+
commandStatus.textContent = 'Executing...';
|
473
|
+
commandStatus.className = 'text-sm text-primary-600 dark:text-primary-400';
|
474
|
+
modal.classList.remove('hidden');
|
475
|
+
|
476
|
+
// Execute command via API with SSE streaming
|
477
|
+
fetch('/cfg/commands/execute/', {
|
478
|
+
method: 'POST',
|
479
|
+
headers: {
|
480
|
+
'Content-Type': 'application/json',
|
481
|
+
'X-CSRFToken': getCookie('csrftoken')
|
482
|
+
},
|
483
|
+
body: JSON.stringify({
|
484
|
+
command: commandName,
|
485
|
+
args: [],
|
486
|
+
options: {}
|
487
|
+
})
|
488
|
+
})
|
489
|
+
.then(response => {
|
490
|
+
if (!response.ok) {
|
491
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
492
|
+
}
|
493
|
+
|
494
|
+
const reader = response.body.getReader();
|
495
|
+
const decoder = new TextDecoder();
|
496
|
+
|
497
|
+
function readStream() {
|
498
|
+
return reader.read().then(({done, value}) => {
|
499
|
+
if (done) return;
|
500
|
+
|
501
|
+
const chunk = decoder.decode(value);
|
502
|
+
const lines = chunk.split('\n');
|
503
|
+
|
504
|
+
lines.forEach(line => {
|
505
|
+
if (line.startsWith('data: ')) {
|
506
|
+
try {
|
507
|
+
const data = JSON.parse(line.slice(6));
|
508
|
+
handleCommandData(data);
|
509
|
+
} catch (e) {
|
510
|
+
console.error('Error parsing command data:', e, line);
|
511
|
+
}
|
512
|
+
}
|
513
|
+
});
|
514
|
+
|
515
|
+
return readStream();
|
516
|
+
});
|
517
|
+
}
|
518
|
+
|
519
|
+
return readStream();
|
520
|
+
})
|
521
|
+
.catch(error => {
|
522
|
+
console.error('Error executing command:', error);
|
523
|
+
addLogLine(commandOutput, `\n❌ Error: ${error.message}`, 'error');
|
524
|
+
commandStatus.textContent = '❌ Error';
|
525
|
+
commandStatus.className = 'text-sm text-red-500 dark:text-red-400';
|
526
|
+
});
|
527
|
+
}
|
528
|
+
|
529
|
+
// Handle SSE command data
|
530
|
+
function handleCommandData(data) {
|
531
|
+
const output = document.getElementById('command-output');
|
532
|
+
const status = document.getElementById('command-status');
|
533
|
+
|
534
|
+
if (!output || !status) return;
|
535
|
+
|
536
|
+
switch (data.type) {
|
537
|
+
case 'start':
|
538
|
+
output.innerHTML = '';
|
539
|
+
addLogLine(output, `🚀 Starting command: ${data.command}`, 'info');
|
540
|
+
const args = (data.args && Array.isArray(data.args)) ? data.args.join(' ') : 'none';
|
541
|
+
addLogLine(output, `📝 Arguments: ${args}`, 'info');
|
542
|
+
addLogLine(output, '', 'spacer');
|
543
|
+
status.textContent = 'Executing...';
|
544
|
+
status.className = 'text-sm text-primary-600 dark:text-primary-400';
|
545
|
+
break;
|
546
|
+
case 'output':
|
547
|
+
addLogLine(output, data.line, 'output');
|
548
|
+
scrollToBottom(document.getElementById('output-container'));
|
549
|
+
break;
|
550
|
+
case 'complete':
|
551
|
+
const success = data.return_code === 0;
|
552
|
+
status.textContent = success ? '✅ Success' : '❌ Failed';
|
553
|
+
status.className = success
|
554
|
+
? 'text-sm text-green-500 dark:text-green-400'
|
555
|
+
: 'text-sm text-red-500 dark:text-red-400';
|
556
|
+
|
557
|
+
addLogLine(output, '', 'spacer');
|
558
|
+
let completionMessage = `${success ? '✅' : '❌'} Command completed with exit code: ${data.return_code}`;
|
559
|
+
if (data.execution_time) {
|
560
|
+
completionMessage += ` (${data.execution_time}s)`;
|
561
|
+
}
|
562
|
+
addLogLine(output, completionMessage, success ? 'success' : 'error');
|
563
|
+
scrollToBottom(document.getElementById('output-container'));
|
564
|
+
break;
|
565
|
+
case 'error':
|
566
|
+
const errorMsg = data.message || data.error || 'Unknown error';
|
567
|
+
addLogLine(output, `❌ ${errorMsg}`, 'error');
|
568
|
+
status.textContent = '❌ Error';
|
569
|
+
status.className = 'text-sm text-red-500 dark:text-red-400';
|
570
|
+
scrollToBottom(document.getElementById('output-container'));
|
571
|
+
break;
|
572
|
+
}
|
573
|
+
}
|
574
|
+
|
575
|
+
// Add log line to output
|
576
|
+
function addLogLine(container, text, type = 'output') {
|
577
|
+
const line = document.createElement('div');
|
578
|
+
line.className = 'log-line font-mono';
|
579
|
+
|
580
|
+
switch (type) {
|
581
|
+
case 'info':
|
582
|
+
line.className += ' text-blue-500 dark:text-blue-400';
|
583
|
+
break;
|
584
|
+
case 'success':
|
585
|
+
line.className += ' text-green-500 dark:text-green-400 font-semibold';
|
586
|
+
break;
|
587
|
+
case 'error':
|
588
|
+
line.className += ' text-red-500 dark:text-red-400 font-semibold';
|
589
|
+
break;
|
590
|
+
case 'spacer':
|
591
|
+
line.style.height = '0.5em';
|
592
|
+
line.innerHTML = ' ';
|
593
|
+
break;
|
594
|
+
default:
|
595
|
+
line.className += ' text-green-400 dark:text-green-400';
|
596
|
+
}
|
597
|
+
|
598
|
+
if (type !== 'spacer') {
|
599
|
+
line.textContent = text;
|
600
|
+
}
|
601
|
+
container.appendChild(line);
|
602
|
+
}
|
603
|
+
|
604
|
+
// Scroll to bottom helper
|
605
|
+
function scrollToBottom(element) {
|
606
|
+
if (element) {
|
607
|
+
element.scrollTop = element.scrollHeight;
|
608
|
+
}
|
609
|
+
}
|
610
|
+
|
611
|
+
// Get CSRF token
|
612
|
+
function getCookie(name) {
|
613
|
+
let cookieValue = null;
|
614
|
+
if (document.cookie && document.cookie !== '') {
|
615
|
+
const cookies = document.cookie.split(';');
|
616
|
+
for (let i = 0; i < cookies.length; i++) {
|
617
|
+
const cookie = cookies[i].trim();
|
618
|
+
if (cookie.substring(0, name.length + 1) === (name + '=')) {
|
619
|
+
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
|
620
|
+
break;
|
621
|
+
}
|
622
|
+
}
|
623
|
+
}
|
624
|
+
return cookieValue;
|
625
|
+
}
|
626
|
+
</script>
|