django-cfg 1.3.9__py3-none-any.whl → 1.3.11__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.
Files changed (187) hide show
  1. django_cfg/__init__.py +1 -1
  2. django_cfg/apps/payments/admin/networks_admin.py +12 -1
  3. django_cfg/apps/payments/admin/payments_admin.py +13 -0
  4. django_cfg/apps/payments/admin_interface/serializers/payment_serializers.py +62 -14
  5. django_cfg/apps/payments/admin_interface/templates/payments/components/payment_card.html +121 -0
  6. django_cfg/apps/payments/admin_interface/templates/payments/components/payment_qr_code.html +95 -0
  7. django_cfg/apps/payments/admin_interface/templates/payments/components/progress_bar.html +37 -0
  8. django_cfg/apps/payments/admin_interface/templates/payments/components/provider_stats.html +60 -0
  9. django_cfg/apps/payments/admin_interface/templates/payments/components/status_badge.html +41 -0
  10. django_cfg/apps/payments/admin_interface/templates/payments/components/status_overview.html +83 -0
  11. django_cfg/apps/payments/admin_interface/templates/payments/payment_detail.html +363 -0
  12. django_cfg/apps/payments/admin_interface/templates/payments/payment_form.html +33 -3
  13. django_cfg/apps/payments/admin_interface/views/api/payments.py +102 -0
  14. django_cfg/apps/payments/admin_interface/views/api/webhook_admin.py +96 -45
  15. django_cfg/apps/payments/admin_interface/views/forms.py +5 -1
  16. django_cfg/apps/payments/config/__init__.py +14 -15
  17. django_cfg/apps/payments/config/django_cfg_integration.py +59 -1
  18. django_cfg/apps/payments/config/helpers.py +8 -13
  19. django_cfg/apps/payments/migrations/0001_initial.py +33 -46
  20. django_cfg/apps/payments/migrations/0002_rename_payments_un_user_id_7f6e79_idx_payments_un_user_id_8ce187_idx_and_more.py +46 -0
  21. django_cfg/apps/payments/migrations/0003_universalpayment_status_changed_at.py +25 -0
  22. django_cfg/apps/payments/models/managers/payment_managers.py +142 -25
  23. django_cfg/apps/payments/models/payments.py +94 -0
  24. django_cfg/apps/payments/services/core/base.py +4 -4
  25. django_cfg/apps/payments/services/core/payment_service.py +265 -38
  26. django_cfg/apps/payments/services/providers/base.py +209 -3
  27. django_cfg/apps/payments/services/providers/models/__init__.py +2 -0
  28. django_cfg/apps/payments/services/providers/models/base.py +25 -2
  29. django_cfg/apps/payments/services/providers/nowpayments/models.py +2 -2
  30. django_cfg/apps/payments/services/providers/nowpayments/provider.py +57 -9
  31. django_cfg/apps/payments/services/providers/registry.py +5 -5
  32. django_cfg/apps/payments/services/types/requests.py +19 -7
  33. django_cfg/apps/payments/signals/payment_signals.py +31 -2
  34. django_cfg/apps/payments/static/payments/js/api-client.js +6 -1
  35. django_cfg/apps/payments/static/payments/js/payment-detail.js +167 -0
  36. django_cfg/apps/payments/static/payments/js/payment-form.js +35 -26
  37. django_cfg/apps/payments/templatetags/payment_tags.py +8 -0
  38. django_cfg/apps/payments/urls.py +3 -2
  39. django_cfg/apps/payments/views/api/currencies.py +3 -0
  40. django_cfg/apps/payments/views/serializers/currencies.py +18 -5
  41. django_cfg/apps/tasks/admin/tasks_admin.py +2 -2
  42. django_cfg/apps/tasks/static/tasks/css/dashboard.css +68 -217
  43. django_cfg/apps/tasks/static/tasks/js/api.js +40 -84
  44. django_cfg/apps/tasks/static/tasks/js/components/DataManager.js +24 -0
  45. django_cfg/apps/tasks/static/tasks/js/components/TabManager.js +85 -0
  46. django_cfg/apps/tasks/static/tasks/js/components/TaskRenderer.js +216 -0
  47. django_cfg/apps/tasks/static/tasks/js/dashboard/main.mjs +245 -0
  48. django_cfg/apps/tasks/static/tasks/js/dashboard/overview.mjs +123 -0
  49. django_cfg/apps/tasks/static/tasks/js/dashboard/queues.mjs +120 -0
  50. django_cfg/apps/tasks/static/tasks/js/dashboard/tasks.mjs +350 -0
  51. django_cfg/apps/tasks/static/tasks/js/dashboard/workers.mjs +169 -0
  52. django_cfg/apps/tasks/tasks/__init__.py +10 -0
  53. django_cfg/apps/tasks/tasks/demo_tasks.py +133 -0
  54. django_cfg/apps/tasks/templates/tasks/components/management_actions.html +42 -45
  55. django_cfg/apps/tasks/templates/tasks/components/{status_cards.html → overview_content.html} +30 -11
  56. django_cfg/apps/tasks/templates/tasks/components/queues_content.html +19 -0
  57. django_cfg/apps/tasks/templates/tasks/components/tab_navigation.html +16 -10
  58. django_cfg/apps/tasks/templates/tasks/components/tasks_content.html +51 -0
  59. django_cfg/apps/tasks/templates/tasks/components/workers_content.html +30 -0
  60. django_cfg/apps/tasks/templates/tasks/layout/base.html +117 -0
  61. django_cfg/apps/tasks/templates/tasks/pages/dashboard.html +82 -0
  62. django_cfg/apps/tasks/templates/tasks/partials/task_row_template.html +40 -0
  63. django_cfg/apps/tasks/templates/tasks/widgets/task_filters.html +37 -0
  64. django_cfg/apps/tasks/templates/tasks/widgets/task_footer.html +41 -0
  65. django_cfg/apps/tasks/templates/tasks/widgets/task_table.html +50 -0
  66. django_cfg/apps/tasks/urls.py +2 -2
  67. django_cfg/apps/tasks/urls_admin.py +2 -2
  68. django_cfg/apps/tasks/utils/__init__.py +1 -0
  69. django_cfg/apps/tasks/utils/simulator.py +356 -0
  70. django_cfg/apps/tasks/views/__init__.py +16 -0
  71. django_cfg/apps/tasks/views/api.py +569 -0
  72. django_cfg/apps/tasks/views/dashboard.py +58 -0
  73. django_cfg/core/integration/__init__.py +21 -0
  74. django_cfg/management/commands/rundramatiq_simulator.py +430 -0
  75. django_cfg/models/constance.py +0 -11
  76. django_cfg/models/payments.py +137 -3
  77. django_cfg/modules/django_tasks.py +54 -21
  78. django_cfg/registry/core.py +4 -9
  79. django_cfg/template_archive/django_sample.zip +0 -0
  80. {django_cfg-1.3.9.dist-info → django_cfg-1.3.11.dist-info}/METADATA +2 -2
  81. {django_cfg-1.3.9.dist-info → django_cfg-1.3.11.dist-info}/RECORD +84 -152
  82. django_cfg/apps/payments/config/constance/__init__.py +0 -22
  83. django_cfg/apps/payments/config/constance/config_service.py +0 -123
  84. django_cfg/apps/payments/config/constance/fields.py +0 -69
  85. django_cfg/apps/payments/config/constance/settings.py +0 -160
  86. django_cfg/apps/payments/migrations/0002_currency_usd_rate_currency_usd_rate_updated_at.py +0 -26
  87. django_cfg/apps/payments/migrations/0003_remove_provider_currency_fields.py +0 -28
  88. django_cfg/apps/payments/migrations/0004_add_reserved_usd_field.py +0 -30
  89. django_cfg/apps/tasks/static/tasks/js/dashboard.js +0 -614
  90. django_cfg/apps/tasks/static/tasks/js/modals.js +0 -452
  91. django_cfg/apps/tasks/static/tasks/js/notifications.js +0 -144
  92. django_cfg/apps/tasks/static/tasks/js/task-monitor.js +0 -454
  93. django_cfg/apps/tasks/static/tasks/js/theme.js +0 -77
  94. django_cfg/apps/tasks/templates/tasks/base.html +0 -96
  95. django_cfg/apps/tasks/templates/tasks/components/info_cards.html +0 -85
  96. django_cfg/apps/tasks/templates/tasks/components/overview_tab.html +0 -22
  97. django_cfg/apps/tasks/templates/tasks/components/queues_tab.html +0 -19
  98. django_cfg/apps/tasks/templates/tasks/components/task_details_modal.html +0 -103
  99. django_cfg/apps/tasks/templates/tasks/components/tasks_tab.html +0 -32
  100. django_cfg/apps/tasks/templates/tasks/components/workers_tab.html +0 -29
  101. django_cfg/apps/tasks/templates/tasks/dashboard.html +0 -29
  102. django_cfg/apps/tasks/views.py +0 -461
  103. django_cfg/management/commands/app_agent_diagnose.py +0 -470
  104. django_cfg/management/commands/app_agent_generate.py +0 -342
  105. django_cfg/management/commands/app_agent_info.py +0 -308
  106. django_cfg/management/commands/auto_generate.py +0 -486
  107. django_cfg/modules/django_app_agent/__init__.py +0 -87
  108. django_cfg/modules/django_app_agent/agents/__init__.py +0 -40
  109. django_cfg/modules/django_app_agent/agents/base/__init__.py +0 -24
  110. django_cfg/modules/django_app_agent/agents/base/agent.py +0 -354
  111. django_cfg/modules/django_app_agent/agents/base/context.py +0 -236
  112. django_cfg/modules/django_app_agent/agents/base/executor.py +0 -430
  113. django_cfg/modules/django_app_agent/agents/generation/__init__.py +0 -12
  114. django_cfg/modules/django_app_agent/agents/generation/app_generator/__init__.py +0 -15
  115. django_cfg/modules/django_app_agent/agents/generation/app_generator/config_validator.py +0 -147
  116. django_cfg/modules/django_app_agent/agents/generation/app_generator/main.py +0 -99
  117. django_cfg/modules/django_app_agent/agents/generation/app_generator/models.py +0 -32
  118. django_cfg/modules/django_app_agent/agents/generation/app_generator/prompt_manager.py +0 -290
  119. django_cfg/modules/django_app_agent/agents/interfaces.py +0 -376
  120. django_cfg/modules/django_app_agent/core/__init__.py +0 -33
  121. django_cfg/modules/django_app_agent/core/config.py +0 -300
  122. django_cfg/modules/django_app_agent/core/exceptions.py +0 -359
  123. django_cfg/modules/django_app_agent/models/__init__.py +0 -71
  124. django_cfg/modules/django_app_agent/models/base.py +0 -283
  125. django_cfg/modules/django_app_agent/models/context.py +0 -496
  126. django_cfg/modules/django_app_agent/models/enums.py +0 -481
  127. django_cfg/modules/django_app_agent/models/requests.py +0 -500
  128. django_cfg/modules/django_app_agent/models/responses.py +0 -585
  129. django_cfg/modules/django_app_agent/pytest.ini +0 -6
  130. django_cfg/modules/django_app_agent/services/__init__.py +0 -42
  131. django_cfg/modules/django_app_agent/services/app_generator/__init__.py +0 -30
  132. django_cfg/modules/django_app_agent/services/app_generator/ai_integration.py +0 -133
  133. django_cfg/modules/django_app_agent/services/app_generator/context.py +0 -40
  134. django_cfg/modules/django_app_agent/services/app_generator/main.py +0 -202
  135. django_cfg/modules/django_app_agent/services/app_generator/structure.py +0 -316
  136. django_cfg/modules/django_app_agent/services/app_generator/validation.py +0 -125
  137. django_cfg/modules/django_app_agent/services/base.py +0 -437
  138. django_cfg/modules/django_app_agent/services/context_builder/__init__.py +0 -34
  139. django_cfg/modules/django_app_agent/services/context_builder/code_extractor.py +0 -141
  140. django_cfg/modules/django_app_agent/services/context_builder/context_generator.py +0 -276
  141. django_cfg/modules/django_app_agent/services/context_builder/main.py +0 -272
  142. django_cfg/modules/django_app_agent/services/context_builder/models.py +0 -40
  143. django_cfg/modules/django_app_agent/services/context_builder/pattern_analyzer.py +0 -85
  144. django_cfg/modules/django_app_agent/services/project_scanner/__init__.py +0 -31
  145. django_cfg/modules/django_app_agent/services/project_scanner/app_discovery.py +0 -311
  146. django_cfg/modules/django_app_agent/services/project_scanner/main.py +0 -221
  147. django_cfg/modules/django_app_agent/services/project_scanner/models.py +0 -59
  148. django_cfg/modules/django_app_agent/services/project_scanner/pattern_detection.py +0 -94
  149. django_cfg/modules/django_app_agent/services/questioning_service/__init__.py +0 -28
  150. django_cfg/modules/django_app_agent/services/questioning_service/main.py +0 -273
  151. django_cfg/modules/django_app_agent/services/questioning_service/models.py +0 -111
  152. django_cfg/modules/django_app_agent/services/questioning_service/question_generator.py +0 -251
  153. django_cfg/modules/django_app_agent/services/questioning_service/response_processor.py +0 -347
  154. django_cfg/modules/django_app_agent/services/questioning_service/session_manager.py +0 -356
  155. django_cfg/modules/django_app_agent/services/report_service.py +0 -332
  156. django_cfg/modules/django_app_agent/services/template_manager/__init__.py +0 -18
  157. django_cfg/modules/django_app_agent/services/template_manager/jinja_engine.py +0 -236
  158. django_cfg/modules/django_app_agent/services/template_manager/main.py +0 -159
  159. django_cfg/modules/django_app_agent/services/template_manager/models.py +0 -36
  160. django_cfg/modules/django_app_agent/services/template_manager/template_loader.py +0 -100
  161. django_cfg/modules/django_app_agent/services/template_manager/templates/admin.py.j2 +0 -105
  162. django_cfg/modules/django_app_agent/services/template_manager/templates/apps.py.j2 +0 -31
  163. django_cfg/modules/django_app_agent/services/template_manager/templates/cfg_config.py.j2 +0 -44
  164. django_cfg/modules/django_app_agent/services/template_manager/templates/cfg_module.py.j2 +0 -81
  165. django_cfg/modules/django_app_agent/services/template_manager/templates/forms.py.j2 +0 -107
  166. django_cfg/modules/django_app_agent/services/template_manager/templates/models.py.j2 +0 -139
  167. django_cfg/modules/django_app_agent/services/template_manager/templates/serializers.py.j2 +0 -91
  168. django_cfg/modules/django_app_agent/services/template_manager/templates/tests.py.j2 +0 -195
  169. django_cfg/modules/django_app_agent/services/template_manager/templates/urls.py.j2 +0 -35
  170. django_cfg/modules/django_app_agent/services/template_manager/templates/views.py.j2 +0 -211
  171. django_cfg/modules/django_app_agent/services/template_manager/variable_processor.py +0 -200
  172. django_cfg/modules/django_app_agent/services/validation_service/__init__.py +0 -25
  173. django_cfg/modules/django_app_agent/services/validation_service/django_validator.py +0 -333
  174. django_cfg/modules/django_app_agent/services/validation_service/main.py +0 -242
  175. django_cfg/modules/django_app_agent/services/validation_service/models.py +0 -66
  176. django_cfg/modules/django_app_agent/services/validation_service/quality_validator.py +0 -352
  177. django_cfg/modules/django_app_agent/services/validation_service/security_validator.py +0 -272
  178. django_cfg/modules/django_app_agent/services/validation_service/syntax_validator.py +0 -203
  179. django_cfg/modules/django_app_agent/ui/__init__.py +0 -25
  180. django_cfg/modules/django_app_agent/ui/cli.py +0 -419
  181. django_cfg/modules/django_app_agent/ui/rich_components.py +0 -622
  182. django_cfg/modules/django_app_agent/utils/__init__.py +0 -38
  183. django_cfg/modules/django_app_agent/utils/logging.py +0 -360
  184. django_cfg/modules/django_app_agent/utils/validation.py +0 -417
  185. {django_cfg-1.3.9.dist-info → django_cfg-1.3.11.dist-info}/WHEEL +0 -0
  186. {django_cfg-1.3.9.dist-info → django_cfg-1.3.11.dist-info}/entry_points.txt +0 -0
  187. {django_cfg-1.3.9.dist-info → django_cfg-1.3.11.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
- ]