django-cfg 1.3.9__py3-none-any.whl → 1.3.13__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- django_cfg/__init__.py +1 -1
- django_cfg/apps/accounts/admin/inlines.py +11 -5
- django_cfg/apps/payments/admin/networks_admin.py +12 -1
- django_cfg/apps/payments/admin/payments_admin.py +13 -0
- django_cfg/apps/payments/admin_interface/serializers/payment_serializers.py +62 -14
- django_cfg/apps/payments/admin_interface/templates/payments/components/payment_card.html +121 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/payment_qr_code.html +95 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/progress_bar.html +37 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/provider_stats.html +60 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/status_badge.html +41 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/status_overview.html +83 -0
- django_cfg/apps/payments/admin_interface/templates/payments/payment_detail.html +363 -0
- django_cfg/apps/payments/admin_interface/templates/payments/payment_form.html +33 -3
- django_cfg/apps/payments/admin_interface/views/api/payments.py +102 -0
- django_cfg/apps/payments/admin_interface/views/api/webhook_admin.py +96 -45
- django_cfg/apps/payments/admin_interface/views/forms.py +5 -1
- django_cfg/apps/payments/config/__init__.py +14 -15
- django_cfg/apps/payments/config/django_cfg_integration.py +59 -1
- django_cfg/apps/payments/config/helpers.py +8 -13
- django_cfg/apps/payments/migrations/0001_initial.py +33 -46
- django_cfg/apps/payments/migrations/0002_rename_payments_un_user_id_7f6e79_idx_payments_un_user_id_8ce187_idx_and_more.py +46 -0
- django_cfg/apps/payments/migrations/0003_universalpayment_status_changed_at.py +25 -0
- django_cfg/apps/payments/models/managers/payment_managers.py +142 -25
- django_cfg/apps/payments/models/payments.py +94 -0
- django_cfg/apps/payments/services/core/base.py +4 -4
- django_cfg/apps/payments/services/core/payment_service.py +265 -38
- django_cfg/apps/payments/services/providers/base.py +209 -3
- django_cfg/apps/payments/services/providers/models/__init__.py +2 -0
- django_cfg/apps/payments/services/providers/models/base.py +25 -2
- django_cfg/apps/payments/services/providers/nowpayments/models.py +2 -2
- django_cfg/apps/payments/services/providers/nowpayments/provider.py +57 -9
- django_cfg/apps/payments/services/providers/registry.py +5 -5
- django_cfg/apps/payments/services/types/requests.py +19 -7
- django_cfg/apps/payments/signals/payment_signals.py +31 -2
- django_cfg/apps/payments/static/payments/js/api-client.js +6 -1
- django_cfg/apps/payments/static/payments/js/payment-detail.js +167 -0
- django_cfg/apps/payments/static/payments/js/payment-form.js +35 -26
- django_cfg/apps/payments/templatetags/payment_tags.py +8 -0
- django_cfg/apps/payments/urls.py +3 -2
- django_cfg/apps/payments/views/api/currencies.py +3 -0
- django_cfg/apps/payments/views/serializers/currencies.py +18 -5
- django_cfg/apps/tasks/admin/tasks_admin.py +2 -2
- django_cfg/apps/tasks/static/tasks/css/dashboard.css +68 -217
- django_cfg/apps/tasks/static/tasks/js/api.js +40 -84
- django_cfg/apps/tasks/static/tasks/js/components/DataManager.js +24 -0
- django_cfg/apps/tasks/static/tasks/js/components/TabManager.js +85 -0
- django_cfg/apps/tasks/static/tasks/js/components/TaskRenderer.js +216 -0
- django_cfg/apps/tasks/static/tasks/js/dashboard/main.mjs +245 -0
- django_cfg/apps/tasks/static/tasks/js/dashboard/overview.mjs +123 -0
- django_cfg/apps/tasks/static/tasks/js/dashboard/queues.mjs +120 -0
- django_cfg/apps/tasks/static/tasks/js/dashboard/tasks.mjs +350 -0
- django_cfg/apps/tasks/static/tasks/js/dashboard/workers.mjs +169 -0
- django_cfg/apps/tasks/tasks/__init__.py +10 -0
- django_cfg/apps/tasks/tasks/demo_tasks.py +133 -0
- django_cfg/apps/tasks/templates/tasks/components/management_actions.html +42 -45
- django_cfg/apps/tasks/templates/tasks/components/{status_cards.html → overview_content.html} +30 -11
- django_cfg/apps/tasks/templates/tasks/components/queues_content.html +19 -0
- django_cfg/apps/tasks/templates/tasks/components/tab_navigation.html +16 -10
- django_cfg/apps/tasks/templates/tasks/components/tasks_content.html +51 -0
- django_cfg/apps/tasks/templates/tasks/components/workers_content.html +30 -0
- django_cfg/apps/tasks/templates/tasks/layout/base.html +117 -0
- django_cfg/apps/tasks/templates/tasks/pages/dashboard.html +82 -0
- django_cfg/apps/tasks/templates/tasks/partials/task_row_template.html +40 -0
- django_cfg/apps/tasks/templates/tasks/widgets/task_filters.html +37 -0
- django_cfg/apps/tasks/templates/tasks/widgets/task_footer.html +41 -0
- django_cfg/apps/tasks/templates/tasks/widgets/task_table.html +50 -0
- django_cfg/apps/tasks/urls.py +2 -2
- django_cfg/apps/tasks/urls_admin.py +2 -2
- django_cfg/apps/tasks/utils/__init__.py +1 -0
- django_cfg/apps/tasks/utils/simulator.py +356 -0
- django_cfg/apps/tasks/views/__init__.py +16 -0
- django_cfg/apps/tasks/views/api.py +569 -0
- django_cfg/apps/tasks/views/dashboard.py +58 -0
- django_cfg/core/integration/__init__.py +21 -0
- django_cfg/management/commands/rundramatiq_simulator.py +430 -0
- django_cfg/models/constance.py +0 -11
- django_cfg/models/payments.py +137 -3
- django_cfg/modules/django_tasks.py +54 -21
- django_cfg/registry/core.py +4 -9
- django_cfg/template_archive/django_sample.zip +0 -0
- {django_cfg-1.3.9.dist-info → django_cfg-1.3.13.dist-info}/METADATA +2 -2
- {django_cfg-1.3.9.dist-info → django_cfg-1.3.13.dist-info}/RECORD +85 -153
- django_cfg/apps/payments/config/constance/__init__.py +0 -22
- django_cfg/apps/payments/config/constance/config_service.py +0 -123
- django_cfg/apps/payments/config/constance/fields.py +0 -69
- django_cfg/apps/payments/config/constance/settings.py +0 -160
- django_cfg/apps/payments/migrations/0002_currency_usd_rate_currency_usd_rate_updated_at.py +0 -26
- django_cfg/apps/payments/migrations/0003_remove_provider_currency_fields.py +0 -28
- django_cfg/apps/payments/migrations/0004_add_reserved_usd_field.py +0 -30
- django_cfg/apps/tasks/static/tasks/js/dashboard.js +0 -614
- django_cfg/apps/tasks/static/tasks/js/modals.js +0 -452
- django_cfg/apps/tasks/static/tasks/js/notifications.js +0 -144
- django_cfg/apps/tasks/static/tasks/js/task-monitor.js +0 -454
- django_cfg/apps/tasks/static/tasks/js/theme.js +0 -77
- django_cfg/apps/tasks/templates/tasks/base.html +0 -96
- django_cfg/apps/tasks/templates/tasks/components/info_cards.html +0 -85
- django_cfg/apps/tasks/templates/tasks/components/overview_tab.html +0 -22
- django_cfg/apps/tasks/templates/tasks/components/queues_tab.html +0 -19
- django_cfg/apps/tasks/templates/tasks/components/task_details_modal.html +0 -103
- django_cfg/apps/tasks/templates/tasks/components/tasks_tab.html +0 -32
- django_cfg/apps/tasks/templates/tasks/components/workers_tab.html +0 -29
- django_cfg/apps/tasks/templates/tasks/dashboard.html +0 -29
- django_cfg/apps/tasks/views.py +0 -461
- django_cfg/management/commands/app_agent_diagnose.py +0 -470
- django_cfg/management/commands/app_agent_generate.py +0 -342
- django_cfg/management/commands/app_agent_info.py +0 -308
- django_cfg/management/commands/auto_generate.py +0 -486
- django_cfg/modules/django_app_agent/__init__.py +0 -87
- django_cfg/modules/django_app_agent/agents/__init__.py +0 -40
- django_cfg/modules/django_app_agent/agents/base/__init__.py +0 -24
- django_cfg/modules/django_app_agent/agents/base/agent.py +0 -354
- django_cfg/modules/django_app_agent/agents/base/context.py +0 -236
- django_cfg/modules/django_app_agent/agents/base/executor.py +0 -430
- django_cfg/modules/django_app_agent/agents/generation/__init__.py +0 -12
- django_cfg/modules/django_app_agent/agents/generation/app_generator/__init__.py +0 -15
- django_cfg/modules/django_app_agent/agents/generation/app_generator/config_validator.py +0 -147
- django_cfg/modules/django_app_agent/agents/generation/app_generator/main.py +0 -99
- django_cfg/modules/django_app_agent/agents/generation/app_generator/models.py +0 -32
- django_cfg/modules/django_app_agent/agents/generation/app_generator/prompt_manager.py +0 -290
- django_cfg/modules/django_app_agent/agents/interfaces.py +0 -376
- django_cfg/modules/django_app_agent/core/__init__.py +0 -33
- django_cfg/modules/django_app_agent/core/config.py +0 -300
- django_cfg/modules/django_app_agent/core/exceptions.py +0 -359
- django_cfg/modules/django_app_agent/models/__init__.py +0 -71
- django_cfg/modules/django_app_agent/models/base.py +0 -283
- django_cfg/modules/django_app_agent/models/context.py +0 -496
- django_cfg/modules/django_app_agent/models/enums.py +0 -481
- django_cfg/modules/django_app_agent/models/requests.py +0 -500
- django_cfg/modules/django_app_agent/models/responses.py +0 -585
- django_cfg/modules/django_app_agent/pytest.ini +0 -6
- django_cfg/modules/django_app_agent/services/__init__.py +0 -42
- django_cfg/modules/django_app_agent/services/app_generator/__init__.py +0 -30
- django_cfg/modules/django_app_agent/services/app_generator/ai_integration.py +0 -133
- django_cfg/modules/django_app_agent/services/app_generator/context.py +0 -40
- django_cfg/modules/django_app_agent/services/app_generator/main.py +0 -202
- django_cfg/modules/django_app_agent/services/app_generator/structure.py +0 -316
- django_cfg/modules/django_app_agent/services/app_generator/validation.py +0 -125
- django_cfg/modules/django_app_agent/services/base.py +0 -437
- django_cfg/modules/django_app_agent/services/context_builder/__init__.py +0 -34
- django_cfg/modules/django_app_agent/services/context_builder/code_extractor.py +0 -141
- django_cfg/modules/django_app_agent/services/context_builder/context_generator.py +0 -276
- django_cfg/modules/django_app_agent/services/context_builder/main.py +0 -272
- django_cfg/modules/django_app_agent/services/context_builder/models.py +0 -40
- django_cfg/modules/django_app_agent/services/context_builder/pattern_analyzer.py +0 -85
- django_cfg/modules/django_app_agent/services/project_scanner/__init__.py +0 -31
- django_cfg/modules/django_app_agent/services/project_scanner/app_discovery.py +0 -311
- django_cfg/modules/django_app_agent/services/project_scanner/main.py +0 -221
- django_cfg/modules/django_app_agent/services/project_scanner/models.py +0 -59
- django_cfg/modules/django_app_agent/services/project_scanner/pattern_detection.py +0 -94
- django_cfg/modules/django_app_agent/services/questioning_service/__init__.py +0 -28
- django_cfg/modules/django_app_agent/services/questioning_service/main.py +0 -273
- django_cfg/modules/django_app_agent/services/questioning_service/models.py +0 -111
- django_cfg/modules/django_app_agent/services/questioning_service/question_generator.py +0 -251
- django_cfg/modules/django_app_agent/services/questioning_service/response_processor.py +0 -347
- django_cfg/modules/django_app_agent/services/questioning_service/session_manager.py +0 -356
- django_cfg/modules/django_app_agent/services/report_service.py +0 -332
- django_cfg/modules/django_app_agent/services/template_manager/__init__.py +0 -18
- django_cfg/modules/django_app_agent/services/template_manager/jinja_engine.py +0 -236
- django_cfg/modules/django_app_agent/services/template_manager/main.py +0 -159
- django_cfg/modules/django_app_agent/services/template_manager/models.py +0 -36
- django_cfg/modules/django_app_agent/services/template_manager/template_loader.py +0 -100
- django_cfg/modules/django_app_agent/services/template_manager/templates/admin.py.j2 +0 -105
- django_cfg/modules/django_app_agent/services/template_manager/templates/apps.py.j2 +0 -31
- django_cfg/modules/django_app_agent/services/template_manager/templates/cfg_config.py.j2 +0 -44
- django_cfg/modules/django_app_agent/services/template_manager/templates/cfg_module.py.j2 +0 -81
- django_cfg/modules/django_app_agent/services/template_manager/templates/forms.py.j2 +0 -107
- django_cfg/modules/django_app_agent/services/template_manager/templates/models.py.j2 +0 -139
- django_cfg/modules/django_app_agent/services/template_manager/templates/serializers.py.j2 +0 -91
- django_cfg/modules/django_app_agent/services/template_manager/templates/tests.py.j2 +0 -195
- django_cfg/modules/django_app_agent/services/template_manager/templates/urls.py.j2 +0 -35
- django_cfg/modules/django_app_agent/services/template_manager/templates/views.py.j2 +0 -211
- django_cfg/modules/django_app_agent/services/template_manager/variable_processor.py +0 -200
- django_cfg/modules/django_app_agent/services/validation_service/__init__.py +0 -25
- django_cfg/modules/django_app_agent/services/validation_service/django_validator.py +0 -333
- django_cfg/modules/django_app_agent/services/validation_service/main.py +0 -242
- django_cfg/modules/django_app_agent/services/validation_service/models.py +0 -66
- django_cfg/modules/django_app_agent/services/validation_service/quality_validator.py +0 -352
- django_cfg/modules/django_app_agent/services/validation_service/security_validator.py +0 -272
- django_cfg/modules/django_app_agent/services/validation_service/syntax_validator.py +0 -203
- django_cfg/modules/django_app_agent/ui/__init__.py +0 -25
- django_cfg/modules/django_app_agent/ui/cli.py +0 -419
- django_cfg/modules/django_app_agent/ui/rich_components.py +0 -622
- django_cfg/modules/django_app_agent/utils/__init__.py +0 -38
- django_cfg/modules/django_app_agent/utils/logging.py +0 -360
- django_cfg/modules/django_app_agent/utils/validation.py +0 -417
- {django_cfg-1.3.9.dist-info → django_cfg-1.3.13.dist-info}/WHEEL +0 -0
- {django_cfg-1.3.9.dist-info → django_cfg-1.3.13.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.3.9.dist-info → django_cfg-1.3.13.dist-info}/licenses/LICENSE +0 -0
@@ -1,622 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Rich UI Components for Django App Agent Module.
|
3
|
-
|
4
|
-
This module provides beautiful terminal UI components using Rich library
|
5
|
-
for progress tracking, question interfaces, error display, and status updates.
|
6
|
-
"""
|
7
|
-
|
8
|
-
from typing import Dict, List, Optional, Any, Generator, ContextManager
|
9
|
-
from contextlib import contextmanager
|
10
|
-
from datetime import datetime, timedelta
|
11
|
-
import time
|
12
|
-
|
13
|
-
from rich.console import Console
|
14
|
-
from rich.panel import Panel
|
15
|
-
from rich.progress import (
|
16
|
-
Progress, SpinnerColumn, TextColumn, BarColumn,
|
17
|
-
TimeElapsedColumn, TimeRemainingColumn, MofNCompleteColumn
|
18
|
-
)
|
19
|
-
from rich.prompt import Prompt, Confirm, IntPrompt
|
20
|
-
from rich.syntax import Syntax
|
21
|
-
from rich.table import Table
|
22
|
-
from rich.tree import Tree
|
23
|
-
from rich.layout import Layout
|
24
|
-
from rich.live import Live
|
25
|
-
from rich.text import Text
|
26
|
-
from rich.align import Align
|
27
|
-
from rich.columns import Columns
|
28
|
-
from rich.status import Status
|
29
|
-
|
30
|
-
from ..models.requests import AppGenerationRequest
|
31
|
-
from ..models.responses import AppGenerationResult
|
32
|
-
from ..models.enums import AppType, AppComplexity, AppFeature
|
33
|
-
|
34
|
-
|
35
|
-
class RichTheme:
|
36
|
-
"""Consistent color theme for Rich UI components."""
|
37
|
-
|
38
|
-
PRIMARY = "bright_blue"
|
39
|
-
SECONDARY = "bright_green"
|
40
|
-
ACCENT = "bright_yellow"
|
41
|
-
SUCCESS = "bright_green"
|
42
|
-
WARNING = "bright_yellow"
|
43
|
-
ERROR = "bright_red"
|
44
|
-
INFO = "bright_cyan"
|
45
|
-
MUTED = "dim white"
|
46
|
-
CODE = "bright_magenta"
|
47
|
-
|
48
|
-
|
49
|
-
class RichProgressTracker:
|
50
|
-
"""Rich progress tracking for long-running operations."""
|
51
|
-
|
52
|
-
def __init__(self, console: Console):
|
53
|
-
"""Initialize progress tracker."""
|
54
|
-
self.console = console
|
55
|
-
self.theme = RichTheme()
|
56
|
-
|
57
|
-
@contextmanager
|
58
|
-
def track_generation(self, app_name: str) -> ContextManager['GenerationProgress']:
|
59
|
-
"""Track application generation progress."""
|
60
|
-
progress = GenerationProgress(self.console, app_name)
|
61
|
-
try:
|
62
|
-
yield progress
|
63
|
-
finally:
|
64
|
-
progress.complete()
|
65
|
-
|
66
|
-
@contextmanager
|
67
|
-
def track_scanning(self) -> ContextManager['ScanningProgress']:
|
68
|
-
"""Track project scanning progress."""
|
69
|
-
progress = ScanningProgress(self.console)
|
70
|
-
try:
|
71
|
-
yield progress
|
72
|
-
finally:
|
73
|
-
progress.complete()
|
74
|
-
|
75
|
-
|
76
|
-
class GenerationProgress:
|
77
|
-
"""Progress tracker for application generation."""
|
78
|
-
|
79
|
-
def __init__(self, console: Console, app_name: str):
|
80
|
-
"""Initialize generation progress."""
|
81
|
-
self.console = console
|
82
|
-
self.app_name = app_name
|
83
|
-
self.start_time = datetime.now()
|
84
|
-
|
85
|
-
# Create progress components
|
86
|
-
self.progress = Progress(
|
87
|
-
SpinnerColumn(),
|
88
|
-
TextColumn("[progress.description]{task.description}"),
|
89
|
-
BarColumn(),
|
90
|
-
MofNCompleteColumn(),
|
91
|
-
TimeElapsedColumn(),
|
92
|
-
TimeRemainingColumn(),
|
93
|
-
console=console,
|
94
|
-
transient=False
|
95
|
-
)
|
96
|
-
|
97
|
-
# Define generation phases
|
98
|
-
self.phases = [
|
99
|
-
"🔍 Analyzing project structure",
|
100
|
-
"🧠 Building development context",
|
101
|
-
"❓ Processing requirements",
|
102
|
-
"📋 Creating app manifest",
|
103
|
-
"🏗️ Generating code files",
|
104
|
-
"✅ Validating code quality",
|
105
|
-
"📊 Calculating metrics",
|
106
|
-
"📄 Creating documentation"
|
107
|
-
]
|
108
|
-
|
109
|
-
self.current_phase = 0
|
110
|
-
self.task_id = None
|
111
|
-
|
112
|
-
def start(self):
|
113
|
-
"""Start progress tracking."""
|
114
|
-
self.progress.start()
|
115
|
-
self.task_id = self.progress.add_task(
|
116
|
-
f"Generating {self.app_name}...",
|
117
|
-
total=len(self.phases)
|
118
|
-
)
|
119
|
-
|
120
|
-
# Show initial phase
|
121
|
-
self.update_phase(0)
|
122
|
-
|
123
|
-
def update_phase(self, phase_index: int, message: Optional[str] = None):
|
124
|
-
"""Update current phase."""
|
125
|
-
if phase_index < len(self.phases):
|
126
|
-
self.current_phase = phase_index
|
127
|
-
description = message or self.phases[phase_index]
|
128
|
-
|
129
|
-
self.progress.update(
|
130
|
-
self.task_id,
|
131
|
-
description=description,
|
132
|
-
completed=phase_index
|
133
|
-
)
|
134
|
-
|
135
|
-
def next_phase(self, message: Optional[str] = None):
|
136
|
-
"""Move to next phase."""
|
137
|
-
self.update_phase(self.current_phase + 1, message)
|
138
|
-
|
139
|
-
def complete(self):
|
140
|
-
"""Complete progress tracking."""
|
141
|
-
if self.task_id:
|
142
|
-
self.progress.update(
|
143
|
-
self.task_id,
|
144
|
-
description="✅ Generation completed!",
|
145
|
-
completed=len(self.phases)
|
146
|
-
)
|
147
|
-
|
148
|
-
self.progress.stop()
|
149
|
-
|
150
|
-
# Show completion summary
|
151
|
-
duration = datetime.now() - self.start_time
|
152
|
-
self._show_completion_summary(duration)
|
153
|
-
|
154
|
-
def _show_completion_summary(self, duration: timedelta):
|
155
|
-
"""Show completion summary."""
|
156
|
-
summary_text = Text()
|
157
|
-
summary_text.append("🎉 Application generation completed!\n", style="bold green")
|
158
|
-
summary_text.append(f"⏱️ Total time: {duration.total_seconds():.1f} seconds\n", style="cyan")
|
159
|
-
summary_text.append(f"📱 App: {self.app_name}", style="blue")
|
160
|
-
|
161
|
-
panel = Panel(
|
162
|
-
summary_text,
|
163
|
-
title="Generation Complete",
|
164
|
-
border_style="green",
|
165
|
-
padding=(1, 2)
|
166
|
-
)
|
167
|
-
|
168
|
-
self.console.print(panel)
|
169
|
-
|
170
|
-
|
171
|
-
class ScanningProgress:
|
172
|
-
"""Progress tracker for project scanning."""
|
173
|
-
|
174
|
-
def __init__(self, console: Console):
|
175
|
-
"""Initialize scanning progress."""
|
176
|
-
self.console = console
|
177
|
-
self.status = Status("🔍 Scanning project...", console=console)
|
178
|
-
|
179
|
-
def start(self):
|
180
|
-
"""Start scanning progress."""
|
181
|
-
self.status.start()
|
182
|
-
|
183
|
-
def update(self, message: str):
|
184
|
-
"""Update scanning status."""
|
185
|
-
self.status.update(f"🔍 {message}")
|
186
|
-
|
187
|
-
def complete(self):
|
188
|
-
"""Complete scanning."""
|
189
|
-
self.status.stop()
|
190
|
-
|
191
|
-
|
192
|
-
class RichQuestionInterface:
|
193
|
-
"""Rich interface for interactive questioning."""
|
194
|
-
|
195
|
-
def __init__(self, console: Console):
|
196
|
-
"""Initialize question interface."""
|
197
|
-
self.console = console
|
198
|
-
self.theme = RichTheme()
|
199
|
-
|
200
|
-
def ask_app_details(self) -> Dict[str, Any]:
|
201
|
-
"""Ask for basic application details."""
|
202
|
-
self.console.print()
|
203
|
-
self._show_header("Application Details", "Let's gather some basic information about your app")
|
204
|
-
|
205
|
-
# App name
|
206
|
-
app_name = self._ask_app_name()
|
207
|
-
|
208
|
-
# Description
|
209
|
-
description = self._ask_description()
|
210
|
-
|
211
|
-
# App type
|
212
|
-
app_type = self._ask_app_type()
|
213
|
-
|
214
|
-
# Complexity
|
215
|
-
complexity = self._ask_complexity()
|
216
|
-
|
217
|
-
return {
|
218
|
-
"app_name": app_name,
|
219
|
-
"description": description,
|
220
|
-
"app_type": app_type,
|
221
|
-
"complexity": complexity
|
222
|
-
}
|
223
|
-
|
224
|
-
def ask_features(self, complexity: AppComplexity) -> List[AppFeature]:
|
225
|
-
"""Ask for feature selection."""
|
226
|
-
self._show_header("Feature Selection", f"Select features for your {complexity.value} application")
|
227
|
-
|
228
|
-
recommended = complexity.get_recommended_features()
|
229
|
-
all_features = list(AppFeature)
|
230
|
-
|
231
|
-
# Show recommended features
|
232
|
-
self._show_recommended_features(recommended)
|
233
|
-
|
234
|
-
# Ask if user wants to customize
|
235
|
-
if Confirm.ask("\n[bold]Customize feature selection?[/bold]", default=False):
|
236
|
-
return self._customize_features(all_features, recommended)
|
237
|
-
else:
|
238
|
-
return list(recommended)
|
239
|
-
|
240
|
-
def ask_contextual_questions(self, questions: List[Dict[str, Any]]) -> Dict[str, Any]:
|
241
|
-
"""Ask contextual questions based on project analysis."""
|
242
|
-
self._show_header("Contextual Questions", "Based on your project, we have some specific questions")
|
243
|
-
|
244
|
-
answers = {}
|
245
|
-
|
246
|
-
for i, question in enumerate(questions, 1):
|
247
|
-
self.console.print(f"\n[bold cyan]Question {i}/{len(questions)}:[/bold cyan]")
|
248
|
-
|
249
|
-
# Show question context if available
|
250
|
-
if question.get("context"):
|
251
|
-
self._show_question_context(question["context"])
|
252
|
-
|
253
|
-
# Ask the question
|
254
|
-
answer = self._ask_question(question)
|
255
|
-
answers[question["id"]] = answer
|
256
|
-
|
257
|
-
# Show progress
|
258
|
-
progress_bar = "█" * (i * 20 // len(questions)) + "░" * (20 - (i * 20 // len(questions)))
|
259
|
-
self.console.print(f"[dim]Progress: [{progress_bar}] {i}/{len(questions)}[/dim]")
|
260
|
-
|
261
|
-
return answers
|
262
|
-
|
263
|
-
def _show_header(self, title: str, subtitle: str = ""):
|
264
|
-
"""Show section header."""
|
265
|
-
header_text = Text()
|
266
|
-
header_text.append(title, style=f"bold {self.theme.PRIMARY}")
|
267
|
-
if subtitle:
|
268
|
-
header_text.append(f"\n{subtitle}", style=self.theme.MUTED)
|
269
|
-
|
270
|
-
panel = Panel(
|
271
|
-
header_text,
|
272
|
-
border_style=self.theme.PRIMARY,
|
273
|
-
padding=(1, 2)
|
274
|
-
)
|
275
|
-
|
276
|
-
self.console.print(panel)
|
277
|
-
|
278
|
-
def _ask_app_name(self) -> str:
|
279
|
-
"""Ask for application name."""
|
280
|
-
while True:
|
281
|
-
app_name = Prompt.ask(
|
282
|
-
"[bold]Application name[/bold]",
|
283
|
-
default="my_app"
|
284
|
-
)
|
285
|
-
|
286
|
-
# Basic validation
|
287
|
-
if app_name.replace("_", "").isalnum() and app_name[0].isalpha():
|
288
|
-
return app_name
|
289
|
-
else:
|
290
|
-
self.console.print("[red]❌ Invalid name. Use letters, numbers, and underscores only.[/red]")
|
291
|
-
|
292
|
-
def _ask_description(self) -> str:
|
293
|
-
"""Ask for application description."""
|
294
|
-
return Prompt.ask(
|
295
|
-
"[bold]Brief description[/bold]",
|
296
|
-
default="A Django application"
|
297
|
-
)
|
298
|
-
|
299
|
-
def _ask_app_type(self) -> AppType:
|
300
|
-
"""Ask for application type."""
|
301
|
-
self.console.print("\n[bold]Application Type:[/bold]")
|
302
|
-
|
303
|
-
table = Table(show_header=False, box=None, padding=(0, 2))
|
304
|
-
table.add_column("Option", style="cyan")
|
305
|
-
table.add_column("Description")
|
306
|
-
|
307
|
-
table.add_row("1", "🐍 Django - Standard Django application")
|
308
|
-
table.add_row("2", "⚙️ Django-CFG - Enhanced with configuration management")
|
309
|
-
|
310
|
-
self.console.print(table)
|
311
|
-
|
312
|
-
choice = Prompt.ask("Choose type", choices=["1", "2"], default="2")
|
313
|
-
return AppType.DJANGO if choice == "1" else AppType.DJANGO_CFG
|
314
|
-
|
315
|
-
def _ask_complexity(self) -> AppComplexity:
|
316
|
-
"""Ask for complexity level."""
|
317
|
-
self.console.print("\n[bold]Complexity Level:[/bold]")
|
318
|
-
|
319
|
-
table = Table(show_header=True, header_style="bold magenta")
|
320
|
-
table.add_column("Option", style="cyan", width=8)
|
321
|
-
table.add_column("Level", style="green")
|
322
|
-
table.add_column("Description")
|
323
|
-
table.add_column("Time", style="yellow")
|
324
|
-
|
325
|
-
table.add_row("1", "Basic", "Simple app with core features", "~5 min")
|
326
|
-
table.add_row("2", "Moderate", "Standard app with common features", "~15 min")
|
327
|
-
table.add_row("3", "Advanced", "Complex app with advanced features", "~30 min")
|
328
|
-
table.add_row("4", "Enterprise", "Full-featured enterprise app", "~60 min")
|
329
|
-
|
330
|
-
self.console.print(table)
|
331
|
-
|
332
|
-
choice = Prompt.ask("Choose complexity", choices=["1", "2", "3", "4"], default="2")
|
333
|
-
|
334
|
-
complexity_map = {
|
335
|
-
"1": AppComplexity.SIMPLE,
|
336
|
-
"2": AppComplexity.MODERATE,
|
337
|
-
"3": AppComplexity.ADVANCED,
|
338
|
-
"4": AppComplexity.ENTERPRISE
|
339
|
-
}
|
340
|
-
|
341
|
-
return complexity_map[choice]
|
342
|
-
|
343
|
-
def _show_recommended_features(self, features: set):
|
344
|
-
"""Show recommended features."""
|
345
|
-
self.console.print("\n[bold green]Recommended Features:[/bold green]")
|
346
|
-
|
347
|
-
columns = []
|
348
|
-
for feature in sorted(features, key=lambda x: x.value):
|
349
|
-
feature_text = Text()
|
350
|
-
feature_text.append("✓ ", style="green")
|
351
|
-
feature_text.append(feature.value.replace("_", " ").title(), style="white")
|
352
|
-
columns.append(Panel(feature_text, padding=(0, 1), border_style="dim"))
|
353
|
-
|
354
|
-
self.console.print(Columns(columns, equal=True, expand=True))
|
355
|
-
|
356
|
-
def _customize_features(self, all_features: List[AppFeature], recommended: set) -> List[AppFeature]:
|
357
|
-
"""Allow feature customization."""
|
358
|
-
selected = recommended.copy()
|
359
|
-
|
360
|
-
self.console.print("\n[bold]Feature Customization:[/bold]")
|
361
|
-
self.console.print("[dim]Type feature name to toggle, 'done' to finish[/dim]")
|
362
|
-
|
363
|
-
while True:
|
364
|
-
# Show current selection in columns
|
365
|
-
self._show_feature_grid(all_features, selected)
|
366
|
-
|
367
|
-
choice = Prompt.ask(
|
368
|
-
"\nFeature to toggle (or 'done')",
|
369
|
-
default="done"
|
370
|
-
).lower()
|
371
|
-
|
372
|
-
if choice == "done":
|
373
|
-
break
|
374
|
-
|
375
|
-
# Find matching feature
|
376
|
-
matching_feature = self._find_feature(choice, all_features)
|
377
|
-
|
378
|
-
if matching_feature:
|
379
|
-
if matching_feature in selected:
|
380
|
-
selected.remove(matching_feature)
|
381
|
-
self.console.print(f"[red]➖ Removed {matching_feature.value}[/red]")
|
382
|
-
else:
|
383
|
-
selected.add(matching_feature)
|
384
|
-
self.console.print(f"[green]➕ Added {matching_feature.value}[/green]")
|
385
|
-
else:
|
386
|
-
self.console.print(f"[red]❌ Feature '{choice}' not found[/red]")
|
387
|
-
|
388
|
-
return list(selected)
|
389
|
-
|
390
|
-
def _show_feature_grid(self, all_features: List[AppFeature], selected: set):
|
391
|
-
"""Show features in a grid layout."""
|
392
|
-
table = Table(show_header=True, header_style="bold magenta")
|
393
|
-
table.add_column("Feature", style="white")
|
394
|
-
table.add_column("Status", width=8, style="center")
|
395
|
-
table.add_column("Description", style="dim")
|
396
|
-
|
397
|
-
for feature in all_features:
|
398
|
-
status = "✓" if feature in selected else " "
|
399
|
-
status_style = "green" if feature in selected else "dim"
|
400
|
-
description = self._get_feature_description(feature)
|
401
|
-
|
402
|
-
table.add_row(
|
403
|
-
feature.value.replace("_", " ").title(),
|
404
|
-
status,
|
405
|
-
description,
|
406
|
-
style=status_style
|
407
|
-
)
|
408
|
-
|
409
|
-
self.console.print(table)
|
410
|
-
|
411
|
-
def _find_feature(self, search: str, features: List[AppFeature]) -> Optional[AppFeature]:
|
412
|
-
"""Find feature by partial name match."""
|
413
|
-
search = search.lower()
|
414
|
-
|
415
|
-
# Exact match first
|
416
|
-
for feature in features:
|
417
|
-
if feature.value.lower() == search:
|
418
|
-
return feature
|
419
|
-
|
420
|
-
# Partial match
|
421
|
-
for feature in features:
|
422
|
-
if search in feature.value.lower():
|
423
|
-
return feature
|
424
|
-
|
425
|
-
return None
|
426
|
-
|
427
|
-
def _get_feature_description(self, feature: AppFeature) -> str:
|
428
|
-
"""Get feature description."""
|
429
|
-
descriptions = {
|
430
|
-
AppFeature.MODELS: "Database models and ORM",
|
431
|
-
AppFeature.VIEWS: "View functions and classes",
|
432
|
-
AppFeature.URLS: "URL routing configuration",
|
433
|
-
AppFeature.ADMIN: "Django admin interface",
|
434
|
-
AppFeature.FORMS: "Form classes and validation",
|
435
|
-
AppFeature.TEMPLATES: "HTML templates",
|
436
|
-
AppFeature.API: "REST API with DRF",
|
437
|
-
AppFeature.TESTS: "Unit and integration tests",
|
438
|
-
AppFeature.TASKS: "Background tasks",
|
439
|
-
AppFeature.DOCS: "Documentation",
|
440
|
-
AppFeature.CONFIG: "Configuration management",
|
441
|
-
AppFeature.SECURITY: "Security and permissions",
|
442
|
-
}
|
443
|
-
return descriptions.get(feature, "Additional feature")
|
444
|
-
|
445
|
-
def _show_question_context(self, context: Dict[str, Any]):
|
446
|
-
"""Show context for a question."""
|
447
|
-
if context.get("code_snippet"):
|
448
|
-
code_panel = Panel(
|
449
|
-
Syntax(context["code_snippet"], "python", theme="monokai"),
|
450
|
-
title="📄 Relevant Code",
|
451
|
-
border_style="dim"
|
452
|
-
)
|
453
|
-
self.console.print(code_panel)
|
454
|
-
|
455
|
-
if context.get("explanation"):
|
456
|
-
self.console.print(f"[dim]{context['explanation']}[/dim]")
|
457
|
-
|
458
|
-
def _ask_question(self, question: Dict[str, Any]) -> Any:
|
459
|
-
"""Ask a single question."""
|
460
|
-
question_type = question.get("type", "text")
|
461
|
-
|
462
|
-
if question_type == "yes_no":
|
463
|
-
return Confirm.ask(question["text"], default=question.get("default", True))
|
464
|
-
|
465
|
-
elif question_type == "choice":
|
466
|
-
choices = question.get("choices", [])
|
467
|
-
if choices:
|
468
|
-
self.console.print(f"\n[bold]{question['text']}[/bold]")
|
469
|
-
for i, choice in enumerate(choices, 1):
|
470
|
-
self.console.print(f" {i}. {choice}")
|
471
|
-
|
472
|
-
choice_num = IntPrompt.ask(
|
473
|
-
"Choose option",
|
474
|
-
choices=[str(i) for i in range(1, len(choices) + 1)],
|
475
|
-
default="1"
|
476
|
-
)
|
477
|
-
return choices[int(choice_num) - 1]
|
478
|
-
|
479
|
-
else: # text
|
480
|
-
return Prompt.ask(question["text"], default=question.get("default", ""))
|
481
|
-
|
482
|
-
|
483
|
-
class RichErrorDisplay:
|
484
|
-
"""Rich error display with helpful suggestions."""
|
485
|
-
|
486
|
-
def __init__(self, console: Console):
|
487
|
-
"""Initialize error display."""
|
488
|
-
self.console = console
|
489
|
-
self.theme = RichTheme()
|
490
|
-
|
491
|
-
def show_error(
|
492
|
-
self,
|
493
|
-
title: str,
|
494
|
-
message: str,
|
495
|
-
errors: Optional[List[str]] = None,
|
496
|
-
warnings: Optional[List[str]] = None,
|
497
|
-
suggestions: Optional[List[str]] = None
|
498
|
-
):
|
499
|
-
"""Show comprehensive error information."""
|
500
|
-
# Main error panel
|
501
|
-
error_text = Text()
|
502
|
-
error_text.append("❌ ", style=self.theme.ERROR)
|
503
|
-
error_text.append(message, style="white")
|
504
|
-
|
505
|
-
error_panel = Panel(
|
506
|
-
error_text,
|
507
|
-
title=f"[bold red]{title}[/bold red]",
|
508
|
-
border_style=self.theme.ERROR,
|
509
|
-
padding=(1, 2)
|
510
|
-
)
|
511
|
-
|
512
|
-
self.console.print(error_panel)
|
513
|
-
|
514
|
-
# Show detailed errors
|
515
|
-
if errors:
|
516
|
-
self._show_error_list("Errors", errors, self.theme.ERROR)
|
517
|
-
|
518
|
-
# Show warnings
|
519
|
-
if warnings:
|
520
|
-
self._show_error_list("Warnings", warnings, self.theme.WARNING)
|
521
|
-
|
522
|
-
# Show suggestions
|
523
|
-
if suggestions:
|
524
|
-
self._show_suggestions(suggestions)
|
525
|
-
|
526
|
-
def _show_error_list(self, title: str, items: List[str], style: str):
|
527
|
-
"""Show list of errors or warnings."""
|
528
|
-
self.console.print(f"\n[bold {style}]{title}:[/bold {style}]")
|
529
|
-
|
530
|
-
for item in items:
|
531
|
-
self.console.print(f" • {item}", style=style)
|
532
|
-
|
533
|
-
def _show_suggestions(self, suggestions: List[str]):
|
534
|
-
"""Show helpful suggestions."""
|
535
|
-
self.console.print(f"\n[bold {self.theme.INFO}]💡 Suggestions:[/bold {self.theme.INFO}]")
|
536
|
-
|
537
|
-
for suggestion in suggestions:
|
538
|
-
self.console.print(f" • {suggestion}", style=self.theme.INFO)
|
539
|
-
|
540
|
-
|
541
|
-
class RichStatusDisplay:
|
542
|
-
"""Rich status display for various operations."""
|
543
|
-
|
544
|
-
def __init__(self, console: Console):
|
545
|
-
"""Initialize status display."""
|
546
|
-
self.console = console
|
547
|
-
self.theme = RichTheme()
|
548
|
-
|
549
|
-
def show_generation_result(self, result: AppGenerationResult):
|
550
|
-
"""Show application generation result."""
|
551
|
-
if result.status == "success":
|
552
|
-
self._show_success_result(result)
|
553
|
-
else:
|
554
|
-
self._show_failure_result(result)
|
555
|
-
|
556
|
-
def _show_success_result(self, result: AppGenerationResult):
|
557
|
-
"""Show successful generation result."""
|
558
|
-
# Success header
|
559
|
-
success_text = Text()
|
560
|
-
success_text.append("🎉 Success! ", style="bold green")
|
561
|
-
success_text.append(f"Generated '{result.app_name}' application", style="white")
|
562
|
-
|
563
|
-
header_panel = Panel(
|
564
|
-
success_text,
|
565
|
-
border_style="green",
|
566
|
-
padding=(1, 2)
|
567
|
-
)
|
568
|
-
|
569
|
-
self.console.print(header_panel)
|
570
|
-
|
571
|
-
# Statistics table
|
572
|
-
stats_table = Table(title="Generation Statistics", show_header=True)
|
573
|
-
stats_table.add_column("Metric", style="cyan")
|
574
|
-
stats_table.add_column("Value", style="green")
|
575
|
-
|
576
|
-
stats_table.add_row("Files Generated", str(len(result.generated_files)))
|
577
|
-
stats_table.add_row("Duration", f"{result.duration_seconds:.1f} seconds")
|
578
|
-
|
579
|
-
if result.quality_metrics:
|
580
|
-
stats_table.add_row("Code Quality", f"{result.quality_metrics.code_readability_score:.2f}/1.0")
|
581
|
-
stats_table.add_row("Test Coverage", f"{result.quality_metrics.test_coverage_percentage:.1f}%")
|
582
|
-
|
583
|
-
self.console.print(stats_table)
|
584
|
-
|
585
|
-
# Next steps
|
586
|
-
self._show_next_steps(result.app_name)
|
587
|
-
|
588
|
-
def _show_failure_result(self, result: AppGenerationResult):
|
589
|
-
"""Show failed generation result."""
|
590
|
-
error_text = Text()
|
591
|
-
error_text.append("❌ Generation Failed\n", style="bold red")
|
592
|
-
error_text.append(result.message, style="white")
|
593
|
-
|
594
|
-
error_panel = Panel(
|
595
|
-
error_text,
|
596
|
-
border_style="red",
|
597
|
-
padding=(1, 2)
|
598
|
-
)
|
599
|
-
|
600
|
-
self.console.print(error_panel)
|
601
|
-
|
602
|
-
# Show errors if any
|
603
|
-
if result.errors:
|
604
|
-
self.console.print("\n[bold red]Errors:[/bold red]")
|
605
|
-
for error in result.errors:
|
606
|
-
self.console.print(f" • {error}", style="red")
|
607
|
-
|
608
|
-
def _show_next_steps(self, app_name: str):
|
609
|
-
"""Show next steps after successful generation."""
|
610
|
-
self.console.print("\n[bold]🚀 Next Steps:[/bold]")
|
611
|
-
|
612
|
-
steps = [
|
613
|
-
f"1. Add '{app_name}' to your INSTALLED_APPS",
|
614
|
-
"2. Run migrations: [cyan]python manage.py makemigrations && python manage.py migrate[/cyan]",
|
615
|
-
"3. Include URLs in your main urls.py",
|
616
|
-
"4. Start development! 🎯"
|
617
|
-
]
|
618
|
-
|
619
|
-
for step in steps:
|
620
|
-
self.console.print(f" {step}")
|
621
|
-
|
622
|
-
self.console.print()
|
@@ -1,38 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Utility functions and helpers for Django App Agent Module.
|
3
|
-
|
4
|
-
This module contains common utilities including:
|
5
|
-
- Structured logging
|
6
|
-
- Validation helpers
|
7
|
-
- File system utilities
|
8
|
-
- String processing functions
|
9
|
-
"""
|
10
|
-
|
11
|
-
from .logging import (
|
12
|
-
get_logger,
|
13
|
-
setup_logging,
|
14
|
-
log_execution_time,
|
15
|
-
log_agent_operation,
|
16
|
-
StructuredLogger,
|
17
|
-
)
|
18
|
-
from .validation import (
|
19
|
-
validate_app_name,
|
20
|
-
validate_file_path,
|
21
|
-
validate_python_identifier,
|
22
|
-
sanitize_filename,
|
23
|
-
)
|
24
|
-
|
25
|
-
__all__ = [
|
26
|
-
# Logging
|
27
|
-
"get_logger",
|
28
|
-
"setup_logging",
|
29
|
-
"log_execution_time",
|
30
|
-
"log_agent_operation",
|
31
|
-
"StructuredLogger",
|
32
|
-
|
33
|
-
# Validation
|
34
|
-
"validate_app_name",
|
35
|
-
"validate_file_path",
|
36
|
-
"validate_python_identifier",
|
37
|
-
"sanitize_filename",
|
38
|
-
]
|