django-cfg 1.4.107__py3-none-any.whl → 1.4.109__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.
Potentially problematic release.
This version of django-cfg might be problematic. Click here for more details.
- django_cfg/__init__.py +1 -1
- django_cfg/apps/accounts/views/profile.py +19 -9
- django_cfg/apps/centrifugo/views/admin_api.py +4 -7
- django_cfg/apps/centrifugo/views/monitoring.py +3 -6
- django_cfg/apps/centrifugo/views/testing_api.py +3 -6
- django_cfg/apps/dashboard/services/system_health_service.py +16 -11
- django_cfg/apps/dashboard/views/activity_views.py +3 -5
- django_cfg/apps/dashboard/views/apizones_views.py +4 -5
- django_cfg/apps/dashboard/views/charts_views.py +4 -5
- django_cfg/apps/dashboard/views/overview_views.py +4 -5
- django_cfg/apps/dashboard/views/statistics_views.py +4 -5
- django_cfg/apps/dashboard/views/system_views.py +4 -5
- django_cfg/apps/knowbase/__init__.py +2 -2
- django_cfg/apps/knowbase/apps.py +2 -8
- django_cfg/apps/knowbase/views/base.py +9 -4
- django_cfg/apps/support/views/api.py +16 -7
- django_cfg/apps/tasks/__init__.py +61 -2
- django_cfg/apps/tasks/admin/__init__.py +3 -10
- django_cfg/apps/tasks/admin/config.py +98 -0
- django_cfg/apps/tasks/admin/task_log.py +265 -0
- django_cfg/apps/tasks/apps.py +7 -9
- django_cfg/apps/tasks/filters/__init__.py +10 -0
- django_cfg/apps/tasks/filters/task_log.py +121 -0
- django_cfg/apps/tasks/migrations/0001_initial.py +196 -0
- django_cfg/apps/tasks/models/__init__.py +4 -0
- django_cfg/apps/tasks/models/task_log.py +246 -0
- django_cfg/apps/tasks/serializers/__init__.py +28 -0
- django_cfg/apps/tasks/serializers/task_log.py +249 -0
- django_cfg/apps/tasks/services/__init__.py +10 -0
- django_cfg/apps/tasks/services/client/__init__.py +7 -0
- django_cfg/apps/tasks/services/client/client.py +234 -0
- django_cfg/apps/tasks/services/config_helper.py +63 -0
- django_cfg/apps/tasks/services/sync.py +204 -0
- django_cfg/apps/tasks/urls.py +7 -13
- django_cfg/apps/tasks/views/__init__.py +4 -10
- django_cfg/apps/tasks/views/task_log.py +41 -0
- django_cfg/apps/tasks/views/task_log_base.py +41 -0
- django_cfg/apps/tasks/views/task_log_overview.py +100 -0
- django_cfg/apps/tasks/views/task_log_related.py +41 -0
- django_cfg/apps/tasks/views/task_log_stats.py +91 -0
- django_cfg/apps/tasks/views/task_log_timeline.py +81 -0
- django_cfg/apps/urls.py +0 -1
- django_cfg/cli/commands/info.py +1 -1
- django_cfg/cli/utils.py +1 -1
- django_cfg/core/base/config_model.py +1 -1
- django_cfg/core/builders/apps_builder.py +1 -1
- django_cfg/core/generation/integration_generators/__init__.py +1 -1
- django_cfg/core/generation/integration_generators/tasks.py +14 -18
- django_cfg/core/generation/security_generators/crypto_fields.py +2 -1
- django_cfg/core/integration/display/startup.py +1 -1
- django_cfg/mixins/__init__.py +12 -0
- django_cfg/mixins/admin_api.py +37 -0
- django_cfg/mixins/client_api.py +39 -0
- django_cfg/models/django/constance.py +2 -8
- django_cfg/models/django/crypto_fields.py +13 -48
- django_cfg/models/tasks/__init__.py +8 -10
- django_cfg/models/tasks/backends.py +76 -207
- django_cfg/models/tasks/config.py +20 -127
- django_cfg/models/tasks/utils.py +17 -29
- django_cfg/modules/django_client/management/commands/generate_client.py +13 -1
- django_cfg/modules/django_unfold/navigation.py +121 -22
- django_cfg/pyproject.toml +2 -2
- django_cfg/registry/core.py +1 -1
- django_cfg/static/frontend/admin.zip +0 -0
- {django_cfg-1.4.107.dist-info → django_cfg-1.4.109.dist-info}/METADATA +3 -3
- {django_cfg-1.4.107.dist-info → django_cfg-1.4.109.dist-info}/RECORD +70 -117
- django_cfg/apps/tasks/admin/actions.py +0 -29
- django_cfg/apps/tasks/admin/tasks_admin.py +0 -154
- django_cfg/apps/tasks/api/serializers.py +0 -82
- django_cfg/apps/tasks/api/views.py +0 -571
- django_cfg/apps/tasks/serializers.py +0 -82
- django_cfg/apps/tasks/static/tasks/css/dashboard-alpine.css +0 -299
- django_cfg/apps/tasks/static/tasks/css/dashboard.css +0 -120
- django_cfg/apps/tasks/static/tasks/js/alpine/README.md +0 -47
- django_cfg/apps/tasks/static/tasks/js/alpine/actions/index.js +0 -8
- django_cfg/apps/tasks/static/tasks/js/alpine/actions/management.js +0 -123
- django_cfg/apps/tasks/static/tasks/js/alpine/actions/pagination.js +0 -21
- django_cfg/apps/tasks/static/tasks/js/alpine/actions/tasks.js +0 -101
- django_cfg/apps/tasks/static/tasks/js/alpine/actions/workers.js +0 -59
- django_cfg/apps/tasks/static/tasks/js/alpine/computed.js +0 -35
- django_cfg/apps/tasks/static/tasks/js/alpine/index.js +0 -148
- django_cfg/apps/tasks/static/tasks/js/alpine/loaders/index.js +0 -36
- django_cfg/apps/tasks/static/tasks/js/alpine/loaders/overview.js +0 -37
- django_cfg/apps/tasks/static/tasks/js/alpine/loaders/queues.js +0 -27
- django_cfg/apps/tasks/static/tasks/js/alpine/loaders/tasks.js +0 -32
- django_cfg/apps/tasks/static/tasks/js/alpine/loaders/workers.js +0 -21
- django_cfg/apps/tasks/static/tasks/js/alpine/state.js +0 -36
- django_cfg/apps/tasks/static/tasks/js/alpine/utils/formatters.js +0 -42
- django_cfg/apps/tasks/static/tasks/js/alpine/utils/helpers.js +0 -68
- django_cfg/apps/tasks/static/tasks/js/dashboard-alpine.js +0 -725
- django_cfg/apps/tasks/tasks/__init__.py +0 -10
- django_cfg/apps/tasks/tasks/demo_tasks.py +0 -127
- django_cfg/apps/tasks/templates/tasks/components/management_actions.html +0 -71
- django_cfg/apps/tasks/templates/tasks/components/overview_content.html +0 -94
- django_cfg/apps/tasks/templates/tasks/components/queues_content.html +0 -44
- django_cfg/apps/tasks/templates/tasks/components/tab_navigation.html +0 -45
- django_cfg/apps/tasks/templates/tasks/components/task_details_modal.html +0 -151
- django_cfg/apps/tasks/templates/tasks/components/tasks_content.html +0 -61
- django_cfg/apps/tasks/templates/tasks/components/tasks_mjs_integration.html +0 -269
- django_cfg/apps/tasks/templates/tasks/components/workers_content.html +0 -60
- django_cfg/apps/tasks/templates/tasks/layout/base.html +0 -20
- django_cfg/apps/tasks/templates/tasks/pages/dashboard-improved.html +0 -168
- django_cfg/apps/tasks/templates/tasks/pages/dashboard.html +0 -77
- django_cfg/apps/tasks/templates/tasks/partials/task_row_template.html +0 -40
- django_cfg/apps/tasks/templates/tasks/widgets/task_filters.html +0 -40
- django_cfg/apps/tasks/templates/tasks/widgets/task_footer.html +0 -86
- django_cfg/apps/tasks/templates/tasks/widgets/task_table.html +0 -90
- django_cfg/apps/tasks/urls_admin.py +0 -15
- django_cfg/apps/tasks/utils/__init__.py +0 -1
- django_cfg/apps/tasks/utils/simulator.py +0 -353
- django_cfg/apps/tasks/views/api.py +0 -571
- django_cfg/apps/tasks/views/dashboard.py +0 -89
- django_cfg/management/commands/rundramatiq.py +0 -24
- django_cfg/management/commands/rundramatiq_simulator.py +0 -22
- django_cfg/management/commands/task_clear.py +0 -25
- django_cfg/management/commands/task_status.py +0 -24
- django_cfg/modules/django_client/system/__init__.py +0 -24
- django_cfg/modules/django_client/system/base_generator.py +0 -123
- django_cfg/modules/django_client/system/generate_mjs_clients.py +0 -176
- django_cfg/modules/django_client/system/mjs_generator.py +0 -219
- django_cfg/modules/django_client/system/schema_parser.py +0 -199
- django_cfg/modules/django_client/system/templates/api_client.js.j2 +0 -87
- django_cfg/modules/django_client/system/templates/app_index.js.j2 +0 -13
- django_cfg/modules/django_client/system/templates/base_client.js.j2 +0 -166
- django_cfg/modules/django_client/system/templates/main_index.js.j2 +0 -80
- django_cfg/modules/django_client/system/templates/types.js.j2 +0 -24
- django_cfg/modules/django_tasks/__init__.py +0 -29
- django_cfg/modules/django_tasks/dramatiq_setup.py +0 -20
- django_cfg/modules/django_tasks/factory.py +0 -127
- django_cfg/modules/django_tasks/management/commands/__init__.py +0 -0
- django_cfg/modules/django_tasks/management/commands/rundramatiq.py +0 -253
- django_cfg/modules/django_tasks/management/commands/rundramatiq_simulator.py +0 -436
- django_cfg/modules/django_tasks/management/commands/task_clear.py +0 -226
- django_cfg/modules/django_tasks/management/commands/task_status.py +0 -257
- django_cfg/modules/django_tasks/service.py +0 -281
- django_cfg/modules/django_tasks/settings.py +0 -107
- /django_cfg/{modules/django_tasks/management → apps/tasks/migrations}/__init__.py +0 -0
- {django_cfg-1.4.107.dist-info → django_cfg-1.4.109.dist-info}/WHEEL +0 -0
- {django_cfg-1.4.107.dist-info → django_cfg-1.4.109.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.4.107.dist-info → django_cfg-1.4.109.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,269 +0,0 @@
|
|
|
1
|
-
<!-- Example of MJS API client integration in Django template -->
|
|
2
|
-
{% load static %}
|
|
3
|
-
|
|
4
|
-
<div id="tasks-dashboard" class="bg-white dark:bg-gray-800 rounded-xl shadow-sm border border-gray-200 dark:border-gray-700">
|
|
5
|
-
<!-- Header -->
|
|
6
|
-
<div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
|
|
7
|
-
<div class="flex items-center justify-between">
|
|
8
|
-
<h2 class="text-lg font-semibold text-gray-900 dark:text-white">Tasks Dashboard (MJS)</h2>
|
|
9
|
-
<button id="refresh-btn" class="px-3 py-1 text-sm bg-purple-600 text-white rounded hover:bg-purple-700">
|
|
10
|
-
Refresh
|
|
11
|
-
</button>
|
|
12
|
-
</div>
|
|
13
|
-
</div>
|
|
14
|
-
|
|
15
|
-
<!-- Stats -->
|
|
16
|
-
<div id="task-stats" class="p-6">
|
|
17
|
-
<div class="grid grid-cols-4 gap-4">
|
|
18
|
-
<div class="bg-gray-50 dark:bg-gray-700 p-4 rounded-lg">
|
|
19
|
-
<div class="text-sm text-gray-600 dark:text-gray-400">Total Tasks</div>
|
|
20
|
-
<div id="total-tasks" class="text-2xl font-bold text-gray-900 dark:text-white">-</div>
|
|
21
|
-
</div>
|
|
22
|
-
<div class="bg-green-50 dark:bg-green-900 p-4 rounded-lg">
|
|
23
|
-
<div class="text-sm text-green-600 dark:text-green-400">Completed</div>
|
|
24
|
-
<div id="completed-tasks" class="text-2xl font-bold text-green-900 dark:text-green-100">-</div>
|
|
25
|
-
</div>
|
|
26
|
-
<div class="bg-yellow-50 dark:bg-yellow-900 p-4 rounded-lg">
|
|
27
|
-
<div class="text-sm text-yellow-600 dark:text-yellow-400">Running</div>
|
|
28
|
-
<div id="running-tasks" class="text-2xl font-bold text-yellow-900 dark:text-yellow-100">-</div>
|
|
29
|
-
</div>
|
|
30
|
-
<div class="bg-red-50 dark:bg-red-900 p-4 rounded-lg">
|
|
31
|
-
<div class="text-sm text-red-600 dark:text-red-400">Failed</div>
|
|
32
|
-
<div id="failed-tasks" class="text-2xl font-bold text-red-900 dark:text-red-100">-</div>
|
|
33
|
-
</div>
|
|
34
|
-
</div>
|
|
35
|
-
</div>
|
|
36
|
-
|
|
37
|
-
<!-- Task List -->
|
|
38
|
-
<div class="p-6 border-t border-gray-200 dark:border-gray-700">
|
|
39
|
-
<h3 class="text-md font-semibold text-gray-900 dark:text-white mb-4">Recent Tasks</h3>
|
|
40
|
-
<div id="task-list" class="space-y-2">
|
|
41
|
-
<!-- Tasks will be inserted here -->
|
|
42
|
-
</div>
|
|
43
|
-
</div>
|
|
44
|
-
|
|
45
|
-
<!-- Loading State -->
|
|
46
|
-
<div id="loading" class="hidden p-6 text-center">
|
|
47
|
-
<div class="animate-spin rounded-full h-8 w-8 border-b-2 border-purple-600 mx-auto"></div>
|
|
48
|
-
<p class="mt-2 text-gray-600 dark:text-gray-400">Loading tasks...</p>
|
|
49
|
-
</div>
|
|
50
|
-
|
|
51
|
-
<!-- Error State -->
|
|
52
|
-
<div id="error" class="hidden p-6 text-center">
|
|
53
|
-
<div class="text-red-600 dark:text-red-400">
|
|
54
|
-
<span class="material-icons text-5xl">error</span>
|
|
55
|
-
<p class="mt-2">Failed to load tasks</p>
|
|
56
|
-
<p id="error-message" class="text-sm mt-1"></p>
|
|
57
|
-
</div>
|
|
58
|
-
</div>
|
|
59
|
-
</div>
|
|
60
|
-
|
|
61
|
-
<script type="module">
|
|
62
|
-
// Import the MJS API client
|
|
63
|
-
import { tasksAPI } from '{% static "api/tasks.mjs" %}';
|
|
64
|
-
|
|
65
|
-
// State management
|
|
66
|
-
let currentTasks = [];
|
|
67
|
-
let autoRefreshInterval = null;
|
|
68
|
-
|
|
69
|
-
// DOM elements
|
|
70
|
-
const elements = {
|
|
71
|
-
totalTasks: document.getElementById('total-tasks'),
|
|
72
|
-
completedTasks: document.getElementById('completed-tasks'),
|
|
73
|
-
runningTasks: document.getElementById('running-tasks'),
|
|
74
|
-
failedTasks: document.getElementById('failed-tasks'),
|
|
75
|
-
taskList: document.getElementById('task-list'),
|
|
76
|
-
loading: document.getElementById('loading'),
|
|
77
|
-
error: document.getElementById('error'),
|
|
78
|
-
errorMessage: document.getElementById('error-message'),
|
|
79
|
-
refreshBtn: document.getElementById('refresh-btn')
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
// Show loading state
|
|
83
|
-
function showLoading() {
|
|
84
|
-
elements.loading.classList.remove('hidden');
|
|
85
|
-
elements.error.classList.add('hidden');
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// Hide loading state
|
|
89
|
-
function hideLoading() {
|
|
90
|
-
elements.loading.classList.add('hidden');
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Show error
|
|
94
|
-
function showError(message) {
|
|
95
|
-
elements.error.classList.remove('hidden');
|
|
96
|
-
elements.errorMessage.textContent = message;
|
|
97
|
-
hideLoading();
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Update statistics
|
|
101
|
-
async function updateStats() {
|
|
102
|
-
try {
|
|
103
|
-
const stats = await tasksAPI.cfgTasksApiTasksStatsRetrieve();
|
|
104
|
-
|
|
105
|
-
elements.totalTasks.textContent = stats.total || 0;
|
|
106
|
-
elements.completedTasks.textContent = stats.completed || 0;
|
|
107
|
-
elements.runningTasks.textContent = stats.running || 0;
|
|
108
|
-
elements.failedTasks.textContent = stats.failed || 0;
|
|
109
|
-
} catch (error) {
|
|
110
|
-
console.error('Failed to fetch stats:', error);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Render task item
|
|
115
|
-
function renderTaskItem(task) {
|
|
116
|
-
const statusColors = {
|
|
117
|
-
'completed': 'text-green-600 bg-green-100',
|
|
118
|
-
'running': 'text-yellow-600 bg-yellow-100',
|
|
119
|
-
'failed': 'text-red-600 bg-red-100',
|
|
120
|
-
'pending': 'text-gray-600 bg-gray-100'
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
const statusColor = statusColors[task.status] || 'text-gray-600 bg-gray-100';
|
|
124
|
-
|
|
125
|
-
return `
|
|
126
|
-
<div class="flex items-center justify-between p-3 bg-gray-50 dark:bg-gray-700 rounded-lg">
|
|
127
|
-
<div class="flex items-center space-x-3">
|
|
128
|
-
<span class="px-2 py-1 text-xs font-medium rounded ${statusColor}">
|
|
129
|
-
${task.status}
|
|
130
|
-
</span>
|
|
131
|
-
<div>
|
|
132
|
-
<div class="font-medium text-gray-900 dark:text-white">${task.name}</div>
|
|
133
|
-
<div class="text-sm text-gray-500 dark:text-gray-400">
|
|
134
|
-
${task.queue || 'default'} • ${new Date(task.created_at).toLocaleString()}
|
|
135
|
-
</div>
|
|
136
|
-
</div>
|
|
137
|
-
</div>
|
|
138
|
-
<div class="text-sm text-gray-500 dark:text-gray-400">
|
|
139
|
-
${task.duration || '-'} ms
|
|
140
|
-
</div>
|
|
141
|
-
</div>
|
|
142
|
-
`;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// Load tasks
|
|
146
|
-
async function loadTasks() {
|
|
147
|
-
showLoading();
|
|
148
|
-
|
|
149
|
-
try {
|
|
150
|
-
// Fetch tasks list
|
|
151
|
-
const response = await tasksAPI.cfgTasksApiTasksListRetrieve();
|
|
152
|
-
currentTasks = response.tasks || [];
|
|
153
|
-
|
|
154
|
-
// Update stats
|
|
155
|
-
await updateStats();
|
|
156
|
-
|
|
157
|
-
// Render task list
|
|
158
|
-
if (currentTasks.length > 0) {
|
|
159
|
-
elements.taskList.innerHTML = currentTasks
|
|
160
|
-
.slice(0, 10) // Show only first 10 tasks
|
|
161
|
-
.map(task => renderTaskItem(task))
|
|
162
|
-
.join('');
|
|
163
|
-
} else {
|
|
164
|
-
elements.taskList.innerHTML = `
|
|
165
|
-
<div class="text-center py-8 text-gray-500 dark:text-gray-400">
|
|
166
|
-
No tasks found
|
|
167
|
-
</div>
|
|
168
|
-
`;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
hideLoading();
|
|
172
|
-
} catch (error) {
|
|
173
|
-
console.error('Failed to load tasks:', error);
|
|
174
|
-
showError(error.message || 'Failed to load tasks');
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// Clear all tasks
|
|
179
|
-
async function clearAllTasks() {
|
|
180
|
-
if (!confirm('Are you sure you want to clear all tasks?')) {
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
try {
|
|
185
|
-
await tasksAPI.cfgTasksApiClearCreate({});
|
|
186
|
-
await loadTasks();
|
|
187
|
-
alert('All tasks cleared successfully');
|
|
188
|
-
} catch (error) {
|
|
189
|
-
console.error('Failed to clear tasks:', error);
|
|
190
|
-
alert('Failed to clear tasks: ' + error.message);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// Simulate tasks
|
|
195
|
-
async function simulateTasks(count = 5) {
|
|
196
|
-
try {
|
|
197
|
-
await tasksAPI.cfgTasksApiSimulateCreate({
|
|
198
|
-
count: count,
|
|
199
|
-
queue: 'default',
|
|
200
|
-
task_type: 'test'
|
|
201
|
-
});
|
|
202
|
-
await loadTasks();
|
|
203
|
-
} catch (error) {
|
|
204
|
-
console.error('Failed to simulate tasks:', error);
|
|
205
|
-
alert('Failed to simulate tasks: ' + error.message);
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
// Setup auto-refresh
|
|
210
|
-
function startAutoRefresh(interval = 5000) {
|
|
211
|
-
stopAutoRefresh();
|
|
212
|
-
autoRefreshInterval = setInterval(() => {
|
|
213
|
-
loadTasks();
|
|
214
|
-
}, interval);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
function stopAutoRefresh() {
|
|
218
|
-
if (autoRefreshInterval) {
|
|
219
|
-
clearInterval(autoRefreshInterval);
|
|
220
|
-
autoRefreshInterval = null;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
// Event listeners
|
|
225
|
-
elements.refreshBtn.addEventListener('click', () => {
|
|
226
|
-
loadTasks();
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
// Keyboard shortcuts
|
|
230
|
-
document.addEventListener('keydown', (e) => {
|
|
231
|
-
// Ctrl+R or Cmd+R to refresh
|
|
232
|
-
if ((e.ctrlKey || e.metaKey) && e.key === 'r') {
|
|
233
|
-
e.preventDefault();
|
|
234
|
-
loadTasks();
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
// Ctrl+Shift+C to clear tasks
|
|
238
|
-
if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key === 'C') {
|
|
239
|
-
e.preventDefault();
|
|
240
|
-
clearAllTasks();
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
// Ctrl+Shift+S to simulate tasks
|
|
244
|
-
if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key === 'S') {
|
|
245
|
-
e.preventDefault();
|
|
246
|
-
simulateTasks();
|
|
247
|
-
}
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
// Initialize on page load
|
|
251
|
-
loadTasks();
|
|
252
|
-
|
|
253
|
-
// Start auto-refresh (update every 5 seconds)
|
|
254
|
-
startAutoRefresh(5000);
|
|
255
|
-
|
|
256
|
-
// Cleanup on page unload
|
|
257
|
-
window.addEventListener('beforeunload', () => {
|
|
258
|
-
stopAutoRefresh();
|
|
259
|
-
});
|
|
260
|
-
|
|
261
|
-
// Export functions for external use
|
|
262
|
-
window.tasksDashboard = {
|
|
263
|
-
loadTasks,
|
|
264
|
-
clearAllTasks,
|
|
265
|
-
simulateTasks,
|
|
266
|
-
startAutoRefresh,
|
|
267
|
-
stopAutoRefresh
|
|
268
|
-
};
|
|
269
|
-
</script>
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
<!-- Workers Content -->
|
|
2
|
-
<div class="bg-white dark:bg-gray-800 rounded-xl shadow-sm border border-gray-200 dark:border-gray-700">
|
|
3
|
-
<div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700 flex items-center justify-between">
|
|
4
|
-
<h2 class="text-lg font-semibold text-gray-900 dark:text-white flex items-center">
|
|
5
|
-
<span class="material-icons text-green-600 dark:text-green-400 mr-2">engineering</span>
|
|
6
|
-
Worker Management
|
|
7
|
-
</h2>
|
|
8
|
-
<div class="flex space-x-2">
|
|
9
|
-
<button @click="startWorkers()"
|
|
10
|
-
:disabled="loading"
|
|
11
|
-
class="inline-flex items-center px-3 py-2 bg-green-600 hover:bg-green-700 text-white text-sm rounded-lg transition-colors disabled:opacity-50 disabled:cursor-not-allowed">
|
|
12
|
-
<span class="material-icons text-sm mr-1">play_arrow</span>
|
|
13
|
-
Start
|
|
14
|
-
</button>
|
|
15
|
-
<button @click="stopWorkers()"
|
|
16
|
-
:disabled="loading"
|
|
17
|
-
class="inline-flex items-center px-3 py-2 bg-red-600 hover:bg-red-700 text-white text-sm rounded-lg transition-colors disabled:opacity-50 disabled:cursor-not-allowed">
|
|
18
|
-
<span class="material-icons text-sm mr-1">stop</span>
|
|
19
|
-
Stop
|
|
20
|
-
</button>
|
|
21
|
-
</div>
|
|
22
|
-
</div>
|
|
23
|
-
<div class="p-6">
|
|
24
|
-
<!-- Loading State -->
|
|
25
|
-
<div x-show="loading && workers.length === 0" x-cloak>
|
|
26
|
-
<div class="flex items-center justify-center py-12">
|
|
27
|
-
<div class="animate-spin rounded-full h-8 w-8 border-b-2 border-primary-600"></div>
|
|
28
|
-
<span class="ml-3 text-gray-600 dark:text-gray-400">Loading workers...</span>
|
|
29
|
-
</div>
|
|
30
|
-
</div>
|
|
31
|
-
|
|
32
|
-
<!-- Empty State -->
|
|
33
|
-
<div x-show="!loading && workers.length === 0" x-cloak>
|
|
34
|
-
<p class="text-center text-gray-600 dark:text-gray-400 py-12">No workers found.</p>
|
|
35
|
-
</div>
|
|
36
|
-
|
|
37
|
-
<!-- Workers List -->
|
|
38
|
-
<div x-show="workers.length > 0" x-cloak>
|
|
39
|
-
<div class="space-y-3">
|
|
40
|
-
<template x-for="worker in workers" :key="worker.id">
|
|
41
|
-
<div class="p-4 bg-gray-50 dark:bg-gray-700 rounded-lg">
|
|
42
|
-
<div class="flex items-center justify-between">
|
|
43
|
-
<div>
|
|
44
|
-
<h3 class="font-medium text-gray-900 dark:text-white" x-text="worker.name || worker.id"></h3>
|
|
45
|
-
<p class="text-sm text-gray-600 dark:text-gray-400">
|
|
46
|
-
<span x-text="worker.current_task || 'Idle'"></span>
|
|
47
|
-
</p>
|
|
48
|
-
</div>
|
|
49
|
-
<div>
|
|
50
|
-
<div class="px-3 py-1 text-xs rounded-full"
|
|
51
|
-
:class="(worker.uptime === 'Active' || worker.is_active) ? 'bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200' : 'bg-gray-100 dark:bg-gray-600 text-gray-800 dark:text-gray-200'"
|
|
52
|
-
x-text="worker.uptime || (worker.is_active ? 'Active' : 'Inactive')"></div>
|
|
53
|
-
</div>
|
|
54
|
-
</div>
|
|
55
|
-
</div>
|
|
56
|
-
</template>
|
|
57
|
-
</div>
|
|
58
|
-
</div>
|
|
59
|
-
</div>
|
|
60
|
-
</div>
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
{% extends 'django_tailwind/app.html' %}
|
|
2
|
-
{% load static %}
|
|
3
|
-
|
|
4
|
-
{% block title %}{% block page_title_text %}Tasks Dashboard{% endblock %} - Django CFG{% endblock %}
|
|
5
|
-
|
|
6
|
-
{# Navbar configuration #}
|
|
7
|
-
{% block header %}
|
|
8
|
-
{% with navbar_items=tasks_nav_items %}
|
|
9
|
-
{% include 'django_tailwind/components/navbar.html' with title=page_title|default:"Tasks Dashboard" icon='<span class="material-icons text-2xl text-primary-600 dark:text-primary-400">dashboard</span>' nav_items=navbar_items %}
|
|
10
|
-
{% endwith %}
|
|
11
|
-
{% endblock %}
|
|
12
|
-
|
|
13
|
-
{% block extra_head %}
|
|
14
|
-
{{ block.super }}
|
|
15
|
-
|
|
16
|
-
<!-- Custom CSS -->
|
|
17
|
-
<link rel="stylesheet" href="{% static 'tasks/css/dashboard.css' %}">
|
|
18
|
-
|
|
19
|
-
{% block extra_css %}{% endblock %}
|
|
20
|
-
{% endblock %}
|
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
{% extends 'tasks/layout/base.html' %}
|
|
2
|
-
{% load static %}
|
|
3
|
-
|
|
4
|
-
{% block extra_css %}
|
|
5
|
-
<style>
|
|
6
|
-
/* Tab styling - важно для работы табов */
|
|
7
|
-
.tab-button.active {
|
|
8
|
-
border-color: #3b82f6 !important;
|
|
9
|
-
color: #3b82f6 !important;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
.tab-panel {
|
|
13
|
-
display: none !important;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
.tab-panel.active {
|
|
17
|
-
display: block !important;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/* Убираем все остальные табы кроме активного */
|
|
21
|
-
#queues-tab,
|
|
22
|
-
#workers-tab,
|
|
23
|
-
#tasks-tab {
|
|
24
|
-
display: none;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
#overview-tab {
|
|
28
|
-
display: block;
|
|
29
|
-
}
|
|
30
|
-
</style>
|
|
31
|
-
{% endblock %}
|
|
32
|
-
|
|
33
|
-
{% block content %}
|
|
34
|
-
{% csrf_token %}
|
|
35
|
-
|
|
36
|
-
<!-- Management Actions -->
|
|
37
|
-
{% include 'tasks/components/management_actions.html' %}
|
|
38
|
-
|
|
39
|
-
<!-- Tab Navigation -->
|
|
40
|
-
{% include 'tasks/components/tab_navigation.html' %}
|
|
41
|
-
|
|
42
|
-
<!-- Tab Content -->
|
|
43
|
-
<div class="tab-content mt-6">
|
|
44
|
-
<!-- Overview Tab -->
|
|
45
|
-
<div id="overview-tab" class="tab-panel active">
|
|
46
|
-
{% include 'tasks/components/overview_content.html' %}
|
|
47
|
-
</div>
|
|
48
|
-
|
|
49
|
-
<!-- Queues Tab -->
|
|
50
|
-
<div id="queues-tab" class="tab-panel">
|
|
51
|
-
{% include 'tasks/components/queues_content.html' %}
|
|
52
|
-
</div>
|
|
53
|
-
|
|
54
|
-
<!-- Workers Tab -->
|
|
55
|
-
<div id="workers-tab" class="tab-panel">
|
|
56
|
-
{% include 'tasks/components/workers_content.html' %}
|
|
57
|
-
</div>
|
|
58
|
-
|
|
59
|
-
<!-- Tasks Tab -->
|
|
60
|
-
<div id="tasks-tab" class="tab-panel">
|
|
61
|
-
{% include 'tasks/components/tasks_content.html' %}
|
|
62
|
-
</div>
|
|
63
|
-
</div>
|
|
64
|
-
|
|
65
|
-
<!-- Templates for JavaScript -->
|
|
66
|
-
{% include 'tasks/partials/task_row_template.html' %}
|
|
67
|
-
|
|
68
|
-
{% endblock %}
|
|
69
|
-
|
|
70
|
-
{% block extra_js %}
|
|
71
|
-
<!-- Improved API Loading with centralized loader -->
|
|
72
|
-
<script type="module">
|
|
73
|
-
// Import the API loader and task API
|
|
74
|
-
import { initializeAPIs, showNotification } from '{% static "js/api-loader.mjs" %}';
|
|
75
|
-
import { tasksAPI } from '{% static "api/tasks/index.mjs" %}';
|
|
76
|
-
|
|
77
|
-
// Initialize the API with error handling wrapper
|
|
78
|
-
async function setupAPIs() {
|
|
79
|
-
try {
|
|
80
|
-
// Load task API with automatic error handling
|
|
81
|
-
const apis = await initializeAPIs(['tasks']);
|
|
82
|
-
|
|
83
|
-
// Make available globally for dashboard modules
|
|
84
|
-
window.tasksAPI = apis.tasks || tasksAPI;
|
|
85
|
-
|
|
86
|
-
// Log successful loading
|
|
87
|
-
console.log('✅ Tasks API loaded with JSDoc types and error handling');
|
|
88
|
-
console.log('📚 Available methods:', Object.getOwnPropertyNames(Object.getPrototypeOf(window.tasksAPI)));
|
|
89
|
-
|
|
90
|
-
// Show IDE hints example
|
|
91
|
-
console.log(`
|
|
92
|
-
💡 IDE Tip: Your editor now provides:
|
|
93
|
-
- Autocomplete for all API methods
|
|
94
|
-
- Parameter hints with types
|
|
95
|
-
- Return type information
|
|
96
|
-
- Inline documentation
|
|
97
|
-
|
|
98
|
-
Try typing: tasksAPI. (and see the suggestions!)
|
|
99
|
-
`);
|
|
100
|
-
|
|
101
|
-
// Test the API connection
|
|
102
|
-
const healthCheck = await window.tasksAPI.cfgTasksApiQueuesStatusRetrieve();
|
|
103
|
-
if (healthCheck) {
|
|
104
|
-
showNotification('API connected successfully', 'success');
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
} catch (error) {
|
|
108
|
-
console.error('❌ Failed to initialize APIs:', error);
|
|
109
|
-
showNotification('Failed to load API. Some features may not work.', 'error');
|
|
110
|
-
|
|
111
|
-
// Fallback to direct import
|
|
112
|
-
window.tasksAPI = tasksAPI;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// Setup APIs when DOM is ready
|
|
117
|
-
if (document.readyState === 'loading') {
|
|
118
|
-
document.addEventListener('DOMContentLoaded', setupAPIs);
|
|
119
|
-
} else {
|
|
120
|
-
setupAPIs();
|
|
121
|
-
}
|
|
122
|
-
</script>
|
|
123
|
-
|
|
124
|
-
<!-- Dashboard Modules (now with improved API) -->
|
|
125
|
-
<script type="module" src="{% static 'tasks/js/dashboard/overview.mjs' %}"></script>
|
|
126
|
-
<script type="module" src="{% static 'tasks/js/dashboard/queues.mjs' %}"></script>
|
|
127
|
-
<script type="module" src="{% static 'tasks/js/dashboard/workers.mjs' %}"></script>
|
|
128
|
-
<script type="module" src="{% static 'tasks/js/dashboard/tasks.mjs' %}"></script>
|
|
129
|
-
|
|
130
|
-
<!-- Main Dashboard Controller -->
|
|
131
|
-
<script type="module" src="{% static 'tasks/js/dashboard/main.mjs' %}"></script>
|
|
132
|
-
|
|
133
|
-
<!-- Debug Helper -->
|
|
134
|
-
<script type="module">
|
|
135
|
-
// Add debug helper to window for testing
|
|
136
|
-
window.debugAPI = {
|
|
137
|
-
// Test various API methods
|
|
138
|
-
testStats: async () => {
|
|
139
|
-
const stats = await window.tasksAPI.tasksApiTasksStatsRetrieve();
|
|
140
|
-
console.log('Task Statistics:', stats);
|
|
141
|
-
return stats;
|
|
142
|
-
},
|
|
143
|
-
|
|
144
|
-
testQueues: async () => {
|
|
145
|
-
const queues = await window.tasksAPI.tasksApiQueuesStatusRetrieve();
|
|
146
|
-
console.log('Queue Status:', queues);
|
|
147
|
-
return queues;
|
|
148
|
-
},
|
|
149
|
-
|
|
150
|
-
testWorkers: async () => {
|
|
151
|
-
const workers = await window.tasksAPI.tasksApiWorkersListRetrieve();
|
|
152
|
-
console.log('Workers List:', workers);
|
|
153
|
-
return workers;
|
|
154
|
-
},
|
|
155
|
-
|
|
156
|
-
// Show all available methods
|
|
157
|
-
showMethods: () => {
|
|
158
|
-
const methods = Object.getOwnPropertyNames(Object.getPrototypeOf(window.tasksAPI))
|
|
159
|
-
.filter(m => typeof window.tasksAPI[m] === 'function')
|
|
160
|
-
.filter(m => !m.startsWith('_'));
|
|
161
|
-
console.log('📋 Available API Methods:', methods);
|
|
162
|
-
return methods;
|
|
163
|
-
}
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
console.log('🔧 Debug helpers available: window.debugAPI');
|
|
167
|
-
</script>
|
|
168
|
-
{% endblock %}
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
{% extends 'tasks/layout/base.html' %}
|
|
2
|
-
{% load static %}
|
|
3
|
-
|
|
4
|
-
{% block extra_css %}
|
|
5
|
-
<link rel="stylesheet" href="{% static 'tasks/css/dashboard-alpine.css' %}">
|
|
6
|
-
{% endblock %}
|
|
7
|
-
|
|
8
|
-
{% block content %}
|
|
9
|
-
<div x-data="tasksDashboard()">
|
|
10
|
-
{% csrf_token %}
|
|
11
|
-
|
|
12
|
-
<!-- Management Actions -->
|
|
13
|
-
{% include 'tasks/components/management_actions.html' %}
|
|
14
|
-
|
|
15
|
-
<!-- Tab Navigation -->
|
|
16
|
-
{% include 'tasks/components/tab_navigation.html' %}
|
|
17
|
-
|
|
18
|
-
<!-- Tab Content -->
|
|
19
|
-
<div class="tab-content mt-6">
|
|
20
|
-
<!-- Overview Tab -->
|
|
21
|
-
<div x-show="activeTab === 'overview'" x-cloak>
|
|
22
|
-
{% include 'tasks/components/overview_content.html' %}
|
|
23
|
-
</div>
|
|
24
|
-
|
|
25
|
-
<!-- Queues Tab -->
|
|
26
|
-
<div x-show="activeTab === 'queues'" x-cloak>
|
|
27
|
-
{% include 'tasks/components/queues_content.html' %}
|
|
28
|
-
</div>
|
|
29
|
-
|
|
30
|
-
<!-- Workers Tab -->
|
|
31
|
-
<div x-show="activeTab === 'workers'" x-cloak>
|
|
32
|
-
{% include 'tasks/components/workers_content.html' %}
|
|
33
|
-
</div>
|
|
34
|
-
|
|
35
|
-
<!-- Tasks Tab -->
|
|
36
|
-
<div x-show="activeTab === 'tasks'" x-cloak>
|
|
37
|
-
{% include 'tasks/components/tasks_content.html' %}
|
|
38
|
-
</div>
|
|
39
|
-
</div>
|
|
40
|
-
|
|
41
|
-
<!-- Templates for JavaScript -->
|
|
42
|
-
{% include 'tasks/partials/task_row_template.html' %}
|
|
43
|
-
|
|
44
|
-
<!-- Task Details Modal -->
|
|
45
|
-
{% include 'tasks/components/task_details_modal.html' %}
|
|
46
|
-
</div>
|
|
47
|
-
{% endblock %}
|
|
48
|
-
|
|
49
|
-
{% block extra_js %}
|
|
50
|
-
<!-- Load and initialize Tasks API -->
|
|
51
|
-
<script type="module">
|
|
52
|
-
try {
|
|
53
|
-
console.log('🔄 Starting TasksAPI module import...');
|
|
54
|
-
const { loadAPI, showNotification } = await import('/static/js/api-loader.mjs');
|
|
55
|
-
|
|
56
|
-
// Load tasks API
|
|
57
|
-
const tasksAPI = await loadAPI('tasks');
|
|
58
|
-
console.log('✅ TasksAPI module imported successfully:', tasksAPI);
|
|
59
|
-
|
|
60
|
-
// Make it available globally as tasksAPI
|
|
61
|
-
window.tasksAPI = tasksAPI;
|
|
62
|
-
window.showNotification = showNotification;
|
|
63
|
-
|
|
64
|
-
console.log('✅ TasksAPI loaded from generated MJS client');
|
|
65
|
-
} catch (error) {
|
|
66
|
-
console.error('❌ Failed to load TasksAPI module:', error);
|
|
67
|
-
console.error('Error stack:', error.stack);
|
|
68
|
-
window.tasksAPI = null;
|
|
69
|
-
}
|
|
70
|
-
</script>
|
|
71
|
-
|
|
72
|
-
<!-- Alpine.js Dashboard Logic (Modular) - Registers component factory globally -->
|
|
73
|
-
<script type="module" src="{% static 'tasks/js/alpine/index.js' %}"></script>
|
|
74
|
-
|
|
75
|
-
<!-- Alpine.js Core - Will find and register the component when it initializes -->
|
|
76
|
-
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
|
|
77
|
-
{% endblock %}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
<!-- Task Row Template for JavaScript -->
|
|
2
|
-
<template id="task-row-template">
|
|
3
|
-
<tr class="task-row hover:bg-gray-50 dark:hover:bg-gray-700/50 transition-colors" data-task-id="">
|
|
4
|
-
<!-- Status -->
|
|
5
|
-
<td class="px-4 py-3 whitespace-nowrap">
|
|
6
|
-
<div class="flex items-center space-x-2">
|
|
7
|
-
<span class="material-icons text-sm task-status-icon"></span>
|
|
8
|
-
<span class="px-2 py-1 text-xs font-medium rounded-full task-status-badge"></span>
|
|
9
|
-
</div>
|
|
10
|
-
<!-- Progress bar for running tasks -->
|
|
11
|
-
<div class="task-progress mt-1 w-16 bg-gray-200 dark:bg-gray-600 rounded-full h-1 hidden">
|
|
12
|
-
<div class="bg-blue-600 h-1 rounded-full transition-all duration-300" style="width: 0%"></div>
|
|
13
|
-
</div>
|
|
14
|
-
</td>
|
|
15
|
-
|
|
16
|
-
<!-- Task Info -->
|
|
17
|
-
<td class="px-4 py-3">
|
|
18
|
-
<div class="text-sm font-medium text-gray-900 dark:text-white task-name"></div>
|
|
19
|
-
<div class="text-xs text-gray-500 dark:text-gray-400 font-mono task-id"></div>
|
|
20
|
-
</td>
|
|
21
|
-
|
|
22
|
-
<!-- Queue -->
|
|
23
|
-
<td class="px-4 py-3 whitespace-nowrap">
|
|
24
|
-
<span class="px-2 py-1 text-xs bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-400 rounded-full task-queue"></span>
|
|
25
|
-
</td>
|
|
26
|
-
|
|
27
|
-
<!-- Duration -->
|
|
28
|
-
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400 task-duration"></td>
|
|
29
|
-
|
|
30
|
-
<!-- Updated -->
|
|
31
|
-
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400 task-updated"></td>
|
|
32
|
-
|
|
33
|
-
<!-- Actions -->
|
|
34
|
-
<td class="px-4 py-3 whitespace-nowrap text-right text-sm font-medium">
|
|
35
|
-
<div class="flex items-center justify-end space-x-1 task-actions">
|
|
36
|
-
<!-- Actions will be populated by JavaScript -->
|
|
37
|
-
</div>
|
|
38
|
-
</td>
|
|
39
|
-
</tr>
|
|
40
|
-
</template>
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
<!-- Task Filters Widget -->
|
|
2
|
-
<div class="task-filters-widget flex flex-wrap gap-3 items-center">
|
|
3
|
-
<!-- Status Filter -->
|
|
4
|
-
<select x-model="filters.status"
|
|
5
|
-
@change="applyFilters()"
|
|
6
|
-
class="text-sm border border-gray-300 dark:border-gray-600 rounded-lg px-3 py-2 bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-primary-500 focus:border-primary-500">
|
|
7
|
-
<option value="">All Status</option>
|
|
8
|
-
<option value="pending">Pending</option>
|
|
9
|
-
<option value="running">Running</option>
|
|
10
|
-
<option value="completed">Completed</option>
|
|
11
|
-
<option value="failed">Failed</option>
|
|
12
|
-
</select>
|
|
13
|
-
|
|
14
|
-
<!-- Queue Filter -->
|
|
15
|
-
<select x-model="filters.queue"
|
|
16
|
-
@change="applyFilters()"
|
|
17
|
-
class="text-sm border border-gray-300 dark:border-gray-600 rounded-lg px-3 py-2 bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-primary-500 focus:border-primary-500">
|
|
18
|
-
<option value="">All Queues</option>
|
|
19
|
-
<option value="default">Default</option>
|
|
20
|
-
<option value="high">High Priority</option>
|
|
21
|
-
<option value="low">Low Priority</option>
|
|
22
|
-
<option value="background">Background</option>
|
|
23
|
-
<option value="payments">Payments</option>
|
|
24
|
-
<option value="critical">Critical</option>
|
|
25
|
-
</select>
|
|
26
|
-
|
|
27
|
-
<!-- Search Input -->
|
|
28
|
-
<input x-model="filters.search"
|
|
29
|
-
@input.debounce.300ms="applyFilters()"
|
|
30
|
-
type="text"
|
|
31
|
-
placeholder="Search tasks..."
|
|
32
|
-
class="text-sm border border-gray-300 dark:border-gray-600 rounded-lg px-3 py-2 bg-white dark:bg-gray-700 text-gray-900 dark:text-white placeholder-gray-500 dark:placeholder-gray-400 focus:ring-2 focus:ring-primary-500 focus:border-primary-500">
|
|
33
|
-
|
|
34
|
-
<!-- Last Update Time -->
|
|
35
|
-
<div class="flex items-center text-xs text-gray-500 dark:text-gray-400 ml-auto">
|
|
36
|
-
<span class="material-icons text-sm mr-1">schedule</span>
|
|
37
|
-
<span>Last updated:</span>
|
|
38
|
-
<span x-text="lastUpdateTime" class="ml-1 font-mono">--:--:--</span>
|
|
39
|
-
</div>
|
|
40
|
-
</div>
|