django-cfg 1.4.107__py3-none-any.whl → 1.4.108__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.108.dist-info}/METADATA +3 -3
- {django_cfg-1.4.107.dist-info → django_cfg-1.4.108.dist-info}/RECORD +70 -107
- 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_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.108.dist-info}/WHEEL +0 -0
- {django_cfg-1.4.107.dist-info → django_cfg-1.4.108.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.4.107.dist-info → django_cfg-1.4.108.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,725 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tasks Dashboard Alpine.js Logic
|
|
3
|
-
*
|
|
4
|
-
* This file extends Alpine.js data and methods for the Tasks Dashboard.
|
|
5
|
-
* It integrates with the tasksAPI to provide reactive state management.
|
|
6
|
-
*
|
|
7
|
-
* TODO: Refactor into modular structure:
|
|
8
|
-
* - alpine/state.js - Initial state
|
|
9
|
-
* - alpine/loaders/ - Data loading methods (loadOverview, loadQueues, loadWorkers, loadTasks)
|
|
10
|
-
* - alpine/actions/ - User actions (simulate, clear, purge, start/stop workers, etc)
|
|
11
|
-
* - alpine/utils/ - Utility functions (formatters, helpers)
|
|
12
|
-
* - alpine/index.js - Main entry combining all modules
|
|
13
|
-
*
|
|
14
|
-
* Current size: 716 lines (needs decomposition for maintainability)
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
// Wait for Alpine.js to be available
|
|
18
|
-
document.addEventListener('alpine:init', () => {
|
|
19
|
-
console.log('🚀 Initializing Alpine.js Dashboard extensions...');
|
|
20
|
-
|
|
21
|
-
// Extend Alpine.js global data/methods
|
|
22
|
-
Alpine.data('tasksDashboard', () => ({
|
|
23
|
-
// Alpine.js state for Tasks Dashboard
|
|
24
|
-
activeTab: 'overview',
|
|
25
|
-
loading: false,
|
|
26
|
-
autoRefresh: true,
|
|
27
|
-
autoRefreshInterval: null,
|
|
28
|
-
lastUpdateTime: '--:--:--',
|
|
29
|
-
|
|
30
|
-
// Data collections
|
|
31
|
-
tasks: [],
|
|
32
|
-
queues: [],
|
|
33
|
-
workers: [],
|
|
34
|
-
stats: {},
|
|
35
|
-
|
|
36
|
-
// Filters
|
|
37
|
-
filters: {
|
|
38
|
-
status: '',
|
|
39
|
-
queue: '',
|
|
40
|
-
search: ''
|
|
41
|
-
},
|
|
42
|
-
|
|
43
|
-
// Counts for badges
|
|
44
|
-
counts: {
|
|
45
|
-
queues: 0,
|
|
46
|
-
workers: 0,
|
|
47
|
-
tasks: 0
|
|
48
|
-
},
|
|
49
|
-
|
|
50
|
-
// Action message state
|
|
51
|
-
actionMessage: '',
|
|
52
|
-
actionType: 'info', // 'info', 'success', 'error'
|
|
53
|
-
|
|
54
|
-
// Modal state
|
|
55
|
-
showTaskModal: false,
|
|
56
|
-
selectedTask: null,
|
|
57
|
-
|
|
58
|
-
// Pagination state
|
|
59
|
-
pagination: {
|
|
60
|
-
page: 1,
|
|
61
|
-
page_size: 20,
|
|
62
|
-
total_pages: 1,
|
|
63
|
-
total_count: 0,
|
|
64
|
-
has_next: false,
|
|
65
|
-
has_previous: false
|
|
66
|
-
},
|
|
67
|
-
|
|
68
|
-
// Lifecycle init
|
|
69
|
-
init() {
|
|
70
|
-
console.log('🎯 Dashboard component initialized');
|
|
71
|
-
|
|
72
|
-
// Initialize dashboard data
|
|
73
|
-
this.loadDashboardData();
|
|
74
|
-
|
|
75
|
-
// Start auto-refresh if enabled
|
|
76
|
-
if (this.autoRefresh) {
|
|
77
|
-
this.startAutoRefresh();
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Watch for tab changes
|
|
81
|
-
this.$watch('activeTab', (value) => {
|
|
82
|
-
console.log('Tab changed to:', value);
|
|
83
|
-
this.onTabChange(value);
|
|
84
|
-
});
|
|
85
|
-
},
|
|
86
|
-
|
|
87
|
-
// Computed properties
|
|
88
|
-
get filteredTasks() {
|
|
89
|
-
let filtered = this.tasks;
|
|
90
|
-
|
|
91
|
-
// Apply status filter
|
|
92
|
-
if (this.filters.status) {
|
|
93
|
-
filtered = filtered.filter(task => task.status === this.filters.status);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Apply queue filter
|
|
97
|
-
if (this.filters.queue) {
|
|
98
|
-
filtered = filtered.filter(task =>
|
|
99
|
-
(task.queue || task.queue_name) === this.filters.queue
|
|
100
|
-
);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Apply search filter
|
|
104
|
-
if (this.filters.search) {
|
|
105
|
-
const search = this.filters.search.toLowerCase();
|
|
106
|
-
filtered = filtered.filter(task =>
|
|
107
|
-
task.name?.toLowerCase().includes(search) ||
|
|
108
|
-
task.actor_name?.toLowerCase().includes(search) ||
|
|
109
|
-
task.task_id?.toLowerCase().includes(search) ||
|
|
110
|
-
task.message_id?.toLowerCase().includes(search) ||
|
|
111
|
-
task.queue?.toLowerCase().includes(search) ||
|
|
112
|
-
task.queue_name?.toLowerCase().includes(search)
|
|
113
|
-
);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
return filtered;
|
|
117
|
-
},
|
|
118
|
-
|
|
119
|
-
// Methods
|
|
120
|
-
async loadDashboardData() {
|
|
121
|
-
console.log('📊 Loading dashboard data...');
|
|
122
|
-
this.loading = true;
|
|
123
|
-
|
|
124
|
-
try {
|
|
125
|
-
// Load all data in parallel
|
|
126
|
-
await Promise.all([
|
|
127
|
-
this.loadOverview(),
|
|
128
|
-
this.loadQueues(),
|
|
129
|
-
this.loadWorkers(),
|
|
130
|
-
this.loadTasks()
|
|
131
|
-
]);
|
|
132
|
-
|
|
133
|
-
this.updateLastUpdateTime();
|
|
134
|
-
console.log('✅ Dashboard data loaded successfully');
|
|
135
|
-
} catch (error) {
|
|
136
|
-
console.error('❌ Failed to load dashboard data:', error);
|
|
137
|
-
if (window.showNotification) {
|
|
138
|
-
window.showNotification('Failed to load dashboard data', 'error');
|
|
139
|
-
}
|
|
140
|
-
} finally {
|
|
141
|
-
this.loading = false;
|
|
142
|
-
}
|
|
143
|
-
},
|
|
144
|
-
|
|
145
|
-
async loadOverview() {
|
|
146
|
-
if (!window.tasksAPI) return;
|
|
147
|
-
|
|
148
|
-
try {
|
|
149
|
-
const response = await window.tasksAPI.tasksApiTasksStatsRetrieve();
|
|
150
|
-
const data = response?.data || response || {};
|
|
151
|
-
|
|
152
|
-
// Flatten statistics into stats for easier access in template
|
|
153
|
-
if (data.statistics) {
|
|
154
|
-
this.stats = {
|
|
155
|
-
...data,
|
|
156
|
-
...data.statistics,
|
|
157
|
-
// Map API fields to template fields
|
|
158
|
-
total_tasks: data.statistics.total || 0,
|
|
159
|
-
completed_tasks: data.statistics.completed || 0,
|
|
160
|
-
running_tasks: data.statistics.running || 0,
|
|
161
|
-
failed_tasks: data.statistics.failed || 0,
|
|
162
|
-
pending_tasks: data.statistics.pending || 0,
|
|
163
|
-
success_rate: (data.statistics.success_rate || 0) / 100 // Convert from % to decimal
|
|
164
|
-
};
|
|
165
|
-
} else {
|
|
166
|
-
this.stats = data;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// Update counts
|
|
170
|
-
this.counts.queues = this.stats.active_queues || 0;
|
|
171
|
-
// Note: workers count is updated in loadWorkers()
|
|
172
|
-
this.counts.tasks = this.stats.total_tasks || 0;
|
|
173
|
-
|
|
174
|
-
console.log('📈 Overview stats loaded:', this.stats);
|
|
175
|
-
} catch (error) {
|
|
176
|
-
console.error('Failed to load overview:', error);
|
|
177
|
-
}
|
|
178
|
-
},
|
|
179
|
-
|
|
180
|
-
async loadQueues() {
|
|
181
|
-
if (!window.tasksAPI) return;
|
|
182
|
-
|
|
183
|
-
try {
|
|
184
|
-
const response = await window.tasksAPI.tasksApiQueuesStatusRetrieve();
|
|
185
|
-
const queuesData = response?.data?.queues || response?.queues;
|
|
186
|
-
|
|
187
|
-
// Convert queues object to array if needed
|
|
188
|
-
if (queuesData && typeof queuesData === 'object' && !Array.isArray(queuesData)) {
|
|
189
|
-
this.queues = Object.entries(queuesData).map(([name, data]) => ({
|
|
190
|
-
name,
|
|
191
|
-
...data
|
|
192
|
-
}));
|
|
193
|
-
} else {
|
|
194
|
-
this.queues = queuesData || [];
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
this.counts.queues = this.queues.length;
|
|
198
|
-
|
|
199
|
-
console.log('📋 Queues loaded:', this.queues.length);
|
|
200
|
-
} catch (error) {
|
|
201
|
-
console.error('Failed to load queues:', error);
|
|
202
|
-
}
|
|
203
|
-
},
|
|
204
|
-
|
|
205
|
-
async loadWorkers() {
|
|
206
|
-
if (!window.tasksAPI) return;
|
|
207
|
-
|
|
208
|
-
try {
|
|
209
|
-
const response = await window.tasksAPI.tasksApiWorkersListRetrieve();
|
|
210
|
-
const data = response?.data || response || {};
|
|
211
|
-
|
|
212
|
-
this.workers = data.workers || [];
|
|
213
|
-
this.counts.workers = data.active_count || this.workers.length;
|
|
214
|
-
|
|
215
|
-
// Update stats.workers for overview display
|
|
216
|
-
this.stats.workers = this.counts.workers;
|
|
217
|
-
|
|
218
|
-
console.log('👷 Workers loaded:', this.workers.length, 'Active:', this.counts.workers);
|
|
219
|
-
} catch (error) {
|
|
220
|
-
console.error('Failed to load workers:', error);
|
|
221
|
-
}
|
|
222
|
-
},
|
|
223
|
-
|
|
224
|
-
async loadTasks(page = 1) {
|
|
225
|
-
if (!window.tasksAPI) return;
|
|
226
|
-
|
|
227
|
-
try {
|
|
228
|
-
// TODO: Pass page parameter to API when backend supports it
|
|
229
|
-
const response = await window.tasksAPI.tasksApiTasksListRetrieve();
|
|
230
|
-
const data = response?.data || response || {};
|
|
231
|
-
|
|
232
|
-
this.tasks = data.tasks || [];
|
|
233
|
-
|
|
234
|
-
// Update pagination info
|
|
235
|
-
if (data.pagination) {
|
|
236
|
-
this.pagination = {
|
|
237
|
-
page: data.pagination.page || 1,
|
|
238
|
-
page_size: data.pagination.page_size || 20,
|
|
239
|
-
total_pages: data.pagination.total_pages || 1,
|
|
240
|
-
total_count: data.pagination.total_count || this.tasks.length,
|
|
241
|
-
has_next: data.pagination.has_next || false,
|
|
242
|
-
has_previous: data.pagination.has_previous || false
|
|
243
|
-
};
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
this.counts.tasks = this.pagination.total_count;
|
|
247
|
-
|
|
248
|
-
console.log('📝 Tasks loaded:', this.tasks.length, 'Total:', this.pagination.total_count);
|
|
249
|
-
} catch (error) {
|
|
250
|
-
console.error('Failed to load tasks:', error);
|
|
251
|
-
}
|
|
252
|
-
},
|
|
253
|
-
|
|
254
|
-
// Pagination methods
|
|
255
|
-
nextPage() {
|
|
256
|
-
if (this.pagination.has_next) {
|
|
257
|
-
this.loadTasks(this.pagination.page + 1);
|
|
258
|
-
}
|
|
259
|
-
},
|
|
260
|
-
|
|
261
|
-
previousPage() {
|
|
262
|
-
if (this.pagination.has_previous) {
|
|
263
|
-
this.loadTasks(this.pagination.page - 1);
|
|
264
|
-
}
|
|
265
|
-
},
|
|
266
|
-
|
|
267
|
-
goToPage(page) {
|
|
268
|
-
if (page >= 1 && page <= this.pagination.total_pages) {
|
|
269
|
-
this.loadTasks(page);
|
|
270
|
-
}
|
|
271
|
-
},
|
|
272
|
-
|
|
273
|
-
applyFilters() {
|
|
274
|
-
console.log('🔍 Applying filters:', this.filters);
|
|
275
|
-
// The filteredTasks computed property will automatically update
|
|
276
|
-
},
|
|
277
|
-
|
|
278
|
-
toggleAutoRefresh() {
|
|
279
|
-
this.autoRefresh = !this.autoRefresh;
|
|
280
|
-
|
|
281
|
-
if (this.autoRefresh) {
|
|
282
|
-
this.startAutoRefresh();
|
|
283
|
-
console.log('✅ Auto-refresh enabled');
|
|
284
|
-
} else {
|
|
285
|
-
this.stopAutoRefresh();
|
|
286
|
-
console.log('⏸️ Auto-refresh disabled');
|
|
287
|
-
}
|
|
288
|
-
},
|
|
289
|
-
|
|
290
|
-
startAutoRefresh() {
|
|
291
|
-
// Clear existing interval
|
|
292
|
-
this.stopAutoRefresh();
|
|
293
|
-
|
|
294
|
-
// Set new interval (refresh every 5 seconds)
|
|
295
|
-
this.autoRefreshInterval = setInterval(() => {
|
|
296
|
-
console.log('🔄 Auto-refresh triggered');
|
|
297
|
-
this.loadDashboardData();
|
|
298
|
-
}, 5000);
|
|
299
|
-
},
|
|
300
|
-
|
|
301
|
-
stopAutoRefresh() {
|
|
302
|
-
if (this.autoRefreshInterval) {
|
|
303
|
-
clearInterval(this.autoRefreshInterval);
|
|
304
|
-
this.autoRefreshInterval = null;
|
|
305
|
-
}
|
|
306
|
-
},
|
|
307
|
-
|
|
308
|
-
updateLastUpdateTime() {
|
|
309
|
-
const now = new Date();
|
|
310
|
-
this.lastUpdateTime = now.toLocaleTimeString('en-US', {
|
|
311
|
-
hour12: false,
|
|
312
|
-
hour: '2-digit',
|
|
313
|
-
minute: '2-digit',
|
|
314
|
-
second: '2-digit'
|
|
315
|
-
});
|
|
316
|
-
},
|
|
317
|
-
|
|
318
|
-
onTabChange(tab) {
|
|
319
|
-
console.log(`🔄 Switched to ${tab} tab`);
|
|
320
|
-
|
|
321
|
-
// Load data for specific tab if not loaded
|
|
322
|
-
switch (tab) {
|
|
323
|
-
case 'overview':
|
|
324
|
-
if (Object.keys(this.stats).length === 0) {
|
|
325
|
-
this.loadOverview();
|
|
326
|
-
}
|
|
327
|
-
break;
|
|
328
|
-
case 'queues':
|
|
329
|
-
if (this.queues.length === 0) {
|
|
330
|
-
this.loadQueues();
|
|
331
|
-
}
|
|
332
|
-
break;
|
|
333
|
-
case 'workers':
|
|
334
|
-
if (this.workers.length === 0) {
|
|
335
|
-
this.loadWorkers();
|
|
336
|
-
}
|
|
337
|
-
break;
|
|
338
|
-
case 'tasks':
|
|
339
|
-
if (this.tasks.length === 0) {
|
|
340
|
-
this.loadTasks();
|
|
341
|
-
}
|
|
342
|
-
break;
|
|
343
|
-
}
|
|
344
|
-
},
|
|
345
|
-
|
|
346
|
-
// Task management methods
|
|
347
|
-
async clearAllTasks() {
|
|
348
|
-
if (!confirm('Are you sure you want to clear all tasks?')) {
|
|
349
|
-
return;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
try {
|
|
353
|
-
this.loading = true;
|
|
354
|
-
this.showActionMessage('Clearing all tasks...', 'info');
|
|
355
|
-
await window.tasksAPI.tasksApiClearCreate({});
|
|
356
|
-
await this.loadTasks();
|
|
357
|
-
|
|
358
|
-
this.showActionMessage('All tasks cleared successfully', 'success');
|
|
359
|
-
|
|
360
|
-
if (window.showNotification) {
|
|
361
|
-
window.showNotification('All tasks cleared successfully', 'success');
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
console.log('✅ All tasks cleared');
|
|
365
|
-
} catch (error) {
|
|
366
|
-
console.error('❌ Failed to clear tasks:', error);
|
|
367
|
-
this.showActionMessage('Failed to clear tasks: ' + error.message, 'error');
|
|
368
|
-
|
|
369
|
-
if (window.showNotification) {
|
|
370
|
-
window.showNotification('Failed to clear tasks: ' + error.message, 'error');
|
|
371
|
-
}
|
|
372
|
-
} finally {
|
|
373
|
-
this.loading = false;
|
|
374
|
-
}
|
|
375
|
-
},
|
|
376
|
-
|
|
377
|
-
async clearAllQueues() {
|
|
378
|
-
if (!confirm('Are you sure you want to clear all queues?')) {
|
|
379
|
-
return;
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
try {
|
|
383
|
-
this.loading = true;
|
|
384
|
-
this.showActionMessage('Clearing all queues...', 'info');
|
|
385
|
-
// Assuming there's an API endpoint for this
|
|
386
|
-
await window.tasksAPI.tasksApiClearQueuesCreate({});
|
|
387
|
-
await this.loadQueues();
|
|
388
|
-
|
|
389
|
-
this.showActionMessage('All queues cleared successfully', 'success');
|
|
390
|
-
|
|
391
|
-
if (window.showNotification) {
|
|
392
|
-
window.showNotification('All queues cleared successfully', 'success');
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
console.log('✅ All queues cleared');
|
|
396
|
-
} catch (error) {
|
|
397
|
-
console.error('❌ Failed to clear queues:', error);
|
|
398
|
-
this.showActionMessage('Failed to clear queues: ' + error.message, 'error');
|
|
399
|
-
|
|
400
|
-
if (window.showNotification) {
|
|
401
|
-
window.showNotification('Failed to clear queues: ' + error.message, 'error');
|
|
402
|
-
}
|
|
403
|
-
} finally {
|
|
404
|
-
this.loading = false;
|
|
405
|
-
}
|
|
406
|
-
},
|
|
407
|
-
|
|
408
|
-
async purgeFailedTasks() {
|
|
409
|
-
if (!confirm('Are you sure you want to purge all failed tasks?')) {
|
|
410
|
-
return;
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
try {
|
|
414
|
-
this.loading = true;
|
|
415
|
-
this.showActionMessage('Purging failed tasks...', 'info');
|
|
416
|
-
// Assuming there's an API endpoint for this
|
|
417
|
-
await window.tasksAPI.tasksApiPurgeFailedCreate({});
|
|
418
|
-
await this.loadTasks();
|
|
419
|
-
|
|
420
|
-
this.showActionMessage('Failed tasks purged successfully', 'success');
|
|
421
|
-
|
|
422
|
-
if (window.showNotification) {
|
|
423
|
-
window.showNotification('Failed tasks purged successfully', 'success');
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
console.log('✅ Failed tasks purged');
|
|
427
|
-
} catch (error) {
|
|
428
|
-
console.error('❌ Failed to purge failed tasks:', error);
|
|
429
|
-
this.showActionMessage('Failed to purge failed tasks: ' + error.message, 'error');
|
|
430
|
-
|
|
431
|
-
if (window.showNotification) {
|
|
432
|
-
window.showNotification('Failed to purge failed tasks: ' + error.message, 'error');
|
|
433
|
-
}
|
|
434
|
-
} finally {
|
|
435
|
-
this.loading = false;
|
|
436
|
-
}
|
|
437
|
-
},
|
|
438
|
-
|
|
439
|
-
async simulateTasks(count = 5) {
|
|
440
|
-
try {
|
|
441
|
-
this.loading = true;
|
|
442
|
-
this.showActionMessage(`Simulating ${count} tasks...`, 'info');
|
|
443
|
-
await window.tasksAPI.tasksApiSimulateCreate({
|
|
444
|
-
count: count,
|
|
445
|
-
queue: 'default',
|
|
446
|
-
task_type: 'test'
|
|
447
|
-
});
|
|
448
|
-
await this.loadTasks();
|
|
449
|
-
|
|
450
|
-
this.showActionMessage(`Simulated ${count} tasks successfully`, 'success');
|
|
451
|
-
|
|
452
|
-
if (window.showNotification) {
|
|
453
|
-
window.showNotification(`Simulated ${count} tasks successfully`, 'success');
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
console.log(`✅ Simulated ${count} tasks`);
|
|
457
|
-
} catch (error) {
|
|
458
|
-
console.error('❌ Failed to simulate tasks:', error);
|
|
459
|
-
this.showActionMessage('Failed to simulate tasks: ' + error.message, 'error');
|
|
460
|
-
|
|
461
|
-
if (window.showNotification) {
|
|
462
|
-
window.showNotification('Failed to simulate tasks: ' + error.message, 'error');
|
|
463
|
-
}
|
|
464
|
-
} finally {
|
|
465
|
-
this.loading = false;
|
|
466
|
-
}
|
|
467
|
-
},
|
|
468
|
-
|
|
469
|
-
showActionMessage(message, type = 'info') {
|
|
470
|
-
this.actionMessage = message;
|
|
471
|
-
this.actionType = type;
|
|
472
|
-
|
|
473
|
-
// Auto-hide after 5 seconds
|
|
474
|
-
setTimeout(() => {
|
|
475
|
-
this.actionMessage = '';
|
|
476
|
-
}, 5000);
|
|
477
|
-
},
|
|
478
|
-
|
|
479
|
-
async startWorkers() {
|
|
480
|
-
try {
|
|
481
|
-
this.loading = true;
|
|
482
|
-
this.showActionMessage('Starting workers...', 'info');
|
|
483
|
-
await window.tasksAPI.tasksApiWorkersManageCreate({ action: 'start' });
|
|
484
|
-
await this.loadWorkers();
|
|
485
|
-
|
|
486
|
-
this.showActionMessage('Workers started successfully', 'success');
|
|
487
|
-
|
|
488
|
-
if (window.showNotification) {
|
|
489
|
-
window.showNotification('Workers started successfully', 'success');
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
console.log('✅ Workers started');
|
|
493
|
-
} catch (error) {
|
|
494
|
-
console.error('❌ Failed to start workers:', error);
|
|
495
|
-
this.showActionMessage('Failed to start workers: ' + error.message, 'error');
|
|
496
|
-
|
|
497
|
-
if (window.showNotification) {
|
|
498
|
-
window.showNotification('Failed to start workers: ' + error.message, 'error');
|
|
499
|
-
}
|
|
500
|
-
} finally {
|
|
501
|
-
this.loading = false;
|
|
502
|
-
}
|
|
503
|
-
},
|
|
504
|
-
|
|
505
|
-
async stopWorkers() {
|
|
506
|
-
if (!confirm('Are you sure you want to stop all workers?')) {
|
|
507
|
-
return;
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
try {
|
|
511
|
-
this.loading = true;
|
|
512
|
-
this.showActionMessage('Stopping workers...', 'info');
|
|
513
|
-
await window.tasksAPI.tasksApiWorkersManageCreate({ action: 'stop' });
|
|
514
|
-
await this.loadWorkers();
|
|
515
|
-
|
|
516
|
-
this.showActionMessage('Workers stopped successfully', 'success');
|
|
517
|
-
|
|
518
|
-
if (window.showNotification) {
|
|
519
|
-
window.showNotification('Workers stopped successfully', 'success');
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
console.log('✅ Workers stopped');
|
|
523
|
-
} catch (error) {
|
|
524
|
-
console.error('❌ Failed to stop workers:', error);
|
|
525
|
-
this.showActionMessage('Failed to stop workers: ' + error.message, 'error');
|
|
526
|
-
|
|
527
|
-
if (window.showNotification) {
|
|
528
|
-
window.showNotification('Failed to stop workers: ' + error.message, 'error');
|
|
529
|
-
}
|
|
530
|
-
} finally {
|
|
531
|
-
this.loading = false;
|
|
532
|
-
}
|
|
533
|
-
},
|
|
534
|
-
|
|
535
|
-
// Task status helpers
|
|
536
|
-
getStatusColor(status) {
|
|
537
|
-
const colors = {
|
|
538
|
-
'pending': 'yellow',
|
|
539
|
-
'running': 'blue',
|
|
540
|
-
'completed': 'green',
|
|
541
|
-
'failed': 'red'
|
|
542
|
-
};
|
|
543
|
-
return colors[status] || 'gray';
|
|
544
|
-
},
|
|
545
|
-
|
|
546
|
-
formatDuration(ms) {
|
|
547
|
-
if (!ms) return '-';
|
|
548
|
-
|
|
549
|
-
if (ms < 1000) {
|
|
550
|
-
return `${ms}ms`;
|
|
551
|
-
} else if (ms < 60000) {
|
|
552
|
-
return `${(ms / 1000).toFixed(1)}s`;
|
|
553
|
-
} else {
|
|
554
|
-
return `${(ms / 60000).toFixed(1)}m`;
|
|
555
|
-
}
|
|
556
|
-
},
|
|
557
|
-
|
|
558
|
-
formatDate(dateString) {
|
|
559
|
-
if (!dateString) return '-';
|
|
560
|
-
|
|
561
|
-
try {
|
|
562
|
-
const date = new Date(dateString);
|
|
563
|
-
return date.toLocaleString('en-US', {
|
|
564
|
-
month: 'short',
|
|
565
|
-
day: 'numeric',
|
|
566
|
-
hour: '2-digit',
|
|
567
|
-
minute: '2-digit',
|
|
568
|
-
second: '2-digit'
|
|
569
|
-
});
|
|
570
|
-
} catch (error) {
|
|
571
|
-
return dateString;
|
|
572
|
-
}
|
|
573
|
-
},
|
|
574
|
-
|
|
575
|
-
// Task action methods
|
|
576
|
-
async viewTaskDetails(task) {
|
|
577
|
-
console.log('View task details:', task);
|
|
578
|
-
this.selectedTask = task;
|
|
579
|
-
this.showTaskModal = true;
|
|
580
|
-
},
|
|
581
|
-
|
|
582
|
-
closeTaskModal() {
|
|
583
|
-
this.showTaskModal = false;
|
|
584
|
-
// Clear selected task after transition
|
|
585
|
-
setTimeout(() => {
|
|
586
|
-
this.selectedTask = null;
|
|
587
|
-
}, 300);
|
|
588
|
-
},
|
|
589
|
-
|
|
590
|
-
async retryTask(task) {
|
|
591
|
-
// TODO: Implement retry task endpoint in backend API
|
|
592
|
-
this.showActionMessage('Retry task feature is not yet implemented', 'error');
|
|
593
|
-
|
|
594
|
-
if (window.showNotification) {
|
|
595
|
-
window.showNotification('Retry task feature is not yet implemented', 'error');
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
console.warn('⚠️ Retry task endpoint not implemented in API');
|
|
599
|
-
},
|
|
600
|
-
|
|
601
|
-
async deleteTask(task) {
|
|
602
|
-
// TODO: Implement delete task endpoint in backend API
|
|
603
|
-
this.showActionMessage('Delete task feature is not yet implemented', 'error');
|
|
604
|
-
|
|
605
|
-
if (window.showNotification) {
|
|
606
|
-
window.showNotification('Delete task feature is not yet implemented', 'error');
|
|
607
|
-
}
|
|
608
|
-
|
|
609
|
-
console.warn('⚠️ Delete task endpoint not implemented in API');
|
|
610
|
-
},
|
|
611
|
-
|
|
612
|
-
// Footer action methods
|
|
613
|
-
async clearCompletedTasks() {
|
|
614
|
-
// TODO: Implement clear completed tasks endpoint in backend API
|
|
615
|
-
this.showActionMessage('Clear completed tasks feature is not yet implemented', 'error');
|
|
616
|
-
|
|
617
|
-
if (window.showNotification) {
|
|
618
|
-
window.showNotification('Clear completed tasks feature is not yet implemented', 'error');
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
console.warn('⚠️ Clear completed tasks endpoint not implemented in API');
|
|
622
|
-
},
|
|
623
|
-
|
|
624
|
-
async exportTasksCSV() {
|
|
625
|
-
try {
|
|
626
|
-
this.showActionMessage('Exporting tasks to CSV...', 'info');
|
|
627
|
-
|
|
628
|
-
// Simple CSV export implementation
|
|
629
|
-
const headers = ['ID', 'Name', 'Status', 'Queue', 'Duration', 'Created', 'Updated'];
|
|
630
|
-
const rows = this.tasks.map(task => [
|
|
631
|
-
task.task_id || task.id,
|
|
632
|
-
task.name,
|
|
633
|
-
task.status,
|
|
634
|
-
task.queue || 'default',
|
|
635
|
-
task.duration || '',
|
|
636
|
-
task.created_at || '',
|
|
637
|
-
task.updated_at || ''
|
|
638
|
-
]);
|
|
639
|
-
|
|
640
|
-
const csvContent = [
|
|
641
|
-
headers.join(','),
|
|
642
|
-
...rows.map(row => row.map(cell => `"${cell}"`).join(','))
|
|
643
|
-
].join('\n');
|
|
644
|
-
|
|
645
|
-
// Create blob and download
|
|
646
|
-
const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
|
|
647
|
-
const link = document.createElement('a');
|
|
648
|
-
const url = URL.createObjectURL(blob);
|
|
649
|
-
|
|
650
|
-
link.setAttribute('href', url);
|
|
651
|
-
link.setAttribute('download', `tasks_export_${new Date().toISOString().split('T')[0]}.csv`);
|
|
652
|
-
link.style.visibility = 'hidden';
|
|
653
|
-
|
|
654
|
-
document.body.appendChild(link);
|
|
655
|
-
link.click();
|
|
656
|
-
document.body.removeChild(link);
|
|
657
|
-
|
|
658
|
-
this.showActionMessage('Tasks exported successfully', 'success');
|
|
659
|
-
|
|
660
|
-
if (window.showNotification) {
|
|
661
|
-
window.showNotification('Tasks exported to CSV', 'success');
|
|
662
|
-
}
|
|
663
|
-
|
|
664
|
-
console.log('✅ Tasks exported to CSV');
|
|
665
|
-
} catch (error) {
|
|
666
|
-
console.error('❌ Failed to export tasks:', error);
|
|
667
|
-
this.showActionMessage('Failed to export tasks: ' + error.message, 'error');
|
|
668
|
-
|
|
669
|
-
if (window.showNotification) {
|
|
670
|
-
window.showNotification('Failed to export tasks: ' + error.message, 'error');
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
}
|
|
674
|
-
}));
|
|
675
|
-
});
|
|
676
|
-
|
|
677
|
-
// Add global helper functions for Alpine.js templates
|
|
678
|
-
window.dashboardHelpers = {
|
|
679
|
-
formatDuration: (ms) => {
|
|
680
|
-
if (!ms) return '-';
|
|
681
|
-
|
|
682
|
-
if (ms < 1000) {
|
|
683
|
-
return `${ms}ms`;
|
|
684
|
-
} else if (ms < 60000) {
|
|
685
|
-
return `${(ms / 1000).toFixed(1)}s`;
|
|
686
|
-
} else {
|
|
687
|
-
return `${(ms / 60000).toFixed(1)}m`;
|
|
688
|
-
}
|
|
689
|
-
},
|
|
690
|
-
|
|
691
|
-
formatDate: (dateString) => {
|
|
692
|
-
if (!dateString) return '-';
|
|
693
|
-
|
|
694
|
-
try {
|
|
695
|
-
const date = new Date(dateString);
|
|
696
|
-
return date.toLocaleString('en-US', {
|
|
697
|
-
month: 'short',
|
|
698
|
-
day: 'numeric',
|
|
699
|
-
hour: '2-digit',
|
|
700
|
-
minute: '2-digit',
|
|
701
|
-
second: '2-digit'
|
|
702
|
-
});
|
|
703
|
-
} catch (error) {
|
|
704
|
-
return dateString;
|
|
705
|
-
}
|
|
706
|
-
},
|
|
707
|
-
|
|
708
|
-
getStatusBadgeClass: (status) => {
|
|
709
|
-
const classes = {
|
|
710
|
-
'pending': 'bg-yellow-100 dark:bg-yellow-900 text-yellow-800 dark:text-yellow-200',
|
|
711
|
-
'running': 'bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200',
|
|
712
|
-
'completed': 'bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200',
|
|
713
|
-
'failed': 'bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200'
|
|
714
|
-
};
|
|
715
|
-
return classes[status] || 'bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200';
|
|
716
|
-
}
|
|
717
|
-
};
|
|
718
|
-
|
|
719
|
-
// Cleanup on page unload
|
|
720
|
-
window.addEventListener('beforeunload', () => {
|
|
721
|
-
console.log('🧹 Cleaning up dashboard...');
|
|
722
|
-
// Alpine.js will handle cleanup automatically
|
|
723
|
-
});
|
|
724
|
-
|
|
725
|
-
console.log('✅ Dashboard Alpine.js extensions loaded');
|