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