django-cfg 1.3.7__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 (246) hide show
  1. django_cfg/__init__.py +1 -1
  2. django_cfg/apps/accounts/admin/__init__.py +24 -8
  3. django_cfg/apps/accounts/admin/activity_admin.py +146 -0
  4. django_cfg/apps/accounts/admin/filters.py +98 -22
  5. django_cfg/apps/accounts/admin/group_admin.py +86 -0
  6. django_cfg/apps/accounts/admin/inlines.py +42 -13
  7. django_cfg/apps/accounts/admin/otp_admin.py +115 -0
  8. django_cfg/apps/accounts/admin/registration_admin.py +173 -0
  9. django_cfg/apps/accounts/admin/resources.py +123 -19
  10. django_cfg/apps/accounts/admin/twilio_admin.py +327 -0
  11. django_cfg/apps/accounts/admin/user_admin.py +362 -0
  12. django_cfg/apps/agents/admin/__init__.py +17 -4
  13. django_cfg/apps/agents/admin/execution_admin.py +204 -183
  14. django_cfg/apps/agents/admin/registry_admin.py +230 -255
  15. django_cfg/apps/agents/admin/toolsets_admin.py +274 -321
  16. django_cfg/apps/agents/core/__init__.py +1 -1
  17. django_cfg/apps/agents/core/django_agent.py +221 -0
  18. django_cfg/apps/agents/core/exceptions.py +14 -0
  19. django_cfg/apps/agents/core/orchestrator.py +18 -3
  20. django_cfg/apps/knowbase/admin/__init__.py +1 -1
  21. django_cfg/apps/knowbase/admin/archive_admin.py +352 -640
  22. django_cfg/apps/knowbase/admin/chat_admin.py +258 -192
  23. django_cfg/apps/knowbase/admin/document_admin.py +269 -262
  24. django_cfg/apps/knowbase/admin/external_data_admin.py +271 -489
  25. django_cfg/apps/knowbase/config/settings.py +21 -4
  26. django_cfg/apps/knowbase/views/chat_views.py +3 -0
  27. django_cfg/apps/leads/admin/__init__.py +3 -1
  28. django_cfg/apps/leads/admin/leads_admin.py +235 -35
  29. django_cfg/apps/maintenance/admin/__init__.py +2 -2
  30. django_cfg/apps/maintenance/admin/api_key_admin.py +125 -63
  31. django_cfg/apps/maintenance/admin/log_admin.py +143 -61
  32. django_cfg/apps/maintenance/admin/scheduled_admin.py +212 -301
  33. django_cfg/apps/maintenance/admin/site_admin.py +213 -352
  34. django_cfg/apps/newsletter/admin/__init__.py +29 -2
  35. django_cfg/apps/newsletter/admin/newsletter_admin.py +531 -193
  36. django_cfg/apps/payments/admin/__init__.py +18 -27
  37. django_cfg/apps/payments/admin/api_keys_admin.py +179 -546
  38. django_cfg/apps/payments/admin/balance_admin.py +166 -632
  39. django_cfg/apps/payments/admin/currencies_admin.py +235 -607
  40. django_cfg/apps/payments/admin/endpoint_groups_admin.py +127 -0
  41. django_cfg/apps/payments/admin/filters.py +83 -3
  42. django_cfg/apps/payments/admin/networks_admin.py +269 -0
  43. django_cfg/apps/payments/admin/payments_admin.py +183 -460
  44. django_cfg/apps/payments/admin/subscriptions_admin.py +119 -636
  45. django_cfg/apps/payments/admin/tariffs_admin.py +248 -0
  46. django_cfg/apps/payments/admin_interface/serializers/payment_serializers.py +153 -34
  47. django_cfg/apps/payments/admin_interface/templates/payments/components/payment_card.html +121 -0
  48. django_cfg/apps/payments/admin_interface/templates/payments/components/payment_qr_code.html +95 -0
  49. django_cfg/apps/payments/admin_interface/templates/payments/components/progress_bar.html +37 -0
  50. django_cfg/apps/payments/admin_interface/templates/payments/components/provider_stats.html +60 -0
  51. django_cfg/apps/payments/admin_interface/templates/payments/components/status_badge.html +41 -0
  52. django_cfg/apps/payments/admin_interface/templates/payments/components/status_overview.html +83 -0
  53. django_cfg/apps/payments/admin_interface/templates/payments/payment_detail.html +363 -0
  54. django_cfg/apps/payments/admin_interface/templates/payments/payment_form.html +43 -17
  55. django_cfg/apps/payments/admin_interface/views/__init__.py +2 -0
  56. django_cfg/apps/payments/admin_interface/views/api/payments.py +102 -0
  57. django_cfg/apps/payments/admin_interface/views/api/webhook_admin.py +109 -63
  58. django_cfg/apps/payments/admin_interface/views/forms.py +5 -1
  59. django_cfg/apps/payments/config/__init__.py +14 -15
  60. django_cfg/apps/payments/config/django_cfg_integration.py +59 -1
  61. django_cfg/apps/payments/config/helpers.py +8 -13
  62. django_cfg/apps/payments/management/commands/manage_currencies.py +236 -274
  63. django_cfg/apps/payments/management/commands/manage_providers.py +4 -1
  64. django_cfg/apps/payments/middleware/api_access.py +32 -6
  65. django_cfg/apps/payments/migrations/0001_initial.py +33 -46
  66. django_cfg/apps/payments/migrations/0002_rename_payments_un_user_id_7f6e79_idx_payments_un_user_id_8ce187_idx_and_more.py +46 -0
  67. django_cfg/apps/payments/migrations/0003_universalpayment_status_changed_at.py +25 -0
  68. django_cfg/apps/payments/models/balance.py +12 -0
  69. django_cfg/apps/payments/models/currencies.py +106 -32
  70. django_cfg/apps/payments/models/managers/currency_managers.py +65 -0
  71. django_cfg/apps/payments/models/managers/payment_managers.py +142 -25
  72. django_cfg/apps/payments/models/payments.py +94 -0
  73. django_cfg/apps/payments/services/core/base.py +4 -4
  74. django_cfg/apps/payments/services/core/currency_service.py +35 -28
  75. django_cfg/apps/payments/services/core/payment_service.py +266 -39
  76. django_cfg/apps/payments/services/providers/__init__.py +3 -0
  77. django_cfg/apps/payments/services/providers/base.py +303 -41
  78. django_cfg/apps/payments/services/providers/models/__init__.py +42 -0
  79. django_cfg/apps/payments/services/providers/models/base.py +145 -0
  80. django_cfg/apps/payments/services/providers/models/providers.py +87 -0
  81. django_cfg/apps/payments/services/providers/models/universal.py +48 -0
  82. django_cfg/apps/payments/services/providers/nowpayments/__init__.py +31 -0
  83. django_cfg/apps/payments/services/providers/nowpayments/config.py +70 -0
  84. django_cfg/apps/payments/services/providers/nowpayments/models.py +150 -0
  85. django_cfg/apps/payments/services/providers/nowpayments/parsers.py +879 -0
  86. django_cfg/apps/payments/services/providers/nowpayments/provider.py +557 -0
  87. django_cfg/apps/payments/services/providers/nowpayments/sync.py +196 -0
  88. django_cfg/apps/payments/services/providers/registry.py +9 -37
  89. django_cfg/apps/payments/services/providers/sync_service.py +277 -0
  90. django_cfg/apps/payments/services/types/requests.py +19 -7
  91. django_cfg/apps/payments/signals/payment_signals.py +31 -2
  92. django_cfg/apps/payments/static/payments/js/api-client.js +29 -6
  93. django_cfg/apps/payments/static/payments/js/payment-detail.js +167 -0
  94. django_cfg/apps/payments/static/payments/js/payment-form.js +98 -32
  95. django_cfg/apps/payments/tasks/__init__.py +39 -0
  96. django_cfg/apps/payments/tasks/types.py +73 -0
  97. django_cfg/apps/payments/tasks/usage_tracking.py +308 -0
  98. django_cfg/apps/payments/templates/admin/payments/_components/dashboard_header.html +23 -0
  99. django_cfg/apps/payments/templates/admin/payments/_components/stats_card.html +25 -0
  100. django_cfg/apps/payments/templates/admin/payments/_components/stats_grid.html +16 -0
  101. django_cfg/apps/payments/templates/admin/payments/apikey/change_list.html +39 -0
  102. django_cfg/apps/payments/templates/admin/payments/balance/change_list.html +50 -0
  103. django_cfg/apps/payments/templates/admin/payments/currency/change_list.html +40 -0
  104. django_cfg/apps/payments/templates/admin/payments/payment/change_list.html +48 -0
  105. django_cfg/apps/payments/templates/admin/payments/subscription/change_list.html +48 -0
  106. django_cfg/apps/payments/templatetags/payment_tags.py +8 -0
  107. django_cfg/apps/payments/urls.py +3 -2
  108. django_cfg/apps/payments/urls_admin.py +1 -1
  109. django_cfg/apps/payments/views/api/currencies.py +8 -5
  110. django_cfg/apps/payments/views/overview/services.py +2 -2
  111. django_cfg/apps/payments/views/serializers/currencies.py +22 -8
  112. django_cfg/apps/support/admin/__init__.py +10 -1
  113. django_cfg/apps/support/admin/support_admin.py +338 -141
  114. django_cfg/apps/tasks/admin/__init__.py +11 -0
  115. django_cfg/apps/tasks/admin/tasks_admin.py +430 -0
  116. django_cfg/apps/tasks/static/tasks/css/dashboard.css +68 -217
  117. django_cfg/apps/tasks/static/tasks/js/api.js +40 -84
  118. django_cfg/apps/tasks/static/tasks/js/components/DataManager.js +24 -0
  119. django_cfg/apps/tasks/static/tasks/js/components/TabManager.js +85 -0
  120. django_cfg/apps/tasks/static/tasks/js/components/TaskRenderer.js +216 -0
  121. django_cfg/apps/tasks/static/tasks/js/dashboard/main.mjs +245 -0
  122. django_cfg/apps/tasks/static/tasks/js/dashboard/overview.mjs +123 -0
  123. django_cfg/apps/tasks/static/tasks/js/dashboard/queues.mjs +120 -0
  124. django_cfg/apps/tasks/static/tasks/js/dashboard/tasks.mjs +350 -0
  125. django_cfg/apps/tasks/static/tasks/js/dashboard/workers.mjs +169 -0
  126. django_cfg/apps/tasks/tasks/__init__.py +10 -0
  127. django_cfg/apps/tasks/tasks/demo_tasks.py +133 -0
  128. django_cfg/apps/tasks/templates/tasks/components/management_actions.html +42 -45
  129. django_cfg/apps/tasks/templates/tasks/components/{status_cards.html → overview_content.html} +30 -11
  130. django_cfg/apps/tasks/templates/tasks/components/queues_content.html +19 -0
  131. django_cfg/apps/tasks/templates/tasks/components/tab_navigation.html +16 -10
  132. django_cfg/apps/tasks/templates/tasks/components/tasks_content.html +51 -0
  133. django_cfg/apps/tasks/templates/tasks/components/workers_content.html +30 -0
  134. django_cfg/apps/tasks/templates/tasks/layout/base.html +117 -0
  135. django_cfg/apps/tasks/templates/tasks/pages/dashboard.html +82 -0
  136. django_cfg/apps/tasks/templates/tasks/partials/task_row_template.html +40 -0
  137. django_cfg/apps/tasks/templates/tasks/widgets/task_filters.html +37 -0
  138. django_cfg/apps/tasks/templates/tasks/widgets/task_footer.html +41 -0
  139. django_cfg/apps/tasks/templates/tasks/widgets/task_table.html +50 -0
  140. django_cfg/apps/tasks/urls.py +2 -2
  141. django_cfg/apps/tasks/urls_admin.py +2 -2
  142. django_cfg/apps/tasks/utils/__init__.py +1 -0
  143. django_cfg/apps/tasks/utils/simulator.py +356 -0
  144. django_cfg/apps/tasks/views/__init__.py +16 -0
  145. django_cfg/apps/tasks/views/api.py +569 -0
  146. django_cfg/apps/tasks/views/dashboard.py +58 -0
  147. django_cfg/config.py +1 -1
  148. django_cfg/core/config.py +10 -5
  149. django_cfg/core/generation.py +1 -1
  150. django_cfg/core/integration/__init__.py +21 -0
  151. django_cfg/management/commands/__init__.py +13 -1
  152. django_cfg/management/commands/migrate_all.py +9 -3
  153. django_cfg/management/commands/migrator.py +11 -6
  154. django_cfg/management/commands/rundramatiq.py +3 -2
  155. django_cfg/management/commands/rundramatiq_simulator.py +430 -0
  156. django_cfg/middleware/__init__.py +0 -2
  157. django_cfg/models/api_keys.py +115 -0
  158. django_cfg/models/constance.py +0 -11
  159. django_cfg/models/payments.py +137 -3
  160. django_cfg/modules/django_admin/__init__.py +64 -0
  161. django_cfg/modules/django_admin/decorators/__init__.py +13 -0
  162. django_cfg/modules/django_admin/decorators/actions.py +106 -0
  163. django_cfg/modules/django_admin/decorators/display.py +106 -0
  164. django_cfg/modules/django_admin/mixins/__init__.py +14 -0
  165. django_cfg/modules/django_admin/mixins/display_mixin.py +81 -0
  166. django_cfg/modules/django_admin/mixins/optimization_mixin.py +41 -0
  167. django_cfg/modules/django_admin/mixins/standalone_actions_mixin.py +202 -0
  168. django_cfg/modules/django_admin/models/__init__.py +20 -0
  169. django_cfg/modules/django_admin/models/action_models.py +33 -0
  170. django_cfg/modules/django_admin/models/badge_models.py +20 -0
  171. django_cfg/modules/django_admin/models/base.py +26 -0
  172. django_cfg/modules/django_admin/models/display_models.py +31 -0
  173. django_cfg/modules/django_admin/utils/badges.py +159 -0
  174. django_cfg/modules/django_admin/utils/displays.py +247 -0
  175. django_cfg/modules/django_currency/__init__.py +2 -2
  176. django_cfg/modules/django_currency/clients/__init__.py +2 -2
  177. django_cfg/modules/django_currency/clients/hybrid_client.py +587 -0
  178. django_cfg/modules/django_currency/core/converter.py +12 -12
  179. django_cfg/modules/django_currency/database/__init__.py +2 -2
  180. django_cfg/modules/django_currency/database/database_loader.py +93 -42
  181. django_cfg/modules/django_llm/llm/client.py +10 -2
  182. django_cfg/modules/django_tasks.py +54 -21
  183. django_cfg/modules/django_unfold/callbacks/actions.py +1 -1
  184. django_cfg/modules/django_unfold/callbacks/statistics.py +1 -1
  185. django_cfg/modules/django_unfold/dashboard.py +14 -13
  186. django_cfg/modules/django_unfold/models/config.py +1 -1
  187. django_cfg/registry/core.py +7 -9
  188. django_cfg/registry/third_party.py +2 -2
  189. django_cfg/template_archive/django_sample.zip +0 -0
  190. {django_cfg-1.3.7.dist-info → django_cfg-1.3.11.dist-info}/METADATA +2 -1
  191. {django_cfg-1.3.7.dist-info → django_cfg-1.3.11.dist-info}/RECORD +198 -160
  192. django_cfg/apps/accounts/admin/activity.py +0 -96
  193. django_cfg/apps/accounts/admin/group.py +0 -17
  194. django_cfg/apps/accounts/admin/otp.py +0 -59
  195. django_cfg/apps/accounts/admin/registration_source.py +0 -97
  196. django_cfg/apps/accounts/admin/twilio_response.py +0 -227
  197. django_cfg/apps/accounts/admin/user.py +0 -300
  198. django_cfg/apps/agents/core/agent.py +0 -281
  199. django_cfg/apps/payments/admin_interface/old/payments/base.html +0 -175
  200. django_cfg/apps/payments/admin_interface/old/payments/components/dev_tool_card.html +0 -125
  201. django_cfg/apps/payments/admin_interface/old/payments/components/loading_spinner.html +0 -16
  202. django_cfg/apps/payments/admin_interface/old/payments/components/ngrok_status_card.html +0 -113
  203. django_cfg/apps/payments/admin_interface/old/payments/components/notification.html +0 -27
  204. django_cfg/apps/payments/admin_interface/old/payments/components/provider_card.html +0 -86
  205. django_cfg/apps/payments/admin_interface/old/payments/components/status_card.html +0 -35
  206. django_cfg/apps/payments/admin_interface/old/payments/currency_converter.html +0 -382
  207. django_cfg/apps/payments/admin_interface/old/payments/payment_dashboard.html +0 -309
  208. django_cfg/apps/payments/admin_interface/old/payments/payment_form.html +0 -303
  209. django_cfg/apps/payments/admin_interface/old/payments/payment_list.html +0 -382
  210. django_cfg/apps/payments/admin_interface/old/payments/payment_status.html +0 -500
  211. django_cfg/apps/payments/admin_interface/old/payments/webhook_dashboard.html +0 -518
  212. django_cfg/apps/payments/admin_interface/old/static/payments/css/components.css +0 -619
  213. django_cfg/apps/payments/admin_interface/old/static/payments/css/dashboard.css +0 -188
  214. django_cfg/apps/payments/admin_interface/old/static/payments/js/components.js +0 -545
  215. django_cfg/apps/payments/admin_interface/old/static/payments/js/ngrok-status.js +0 -163
  216. django_cfg/apps/payments/admin_interface/old/static/payments/js/utils.js +0 -412
  217. django_cfg/apps/payments/config/constance/__init__.py +0 -22
  218. django_cfg/apps/payments/config/constance/config_service.py +0 -123
  219. django_cfg/apps/payments/config/constance/fields.py +0 -69
  220. django_cfg/apps/payments/config/constance/settings.py +0 -160
  221. django_cfg/apps/payments/services/providers/nowpayments.py +0 -478
  222. django_cfg/apps/tasks/admin.py +0 -320
  223. django_cfg/apps/tasks/static/tasks/js/dashboard.js +0 -614
  224. django_cfg/apps/tasks/static/tasks/js/modals.js +0 -452
  225. django_cfg/apps/tasks/static/tasks/js/notifications.js +0 -144
  226. django_cfg/apps/tasks/static/tasks/js/task-monitor.js +0 -454
  227. django_cfg/apps/tasks/static/tasks/js/theme.js +0 -77
  228. django_cfg/apps/tasks/templates/tasks/base.html +0 -96
  229. django_cfg/apps/tasks/templates/tasks/components/info_cards.html +0 -85
  230. django_cfg/apps/tasks/templates/tasks/components/overview_tab.html +0 -22
  231. django_cfg/apps/tasks/templates/tasks/components/queues_tab.html +0 -19
  232. django_cfg/apps/tasks/templates/tasks/components/task_details_modal.html +0 -103
  233. django_cfg/apps/tasks/templates/tasks/components/tasks_tab.html +0 -32
  234. django_cfg/apps/tasks/templates/tasks/components/workers_tab.html +0 -29
  235. django_cfg/apps/tasks/templates/tasks/dashboard.html +0 -29
  236. django_cfg/apps/tasks/views.py +0 -461
  237. django_cfg/management/commands/auto_generate.py +0 -486
  238. django_cfg/middleware/static_nocache.py +0 -55
  239. django_cfg/modules/django_currency/clients/yahoo_client.py +0 -157
  240. /django_cfg/modules/{django_unfold → django_admin}/icons/README.md +0 -0
  241. /django_cfg/modules/{django_unfold → django_admin}/icons/__init__.py +0 -0
  242. /django_cfg/modules/{django_unfold → django_admin}/icons/constants.py +0 -0
  243. /django_cfg/modules/{django_unfold → django_admin}/icons/generate_icons.py +0 -0
  244. {django_cfg-1.3.7.dist-info → django_cfg-1.3.11.dist-info}/WHEEL +0 -0
  245. {django_cfg-1.3.7.dist-info → django_cfg-1.3.11.dist-info}/entry_points.txt +0 -0
  246. {django_cfg-1.3.7.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
- });