django-cfg 1.3.9__py3-none-any.whl → 1.3.13__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- django_cfg/__init__.py +1 -1
- django_cfg/apps/accounts/admin/inlines.py +11 -5
- django_cfg/apps/payments/admin/networks_admin.py +12 -1
- django_cfg/apps/payments/admin/payments_admin.py +13 -0
- django_cfg/apps/payments/admin_interface/serializers/payment_serializers.py +62 -14
- django_cfg/apps/payments/admin_interface/templates/payments/components/payment_card.html +121 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/payment_qr_code.html +95 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/progress_bar.html +37 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/provider_stats.html +60 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/status_badge.html +41 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/status_overview.html +83 -0
- django_cfg/apps/payments/admin_interface/templates/payments/payment_detail.html +363 -0
- django_cfg/apps/payments/admin_interface/templates/payments/payment_form.html +33 -3
- django_cfg/apps/payments/admin_interface/views/api/payments.py +102 -0
- django_cfg/apps/payments/admin_interface/views/api/webhook_admin.py +96 -45
- django_cfg/apps/payments/admin_interface/views/forms.py +5 -1
- django_cfg/apps/payments/config/__init__.py +14 -15
- django_cfg/apps/payments/config/django_cfg_integration.py +59 -1
- django_cfg/apps/payments/config/helpers.py +8 -13
- django_cfg/apps/payments/migrations/0001_initial.py +33 -46
- django_cfg/apps/payments/migrations/0002_rename_payments_un_user_id_7f6e79_idx_payments_un_user_id_8ce187_idx_and_more.py +46 -0
- django_cfg/apps/payments/migrations/0003_universalpayment_status_changed_at.py +25 -0
- django_cfg/apps/payments/models/managers/payment_managers.py +142 -25
- django_cfg/apps/payments/models/payments.py +94 -0
- django_cfg/apps/payments/services/core/base.py +4 -4
- django_cfg/apps/payments/services/core/payment_service.py +265 -38
- django_cfg/apps/payments/services/providers/base.py +209 -3
- django_cfg/apps/payments/services/providers/models/__init__.py +2 -0
- django_cfg/apps/payments/services/providers/models/base.py +25 -2
- django_cfg/apps/payments/services/providers/nowpayments/models.py +2 -2
- django_cfg/apps/payments/services/providers/nowpayments/provider.py +57 -9
- django_cfg/apps/payments/services/providers/registry.py +5 -5
- django_cfg/apps/payments/services/types/requests.py +19 -7
- django_cfg/apps/payments/signals/payment_signals.py +31 -2
- django_cfg/apps/payments/static/payments/js/api-client.js +6 -1
- django_cfg/apps/payments/static/payments/js/payment-detail.js +167 -0
- django_cfg/apps/payments/static/payments/js/payment-form.js +35 -26
- django_cfg/apps/payments/templatetags/payment_tags.py +8 -0
- django_cfg/apps/payments/urls.py +3 -2
- django_cfg/apps/payments/views/api/currencies.py +3 -0
- django_cfg/apps/payments/views/serializers/currencies.py +18 -5
- django_cfg/apps/tasks/admin/tasks_admin.py +2 -2
- django_cfg/apps/tasks/static/tasks/css/dashboard.css +68 -217
- django_cfg/apps/tasks/static/tasks/js/api.js +40 -84
- django_cfg/apps/tasks/static/tasks/js/components/DataManager.js +24 -0
- django_cfg/apps/tasks/static/tasks/js/components/TabManager.js +85 -0
- django_cfg/apps/tasks/static/tasks/js/components/TaskRenderer.js +216 -0
- django_cfg/apps/tasks/static/tasks/js/dashboard/main.mjs +245 -0
- django_cfg/apps/tasks/static/tasks/js/dashboard/overview.mjs +123 -0
- django_cfg/apps/tasks/static/tasks/js/dashboard/queues.mjs +120 -0
- django_cfg/apps/tasks/static/tasks/js/dashboard/tasks.mjs +350 -0
- django_cfg/apps/tasks/static/tasks/js/dashboard/workers.mjs +169 -0
- django_cfg/apps/tasks/tasks/__init__.py +10 -0
- django_cfg/apps/tasks/tasks/demo_tasks.py +133 -0
- django_cfg/apps/tasks/templates/tasks/components/management_actions.html +42 -45
- django_cfg/apps/tasks/templates/tasks/components/{status_cards.html → overview_content.html} +30 -11
- django_cfg/apps/tasks/templates/tasks/components/queues_content.html +19 -0
- django_cfg/apps/tasks/templates/tasks/components/tab_navigation.html +16 -10
- django_cfg/apps/tasks/templates/tasks/components/tasks_content.html +51 -0
- django_cfg/apps/tasks/templates/tasks/components/workers_content.html +30 -0
- django_cfg/apps/tasks/templates/tasks/layout/base.html +117 -0
- django_cfg/apps/tasks/templates/tasks/pages/dashboard.html +82 -0
- django_cfg/apps/tasks/templates/tasks/partials/task_row_template.html +40 -0
- django_cfg/apps/tasks/templates/tasks/widgets/task_filters.html +37 -0
- django_cfg/apps/tasks/templates/tasks/widgets/task_footer.html +41 -0
- django_cfg/apps/tasks/templates/tasks/widgets/task_table.html +50 -0
- django_cfg/apps/tasks/urls.py +2 -2
- django_cfg/apps/tasks/urls_admin.py +2 -2
- django_cfg/apps/tasks/utils/__init__.py +1 -0
- django_cfg/apps/tasks/utils/simulator.py +356 -0
- django_cfg/apps/tasks/views/__init__.py +16 -0
- django_cfg/apps/tasks/views/api.py +569 -0
- django_cfg/apps/tasks/views/dashboard.py +58 -0
- django_cfg/core/integration/__init__.py +21 -0
- django_cfg/management/commands/rundramatiq_simulator.py +430 -0
- django_cfg/models/constance.py +0 -11
- django_cfg/models/payments.py +137 -3
- django_cfg/modules/django_tasks.py +54 -21
- django_cfg/registry/core.py +4 -9
- django_cfg/template_archive/django_sample.zip +0 -0
- {django_cfg-1.3.9.dist-info → django_cfg-1.3.13.dist-info}/METADATA +2 -2
- {django_cfg-1.3.9.dist-info → django_cfg-1.3.13.dist-info}/RECORD +85 -153
- django_cfg/apps/payments/config/constance/__init__.py +0 -22
- django_cfg/apps/payments/config/constance/config_service.py +0 -123
- django_cfg/apps/payments/config/constance/fields.py +0 -69
- django_cfg/apps/payments/config/constance/settings.py +0 -160
- django_cfg/apps/payments/migrations/0002_currency_usd_rate_currency_usd_rate_updated_at.py +0 -26
- django_cfg/apps/payments/migrations/0003_remove_provider_currency_fields.py +0 -28
- django_cfg/apps/payments/migrations/0004_add_reserved_usd_field.py +0 -30
- django_cfg/apps/tasks/static/tasks/js/dashboard.js +0 -614
- django_cfg/apps/tasks/static/tasks/js/modals.js +0 -452
- django_cfg/apps/tasks/static/tasks/js/notifications.js +0 -144
- django_cfg/apps/tasks/static/tasks/js/task-monitor.js +0 -454
- django_cfg/apps/tasks/static/tasks/js/theme.js +0 -77
- django_cfg/apps/tasks/templates/tasks/base.html +0 -96
- django_cfg/apps/tasks/templates/tasks/components/info_cards.html +0 -85
- django_cfg/apps/tasks/templates/tasks/components/overview_tab.html +0 -22
- django_cfg/apps/tasks/templates/tasks/components/queues_tab.html +0 -19
- django_cfg/apps/tasks/templates/tasks/components/task_details_modal.html +0 -103
- django_cfg/apps/tasks/templates/tasks/components/tasks_tab.html +0 -32
- django_cfg/apps/tasks/templates/tasks/components/workers_tab.html +0 -29
- django_cfg/apps/tasks/templates/tasks/dashboard.html +0 -29
- django_cfg/apps/tasks/views.py +0 -461
- django_cfg/management/commands/app_agent_diagnose.py +0 -470
- django_cfg/management/commands/app_agent_generate.py +0 -342
- django_cfg/management/commands/app_agent_info.py +0 -308
- django_cfg/management/commands/auto_generate.py +0 -486
- django_cfg/modules/django_app_agent/__init__.py +0 -87
- django_cfg/modules/django_app_agent/agents/__init__.py +0 -40
- django_cfg/modules/django_app_agent/agents/base/__init__.py +0 -24
- django_cfg/modules/django_app_agent/agents/base/agent.py +0 -354
- django_cfg/modules/django_app_agent/agents/base/context.py +0 -236
- django_cfg/modules/django_app_agent/agents/base/executor.py +0 -430
- django_cfg/modules/django_app_agent/agents/generation/__init__.py +0 -12
- django_cfg/modules/django_app_agent/agents/generation/app_generator/__init__.py +0 -15
- django_cfg/modules/django_app_agent/agents/generation/app_generator/config_validator.py +0 -147
- django_cfg/modules/django_app_agent/agents/generation/app_generator/main.py +0 -99
- django_cfg/modules/django_app_agent/agents/generation/app_generator/models.py +0 -32
- django_cfg/modules/django_app_agent/agents/generation/app_generator/prompt_manager.py +0 -290
- django_cfg/modules/django_app_agent/agents/interfaces.py +0 -376
- django_cfg/modules/django_app_agent/core/__init__.py +0 -33
- django_cfg/modules/django_app_agent/core/config.py +0 -300
- django_cfg/modules/django_app_agent/core/exceptions.py +0 -359
- django_cfg/modules/django_app_agent/models/__init__.py +0 -71
- django_cfg/modules/django_app_agent/models/base.py +0 -283
- django_cfg/modules/django_app_agent/models/context.py +0 -496
- django_cfg/modules/django_app_agent/models/enums.py +0 -481
- django_cfg/modules/django_app_agent/models/requests.py +0 -500
- django_cfg/modules/django_app_agent/models/responses.py +0 -585
- django_cfg/modules/django_app_agent/pytest.ini +0 -6
- django_cfg/modules/django_app_agent/services/__init__.py +0 -42
- django_cfg/modules/django_app_agent/services/app_generator/__init__.py +0 -30
- django_cfg/modules/django_app_agent/services/app_generator/ai_integration.py +0 -133
- django_cfg/modules/django_app_agent/services/app_generator/context.py +0 -40
- django_cfg/modules/django_app_agent/services/app_generator/main.py +0 -202
- django_cfg/modules/django_app_agent/services/app_generator/structure.py +0 -316
- django_cfg/modules/django_app_agent/services/app_generator/validation.py +0 -125
- django_cfg/modules/django_app_agent/services/base.py +0 -437
- django_cfg/modules/django_app_agent/services/context_builder/__init__.py +0 -34
- django_cfg/modules/django_app_agent/services/context_builder/code_extractor.py +0 -141
- django_cfg/modules/django_app_agent/services/context_builder/context_generator.py +0 -276
- django_cfg/modules/django_app_agent/services/context_builder/main.py +0 -272
- django_cfg/modules/django_app_agent/services/context_builder/models.py +0 -40
- django_cfg/modules/django_app_agent/services/context_builder/pattern_analyzer.py +0 -85
- django_cfg/modules/django_app_agent/services/project_scanner/__init__.py +0 -31
- django_cfg/modules/django_app_agent/services/project_scanner/app_discovery.py +0 -311
- django_cfg/modules/django_app_agent/services/project_scanner/main.py +0 -221
- django_cfg/modules/django_app_agent/services/project_scanner/models.py +0 -59
- django_cfg/modules/django_app_agent/services/project_scanner/pattern_detection.py +0 -94
- django_cfg/modules/django_app_agent/services/questioning_service/__init__.py +0 -28
- django_cfg/modules/django_app_agent/services/questioning_service/main.py +0 -273
- django_cfg/modules/django_app_agent/services/questioning_service/models.py +0 -111
- django_cfg/modules/django_app_agent/services/questioning_service/question_generator.py +0 -251
- django_cfg/modules/django_app_agent/services/questioning_service/response_processor.py +0 -347
- django_cfg/modules/django_app_agent/services/questioning_service/session_manager.py +0 -356
- django_cfg/modules/django_app_agent/services/report_service.py +0 -332
- django_cfg/modules/django_app_agent/services/template_manager/__init__.py +0 -18
- django_cfg/modules/django_app_agent/services/template_manager/jinja_engine.py +0 -236
- django_cfg/modules/django_app_agent/services/template_manager/main.py +0 -159
- django_cfg/modules/django_app_agent/services/template_manager/models.py +0 -36
- django_cfg/modules/django_app_agent/services/template_manager/template_loader.py +0 -100
- django_cfg/modules/django_app_agent/services/template_manager/templates/admin.py.j2 +0 -105
- django_cfg/modules/django_app_agent/services/template_manager/templates/apps.py.j2 +0 -31
- django_cfg/modules/django_app_agent/services/template_manager/templates/cfg_config.py.j2 +0 -44
- django_cfg/modules/django_app_agent/services/template_manager/templates/cfg_module.py.j2 +0 -81
- django_cfg/modules/django_app_agent/services/template_manager/templates/forms.py.j2 +0 -107
- django_cfg/modules/django_app_agent/services/template_manager/templates/models.py.j2 +0 -139
- django_cfg/modules/django_app_agent/services/template_manager/templates/serializers.py.j2 +0 -91
- django_cfg/modules/django_app_agent/services/template_manager/templates/tests.py.j2 +0 -195
- django_cfg/modules/django_app_agent/services/template_manager/templates/urls.py.j2 +0 -35
- django_cfg/modules/django_app_agent/services/template_manager/templates/views.py.j2 +0 -211
- django_cfg/modules/django_app_agent/services/template_manager/variable_processor.py +0 -200
- django_cfg/modules/django_app_agent/services/validation_service/__init__.py +0 -25
- django_cfg/modules/django_app_agent/services/validation_service/django_validator.py +0 -333
- django_cfg/modules/django_app_agent/services/validation_service/main.py +0 -242
- django_cfg/modules/django_app_agent/services/validation_service/models.py +0 -66
- django_cfg/modules/django_app_agent/services/validation_service/quality_validator.py +0 -352
- django_cfg/modules/django_app_agent/services/validation_service/security_validator.py +0 -272
- django_cfg/modules/django_app_agent/services/validation_service/syntax_validator.py +0 -203
- django_cfg/modules/django_app_agent/ui/__init__.py +0 -25
- django_cfg/modules/django_app_agent/ui/cli.py +0 -419
- django_cfg/modules/django_app_agent/ui/rich_components.py +0 -622
- django_cfg/modules/django_app_agent/utils/__init__.py +0 -38
- django_cfg/modules/django_app_agent/utils/logging.py +0 -360
- django_cfg/modules/django_app_agent/utils/validation.py +0 -417
- {django_cfg-1.3.9.dist-info → django_cfg-1.3.13.dist-info}/WHEEL +0 -0
- {django_cfg-1.3.9.dist-info → django_cfg-1.3.13.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.3.9.dist-info → django_cfg-1.3.13.dist-info}/licenses/LICENSE +0 -0
@@ -1,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
|
-
});
|