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,614 +0,0 @@
1
- /**
2
- * Dashboard Main Logic
3
- * Handles tab navigation, data loading, and UI updates
4
- */
5
-
6
- class TasksDashboard {
7
- constructor() {
8
- this.currentTab = 'overview';
9
- this.refreshInterval = null;
10
- this.refreshRate = 30000; // 30 seconds
11
-
12
- this.init();
13
- }
14
-
15
- /**
16
- * Initialize dashboard
17
- */
18
- init() {
19
- this.setupTabNavigation();
20
- this.setupEventListeners();
21
- this.loadInitialData();
22
- this.startAutoRefresh();
23
- }
24
-
25
- /**
26
- * Setup tab navigation
27
- */
28
- setupTabNavigation() {
29
- const tabButtons = document.querySelectorAll('.tab-button');
30
- const tabPanels = document.querySelectorAll('.tab-panel');
31
-
32
- tabButtons.forEach(button => {
33
- button.addEventListener('click', (e) => {
34
- const tabId = e.currentTarget.dataset.tab;
35
- this.switchTab(tabId);
36
- });
37
- });
38
- }
39
-
40
- /**
41
- * Switch to a specific tab
42
- * @param {string} tabId - Tab identifier
43
- */
44
- switchTab(tabId) {
45
- // Update button states
46
- document.querySelectorAll('.tab-button').forEach(btn => {
47
- btn.classList.remove('active', 'border-primary-500', 'text-primary-600', 'dark:text-primary-400');
48
- btn.classList.add('border-transparent', 'text-gray-500', 'hover:text-gray-700', 'hover:border-gray-300', 'dark:text-gray-400', 'dark:hover:text-gray-300');
49
- });
50
-
51
- const activeButton = document.querySelector(`[data-tab="${tabId}"]`);
52
- if (activeButton) {
53
- activeButton.classList.add('active', 'border-primary-500', 'text-primary-600', 'dark:text-primary-400');
54
- activeButton.classList.remove('border-transparent', 'text-gray-500', 'hover:text-gray-700', 'hover:border-gray-300', 'dark:text-gray-400', 'dark:hover:text-gray-300');
55
- }
56
-
57
- // Update panel visibility
58
- document.querySelectorAll('.tab-panel').forEach(panel => {
59
- panel.classList.add('hidden');
60
- panel.classList.remove('active');
61
- });
62
-
63
- const activePanel = document.getElementById(`${tabId}-tab`);
64
- if (activePanel) {
65
- activePanel.classList.remove('hidden');
66
- activePanel.classList.add('active');
67
- }
68
-
69
- this.currentTab = tabId;
70
- this.loadTabData(tabId);
71
- }
72
-
73
- /**
74
- * Setup event listeners
75
- */
76
- setupEventListeners() {
77
- // Refresh buttons
78
- const refreshQueuesBtn = document.getElementById('refresh-queues-btn');
79
- if (refreshQueuesBtn) {
80
- refreshQueuesBtn.addEventListener('click', () => this.loadQueueData());
81
- }
82
-
83
- const refreshTasksBtn = document.getElementById('refresh-tasks-btn');
84
- if (refreshTasksBtn) {
85
- refreshTasksBtn.addEventListener('click', () => this.loadTaskData());
86
- }
87
-
88
- // Worker management buttons
89
- const startWorkersBtn = document.getElementById('start-workers-btn');
90
- if (startWorkersBtn) {
91
- startWorkersBtn.addEventListener('click', () => this.startWorkers());
92
- }
93
-
94
- const stopWorkersBtn = document.getElementById('stop-workers-btn');
95
- if (stopWorkersBtn) {
96
- stopWorkersBtn.addEventListener('click', () => this.stopWorkers());
97
- }
98
-
99
- // Queue management buttons
100
- const clearQueuesBtn = document.getElementById('clear-queues-btn');
101
- if (clearQueuesBtn) {
102
- clearQueuesBtn.addEventListener('click', () => this.clearQueues());
103
- }
104
-
105
- const purgeFailedBtn = document.getElementById('purge-failed-btn');
106
- if (purgeFailedBtn) {
107
- purgeFailedBtn.addEventListener('click', () => this.purgeFailedTasks());
108
- }
109
-
110
- // Task status filter
111
- const taskStatusFilter = document.getElementById('task-status-filter');
112
- if (taskStatusFilter) {
113
- taskStatusFilter.addEventListener('change', () => this.loadTaskData());
114
- }
115
-
116
- // Management action buttons
117
- const clearAllQueuesBtn = document.getElementById('clear-all-queues-btn');
118
- if (clearAllQueuesBtn) {
119
- clearAllQueuesBtn.addEventListener('click', () => this.clearAllQueues());
120
- }
121
-
122
- const purgeFailedTasksBtn = document.getElementById('purge-failed-tasks-btn');
123
- if (purgeFailedTasksBtn) {
124
- purgeFailedTasksBtn.addEventListener('click', () => this.purgeFailedTasks());
125
- }
126
- }
127
-
128
- /**
129
- * Load initial data
130
- */
131
- async loadInitialData() {
132
- await this.loadOverviewData();
133
- }
134
-
135
- /**
136
- * Load data for specific tab
137
- * @param {string} tabId - Tab identifier
138
- */
139
- async loadTabData(tabId) {
140
- switch (tabId) {
141
- case 'overview':
142
- await this.loadOverviewData();
143
- break;
144
- case 'queues':
145
- await this.loadQueueData();
146
- break;
147
- case 'workers':
148
- await this.loadWorkerData();
149
- break;
150
- case 'tasks':
151
- await this.loadTaskData();
152
- break;
153
- }
154
- }
155
-
156
- /**
157
- * Load overview data
158
- */
159
- async loadOverviewData() {
160
- try {
161
- const [queueData, taskData] = await Promise.all([
162
- window.tasksAPI.getQueueStatus(),
163
- window.tasksAPI.getTaskStatistics()
164
- ]);
165
-
166
-
167
- // Extract data from API response wrapper
168
- const actualQueueData = queueData.data || queueData;
169
- const actualTaskData = taskData.data || taskData;
170
-
171
- this.updateStatusCards(actualQueueData, actualTaskData);
172
- this.updateSystemStatus(actualQueueData, actualTaskData);
173
- } catch (error) {
174
- console.error('Failed to load overview data:', error);
175
- this.showError('Failed to load overview data');
176
- }
177
- }
178
-
179
- /**
180
- * Update status cards
181
- * @param {Object} queueData - Queue status data
182
- * @param {Object} taskData - Task statistics data
183
- */
184
- updateStatusCards(queueData, taskData) {
185
- // Active queues
186
- const activeQueuesEl = document.getElementById('active-queues-count');
187
- if (activeQueuesEl && queueData.queues) {
188
- const activeQueues = Object.keys(queueData.queues).length;
189
- activeQueuesEl.textContent = activeQueues;
190
- }
191
-
192
- // Active workers
193
- const activeWorkersEl = document.getElementById('active-workers-count');
194
- if (activeWorkersEl && queueData.workers) {
195
- activeWorkersEl.textContent = queueData.workers.length || 0;
196
- }
197
-
198
- // Pending tasks
199
- const pendingTasksEl = document.getElementById('pending-tasks-count');
200
- if (pendingTasksEl && queueData.queues) {
201
- const pendingTasks = Object.values(queueData.queues).reduce((sum, queue) => sum + (queue.size || 0), 0);
202
- pendingTasksEl.textContent = pendingTasks;
203
- }
204
-
205
- // Failed tasks
206
- const failedTasksEl = document.getElementById('failed-tasks-count');
207
- if (failedTasksEl && taskData.statistics) {
208
- failedTasksEl.textContent = taskData.statistics.failed || 0;
209
- }
210
- }
211
-
212
- /**
213
- * Update system status
214
- * @param {Object} queueData - Queue status data
215
- * @param {Object} taskData - Task statistics data
216
- */
217
- updateSystemStatus(queueData, taskData) {
218
- const container = document.getElementById('system-status-container');
219
- if (!container) return;
220
-
221
- // System is healthy if Redis is connected, workers are optional in development
222
- const isHealthy = queueData.redis_connected;
223
-
224
- container.innerHTML = `
225
- <div class="space-y-4">
226
- <div class="flex items-center justify-between p-4 rounded-lg ${isHealthy ? 'bg-green-50 dark:bg-green-900/20' : 'bg-red-50 dark:bg-red-900/20'}">
227
- <div class="flex items-center">
228
- <span class="material-icons text-2xl mr-3 ${isHealthy ? 'text-green-600 dark:text-green-400' : 'text-red-600 dark:text-red-400'}">
229
- ${isHealthy ? 'check_circle' : 'error'}
230
- </span>
231
- <div>
232
- <h3 class="font-medium ${isHealthy ? 'text-green-900 dark:text-green-100' : 'text-red-900 dark:text-red-100'}">
233
- System ${isHealthy ? 'Healthy' : 'Issues Detected'}
234
- </h3>
235
- <p class="text-sm ${isHealthy ? 'text-green-700 dark:text-green-300' : 'text-red-700 dark:text-red-300'}">
236
- ${isHealthy ? 'All systems operational' : 'Some components need attention'}
237
- </p>
238
- </div>
239
- </div>
240
- <div class="text-right">
241
- <div class="text-sm text-gray-500 dark:text-gray-400">
242
- Last updated: ${new Date().toLocaleTimeString()}
243
- </div>
244
- </div>
245
- </div>
246
-
247
- <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
248
- <div class="flex items-center p-3 rounded-lg bg-gray-50 dark:bg-gray-800">
249
- <span class="material-icons text-lg mr-2 ${queueData.redis_connected ? 'text-green-600' : 'text-red-600'}">
250
- ${queueData.redis_connected ? 'check' : 'close'}
251
- </span>
252
- <span class="text-sm">Redis: ${queueData.redis_connected ? 'Connected' : 'Disconnected'}</span>
253
- </div>
254
-
255
- <div class="flex items-center p-3 rounded-lg bg-gray-50 dark:bg-gray-800">
256
- <span class="material-icons text-lg mr-2 ${queueData.workers && queueData.workers.length > 0 ? 'text-green-600' : 'text-red-600'}">
257
- ${queueData.workers && queueData.workers.length > 0 ? 'check' : 'close'}
258
- </span>
259
- <span class="text-sm">Workers: ${queueData.workers ? queueData.workers.length : 0} active</span>
260
- </div>
261
-
262
- <div class="flex items-center p-3 rounded-lg bg-gray-50 dark:bg-gray-800">
263
- <span class="material-icons text-lg mr-2 text-blue-600">
264
- queue
265
- </span>
266
- <span class="text-sm">Queues: ${queueData.queues ? Object.keys(queueData.queues).length : 0} configured</span>
267
- </div>
268
- </div>
269
- </div>
270
- `;
271
- }
272
-
273
- /**
274
- * Load queue data
275
- */
276
- async loadQueueData() {
277
- try {
278
- const response = await window.tasksAPI.getQueueStatus();
279
- const data = response.data || response;
280
- this.updateQueuesContainer(data);
281
- } catch (error) {
282
- console.error('Failed to load queue data:', error);
283
- this.showError('Failed to load queue data');
284
- }
285
- }
286
-
287
- /**
288
- * Update queues container
289
- * @param {Object} data - Queue data
290
- */
291
- updateQueuesContainer(data) {
292
- const container = document.getElementById('queues-container');
293
- if (!container || !data.queues) return;
294
-
295
- const queuesHtml = Object.entries(data.queues).map(([name, queue]) => `
296
- <div class="border border-gray-200 dark:border-gray-700 rounded-lg p-4 mb-4">
297
- <div class="flex items-center justify-between mb-2">
298
- <h3 class="font-medium text-gray-900 dark:text-white">${name}</h3>
299
- <span class="px-2 py-1 text-xs rounded-full ${queue.size > 0 ? 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200' : 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200'}">
300
- ${queue.size || 0} tasks
301
- </span>
302
- </div>
303
- <div class="text-sm text-gray-600 dark:text-gray-400">
304
- <p>Size: ${queue.size || 0}</p>
305
- <p>Status: ${queue.size > 0 ? 'Active' : 'Empty'}</p>
306
- </div>
307
- </div>
308
- `).join('');
309
-
310
- container.innerHTML = queuesHtml || '<p class="text-gray-500 dark:text-gray-400">No queues configured</p>';
311
- }
312
-
313
- /**
314
- * Load worker data
315
- */
316
- async loadWorkerData() {
317
- try {
318
- const response = await window.tasksAPI.getQueueStatus();
319
- const data = response.data || response;
320
- this.updateWorkersContainer(data);
321
- } catch (error) {
322
- console.error('Failed to load worker data:', error);
323
- this.showError('Failed to load worker data');
324
- }
325
- }
326
-
327
- /**
328
- * Update workers container
329
- * @param {Object} data - Worker data
330
- */
331
- updateWorkersContainer(data) {
332
- const container = document.getElementById('workers-container');
333
- if (!container) return;
334
-
335
- if (data.workers && data.workers.length > 0) {
336
- const workersHtml = data.workers.map(worker => `
337
- <div class="border border-gray-200 dark:border-gray-700 rounded-lg p-4 mb-4">
338
- <div class="flex items-center justify-between">
339
- <div>
340
- <h3 class="font-medium text-gray-900 dark:text-white">Worker ${worker.id || 'Unknown'}</h3>
341
- <p class="text-sm text-gray-600 dark:text-gray-400">Status: ${worker.status || 'Active'}</p>
342
- </div>
343
- <span class="px-2 py-1 text-xs rounded-full bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200">
344
- Running
345
- </span>
346
- </div>
347
- </div>
348
- `).join('');
349
-
350
- container.innerHTML = workersHtml;
351
- } else {
352
- container.innerHTML = '<p class="text-gray-500 dark:text-gray-400">No active workers</p>';
353
- }
354
- }
355
-
356
- /**
357
- * Load task data
358
- */
359
- async loadTaskData() {
360
- try {
361
- const response = await window.tasksAPI.getTaskStatistics();
362
- const data = response.data || response;
363
- this.updateTasksContainer(data);
364
- } catch (error) {
365
- console.error('Failed to load task data:', error);
366
- this.showError('Failed to load task data');
367
- }
368
- }
369
-
370
- /**
371
- * Update tasks container
372
- * @param {Object} data - Task data
373
- */
374
- updateTasksContainer(data) {
375
- const container = document.getElementById('tasks-container');
376
- if (!container) return;
377
-
378
- if (data.recent_tasks && data.recent_tasks.length > 0) {
379
- const tasksHtml = data.recent_tasks.map(task => `
380
- <div class="border border-gray-200 dark:border-gray-700 rounded-lg p-4 mb-4">
381
- <div class="flex items-center justify-between">
382
- <div>
383
- <h3 class="font-medium text-gray-900 dark:text-white">${task.actor_name || 'Unknown Task'}</h3>
384
- <p class="text-sm text-gray-600 dark:text-gray-400">
385
- Created: ${new Date(task.created_at).toLocaleString()}
386
- </p>
387
- </div>
388
- <span class="px-2 py-1 text-xs rounded-full ${this.getStatusColor(task.status)}">
389
- ${task.status || 'Unknown'}
390
- </span>
391
- </div>
392
- </div>
393
- `).join('');
394
-
395
- container.innerHTML = tasksHtml;
396
- } else {
397
- container.innerHTML = '<p class="text-gray-500 dark:text-gray-400">No recent tasks</p>';
398
- }
399
- }
400
-
401
- /**
402
- * Get status color classes
403
- * @param {string} status - Task status
404
- * @returns {string} CSS classes
405
- */
406
- getStatusColor(status) {
407
- switch (status) {
408
- case 'done':
409
- return 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200';
410
- case 'failed':
411
- return 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200';
412
- case 'running':
413
- return 'bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200';
414
- case 'pending':
415
- return 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200';
416
- default:
417
- return 'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-200';
418
- }
419
- }
420
-
421
- /**
422
- * Start workers
423
- */
424
- async startWorkers() {
425
- try {
426
- const processes = document.getElementById('worker-processes')?.value || 1;
427
- const threads = document.getElementById('worker-threads')?.value || 4;
428
-
429
- await window.tasksAPI.startWorkers({ processes, threads });
430
- this.showSuccess('Workers started successfully');
431
- this.loadTabData(this.currentTab);
432
- } catch (error) {
433
- console.error('Failed to start workers:', error);
434
- this.showError('Failed to start workers');
435
- }
436
- }
437
-
438
- /**
439
- * Stop workers
440
- */
441
- async stopWorkers() {
442
- try {
443
- await window.tasksAPI.stopWorkers();
444
- this.showSuccess('Workers stopped successfully');
445
- this.loadTabData(this.currentTab);
446
- } catch (error) {
447
- console.error('Failed to stop workers:', error);
448
- this.showError('Failed to stop workers');
449
- }
450
- }
451
-
452
- /**
453
- * Clear all queues
454
- */
455
- async clearQueues() {
456
- if (!confirm('Are you sure you want to clear all queues? This will remove all pending tasks.')) {
457
- return;
458
- }
459
-
460
- try {
461
- await window.tasksAPI.clearQueues();
462
- this.showSuccess('Queues cleared successfully');
463
- this.loadTabData(this.currentTab);
464
- } catch (error) {
465
- console.error('Failed to clear queues:', error);
466
- this.showError('Failed to clear queues');
467
- }
468
- }
469
-
470
- /**
471
- * Clear all queues (from management actions)
472
- */
473
- async clearAllQueues() {
474
- if (!confirm('Are you sure you want to clear all queues? This will remove all pending tasks.')) {
475
- return;
476
- }
477
-
478
- try {
479
- this.showManagementActionStatus('Clearing all queues...', 'info');
480
- await window.tasksAPI.clearQueues();
481
- this.showManagementActionStatus('✅ All queues cleared successfully', 'success');
482
- this.loadTabData(this.currentTab);
483
- } catch (error) {
484
- console.error('Failed to clear queues:', error);
485
- this.showManagementActionStatus('❌ Failed to clear queues', 'error');
486
- }
487
- }
488
-
489
- /**
490
- * Purge failed tasks
491
- */
492
- async purgeFailedTasks() {
493
- if (!confirm('Are you sure you want to purge all failed tasks?')) {
494
- return;
495
- }
496
-
497
- try {
498
- // Check if called from management actions
499
- const isFromManagementActions = event && event.target && event.target.id === 'purge-failed-tasks-btn';
500
-
501
- if (isFromManagementActions) {
502
- this.showManagementActionStatus('Purging failed tasks...', 'info');
503
- }
504
-
505
- await window.tasksAPI.purgeFailedTasks();
506
-
507
- if (isFromManagementActions) {
508
- this.showManagementActionStatus('✅ Failed tasks purged successfully', 'success');
509
- } else {
510
- this.showSuccess('Failed tasks purged successfully');
511
- }
512
-
513
- this.loadTabData(this.currentTab);
514
- } catch (error) {
515
- console.error('Failed to purge failed tasks:', error);
516
-
517
- const isFromManagementActions = event && event.target && event.target.id === 'purge-failed-tasks-btn';
518
- if (isFromManagementActions) {
519
- this.showManagementActionStatus('❌ Failed to purge failed tasks', 'error');
520
- } else {
521
- this.showError('Failed to purge failed tasks');
522
- }
523
- }
524
- }
525
-
526
- /**
527
- * Start auto refresh
528
- */
529
- startAutoRefresh() {
530
- this.refreshInterval = setInterval(() => {
531
- this.loadTabData(this.currentTab);
532
- }, this.refreshRate);
533
- }
534
-
535
- /**
536
- * Stop auto refresh
537
- */
538
- stopAutoRefresh() {
539
- if (this.refreshInterval) {
540
- clearInterval(this.refreshInterval);
541
- this.refreshInterval = null;
542
- }
543
- }
544
-
545
- /**
546
- * Show success message
547
- * @param {string} message - Success message
548
- */
549
- showSuccess(message) {
550
- // Simple implementation - can be enhanced with toast notifications
551
- console.log('Success:', message);
552
- alert(message);
553
- }
554
-
555
- /**
556
- * Show error message
557
- * @param {string} message - Error message
558
- */
559
- showError(message) {
560
- // Simple implementation - can be enhanced with toast notifications
561
- console.error('Error:', message);
562
- alert(`Error: ${message}`);
563
- }
564
-
565
- /**
566
- * Show management action status
567
- * @param {string} message - Status message
568
- * @param {string} type - Status type (info, success, error)
569
- */
570
- showManagementActionStatus(message, type = 'info') {
571
- const statusContainer = document.getElementById('management-action-status');
572
- const messageElement = document.getElementById('management-action-message');
573
-
574
- if (!statusContainer || !messageElement) {
575
- return;
576
- }
577
-
578
- // Update message
579
- messageElement.textContent = message;
580
-
581
- // Update styling based on type
582
- statusContainer.className = 'mt-4';
583
- const statusDiv = statusContainer.querySelector('div');
584
-
585
- if (type === 'success') {
586
- statusDiv.className = 'p-3 rounded-lg bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800';
587
- statusDiv.querySelector('.material-icons').className = 'material-icons text-green-600 dark:text-green-400 mr-2';
588
- messageElement.className = 'text-sm text-green-800 dark:text-green-200';
589
- } else if (type === 'error') {
590
- statusDiv.className = 'p-3 rounded-lg bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800';
591
- statusDiv.querySelector('.material-icons').className = 'material-icons text-red-600 dark:text-red-400 mr-2';
592
- messageElement.className = 'text-sm text-red-800 dark:text-red-200';
593
- } else {
594
- statusDiv.className = 'p-3 rounded-lg bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800';
595
- statusDiv.querySelector('.material-icons').className = 'material-icons text-blue-600 dark:text-blue-400 mr-2';
596
- messageElement.className = 'text-sm text-blue-800 dark:text-blue-200';
597
- }
598
-
599
- // Show status
600
- statusContainer.classList.remove('hidden');
601
-
602
- // Auto-hide after 5 seconds for success/error messages
603
- if (type === 'success' || type === 'error') {
604
- setTimeout(() => {
605
- statusContainer.classList.add('hidden');
606
- }, 5000);
607
- }
608
- }
609
- }
610
-
611
- // Initialize dashboard when DOM is loaded
612
- document.addEventListener('DOMContentLoaded', () => {
613
- window.dashboard = new TasksDashboard();
614
- });