django-cfg 1.2.31__py3-none-any.whl → 1.3.1__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/api/health/views.py +4 -2
- django_cfg/apps/knowbase/config/settings.py +16 -15
- django_cfg/apps/payments/README.md +326 -0
- django_cfg/apps/payments/admin/__init__.py +20 -10
- django_cfg/apps/payments/admin/api_keys_admin.py +521 -237
- django_cfg/apps/payments/admin/balance_admin.py +592 -297
- django_cfg/apps/payments/admin/currencies_admin.py +526 -222
- django_cfg/apps/payments/admin/filters.py +306 -199
- django_cfg/apps/payments/admin/payments_admin.py +465 -70
- django_cfg/apps/payments/admin/subscriptions_admin.py +578 -128
- django_cfg/apps/payments/admin_interface/__init__.py +18 -0
- django_cfg/apps/payments/admin_interface/templates/payments/base.html +162 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/dev_tool_card.html +38 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/loading_spinner.html +16 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/notification.html +27 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/provider_card.html +86 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/status_card.html +39 -0
- django_cfg/apps/payments/admin_interface/templates/payments/currency_converter.html +382 -0
- django_cfg/apps/payments/admin_interface/templates/payments/payment_dashboard.html +300 -0
- django_cfg/apps/payments/admin_interface/templates/payments/payment_form.html +303 -0
- django_cfg/apps/payments/admin_interface/templates/payments/payment_list.html +382 -0
- django_cfg/apps/payments/admin_interface/templates/payments/payment_status.html +500 -0
- django_cfg/apps/payments/admin_interface/templates/payments/webhook_dashboard.html +594 -0
- django_cfg/apps/payments/admin_interface/views/__init__.py +23 -0
- django_cfg/apps/payments/admin_interface/views/payment_views.py +259 -0
- django_cfg/apps/payments/admin_interface/views/webhook_dashboard.py +37 -0
- django_cfg/apps/payments/apps.py +34 -9
- django_cfg/apps/payments/config/__init__.py +28 -51
- django_cfg/apps/payments/config/constance/__init__.py +22 -0
- django_cfg/apps/payments/config/constance/config_service.py +123 -0
- django_cfg/apps/payments/config/constance/fields.py +69 -0
- django_cfg/apps/payments/config/constance/settings.py +160 -0
- django_cfg/apps/payments/config/django_cfg_integration.py +202 -0
- django_cfg/apps/payments/config/helpers.py +130 -0
- django_cfg/apps/payments/management/__init__.py +1 -3
- django_cfg/apps/payments/management/commands/__init__.py +1 -3
- django_cfg/apps/payments/management/commands/manage_currencies.py +303 -151
- django_cfg/apps/payments/management/commands/manage_providers.py +333 -160
- django_cfg/apps/payments/middleware/__init__.py +3 -1
- django_cfg/apps/payments/middleware/api_access.py +329 -222
- django_cfg/apps/payments/middleware/rate_limiting.py +342 -152
- django_cfg/apps/payments/middleware/usage_tracking.py +249 -240
- django_cfg/apps/payments/migrations/0001_initial.py +708 -536
- django_cfg/apps/payments/models/__init__.py +13 -18
- django_cfg/apps/payments/models/api_keys.py +121 -43
- django_cfg/apps/payments/models/balance.py +150 -115
- django_cfg/apps/payments/models/base.py +68 -15
- django_cfg/apps/payments/models/currencies.py +172 -148
- django_cfg/apps/payments/models/managers/__init__.py +44 -0
- django_cfg/apps/payments/models/managers/api_key_managers.py +329 -0
- django_cfg/apps/payments/models/managers/balance_managers.py +599 -0
- django_cfg/apps/payments/models/managers/currency_managers.py +385 -0
- django_cfg/apps/payments/models/managers/payment_managers.py +511 -0
- django_cfg/apps/payments/models/managers/subscription_managers.py +641 -0
- django_cfg/apps/payments/models/payments.py +235 -285
- django_cfg/apps/payments/models/subscriptions.py +257 -177
- django_cfg/apps/payments/models/tariffs.py +147 -40
- django_cfg/apps/payments/services/__init__.py +209 -56
- django_cfg/apps/payments/services/cache/__init__.py +6 -6
- django_cfg/apps/payments/services/cache/{simple_cache.py → cache_service.py} +112 -12
- django_cfg/apps/payments/services/core/__init__.py +10 -6
- django_cfg/apps/payments/services/core/balance_service.py +435 -360
- django_cfg/apps/payments/services/core/base.py +166 -0
- django_cfg/apps/payments/services/core/currency_service.py +478 -0
- django_cfg/apps/payments/services/core/payment_service.py +346 -467
- django_cfg/apps/payments/services/core/subscription_service.py +425 -481
- django_cfg/apps/payments/services/core/webhook_service.py +410 -0
- django_cfg/apps/payments/services/integrations/__init__.py +29 -0
- django_cfg/apps/payments/services/integrations/ngrok_service.py +47 -0
- django_cfg/apps/payments/services/integrations/providers_config.py +107 -0
- django_cfg/apps/payments/services/providers/__init__.py +9 -14
- django_cfg/apps/payments/services/providers/base.py +234 -174
- django_cfg/apps/payments/services/providers/nowpayments.py +478 -0
- django_cfg/apps/payments/services/providers/registry.py +367 -301
- django_cfg/apps/payments/services/types/__init__.py +78 -0
- django_cfg/apps/payments/services/types/data.py +177 -0
- django_cfg/apps/payments/services/types/requests.py +150 -0
- django_cfg/apps/payments/services/types/responses.py +156 -0
- django_cfg/apps/payments/services/types/webhooks.py +232 -0
- django_cfg/apps/payments/signals/__init__.py +33 -8
- django_cfg/apps/payments/signals/api_key_signals.py +210 -129
- django_cfg/apps/payments/signals/balance_signals.py +174 -0
- django_cfg/apps/payments/signals/payment_signals.py +128 -103
- django_cfg/apps/payments/signals/subscription_signals.py +194 -142
- django_cfg/apps/payments/static/payments/css/components.css +380 -0
- django_cfg/apps/payments/static/payments/css/dashboard.css +188 -0
- django_cfg/apps/payments/static/payments/js/components.js +545 -0
- django_cfg/apps/payments/static/payments/js/utils.js +412 -0
- django_cfg/apps/payments/templatetags/__init__.py +1 -1
- django_cfg/apps/payments/templatetags/payment_tags.py +466 -0
- django_cfg/apps/payments/urls.py +45 -48
- django_cfg/apps/payments/urls_admin.py +33 -42
- django_cfg/apps/payments/views/api/__init__.py +101 -0
- django_cfg/apps/payments/views/api/api_keys.py +387 -0
- django_cfg/apps/payments/views/api/balances.py +381 -0
- django_cfg/apps/payments/views/api/base.py +298 -0
- django_cfg/apps/payments/views/api/currencies.py +402 -0
- django_cfg/apps/payments/views/api/payments.py +415 -0
- django_cfg/apps/payments/views/api/subscriptions.py +475 -0
- django_cfg/apps/payments/views/api/webhooks.py +476 -0
- django_cfg/apps/payments/views/serializers/__init__.py +99 -0
- django_cfg/apps/payments/views/serializers/api_keys.py +424 -0
- django_cfg/apps/payments/views/serializers/balances.py +300 -0
- django_cfg/apps/payments/views/serializers/currencies.py +335 -0
- django_cfg/apps/payments/views/serializers/payments.py +387 -0
- django_cfg/apps/payments/views/serializers/subscriptions.py +429 -0
- django_cfg/apps/payments/views/serializers/webhooks.py +137 -0
- django_cfg/config.py +1 -1
- django_cfg/core/config.py +40 -4
- django_cfg/core/generation.py +25 -4
- django_cfg/core/integration/README.md +363 -0
- django_cfg/core/integration/__init__.py +47 -0
- django_cfg/core/integration/commands_collector.py +239 -0
- django_cfg/core/integration/display/__init__.py +15 -0
- django_cfg/core/integration/display/base.py +157 -0
- django_cfg/core/integration/display/ngrok.py +164 -0
- django_cfg/core/integration/display/startup.py +815 -0
- django_cfg/core/integration/url_integration.py +123 -0
- django_cfg/core/integration/version_checker.py +160 -0
- django_cfg/management/commands/auto_generate.py +4 -0
- django_cfg/management/commands/check_settings.py +6 -0
- django_cfg/management/commands/clear_constance.py +5 -2
- django_cfg/management/commands/create_token.py +6 -0
- django_cfg/management/commands/list_urls.py +6 -0
- django_cfg/management/commands/migrate_all.py +6 -0
- django_cfg/management/commands/migrator.py +3 -0
- django_cfg/management/commands/rundramatiq.py +6 -0
- django_cfg/management/commands/runserver_ngrok.py +51 -29
- django_cfg/management/commands/script.py +6 -0
- django_cfg/management/commands/show_config.py +12 -2
- django_cfg/management/commands/show_urls.py +4 -0
- django_cfg/management/commands/superuser.py +6 -0
- django_cfg/management/commands/task_clear.py +4 -1
- django_cfg/management/commands/task_status.py +3 -1
- django_cfg/management/commands/test_email.py +3 -0
- django_cfg/management/commands/test_telegram.py +6 -0
- django_cfg/management/commands/test_twilio.py +6 -0
- django_cfg/management/commands/tree.py +6 -0
- django_cfg/management/commands/validate_config.py +155 -149
- django_cfg/models/constance.py +31 -11
- django_cfg/models/payments.py +175 -492
- django_cfg/modules/django_logger.py +160 -146
- django_cfg/modules/django_unfold/dashboard.py +64 -16
- django_cfg/registry/core.py +1 -0
- django_cfg/template_archive/django_sample.zip +0 -0
- django_cfg/utils/smart_defaults.py +222 -571
- django_cfg/utils/toolkit.py +51 -11
- {django_cfg-1.2.31.dist-info → django_cfg-1.3.1.dist-info}/METADATA +4 -1
- {django_cfg-1.2.31.dist-info → django_cfg-1.3.1.dist-info}/RECORD +153 -185
- django_cfg/apps/payments/__init__.py +0 -8
- django_cfg/apps/payments/admin/tariffs_admin.py +0 -199
- django_cfg/apps/payments/config/module.py +0 -70
- django_cfg/apps/payments/config/providers.py +0 -105
- django_cfg/apps/payments/config/settings.py +0 -96
- django_cfg/apps/payments/config/utils.py +0 -52
- django_cfg/apps/payments/decorators.py +0 -291
- django_cfg/apps/payments/management/commands/README.md +0 -146
- django_cfg/apps/payments/management/commands/currency_stats.py +0 -304
- django_cfg/apps/payments/managers/__init__.py +0 -23
- django_cfg/apps/payments/managers/api_key_manager.py +0 -35
- django_cfg/apps/payments/managers/balance_manager.py +0 -361
- django_cfg/apps/payments/managers/currency_manager.py +0 -306
- django_cfg/apps/payments/managers/payment_manager.py +0 -192
- django_cfg/apps/payments/managers/subscription_manager.py +0 -37
- django_cfg/apps/payments/managers/tariff_manager.py +0 -29
- django_cfg/apps/payments/migrations/0002_network_providercurrency_and_more.py +0 -241
- django_cfg/apps/payments/migrations/0003_add_usd_rate_cache.py +0 -30
- django_cfg/apps/payments/models/events.py +0 -73
- django_cfg/apps/payments/serializers/__init__.py +0 -57
- django_cfg/apps/payments/serializers/api_keys.py +0 -51
- django_cfg/apps/payments/serializers/balance.py +0 -59
- django_cfg/apps/payments/serializers/currencies.py +0 -63
- django_cfg/apps/payments/serializers/payments.py +0 -62
- django_cfg/apps/payments/serializers/subscriptions.py +0 -71
- django_cfg/apps/payments/serializers/tariffs.py +0 -56
- django_cfg/apps/payments/services/billing/__init__.py +0 -8
- django_cfg/apps/payments/services/cache/base.py +0 -30
- django_cfg/apps/payments/services/core/fallback_service.py +0 -432
- django_cfg/apps/payments/services/internal_types.py +0 -461
- django_cfg/apps/payments/services/middleware/__init__.py +0 -8
- django_cfg/apps/payments/services/monitoring/__init__.py +0 -22
- django_cfg/apps/payments/services/monitoring/api_schemas.py +0 -76
- django_cfg/apps/payments/services/monitoring/provider_health.py +0 -372
- django_cfg/apps/payments/services/providers/cryptapi/__init__.py +0 -4
- django_cfg/apps/payments/services/providers/cryptapi/config.py +0 -8
- django_cfg/apps/payments/services/providers/cryptapi/models.py +0 -192
- django_cfg/apps/payments/services/providers/cryptapi/provider.py +0 -439
- django_cfg/apps/payments/services/providers/cryptomus/__init__.py +0 -4
- django_cfg/apps/payments/services/providers/cryptomus/models.py +0 -176
- django_cfg/apps/payments/services/providers/cryptomus/provider.py +0 -429
- django_cfg/apps/payments/services/providers/cryptomus/provider_v2.py +0 -564
- django_cfg/apps/payments/services/providers/models/__init__.py +0 -34
- django_cfg/apps/payments/services/providers/models/currencies.py +0 -190
- django_cfg/apps/payments/services/providers/nowpayments/__init__.py +0 -4
- django_cfg/apps/payments/services/providers/nowpayments/models.py +0 -196
- django_cfg/apps/payments/services/providers/nowpayments/provider.py +0 -380
- django_cfg/apps/payments/services/providers/stripe/__init__.py +0 -4
- django_cfg/apps/payments/services/providers/stripe/models.py +0 -184
- django_cfg/apps/payments/services/providers/stripe/provider.py +0 -109
- django_cfg/apps/payments/services/security/__init__.py +0 -34
- django_cfg/apps/payments/services/security/error_handler.py +0 -635
- django_cfg/apps/payments/services/security/payment_notifications.py +0 -342
- django_cfg/apps/payments/services/security/webhook_validator.py +0 -474
- django_cfg/apps/payments/static/payments/css/payments.css +0 -340
- django_cfg/apps/payments/static/payments/js/notifications.js +0 -202
- django_cfg/apps/payments/static/payments/js/payment-utils.js +0 -318
- django_cfg/apps/payments/static/payments/js/theme.js +0 -86
- django_cfg/apps/payments/tasks/__init__.py +0 -12
- django_cfg/apps/payments/tasks/webhook_processing.py +0 -177
- django_cfg/apps/payments/templates/admin/payments/currency/change_list.html +0 -50
- django_cfg/apps/payments/templates/payments/base.html +0 -182
- django_cfg/apps/payments/templates/payments/components/payment_card.html +0 -201
- django_cfg/apps/payments/templates/payments/components/payment_qr_code.html +0 -109
- django_cfg/apps/payments/templates/payments/components/progress_bar.html +0 -43
- django_cfg/apps/payments/templates/payments/components/provider_stats.html +0 -40
- django_cfg/apps/payments/templates/payments/components/status_badge.html +0 -34
- django_cfg/apps/payments/templates/payments/components/status_overview.html +0 -148
- django_cfg/apps/payments/templates/payments/dashboard.html +0 -258
- django_cfg/apps/payments/templates/payments/dashboard_simple_test.html +0 -35
- django_cfg/apps/payments/templates/payments/payment_create.html +0 -579
- django_cfg/apps/payments/templates/payments/payment_detail.html +0 -373
- django_cfg/apps/payments/templates/payments/payment_list.html +0 -354
- django_cfg/apps/payments/templates/payments/stats.html +0 -261
- django_cfg/apps/payments/templates/payments/test.html +0 -213
- django_cfg/apps/payments/templatetags/payments_tags.py +0 -315
- django_cfg/apps/payments/utils/__init__.py +0 -43
- django_cfg/apps/payments/utils/billing_utils.py +0 -342
- django_cfg/apps/payments/utils/config_utils.py +0 -239
- django_cfg/apps/payments/utils/middleware_utils.py +0 -228
- django_cfg/apps/payments/utils/validation_utils.py +0 -94
- django_cfg/apps/payments/views/__init__.py +0 -63
- django_cfg/apps/payments/views/api_key_views.py +0 -164
- django_cfg/apps/payments/views/balance_views.py +0 -75
- django_cfg/apps/payments/views/currency_views.py +0 -122
- django_cfg/apps/payments/views/payment_views.py +0 -149
- django_cfg/apps/payments/views/subscription_views.py +0 -135
- django_cfg/apps/payments/views/tariff_views.py +0 -131
- django_cfg/apps/payments/views/templates/__init__.py +0 -25
- django_cfg/apps/payments/views/templates/ajax.py +0 -451
- django_cfg/apps/payments/views/templates/base.py +0 -212
- django_cfg/apps/payments/views/templates/dashboard.py +0 -60
- django_cfg/apps/payments/views/templates/payment_detail.py +0 -102
- django_cfg/apps/payments/views/templates/payment_management.py +0 -158
- django_cfg/apps/payments/views/templates/qr_code.py +0 -174
- django_cfg/apps/payments/views/templates/stats.py +0 -244
- django_cfg/apps/payments/views/templates/utils.py +0 -181
- django_cfg/apps/payments/views/webhook_views.py +0 -266
- django_cfg/apps/payments/viewsets.py +0 -66
- django_cfg/core/integration.py +0 -160
- django_cfg/template_archive/.gitignore +0 -1
- django_cfg/template_archive/__init__.py +0 -0
- django_cfg/urls.py +0 -33
- {django_cfg-1.2.31.dist-info → django_cfg-1.3.1.dist-info}/WHEEL +0 -0
- {django_cfg-1.2.31.dist-info → django_cfg-1.3.1.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.2.31.dist-info → django_cfg-1.3.1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,815 @@
|
|
1
|
+
"""
|
2
|
+
Startup display manager for Django CFG.
|
3
|
+
"""
|
4
|
+
|
5
|
+
from typing import Optional, Dict, Any, List
|
6
|
+
from rich.text import Text
|
7
|
+
from rich.table import Table
|
8
|
+
from rich.panel import Panel
|
9
|
+
from .base import BaseDisplayManager, MAIN_PANEL_WIDTH, HALF_PANEL_WIDTH
|
10
|
+
from .ngrok import NgrokDisplayManager
|
11
|
+
|
12
|
+
|
13
|
+
class StartupDisplayManager(BaseDisplayManager):
|
14
|
+
"""Manager for displaying startup information."""
|
15
|
+
|
16
|
+
def __init__(self, config=None):
|
17
|
+
"""Initialize startup display manager."""
|
18
|
+
super().__init__(config)
|
19
|
+
self.ngrok_manager = NgrokDisplayManager(config)
|
20
|
+
|
21
|
+
def display_startup_info(self):
|
22
|
+
"""Display startup information based on config.startup_info_mode."""
|
23
|
+
try:
|
24
|
+
if not self.config:
|
25
|
+
return
|
26
|
+
|
27
|
+
# Always check and display ngrok info first if active
|
28
|
+
self.ngrok_manager.display_if_active()
|
29
|
+
|
30
|
+
from django_cfg.core.config import StartupInfoMode
|
31
|
+
mode = self.config.startup_info_mode
|
32
|
+
|
33
|
+
if mode == StartupInfoMode.NONE:
|
34
|
+
self.display_minimal_info()
|
35
|
+
elif mode == StartupInfoMode.SHORT:
|
36
|
+
self.display_essential_info()
|
37
|
+
elif mode == StartupInfoMode.FULL:
|
38
|
+
self.display_complete_info()
|
39
|
+
|
40
|
+
except Exception:
|
41
|
+
# Silently fail - startup info is not critical
|
42
|
+
pass
|
43
|
+
|
44
|
+
def display_minimal_info(self):
|
45
|
+
"""Display minimal startup info (NONE mode)."""
|
46
|
+
version = self.get_version()
|
47
|
+
panel_style, env_emoji, env_color = self.get_environment_style()
|
48
|
+
|
49
|
+
# Simple one-liner
|
50
|
+
info_text = Text()
|
51
|
+
info_text.append(f"{env_emoji} Django CFG ", style="bold")
|
52
|
+
info_text.append(f"v{version}", style="cyan")
|
53
|
+
info_text.append(" • ", style="dim")
|
54
|
+
info_text.append(f"{self.config.env_mode}", style=env_color)
|
55
|
+
info_text.append(" • ", style="dim")
|
56
|
+
info_text.append(f"{self.config.project_name}", style="white")
|
57
|
+
|
58
|
+
# Check for critical updates
|
59
|
+
try:
|
60
|
+
from ..version_checker import get_version_info
|
61
|
+
version_info = get_version_info()
|
62
|
+
if version_info.get('update_available'):
|
63
|
+
info_text.append(" • ", style="dim")
|
64
|
+
info_text.append("🚨 UPDATE AVAILABLE", style="bold yellow")
|
65
|
+
info_text.append(" (", style="dim")
|
66
|
+
info_text.append("poetry add django-cfg@latest", style="bright_blue")
|
67
|
+
info_text.append(")", style="dim")
|
68
|
+
except Exception:
|
69
|
+
pass
|
70
|
+
|
71
|
+
self.console.print(info_text)
|
72
|
+
|
73
|
+
def display_essential_info(self):
|
74
|
+
"""Display essential startup info (SHORT mode)."""
|
75
|
+
version = self.get_version()
|
76
|
+
panel_style, env_emoji, env_color = self.get_environment_style()
|
77
|
+
|
78
|
+
# Create compact header
|
79
|
+
header_text = Text()
|
80
|
+
header_text.append(f"{env_emoji} Django CFG ", style="bold")
|
81
|
+
header_text.append(f"v{version}", style="cyan")
|
82
|
+
header_text.append(" • ", style="dim")
|
83
|
+
header_text.append(f"{self.config.env_mode}", style=env_color)
|
84
|
+
header_text.append(" • ", style="dim")
|
85
|
+
header_text.append(f"{self.config.project_name}", style="white")
|
86
|
+
|
87
|
+
header_panel = self.create_panel(
|
88
|
+
header_text,
|
89
|
+
title="",
|
90
|
+
border_style=panel_style,
|
91
|
+
width=None
|
92
|
+
)
|
93
|
+
header_panel.padding = (0, 1) # Override padding for header
|
94
|
+
self.console.print(header_panel)
|
95
|
+
|
96
|
+
# Check for updates first
|
97
|
+
self._display_update_notification_short()
|
98
|
+
|
99
|
+
# Create columns for essential info
|
100
|
+
self._display_essential_columns()
|
101
|
+
|
102
|
+
def display_complete_info(self):
|
103
|
+
"""Display complete startup info (FULL mode)."""
|
104
|
+
version = self.get_version()
|
105
|
+
panel_style, env_emoji, env_color = self.get_environment_style()
|
106
|
+
|
107
|
+
# Get library info
|
108
|
+
from django_cfg.config import (
|
109
|
+
LIB_NAME, LIB_SITE_URL, LIB_DOCS_URL, LIB_GITHUB_URL,
|
110
|
+
LIB_SUPPORT_URL, LIB_HEALTH_URL
|
111
|
+
)
|
112
|
+
|
113
|
+
# Create main info table
|
114
|
+
info_table = self.create_table()
|
115
|
+
info_table.add_column("Setting", style="cyan", width=30)
|
116
|
+
info_table.add_column("Value", style="white")
|
117
|
+
|
118
|
+
info_table.add_row("📦 Version", version)
|
119
|
+
info_table.add_row("🔗 Prefix", "/cfg/")
|
120
|
+
info_table.add_row("🌍 Environment", self.config.env_mode)
|
121
|
+
info_table.add_row("🔧 Debug", str(self.config.debug))
|
122
|
+
info_table.add_row("🏗️ Project", self.config.project_name)
|
123
|
+
|
124
|
+
# Add environment source
|
125
|
+
env_source = getattr(self.config, '_environment', 'default_fallback')
|
126
|
+
info_table.add_row("🔍 Env Source", env_source)
|
127
|
+
|
128
|
+
info_table.add_row("🌐 Site", LIB_SITE_URL)
|
129
|
+
info_table.add_row("📚 Docs", LIB_DOCS_URL)
|
130
|
+
info_table.add_row("🐙 GitHub", LIB_GITHUB_URL)
|
131
|
+
info_table.add_row("🆘 Support", LIB_SUPPORT_URL)
|
132
|
+
|
133
|
+
# Use full URL for health endpoint
|
134
|
+
health_url = f"{self.get_base_url()}/cfg/health/"
|
135
|
+
info_table.add_row("❤️ Health", health_url)
|
136
|
+
|
137
|
+
# Create main panel with full width
|
138
|
+
main_panel = self.create_full_width_panel(
|
139
|
+
info_table,
|
140
|
+
title=f"{env_emoji} Django CFG Configuration",
|
141
|
+
border_style=panel_style
|
142
|
+
)
|
143
|
+
|
144
|
+
self.console.print(main_panel)
|
145
|
+
|
146
|
+
# Check for updates
|
147
|
+
self._display_update_notification_full()
|
148
|
+
|
149
|
+
# Create columns for apps and endpoints
|
150
|
+
self._display_main_columns()
|
151
|
+
|
152
|
+
# App-specific configuration panels
|
153
|
+
self._display_config_panels()
|
154
|
+
|
155
|
+
# Revolution info
|
156
|
+
self._display_revolution_info()
|
157
|
+
|
158
|
+
# Management commands
|
159
|
+
self._display_commands_info()
|
160
|
+
|
161
|
+
self.print_spacing()
|
162
|
+
|
163
|
+
def _display_update_notification_short(self):
|
164
|
+
"""Display update notification for SHORT mode."""
|
165
|
+
try:
|
166
|
+
from ..version_checker import get_version_info
|
167
|
+
version_info = get_version_info()
|
168
|
+
|
169
|
+
if version_info.get('update_available'):
|
170
|
+
current = version_info.get('current_version', 'unknown')
|
171
|
+
latest = version_info.get('latest_version', 'unknown')
|
172
|
+
|
173
|
+
update_text = Text()
|
174
|
+
update_text.append("🚨 Update available: ", style="bold yellow")
|
175
|
+
update_text.append(f"{current}", style="red")
|
176
|
+
update_text.append(" → ", style="dim")
|
177
|
+
update_text.append(f"{latest}", style="green")
|
178
|
+
update_text.append("\n💡 Run: ", style="dim")
|
179
|
+
update_text.append("poetry add django-cfg@latest", style="bright_blue")
|
180
|
+
|
181
|
+
update_panel = self.create_panel(
|
182
|
+
update_text,
|
183
|
+
title="",
|
184
|
+
border_style="yellow",
|
185
|
+
width=None
|
186
|
+
)
|
187
|
+
update_panel.padding = (0, 2) # Override padding
|
188
|
+
self.console.print(update_panel)
|
189
|
+
except Exception:
|
190
|
+
pass
|
191
|
+
|
192
|
+
def _display_update_notification_full(self):
|
193
|
+
"""Display update notification for FULL mode."""
|
194
|
+
try:
|
195
|
+
from ..version_checker import get_version_info
|
196
|
+
version_info = get_version_info()
|
197
|
+
|
198
|
+
if version_info.get('update_available'):
|
199
|
+
update_table = self.create_table()
|
200
|
+
update_table.add_column("Info", style="yellow", width=15)
|
201
|
+
update_table.add_column("Value", style="white")
|
202
|
+
|
203
|
+
current = version_info.get('current_version', 'unknown')
|
204
|
+
latest = version_info.get('latest_version', 'unknown')
|
205
|
+
update_url = version_info.get('update_url', '')
|
206
|
+
|
207
|
+
update_table.add_row("Current", f"[red]{current}[/red]")
|
208
|
+
update_table.add_row("Latest", f"[green]{latest}[/green]")
|
209
|
+
update_table.add_row("💡 Update", "[bright_blue]poetry add django-cfg@latest[/bright_blue]")
|
210
|
+
if update_url:
|
211
|
+
update_table.add_row("PyPI", update_url)
|
212
|
+
|
213
|
+
update_panel = self.create_full_width_panel(
|
214
|
+
update_table,
|
215
|
+
title="🚨 Update Available",
|
216
|
+
border_style="yellow"
|
217
|
+
)
|
218
|
+
|
219
|
+
self.console.print(update_panel)
|
220
|
+
except Exception:
|
221
|
+
pass
|
222
|
+
|
223
|
+
def _display_essential_columns(self):
|
224
|
+
"""Display essential info in columns for SHORT mode."""
|
225
|
+
# Enabled apps
|
226
|
+
enabled_apps = self.config.get_enabled_apps() or []
|
227
|
+
apps_table = self.create_table()
|
228
|
+
apps_table.add_column("App", style="bright_blue")
|
229
|
+
|
230
|
+
for app in enabled_apps[:5]: # Limit for SHORT mode
|
231
|
+
app_name = app.split('.')[-1]
|
232
|
+
apps_table.add_row(f"• {app_name}")
|
233
|
+
|
234
|
+
# Key endpoints
|
235
|
+
endpoints_table = self.create_table()
|
236
|
+
endpoints_table.add_column("Endpoint", style="bright_green")
|
237
|
+
|
238
|
+
endpoints_table.add_row(f"• {self.get_base_url('cfg', 'health')}")
|
239
|
+
endpoints_table.add_row(f"• {self.get_base_url('api', 'payments')}")
|
240
|
+
|
241
|
+
# Use new two-column table method for perfect 50/50 layout
|
242
|
+
self.print_two_column_table(
|
243
|
+
left_content=apps_table,
|
244
|
+
right_content=endpoints_table,
|
245
|
+
left_title="📱 Enabled Apps",
|
246
|
+
right_title="🔗 Key Endpoints",
|
247
|
+
left_style="blue",
|
248
|
+
right_style="green"
|
249
|
+
)
|
250
|
+
|
251
|
+
def _display_main_columns(self):
|
252
|
+
"""Display main columns (apps and endpoints) for FULL mode."""
|
253
|
+
# Enabled apps
|
254
|
+
enabled_apps = self.config.get_enabled_apps() or []
|
255
|
+
apps_table = self.create_table()
|
256
|
+
apps_table.add_column("App", style="bright_blue")
|
257
|
+
|
258
|
+
for app in enabled_apps:
|
259
|
+
app_name = app.split('.')[-1]
|
260
|
+
apps_table.add_row(f"• {app_name}")
|
261
|
+
|
262
|
+
# Endpoints
|
263
|
+
endpoints_table = self.create_table()
|
264
|
+
endpoints_table.add_column("Endpoint", style="bright_green")
|
265
|
+
|
266
|
+
# Add core endpoints
|
267
|
+
endpoints_table.add_row(f"• {self.get_base_url('cfg', 'health')}")
|
268
|
+
endpoints_table.add_row(f"• {self.get_base_url('cfg', 'commands')}")
|
269
|
+
|
270
|
+
# Add app-specific API endpoints based on enabled apps
|
271
|
+
for app in enabled_apps:
|
272
|
+
app_name = app.split('.')[-1]
|
273
|
+
if app_name in ['health', 'commands']:
|
274
|
+
continue
|
275
|
+
else:
|
276
|
+
endpoints_table.add_row(f"• {self.get_base_url('api', app_name)}")
|
277
|
+
|
278
|
+
# Use new two-column table method for perfect 50/50 layout
|
279
|
+
self.print_two_column_table(
|
280
|
+
left_content=apps_table,
|
281
|
+
right_content=endpoints_table,
|
282
|
+
left_title="📱 Enabled Apps",
|
283
|
+
right_title="🔗 Endpoints",
|
284
|
+
left_style="blue",
|
285
|
+
right_style="green"
|
286
|
+
)
|
287
|
+
|
288
|
+
def _display_config_panels(self):
|
289
|
+
"""Display app-specific configuration panels."""
|
290
|
+
config_panels = []
|
291
|
+
|
292
|
+
# Payments configuration
|
293
|
+
if (self.config and hasattr(self.config, 'payments') and
|
294
|
+
self.config.payments and self.config.payments.enabled):
|
295
|
+
|
296
|
+
payment_table = self.create_table()
|
297
|
+
payment_table.add_column("Setting", style="cyan", width=20)
|
298
|
+
payment_table.add_column("Value", style="white")
|
299
|
+
|
300
|
+
payment_table.add_row("Enabled", f"[green]{self.config.payments.enabled}[/green]")
|
301
|
+
middleware_enabled = self.config.payments.middleware_enabled
|
302
|
+
color = 'green' if middleware_enabled else 'red'
|
303
|
+
payment_table.add_row("Middleware", f"[{color}]{middleware_enabled}[/{color}]")
|
304
|
+
|
305
|
+
config_panels.append(self.create_panel(
|
306
|
+
payment_table,
|
307
|
+
title="💳 Payments",
|
308
|
+
border_style="yellow"
|
309
|
+
))
|
310
|
+
|
311
|
+
# Tasks configuration - removed from config_panels, will be shown separately
|
312
|
+
|
313
|
+
# Constance configuration
|
314
|
+
try:
|
315
|
+
constance_table = self.create_table()
|
316
|
+
constance_table.add_column("Setting", style="cyan", width=20)
|
317
|
+
constance_table.add_column("Value", style="white")
|
318
|
+
|
319
|
+
# Constance fields moved to separate block
|
320
|
+
# Get cache info
|
321
|
+
try:
|
322
|
+
cache_config = getattr(self.config, 'cache', None)
|
323
|
+
if cache_config:
|
324
|
+
constance_table.add_row("Cache", f"[green]{cache_config.backend}[/green]")
|
325
|
+
else:
|
326
|
+
constance_table.add_row("Cache", "[yellow]Not configured[/yellow]")
|
327
|
+
except Exception:
|
328
|
+
constance_table.add_row("Cache", "[red]Error[/red]")
|
329
|
+
|
330
|
+
# Add validation info
|
331
|
+
try:
|
332
|
+
from django_cfg.core.validation import ConfigurationValidator
|
333
|
+
validation_errors = ConfigurationValidator.validate(self.config)
|
334
|
+
error_count = len(validation_errors)
|
335
|
+
if error_count == 0:
|
336
|
+
constance_table.add_row("Validation", "[green]✓ Valid[/green]")
|
337
|
+
else:
|
338
|
+
constance_table.add_row("Validation", f"[red]✗ {error_count} errors[/red]")
|
339
|
+
except Exception:
|
340
|
+
constance_table.add_row("Validation", "[red]Error[/red]")
|
341
|
+
|
342
|
+
# Add installed apps count
|
343
|
+
try:
|
344
|
+
installed_apps = self.config.get_installed_apps() if hasattr(self.config, 'get_installed_apps') else []
|
345
|
+
constance_table.add_row("Apps", f"[blue]{len(installed_apps)}[/blue]")
|
346
|
+
except Exception:
|
347
|
+
constance_table.add_row("Apps", "[red]Error[/red]")
|
348
|
+
|
349
|
+
config_panels.append(self.create_panel(
|
350
|
+
constance_table,
|
351
|
+
title="⚙️ Configuration",
|
352
|
+
border_style="cyan"
|
353
|
+
))
|
354
|
+
except Exception:
|
355
|
+
pass
|
356
|
+
|
357
|
+
# Show config panels
|
358
|
+
if len(config_panels) >= 2:
|
359
|
+
# Show first two panels in 50/50 layout
|
360
|
+
self.print_two_column_table(
|
361
|
+
left_content=config_panels[0].renderable,
|
362
|
+
right_content=config_panels[1].renderable,
|
363
|
+
left_title=config_panels[0].title,
|
364
|
+
right_title=config_panels[1].title,
|
365
|
+
left_style=config_panels[0].border_style,
|
366
|
+
right_style=config_panels[1].border_style
|
367
|
+
)
|
368
|
+
|
369
|
+
# Show remaining panels individually
|
370
|
+
for panel in config_panels[2:]:
|
371
|
+
self.console.print(panel)
|
372
|
+
elif config_panels:
|
373
|
+
# Show single panel
|
374
|
+
for panel in config_panels:
|
375
|
+
self.console.print(panel)
|
376
|
+
|
377
|
+
# Show Background Tasks separately
|
378
|
+
self._display_background_tasks()
|
379
|
+
|
380
|
+
# Show detailed Constance information (includes summary)
|
381
|
+
self._display_constance_details()
|
382
|
+
|
383
|
+
def _display_background_tasks(self):
|
384
|
+
"""Display Background Tasks information in a separate panel."""
|
385
|
+
try:
|
386
|
+
# Always show Background Tasks section if config exists
|
387
|
+
if not self.config:
|
388
|
+
return
|
389
|
+
|
390
|
+
task_table = self.create_table()
|
391
|
+
task_table.add_column("Setting", style="cyan", width=20)
|
392
|
+
task_table.add_column("Value", style="white")
|
393
|
+
|
394
|
+
# Show real tasks status
|
395
|
+
tasks_enabled = self.config.should_enable_tasks()
|
396
|
+
if tasks_enabled:
|
397
|
+
task_table.add_row("Tasks Enabled", "[green]True[/green]")
|
398
|
+
else:
|
399
|
+
task_table.add_row("Tasks Enabled", "[yellow]False[/yellow]")
|
400
|
+
|
401
|
+
if hasattr(self.config, 'tasks') and self.config.tasks:
|
402
|
+
queue_name = getattr(self.config.tasks, 'queue_name', 'default')
|
403
|
+
task_table.add_row("Queue", f"[yellow]{queue_name}[/yellow]")
|
404
|
+
else:
|
405
|
+
task_table.add_row("Queue", "[yellow]default[/yellow]")
|
406
|
+
|
407
|
+
# Add worker command
|
408
|
+
task_table.add_row("Start Workers", "[bright_blue]poetry run python manage.py rundramatiq[/bright_blue]")
|
409
|
+
|
410
|
+
task_panel = self.create_full_width_panel(
|
411
|
+
task_table,
|
412
|
+
title="⚡ Background Tasks",
|
413
|
+
border_style="purple"
|
414
|
+
)
|
415
|
+
|
416
|
+
self.console.print(task_panel)
|
417
|
+
|
418
|
+
except Exception as e:
|
419
|
+
import traceback
|
420
|
+
print(f"❌ ERROR in _display_background_tasks: {e}")
|
421
|
+
traceback.print_exc()
|
422
|
+
|
423
|
+
def _display_constance_integrated_block(self, constance_config, all_fields):
|
424
|
+
"""Display integrated Constance block with summary and field details."""
|
425
|
+
try:
|
426
|
+
# Create main content table that will contain everything
|
427
|
+
main_content = Table(show_header=False, box=None, padding=(0, 1))
|
428
|
+
main_content.add_column("Content", justify="left")
|
429
|
+
|
430
|
+
# 1. Add summary section
|
431
|
+
summary_table = self.create_table()
|
432
|
+
summary_table.add_column("Source", style="cyan", width=20)
|
433
|
+
summary_table.add_column("Fields", style="white")
|
434
|
+
|
435
|
+
# Count fields by source
|
436
|
+
user_fields = len(constance_config.fields)
|
437
|
+
|
438
|
+
# Count by app
|
439
|
+
tasks_count = 0
|
440
|
+
knowbase_count = 0
|
441
|
+
payments_count = 0
|
442
|
+
|
443
|
+
config = self.config
|
444
|
+
if config and config.should_enable_tasks():
|
445
|
+
try:
|
446
|
+
from django_cfg.modules.django_tasks import extend_constance_config_with_tasks
|
447
|
+
tasks_fields = extend_constance_config_with_tasks()
|
448
|
+
tasks_count = len(tasks_fields)
|
449
|
+
except:
|
450
|
+
pass
|
451
|
+
|
452
|
+
if config and config.enable_knowbase:
|
453
|
+
try:
|
454
|
+
from django_cfg.apps.knowbase.config import get_django_cfg_knowbase_constance_fields
|
455
|
+
knowbase_fields = get_django_cfg_knowbase_constance_fields()
|
456
|
+
knowbase_count = len(knowbase_fields)
|
457
|
+
except:
|
458
|
+
pass
|
459
|
+
|
460
|
+
if config and config.payments and config.payments.enabled:
|
461
|
+
try:
|
462
|
+
from django_cfg.apps.payments.config import get_django_cfg_payments_constance_fields
|
463
|
+
payments_fields = get_django_cfg_payments_constance_fields()
|
464
|
+
payments_count = len(payments_fields)
|
465
|
+
except:
|
466
|
+
pass
|
467
|
+
|
468
|
+
summary_table.add_row("User Defined", f"[blue]{user_fields}[/blue]")
|
469
|
+
if tasks_count > 0:
|
470
|
+
summary_table.add_row("Tasks Module", f"[green]{tasks_count}[/green]")
|
471
|
+
if knowbase_count > 0:
|
472
|
+
summary_table.add_row("Knowbase App", f"[green]{knowbase_count}[/green]")
|
473
|
+
if payments_count > 0:
|
474
|
+
summary_table.add_row("Payments App", f"[green]{payments_count}[/green]")
|
475
|
+
summary_table.add_row("Total", f"[yellow]{len(all_fields)}[/yellow]")
|
476
|
+
|
477
|
+
main_content.add_row(summary_table)
|
478
|
+
main_content.add_row("") # Spacer
|
479
|
+
|
480
|
+
# 2. Add field details section
|
481
|
+
groups = {}
|
482
|
+
for field in all_fields:
|
483
|
+
group = field.group
|
484
|
+
if group not in groups:
|
485
|
+
groups[group] = []
|
486
|
+
groups[group].append(field)
|
487
|
+
|
488
|
+
group_names = list(groups.keys())[:2]
|
489
|
+
|
490
|
+
if len(group_names) >= 2:
|
491
|
+
# Create two-column layout for field details
|
492
|
+
details_table = Table(show_header=False, box=None, padding=(0, 2))
|
493
|
+
details_table.add_column("Left", justify="left")
|
494
|
+
details_table.add_column("Right", justify="left")
|
495
|
+
|
496
|
+
# Left column - first group
|
497
|
+
left_table = self.create_table()
|
498
|
+
left_table.add_column("Field", style="bright_cyan")
|
499
|
+
left_table.add_column("Type", style="yellow")
|
500
|
+
for field in groups[group_names[0]][:8]:
|
501
|
+
left_table.add_row(field.name, field.field_type)
|
502
|
+
|
503
|
+
# Right column - second group
|
504
|
+
right_table = self.create_table()
|
505
|
+
right_table.add_column("Field", style="bright_cyan")
|
506
|
+
right_table.add_column("Type", style="yellow")
|
507
|
+
for field in groups[group_names[1]][:8]:
|
508
|
+
right_table.add_row(field.name, field.field_type)
|
509
|
+
|
510
|
+
# Create panels for each group
|
511
|
+
left_panel = Panel(
|
512
|
+
left_table,
|
513
|
+
title=f"🔧 {group_names[0]} Settings",
|
514
|
+
border_style="cyan",
|
515
|
+
expand=True,
|
516
|
+
padding=(1, 1)
|
517
|
+
)
|
518
|
+
|
519
|
+
right_panel = Panel(
|
520
|
+
right_table,
|
521
|
+
title=f"🔧 {group_names[1]} Settings",
|
522
|
+
border_style="blue",
|
523
|
+
expand=True,
|
524
|
+
padding=(1, 1)
|
525
|
+
)
|
526
|
+
|
527
|
+
details_table.add_row(left_panel, right_panel)
|
528
|
+
main_content.add_row(details_table)
|
529
|
+
|
530
|
+
elif len(group_names) == 1:
|
531
|
+
# Single group
|
532
|
+
single_table = self.create_table()
|
533
|
+
single_table.add_column("Field", style="bright_cyan")
|
534
|
+
single_table.add_column("Type", style="yellow")
|
535
|
+
single_table.add_column("Default", style="white")
|
536
|
+
|
537
|
+
for field in groups[group_names[0]][:10]:
|
538
|
+
default_str = str(field.default)[:20] + "..." if len(str(field.default)) > 20 else str(field.default)
|
539
|
+
single_table.add_row(field.name, field.field_type, default_str)
|
540
|
+
|
541
|
+
single_panel = Panel(
|
542
|
+
single_table,
|
543
|
+
title=f"🔧 {group_names[0]} Settings",
|
544
|
+
border_style="cyan",
|
545
|
+
expand=True,
|
546
|
+
padding=(1, 1)
|
547
|
+
)
|
548
|
+
main_content.add_row(single_panel)
|
549
|
+
|
550
|
+
# Create the main panel containing everything
|
551
|
+
integrated_panel = self.create_full_width_panel(
|
552
|
+
main_content,
|
553
|
+
title="📊 Constance Fields Summary",
|
554
|
+
border_style="purple"
|
555
|
+
)
|
556
|
+
|
557
|
+
self.console.print(integrated_panel)
|
558
|
+
|
559
|
+
except Exception as e:
|
560
|
+
import traceback
|
561
|
+
print(f"❌ ERROR in _display_constance_integrated_block: {e}")
|
562
|
+
traceback.print_exc()
|
563
|
+
|
564
|
+
def _display_constance_details(self):
|
565
|
+
"""Display detailed Constance configuration information."""
|
566
|
+
try:
|
567
|
+
if not (self.config and hasattr(self.config, 'constance')):
|
568
|
+
return
|
569
|
+
|
570
|
+
constance_config = self.config.constance
|
571
|
+
all_fields = constance_config.get_all_fields()
|
572
|
+
|
573
|
+
if not all_fields:
|
574
|
+
return
|
575
|
+
|
576
|
+
# Show integrated summary and details in one block
|
577
|
+
self._display_constance_integrated_block(constance_config, all_fields)
|
578
|
+
|
579
|
+
except Exception as e:
|
580
|
+
import traceback
|
581
|
+
print(f"❌ ERROR in _display_constance_details: {e}")
|
582
|
+
traceback.print_exc()
|
583
|
+
|
584
|
+
def _display_constance_summary(self, constance_config, all_fields):
|
585
|
+
"""Display summary of Constance fields by source."""
|
586
|
+
try:
|
587
|
+
# Count fields by source
|
588
|
+
user_fields = len(constance_config.fields) # User-defined fields
|
589
|
+
app_fields = constance_config._get_app_constance_fields()
|
590
|
+
|
591
|
+
# Count by app
|
592
|
+
tasks_count = 0
|
593
|
+
knowbase_count = 0
|
594
|
+
payments_count = 0
|
595
|
+
|
596
|
+
# Try to get individual app field counts
|
597
|
+
config = self.config
|
598
|
+
if config and config.should_enable_tasks():
|
599
|
+
try:
|
600
|
+
from django_cfg.modules.django_tasks import extend_constance_config_with_tasks
|
601
|
+
tasks_fields = extend_constance_config_with_tasks()
|
602
|
+
tasks_count = len(tasks_fields)
|
603
|
+
except:
|
604
|
+
pass
|
605
|
+
|
606
|
+
if config and config.enable_knowbase:
|
607
|
+
try:
|
608
|
+
from django_cfg.apps.knowbase.config import get_django_cfg_knowbase_constance_fields
|
609
|
+
knowbase_fields = get_django_cfg_knowbase_constance_fields()
|
610
|
+
knowbase_count = len(knowbase_fields)
|
611
|
+
except:
|
612
|
+
pass
|
613
|
+
|
614
|
+
if config and config.payments and config.payments.enabled:
|
615
|
+
try:
|
616
|
+
from django_cfg.apps.payments.config import get_django_cfg_payments_constance_fields
|
617
|
+
payments_fields = get_django_cfg_payments_constance_fields()
|
618
|
+
payments_count = len(payments_fields)
|
619
|
+
except:
|
620
|
+
pass
|
621
|
+
|
622
|
+
# Create summary table
|
623
|
+
summary_table = self.create_table()
|
624
|
+
summary_table.add_column("Source", style="cyan", width=20)
|
625
|
+
summary_table.add_column("Fields", style="white")
|
626
|
+
|
627
|
+
summary_table.add_row("User Defined", f"[blue]{user_fields}[/blue]")
|
628
|
+
|
629
|
+
if tasks_count > 0:
|
630
|
+
summary_table.add_row("Tasks Module", f"[green]{tasks_count}[/green]")
|
631
|
+
if knowbase_count > 0:
|
632
|
+
summary_table.add_row("Knowbase App", f"[green]{knowbase_count}[/green]")
|
633
|
+
if payments_count > 0:
|
634
|
+
summary_table.add_row("Payments App", f"[green]{payments_count}[/green]")
|
635
|
+
|
636
|
+
summary_table.add_row("Total", f"[yellow]{len(all_fields)}[/yellow]")
|
637
|
+
|
638
|
+
summary_panel = self.create_panel(
|
639
|
+
summary_table,
|
640
|
+
title="📊 Constance Fields Summary",
|
641
|
+
border_style="purple"
|
642
|
+
)
|
643
|
+
|
644
|
+
self.console.print(summary_panel)
|
645
|
+
|
646
|
+
except Exception as e:
|
647
|
+
import traceback
|
648
|
+
print(f"❌ ERROR in _display_constance_summary: {e}")
|
649
|
+
traceback.print_exc()
|
650
|
+
|
651
|
+
def _display_revolution_info(self):
|
652
|
+
"""Display Django Revolution information."""
|
653
|
+
try:
|
654
|
+
from django_revolution import get_revolution_info
|
655
|
+
revolution_info = get_revolution_info()
|
656
|
+
|
657
|
+
revolution_table = self.create_table()
|
658
|
+
revolution_table.add_column("Setting", style="cyan", width=30)
|
659
|
+
revolution_table.add_column("Value", style="white")
|
660
|
+
|
661
|
+
revolution_table.add_row("📦 Version", revolution_info.get('version', 'unknown'))
|
662
|
+
revolution_table.add_row("📊 Zones", str(revolution_info.get('zones_count', 0)))
|
663
|
+
revolution_table.add_row("📱 Apps", str(revolution_info.get('apps_count', 0)))
|
664
|
+
revolution_table.add_row("🔗 API Prefix", revolution_info.get('api_prefix', '/api/'))
|
665
|
+
|
666
|
+
revolution_panel = self.create_panel(
|
667
|
+
revolution_table,
|
668
|
+
title="🚀 Django Revolution",
|
669
|
+
border_style="blue"
|
670
|
+
)
|
671
|
+
|
672
|
+
self.console.print(revolution_panel)
|
673
|
+
except ImportError:
|
674
|
+
# Django Revolution not available
|
675
|
+
pass
|
676
|
+
except Exception:
|
677
|
+
pass
|
678
|
+
|
679
|
+
def _display_commands_info(self):
|
680
|
+
"""Display management commands information."""
|
681
|
+
try:
|
682
|
+
from ..commands_collector import get_all_commands, get_commands_with_descriptions
|
683
|
+
|
684
|
+
# Get command counts
|
685
|
+
all_commands = get_all_commands()
|
686
|
+
core_count = sum(len(commands) for commands in all_commands.get('django_cfg_core', {}).values())
|
687
|
+
app_count = sum(len(commands) for commands in all_commands.get('django_cfg_apps', {}).values())
|
688
|
+
project_count = sum(len(commands) for commands in all_commands.get('project_commands', {}).values())
|
689
|
+
total_count = core_count + app_count + project_count
|
690
|
+
|
691
|
+
# Main commands info
|
692
|
+
commands_table = self.create_table()
|
693
|
+
commands_table.add_column("Type", style="cyan", width=20)
|
694
|
+
commands_table.add_column("Count", style="white")
|
695
|
+
|
696
|
+
commands_table.add_row("🔧 Core Commands", str(core_count))
|
697
|
+
commands_table.add_row("📱 App Commands", str(app_count))
|
698
|
+
commands_table.add_row("🏗️ Project Commands", str(project_count))
|
699
|
+
commands_table.add_row("📊 Total", str(total_count))
|
700
|
+
|
701
|
+
commands_panel = self.create_full_width_panel(
|
702
|
+
commands_table,
|
703
|
+
title="⚡ Management Commands",
|
704
|
+
border_style="purple"
|
705
|
+
)
|
706
|
+
|
707
|
+
self.console.print(commands_panel)
|
708
|
+
|
709
|
+
# Detailed commands breakdown
|
710
|
+
self._display_commands_breakdown()
|
711
|
+
|
712
|
+
except Exception as e:
|
713
|
+
import traceback
|
714
|
+
print(f"❌ ERROR in _display_commands_info: {e}")
|
715
|
+
traceback.print_exc()
|
716
|
+
|
717
|
+
def _display_commands_breakdown(self):
|
718
|
+
"""Display detailed commands breakdown."""
|
719
|
+
try:
|
720
|
+
from ..commands_collector import get_all_commands
|
721
|
+
all_commands = get_all_commands()
|
722
|
+
|
723
|
+
columns_content = []
|
724
|
+
|
725
|
+
# Core commands
|
726
|
+
core_commands_dict = all_commands.get('django_cfg_core', {})
|
727
|
+
if core_commands_dict:
|
728
|
+
core_table = self.create_table()
|
729
|
+
core_table.add_column("Command", style="bright_blue")
|
730
|
+
|
731
|
+
# Flatten all core commands
|
732
|
+
all_core_commands = []
|
733
|
+
for commands_list in core_commands_dict.values():
|
734
|
+
all_core_commands.extend(commands_list)
|
735
|
+
|
736
|
+
for cmd in all_core_commands[:15]: # Limit to first 15
|
737
|
+
core_table.add_row(f"• {cmd}")
|
738
|
+
|
739
|
+
columns_content.append(self.create_panel(
|
740
|
+
core_table,
|
741
|
+
title="🔧 Core Commands",
|
742
|
+
border_style="blue"
|
743
|
+
))
|
744
|
+
|
745
|
+
# App commands
|
746
|
+
app_commands_dict = all_commands.get('django_cfg_apps', {})
|
747
|
+
if app_commands_dict:
|
748
|
+
app_table = self.create_table()
|
749
|
+
app_table.add_column("Command", style="bright_green")
|
750
|
+
|
751
|
+
for app_name, commands_list in app_commands_dict.items():
|
752
|
+
if commands_list:
|
753
|
+
app_table.add_row(f"[bold]{app_name.title()}:[/bold]")
|
754
|
+
for cmd in commands_list[:3]: # Limit per app
|
755
|
+
app_table.add_row(f" • {cmd}")
|
756
|
+
|
757
|
+
columns_content.append(self.create_panel(
|
758
|
+
app_table,
|
759
|
+
title="📱 App Commands",
|
760
|
+
border_style="green"
|
761
|
+
))
|
762
|
+
|
763
|
+
# Show command columns in 50/50 layout
|
764
|
+
if len(columns_content) == 2:
|
765
|
+
self.print_two_column_table(
|
766
|
+
left_content=columns_content[0].renderable,
|
767
|
+
right_content=columns_content[1].renderable,
|
768
|
+
left_title="🔧 Core Commands",
|
769
|
+
right_title="📱 App Commands",
|
770
|
+
left_style="blue",
|
771
|
+
right_style="green"
|
772
|
+
)
|
773
|
+
elif len(columns_content) == 1:
|
774
|
+
# Single column - show as panel
|
775
|
+
self.console.print(columns_content[0])
|
776
|
+
elif columns_content:
|
777
|
+
# Fallback for other cases
|
778
|
+
self.print_columns(columns_content, equal=True, expand=True)
|
779
|
+
|
780
|
+
# Project commands (separate panel due to length)
|
781
|
+
project_commands_dict = all_commands.get('project_commands', {})
|
782
|
+
if project_commands_dict:
|
783
|
+
# Flatten all project commands
|
784
|
+
all_project_commands = []
|
785
|
+
for commands_list in project_commands_dict.values():
|
786
|
+
all_project_commands.extend(commands_list)
|
787
|
+
|
788
|
+
# Split commands into two columns
|
789
|
+
mid_point = len(all_project_commands) // 2
|
790
|
+
left_commands = all_project_commands[:mid_point]
|
791
|
+
right_commands = all_project_commands[mid_point:]
|
792
|
+
|
793
|
+
# Create two-column table inside one panel
|
794
|
+
project_columns_table = Table(show_header=False, box=None, padding=(0, 2))
|
795
|
+
project_columns_table.add_column("Left", justify="left")
|
796
|
+
project_columns_table.add_column("Right", justify="left")
|
797
|
+
|
798
|
+
# Create content for each column
|
799
|
+
left_content = "\n".join([f"• {cmd}" for cmd in left_commands[:15]]) # Limit to 15 per column
|
800
|
+
right_content = "\n".join([f"• {cmd}" for cmd in right_commands[:15]])
|
801
|
+
|
802
|
+
project_columns_table.add_row(left_content, right_content)
|
803
|
+
|
804
|
+
project_panel = self.create_full_width_panel(
|
805
|
+
project_columns_table,
|
806
|
+
title="🏗️ Project Commands",
|
807
|
+
border_style="yellow"
|
808
|
+
)
|
809
|
+
|
810
|
+
self.console.print(project_panel)
|
811
|
+
|
812
|
+
except Exception as e:
|
813
|
+
import traceback
|
814
|
+
print(f"❌ ERROR in _display_commands_breakdown: {e}")
|
815
|
+
traceback.print_exc()
|